Algorithm 排序演算法

2021-07-22 22:33:09 字數 4076 閱讀 3755

閒來無事回顧一下原來所學的排序演算法,包括冒泡、選擇、插入、希爾、快速、歸併排序,這六種。

首先依次講解原理,最後放出實現及測試速度原始碼。

我想大部分人學習的第乙個排序演算法就是這個。

顧名思義,如泡泡般,越到水面就越大,即經過連續不斷的判斷,選取大(或小)的值進行交換,一輪結束後,未排序資料最後面的就是最大(或最小)的值。

比較相鄰的元素,如果前乙個比後乙個大,就交換它們兩個。

對每乙個對相鄰的元素作同樣的操作,從開始的第一對到結尾的最後一對,這步驟做完後,最後的元素就是最大的元素。

針對所有的元素重複以上的步驟,除開最後乙個。

持續每次對原來越少的元素重複上面的步驟,直到沒有任何一對數字需要比較。

選擇排序相對於氣泡排序來說,減少了資料交換的次數,在每輪比較中,僅儲存大的元素的序號,在一輪結束後通過序號獲取最大的元素將其移動到最後面。

在為排序序列中找到最小(大)元素,存放到排序序列的起始位置(終止位置)

從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的起始位置(終止位置)。

重複上述操作直到所有元素排序完畢。

插入的意思就是將未排序的元素插入到已排序的元素之中。將第乙個元素作為已排序的元素,然後取第二個元素與第乙個元素比較,小於的話就將其插入到第乙個元素之前,否者不變,此時得到乙個有序元素數列,然後如第三個元素依次與第二個元素和第乙個元素比較,依此類推,將所有未排序的元素依次與前面所有已排序的元素進行比較,然後插入。

通過構建有序序列,對於未排序資料,在已排序序列中從後向前掃瞄,找到對應的位置並插入。

又稱遞減增量排序演算法

希爾排序是針對插入排序優化後的演算法。引入了步長(增量),將元素分割槽處理。越到後面步長越小,直至變成普通的插入排序,此時元素已幾乎排列完成,插入排序的速度是最快的。

快速排序可以理解為挖坑填坑排序,一般情況下是將第乙個元素當作坑,然後以坑元素為分界線,大的在右邊,小的在左邊,最後剩下的位置就是坑元素排序後的位置,然後除坑元素以外,左右分為兩個元素數列,重複以上操作,直至不可分位置,即排列好所有元素。一般使用遞迴的方法實現。

快速排序使用分治法(divide and conquer)策略來把乙個序列(list)分為兩個子串行(sub-lists)。

步驟為:

1. 從數列中挑出乙個元素,稱為」基準」(pivot)。

2. 重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面(相同的數可以到任一邊)。在這個分割槽結束之後,該基準就處於數列的中間位置。這個稱為分割槽(partition)操作。

3. 遞迴地(recursive)把小於基準值元素的子數列和大於基準值元素的子數列排序。

遞迴的最底部情形,是數列的大小是零或一,也就是永遠都已經被排序好了。雖然一直遞迴下去,但是這個演算法總會結束,因為在每次的迭代(iteration)中,它至少會把乙個元素擺到它最後的位置去。

可以理解為不停的分組直至組中元素不能再分,然後按照分組的順序反向有序合併分組,最終就能的到乙個有序序列。一般使用遞迴實現。

原理如下(假設序列共有n個元素):

1. 將序列每相鄰兩個數字進行歸併操作,形成floor(n/2) 個序列,排序後每個序列包含兩個元素

2. 將上述序列再次歸併,形成floor(n/4)個序列,每個序列包含四個元素

3. 重複步驟2,直到所有元素排序完畢

# include 

# include

# include

# include

# include

//交換元素

# define swap(a, b)

//氣泡排序

void bubblesort(int nnumbers, int length)}}

}//插入排序

void insertsort(int nnumbers, int length)

if (i != targetindex)

}}//選擇排序

void selectsort(int nnumbers, int length)

}if (nmaxindex != i)

}}//希爾排序

void shellsort(int nnumbers, int length)

if (i != ntargetindex)}}

}//快速排序

void quicksort(int nnumbers, int nstart, int nend)

int ns = nstart;

int ne = nend;

int nbuf = nnumbers[ns];//挖坑

while (ns < ne)

if (ns < ne)

//將大的元素放到右邊

while (ns < ne && nbuf > nnumbers[ns])

if (ns < ne)

}nnumbers[ns] = nbuf;//填坑

//分組並遞迴呼叫

quicksort(nnumbers, nstart, ns - 1);//左數列

quicksort(nnumbers, ns + 1, nend);//右數列

}//歸併演算法-排序並合併分組

void mergetsortgroup(int nnumbers, int nstart, int nmid, int nend, int *temp)

//合併剩餘元素

while (ngroup_1 <= nmid)

//合併剩餘元素

while (ngroup_2 <= nend)

//複製到正真的元素數列

nindex--;

while (nindex >= 0)

}//歸併演算法-分組

void mergesplitgroup(int nnumbers, int nstart, int nend, int* temp)

}//歸併演算法

void mergesort(int nnumbers, int length)

//使用隨機數填充陣列

void initrandnumber(int nnumbers, int length)

}//檢查排序是否正確

bool checksort(int nnumbers, int length)

}if (i + 1

< length)}}

return

true;

}//列印陣列

void print(int nnumbers, int length)

printf("\n");

}void main()

執行結果如下:

如不清楚可查閱下列資料:

wiki:

Algorithm 排序演算法 堆排序

堆排序是選擇類排序演算法,核心思想依然是選擇最大 小 的元素,與直接選擇排序不同的是,堆排序借助了最大堆的特性,使得最大元素的查詢更加的便利。最大堆 最大堆是二叉堆的乙個形式,最大堆要求根節點的關鍵字是所有節點關鍵字中的最大者,即要求最大堆根節點的關鍵字不小於其左葉子的關鍵字,也不能小於右葉子的關鍵...

演算法Algorithm 桶(Bucket)排序

確定待排序數列 n個數 的最小值和最大值,確定桶的數量k 然後把這個n個數 均勻的 放到k個桶中 再對每個桶中的數列進行排序 可以使用其他排序演算法 最後依次讀取每個桶中的數就是排好序的整個數列。使用乙個對映函式來達到把n個數放到k個桶的操作,其規則是 左側 桶 先放置的 中的數全部小於 右側 桶中...

Algorithm 選擇排序

選擇排序 比如在乙個長度為n的無序陣列中,在第一趟遍歷n個資料,找出其中最小的數值與第乙個元素交換,第二趟遍歷剩下的n 1個資料,找出其中最小的數值與第二個元素交換.第n 1趟遍歷剩下的2個資料,找出其中最小的數值與第n 1個元素交換,至此選擇排序完成。舉個例子 5 7 6 4 3 8 第一趟 3 ...