日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

一文总结十大经典排序算法(思维导图 + 动图演示 + 代码实现 C/C++/Python + 致命吐槽)

發布時間:2023/12/14 c/c++ 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一文总结十大经典排序算法(思维导图 + 动图演示 + 代码实现 C/C++/Python + 致命吐槽) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

聲明

1)該文章整理自網上的大牛和專家無私奉獻的資料,具體引用的資料請看參考文獻。
2)本文僅供學術交流,非商用。如果某部分不小心侵犯了大家的利益,還望海涵,并聯系博主刪除。
3)博主才疏學淺,文中如有不當之處,請各位指出,共同進步,謝謝。
4)此屬于第一版本,若有錯誤,還需繼續修正與增刪。還望大家多多指點。大家都共享一點點,一起為祖國科研的推進添磚加瓦。

文章目錄

  • 聲明
    • 0、寫在前面
    • 1、冒泡排序
    • 2、選擇排序
    • 3、插入排序
    • 4、希爾排序
    • 5、歸并排序
    • 6、快速排序
    • 7、堆排序
    • 8、計數排序
    • 9、桶排序
    • 10、基數排序
    • 參考

0、寫在前面

最近終于是學到了排序算法,

排序,就是使一串記錄,按照其中的某個或某些關鍵字的大小,遞增或遞減的排列起來的操作。排序算法,就是如何使得記錄按照要求排列的方法。

為什么排序算法在很多領域被相當地重視?

主要是一個優秀的算法可以節省大量的資源,尤其是在大量數據的處理方面。

排序算法可以分為內部排序和外部排序:

  • 內部排序是數據記錄在內存中進行排序,
  • 而外部排序是因排序的數據很大,一次不能容納全部的排序記錄,在排序過程中需要訪問外存。

經典排序算法主要有一下幾個(思維導圖):

點擊查看大圖!

主要的性質肯定少不了:

  • 數據對象

數據對象
數組或者鏈表,或者both。

  • 穩定性

穩定性
假定在待排序的記錄序列中,存在多個具有相同的關鍵字的記錄,若經過排序,這些記錄的相對次序保持不變,即在原序列中,r[i]=r[j],且 r[i] 在 r[j] 之前,而在排序后的序列中,r[i] 仍在 r[j] 之前,則稱這種排序算法是 穩定 的;否則稱為 不穩定 的。

  • 時間復雜度

時間復雜度
時間復雜性,又稱時間復雜度,是一個定性描述該算法的運行時間的函數。

  • 空間復雜度

空間復雜度
空間復雜度是對一個算法在運行過程中臨時占用存儲空間大小的量度。

點擊查看大圖!

1、冒泡排序

描述:

重復地走訪要排序的元素列,依次比較兩個相鄰的元素,如果順序錯誤,就把他們交換。

動圖演示:

  • 什么時候最快?
    當輸入的數據已經是正序時(???那還用排序?都已經是正序了,還要你何用)。
  • 什么時候最慢?
    當輸入的數據是反序時(死心眼嘛?循環反序再輸出數據不就行了,還用你是閑的嗎)。

代碼:

#python def bubbleSort(arr):for i in range(1, len(arr)):for j in range(0, len(arr)-i):if arr[j] > arr[j+1]:arr[j], arr[j + 1] = arr[j + 1], arr[j]return arr //C void swap(int *a,int *b){int temp = *a;*a = *b;*b = temp; } void bubble_sort(int arr[], int len){int i, j, temp;for (i = 0; i < len - 1; i++)for (j = 0; j < len - 1 - i; j++)if (arr[j] > arr[j + 1]) {swap(&arr[j], &arr[j + 1]);} } //C++ template<typename T> void bubble_sort(T arr[], int len) {int i, j;for (i = 0; i < len - 1; i++)for (j = 0; j < len - 1 - i; j++)if (arr[j] > arr[j + 1])swap(arr[j], arr[j + 1]); }

寫一個 Swap 交換和 flag 提前跳出,加上第一層倒序循環,是可以的。


參考MOOC浙大數據結構

