排序算法

来源:互联网 发布:励志的句子 知乎 编辑:程序博客网 时间:2024/06/06 09:42
#include<iostream>#include<fstream>#include<sstream>#include<string>using namespace std;#define MAXSIZE 20typedef int KeyType;typedef struct{KeyType key;string otherinfo;}RedType;typedef struct{RedType r[MAXSIZE+1];int length;void print();}SqList;typedef SqList HeapType;/*堆采用顺序表存储表示*/void SqList::print(){for(int i=1;i<=length;i++)cout<<r[i].key<<'\t'<<r[i].otherinfo<<endl;}/*直接插入排序*//*其时间复杂度为O(n**2)*/void InsertSort(SqList &L){for(int i=2;i<=L.length;i++)/*length-1次迭代*/if(L.r[i].key<L.r[i-1].key)/*从最后一个先左比较,若大,则保持位置不变*/{L.r[0]=L.r[i];/*r[0]作为哨兵*/L.r[i]=L.r[i-1];for(int j=i-2;L.r[j].key>L.r[0].key;j--)/*找到比哨兵值小的位置,其前的元素后移*/L.r[j+1]=L.r[j];L.r[j+1]=L.r[0];/*插入正确的位置*/}}/*其它插入排序*//*折半插入排序*//*利用折半查找来实现查找操作*//*时间复杂度还是O(n**2)*//*虽然查找省了时间,但仍然需要移位*/void BInsertSort(SqList &L){for(int i=2;i<=L.length;i++)if(L.r[i].key<L.r[i-1].key){L.r[0]=L.r[i];/*与直接插入排序的区别在于查找位置*/int low=1,high=i-1,m;while(low<=high){m=(low+high)/2;//折半if(L.r[m].key>L.r[0].key)//插入点在低半区 high=m-1;else//插入点在高半区low=m+1;}for(int j=i-1;j>=high+1;j--)//记录后移L.r[j+1]=L.r[j];L.r[high+1]=L.r[0];//插入}}void ShellInsert(SqList &L,int dk){for(int i=dk+1;i!=L.length;i++)if(L.r[i].key<L.r[i-dk].key)/*需将L.r[i]插入有序增量子序列中*/{L.r[0]=L.r[i];/*暂存在L.r[0]中*/for(int j=i-dk;j>0 && L.r[j].key>L.r[0].key;j-=dk)L.r[j+dk]=L.r[j];/*记录后移,查找插入位置*/L.r[j+dk]=L.r[0];/*插入*/}}/*希尔排序,又称缩小增量排序,插入排序的一种*//*先将整个待排记录序列分割成如干子序列进行直接插入排序,待整个序列基本有序的时候,再对全体记录进行一次直接插入排序*/void ShellSort(SqList &L,int dlta[],int t){for(int k=0;k<t;k++)ShellInsert(L,dlta[k]);}/*快速排序*//*基本思想:通过一趟排序将代排记录分割成独立的两部分,其中一部分记录关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序*//*快速排序是O(nlogn)的排序方法中,其平均性能最好。但初始记录顺序有序时,快排将退化为气泡排序其时间复杂度变成O(n**2)但快速排序需要一个栈空间来实习递归,若每一趟排序都将记录序列均匀的分割成长度相近的两个子序列,则栈的最大深度为[log2n+1];最坏的时候,若每趟排序均偏向子序列的一端,则为最坏情况,栈的最大深度为n*/int Partition(SqList &L,int low,int high){L.r[0]=L.r[low];/*用子表的第一个记录作扭轴记录*/int pivotkey=L.r[low].key;/*扭轴记录关键字*/while(low<high)/*从表的两端交替向中间扫描*/{while(low<high && L.r[high].key>=pivotkey) --high;L.r[low]=L.r[high];/*将比扭轴记录小的记录移到低端*/while(low<high && L.r[low].key<=pivotkey) ++low;L.r[high]=L.r[low];/*将比扭轴记录大的记录移到高端*/}L.r[low]=L.r[0];/*扭轴记录到位*/return low;}/*递归形式的快速排序*/void QSort(SqList &L,int low,int high){if(low<high)/*长度大于1*/{int pivocloc=Partition(L,low,high);/*一分为二*/QSort(L,low,pivocloc-1);/*对低子表递归排序*/QSort(L,pivocloc+1,high);/*对高子表递归排序*/}}void QuickSort(SqList &L){QSort(L,1,L.length);}/*简单选择排序*//*通过n-i次关键字的比较,从n-i+1个记录中选出关键字最小的记录,并和第i个记录交换*//*简单选择排序,所需记录移动的操作次数较少,其最小值为“0”,最大值为3(n-1)*//*比较次数相同,均为n(n-1)/2。总的时间复杂度为O(n**2)*/int SelectMinKey(SqList &L,int i){int imin=i;for(int j=i+1;j!=L.length;j++){if(L.r[j].key<L.r[imin].key){imin=j;}}return imin;}void SelectSort(SqList &L){for(int i=1;i!=L.length;i++){int j=SelectMinKey(L,i);if(i!=j){RedType temp;temp=L.r[i];L.r[i]=L.r[j];L.r[j]=temp;}}}/*堆排序*//*只需要一个记录大小的辅助空间,每个待排序的记录仅占一个存储空间*//*由于堆排序最坏情况下,其时间复杂度也为O(nlogn)。相对于快速排序,这是堆排序最大优点*//*堆排序仅需要一个记录大小供交换用的辅助空间*/void HeapAdjust(HeapType &H,int s,int m){RedType rc=H.r[s];for(int j=2*s;j<=m;j=j*2)/*沿key较大的孩子结点向下筛选*/{if(j<m && (H.r[j].key<H.r[j+1].key)) ++j;//j为key较大的记录的下标if(!(rc.key<H.r[j].key)) break;//rc应插入在位置sH.r[s]=H.r[j];s=j;}H.r[s]=rc;//插入}void HeapSort(HeapType &H){for(int i=H.length/2;i>0;--i)HeapAdjust(H,i,H.length);/*建成大顶堆*/for(i=H.length;i>1;--i){RedType temp;/*将堆顶记录和当前未经排序子序列中最后一个记录相互交换*/temp=H.r[i];H.r[i]=H.r[1];H.r[1]=temp;HeapAdjust(H,1,i-1);/*将H.r[1..i-1]调整为大顶堆*/}}int main(){ifstream infile;infile.open("data.txt");if(!infile){cerr<<"error:unable to open input file:"<<infile<<endl;return -1;}string line;SqList L;L.length=0;while(getline(infile,line))/*读一行数据到line*/{L.length++;istringstream stream(line);/*读string功能*/stream>>L.r[L.length].key>>L.r[L.length].otherinfo;}//InsertSort(L);//BInsertSort(L);//int dlta[3]={5,3,1};//ShellSort(L,dlta,3);//QuickSort(L);//SelectSort(L);HeapSort(L);L.print();return 0;}


数据文件 data.txt

49 zhoujielun38 xiaoshengyang65 zhouxinchi97 caiyilin76 tangwei13 liangcaowei27 wujinru49 yaoming