閒來無事回顧一下原來所學的排序演算法,包括冒泡、選擇、插入、希爾、快速、歸併排序,這六種。
首先依次講解原理,最後放出實現及測試速度原始碼。
我想大部分人學習的第乙個排序演算法就是這個。
顧名思義,如泡泡般,越到水面就越大,即經過連續不斷的判斷,選取大(或小)的值進行交換,一輪結束後,未排序資料最後面的就是最大(或最小)的值。
比較相鄰的元素,如果前乙個比後乙個大,就交換它們兩個。
對每乙個對相鄰的元素作同樣的操作,從開始的第一對到結尾的最後一對,這步驟做完後,最後的元素就是最大的元素。
針對所有的元素重複以上的步驟,除開最後乙個。
持續每次對原來越少的元素重複上面的步驟,直到沒有任何一對數字需要比較。
選擇排序相對於氣泡排序來說,減少了資料交換的次數,在每輪比較中,僅儲存大的元素的序號,在一輪結束後通過序號獲取最大的元素將其移動到最後面。
在為排序序列中找到最小(大)元素,存放到排序序列的起始位置(終止位置)
從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的起始位置(終止位置)。
重複上述操作直到所有元素排序完畢。
插入的意思就是將未排序的元素插入到已排序的元素之中。將第乙個元素作為已排序的元素,然後取第二個元素與第乙個元素比較,小於的話就將其插入到第乙個元素之前,否者不變,此時得到乙個有序元素數列,然後如第三個元素依次與第二個元素和第乙個元素比較,依此類推,將所有未排序的元素依次與前面所有已排序的元素進行比較,然後插入。
通過構建有序序列,對於未排序資料,在已排序序列中從後向前掃瞄,找到對應的位置並插入。
又稱遞減增量排序演算法
希爾排序是針對插入排序優化後的演算法。引入了步長(增量),將元素分割槽處理。越到後面步長越小,直至變成普通的插入排序,此時元素已幾乎排列完成,插入排序的速度是最快的。
快速排序可以理解為挖坑填坑排序,一般情況下是將第乙個元素當作坑,然後以坑元素為分界線,大的在右邊,小的在左邊,最後剩下的位置就是坑元素排序後的位置,然後除坑元素以外,左右分為兩個元素數列,重複以上操作,直至不可分位置,即排列好所有元素。一般使用遞迴的方法實現。
快速排序使用分治法(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 ...