各种排序算法探讨与实现

来源:互联网 发布:淘宝全球购 买手直播 编辑:程序博客网 时间:2024/05/16 11:19

本文对各个排序算法进行了一点复习整理,并通过一段代码对几种排序算法进行了实现。这包括:冒泡排序,插入排序,选择排序,希尔排序,堆排序,归并排序,快速排序,基数排序,计数排序等。相关简要讨论在程序中有一定说明。

各种算法实现见以下示例代码:

/********************************************************************各种排序算法示例程序---By F8Master*/#include<stdlib.h>#include<iostream>#include<vector>#include<iomanip>using namespace std;template <class Comparable>void bubbleSort(vector<Comparable> &a);template<typename Comparable>void insertSort(vector<Comparable> &a);template<typename Comparable>void selectSort(vector<Comparable> &a);template<typename Comparable>void shellSort(vector<Comparable> &a);template<typename Comparable>void heapSort(vector<Comparable> &a);template<typename Comparable>void mergeSort(vector<Comparable> &a);template<typename Comparable>void quickSort(vector<Comparable> &a);template<typename Comparable>void countSort(vector<Comparable> &a);template<typename Comparable>void radixSort(vector<Comparable> &a);void main(){vector<int> v;while(true){cout<<"Choose sort Algorithm(0 for end) :"<<endl;int num=0;cout<<setw(2)<<++num<<setw(20)<<"BubbleSort"<<endl;cout<<setw(2)<<++num<<setw(20)<<"InsertSort"<<endl;cout<<setw(2)<<++num<<setw(20)<<"SelectSort"<<endl;cout<<setw(2)<<++num<<setw(20)<<"ShellSort"<<endl;cout<<setw(2)<<++num<<setw(20)<<"HeapSort"<<endl;cout<<setw(2)<<++num<<setw(20)<<"MergeSort"<<endl;cout<<setw(2)<<++num<<setw(20)<<"QuickSort"<<endl;cout<<setw(2)<<++num<<setw(20)<<"CountSort"<<endl;cout<<setw(2)<<++num<<setw(20)<<"RadixSort"<<endl;int selnum;cin>>selnum;if(selnum==0)break;v.clear();for(int i=0;i<128;i++)v.push_back(rand()%1000);cout<<"Before sort:"<<endl;for(int i =0;i<v.size();i++)cout<<setw(5)<<v[i];cout<<endl;switch(selnum){case 1: bubbleSort(v);case 2: insertSort(v);case 3:selectSort(v);case 4:shellSort(v);case 5: heapSort(v);case 6: mergeSort(v);case 7: quickSort(v);case 8: countSort(v);case 9: radixSort(v);default:break;}cout<<"\nAfter sort:"<<endl;for(int i =0;i<v.size();i++)cout<<setw(5)<<v[i];cout<<endl;}system("pause");}/*****************************************************************//* 冒泡排序基本思想是:两两比较相邻记录的关键字,如果反序则交换 *时间复杂度最好的情况为O(n),最坏的情况是O(n^2);是一种稳定的排序算法*/template <class Comparable>void bubbleSort(vector<Comparable> &a)//冒泡{for(int i = 1;i<a.size();i++){for(int j = 0;j<a.size()-i;j++){if(a[j]>a[j+1])swap(a[j],a[j+1]);}}}/**************************************************************************//**************************************************************************//*插入排序基本思想: 将一个记录插入到前面已经排好序的序列中, 从而得到一个新的,记录数增1的序列* 时间复杂度也为O(n^2), 若列表基本有序,则插入排序比冒泡、选择更有效率 */template<typename Comparable>void insertSort(vector<Comparable> &a)//插入{insertSort(a,0,a.size()-1);}template<typename Comparable>void insertSort(vector<Comparable> &a, int left, int right)//插入实现,将在快排中用到{for(int i = left+1;i<right-left+1;i++){int tmp = a[i];int j;for(j=i-1;j>=i &&tmp<a[j];j--)a[j+1]=a[j];a[j+1]=tmp;}}/**************************************************************************//**************************************************************************//* 选择排序基本思想:就是通过n-i次比较,从n-i+1个记录中选择关键字最小的记录,并和第i(1<=i<=n)个记录交换。* 时间复杂度也为O(n^2),但选择排序的性能要略优于冒泡排序 */template<typename Comparable>void selectSort(vector<Comparable> &a)//选择{for(int i=0;i<a.size();i++){int pos = i;int min = a[i];for(int j = i+1;j<a.size();j++){if(a[j]<min){min = a[j];pos = j;}}swap(a[i],a[pos]);}}/**************************************************************************//*希尔排序基本思想:间隔一定增量的元素进行排序,一次见效增量值直到1*效率估计O(nlog2^n)~O(n^1.5),取决于增量值的最初大小。建议使用质数作为增量值,本程序并未如此实现/**************************************************************************/template<typename Comparable>void shellSort(vector<Comparable> &a)//希尔{for(int gap = a.size()/2;gap>0;gap/=2){for(int i=gap;i<a.size();i++){int tmp = a[i];int j=i;for( ; j>=gap&&tmp<a[j-gap];j-=gap)a[j]=a[j-gap];a[j]=tmp;}}}/**************************************************************************//**************************************************************************//*通过构造最大堆,并依次交换最大元素与末尾元素实现排序*时间复杂度为 O(nlogn)*/template<typename Comparable>void heapSort(vector<Comparable> &a)//堆排序{for(int i=a.size()/2;i>=0;i--)//构造最大堆percDown(a,i,a.size());for(int j = a.size()-1;j>0;j--){swap(a[0],a[j]);percDown(a,0,j);}}int leftChild(int i){return i*2+1;}template<typename Comparable>void percDown(vector<Comparable> &a,int i,int n){int child;int tmp;//存较小的值for(tmp = a[i];leftChild(i)<n;i=child){child = leftChild(i);if(child!=n-1 && a[child]<a[child+1])child++;if(tmp<a[child])a[i]=a[child];elsebreak;}a[i]=tmp;}/********************************************************************************//********************************************************************************//*通过递归实现,将已经有序的两个序列合并为一个序列,该方法对空间的要求较高* 时间复杂度为O(nlogn),空间复杂度为O(n+logn)*/template<typename Comparable>void mergeSort(vector<Comparable> &a)//归并排序{vector<Comparable> tmpArray(a.size());//临时存储数组mergeSort(a,tmpArray,0,a.size()-1);}template<typename Comparable>void mergeSort(vector<Comparable> &a, vector<Comparable> &tmpArray, int left, int right)//归并排序递归调用部分{if(left<right){int center = (left + right)/2;mergeSort(a,tmpArray,left,center);mergeSort(a,tmpArray,center+1,right);merge(a,tmpArray,left,center+1,right);}}template<typename Comparable>void merge(vector<Comparable> &a, vector<Comparable> &tmpArray, int leftPos, int rightPos, int rightEnd)//归并排序合并部分{int leftEnd = rightPos-1;int tmpPos = leftPos;int numElements= rightEnd - leftPos +1;while(leftPos<=leftEnd && rightPos<=rightEnd){if(a[leftPos]<a[rightPos])tmpArray[tmpPos++]=a[leftPos++];elsetmpArray[tmpPos++]=a[rightPos++];}while(leftPos<=leftEnd)tmpArray[tmpPos++]=a[leftPos++];while(rightPos<=rightEnd)tmpArray[tmpPos++]=a[rightPos++];for(int i=0;i<numElements;i++,rightEnd--)a[rightEnd]=tmpArray[rightEnd];}/********************************************************************************//********************************************************************************//*快速排序基本思想:通过递归实现,选定一个枢纽元素,对待排序序列进行分割,分割之后的序列一个部分小于枢纽元素,一个部分大于枢纽元素,再对这两个分割好的子序列进行上述的过程。 平均时间复杂度O(nlogn)*/template<typename Comparable>void quickSort(vector<Comparable> &a)//快速排序{quickSort(a,0,a.size()-1);}template<typename Comparable>void quickSort(vector<Comparable> &a,int left, int right)//快速排序实现{if(left+10<=right){Comparable pivot = median3(a,left,right);//确定枢纽元int i =left,j=right-1;for( ; ; ){while(a[++i]<pivot){}//找到左边首个不小于pivot的值while(a[--j]>pivot){}//找到右边首个不大于pivot的值if(i<j)swap(a[i],a[j]);elsebreak;}swap(a[i],a[right-1]);quickSort(a,left,i-1);quickSort(a,i+1,right);}elseinsertSort(a,left,right);}template<typename Comparable>const Comparable &median3(vector<Comparable> &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]);//交换后大小顺序为左<中<右swap(a[center],a[right-1]);//枢纽元放在a[right-1]位置return a[right-1];}/********************************************************************************//********************************************************************************//*计数排序基本思想:通过一个额外的count数据记录出每个元素的个数,并计算出应该出现的位置,从而实现排序*该方法不基于比较*/template<typename Comparable>void countSort(vector<Comparable> &a)//计数排序{Comparable min,max;findMinMax(a,a.size(),&min,&max);int numElements = max-min+1; //跨度范围vector<Comparable> count(numElements,int(0));for(int i = 0;i<a.size();i++)//计数{count[a[i]-min]++;}for(int i=0,j=0;i<numElements;i++)//重写原数组{while(count[i]>0){a[j++]=i+min;--count[i];}}}template<typename Comparable>void findMinMax(vector<Comparable> &a,int size,Comparable *min,Comparable *max){if(size==0)return;else if(size==1){*min = *max = a[0];return;}else{*min = a[0]<a[1]?a[0]:a[1];*max = a[0]>a[1]?a[0]:a[1];Comparable tmpMin;Comparable tmpMax;int i,j;for(i = 2,j = 3 ; i<size&&j<size ;i+=2,j+=2){tmpMin = a[i]<a[j]?a[i]:a[j];tmpMax = a[i]>a[j]?a[i]:a[j];if(tmpMin<*min)*min = tmpMin;if(tmpMax>*max)*max = tmpMax;}if(size%2!=0){if(a[size -1] > *max)*max = a[size - 1];else if(a[size -1] < *min)*min = a[size -1];}}}/********************************************************************************//********************************************************************************//*基数排序基本思想:对于int型而言,可以解释为一次一句百位、十位、个位进行分组,组内递归调用进行排序*/template<typename Comparable>void radixSort(vector<Comparable> &a)//基数排序{radixSort(a,0,a.size()-1,3);}template<typename Comparable>void radixSort(vector<Comparable> &a,int left,int right,int d){int i,j,radix=10,p1,p2;vector<Comparable> count(radix,int(0));//计数数组vector<Comparable> auxArray(right-left+1);//辅助数组if(d<=0)//递归截止条件return;for(i=left;i<=right;i++)count[getDigit(a[i],d)]++;for(j=1;j<radix;j++)count[j]+=count[j-1];for(i=left;i<=right;i++){j=getDigit(a[i],d);auxArray[count[j]-1]=a[i];count[j]--;}for(i=left,j=0;i<=right;i++,j++)//辅助数组元素写入原数组{a[i]=auxArray[j];}for(j=0;j<radix;j++){p1=count[j]+left;if(j==radix-1)p2=right;elsep2=count[j+1]-1+left;if(p1<p2)radixSort(a,p1,p2,d-1);}}int getDigit(int a,int d)//返回指定位的值,个位为d=1,以此类推{int tmp=1;for(int i=0;i<d-1;i++)tmp*=10;return (a / tmp)%10;}


0 0