一些排序算法
头文件
/************************* 交换排序 **************************/ //冒泡排序 void BubbleSort(vector<int> &v,int begin,int end); //快速排序 void QuickSort(vector<int> & v,int begin,int end); /************************ 插入排序 *************************/ //直接插入排序 void InsertionSort(vector<int> &v,int begin,int end); //折半插入排序 void BinaryInsertSort(vector<int> &v,int begin,int end); //希尔排序 void ShellSort(vector<int> & v,int begin,int end); /************************ 选择排序 *************************/ //直接选择排序 void SelectSort(vector<int> & v,int begin,int end); //锦标赛排序 void ChamptionSort(vector<int> & v,int begin,int end); //堆排序 void HeapSort(vector<int> &v,int begin,int end); /************************ 归并排序 *************************/ //递归的两路归并 void MergeSort(vector<int> & v,int begin,int end); /*********************** 基数排序 ***********************/ void RadixSort(vector<int> & v,int begin,int end);
实现源文件
#include "StdAfx.h" #include "Sorts.h" #include <MATH.H> int getpositionvalue(list<int> & ilist,int pos){ list<int>::iterator it = ilist.begin(); while(pos-- >0) ++it; return *it; } void setpositionvalue(list<int> & ilist,int pos,int value){ list<int>::iterator it = ilist.begin(); while(pos-- >0) ++it; ilist.insert(it,value); } //冒泡排序 void BubbleSort(vector<int> &v,int begin,int end){ int i = 0; int j = 0; int sorted = 0; //后面的已经排好的位数,接下来就不用再比较了 for(i = begin;i < end;i++){ for(j = begin;j < end-sorted;j++){ if(v[j] > v[j+1]){ int temp = v[j+1]; v[j+1] = v[j]; v[j] = temp; } } sorted++; } } //快速排序 int Partition(vector<int> & v,int begin,int end){ int i = begin; int j = end; int key = v[begin]; while(i<j){ while(v[j] >= key && i<j) //从后往前找到第一个比key小的 j--; v[i] = v[j]; while(v[i] < key && i<j) //从前往后找到比key大的 i++; v[j] = v[i]; } v[i] = key; return i; } void QuickSort(vector<int> & v,int begin,int end){ if(begin < end){ int tempindex = Partition(v,begin,end); QuickSort(v,begin,tempindex); QuickSort(v,tempindex+1,end); } } //直接插入排序 void InsertionSort(vector<int> &v,int begin,int end){ list<int> ilist; ilist.push_back(v[begin]); int i = begin+1; list<int>::iterator it = ilist.begin(); for( ;i<=end;i++){ int flag = 0; for(it = ilist.begin();it!=ilist.end();it++){ if(v[i] < *it){ ilist.insert(it,v[i]); flag = 1; // 代表已在前面插入,否则需要在后面push_back break; // 插入之后就得退出了 } } if(flag == 0) ilist.push_back(v[i]); } for( it = ilist.begin();it!=ilist.end();it++,begin++){ v[begin] = *it; } } //折半插入排序 (插入比较时,用二分查找法) void BinaryInsertSort(vector<int> &v,int begin,int end){ list<int> ilist; ilist.push_back(v[begin]); int i = begin+1; list<int>::iterator it = ilist.begin(); for( ;i<=end;i++){ int tempbegin = 0; int tempend = ilist.size()-1; while(tempbegin <= tempend){ int mid = (tempbegin+tempend)/2 ; if(getpositionvalue(ilist,mid) > v[i]){ tempend = mid-1; } else tempbegin = mid+1; } if(tempbegin <= ilist.size()-1){ //说明比v[i]大的元素还在list中,在内部插入 setpositionvalue(ilist,tempbegin,v[i]); } else //否则push_back,在最后面插入 ilist.push_back(v[i]); } for( it = ilist.begin();it!=ilist.end();it++,begin++){ v[begin] = *it; } } //希尔排序 //选取步长分组,对分组的进行直接插入排序,一直到步长为0,因为经过之前的处理已经是大概有序了,在进行直接插入排序很快 //受之前插入代码的影响,有很多对象的构造析构成本消耗,但是思路很清晰!!! void ShellSort(vector<int> & v,int begin,int end){ int d = (end-begin+1)/2; while(d){ // cout<<d<<endl; int tempd = d; int i = 0,j = 0; int tempbegin = begin; while(tempd--){ vector<int> tempivec; for(i = tempbegin ; i <= end ; i+=d){ //以d为步长 tempivec.push_back(v[i]); } InsertionSort(tempivec,0,tempivec.size()-1); //插入排序 for(i = tempbegin,j =0 ; i <= end ; i+=d,j++){ //排序后将排序好的部分返回到原vector,第一步 取值分组的逆操作 // tempivec.push_back(v[i]); v[i] = tempivec[j]; } tempbegin++; } d = d/2; } } //直接选择排序 void SelectSort(vector<int> & v,int begin,int end){ int i = 0; int k = 0; for( ; begin <= end ; begin++){ int min = v[begin]; k = begin; //k记录默认最小位置 for(i = begin+1;i<=end;i++){ if(v[i] < min){ min = v[i]; k = i; // k记录最小值的位置,若后面有最小的,更新k的值 } } if(k != end){ v[k] = v[begin]; v[begin] = min; } } } //锦标赛排序 void MakeChamption(vector<int> &v,int begin,int end); //构造一个类似最大堆,选出冠军 void GetChamption(vector<int> &v,int begin,int end); //将已完成的锦标赛的第一个元素与最后一个元素互换 void ChamptionSort(vector<int> & v,int begin,int end){ // 堆排序是用来改正锦标赛的缺点的 // cout<<"ChampionSort"<<endl; while(end > begin){ GetChamption(v,begin,end); // cout<<v[end]<<endl; end--; } } void GetChamption(vector<int> &v,int begin,int end){ if(begin >= end) return; MakeChamption(v,begin,end); int temp = v[end]; v[end] = v[begin]; v[begin] = temp; } void MakeChamption(vector<int> &v,int begin,int end){ int size = end - begin; if(size < 1 ) return ; //如果有1个元素,就不需要再操作了 int parentindex = (end-begin-1)/2+begin; //index of parent while(true){ // cout<<"parentindex"<<parentindex<<endl; if(parentindex == begin-1) return; int lchildindex = (parentindex - begin) * 2 + 1 + begin; //index of parent's lchild int rchildindex = (parentindex - begin) * 2 + 1 + begin + 1; //index of parent's rchild int maxchildindex = 0; if(rchildindex > end) //maxchildindex两种情况,若左右孩子存在选较大值得,若右孩子不存在,选左孩子为maxchildindex maxchildindex = lchildindex; else maxchildindex = v[lchildindex] > v[rchildindex] ? lchildindex:rchildindex; if(v[maxchildindex] > v[parentindex]){ int temp = v[parentindex]; v[parentindex] = v[maxchildindex]; v[maxchildindex] = temp; } parentindex--; } } //堆排序 //可以参考《STL源码剖析》 heap部分,172~180,将过程再细分为pop,push部分 void HeapifyIndex(vector<int> &v,int begin,int end,int parentindex); //对v[index]为根的堆进行调整适应 void BuildHeap(vector<int> &v,int begin,int end); void HeapSort(vector<int> &v,int begin,int end){ //重新实现 BuildHeap(v,begin,end); int tempend = end; for( ; tempend > begin;){ int temp = v[tempend]; v[tempend] = v[begin]; v[begin] = temp; HeapifyIndex(v,begin,--tempend,begin); } } void HeapifyIndex(vector<int> &v,int begin,int end,int parentindex){ // if(parentindex >= end) // return; int lchildindex = (parentindex - begin) * 2 + 1 + begin; //index of parent's lchild int rchildindex = (parentindex - begin) * 2 + 1 + begin + 1; //index of parent's rchild int largeindex = 0; if(rchildindex <= end && v[rchildindex] > v[parentindex]) largeindex = rchildindex; else largeindex = parentindex; if(lchildindex <= end && v[lchildindex] > v[largeindex]) largeindex = lchildindex; if(largeindex != parentindex ){ //最大的那个元素如果不是parentindex值, //就需要与父节点进行交换,就有可能破坏其子的最大堆性质,因此需要进行递归 //可参考《算法导论》 p86~90 int temp = v[largeindex]; v[largeindex] = v[parentindex]; v[parentindex] = temp; HeapifyIndex(v,begin,end,largeindex); } } void BuildHeap(vector<int> &v,int begin,int end){ //从最后一个父节点(即end的父)开始往前调整 int parentindex = (end-begin-1)/2+begin; //index of parent for(;parentindex >= begin ;parentindex--){ HeapifyIndex(v,begin,end,parentindex); } } //递归的两路归并 void Merge(vector<int> & v,int begin,int mid,int end){ vector<int> temp; int index1 = begin; int index2 = mid+1; while(index1 <= mid && index2 <= end){ if(v[index1] < v[index2]){ temp.push_back(v[index1]); index1++; } else{ temp.push_back(v[index2]); index2++; } } while(index1 <= mid) temp.push_back(v[index1++]); while(index2 <= end) temp.push_back(v[index2++]); for(int i = 0;i<temp.size();i++){ v[begin++] = temp[i]; } } void MergeSort(vector<int> & v,int begin,int end){ if(begin < end){ int mid = (begin+end)/2; MergeSort(v,begin,mid); MergeSort(v,mid+1,end); Merge(v,begin,mid,end); } } //基数排序 void RadixSort(vector<int> & v,int begin,int end){ vector< list<int> > listvec; listvec.resize(10); list<int> resulttemp; int i = 0; for(i = begin;i<=end;i++) resulttemp.push_back(v[i]); int d = 3; //d为分配回收的次数,即最大值的位数 int index = 0; //获取第几位的数,0 为个位,1为十位,2为百位 list<int>::iterator itres; while(d-- > 0){ itres = resulttemp.begin(); for(; itres!= resulttemp.end();itres++){ //将所有数以从index的数值(上述规则)分配至相应的桶 int radix = pow(10,index); int numofindex = ((*itres)/ radix)%10; listvec[numofindex].push_back(*itres); } index++; resulttemp.clear(); for(i = 0;i<10;i++){ //依次将桶中的数值回收至list中 resulttemp.splice(resulttemp.end(),listvec[i]); listvec[i].clear(); } } for(i = begin,itres = resulttemp.begin(); itres != resulttemp.end();itres++,i++){ v[i] = *itres; } }