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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

排序大全

發布時間:2024/4/11 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 排序大全 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、排序的分類



插入排序算法復雜度為O(n2)因而,插入排序不適合對于數據量比較大的排序應用。

插入排序的空間復雜度為O(1)。

穩定性:穩定。

/void Insertsort(int arr[],size_t size)
// {
// for(size_t j=1;j<size;j++)
// {
// int i=j;
// while(i>0&&(arr[i]<arr[i-1]))
// {
// int key=arr[i];
// arr[i]=arr[i-1];
// arr[i-1]=key;
// i--;
// }
// }

希爾排序

基本思想:先將整個待排元素序列分割成若干個子序列(由相隔某個“增量”的元素組成的)分別進行直接插入排序,然后依次縮減增量再進行排序,待整個序列中的元素基本有序(增量足夠小)時,再對全體元素進行一次直接插入排序。


圖解(假設為升序):

O(N)<希爾排序的時間復雜度<O(N^2),希爾排序,當N大時,平均的時間復雜度,大約在N^1.25--1.6N^1.25之間。

希爾排序的空間復雜度為O(1)

void ShellSort(T* a,size_t n)//希爾排序 ?

{ ?

? ? assert(a); ?

? ? int gap = n;//gap為所給增量 ?

? ? while(gap > 1) ?

? ? { ?

? ? ? ? //實驗證明,gap=gap/3是比較優的,+1則是為了最后一次對全體數據進行插入排序 ?

? ? ? ? gap = gap/3 + 1; ?

? ? ? ? for (size_t i = gap; i < n; ++i) ?

? ? ? ? { ?

? ? ? ? ? ? int end = i - gap; ?

? ? ? ? ? ? T tmp = a[i]; ?

??

? ? ? ? ? ? while(end >= 0) ?

? ? ? ? ? ? { ?

? ? ? ? ? ? ? ? if (Compare()(tmp,a[end])) ?

? ? ? ? ? ? ? ? { ?

? ? ? ? ? ? ? ? ? ? a[end+gap] = a[end]; ?

? ? ? ? ? ? ? ? ? ? end -= gap; ?

? ? ? ? ? ? ? ? } ?

? ? ? ? ? ? ? ? else ?

? ? ? ? ? ? ? ? { ?

? ? ? ? ? ? ? ? ? ? break; ?

? ? ? ? ? ? ? ? } ?

? ? ? ? ? ? } ?

? ? ? ? ? ? a[end+gap] = tmp; ?

? ? ? ? } ?

? ? } ?

選擇排序


選擇排序的比較次數O(n^2),比較次數與關鍵字的初始狀態無關,總的比較次數:

N=(n-1)+(n-2)+...+1=n*(n-1)/2。?

交換次數O(n),最好情況是,已經有序,交換0次;最壞情況是,逆序,交換n-1次。

故此,選擇排序的時間復雜度為O(N^2)

選擇排序的空間復雜度為O(1)

  • //C++風格的選擇排序??
  • void?SelectSort2(int*?a,size_t?n)??
  • {??
  • ????assert(a);??
  • ????int?minIndex?=?0;??
  • ????for?(size_t?i?=?0;?i?<?n?-?1;?++i)??
  • ????{??
  • ????????minIndex?=?i;??????//未排序區間最小數據的位置下標??
  • ????????size_t?pos?=?i?+?1;//未排序區間的第一個數據下標??
  • ??
  • ????????while(pos?<?n)//選出未排序區間最小的數據??
  • ????????{??
  • ????????????if?(a[pos]?<?a[minIndex])??
  • ????????????{??
  • ????????????????minIndex?=?pos;??
  • ????????????}??
  • ????????????++pos;??
  • ????????}??
  • ????????swap(a[i],a[minIndex]);//將所選數據放到正確位置??
  • ????}??
  • } ?
  • //選擇排序的優化:每次既選出最大的數,也選出最小的數??
  • void?SelectSort3(int*?a,size_t?n)??
  • {??
  • ????assert(a);??
  • ????int?left?=?0;//未排序區間的左下標??
  • ????int?right?=?n?-?1;//未排序區間的右下標??
  • ??
  • ????while?(left?<?right)??
  • ????{??
  • ????????int?minIndex?=?left;//未排序區間最小數據的位置下標??
  • ????????int?maxIndex?=?right;//未排序區間最大數據的位置下標??
  • ??
  • ????????//選出最大和最小數據的下標??
  • ????????for?(int?i?=?left;?i?<=?right;?++i)??
  • ????????{??
  • ????????????if?(a[i]?<?a[minIndex])??
  • ????????????{??
  • ????????????????minIndex?=?i;??
  • ????????????}??
  • ????????????if?(a[i]?>?a[maxIndex])??
  • ????????????{??
  • ????????????????maxIndex?=?i;??
  • ????????????}??
  • ????????}??
  • ????????//修正:最大值在最小位置或最小值在最大位置??
  • ????????swap(a[maxIndex],a[right]);//將最大數據放到區間最右側??
  • ????????if?(minIndex?==?right)??
  • ????????{??
  • ????????????minIndex?=?maxIndex;??
  • ????????}??
  • ????????swap(a[minIndex],a[left]);//將最小數據放在區間最左側??
  • ??
  • ????????left++;//縮小區間范圍??
  • ????????right--;//縮小區間范圍??
  • ? ? } ?
  • } ??
  • 堆排序的基本思想

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


  • 堆排序的時間復雜度為O(N*lgN)

    堆排序的空間復雜度為O(1)


    • //void ?Headadjust(int* array,int size,int parent)
      //{
      // int child=parent*2+1;
      // while(child<size)
      // {
      //
      // if((child+1)<size&&array[child]<array[child+1])
      // ? ? ? ? ?{
      // ? ? ? ?child=child+1;
      // ? ? ? }
      //
      //
      // if (array[child]>array[parent])
      // {
      // std::swap(array[child],array[parent]);
      // parent=child;
      // child=parent*2+1;
      // }
      // else?
      // return ;
      // }
      //
      //}
      //
      //int ?head(int* array,int size)
      //{
      // for(int root=((size-2)/2);root>=0;root--)
      // {
      // Headadjust(array, size,root);
      // }
      //
      // int end=size-1;
      // while(end>0)
      // {
      // std::swap(array[0],array[end]);
      // Headadjust(array, end,0);
      // --end;
      // }
      // return 0;
      //}

      快速排序

    • 說到底,快速排序就是冒泡排序的一種改進,冒泡排序是通過每一趟冒泡將最大值(最小值)放到恰當位置,而快速排序則是每趟排序從待排序區間選一個基準值(也稱作樞紐值),將比它小的數據全放在其左邊,將比它大的值放在其右邊然后遞歸其左右子區間對其排序,一層層遞歸下去,某區直到間只剩一個數據時,停止遞歸,此子區間已經算是有序,繼而向其上層區間返回,一層層向上返回,當首次樞紐值的左右區間均已有序時,整個排序就算完成。



      //k快速排序




      //Vesion1
      //int ?MID(int* array,int left,int right)
      //{
      // int begin=left;
      // int end=right-1;
      // int key=array[end];
      // while(begin<end)
      // {
      // while(begin<end&&array[begin]<=key)
      // begin++;
      //
      // while(begin<end&&array[end]>=key)
      // end--;
      //
      // if(begin<end)
      // {
      // std::swap(array[begin],array[end]);
      // }
      //
      // /*if(begin!=(right-1))
      // {
      // std::swap(array[begin],array[right-1]);
      // }*/
      // }
      // return end;
      //}
      //void Quicksort(int array[],int left,int right)
      //{
      // if(left<right)
      // {
      // int b=left;
      int e=right-1;
      int key=array[e];
      while(b<e)
      {
      while(b<e&&array[b]<=key)
      b++;
      if(b<e)
      array[e--]=array[b];

      while(b<e&&array[e]>=key)
      e--;
      if(b<e)
      array[b++]=array[e];

      }
      array[b]=key;
      Quicksort(array,left,b);
      Quicksort(array,b+1,right);
      }
      }
      //int GetmidIndex(int array[],int left,int right)
      //{
      //
      // int mid=(left+right)/2;
      // if(array[left]<array[right])
      // {
      // if(array[left]>array[mid])
      // return left;
      // else if(array[right]<array[mid])
      // return right;
      // else
      // return mid;
      // }
      // else
      // {
      // if(array[right]>array[mid])
      // return right;
      // else if(array[left]<array[mid])
      // return left;
      // else
      // return mid;
      // }
      //}
      //int ?Quicksort(int array[],int left,int right)
      //{
      // ?
      // ? ?int mid = GetmidIndex(array, left, right);
      // ? ?if (mid != right)
      // ? ?{
      // ? ? ? ? ? ?swap(array[mid], array[right]);//將中間值交換到此范圍最右邊,提高效率
      // ? ?}
      // ? ?int key = array[right];//一般將最
      //
      // int begin=left;
      // int end=right;
      // ? ?key=array[end];
      // while(begin<end)
      // {
      //
      // ? ?while(begin<end&&array[begin]<=key)
      // begin++;
      //
      // while(begin<end&&array[end]>=key)
      // end--;
      //
      // if(begin<end)
      // std::swap(array[begin],array[end]); ? ?
      // }
      // if (array[right] <array[begin])
      // ? ?{
      // ? ? ? ?swap(array[begin], array[right]);
      // ? ? ? ?return begin;
      // ? ?}
      // ? ?else
      // ? ? ? ?return right;
      //
      //}
      //void QuickSort1(int *array, int left, int right)//遞歸
      //?
      //{
      // ? ?
      // ? ? ? ?if (left < right)
      // ? ? ? ?{
      // ? ? ? ? ? ?int boundary = Quicksort(array, left, right);//關鍵字所在位置的下標
      // ? ? ? ? ? ?QuickSort1(array, left, boundary-1);
      // ? ? ? ? ? ?QuickSort1(array, boundary + 1, right);
      // ? ? ? ?}
      // }
      //
      //void sort(int* array,int left,int right)
      //{
      // stack<int> s;
      // if(left<right)
      // {
      // int mid=Quicksort(array,left, right);
      // if(left<mid-1)
      // {
      // s.push(left);
      // ? ?s.push(mid-1);
      // }
      // if(mid+1<right)
      // {
      // s.push(mid+1);
      // s.push(right);
      // }
      // while(!s.empty())
      // {
      // int end=s.top();
      // s.pop();
      // int begin=s.top();
      // s.pop();
      // mid=Quicksort(array,begin, end);
      // if(begin<mid-1)
      // {
      // s.push(begin);
      // s.push(mid-1);
      // }
      // if(mid+1<end)
      // {
      // s.push(mid+1);
      // s.push(end);
      // }
      //
      // }
      // }
      //}


      一、歸并排序

      1、基本思想

      ? ?歸并排序(Merge sort,臺灣譯作:合并排序)是建立在歸并操作上的一種有效的排序算法。該算法是采用分治法(Divide and Conquer)的一個非常典型的應用。

      算法//
      ?void Merge(int* array,int left,int right,int* temp)
      ?{
      int mid=(left+right)/2;
      int b1=left;
      ? ? ?int end1=mid;
      int b2=mid+1;
      int end2=right;
      int index=left;
      while(b1<=end1&&b2<=end2)
      {
      if(array[b1]<=array[b2])
      {
      temp[index++]=array[b1++];
      }
      else
      {
      temp[index++]=array[b2++];
      }
      }
      while(b1<=end1)
      {
      temp[index++]=array[b1++];
      }
      while(b2<=end2)
      {
      temp[index++]=array[b2++];
      }
      ?}

      //void ?_sort(int* array,int left,int right,int* temp)
      // {
      // if(left<right)
      // {
      // int mid=(left+right)/2;
      // _sort(array,left,mid,temp);
      // _sort(array,mid+1,right,temp);
      // Merge(array,left,right,temp);
      // memcpy(array+left,temp+left,(right-left+1)*sizeof(array[0]));
      // }
      //
      // }

      原理

      1>按照類似快速排序的方法遞歸地將待排序序列依次劃分為兩個區間,區間只剩一個數停止劃分;
      2>如果一個區間只剩一個數,我們可將其看做有序區間,然后對左右兩個小區間進行歸并,歸并后仍要保持區間的有序性;
      3>同2>提到的方法我們每次將兩個有序的子區間歸并為一個大的有序區間,并返回給上一層遞歸;

      4>直到所有劃分的區間歸并為一個有序序列,歸并排序就算完成。



      一、計數排序

      1、基本思想

      ???給定一組要排序的序列,找出這組序列中的最大值,然后開辟一個最大值加1大小的數組,將這個數組里面的元素全部置零,然后用這個數組統計出要排序的序列中各個元素出現的次數。等到統計完成的時候,排序就已經完成了。
      圖解(假設升序)




      2、算法執行步驟:

      1>找出待排序序列里的最大值max;

      2>開辟一個大小為max+1的臨時數組tmp ,將數組元素的所有初值賦為0;

      3>遍歷待排序序列,將序列中出現值作為下標,對tmp 數組的對應位置數據進行++;

      4>上述操作完成后,tmp中統計了每個數據在待排序列中出現的次數;

      3>最后,將tmp數組里值不為0的所有下標拷進原序列(注意同一個下標可能有多個重復值,都要進行拷貝,不能遺漏),排序就算完成。


      3、計數排序的優化

      ? ? ? 從上面的例子中可以看出,3是待排序序列的最小值,在tmp數組中3 之前的位置并沒有什么卵用,那么基于節省空間的角度進行考慮,我們可以開辟更小的臨時數組統計次數,同樣能完成排序。

      ? ? 比如要對1000,999,1008這三數進行排序,按照普通的方法前998個空間都被浪費掉了,所以這時候我們對它進行優化。找出要排序的這組元素中的最大值和最小值,這樣就確定了這組元素的范圍,然后開辟這個范圍加1大小的數組,然后再將要排序的元素映射到這個新開辟的數組中就可以了。

      結論:計數排序適用于數據比較集中的序列排序


      4、時間復雜度&&空間復雜度

      ? ? 計數排序是一種非比較的排序方法,它的時間復雜度是O(N+K)空間復雜度是0(K),其中K是要排序的數組的范圍。可以看出計數排序是一種以空間呢換取時間的方法。如果當K>N*logN的時候,計數排序就不是好的選擇了,因為基于比較排序的算法的下限是O(N*logN)。?


      5、代碼實現

      [cpp]?view plain?copy ?
    • #pragma?once??
    • #include?<iostream>??
    • #include?<assert.h>??
    • using?namespace?std;??
    • ??
    • void?PrintArray(int*?a,size_t?n)??
    • {??
    • ????for?(size_t?i?=?0;?i?<?n;?++i)??
    • ????{??
    • ????????cout<<a[i]<<"?";??
    • ????}??
    • ????cout<<endl;??
    • }??
    • ??
    • ??
    • void?CountSort(int*?a,size_t?n)??
    • {??
    • ????//查找待排序序列的最大值??
    • ????int?max?=?a[0];??
    • ????for?(size_t?i?=?0;?i?<?n-1;?++i)??
    • ????{??
    • ????????if?(max?<?a[i+1])??
    • ????????{??
    • ????????????max?=?a[i+1];??
    • ????????}??
    • ????}??
    • ??
    • ????//開辟臨時數組用來統計數據出現次數??
    • ????int*?tmp?=?new?int[max+1];??
    • ????//對臨時數組初值賦為0??
    • ????memset(tmp,0,sizeof(int)*(max+1));??
    • ????//統計數據出現次數??
    • ????for?(size_t?i?=?0;?i?<?n;?++i)??
    • ????{??
    • ????????tmp[a[i]]++;??
    • ????}??
    • ??
    • ????//將數據考回原數組??
    • ????int?index?=?0;??
    • ????for?(int?i?=?0;?i?<=?max;?++i)??
    • ????{??
    • ????????while(tmp[i]--)??
    • ????????{??
    • ????????????a[index]?=?i;??
    • ????????????++index;??
    • ????????}??
    • ????}??
    • ????delete?[]tmp;??
    • }??
    • ??
    • //計數排序的優化??
    • void?CountSort1(int*?a,size_t?n)??
    • {??
    • ????//找到待排序序列的最大值和最小值??
    • ????int?max?=?a[0];??
    • ????int?min?=?a[0];??
    • ????for?(size_t?i?=?0;?i?<?n-1;?++i)??
    • ????{??
    • ????????if?(max?<?a[i+1])??
    • ????????{??
    • ????????????max?=?a[i+1];??
    • ????????}??
    • ????????if?(min?>?a[i+1])??
    • ????????{??
    • ????????????min?=?a[i+1];??
    • ????????}??
    • ????}??
    • ??
    • ????//開辟適當空間的數組??
    • ????int?range?=?max?-?min?+?1;??
    • ????int*?tmp?=?new?int[range];??
    • ????memset(tmp,0,sizeof(int)*(range));??
    • ????for?(size_t?i?=?0;?i?<?n;?++i)??
    • ????{??
    • ????????tmp[a[i]-min]++;??
    • ????}??
    • ??
    • ????//將數據考回原數組??
    • ????int?index?=?0;??
    • ????for?(int?i?=?0;?i?<?range;?++i)??
    • ????{??
    • ????????while(tmp[i]--)??
    • ????????{??
    • ????????????a[index]?=?i+min;??
    • ????????????++index;??
    • ????????}??
    • ????}??
    • ????delete?[]tmp;??
    • }??
    • ??
    • void?TestCountSort()??
    • {??
    • ????int?a[]?=?{2,5,4,9,3,6,8,7,1,0};??
    • ????int?a1[]?=?{73,20,93,43,55,14,28,65,39,81};??
    • ????size_t?sz?=?sizeof(a)/sizeof(a[0]);??
    • ????size_t?sz1?=?sizeof(a1)/sizeof(a1[0]);??
    • ??
    • ????CountSort(a,sz);??
    • ????CountSort1(a1,sz1);??
    • ????PrintArray(a,sz);??
    • ????PrintArray(a1,sz1);??
    • }??

    • 運行結果:



      二、基數排序

      1、基數排序的分類
      LSD-- Least Significant Digit first(從低位向高位排)
      MSD-- Most Significant Digit first(從高位向低位排)

      由于原理差不多,此文只針對LSD進行分析。


      2、基本思想

      ? ? 基數排序又稱"桶子法",它從低位開始將待排序的數按照這一位的值放到相應的編號為0到9的桶中。等到低位排完之后得到一個序列,再將這個序列按照次低位的大小進入相應的桶中。以此類推,直到將所有的位都排完之后,這組數就已經有序了。


      圖解(假設升序)



      3、算法執行步驟

      1》統計待排序序列中最大的數是幾位數;

      2》開辟一個與原數組大小相同的臨時數組tmp;

      3》用一個count數組統計原數組中某一位(從個位向高位統計)相同的數據出現的次數;

      4》用一個start數組計算原數組中某一位(從個位向高位計算)相同的數據出現的位置;

      5》將桶中數據從小到大(由頂至底)用tmp數組收集起來;

      6》循環3》4》5》直到所有位都被統計并計算過,然后用tmp收集起來;

      7》將tmp數組的數據拷回原數組,排序完成。


      圖解:



      4、時間復雜度&&空間復雜度

      ? ? 基數排序是一種非比較排序,它的時間復雜度是O(N*digit)其中digit是這組待排序中的最大的數的數量級。基數排序的空間復雜度就是在分配元素時,使用的桶空間,所以基數排序的空間復雜度是O(N)。它是一種穩定的排序方法。


      5、代碼實現

      [cpp]?view plain?copy ?
    • #pragma?once??
    • #include?<iostream>??
    • #include?<assert.h>??
    • using?namespace?std;??
    • ??
    • int?GetMaxDigit(int*?a,size_t?n)//得到數組最大值的位數??
    • {??
    • ????int?digit?=?1;??
    • ????int?base?=?10;??
    • ??
    • ????for?(size_t?i?=?0;?i?<?n;?++i)??
    • ????{??
    • ????????//每次與幾位數的最小數據(10、100、1000……)進行比較,??
    • ????????//優點是相同位數的數據只統計一次??
    • ????????while(a[i]?>=?base)??
    • ????????{??
    • ????????????++digit;??
    • ????????????base?*=?10;??
    • ????????}??
    • ????}??
    • ??????
    • ????return?digit;??
    • }??
    • ??
    • void?LSDSort(int*?a,size_t?n)??
    • {??
    • ????assert(a);??
    • ????int?base?=?1;??
    • ????int?digit?=?GetMaxDigit(a,n);//統計位數??
    • ????int*?tmp?=?new?int[n];//開辟臨時數組??
    • ??
    • ????while(digit--)??
    • ????{??
    • ????????int?count[10]?=?{0};??
    • ????????//統計某位相同的數據出現次數??
    • ????????for?(size_t?i?=?0;?i?<?n;?++i)??
    • ????????{??
    • ????????????int?index?=?a[i]/base?%10;??
    • ????????????count[index]++;??
    • ????????}??
    • ??
    • ????????int?start[10]?=?{0};??
    • ????????//統計個位相同的數在數組a中出現的位置??
    • ????????for?(size_t?i?=?1;?i?<?n;?++i)??
    • ????????{??
    • ????????????start[i]?=?count[i-1]?+?start[i-1];??
    • ????????}??
    • ??
    • ????????memset(tmp,0,sizeof(int)*n);//為tmp數組初始化??
    • ????????//從桶中收集數據(從小到大)??
    • ????????for?(size_t?i?=?0;?i?<?n;?++i)??
    • ????????{??
    • ????????????int?index?=?a[i]/base?%10;??
    • ????????????tmp[start[index]++]?=?a[i];??
    • ????????}??
    • ??
    • ????????//將數據拷回原數組??
    • ????????memcpy(a,tmp,sizeof(int)*n);??
    • ????????base?*=?10;??
    • ????}??
    • ????delete?[]tmp;??
    • }??
    • ??
    • void?PrintArray(int*?a,size_t?n)??
    • {??
    • ????for?(size_t?i?=?0;?i?<?n;?++i)??
    • ????{??
    • ????????cout<<a[i]<<"?";??
    • ????}??
    • ????cout<<endl;??
    • }??
    • void?TestLDSort()??
    • {??
    • ????int?a[]?=?{73,20,93,43,55,14,28,65,39,81};??
    • ????size_t?sz?=?sizeof(a)/sizeof(a[0]);??
    • ??
    • ????LSDSort(a,sz);??
    • ????PrintArray(a,sz);??
    • }??

    • 運行結果:




      1?0






    總結

    以上是生活随笔為你收集整理的排序大全的全部內容,希望文章能夠幫你解決所遇到的問題。

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