選擇排序有直接選擇排序和堆排序。基本思想:每一趟在待排序的記錄中選出關鍵字最小的元素,依次存放在已排好序的序列的最後。直到所有元素都好排好序為止。
演算法思想:
每次從待排序的無序區中選出關鍵字最小的元素,將該元素與該無序區中的第乙個元素交換位置。初始時,從[0…n-1]選出乙個關鍵字最小的元素,與r[0]交換位置。第二趟排序時,從[1…n-1]選出乙個關鍵字最小的元素,與r[1]交換位置,此時r[0…1]為有序區,依次類推,進行n-1趟後,r[0…n-1]中的元素按遞增有序。
演算法實現:
#include
void
selectsort
(int r,
int n)
}// 將最小的元素與r[i]進行交換
if(i != k)}}
intmain()
;selectsort
(data,8)
;for
(int i =
0; i <
8;i++
)printf
("\n");
return0;
}
堆排序是乙個種樹形選擇排序,演算法思想:
在排序過程中,將陣列r[0…n]看成是一棵完全二叉樹的順序儲存結構,利用完全二叉樹中雙親結點和該子結點之間的記憶體關係,在當前無序區中選擇關鍵字最大(或最小)的元素。
堆排序正是利用大根堆(或小根堆)來選擇當前無序區中關鍵字最大(或最小)的元素來實現排序的。每一趟排序就是將當前無序區調整為乙個大根堆,選擇關鍵字最大的堆頂元素和無序區中最後乙個元素進行交換。通過不斷將剩餘的無序區調整為乙個大根堆,然後再將堆頂元素與無序區中最後乙個元素進行交換來完成排序的。
那麼堆排序的關鍵就是構造堆,構造堆的過程:
將待排序的檔案的關鍵字儲存在乙個陣列r[0…n-1]中(儲存在r[1…n])更好理解,將r看成一棵完全二叉樹的順序儲存結構,每個結點代表乙個元素。那麼任意結點ri的左孩子是r[2i+1](如果是r[1…n],那麼左孩子就是r[2i]),右孩子是r[2i+2](如果是r[1…n],那麼右孩子就是r[2i+1]),r[i]的雙親結點就是r[i/2]。構造大根堆的過程:假設完全二叉樹的某乙個結點i的左子樹和右子樹已是堆,那麼將r[2i+1]和r[2i+2]中的較大者與r[i]比較,如果r[i]較小,則交換,交換後,就有可能破壞下一級的堆,因此繼續採取同樣的方法構造下一級的堆,直至完全二叉樹中以結點i為根的子樹成堆為止,當無序區調整為大根堆時,堆頂元素就是無序區中關鍵字最大的元素,將其與無序區中最後乙個元素進行交換。重複構造堆和進行交換,經過n-1趟後就可以排好序。
參考:
演算法實現:
#include
void
check
(int r,
int i,
int l)
// r[i]與左右孩子結點中較大者進行比較
if(j < l && r[i]
< r[j])}
void
heapsort
(int r,
int n)
temp--
;// 堆頂元素與無序區最後乙個元素交換
int t = r[temp]
; r[temp]
= r[0]
; r[0]
= t;}}
intmain()
;heapsort
(data,8)
;for
(int i =
0; i <
8; i++
)printf
("\n");
return0;
}
在直接選擇排序中存在著不相鄰元素之間的交換,因而可能會改變具有相同關鍵字的前後位置,因此直接選擇排序演算法是不穩定的。堆排序也是不穩定的。在直接排序序中,為了從n個關鍵字中選擇出最小的,需要進行n-1次的比較,然後再在n-1個關鍵字找出次小的關鍵字,需要進行n-2次比較,實際上,在進行n-2比較中,有許多比較都已經做過只是沒有記錄下來,堆排序剛好彌補了這一點的不足。 C 資料結構之選擇排序(三)
選擇排序是氣泡排序的改進!選擇排序 讓陣列中未排序的第乙個數,依次與後面的數進行比較,如果前面的數大於後面的數,就進行位置的交換。即第乙個數依次與後面的數比較,比較完之後最小的數在最前面 先標記一輪比較完後再交換位置 然後從第二個數開始以此類推,直至倒數第二個數為止。如下圖所示 c 如下 inclu...
複習資料結構 排序(三) 選擇排序
選擇排序的核心是 每趟選擇最小的元素和首部交換。時間複雜度 o n 2 選擇排序是一種不穩定的排序,為什麼呢?因為不好處理相等兩個數的前後位置,舉個例子,序列5 8 5 2 9,我們知道第一遍選擇第1個元素5會和2交換,那麼原序列中2個5的相對前後順序就被破壞了,所以選擇排序不是乙個穩定的排序演算法...
資料結構之選擇排序
基本方法 從0索引開始,依次和後面元素比較,小的往前放,第一次完畢,最小值出現在了最小索引處,第二次找到第二小的值。具體是如何實現呢?第一輪是0索引上的資料依次跟後面各個索引上的資料進行比較,直到遇到乙個比它小的資料,這時候,這個小的資料就替換掉0索引上原來的資料,接著這個替換掉的資料繼續跟它原來的...