// C void Swap(ElementType *a, ElementType *b){ElementType t = *a; *a = *b; *b = t; } void BubbleSort(ElementType A[], int N){int P, i;int flag;for (P = N - 1; P >= 0; P--){flag = 0;for (i = 0; i < P; i++){if (A[i] > A[i + 1]){Swap(&A[i], &A[i + 1]);flag = 1;}}if (flag = 0) break;} }

2、選擇排序

描述:

第一次從待排序的數據元素中選出最小(或最大)的一個元素,存放在序列的起始位置,然后再從剩余的未排序元素中尋找到最小(大)元素,然后放到已排序的序列的末尾。以此類推,直到全部待排序的數據元素的個數為零。

動圖演示:

(其實就是打牌,抓牌,看牌,馬牌)

代碼:

#python def selectionSort(arr):for i in range(len(arr) - 1):# 記錄最小數的索引minIndex = ifor j in range(i + 1, len(arr)):if arr[j] < arr[minIndex]:minIndex = j# i 不是最小數時,將 i 和最小數進行交換if i != minIndex:arr[i], arr[minIndex] = arr[minIndex], arr[i]return arr //C void swap(int *a,int *b){int temp = *a;*a = *b;*b = temp; } void selection_sort(int arr[], int len){int i,j;for (i = 0 ; i < len - 1 ; i++){int min = i;//遍歷未排序的元素for (j = i + 1; j < len; j++){if (arr[j] < arr[min]) //找到目前最小值min = j; //記錄最小值swap(&arr[min], &arr[i]); //做交換}} } //C++ template<typename T> void selection_sort(std::vector<T>& arr) {for (int i = 0; i < arr.size() - 1; i++) {int min = i;for (int j = i + 1; j < arr.size(); j++){if (arr[j] < arr[min])min = j;std::swap(arr[i], arr[min]);}} }

參考MOOC浙大數據結構

// C void Swap(ElementType *a, ElementType *b){ElementType t = *a; *a = *b; *b = t; } void SimpleSelectionSort(ElementType A[], int N){int i, j, min;for (i = 0; i < N-1; i++){min = i;for (j = i + 1; j < N; j++){if (A[i] < A[min])min = j;Swap(&A[i], &A[min]);}} }

3、插入排序

描述:

通過構建有序序列,對于未排序數據,在已排序序列中從后向前掃描,找到相應位置并插入。

動圖演示:

(慢,真的慢,不是假的)

代碼:

#python def insertionSort(arr):for i in range(len(arr)):preIndex = i-1current = arr[i]while preIndex >= 0 and arr[preIndex] > current:arr[preIndex+1] = arr[preIndex]preIndex-=1arr[preIndex+1] = currentreturn arr //C void insertion_sort(int arr[], int len){int i,j,key;for (i=1;i<len;i++){key = arr[i];j=i-1;while((j>=0) && (arr[j]>key)) {arr[j+1] = arr[j];j--;}arr[j+1] = key;} } //C++ void insertion_sort(int arr[],int len){for(int i=1;i<len;i++){int key=arr[i];int j=i-1;while((j>=0) && (key<arr[j])){arr[j+1]=arr[j];j--;}arr[j+1]=key;} }

參考MOOC浙大數據結構

void InsertionSort( ElementType A[], int N ){int P, i;ElementType Tmp;for ( P=1; P<N; P++ ) {Tmp = A[P];for ( i=P; i>0 && A[i-1]>Tmp; i-- )A[i] = A[i-1];A[i] = Tmp;} }

4、希爾排序

描述:

把記錄按下標的一定增量分組,對每組使用直接插入排序算法排序;隨著增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個文件恰被分成一組,算法便終止。

動圖演示:

希爾排序是基于插入排序進行改進的,(改完確實快了好多啊,以前是老黃牛,現在是小摩托了)

代碼:

#python def shellSort(arr):import mathgap=1while(gap < len(arr)/3):gap = gap*3+1while gap > 0:for i in range(gap,len(arr)):temp = arr[i]j = i-gapwhile j >=0 and arr[j] > temp:arr[j+gap]=arr[j]j-=gaparr[j+gap] = tempgap = math.floor(gap/3)return arr //C void shell_sort(int arr[], int len) {int gap, i, j;int temp;for (gap = len >> 1; gap > 0; gap >>= 1){for (i = gap; i < len; i++) {temp = arr[i];for (j = i - gap; j >= 0 && arr[j] > temp; j -= gap)arr[j + gap] = arr[j];arr[j + gap] = temp;}} } //C++ template<typename T> void shell_sort(T array[], int length) {int h = 1;while (h < length / 3) {h = 3 * h + 1;}while (h >= 1) {for (int i = h; i < length; i++) {for (int j = i; j >= h && array[j] < array[j - h]; j -= h) {std::swap(array[j], array[j - h]);}}h = h / 3;} }

參考MOOC浙大數據結構

void ShellSort( ElementType A[], int N ){int Si, D, P, i;ElementType Tmp;/* 這里只列出一小部分增量 */int Sedgewick[] = {929, 505, 209, 109, 41, 19, 5, 1, 0};for ( Si=0; Sedgewick[Si]>=N; Si++ ) ;for ( D=Sedgewick[Si]; D>0; D=Sedgewick[++Si] ){for ( P=D; P<N; P++ ){Tmp = A[P];for ( i=P; i>=D && A[i-D]>Tmp; i-=D )A[i] = A[i-D];A[i] = Tmp;}} }

5、歸并排序

描述:

采用分而治之法的一個非常典型的應用,將已有序的子序列合并,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。

動圖演示:

就是化整為零,分家,哈哈

代碼:

#python def mergeSort(arr):import mathif(len(arr)<2):return arrmiddle = math.floor(len(arr)/2)left, right = arr[0:middle], arr[middle:]return merge(mergeSort(left), mergeSort(right))def merge(left,right):result = []while left and right:if left[0] <= right[0]:result.append(left.pop(0))else:result.append(right.pop(0));while left:result.append(left.pop(0))while right:result.append(right.pop(0));return result //C void merge_sort_recursive(int arr[], int reg[], int start, int end) {if (start >= end)return;int len = end - start, mid = (len >> 1) + start;int start1 = start, end1 = mid;int start2 = mid + 1, end2 = end;merge_sort_recursive(arr, reg, start1, end1);merge_sort_recursive(arr, reg, start2, end2);int k = start;while (start1 <= end1 && start2 <= end2)reg[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++];while (start1 <= end1)reg[k++] = arr[start1++];while (start2 <= end2)reg[k++] = arr[start2++];for (k = start; k <= end; k++)arr[k] = reg[k]; } void merge_sort(int arr[], const int len) {int reg[len];merge_sort_recursive(arr, reg, 0, len - 1); } //C++ void Merge(vector<int> &Array, int front, int mid, int end) {// preconditions:// Array[front...mid] is sorted// Array[mid+1 ... end] is sorted// Copy Array[front ... mid] to LeftSubArray// Copy Array[mid+1 ... end] to RightSubArrayvector<int> LeftSubArray(Array.begin() + front, Array.begin() + mid + 1);vector<int> RightSubArray(Array.begin() + mid + 1, Array.begin() + end + 1);int idxLeft = 0, idxRight = 0;LeftSubArray.insert(LeftSubArray.end(), numeric_limits<int>::max());RightSubArray.insert(RightSubArray.end(), numeric_limits<int>::max());// Pick min of LeftSubArray[idxLeft] and RightSubArray[idxRight], // and put into Array[i]for (int i = front; i <= end; i++) {if (LeftSubArray[idxLeft] < RightSubArray[idxRight]) {Array[i] = LeftSubArray[idxLeft];idxLeft++;} else {Array[i] = RightSubArray[idxRight];idxRight++;}} } void MergeSort(vector<int> &Array, int front, int end) {if (front >= end)return;int mid = (front + end) / 2;MergeSort(Array, front, mid);MergeSort(Array, mid + 1, end);Merge(Array, front, mid, end); }

參考MOOC浙大數據結構

//C /* L = 左邊起始位置, R = 右邊起始位置, RightEnd = 右邊終點位置*/ void Merge( ElementType A[], ElementType TmpA[], int L, int R, int RightEnd ){ /* 將有序的A[L]~A[R-1]和A[R]~A[RightEnd]歸并成一個有序序列 */int LeftEnd, NumElements, Tmp;int i;LeftEnd = R - 1; /* 左邊終點位置 */Tmp = L; /* 有序序列的起始位置 */NumElements = RightEnd - L + 1;while( L <= LeftEnd && R <= RightEnd ) {if ( A[L] <= A[R] )TmpA[Tmp++] = A[L++]; /* 將左邊元素復制到TmpA */elseTmpA[Tmp++] = A[R++]; /* 將右邊元素復制到TmpA */}while( L <= LeftEnd )TmpA[Tmp++] = A[L++]; /* 直接復制左邊剩下的 */while( R <= RightEnd )TmpA[Tmp++] = A[R++]; /* 直接復制右邊剩下的 */for( i = 0; i < NumElements; i++, RightEnd -- )A[RightEnd] = TmpA[RightEnd]; /* 將有序的TmpA[]復制回A[] */ } void Msort( ElementType A[], ElementType TmpA[], int L, int RightEnd ){ /* 核心遞歸排序函數 */ int Center;if ( L < RightEnd ) {Center = (L+RightEnd) / 2;Msort( A, TmpA, L, Center ); /* 遞歸解決左邊 */ Msort( A, TmpA, Center+1, RightEnd ); /* 遞歸解決右邊 */ Merge( A, TmpA, L, Center+1, RightEnd ); /* 合并兩段有序序列 */ } } void MergeSort( ElementType A[], int N ){ /* 歸并排序 */ElementType *TmpA;TmpA = (ElementType *)malloc(N*sizeof(ElementType));if ( TmpA != NULL ) {Msort( A, TmpA, 0, N-1 );free( TmpA );}else printf( "空間不足" ); }

6、快速排序

描述:

通過一趟排序將待排記錄分隔成獨立的兩部分,其中一部分記錄的關鍵字均比另一部分的關鍵字小,則可分別對這兩部分記錄繼續進行排序,以達到整個序列有序。

動圖演示:

快速排序是目前感覺最厲害的。

代碼:

#python def quickSort(arr, left=None, right=None):left = 0 if not isinstance(left,(int, float)) else leftright = len(arr)-1 if not isinstance(right,(int, float)) else rightif left < right:partitionIndex = partition(arr, left, right)quickSort(arr, left, partitionIndex-1)quickSort(arr, partitionIndex+1, right)return arrdef partition(arr, left, right):pivot = leftindex = pivot+1i = indexwhile i <= right:if arr[i] < arr[pivot]:swap(arr, i, index)index+=1i+=1swap(arr,pivot,index-1)return index-1def swap(arr, i, j):arr[i], arr[j] = arr[j], arr[i] //C void swap(int *x, int *y) {int t = *x;*x = *y;*y = t; }void quick_sort_recursive(int arr[], int start, int end) {if (start >= end)return;int mid = arr[end];int left = start, right = end - 1;while (left < right) {while (arr[left] < mid && left < right)left++;while (arr[right] >= mid && left < right)right--;swap(&arr[left], &arr[right]);}if (arr[left] >= arr[end])swap(&arr[left], &arr[end]);elseleft++;if (left)quick_sort_recursive(arr, start, left - 1);quick_sort_recursive(arr, left + 1, end); }void quick_sort(int arr[], int len) {quick_sort_recursive(arr, 0, len - 1); } //C++ template <typename T> void quick_sort_recursive(T arr[], int start, int end) {if (start >= end)return;T mid = arr[end];int left = start, right = end - 1;//在整個范圍內搜尋比樞紐元值小或大的元素,然后將左側元素與右側元素交換while (left < right) { //試圖在左側找到一個比樞紐元更大的元素while (arr[left] < mid && left < right)left++;//試圖在右側找到一個比樞紐元更小的元素while (arr[right] >= mid && left < right)right--;std::swap(arr[left], arr[right]); //交換元素}if (arr[left] >= arr[end])std::swap(arr[left], arr[end]);elseleft++;quick_sort_recursive(arr, start, left - 1);quick_sort_recursive(arr, left + 1, end); }template <typename T> void quick_sort(T arr[], int len) {quick_sort_recursive(arr, 0, len - 1); }

參考MOOC浙大數據結構

