選擇排序
算法思想:以升序爲例,在整個區間中找出排序碼最小的元素,如果這個元素不是這組序列中的第一個元素,那麼將它和第一個元素進行交換,使得最小的元素就在第一個位置,然後縮小區間,循環執行上述操作,只到區間中只剩下一個元素。
具體步驟(升序):
- 在區間中找到關鍵碼最小的元素。
- 如果不是待排序區間的第一個元素,則和帶排序區間第一個元素交換。
- 縮小待排序區間。
代碼實現:
void ChangeSort(int *array, int size)
{
assert(array);
for (int i = 1; i < size; ++i)
{
int minindex = i;//未排序的最小元素下標
int start = i - 1;//未排序區間第一個元素下標
while (minindex<size)
{
if (array[minindex] < array[start])
swap(array[minindex], array[start]);
++minindex;
}
}
}
算法性能:
時間複雜度:最好的情況是已經有序,交換次數爲0,最壞的情況是逆序,交換次數是n-1,比較次數與關鍵字的初始狀態無關。總的比較次數爲N=n*(n-1)/2,所以時間複雜度爲O(N^2)
空間複雜度:O(1)
穩定性:不穩定
堆排序
基本思想:堆排序就是利用堆這種數據結構實現的一種排序算法,堆是完全二叉樹的一種。堆的特點是:
- 最大堆:每一個父節點的值都大於兩個子節點
- 最小堆:每一個父節點的值都小於兩個子節點
堆排序的基本思想就是利用了這種結構,如果我們需要升序:
1.把所有[a1,a2,a3…an]建成大堆。
2.把堆頂的元素(即數組中最大的元素和堆中最後一個元素交換),此時分爲兩個區域,一個[a1,a2,an–1]無序區和[an]有序區。
3.因爲交換了元素,有可能會違反了堆的性質,因此無序區的元素進行調整,滿足堆的性質。
4.重複步驟2,直到有序區的元素有n-1個。
代碼實現:
void AdJustDown(int *array, int size, int n)
{
int parent = n;
int child = parent*+1;
while (child<n)
{
if ((child + 1 < size) && array[child] < array[child + 1])
{
++child;
}
if (array[child] > array[parent])
{
swap(array[child], array[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void HeapSort(int *array, int size)
{
assert(array);
for (int i=(size-2)>>1;i>=0;++i)
{
AdJustDown(array,size,i);//創建大堆,將所有數據都重新排序
}
for (int i = size - 1; i >= 0; ++i)
{
swap(array[0], array[size]);//交換堆頂元素和已序序列第一個元素
AdJustDown(array, i, 0);//縮小區間,調整堆結構
}
}
算法性能:
- 時間複雜度:因爲堆中元素的個數是N,所以堆的高度是logN,那麼比較次數就是2logN,交換的次數是N次,所以平均時間複雜度是O(NlogN)
- 空間複雜度:O(1)
- 穩定性:不穩定
驗證結果: