数据结构-内部排序

来源:互联网 发布:js调用cmd 编辑:程序博客网 时间:2024/06/05 20:38

内部排序算法

时间复杂度: O(n^2)  O(n^2)   O(n^2)

空间复杂度: O(1)    O(1)      O(1)

算法名称:   插入     选择     冒泡

 

算法名称:   希尔    堆        快速         归并     基数

空间复杂度:O(1)     O(1)       O(logn)     O(n)    O(2rd)

时间复杂度:O(nlogn) O(nlogn)  O(nlogn)    O(nlogn) O(d(n+rd))

 

稳定的:插入 冒泡 归并 基数

其它:不稳定排序。

示列代码:

#include<iostream>#include<stdlib.h>using namespace std;#define MAXSIZE 500typedef int KeyType;////定义关键字类型typedef char InfoType;struct RecType{KeyType key;//关键字项InfoType data;//其他数据项,类型为InfoType}R[MAXSIZE],R1[MAXSIZE];//插入排序void StrInsSort(RecType R[],int n)//直接插入排序{//时间复杂度O(n2)for(int i=2;i<=n;i++){R[0]=R[i];//将待排序记录放进监视哨int j=i-1;while(R[0].key<R[j].key){R[j+1]=R[j];//记录后移j--;}R[j+1]=R[0];//将待排序记录放到合适位置}}void BinsSort(RecType R[],int n)//折半插入排序{//折半插入排序仅仅是减少了关键字间的比较次数,//但是记录移动的次数不变,所以时间复杂度仍然为:O(n2)for(int i=2;i<=n;i++){R[0]=R[i];int low=1,high=i-1;//设置折半查找的范围while(low<=high)//折半查找插入位置{int m=(low+high)/2;if(R[0].key<R[m].key)high=m-1;else low=m+1;}for(int j=i-1;j>=high+1;j--)R[j+1] = R[j];//记录后移R[high+1] = R[0];//插入}}void ShellSort(RecType R[],int n)//希尔排序{//时间复杂度为:O(n1.3)//Shell:d1=  n/2 , di+1=  di/2 ,最后一个取1for(int d=n/2;d>=1;d=d/2){for(int i=1+d;i<=n;i++){//将R[i]插入到所属组的有序列段中,直接插入排序R[0]=R[i];int j=i-d;while(j>0&&R[0].key<R[j].key){R[j+d]=R[j];//记录后移,查找插入位置j=j-d;}R[j+d]=R[0];//将第i个元素插入到合适位置}}}//交换排序void BubbleSort(RecType R[],int n)//起泡排序{//时间复杂度O(n2)for(int i=1;i<n;i++)//最多n-1趟起泡{for(int j=1;j<=n-i;j++)//每趟都把最大的放在最后面{//两两比较,发现逆序立即交换if(R[j].key>R[j+1].key){RecType temp = R[j];R[j]=R[j+1];R[j+1]=temp;}}}}void BubbleSort1(RecType R[],int n)//改进的起泡排序{//时间复杂度O(n2)int i =n;//i指示无序序列中最后一个记录的位置while(i>1)//冒泡排序的结束条件为:最后一趟没有进行交换{int lastExchange = 1;//记录最后一次交换发生的位置for(int j=1;j<i;j++){if(R[j].key>R[j+1].key){RecType temp = R[j];R[j]=R[j+1];R[j+1]=temp;lastExchange=j;}}i = lastExchange;}}//快速排序也叫分区交换排序int Partition(RecType R[],int low,int high){//交换记录子序列R[low..high]中的记录,使枢轴记录//到位并返回其 所在位置,此时,在它之前(后)的记录均不大(小)于它R[0] = R[low];//以子表的第一个记录作枢轴,将其暂存到记录R[0]中int pivotkey = R[low].key;//枢轴记录关键字while(low<high){//从表的两端交替地向中间扫描while(low<high && R[high].key>=pivotkey)high--;R[low] = R[high];//将比枢轴小的记录移到低端while(low<high && R[low].key<=pivotkey)low++;R[high]=R[low];//将比枢轴大的记录移到高端}R[low]=R[0];//枢轴记录到位return low;//返回枢轴位置}void change(RecType R[],int low,int high)//快速排序前进行预处理{//比较R[s].key和R[t].key和R[(s+t)/2].key,//然后取关键字为“三者之中值”的记录作为枢轴记录,将其与R[s]互换即可if(R[low].key>=R[high].key){if(R[low].key>=R[(low+high)/2].key){if(R[(low+high)/2].key>=R[high].key){RecType temp = R[(low+high)/2];R[(low+high)/2] = R[low];R[low] = temp;}else{RecType temp = R[high];R[high] = R[low];R[low] = temp;}}}else{if(R[high].key>=R[(low+high)/2].key){if(R[(low+high)/2].key>=R[low].key){RecType temp = R[(low+high)/2];R[(low+high)/2] = R[low];R[low] = temp;}}}}void QSort(RecType R[],int low,int high){//对记录序列R[low..high]进行快速排序if(low<high)//长度大于1{change(R,low,high);//为了避免出现一趟排序后记录集中在枢轴一侧的情况,快速排序前进行预处理int location = Partition(R,low,high);//获得枢轴位置,将R[low..high]分成两部分QSort(R,low,location-1);QSort(R,location+1,high);}}void QuickSort(RecType R[],int n){//时间复杂度nlogn//对记录序列进行快速排序QSort(R,1,n);}//选择排序void SelectSort(RecType R[],int n)//直接选择排序{//时间复杂度O(n2)for(int i=1;i<n;i++){//选择第i小的记录,并交换到位int k=i;//假定第i个元素的关键字最小for(int j=i+1;j<=n;j++)//找最小元素的下标{if(R[j].key<R[k].key)k=j;}if(i!=k){RecType temp = R[i];R[i]=R[k];R[k]=temp;}}}void Sift(RecType R[],int i,int m)//调整堆的算法,筛选{//假设R[i+1..m]中各元素满足堆的定义,//本算法调整R[i]使序列R[i..m]中各元素满足堆的性质R[0]=R[i];//暂存“根”记录R[i]for(int j=2*i;j<=m;j*=2)//j<=m时,R[2i]是R[i]的左孩子{//若R[i]的右孩子存在,且关键字大于左孩子,j指向R[i]的右孩子//j指向关键字最大的孩子if(j<m&&R[j].key<R[j+1].key)j++;if(R[0].key<R[j].key)//孩子结点关键字较大{R[i]=R[j];//将R[j]换到双亲位置i=j;}else break;//调整完毕,退出循环}R[i]=R[0];//最初被调整结点放入正确位置}void HeapSort(RecType R[],int n)//堆排序{//时间复杂度O(nlogn),待排序数目小的话不提倡用堆排序,因为建堆太费时//对记录序列R[1..n]进行堆排序。for(int i=n/2;i>0;i--)//把R[1..n]建成大顶堆,对于完全二叉树,n/2正好是最后一个非叶子结点{Sift(R,i,n);}for(int j=n;j>1;j--){//将堆顶记录和当前未经排序子序列R[1..i]中//最后一个记录相互交换RecType temp=R[1];R[1]=R[j];R[j]=temp;Sift(R,1,j-1);//将R[1..i-1]重新调整为大顶堆}}//归并排序void Merge(RecType R[],RecType R1[],int i,int l,int h){//将有序的R[i..l]和R[l+1..h]归并为有序的R1[i..h]int j,k;for(j=l+1,k=i;i<=l&&j<=h;k++){//将R中记录由小到大地并入R1if(R[i].key<=R[j].key)R1[k]=R[i++];else R1[k]=R[j++];}if(i<=l)//将剩余的R[i..l]复制到R1{for(;i<=l;i++){R1[k++]=R[i];}}if(j<=h)//将剩余的R[j..h]复制到R1{for(;j<=h;j++){R1[k++]=R[j];}}}void Msort(RecType R[],RecType R1[],int s,int t){//将R[s..t]进行2-路归并排序为R1[s..t]RecType R2[MAXSIZE];if(s==t)R1[s]=R[s];//长度为1else{int m=(s+t)/2;//将R[s..t]平分为R[s..m]和R[m+1..t]Msort(R,R2,s,m);//递归地将R[s..m]归并为有序的R2[s..m]Msort(R,R2,m+1,t);//递归地将R[m+1..t]归并为有序的R2[m+1..t]Merge(R2,R1,s,m,t);//将R2[s..m]和R2[m+1..t]归并到R1[s..t]}}void MergeSort(RecType R[],int n)//2-路归并排序{//时间复杂度O(nlogn)//对记录序列R[1..n]作2-路归并排序。//RecType R1[MAXSIZE];Msort(R,R1,1,n);}void select(){cout<<"欢迎进入排序操作界面"<<endl;cout<<"1,初始化待排序的序列"<<endl;cout<<"2,直接插入排序"<<endl;cout<<"3,折半插入排序"<<endl;cout<<"4,希尔排序"<<endl;cout<<"5,起泡排序"<<endl;cout<<"6,改进的起泡排序"<<endl;cout<<"7,快速排序"<<endl;cout<<"8,直接选择排序"<<endl;cout<<"9,堆排序"<<endl;cout<<"10,二路归并排序"<<endl;cout<<"11,输出序列"<<endl;cout<<"0,退出"<<endl;}int main(){int n,i=0,flg=0,op;select();while(1){cout<<"输入操作序号"<<endl;cin>>op;switch(op){case 0:exit(0);break;case 1:cout<<"输入待排序的数字的个数:"<<endl;cin>>n;cout<<"依此输入数字"<<endl;for(i=1;i<=n;i++){cin>>R[i].key;}cout<<"序列初始化完成"<<endl;break;case 2:StrInsSort(R,n);cout<<"直接插入排序完成"<<endl;break;case 3:BinsSort(R,n);cout<<"折半插入排序完成"<<endl;break;case 4:ShellSort(R,n);cout<<"希尔排序完成"<<endl;break;case 5:BubbleSort(R,n);cout<<"起泡排序完成"<<endl;break;case 6:BubbleSort1(R,n);cout<<"改进后的起泡排序完成"<<endl;break;case 7:QuickSort(R,n);cout<<"快速排序完成"<<endl;break;case 8:SelectSort(R,n);cout<<"直接选择排序完成"<<endl;break;case 9:HeapSort(R,n);cout<<"堆排序完成"<<endl;break;case 10:MergeSort(R,n);cout<<"二路归并排序完成"<<endl;flg=1;break;case 11:cout<<"序列为"<<endl;if(flg==0){for(int j=1;j<=n;j++){cout<<R[j].key<<" ";}}else{for(int j=1;j<=n;j++){cout<<R1[j].key<<" ";}flg=0;}cout<<endl;break;default:cout<<"输入操作错误"<<endl;break;}}}