王道八大排序:直接插入排序 折半插入排序 希尔排序 冒泡排序 快速排序 归并排序 基数排序
文章目錄
- 1、插入排序
- 1.1直接插入排序
- 1.2折半插入排序
- 1.3希爾排序
- 2、交換排序
- 2.1冒泡排序
- 2.2快速排序
- 3、選擇排序
- 3.1簡單選擇排序
- 3.2堆排序
- 4、歸并排序
- 5、基數排序
1、插入排序
1.1直接插入排序
直接插入排序:每次將當前元素按照其大小插入到前面已有序的子序列中。
//arr[0~n-1]存數據; void InsertSort(int arr[], int n){int i, j, temp;//遍歷數組for (i = 1; i < n; i++){//當前元素的前驅大于當前元素if (arr[i - 1] > arr[i]) {temp = arr[i]; //保存arr[i]//將前面有序序列中的所有大于arr[i]的值全部后移一位for (j = i - 1; j >= 0 && arr[j] > temp; j--){arr[j + 1] = arr[j];}arr[j + 1] = temp; //將原arr[i]賦值給arr[j + 1]}//if}//for }1.2折半插入排序
折半插入排序:與折半查找類似,逐一遍歷數組元素,在數組前面有序的序列中找到該元素的位置
void InsertSort(int arr[], int n) {int i, low, high, mid;//用arr[1~n]存數,arr[0]保存當前元素,將arr[1]視為有序;for (i = 2; i<=n; i++) { arr[0] = arr[i]; //初始化low和high指針分別為第一個元素和第i - 1個元素low = 1;high = i - 1;//循環直到low > high,查找當前元素在當前序列中的位置while (low <= high) {mid = (high + low) / 2; //更新mid//mid指向的元素小于arr[0],去左半邊繼續排序if (arr[0] < arr[mid]) high = mid - 1;//mid指向的元素大于等于arr[0],去右半邊,這是該算法穩定的原因else low = mid + 1;}//從arr[high+1]或arr[low]元素統一后移for (int j = i - 1; j >= high+1; j--) {arr[j+1] = arr[j ];}//在arr[high+1]或arr[low]處插入元素arr[high+1] = arr[0];}//for }1.3希爾排序
希爾排序:把相隔某個增量的元素組成一個子表,對各個子表進行直接插入排序,當整個表中基本有序的時候,再對整個表進行一次直接插入排序。
void ShellSort(int arr[], int n) {int d;//初始化d為n/2,每一輪d為上一輪的1/2for (d = n / 2; d >= 1; d /= 2) {//從每個分組的第二個元素開始,遍歷剩余元素,進行直接插入排序for (int i = d+1; i <= n; i++) {if (arr[i] < arr[i - d]) { //將arr[i]直接插入有序增量子表(組間元素對比)arr[0] = arr[i]; //暫存arr[0]int j;for (j = i - d; j > 0 && arr[j] > arr[0]; j -= d) {arr[j + d] = arr[j]; //記錄后移}arr[j + d] = arr[0]; //插入}//if}//for}//for }2、交換排序
2.1冒泡排序
冒泡排序:從后往前兩兩比較相鄰元素的值,若為逆序,則交換。
//交換 void swap(int& a, int& b) {int temp = a;a = b;b = temp; } //冒泡排序 void BubbleSort(int arr[], int n) {for (int i = 0; i < n - 1; i++) {bool flag = false;//標記此輪循環中是否發生交換//每次從數組中最后1個元素向前遍歷,直到第i個元素for (int j = n - 1; j > i; j--) {//將相鄰兩個元素為逆序,則交換,并更改flag。if (arr[j - 1] > arr[j]) {swap(arr[j - 1], arr[j]);flag = true;}}//for//此次循環元素都是正序,則結束函數if (flag==false) return;}//for }2.2快速排序
快速排序:
1、取當前表中的第1個元素為基準元素,找到它在表中的位置,即左邊元素都小于它,右邊元素都大于等于它,這樣就確定了基準元素的最終位置。
2、以它為分割,遞歸的對兩個子表進行上述操作,直到每個表都只有1個或0個元素為止。
3、選擇排序
3.1簡單選擇排序
簡單選擇排序:遍歷數組,每次找到一個最小的元素插入到待排序表的表頭位置。
//交換元素 void swap(int& a, int& b) {int temp = a;a = b;b = temp; } //簡單選擇排序 void SelectSort(int arr[], int n) {//遍歷數組 arr[0~n-2] 最后一個元素arr[n-1]不用遍歷;for (int i = 0; i < n-1; i++) {int min = i; //標記未排序數列中最小值元素的下標,初始為第 i 個元素;for (int j = i + 1; j< n; j++) { //從i + 1開始遍歷數組if (arr[j] < arr[min]) min = j;}//for完之后min指向未排序數列中最小值元素的下標if(min!=i) swap(arr[i], arr[min]); //交換第 i 個元素和最小值元素} }3.2堆排序
堆排序:
1、首先建成大根堆,即堆頂元素大于左右子樹的值,左右子樹也滿足該特性。
2、輸出堆頂元素,將堆底元素送入堆頂,此時堆特性被破壞,將堆頂元素向下調整直到滿足堆特性,再輸出堆頂元素。
3、如此重復,直到堆中只剩一個元素為止。
4、歸并排序
歸并排序:將兩個或多個有序表合并成一個有序表。
//Merge()函數:將前后兩個有序表歸并成一個有序表 int *B= (int*)malloc(sizeof(int) * (maxsize+1)); //輔助數組B[] void Merge(int A[], int L, int mid, int R) {for (int k = L; k <= R; k++)B[k] = A[k]; //將A數組元素復制到B中int i, j, k;//遍歷數組for (i = L, j =mid+1, k = i; i<= mid && j<= R; k++) {if (B[i] <= B[j]) A[k] = B[i++]; //比較B中的左右子表中的元素大小,兩個子表若元素相同,則優先選擇左子表else A[k] =B[j++]; //將較小值復制到A中}//將剩余元素插入到表中while (i <= mid) A[k++] = B[i++];//若一個表未檢測完,復制while (j <= R) A[k++] = B[j++]; //若二個表未檢測完,復制 }void MergeSort(int A[], int L, int R) {if (L < R) {int mid =(L+ R) / 2;//從中間劃分兩個子序列MergeSort(A, L, mid);//對左子表進行遞歸排序MergeSort(A, mid + 1, R); //對右子表進行遞歸排序Merge(A, L,mid, R); //歸并}//if }5、基數排序
基數排序:
不基于比較和移動元素來進行排序,它將一個邏輯關鍵字分為多個關鍵字,基于關鍵字各位的大小進行排序的。
在排序的過程中,需要使用r個隊列。排序過程如下:
分配:開始時,把各個隊列置為空隊列,然后依次考察待排元素的關鍵字大小,把元素放入與關鍵字大小對應的隊列中。
收集:把各個隊列中的結點首尾相接,得到新的元素序列,從而組成新的線性表。
重復分配-收集的過程,直到有序。
總結
以上是生活随笔為你收集整理的王道八大排序:直接插入排序 折半插入排序 希尔排序 冒泡排序 快速排序 归并排序 基数排序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据科学家必备的5种离群点/异常检测方法
- 下一篇: 迅为《i.MX8MM开发板使用手册1.4