//c //判斷數組規模,如果太小,直接就插入排序 void swap(int *a,int *b){int temp = *a;*a = *b;*b = temp; }void InsertionSort( ElementType A[], int N ){int P, i;ElementType Tmp;for ( P=1; P<N; P++ ) {Tmp = A[P];for ( i=P; i>0 && A[i-1]>Tmp; i-- )A[i] = A[i-1];A[i] = Tmp;} }ElementType Median3(ElementType A[], int Left, int Right){int Center=(Left+Right)/2;if(A[Left]>A[center])Swap(&A[Left], &A[center]);if(A[Left]>A[Right])Swap(&A[Left], &A[Right]);if(A[center]>A[Right])Swap(&A[Center], &A[Right]);/*此時A[Left]c=A[center]c=A[Right]*/Swap(&A[center], &A[Right-1]); /*將基準Pivot藏到右邊*//*只需要考慮A[Left+1]…A[Right-2]*/return A[Right-1]; /*返回基準 Pivot*/ }void Qsort(Elementrype A[], int Left, int Right){/*核心遞歸函數*/int pivot, Cutoff, Low, High;if(Cutoff<=Right-Left){ /*如果序列元素充分多,進入快排*/Pivot=Median3(A, Left, Right); /*選基準*/Low=Left;High=Right-1;while(1){ /*將序列中比基準小的移到基準左邊,大的移到右邊*/while(A[++Low]<Pivot);while(A[--High]>pivot);if(Low<High) Swap(&A[Low], &A[High]);else break;}Swap(&A[Low], &A[Right-1]); /*將基準換到正確的位置*/Qsort(A, Left, Low-1); /*遞歸解決左邊*/Qsort(A, Low+1, Right); /*遞歸解決右邊*/}else Insertionsort(A+Left, Right-Left+1); /*元素太少,用簡單排序*/ }void Quicksort(ElementType A[]int N){/*統一接口*/Qsort(A, 0, N-1); }

7、堆排序

描述:

堆排序是指利用堆這種數據結構所設計的一種排序算法。堆積是一個近似完全二叉樹的結構,并同時滿足堆積的性質:即子結點的鍵值或索引總是小于(或者大于)它的父節點。

動圖演示:

堆排序是其實就和之前的堆一樣,但是我不太會。

代碼:

#python def buildMaxHeap(arr):import mathfor i in range(math.floor(len(arr)/2),-1,-1):heapify(arr,i)def heapify(arr, i):left = 2*i+1right = 2*i+2largest = iif left < arrLen and arr[left] > arr[largest]:largest = leftif right < arrLen and arr[right] > arr[largest]:largest = rightif largest != i:swap(arr, i, largest)heapify(arr, largest)def swap(arr, i, j):arr[i], arr[j] = arr[j], arr[i]def heapSort(arr):global arrLenarrLen = len(arr)buildMaxHeap(arr)for i in range(len(arr)-1,0,-1):swap(arr,0,i)arrLen -=1heapify(arr, 0)return arr //C void swap(int *a, int *b) {int temp = *b;*b = *a;*a = temp; }void max_heapify(int arr[], int start, int end) {// 建立父節點指標和子節點指標int dad = start;int son = dad * 2 + 1;while (son <= end) { // 若子節點指標在範圍內才做比較if (son + 1 <= end && arr[son] < arr[son + 1]) // 先比較兩個子節點大小,選擇最大的son++;if (arr[dad] > arr[son]) //如果父節點大於子節點代表調整完畢,直接跳出函數return;else { // 否則交換父子內容再繼續子節點和孫節點比較swap(&arr[dad], &arr[son]);dad = son;son = dad * 2 + 1;}} }void heap_sort(int arr[], int len) {int i;// 初始化,i從最後一個父節點開始調整for (i = len / 2 - 1; i >= 0; i--)max_heapify(arr, i, len - 1);// 先將第一個元素和已排好元素前一位做交換,再重新調整,直到排序完畢for (i = len - 1; i > 0; i--) {swap(&arr[0], &arr[i]);max_heapify(arr, 0, i - 1);} } //C++ void max_heapify(int arr[], int start, int end) {// 建立父節點指標和子節點指標int dad = start;int son = dad * 2 + 1;while (son <= end) { // 若子節點指標在範圍內才做比較if (son + 1 <= end && arr[son] < arr[son + 1]) // 先比較兩個子節點大小,選擇最大的son++;if (arr[dad] > arr[son]) // 如果父節點大於子節點代表調整完畢,直接跳出函數return;else { // 否則交換父子內容再繼續子節點和孫節點比較swap(arr[dad], arr[son]);dad = son;son = dad * 2 + 1;}} }void heap_sort(int arr[], int len) {// 初始化,i從最後一個父節點開始調整for (int i = len / 2 - 1; i >= 0; i--)max_heapify(arr, i, len - 1);// 先將第一個元素和已經排好的元素前一位做交換,再從新調整(剛調整的元素之前的元素),直到排序完畢for (int i = len - 1; i > 0; i--) {swap(arr[0], arr[i]);max_heapify(arr, 0, i - 1);} }

