在“排序問題總結”這篇文章中介紹了各種的排序演算法,給出了各種演算法的思想,並沒有給出各種演算法的實現。這篇文章對應上面的各種方法寫出演算法的實現。
(歡迎轉載,但請標明轉載連結,謝謝)
(一)直接插入排序
#include "stdafx.h"#include<iostream>using namespace std;int _tmain(int argc, _TCHAR* argv[]){int count;cout<<"input the number of digits:"<<endl;cin>>count;cout<<"input details of digits:"<<endl;int *point=new int[count+1];for(int i=1;i<=count;i++){cin>>point[i];}for(int i=2;i<=count;i++){if(point[i]<point[i-1]){point[0]=point[i];point[i]=point[i-1];while(point[0]<point[i-2]){point[i-1]=point[i-2];i--;}point[i-1]=point[0];}}cout<<"the ordered digits:\n";for(int i=1;i<=count;i++){cout<<point[i]<<' ';}delete[] point;return 0;}
運行結果如下所示:
(二)希爾排序
在直接插入排序演算法中,每次插入一個數,使有序序列只增加1個節點, 並且對插入下一個數沒有提供任何協助。如果比較相隔較遠距離(稱為增量)的數,使得數移動時能跨過多個元素,則進行一次比較就可能消除多個元素交換。D.L.shell於1959年在以他名字命名的排序演算法中實現了這一思想。演算法先將要排序的一組數按某個增量d分成若干組,每組中記錄的下標相差d.對每組中全部元素進行排序,然後再用一個較小的增量對它進行,在每組中再進行排序。當增量減到1時,整個要排序的數被分成一組,排序完成。
演算法實現如下:
#include "stdafx.h"#include<iostream>using namespace std;int _tmain(int argc, _TCHAR* argv[]){int count;int h,j,k,t;cout<<"input the number of digits:"<<endl;cin>>count;cout<<"input details of digits:"<<endl;int *point=new int[count];for(int i=0;i<count;i++){cin>>point[i];}for(h=count/2;h>0;h=h/2)//控制增量{for(j=h;j<count;j++)//直接插入排序{t=*(point+j);for(k=j-h;(k>=0&&t<*(point+k));k-=h){*(point+k+h)=*(point+k);}*(point+k+h)=t;}}cout<<"the ordered digits:\n";for(int i=0;i<count;i++){cout<<point[i]<<' ';}delete[] point;return 0;}
運行結果如下所示:
(三)簡單選擇排序
簡單選擇排序就是從一組資料中選出最小的那個數與第一個數進行交換,然後除去第一個數再從剩下的數中選出最小的數與第二個數進行交換,依次類推....
演算法實現如下:
#include "stdafx.h"#include<iostream>using namespace std;int _tmain(int argc, _TCHAR* argv[]){int count;cout<<"input the number of digits:"<<endl;cin>>count;cout<<"input details of digits:"<<endl;int *point=new int[count];for(int i=0;i<count;i++){cin>>point[i];}int k,temp;for(int i=0;i<count-1;i++){k=i;for(int j=i+1;j<count;j++){if(point[j]<point[k])k=j;}temp=point[i];point[i]=point[k];point[k]=temp;}cout<<"the ordered digits:\n";for(int i=0;i<count;i++){cout<<point[i]<<' ';}delete[] point;return 0;}
運行結果如下:
(四)冒牌排序
冒泡排序是指對於一組需要排序的數,自上而下對相鄰的兩個數進行比較,如果後面的小於前面的數則交換位置,使得小數往上冒,大數往下沉...
演算法實現如下:
#include "stdafx.h"#include<iostream>using namespace std;int _tmain(int argc, _TCHAR* argv[]){int count;cout<<"input the number of digits:"<<endl;cin>>count;cout<<"input details of digits:"<<endl;int *point=new int[count];for(int i=0;i<count;i++){cin>>point[i];}for(int i=0;i<count-1;i++){for(int j=1;j<count-i;j++){if(point[j]<point[j-1]){int temp=point[j-1];point[j-1]=point[j];point[j]=temp;}}}cout<<"the ordered digits:\n";for(int i=0;i<count;i++){cout<<point[i]<<' ';}delete[] point;return 0;}
運行結果如下:
上述的冒泡排序演算法是基本的演算法,我們可以在排序的過程中加入一個標誌,當在一次迴圈中沒有任何兩個數的位置交換時那麼我們就結束,而不再後面的迴圈中繼續比較。此時相應的改進演算法實現如下:
#include "stdafx.h"#include<iostream>using namespace std;int _tmain(int argc, _TCHAR* argv[]){int count;bool flag=true;cout<<"input the number of digits:"<<endl;cin>>count;cout<<"input details of digits:"<<endl;int *point=new int[count];for(int i=0;i<count;i++){cin>>point[i];}for(int i=0;i<count-1;i++){for(int j=1;j<count-i;j++){if(point[j]<point[j-1]){int temp=point[j-1];point[j-1]=point[j];point[j]=temp;flag=false;}}if(flag)break;}cout<<"the ordered digits:\n";for(int i=0;i<count;i++){cout<<point[i]<<' ';}delete[] point;return 0;}
經過檢驗,所改進的演算法既能夠正確排序,也能夠在一定程度上改進效率。
(五)快速排序
快速排序是對冒泡排序的一種改進。冒泡排序一次掃描只能確保最大的數(或最小的數)在正確的位置上
,剩下待排序的資料長度只會減1,而快速排序法一次掃描之後可以確保以這個數為基點,左邊的數都比它小(大),而右邊的數都比它大(小),用同樣的方式處理兩邊的數。
演算法實現如下:
#include "stdafx.h"#include<iostream>using namespace std;int partition(int *,const int,const int);void quicksort(int *,const int,const int);int _tmain(int argc, _TCHAR* argv[]){int count;cout<<"使用快速排序法排序:"<<endl;cout<<"input the number of digits:"<<endl;cin>>count;cout<<"input details of digits:"<<endl;int *point=new int[count];for(int i=0;i<count;i++){cin>>point[i];}quicksort(point,0,count-1);cout<<"the ordered digits:\n";for(int i=0;i<count;i++){cout<<point[i]<<' ';}delete[] point;return 0;}int partition(int* point,const int left,const int right){int i=left;int j=right;int temp=point[i];while(i<j){while(i<j&&point[j]>=temp)j--;if(i<j){int temp1;temp1=point[i];point[i]=point[j];point[j]=temp1;i++;}while(i<j&&point[i]<=temp)i++;if(i<j){int temp1;temp1=point[i];point[i]=point[j];point[j]=temp1;j--;}}point[i]=temp;return i;}void quicksort(int *point,const int left,const int right){if(left>=right)return;int pos=partition(point,left,right);quicksort(point,left,pos-1);quicksort(point,pos+1,right);}
運行結果如下:
(六)堆排序
堆的定義如下:具有n個元素的序列(h1,h2,...,hn),若且唯若滿足(hi>=h2i,hi>=2i+1)或(hi<=h2i,hi<=2i+1)(i=1,2,...,n/2)時稱之為堆。在這裡只討論滿足前者條件的堆。由堆的定義可以看出,堆頂元素(即第一個元素)必為最大項(大頂堆)。完全二叉樹可以很直觀地表示堆的結構。堆頂為根,其它為左子樹、右子樹。初始時把要排序的數的序列看作是一棵順序儲存的二叉樹,調整它們的儲存序,使之成為一個堆,這時堆的根節點的數最大。然後將根節點與堆的最後一個節點交換。然後對前面(n-1)個數重新調整使之成為堆。依此類推,直到只有兩個節點的堆,並對它們作交換,最後得到有n個節點的有序序列。從演算法描述來看,堆排序需要兩個過程,一是建立堆,二是堆頂與堆的最後一個元素交換位置。
演算法實現如下:
#include "stdafx.h"#include<iostream>using namespace std;void heap_adjust(int *,int,int);void heap_sort(int *,int);int _tmain(int argc, _TCHAR* argv[]){int count;cout<<"使用堆排序:"<<endl;cout<<"input the number of digits:"<<endl;cin>>count;cout<<"input details of digits:"<<endl;int *point=new int[count];for(int i=0;i<count;i++){cin>>point[i];}heap_sort(point,count);cout<<"the ordered digits:\n";for(int i=0;i<count;i++){cout<<point[i]<<' ';}delete[] point;return 0;}void heap_adjust(int *point,int n,int t){int temp=point[t];int i=t;int j=2*i+1;while(j<n){if(j<n-1&&(point[j]<point[j+1]))//判斷是否有右子節點,如果有則比較左右子節點{j++;}if(temp<point[j])//將子節點與父節點進行比較{point[i]=point[j];i=j;j=2*i+1;}elsebreak;}point[i]=temp;}void heap_sort(int *point,int n){int temp;for(int i=n/2;i>=0;i--){heap_adjust(point,n,i);}for(int k=n-1;k>=1;k--){temp=point[0];point[0]=point[k];point[k]=temp;heap_adjust(point,k,0);}}
運行結果如下:
(七)歸併排序
歸併排序是指將一個無序表列分為若干個子序列,再將子序列排序成有序表,最後將這些子序列歸併成一個整體的有序序列。
演算法實現如下:
#include "stdafx.h"#include<iostream>using namespace std;void merge_sort(int *,int ,int);void merge(int *,int,int,int);int _tmain(int argc, _TCHAR* argv[]){int count;cout<<"使用歸併排序:"<<endl;cout<<"input the number of digits:"<<endl;cin>>count;cout<<"input details of digits:"<<endl;int *point=new int[count];for(int i=0;i<count;i++){cin>>point[i];}merge_sort(point,0,count-1);cout<<"the ordered digits:\n";for(int i=0;i<count;i++){cout<<point[i]<<' ';}delete[] point;return 0;}void merge_sort(int *point,int start,int end){if(start<end){int i=(start+end)/2;merge_sort(point,start,i);merge_sort(point,i+1,end);merge(point,start,i,end);}}void merge(int *point,int start,int mid,int end){int len1,len2;len1=mid-start+1;len2=end-mid;int *arr1=new int[len1+1];int *arr2=new int[len2+1];for(int i=0;i<len1;i++){arr1[i]=point[start+i];}for(int i=0;i<len2;i++){arr2[i]=point[mid+i+1];}arr1[len1]=1000;arr2[len2]=1000;for(int k=start,i=0,j=0;k<=end;k++){if(arr1[i]<arr2[j]){point[k]=arr1[i++];}else{point[k]=arr2[j++];}}delete[] arr1;delete[] arr2;}
程式運行結果如下:
(八)基數排序
基數排序法又稱之為“桶子法”,它是將要排序的元素分配至某些桶中藉以達到排序的作用。基數排序法克採用LSD(Least significant digital)或者MSD(Most significant digital),LSD從索引值的最右邊開始,而MSD則從索引值的最左邊開始。
取一個簡單的例子來說,對於下面一組資料
12,15,9,10,14,24,18
(1)按照個位元進行排序:10,12,14,24,15,18,9
(2)按照十位元進行排序:9,10,12,14,15,18,24
演算法實現如下:
// jishupaixu.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include<iostream>#include<assert.h>using namespace std;int pre_process_data(int *, int, int);void sort_for_basic_number(int *, int, int *);void sort_data_by_basic_number(int *, int *, int *, int, int);void radix_sort(int *, int);int _tmain(int argc, _TCHAR* argv[]){int count;cout<<"採用基數排序"<<endl;cout<<"輸入參加排序的資料個數:"<<endl;cin>>count;int *point=new int[count];cout<<"請輸入待排序序列:"<<endl;for(int i=0;i<count;i++){cin>>point[i];}radix_sort(point,count);cout<<"經過排序後的資料序列為:"<<endl;for(int i=0;i<count;i++){cout<<point[i]<<' ';}return 0;}int pre_process_data(int array[], int length, int weight){int index ;int value = 1;for(index = 0; index < weight; index++)value *= 10;for(index = 0; index < length; index ++)array[index] = array[index] % value /(value /10);for(index = 0; index < length; index ++)if(0 != array[index])return 1;return 0;}void sort_for_basic_number(int array[], int length, int swap[]){int index;int basic;int total = 0;for(basic = -9; basic < 10; basic++){for(index = 0; index < length; index++){if(-10 != array[index] && basic == array[index] ){swap[total ++] = array[index];array[index] = -10;}}}memmove(array, swap, sizeof(int) * length);}void sort_data_by_basic_number(int array[], int data[], int swap[], int length, int weight){int index ;int outer;int inner;int value = 1;for(index = 0; index < weight; index++)value *= 10;for(outer = 0; outer < length; outer++){for(inner = 0; inner < length; inner++){if(-10 != array[inner] && data[outer]==(array[inner] % value /(value/10))){swap[outer] = array[inner];array[inner] = -10;break;}}}memmove(array, swap, sizeof(int) * length);return;}void radix_sort(int array[], int length){int* pData;int weight = 1;int count;int* swap;if(NULL == array || 0 == length)return;pData = (int*)malloc(sizeof(int) * length);assert(NULL != pData);memmove(pData, array, length * sizeof(int));swap = (int*)malloc(sizeof(int) * length);assert(NULL != swap);while(1){count = pre_process_data(pData, length, weight);if(!count)break;sort_for_basic_number(pData, length, swap);sort_data_by_basic_number(array, pData, swap, length, weight);memmove(pData, array, length * sizeof(int));weight ++;}free(pData);free(swap);return;}
程式運行結果如下: