#include<iostream>
using namespace std;
#define MAXSIZE 500
typedef 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 ,最后一个取1
for(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中记录由小到大地并入R1
if(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];//长度为1
else
{
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;
}
}
}
各种排序算法
最新推荐文章于 2021-08-17 20:20:10 发布