參考MOOC浙大數據結構

void Swap( ElementType *a, ElementType *b ) {ElementType t = *a; *a = *b; *b = t; }void PercDown( ElementType A[], int p, int N ) { /* 改編代碼4.24的PercDown( MaxHeap H, int p ) *//* 將N個元素的數組中以A[p]為根的子堆調整為最大堆 */int Parent, Child;ElementType X;X = A[p]; /* 取出根結點存放的值 */for( Parent=p; (Parent*2+1)<N; Parent=Child ) {Child = Parent * 2 + 1;if( (Child!=N-1) && (A[Child]<A[Child+1]) )Child++; /* Child指向左右子結點的較大者 */if( X >= A[Child] ) break; /* 找到了合適位置 */else /* 下濾X */A[Parent] = A[Child];}A[Parent] = X; }void HeapSort( ElementType A[], int N ) { /* 堆排序 */int i;for ( i=N/2-1; i>=0; i-- )/* 建立最大堆 */PercDown( A, i, N );for ( i=N-1; i>0; i-- ) {/* 刪除最大堆頂 */Swap( &A[0], &A[i] ); /* 見代碼7.1 */PercDown( A, 0, i );} }

8、計數排序

描述:

計數排序不是基于比較的排序算法,其核心在于將輸入的數據值轉化為鍵存儲在額外開辟的數組空間中。

動圖演示:

如果不是一定需要比較的例子,計數要快不知道多少,比如工齡統計。

代碼:

#python def countingSort(arr, maxValue):bucketLen = maxValue+1bucket = [0]*bucketLensortedIndex =0arrLen = len(arr)for i in range(arrLen):if not bucket[arr[i]]:bucket[arr[i]]=0bucket[arr[i]]+=1for j in range(bucketLen):while bucket[j]>0:arr[sortedIndex] = jsortedIndex+=1bucket[j]-=1return arr //C void print_arr(int *arr, int n) {int i;printf("%d", arr[0]);for (i = 1; i < n; i++)printf(" %d", arr[i]);printf("\n"); }void counting_sort(int *ini_arr, int *sorted_arr, int n) {int *count_arr = (int *) malloc(sizeof(int) * 100);int i, j, k;for (k = 0; k < 100; k++)count_arr[k] = 0;for (i = 0; i < n; i++)count_arr[ini_arr[i]]++;for (k = 1; k < 100; k++)count_arr[k] += count_arr[k - 1];for (j = n; j > 0; j--)sorted_arr[--count_arr[ini_arr[j - 1]]] = ini_arr[j - 1];free(count_arr); }

9、桶排序

描述:

桶排序是計數排序的升級版。它利用了函數的映射關系,高效與否的關鍵就在于這個映射函數的確定。

動圖演示:


看來計數排序是真的很好用,不然不會有plus!

代碼:

struct ListNode{explicit ListNode(int i=0):mData(i),mNext(NULL){}ListNode* mNext;int mData; };ListNode* insert(ListNode* head,int val){ListNode dummyNode;ListNode *newNode = new ListNode(val);ListNode *pre,*curr;dummyNode.mNext = head;pre = &dummyNode;curr = head;while(NULL!=curr && curr->mData<=val){pre = curr;curr = curr->mNext;}newNode->mNext = curr;pre->mNext = newNode;return dummyNode.mNext; }ListNode* Merge(ListNode *head1,ListNode *head2){ListNode dummyNode;ListNode *dummy = &dummyNode;while(NULL!=head1 && NULL!=head2){if(head1->mData <= head2->mData){dummy->mNext = head1;head1 = head1->mNext;}else{dummy->mNext = head2;head2 = head2->mNext;}dummy = dummy->mNext;}if(NULL!=head1) dummy->mNext = head1;if(NULL!=head2) dummy->mNext = head2;return dummyNode.mNext; }void BucketSort(int n,int arr[]){vector<ListNode*> buckets(BUCKET_NUM,(ListNode*)(0));for(int i=0;i<n;++i){int index = arr[i]/BUCKET_NUM;ListNode *head = buckets.at(index);buckets.at(index) = insert(head,arr[i]);}ListNode *head = buckets.at(0);for(int i=1;i<BUCKET_NUM;++i){head = Merge(head,buckets.at(i));}for(int i=0;i<n;++i){arr[i] = head->mData;head = head->mNext;} }

10、基數排序

描述:

基數排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次類推,直到最高位。有時候有些屬性是有優先級順序的,先按低優先級排序,再按高優先級排序。最后的次序就是高優先級高的在前,高優先級相同的低優先級高的在前。

動圖演示:

基數排序就像撲克分類!

是數字還是色號?

代碼:

//C void print(int *a, int n) {int i;for (i = 0; i < n; i++) {printf("%d\t", a[i]);} }void radixsort(int *a, int n) {int i, b[MAX], m = a[0], exp = 1;for (i = 1; i < n; i++) {if (a[i] > m) {m = a[i];}}while (m / exp > 0) {int bucket[BASE] = { 0 };for (i = 0; i < n; i++) {bucket[(a[i] / exp) % BASE]++;}for (i = 1; i < BASE; i++) {bucket[i] += bucket[i - 1];}for (i = n - 1; i >= 0; i--) {b[--bucket[(a[i] / exp) % BASE]] = a[i];}for (i = 0; i < n; i++) {a[i] = b[i];}exp *= BASE;#ifdef SHOWPASSprintf("\nPASS : ");print(a, n); #endif} } //C++ //輔助函數,求數據的最大位數 int maxbit(int data[], int n) {int maxData = data[0]; ///< 最大數/// 先求出最大數,再求其位數,這樣有原先依次每個數判斷其位數,稍微優化點。for (int i = 1; i < n; ++i) {if (maxData < data[i])maxData = data[i];}int d = 1;int p = 10;while (maxData >= p) {//p *= 10; // Maybe overflowmaxData /= 10;++d;}return d; } //基數排序 void radixsort(int data[], int n) {int d = maxbit(data, n);int *tmp = new int[n];int *count = new int[10]; //計數器int i, j, k;int radix = 1;//進行d次排序for(i = 1; i <= d; i++) {for(j = 0; j < 10; j++)count[j] = 0; //每次分配前清空計數器for(j = 0; j < n; j++){k = (data[j] / radix) % 10; //統計每個桶中的記錄數count[k]++;}for(j = 1; j < 10; j++)count[j] = count[j - 1] + count[j]; //將tmp中的位置依次分配給每個桶for(j = n - 1; j >= 0; j--) { //將所有桶中記錄依次收集到tmp中k = (data[j] / radix) % 10;tmp[count[k] - 1] = data[j];count[k]--;}for(j = 0; j < n; j++) //將臨時數組的內容復制到data中data[j] = tmp[j];radix = radix * 10;}delete []tmp;delete []count; }

參考MOOC浙大數據結構

