1樓:一個北漂的雜貨鋪
一、插入排序(insertion sort)
1. 基本思想:
每次將一個待排序的資料元素,插入到前面已經排好序的數列中的適當位置,使數列依然有序;直到待排序資料元素全部插入完為止。
2. 排序過程:
【示例】:
[初始關鍵字] [49] 38 65 97 76 13 27 49
j=2(38) [38 49] 65 97 76 13 27 49
j=3(65) [38 49 65] 97 76 13 27 49
j=4(97) [38 49 65 97] 76 13 27 49
j=5(76) [38 49 65 76 97] 13 27 49
j=6(13) [13 38 49 65 76 97] 27 49
j=7(27) [13 27 38 49 65 76 97] 49
j=8(49) [13 27 38 49 49 65 76 97]
procedure insertsort(var r : filetype);
//對r[1..n]按遞增序進行插入排序, r[0]是監視哨//
begin
for i := 2 to n do //依次插入r[2],...,r[n]//
begin
r[0] := r; j := i - 1;
while r[0] < r[j] do //查詢r的插入位置//
begin
r[j+1] := r[j]; //將大於r的元素後移//
j := j - 1
endr[j + 1] := r[0] ; //插入r //
endend; //insertsort //
複製**
二、選擇排序
1. 基本思想:
每一趟從待排序的資料元素中選出最小(或最大)的一個元素,順序放在已排好序的數列的最後,直到全部待排序的資料元素排完。
2. 排序過程:
【示例】:
初始關鍵字 [49 38 65 97 76 13 27 49]
第一趟排序後 13 [38 65 97 76 49 27 49]
第二趟排序後 13 27 [65 97 76 49 38 49]
第三趟排序後 13 27 38 [97 76 49 65 49]
第四趟排序後 13 27 38 49 [49 97 65 76]
第五趟排序後 13 27 38 49 49 [97 97 76]
第六趟排序後 13 27 38 49 49 76 [76 97]
第七趟排序後 13 27 38 49 49 76 76 [ 97]
最後排序結果 13 27 38 49 49 76 76 97
procedure selectsort(var r : filetype); //對r[1..n]進行直接選擇排序 //
begin
for i := 1 to n - 1 do //做n - 1趟選擇排序//
begin
k := i;
for j := i + 1 to n do //在當前無序區r[i..n]中選最小的元素r[k]//
begin
if r[j] < r[k] then k := j
end;
if k <> i then //交換r和r[k] //
begin temp := r; r := r[k]; r[k] := temp; end;
endend; //selectsort //
複製**
三、氣泡排序(bubblesort)
1. 基本思想:
兩兩比較待排序資料元素的大小,發現兩個資料元素的次序相反時即進行交換,直到沒有反序的資料元素為止。
2. 排序過程:
設想被排序的陣列r[1..n]垂直豎立,將每個資料元素看作有重量的氣泡,根據輕氣泡不能在重氣泡之下的原則,從下往上掃描陣列r,凡掃描到違反本原則的輕氣泡,就使其向上"漂浮",如此反覆進行,直至最後任何兩個氣泡都是輕者在上,重者在下為止。
【示例】:
49 13 13 13 13 13 13 13
38 49 27 27 27 27 27 27
65 38 49 38 38 38 38 38
97 65 38 49 49 49 49 49
76 97 65 49 49 49 49 49
13 76 97 65 65 65 65 65
27 27 76 97 76 76 76 76
49 49 49 76 97 97 97 97
procedure bubblesort(var r : filetype) //從下往上掃描的起泡排序//
begin
for i := 1 to n-1 do //做n-1趟排序//
begin
noswap := true; //置未排序的標誌//
for j := n - 1 downto 1 do //從底部往上掃描//
begin
if r[j+1]< r[j] then //交換元素//
begin
temp := r[j+1]; r[j+1 := r[j]; r[j] := temp;
noswap := false
end;
end;
if noswap then return//本趟排序中未發生交換,則終止演算法//
endend; //bubblesort//
複製**
四、快速排序(quick sort)
1. 基本思想:
在當前無序區r[1..h]中任取一個資料元素作為比較的"基準"(不妨記為x),用此基準將當前無序區劃分為左右兩個較小的無序區:r[1..
i-1]和r[i+1..h],且左邊的無序子區中資料元素均小於等於基準元素,右邊的無序子區中資料元素均大於等於基準元素,而基準x則位於最終排序的位置上,即r[1..i-1]≤x.
key≤r[i+1..h](1≤i≤h),當r[1..i-1]和r[i+1..
h]均非空時,分別對它們進行上述的劃分過程,直至所有無序子區中的資料元素均已排序為止。
2. 排序過程:
【示例】:
初始關鍵字 [49 38 65 97 76 13 27 49]
第一次交換後
[27 38 65 97 76 13 49 49]
第二次交換後
[27 38 49 97 76 13 65 49]
j向左掃描,位置不變,第三次交換後
[27 38 13 97 76 49 65 49]
i向右掃描,位置不變,第四次交換後
[27 38 13 49 76 97 65 49]
j向左掃描
[27 38 13 49 76 97 65 49]
(一次劃分過程)
初始關鍵字
[49 38 65 97 76 13 27 49]
一趟排序之後
[27 38 13] 49 [76 97 65 49]
二趟排序之後
[13] 27 [38] 49 [49 65]76 [97]
三趟排序之後 13 27 38 49 49 [65]76 97
最後的排序結果 13 27 38 49 49 65 76 97
各趟排序之後的狀態
procedure parttion(var r : filetype; l, h : integer; var i : integer);
//對無序區r[1,h]做劃分,i給以出本次劃分後已被定位的基準元素的位置 //
begin
i := 1; j := h; x := r ;//初始化,x為基準//
repeat
while (r[j] >= x) and (i < j) do
begin
j := j - 1 //從右向左掃描,查詢第1個小於 x的元素//
if i < j then //已找到r[j] 〈x//
begin
r := r[j]; //相當於交換r和r[j]//
i := i + 1
end;
while (r <= x) and (i < j) do
i := i + 1 //從左向右掃描,查詢第1個大於 x的元素///
end;
if i < j then //已找到r > x //
begin r[j] := r; //相當於交換r和r[j]//
j := j - 1
enduntil i = j;
r := x //基準x已被最終定位//
end; //parttion //
複製**procedure quicksort(var r :filetype; s,t: integer); //對r[s..t]快速排序//
begin
if s < t then //當r[s..t]為空或只有一個元素是無需排序//
begin
partion(r, s, t, i); //對r[s..t]做劃分//
quicksort(r, s, i-1);//遞迴處理左區間r[s,i-1]//
quicksort(r, i+1,t);//遞迴處理右區間r[i+1..t] //
end;
end; //quicksort//
複製**
五、堆排序(heap sort)
1. 基本思想:
堆排序是一樹形選擇排序,在排序過程中,將r[1..n]看成是一顆完全二叉樹的順序儲存結構,利用完全二叉樹中雙親結點和孩子結點之間的內在關係來選擇最小的元素。
2. 堆的定義: n個元素的序列k1,k2,k3,...,kn.稱為堆,當且僅當該序列滿足特性:
ki≤k2i ki ≤k2i+1(1≤ i≤ [n/2])
堆實質上是滿足如下性質的完全二叉樹:樹中任一非葉子結點的關鍵字均大於等於其孩子結點的關鍵字。例如序列10,15,56,25,30,70就是一個堆,它對應的完全二叉樹如上圖所示。
這種堆中根結點(稱為堆頂)的關鍵字最小,我們把它稱為小根堆。反之,若完全二叉樹中任一非葉子結點的關鍵字均大於等於其孩子的關鍵字,則稱之為大根堆。
3. 排序過程:
堆排序正是利用小根堆(或大根堆)來選取當前無序區中關鍵字小(或最大)的記錄實現排序的。我們不妨利用大根堆來排序。每一趟排序的基本操作是:
將當前無序區調整為一個大根堆,選取關鍵字最大的堆頂記錄,將它和無序區中的最後一個記錄交換。這樣,正好和直接選擇排序相反,有序區是在原記錄區的尾部形成並逐步向前擴大到整個記錄區。
【示例】:對關鍵字序列42,13,91,23,24,16,05,88建堆
procedure sift(var r :filetype; i, m : integer);
//在陣列r[i..m]中呼叫r,使得以它為完全二叉樹構成堆。事先已知其左、右子樹(2i+1 <=m時)均是堆//
begin
x := r; j := 2*i; //若j <=m, r[j]是r的左孩子//
while j <= m do //若當前被調整結點r有左孩子r[j]//
begin
if (j < m) and r[j].key < r[j+1].key then
j := j + 1 //令j指向關鍵字較大的右孩子//
//j指向r的左、右孩子中關鍵字較大者//
if x.key < r[j].key then //孩子結點關鍵字較大//
begin
r := r[j]; //將r[j]換到雙親位置上//
i := j ; j := 2*i //繼續以r[j]為當前被調整結點往下層調整//
end;
else
exit//調整完畢,退出迴圈//
endr := x;//將最初被調整的結點放入正確位置//
end;//sift//
複製**procedure heapsort(var r : filetype); //對r[1..n]進行堆排序//
begin
for i := n div downto 1 do //建立初始堆//
sift(r, i , n)
for i := n downto 2 do //進行n-1趟排序//
begin
t := r[1]; r[1] := r; r := t;//將當前堆頂記錄和堆中最後一個記錄交換//
sift(r, 1, i-1) //將r[1..i-1]重成堆//
endend; //heapsort//
複製**
六、幾種排序演算法的比較和選擇
1. 選取排序方法需要考慮的因素:
(1) 待排序的元素數目n;
(2) 元素本身資訊量的大小;
(3) 關鍵字的結構及其分佈情況;
(4) 語言工具的條件,輔助空間的大小等。
2. 小結:
(1) 若n較小(n <= 50),則可以採用直接插入排序或直接選擇排序。由於直接插入排序所需的記錄移動操作較直接選擇排序多,因而當記錄本身資訊量較大時,用直接選擇排序較好。
(2) 若檔案的初始狀態已按關鍵字基本有序,則選用直接插入或氣泡排序為宜。
(3) 若n較大,則應採用時間複雜度為o(nlog2n)的排序方法:快速排序、堆排序或歸併排序。
快速排序是目前基於比較的內部排序法中被認為是最好的方法。
(4) 在基於比較排序方法中,每次比較兩個關鍵字的大小之後,僅僅出現兩種可能的轉移,因此可以用一棵二叉樹來描述比較判定過程,由此可以證明:當檔案的n個關鍵字隨機分佈時,任何藉助於"比較"的排序演算法,至少需要o(nlog2n)的時間。
這句話很重要 它告訴我們自己寫的演算法 是有改進到最優 當然沒有必要一直追求最優
(5) 當記錄本身資訊量較大時,為避免耗費大量時間移動記錄,可以用連結串列作為儲存結構。
怎麼做氣泡排序?氣泡排序法是如何排序的???
具體 如下 從小到大排序。include void main int a 10 i,j,k,temp printf 輸入10個數 for i 0 i 10 i scanf d a i 輸入10個數,初始化陣列。for i 0 i 9 i for j i 1 j 10 j 用陣列中第i個數和i後面的數...
c語言選擇法排序,C語言選擇法排序
大野瘦子 include define m 5 void main int b m i,j,t,k for i 0 iscanf d b i for i 0 ifor k i,j i 1 jif b k k j if i k t b i b i b k b k t for i 0 iprintf d...
C 下用氣泡排序法排列數,C 下用氣泡排序法排列10個數
乾珈藍佑 將你的 中 for j 9,q 1 q n k j q 的n改為10就可以了 for j 9,q 1 q 10 k j q 改為10以後,程式就沒有問題了 你的main函式顯示有問題,顯示的aa.display 在排序的aa.sortnum 之前了,那樣顯示的是排序前的順序,在aa.sor...