常見排序演算法C++實現(冒泡,直接插入,希爾,堆,歸併,簡單選擇,快排)
阿新 • • 發佈:2019-01-07
常見的排序演算法:氣泡排序、直接插入、希爾排序,堆排序,簡單選擇排序,快速排序。這些最基本的演算法都是應該熟練掌握的,下面是C++實現的程式碼,方便大家學習參考:
#include<iostream> using namespace std; void swap(int &i,int &j)//實現i,j交換的函式 { i=i^j; j=i^j; i=i^j; } void Display(const int *arr,int length) { if(arr==NULL || length<=0) { return ; } int i; for(i=0;i<length;i++) { cout<<arr[i]<<" "; } cout<<endl; } /*****************直接插入排序***********************/ void InsertSort(int *arr,int length)//直接插入排序 { if(arr==NULL || length<=1)//如果大小為1也無需再排序 { return ; } int i; for(i=1;i<length;i++)//從第二個值開始插 { int temp=arr[i];//先儲存待插入的值,因為移動會被覆蓋 int j; for(j=i-1;j>=0 && arr[j]>temp;j--)//一邊比較一邊移動 { arr[j+1]=arr[j]; } if(i!=j+1)//如果前面存在比a[i]小的數 { arr[j+1]=temp;//在當前值的下一個位置插入 } } } /*************************氣泡排序**************************/ void BubbleSort(int *arr,int length)//氣泡排序 { if(arr==NULL || length<=1) { return ; } int i,j; bool change=true;//對氣泡排序的優化 for(i=0;i<length-1 && change;i++)//i表示最多冒泡的次數 { change=false; for(j=0;j<length-1-i;j++) { if(arr[j]>arr[j+1])//通過異或實現高效資料交換 { swap(arr[j],arr[j+1]); change=true; } } } } /******************簡單選擇排序************************/ void SelectSort(int *arr,int length)//簡單選擇排序 { if(arr==NULL || length<=1) { return ; } int i,min; for(i=0;i<length-1;i++) { min=i;//每次假設第一個值為最小值 int j; for(j=i+1;j<length;j++) { if(arr[min]>arr[j]) { min=j;//記下當前最小值的位置 } } if(min!=i) { swap(arr[i],arr[min]); } } } ////////////////快速排序//////////////////////////////////// int Partition(int *arr,int left,int right)//將陣列一分為二,並尋找支點的位置 { int x=arr[left];//每次將第一個值作為支點的值 while(left<right) { while(arr[right]>=x && left<right)//從右向左掃描,注意是小於等於 { right--; } if(left<right) { swap(arr[left],arr[right]); } while(arr[left]<=x && left<right)//從左向右掃描,注意是小於等於 { left++; } if(left<right) { swap(arr[left],arr[right]); } } return left;//此時left等於right } void QSort(int *arr,int left,int right)//快速排序,left=0,right=length-1 { if(left<right) { int mid=Partition(arr,left,right); QSort(arr,left,mid-1); QSort(arr,mid+1,right); } } void QuickSort(int *arr,int length) { if(arr==NULL || length<=1) { return ; } QSort(arr,0,length-1); } //////////////////////////歸併排序///////////////////////////////////// void Merge(int *arr,int first,int mid,int last,int *temp)//將arr[first...mid]與arr[mid+1...last]歸併 { int i,j; int k=0; for(i=first,j=mid+1;i<=mid && j<=last;) { if(arr[i]<=arr[j])//所以是穩定排序 { temp[k++]=arr[i++]; } else { temp[k++]=arr[j++]; } } while(i<=mid) { temp[k++]=arr[i++]; } while(j<=last) { temp[k++]=arr[j++]; } for(i=0;i<k;i++)//將合併後的陣列temp[]還原到arr[] { arr[first+i]=temp[i];//是arr[low+i]不是arr[i] } } void Msort(int *arr,int first,int last,int *temp) { if(first==last) { temp[first]=arr[first]; } else if(first<last) { int mid=(first+last)/2; Msort(arr,first,mid,temp); Msort(arr,mid+1,last,temp); Merge(arr,first,mid,last,temp); } } void MergeSort(int *arr,int length)//歸併排序 { if(arr==NULL || length<=1) { return ; } int *temp=new int [length]; Msort(arr,0,length-1,temp); delete []temp; } //////////////////希爾排序//////////////////////// void ShellInsert(int *arr,int length,int d) { int i,j; for(i=d;i<length;i++) { int temp=arr[i]; for(j=i-d;j>=0 && arr[j]>temp;j-=d) { arr[j+d]=arr[j]; } if(j!=i-d) { arr[j+d]=temp; } } } void ShellSort(int *arr,int length)//希爾排序 { if(arr==NULL || length<=1) { return ; } int d=length/2; while(d>=1) { ShellInsert(arr,length,d); d/=2; } } ////////////////堆排序(大頂堆)////////////////////////// ///////堆是一個完全二叉樹,若結點索引從0開始,則i結點的左孩子為2*i+1,右為2*i+2 void HeapAdjustDown(int *arr,int length,int i)//對第i個值做向下調整,i=0,...,length-1 { if(arr==NULL || length<=0 || i<0) { return ; } int temp=arr[i]; int j;//i相當於前驅,j相當於後繼 for(j=2*i+1;j<length;)//即j<=length-1 { if(j+1<length && arr[j]<arr[j+1])//如果存在右孩子,且右孩子值待遇 { j++;//與右孩子交換 } if(arr[j]<=temp)//如果左右孩子中的較大值小於該結點值,則說明無需向下調整了 { break; } else//如果左右孩子中的較大值大於該結點值,則想到直接插入排序 { arr[i]=arr[j];//孩子結點值中較大的上移動 i=j;//i用於追蹤待插入點的位置 j=2*i+1; } } if(arr[i]!=temp)//如果i的值發生了移動 { arr[i]=temp;//將最初第i個節點值放入合適的位置 } } void CreateHeap(int *arr,int length)//建立一個堆 { if(arr==NULL || length<=0) { return ; } int i; for(i=(length-2)/2;i>=0;i--)//最後一個元素的序號為length-1,故該結點的父結點為(length-2)/2 { HeapAdjustDown(arr,length,i);//從倒數第二行開始倒著向下調整 } } void HeapDelete(int *arr,int len)//刪堆頂元素,len表示當前表的長度 { if(arr==NULL || len<=0 || len==1)//len=1,表示當堆中只有一個元素時,無需排序 { return ; } else { swap(arr[0],arr[len-1]); HeapAdjustDown(arr,len-1,0);//刪除後,陣列長度減1了 } } void HeapSort(int *arr,int length)//堆排序 { if(arr==NULL || length<=1) { return ; } CreateHeap(arr,length);//先建立一個堆0 int i; for(i=0;i<=length-1;i++)//刪除length-1次即可,因為最後一個元素就剩自己了 { HeapDelete(arr,length-i); } } int main() { int a[]={12,3,5,1,4,5,4,21,1,3}; Display(a,sizeof(a)/sizeof(int));//顯示排序前的元素 //void (*pSort)(int*,int)=NULL;//定義一個函式指標,方法一 typedef void (*Fun)(int *,int);//Fun為函式指標類 Fun pFunc=NULL;//定義函式指標,方法二,與上面等價 pFunc=InsertSort; // pFunc=BubbleSort; // pFunc=SelectSort; // <span style="font-family: Arial, Helvetica, sans-serif;">pFunc</span><span style="font-family: Arial, Helvetica, sans-serif;">=QuickSort;</span> // <span style="font-family: Arial, Helvetica, sans-serif;">pFunc</span><span style="font-family: Arial, Helvetica, sans-serif;">=ShellSort;</span> // pFunc=HeapSort; if(pSort) { pSort(a,sizeof(a)/sizeof(int));//顯示排序後的元素 } Display(a,sizeof(a)/sizeof(int)); system("pause"); return 0; }