//c /* 基數排序 - 次位優先 *//* 假設元素最多有MaxDigit個關鍵字,基數全是同樣的Radix */ #define MaxDigit 4 #define Radix 10/* 桶元素結點 */ typedef struct Node *PtrToNode; struct Node {int key;PtrToNode next; };/* 桶頭結點 */ struct HeadNode {PtrToNode head, tail; }; typedef struct HeadNode Bucket[Radix];int GetDigit ( int X, int D ) { /* 默認次位D=1, 主位D<=MaxDigit */int d, i;for (i=1; i<=D; i++) {d = X % Radix;X /= Radix;}return d; }void LSDRadixSort( ElementType A[], int N ) { /* 基數排序 - 次位優先 */int D, Di, i;Bucket B;PtrToNode tmp, p, List = NULL; for (i=0; i<Radix; i++) /* 初始化每個桶為空鏈表 */B[i].head = B[i].tail = NULL;for (i=0; i<N; i++) { /* 將原始序列逆序存入初始鏈表List */tmp = (PtrToNode)malloc(sizeof(struct Node));tmp->key = A[i];tmp->next = List;List = tmp;}/* 下面開始排序 */ for (D=1; D<=MaxDigit; D++) { /* 對數據的每一位循環處理 *//* 下面是分配的過程 */p = List;while (p) {Di = GetDigit(p->key, D); /* 獲得當前元素的當前位數字 *//* 從List中摘除 */tmp = p; p = p->next;/* 插入B[Di]號桶尾 */tmp->next = NULL;if (B[Di].head == NULL)B[Di].head = B[Di].tail = tmp;else {B[Di].tail->next = tmp;B[Di].tail = tmp;}}/* 下面是收集的過程 */List = NULL; for (Di=Radix-1; Di>=0; Di--) { /* 將每個桶的元素順序收集入List */if (B[Di].head) { /* 如果桶不為空 *//* 整桶插入List表頭 */B[Di].tail->next = List;List = B[Di].head;B[Di].head = B[Di].tail = NULL; /* 清空桶 */}}}/* 將List倒入A[]并釋放空間 */for (i=0; i<N; i++) {tmp = List;List = List->next;A[i] = tmp->key;free(tmp);} }/* 基數排序 - 主位優先 *//* 假設元素最多有MaxDigit個關鍵字,基數全是同樣的Radix */#define MaxDigit 4 #define Radix 10/* 桶元素結點 */ typedef struct Node *PtrToNode; struct Node{int key;PtrToNode next; };/* 桶頭結點 */ struct HeadNode {PtrToNode head, tail; }; typedef struct HeadNode Bucket[Radix];int GetDigit ( int X, int D ) { /* 默認次位D=1, 主位D<=MaxDigit */int d, i;for (i=1; i<=D; i++) {d = X%Radix;X /= Radix;}return d; }void MSD( ElementType A[], int L, int R, int D ) { /* 核心遞歸函數: 對A[L]...A[R]的第D位數進行排序 */int Di, i, j;Bucket B;PtrToNode tmp, p, List = NULL; if (D==0) return; /* 遞歸終止條件 */for (i=0; i<Radix; i++) /* 初始化每個桶為空鏈表 */B[i].head = B[i].tail = NULL;for (i=L; i<=R; i++) { /* 將原始序列逆序存入初始鏈表List */tmp = (PtrToNode)malloc(sizeof(struct Node));tmp->key = A[i];tmp->next = List;List = tmp;}/* 下面是分配的過程 */p = List;while (p) {Di = GetDigit(p->key, D); /* 獲得當前元素的當前位數字 *//* 從List中摘除 */tmp = p; p = p->next;/* 插入B[Di]號桶 */if (B[Di].head == NULL) B[Di].tail = tmp;tmp->next = B[Di].head;B[Di].head = tmp;}/* 下面是收集的過程 */i = j = L; /* i, j記錄當前要處理的A[]的左右端下標 */for (Di=0; Di<Radix; Di++) { /* 對于每個桶 */if (B[Di].head) { /* 將非空的桶整桶倒入A[], 遞歸排序 */p = B[Di].head;while (p) {tmp = p;p = p->next;A[j++] = tmp->key;free(tmp);}/* 遞歸對該桶數據排序, 位數減1 */MSD(A, i, j-1, D-1);i = j; /* 為下一個桶對應的A[]左端 */} } }void MSDRadixSort( ElementType A[], int N ) { /* 統一接口 */MSD(A, 0, N-1, MaxDigit); }


我還是喜歡浙大的代碼風格!

參考

  • 百度百科
  • https://www.runoob.com/
  • https://github.com/hustcc/JS-Sorting-Algorithm

總結

以上是生活随笔為你收集整理的一文总结十大经典排序算法(思维导图 + 动图演示 + 代码实现 C/C++/Python + 致命吐槽)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。