各种排序算法

#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;
		}
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值