C語言實現各種排序(1)
阿新 • • 發佈:2018-12-16
#include<stdio.h> //排序分為插入排序,希爾排序,氣泡排序,快速排序,選擇排序,堆排序,歸併排序,基數排序(桶排序) //1.1 //直接插入排序,較為簡單,思路為從第二個數開始逐個將其插入前面有序的序列中 //平均時間複雜度為O(N2),最快時間複雜度為O(N),最壞時間複雜度為O(N2),空間複雜度為O(1) void InsertSort(int *a,int n) { int i; for (i = 2; i <= n; i++) { if (a[i-1] > a[i]) { int j = i - 1; a[0] = a[i]; for (; j > 0 && a[j] > a[0]; j--) a[j + 1] = a[j]; a[j + 1] = a[0]; } } } //1.2 //折半插入排序 //思路相同,查詢方法改為折半查詢插入位置 void BInsertSort(int *a, int n) { int i; for (i = 2; i <= n; i++) { if (a[i - 1] > a[i]) { a[0] = a[i]; int low = 1, high = i - 1; while (low <= high) { int mid = (low + high)/2; if (a[mid] > a[0]) high = mid - 1; else low = mid + 1; } int j; for (j = i - 1; j > high; j--) { a[j + 1] = a[j]; } a[j + 1] = a[0]; } } } //1.3 //二路插入排序 //具體實現不再寫,思路為設定一個頭指標為較小的數,設定一個尾指標為較大的數,開始迴圈查詢,若數比頭指標小則插入頭指標前,若比尾指標大 //則插入尾指標後,若在二者之間則利用二分查詢找到合適的插入位置進行位置變換。 //1.4 //希爾排序思路與直接插入排序相似,加入步長概念,原理為排較為有序的序列時時間較短 //平均時間複雜度O(N1.3),空間複雜度為O(1) void ShellInsert(int *a, int n, int dk)//一趟希爾插入排序,dk為步長 { int i; for (i = dk + 1; i <= n; i++) { if (a[i - dk] > a[i]) { a[0] = a[i]; int j; for (j = i - dk; j > 0 && a[j] > a[0]; j -= dk) a[j + dk] = a[j]; a[j + dk] = a[0]; } } } void ShellSort(int *a, int n, int *dlt,int k)//按照增量為dlt[0...k-1]做一次希爾排序 { int i = 0; for (i = 0; i < k; i++) { ShellInsert(a, n, dlt[i]); } } //2.1 //基於交換的排序,氣泡排序法 //平均時間複雜度為O(N2),最壞時間複雜度為O(N2),最好時間複雜度為O(N) void BubbleSort(int *a, int length)//相當於每次將最大或最小的排到最後一個 { for (int i = 0; i < length - 1; i++) { for (int j = 0; j < length - i - 1; j++) { if (a[j] > a[j + 1]) { int temp; temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; } } } } //2.2 //快速排序,設定low和high兩個指標,每次排完後找到一個樞軸,使其左邊為比它小的元素,右邊為比它大的元素; //再繼續對其左邊和右邊執行這個過程 //平均時間複雜度和最好時間複雜度都為O(N*logN),最壞時間複雜度為O(N2) int Partition(int *a, int left,int right) { int low = left, high = right; int base=a[low]; while (low < high) { while (low<high&&a[high]>=base) high--; if (low < high) a[low] = a[high]; while (low < high&&a[low] <= base) low++; if (low < high) a[high] = a[low]; } a[low] = base; return low; } void QSort(int *a, int left, int right) { if (left < right) { int pivotloc = Partition(a, left, right); QSort(a, left, pivotloc - 1); QSort(a, pivotloc + 1, right); } } //3.1 //基於選擇的排序 //選擇排序,思路為每次迴圈找到最小的並將其放在陣列頭處 //平均複雜度O(N2),最壞情況O(N2),最好情況O(N) void SelectSort(int *a, int n) { int i, j; int min, temp; for (i = 0; i < n-1; i++) { min = i; for (j = i; j < n; j++) { if (a[j] < a[min]) min = j; } temp = a[min]; a[min] = a[i]; a[i] = temp; } } //3.2 //堆排序 思路:建立堆,初始化堆,每次輸出堆頂後將最後一個節點與堆頂互換,重新調整堆 //該排序為從小到大排序 //平均最壞最好時間複雜度都為O(N*logN) typedef struct Heap { int length; int *elem; }Heap; void HeapAdjust(Heap H,int s,int m)//調整使其成為一個大頂堆 { int largest; int temp; int lc = 2 * s; int rc = lc + 1; if (H.elem[lc] > H.elem[s] && lc <= m) largest = lc; else largest = s; if (H.elem[rc] > H.elem[largest] && rc <= m) largest = rc; if (largest != s) { temp = H.elem[largest]; H.elem[largest] = H.elem[s]; H.elem[s] = temp; HeapAdjust(H, largest, m); } } void HeapSort(Heap H) { int i, temp; for (i = H.length / 2; i > 0; i--) { HeapAdjust(H, i, H.length); }//初始化堆 for (i = H.length; i > 1; i--) { temp = H.elem[1]; H.elem[1] = H.elem[i]; H.elem[i] = temp; HeapAdjust(H, 1, i-1); }//將堆頂和最後一個互換位置,然後對前i-1個元素重新調整 } //4.1 //歸併排序,平均最好最壞時間複雜度都為O(N*logN) //思路對每一部分進行排序,使用的思想是歸併思想,利用分治的策略解決問題 //重複比較加填入的方法 int main() { int a[11] = { 0,3,1,3,2,4,5,6,1,7,13 }; /*InsertSort(a, 10);*/ //插入排序測試 /*BInsertSort(a, 10);*/ //二分插入排序測試 /*int dlt[4] = { 4,3,2,1 }; //希爾排序測試 ShellSort(a, 10, dlt, 4);*/ /*BubbleSort(a + 1, 10);*/ //氣泡排序測試 /*QSort(a, 1, 10);*/ //快排測試 /*SelectSort(a+1, 10);*/ //選擇排序測試 /*Heap H; //堆排序測試 H.elem = a; H.length = 10; HeapSort(H);*/ for (int i = 1; i < 11; i++) printf("%d ", a[i]); }