排序综合问题(八大排序)

设计程序,利用随机函数产生20000个随机整数(1~1000000),完成下面功能:

(1)对这些数分别进行直接插入排序、折半插入排序、希尔排序、起泡排序、快速排序、简单选择排序、堆排序、2-路归并排序,并把排序结果保存到文件中。

(2)分析上述排序算法的性能(以运行程序所花费的时间为准进行对比),找出较快的排序方法。

(3)若排序的整数增加到100000个、100000000个,以上排序结果有什么变化,请分析并验证。

#include<iostream> 
#include<cstdlib>
#include<ctime>
#define MAXSIZE 20000   //顺序表最大长度
using namespace std ;
typedef struct{
	int key;           //关键字项,关键字类型为整形
	char *otherinfo;   //其它数据项
}RedType;     //记录类型
typedef struct{
	RedType r[MAXSIZE+1];     //0号单元闲置
	int length;               //顺序表长度
}SqList;     //顺序表类型
//直接插入排序
void InsertSort(SqList &L)
{
	int j ;
	for(int i=2;i<=L.length;i++)
	{
		if(L.r[i].key<L.r[i-1].key)
		{
			L.r[0]=L.r[i] ;
			L.r[i]=L.r[i-1] ;
			for(j=i-2;L.r[0].key<L.r[j].key;--j)
				L.r[j+1]=L.r[j] ;
			L.r[j+1]=L.r[0] ;
		}
	}
}
//折半插入排序
void BInsertSort(SqList &L)
{
	for(int i=2;i<L.length;i++)
	{
		L.r[0] = L.r[i] ;
		int low = 1 ;
		int high = i-1 ;
		while(low <=high)
		{
			int m=(low+high)/2 ;
			if(L.r[0].key<L.r[m].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] ;
	}
}
//希尔排序  ShellInsert() ShellSort()
//对顺序表L中的记录进行一趟增量为dk的希尔排序
void ShellInsert(SqList &L,int dk)
{
	int j ;
	for(int i=dk+1;i<=L.length;i++)
		if(L.r[i].key<L.r[i-dk].key)
		{
			L.r[0]=L.r[i] ;
			for(j=i-dk;j>0&&L.r[0].key<L.r[j].key;j-=dk)
			L.r[j+dk] = L.r[j] ;
			L.r[j+dk] = L.r[0] ;
		}
}
//对顺序表L中的记录按增量序列(存储在数组dt中)进行t趟希尔排序
void ShellSort(SqList &L,int dt[],int t)
{
	for(int k=0;k<t;++k)
		ShellInsert(L,dt[k]) ;
}
//冒泡排序
void BubbleSort(SqList &L)
{//对顺序表L进行冒泡排序
	int m = L.length - 1 ;
	int flag = 1 ;   //flag 用来标记某一烫排序是否发生交换 
	while((m>0)&&(flag==1))
	{
		flag = 0 ;     //flag 置为 0 ,如果本趟排序没有发生交换,则不会执行下一趟排序 
		for(int j=1;j<=m;j++)
			if(L.r[j].key>L.r[j+1].key)
			{
				flag = 1 ;    //flag置为 1 表示本趟排序发生了交换 
				RedType t = L.r[j];
				L.r[j] = L.r[j+1] ;
				L.r[j+1] = t ;            //交换前后两个记录 
			} 
		--m ;
	} 
}
//快速排序 Partition()  QSort() QuickSort()
//对顺序表L中的子表L.r[low...high]进行一次划分,并返回枢轴位置
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 ;
}
//对顺序表L中的子序列L.r[low...high]进行快速排序
void QSort(SqList &L,int low,int high)
{
	if(low<high)
	{
		int pivotloc = Partition(L,low,high) ;
		QSort(L,low,pivotloc-1) ;
		QSort(L,pivotloc+1,high) ;
	}
}
//对顺序表L中的记录进行快速排序
void QuickSort(SqList &L)
{
	QSort(L,1,L.length) ;
}
//简单选择排序
void  SelectSort(SqList &L)
{//对顺序表L做简单选择排序
	for(int i=1;i<L.length;i++)
	{//在 L.r[i....L.length]中选择关键字最小的记录 
		int k = i ;
		for(int j=i+1;j<L.length;j++)
			if(L.r[j].key<L.r[k].key)
				k = j ;      // k 指向此趟排序中关键字最小的记录 
		if(k!=i)
		{
			RedType t = L.r[i] ;
			L.r[i] = L.r[k] ;
			L.r[k] = t ;   //交换 r[i]与r[k]  
		}  
	} 
}
//堆排序  HeapAdjust()  CreatHeap()  HeapSort()
//筛选法调整堆 
void HeapAdjust(SqList &L,int s,int m)
{//假设 r[s+1..m]已经是堆,将r[s.m] 调整为以 r[s] 为根的大根堆
	RedType rc = L.r[s] ;
	for(int j=2*s;j<=m;j*=2)   //沿key较大的孩子结点向下筛选 
	{
		if(j<m&&L.r[j].key<L.r[j+1].key)
			++j ;               // j 为 key 较大的记录的下标 
		if(rc.key>=L.r[j].key)    // rc 应插入在位置 s 上 
			break ; 
		L.r[s] = L.r[j] ;
		s = j ;
	} 
	L.r[s] = rc ;
}
//初建堆
void CreatHeap(SqList &L) 
{//把无序序列 L.r[1...n] 建成大根堆 
	int n = L.length ;
	for(int i=n/2;i>0;i--)   //反复调用HeapAdjust 
		HeapAdjust(L,i,n) ;
} 
//堆排序算法实现
void HeapSort(SqList &L)
{
	CreatHeap(L) ;//把无序序列 L.r[1...L.length] 建成大根堆
	for(int i=L.length;i>1;i--)
	{
		RedType x = L.r[1] ; //将堆记录和当前未经排序L.r[1...i]中最后一个记录互换 
		L.r[1] = L.r[i] ;
		L.r[i] = x ;
		HeapAdjust(L,1,i-1) ;//将L.r[1...i-1] 重新调整为大根堆 
 	} 
} 
// 2-路归并排序
//相邻两个有序子序列的归并 
void Merge(RedType R[],RedType T[],int low,int mid,int high)
{//将有序表R[low...mid]和R[mid+1...hight] 归并为有序列表T[low...hight]
	 int i = low ;
	 int j = mid + 1 ;
	 int k = low ;
	while(i<=mid&&j<=high) //	将 R 中记录由小到大并入 T 中 
	{
		if(R[i].key<=R[j].key)
			T[k++] = R[i++] ;
		else
			T[k++] = R[j++] ;
	} 
	while(i<=mid)
		T[k++] = R[i++] ;   //将剩余的 R[i..mid] 复制到 T 中 
	while(j<=high)
		T[k++] = R[j++] ;   //将剩余的 R[j..high] 复制到 T 中 
} 
//分
void MSort(RedType R[],RedType T[],int low,int high)
{ //R[low..high] 归并排序后放入 T[low..high]中
	if(low == high)
		T[low] = R[low] ;
	else 
	{
		RedType S[MAXSIZE+1];
		int mid = (low+high) / 2 ;
		MSort(R,S,low,mid) ;
		MSort(R,S,mid+1,high);
		Merge(S,T,low,mid,high) ;
	} 
} 
//递归调用排序 
void MergeSort(SqList &L) 
{
	MSort(L.r,L.r,1,L.length) ;
} 
//创建顺序表:向顺序表L中添加10个记录,记录的关键字为1-100范围内的随机整数
void CreateList(SqList &L)
{
	int i;
	srand(time(0));
	for(i=1;i<20000;i++)
	{
		L.r[i].key =rand()%1000000+1;
	}
	L.length =20000;
}
//菜单
void showmenu()
{
	printf("-------------操作选项---------------\n") ;
	printf("------------------------------------\n") ;
	printf("       1、直接插入排序\n") ;
	printf("       2、折半插入排序\n") ;
	printf("       3、希尔排序\n") ;
	printf("       4、冒泡排序\n") ;
	printf("       5、快速排序\n") ;
	printf("       6、简单选择排序\n") ;
	printf("       7、堆排序\n") ;
	printf("       8、归并排序\n") ;
	printf("------------------------------------\n") ;
} 
int main()
{
	SqList L;  
	CreateList(L);         //创建顺序表L,生成随机数 
	clock_t start, finish ;//每个函数开始和结束的时间 
	double shijian = 0.0 ; //函数  结束的时间-开始的时间=排序总用时  
	int n,dt[3]={5,3,1};    //dt中存放的是希尔排序时使用的三个增量
	showmenu() ; 
	printf("\n") ;
	printf("测试数据量:1000\n") ;
	printf("\n") ;
	//将生成的随机数读入到 data.doc 文件中 
	FILE * fpWrite = fopen("C:\\Users\\LZY\\Desktop\\data.doc","w") ;
		for(int i=1;i<=L.length;i++)
			fprintf(fpWrite,"%-8d ",L.r[i].key) ;
	if(fpWrite!=NULL)
			printf("初始数据读入文件成功\n") ;
	fclose(fpWrite) ; //关闭文件 
	cin>>n;         //输出选择的排序方法序号
	while(n!=0)     //循环显示菜单,按0结束程序
	{
		switch(n)     //根据选择的序号调用不同的排序方法
		{
		case 1:   
			start = clock() ;
			InsertSort(L);    //直接插入排序
			finish = clock() ;
			shijian = double(finish - start) ;
			printf("直接插入排序耗时:%lf \n",shijian) ;
			break;
		case 2:
			start = clock() ;
			BInsertSort(L);   //折半插入排序
			finish = clock() ;
			shijian = double(finish - start) ;
			printf("折半插入排序耗时:%lf \n",shijian) ;
			break;
		case 3:
			start = clock() ;
			ShellSort(L,dt,3);    //希尔排序,(3趟)
			finish = clock() ;
			shijian = double(finish - start) ;
			printf("希尔排序耗时:%lf \n",shijian) ; 
			break;
		case 4:   
			start = clock() ;
			BubbleSort(L);    //冒泡排序
			finish = clock() ;
			shijian = double(finish - start) ;
			printf("冒泡排序耗时:%lf \n",shijian) ; 
			break ;
		case 5:
			start = clock() ;
			QuickSort(L);    //快速排序
			finish = clock() ;
			shijian = double(finish - start) ;
			printf("快速排序耗时:%lf \n",shijian) ; 
			break;
		case 6:
			start = clock() ;
			SelectSort(L);    //简单选择排序
			finish = clock() ;
			shijian = double(finish - start) ;
			printf("简单选择排序耗时:%lf \n",shijian) ; 
			break;
		case 7:
			start = clock() ;
			HeapSort(L);    //堆排序
			finish = clock() ;
			shijian = double(finish - start) ;
			printf("堆排序耗时:%lf \n",shijian) ; 
			break;
		case 8:
			start = clock() ;
			MergeSort(L);    //归并排序
			finish = clock() ;
			shijian = double(finish - start) ;
			printf("归并排序耗时:%lf \n",shijian) ; 
			break;
		default:
			cout<<"序号选择错误,请重新选择!"<<endl;
			break;
		}
		//将排序后的数据读入到 data1.doc 文件中 
		FILE * fpWrite = fopen("C:\\Users\\LZY\\Desktop\\data1.doc","w") ;
		for(int i=1;i<=L.length;i++)
			fprintf(fpWrite,"%-8d ",L.r[i].key) ;
		if(fpWrite!=NULL)
			printf("排序后数据读入文件成功\n") ; 
		fclose(fpWrite) ; //关闭文件
		CreateList(L);    //每次排序后,重置L中的10个记录
		cin>>n;
	}	
	return 0 ;
}

 

  • 6
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值