常見排序演算法的整理
一直以來對排序演算法沒有深刻的理解,只能簡單的程式碼編寫,因此今天抽出一些時間對以前排序的不足加以修改。
這裡我們來探討一下常用的比較排序演算法,下表給出了常見比較排序演算法的效能:
穩定性的判別:如果說排序前兩個相等的數位置是a,b,排序後兩個數仍然是a,b,則說明這個排序是穩定的。通俗來講就是說:排序前後兩個相等的數相對位置不發生改變。
氣泡排序:
1.比較相鄰的元素,如果前者大於後者,則將兩個數進行交換。
2.對每一對相鄰元素都做相同的工作,從第一對到最後一對,這步做完之後,最後一個元素便是最大值。
3.針對所有元素都重複以上步驟,每重複一次,便對相鄰比較次數減一。
4.直到沒有相鄰元素比較即完成了氣泡排序。
程式碼實現:
//氣泡排序
//時間複雜度O(N^2)
//空間複雜度O(1)
//穩定性:穩定
void BubbleSort(int array[], int size)
{
int i, j;
for (i = 0; i < size-1; i++)
{
for (j = 0; j < size - 1 - i; j++)
{
if (array[j] > array[j + 1])
swap(&array[j], &array[j + 1]);
}
}
}
選擇排序:
1.從第一個元素開始,然後與所有元素進行比較。
2.遇到比他小的進行交換,一直比較完所有元素,得到最小的那個元素。
3.除了最小的那個元素,其餘重複以上步驟,直到只剩一個元素為止。
程式碼實現:
//選擇排序 //時間複雜度O(n^2) //空間複雜度O(1) //穩定性:不穩定 void SelectSort(int array[], int size) { int i = 0; for (; i < size; i++) { for (int j = i; j < size; j++) { if (array[i]<array[j]) { swap(&array[i], &array[j]); } } } }
插入排序:
1.首先預設第一個元素已經排好序,然後取出下一個元素。
2.將排好序的元素進行從後往前遍歷,如果說已排序的元素大於新元素,則進行搬運,將該元素移到下一位置。
3.繼續遍歷,直到元素小於新元素時,將新元素插入到元素後面。
4.重複以上步驟。直到所有元素比較完成。
程式碼實現:
//插入排序
//時間複雜度O(N^2)
//空間複雜度O(1)
//穩定性:穩定
void InsertSort(int array[], int size)
{
if (size <= 1)
return;
int bound = 1;//[0,bound)有序空間
for (; bound < size; bound++)
{
int bound_value = array[bound];
int i = bound;
for (; i>0; i--)
{
if (array[i - 1] < bound_value)
{
array[i] = array[i - 1];//進行搬運
}
else{
break;
}
}
array[i] = bound_value;
}
}
堆排序:
1.用給定的無序陣列建一個大堆。
2.每次將堆頂元素與最後一個數進行交換。
3.將堆的大小減一,進行重新調整,直到只剩一個元素。
程式碼實現:
//堆排序
//時間複雜度O(nlogn)
//空間複雜度O(1)
//穩定性:不穩定
void AdjustDown(int array[], int size, int index)//向下調整,大堆
{
int parent = index;
int child = 2 * index + 1;
while (child < size){
if (child + 1 < size&&array[child] < array[child + 1])
{
child = child + 1;
}
if (array[parent]<array[child])
{
swap(&array[parent], &array[child]);
}
else{
break;
}
parent = child;
child = 2 * child + 1;
}
return;
}
void HeapCreate(int array, int size)
{
if (size <= 1)
return;
int i = (size - 1 - 1) / 2;
for (; i >= 0; i--)
{
AdjustDown(array, size, i);
}
}
void HeapPop(int array[], int size)
{
if (size <= 1)
return;
swap(&array[0], &array[size - 1]);
AdjustDown(array, size-1,0);
}
void HeapSort(int array[], int size)
{
if (size <= 1)
return;
HeapCreate(array, size);
int i = 0;
for (; i < size; i++)
{
HeapPop(array, size - i);
}
}
歸併排序:
1.申請同等大小的空間,將陣列拆分為一小塊連續的空間(其實也就是拆成1)。
2.設定兩個指標,最初為止為兩個已排好序陣列的起始位置。
3.比較兩個指標所指向的內容,將較小的元素放入到新的空間當中,並且指標向後移動。
4.重複3,直到有一指標指向排好序的末尾。
5.將另一陣列剩餘的元素全都放入新陣列當中。
程式碼實現:
//歸併排序
//時間複雜度O(nlogn)
//空間複雜度O(N)
//穩定性:穩定
void MergeArray(int array[], int beg, int mid, int end, int *tmp)
{
int output = beg;
int cur1 = beg;
int cur2 = mid;
while (cur1 < mid&&cur2 < end)
{
if (array[cur1] < array[cur2])
{
tmp[output++] = array[cur1++];//將較小值放入新空間
}
else{
tmp[output++] = array[cur2++];
}
}
while (cur1 < mid)
{
tmp[output++] = array[cur1++];
}
while (cur2 < end)
{
tmp[output++] = array[cur2++];
}
memcpy(array + beg, tmp + beg, sizeof(int)*(end - beg));//還給原空間
}
void _MergeSort(int array, int beg, int end, int *tmp)
{
if (end - beg <= 1)
return;
int mid = beg + (end - beg) / 2;//分割
_MergeSort(array, beg, mid, tmp);
_MergeSort(array, mid, end, tmp);
MergeArray(array, beg, mid, end, tmp);
}
void MergeSort(int array[], int size)
{
int *tmp = (int *)malloc(sizeof(int)*size);//建立新空間
_MergeSort(array, 0, size, tmp);
free(tmp);
}
快速排序:
1.首先選一個元素,作為它的基準值。
2.定義兩個指標,一個指向陣列的起始,一個指向陣列的末尾。
3.起始指標從前向後移動,找到第一個大於基準值的值,末尾指標從後往前走,找到第一個小於它的值。進行交換。
4.當兩個指標交叉時,迴圈結束。交換起始指標指向的值和基準值的值。
5.返回基準值的下標。得到基準值前面的元素都比基準值小,後面的元素都比基準值大。
6.將基準值前面元素和後面元素進行分割槽重複以上步驟。
程式碼實現:
//快速排序
//時間複雜度O(nlogn)
//空間複雜度O(nlogn)
//穩定性:不穩定
int Partion(int array[], int beg, int end)
{
int left = beg;
int right = end - 1;
int tmp = array[end - 1];//基準值
while (left < right){
while (left < right&&array[left] <= tmp)//找到第一個大於基準值的數
{
++left;
}
while (left<right&&array[right]>=tmp)//找到第一個小於基準值的數
{
--right;
}
if (left < right)
{
swap(&array[left], &array[right]);
}
}
swap(&array[left], &array[end-1]);//將得到left左邊都小於array[left],右邊都大於array[left]
return left;
}
void _QuickSort(int array[], int beg, int end)
{
if (end - beg <= 1)
return;
int mid = Partion(array, beg, end);//分割空間
_QuickSort(array, beg, mid);
_QuickSort(array, mid, end);
}
void QuickSort(int array[], int size)
{
_QuickSort(array, 0, size);
}
int main()
{
int array[] = { 5, 7, 8, 9, 6, 2, 3, 1 };
//BubbleSort(array, sizeof(array) / sizeof(array[0]));
//SelectSort(array, sizeof(array) / sizeof(array[0]));
//InsertSort(array, sizeof(array) / sizeof(array[0]));
//HeapSort(array, sizeof(array) / sizeof(array[0]));
//MergeSort(array, sizeof(array) / sizeof(array[0]));
QuickSort(array, sizeof(array) / sizeof(array[0]));
for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++)
{
printf("%d ", array[i]);
}
printf("\n");
system("pause");
return 0;
}