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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

排序下---(冒泡排序,快速排序,快速排序优化,快速排序非递归,归并排序,计数排序)

發(fā)布時(shí)間:2023/11/30 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 排序下---(冒泡排序,快速排序,快速排序优化,快速排序非递归,归并排序,计数排序) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

排序上

排序上

交換類排序

基本思想:所謂交換,就是根據(jù)序列中兩個(gè)記錄鍵值的比較結(jié)果來對換這兩個(gè)記錄在序列中的位置,交換排序的特點(diǎn)是:將鍵值較大的記錄向序列的尾部移動,鍵值較小的記錄向序列的前部移動。

冒泡排序

冒泡排序的特性總結(jié):

  • 冒泡排序是一種非常容易理解的排序
  • 時(shí)間復(fù)雜度:O(N^2)
  • 空間復(fù)雜度:O(1)
  • 穩(wěn)定性:穩(wěn)定
  • 代碼實(shí)現(xiàn)

    void BublleSort(int*array, int size) {for (int i = 0; i < size - 1; ++i) //總共冒泡的趟數(shù){//冒泡的方式----->用相鄰元素進(jìn)行比較for (int j = 0; j < size - i - 1; ++j) //一次冒泡{if (array[j]>array[j + 1])Swap(&array[j], &array[j + 1]);}} }

    冒泡排序優(yōu)化

    void BublleSort(int*array, int size) { for (int i = 0; i < size - 1; ++i) //總共冒泡的趟數(shù){int IsChange = 0; //查看這一趟有沒有交換//冒泡的方式----->用相鄰元素進(jìn)行比較for (int j = 0; j < size - i - 1; ++j) //一次冒泡{if (array[j]>array[j + 1]){Swap(&array[j], &array[j + 1]);IsChange = 1;} }if (!IsChange) //如果沒有交換return;} }

    快速排序

    一種二叉樹結(jié)構(gòu)的交換排序方法,其基本思想為:任取待排序元素序列中的某元素作為基準(zhǔn)值,按照該排序碼將待排序集合分割成兩子序列,左子序列中所有元素均小于基準(zhǔn)值,右子序列中所有元素均大于基準(zhǔn)值,然后最左右子序列重復(fù)該過程,直到所有元素都排列在相應(yīng)位置上為止。

    快速排序的特性總結(jié):
  • 快速排序整體的綜合性能和使用場景都是比較好的,所以才敢叫快速排序
  • 時(shí)間復(fù)雜度:O(N*logN),最差場景,單支樹O(N2)
  • 空間復(fù)雜度:O(logN)
  • 穩(wěn)定性:不穩(wěn)定
  • 快排參考鏈接
  • 代碼實(shí)現(xiàn)

    int Partion(int*array, int left, int right) {//劃分基準(zhǔn)值 } void QuickSort(int *array, int left, int right) {if (right - left > 1){int div = Partion(array, left, right);QuickSort(array, left, div);QuickSort(array, div + 1, right);} }

    劃分基準(zhǔn)值的方式

  • hoare版本
  • int Partion(int*array, int left, int right) {int key = array[right - 1];int begin = left;int end = right - 1;while (begin<end){//從前往后找比基準(zhǔn)值大的元素,找到就停下來,等于也往前走,因?yàn)檎业氖谴蟮?/span>while (begin < end&&array[begin] <= key)begin++;//end從后往前找比基準(zhǔn)值小的元素,找到就停下來,等于也往前走,找的是小的,不是等于while (begin < end&&array[end] >= key)end--;if (begin < end)Swap(&array[begin], &array[end]);}if (begin != right - 1)Swap(&array[begin], &array[right-1]);return begin; }
  • 挖坑法
  • int Partion2(int*array, int left, int right) {int key = array[right - 1];int begin = left;int end = right - 1;while (begin<end){while (begin<end&&array[begin] <= key)begin++;if (begin<end){//上一個(gè)坑是end,begin是比基準(zhǔn)值大的數(shù)array[end] = array[begin];end--;}while (begin<end&&array[end] >= key)end--;if (begin<end){//上次坑是end,填坑的是begin,填完坑后,begin成坑,由新end比基準(zhǔn)值小的數(shù)來填array[begin] = array[end];begin++;}}array[begin] = key;return begin; }
  • 前后指針版本
  • int Partion3(int*array, int left, int right) {int key = array[right - 1];int cur = left;int pre = cur - 1;while (cur<right){if (array[cur] < key && ++pre != cur)Swap(&array[cur], &array[pre]);cur++;}if (++pre != right - 1)Swap(&array[pre], &array[right - 1]);return pre; }

    快排的優(yōu)化

  • 三數(shù)取中法選key
  • 遞歸到小的子區(qū)間時(shí),可以考慮使用插入排序
  • 三數(shù)取中法
    //三數(shù)取中法 int GetMiddleIdx(int*array, int left, int right) {int mid = left + ((right - left) >> 1);//left mid right-1if (array[left] < array[right - 1]){if (array[mid] < array[left])return left;else if (array[mid]>array[right - 1])return right - 1;elsereturn mid;}else{if (array[mid] > array[left])return left;else if (array[mid] < array[right - 1])return right - 1;elsereturn mid;} } int Partion(int*array, int left, int right) {int middle = GetMiddleIdx(array, left, right);if (middle != right - 1)Swap(&array[middle], &array[right - 1]);int key = array[right - 1];int begin = left;int end = right - 1;while (begin<end){//從前往后找比基準(zhǔn)值大的元素,找到就停下來,等于也往前走,因?yàn)檎业氖谴蟮?/span>while (begin < end&&array[begin] <= key)begin++;//end從后往前找比基準(zhǔn)值小的元素,找到就停下來,等于也往前走,找的是小的,不是等于while (begin < end&&array[end] >= key)end--;if (begin < end)Swap(&array[begin], &array[end]);}if (begin != right - 1)Swap(&array[begin], &array[right - 1]);return begin; }
    元素個(gè)數(shù)小用直接插入排序
    void QuickSort(int *array, int left, int right) {if (right - left < 16)//如果快排的元素個(gè)數(shù)沒有達(dá)到16及其以上,就用插入排序InsertSort(array, right - left);else{int div = Partion(array, left, right);QuickSort(array, left, div);QuickSort(array, div + 1, right);} }

    快速排序非遞歸寫法

    #include"stack.h" //快排非遞歸 void QuickSortNor(int*array, int size) {int left = 0;int right = size;Stack s;StackInit(&s);StackPush(&s,right);StackPush(&s,left); //后進(jìn)去的先出來,先出來的是左while (!StackEmpty(&s)){left = StackTop(&s);StackPop(&s);right = StackTop(&s);StackPop(&s);if (left < right){int div = Partion3(array, left, right);//先保存右半部分,先進(jìn)后出來StackPush(&s,right);//右半部分右邊界StackPush(&s, div + 1);//右半部分左邊界//再保存左邊部分,后進(jìn)先出來StackPush(&s, div);//左半部分右邊界StackPush(&s, left);//左半部分左邊界}}StackDestroy(&s); }

    歸并排序

    歸并排序

    基本思想:

    歸并排序(MERGE-SORT)是建立在歸并操作上的一種有效的排序算法,該算法是采用分治法(Divide andConquer)的一個(gè)非常典型的應(yīng)用。將已有序的子序列合并,得到完全有序的序列;即先使每個(gè)子序列有序,再使子序列段間有序。若將兩個(gè)有序表合并成一個(gè)有序表,稱為二路歸并。

    歸并排序的特性總結(jié):

  • 歸并的缺點(diǎn)在于需要O(N)的空間復(fù)雜度,歸并排序的思考更多的是解決在磁盤中的外排序問題。
  • 時(shí)間復(fù)雜度:O(N*logN)
  • 空間復(fù)雜度:O(N)
  • 穩(wěn)定性:穩(wěn)定
  • 代碼實(shí)現(xiàn)

    //歸并到temp臨時(shí)空間里 //兩個(gè)有序序列合并成一個(gè) void MergeData(int*array, int left, int mid, int right, int *temp) {int begin1 = left, end1 = mid;int begin2 = mid, end2 = right;int index = left;while (begin1 < end1 && begin2 < end2)//第一個(gè)和第二個(gè)區(qū)間里的元素沒有處理完{if (array[begin1] < array[begin2])temp[index++] = array[begin1++];elsetemp[index++] = array[begin2++];}//如果第一個(gè)空間里的數(shù)沒有搬移完while (begin1 < end1)temp[index++] = array[begin1++];//第一個(gè)空間搬移完了,第二個(gè)空間里的元素沒有搬移完while (begin2 < end2)temp[index++] = array[begin2++]; } void _MergeSort(int*array, int left, int right,int*temp) {//int*temp=(int*)malloc(sizeof(array[left])*(right-left));if (right - left>1) //區(qū)間里的元素超過一個(gè),再排序{//找中間位置int mid = left + ((right - left) >> 1);_MergeSort(array, left, mid,temp);_MergeSort(array, mid, right,temp);MergeData(array, left, mid, right, temp);memcpy(array + left, temp + left, sizeof(array[left])*(right - left));} } void MergeSort(int *array, int size) {int *temp = (int*)malloc(size*sizeof(array[0]));if (NULL == temp){assert(0);return;}_MergeSort(array, 0, size, temp);free(temp); }

    歸并排序非遞歸

    void MergeSortNor(int *array, int size) {int *temp = (int*)malloc(size*sizeof(array[0]));if (NULL == temp){assert(0);return;}int gap = 1;while (gap < size){for (int i = 0; i < size; i += 2 * gap){int left = i;//左int mid = left + gap;//中int right = mid + gap;//右if (mid >= size)mid = size;if (right >= size)right = size;MergeData(array, left, mid, right, temp);}memcpy(array, temp, (sizeof(array[0])*size));gap *= 2;}free(temp); }

    非比較排序

    思想:計(jì)數(shù)排序又稱為鴿巢原理,是對哈希直接定址法的變形應(yīng)用。


    操作步驟:

  • 統(tǒng)計(jì)相同元素出現(xiàn)次數(shù)
  • 根據(jù)統(tǒng)計(jì)的結(jié)果將序列回收到原來的序列中
  • 計(jì)數(shù)排序的特性總結(jié):

  • 計(jì)數(shù)排序在數(shù)據(jù)范圍集中時(shí),效率很高,但是適用范圍及場景有限
  • 時(shí)間復(fù)雜度:O(MAX(N,范圍))
  • 空間復(fù)雜度:O(范圍)
  • 穩(wěn)定性:穩(wěn)定
  • 代碼實(shí)現(xiàn)

    //場景:數(shù)據(jù)密集集中在某個(gè)范圍中 void CountSort(int*array, int size) {int minVal = array[0];//范圍的左邊界值int maxVal = array[0];//范圍的右邊界值//1--找數(shù)據(jù)的范圍for (int i = 1; i < size; ++i){if (array[i] < minVal)minVal = array[i];if (array[i]>maxVal)maxVal = array[i];}//2--計(jì)算保存計(jì)數(shù)的空間int range = maxVal - minVal + 1;int *temp = (int*)malloc(sizeof(int)*range);if (NULL == temp){assert(0);return;}//3---空間位置里全部置為0memset(temp, 0, sizeof(int)*range);//memeset 按一個(gè)一個(gè)字節(jié)賦值,賦值0可以,賦值其他值不行,例如100,給一個(gè)字節(jié)賦值100//4--統(tǒng)計(jì)每個(gè)數(shù)據(jù)出現(xiàn)的次數(shù)for (int i = 0; i < size; ++i){temp[array[i] - minVal]++;}//5--回收數(shù)據(jù)int index = 0;for (int i = 0; i < range; ++i){while (temp[i]--) //當(dāng)前元素值不為0,說明該下標(biāo)還有個(gè)數(shù) {array[index++] = i + minVal;}}free(temp); }

    計(jì)數(shù)排序參考鏈接

    排序總結(jié)

    總結(jié)

    以上是生活随笔為你收集整理的排序下---(冒泡排序,快速排序,快速排序优化,快速排序非递归,归并排序,计数排序)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。