【数据结构】排序算法——九大排序算法

reference:排序算法参考《数据结构》严蔚敏(清华大学出版社)

首先是最经典的冒泡排序

void poposort(int a[],int n)
{
	int i,j;
	for(i=0;i<n-1;i++)
		for(j=0;j<n-1-i;j++)
			if(a[j]>a[j+1])
			{
				int temp;
				temp=a[j];
				a[j]=a[j+1];
				a[j+1]=temp;
			}
}

快速排序

/*快速排序的基本思想:
是通过一趟排序将所有的数据分割成两部分,其中一部分所有的数比
基准数都要大,另一部分所有数都比基准数要小,然后再对接下来的
两部分再快速排序*/ 
void qsort(int a[],int min,int max)
{
	int key=a[min];//将基准数定为第一个数 
	int start=min,end=max;//这一部分的开端和结尾下标 
	int temp;
	while(end>start)
	{
		while(end>start&&a[end]>=key)
			end--;//从尾开始,如果后面是大数,end向前进,走不动了停止 
		if(a[end]<key)
		{
			temp=a[end];
			a[end]=a[start];
			a[start]=temp;
		}//如果停止位置数小于key则交换 
		while(end>start&&a[start]<=key)
			start++;//从头开始,如果后面是小数,start向后走,走不动了停止前进 
		if(a[start]>key)
		{
			temp=a[start];
			a[start]=a[end];
			a[end]=temp;
		}//如果停止位置大于key则交换 
	}//如果end是大于start的,说明这趟数没有走完,继续走,如果走完了,说明成功将数分为了大小两部分 
	if(start>min)
	{
		qsort(a,min,start-1);//前一部分排序 
	}
	if(end<max)
	{
		qsort(a,end+1,max);//后一部分排序 
	}
}//递归快速排序,如果start==end==min==max说明程序结束 

直接插入排序

void insertsort(int a[],int n)
{
	int i,j;
	for(i=2;i<=n;i++)
		if(a[i]<a[i-1])
		{
			a[0]=a[i];//a[0]作为存储小数的空间来用 
			a[i]=a[i-1];
			for(j=i-2;a[0]<a[j];j--)
			{
				a[j+1]=a[j];
			}//后面数向前移动,方便插入 
			a[j+1]=a[0];//插入的步骤 
		}
}//每次找一部分,然后把最后一个数按顺序插入,其中插入可以用折半插入 

折半插入排序

void zhebaninsertsort(int a[],int n)
{
	int key;
	int i,j;
	int low,high,mid;
	for(i=1;i<n;i++)
		if(a[i]<a[i-1])
		{
			key=a[i];
			low=0;
			high=i-1;
			while(low<=high)
			{
				mid=(low+high)/2;
				if(key<a[mid])
				high=mid-1;
				else
				low=mid+1;
			}
			for(j=i;j>high+1;j--)
				a[j]=a[j-1];
			a[high+1]=key;
		}
}//每次找一部分,然后把最后一个数按顺序插入,其中插入可以用折半插入

选择排序

int selectminikey(int a[],int k,int n)
{
	int min=a[k];
	int i;
	int key;
	for(i=k;i<n;i++)
		if(a[i]<=min)
		{
			min=a[i];
			key=i;
		}
	return key;
}//选择最小数 
void selectsort(int a[],int n)
{
	int i,j;
	for(i=0;i<n-1;i++)
	{
		j=selectminikey(a,i,n);
		if(i!=j)
		{
			int temp;
			temp=a[i];
			a[i]=a[j];
			a[j]=temp;
		}
	}
}//每次都选择最小的和当前的坐标比,如果当前不是最小则交换

基数排序

void radixsort(int a[],int n)
{
	int *b; 
	int radix=1;//作基数 
	int i,j,k;
	b=(int *)malloc(n*sizeof(int));
	for(k=0;k<=5;k++)
	{//这里最大能排到第6位数 
	    int bucket[base]={0};//作计数器 
	    for(i=0;i<n;i++)
	    {//统计每个桶中的记录数 
	    	j=(a[i]/radix)%base;
			bucket[j]++;
	    	//printf("%d ",bucket[(a[i]/exp)%base]);
		}
		//printf("\n");
	    for(i=1;i<base;i++) 
	    {
	    	bucket[i]+=bucket[i-1];
	    	//printf("%d ",bucket[i]);
		}
	    //printf("\n");
	    for(i=n-1;i>=0;i--)
	      	b[--bucket[(a[i]/radix)%base]]=a[i];
	    for (i=0;i<n;i++)
	      	a[i]=b[i];
	    radix*=base;
	}
}//基数排序,把基数分为10个桶,按位排序,关键字为当前位置的数 

归并排序

/*已有序的子序列合并,得到完全有序的序列;即先使每
个子序列有序,再使子序列段间有序。将两个有序表合
并成一个有序表*/ 
void merge(int sr[],int tr[],int i,int m,int n)
{
	int j,k;
	for(k=i,j=m+1;i<=m&&j<=n;k++)//tr数组从i开始计数,i,j表示两部分分别的坐标 
	{
		if(sr[i]<sr[j])
			tr[k]=sr[i++];
		else 
			tr[k]=sr[j++];
	}
	
	if(i<=m)
		while(k<=n&&i<=m)
			tr[k++]=sr[i++];//同下 
	if(j<=n)
		while(k<=n&&j<=n)
			tr[k++]=sr[j++];//剩余元素并入 
}
void mergesort(int sr[],int tr1[],int s,int t)
{//将sr[s..t]归并排序为tr1[s..t] 
	int m;
	int tr2[100000];
	if(s==t)
		tr1[t]=sr[s];
	else
	{//如果头坐标不等于尾坐标 
		m=(s+t)/2;//分为两部分分别排序 
		mergesort(sr,tr2,s,m);
		mergesort(sr,tr2,m+1,t);
		merge(tr2,tr1,s,m,t);//两部分归并,排序的主要部分 
	}
}

堆排序

{//已知a[s..m]中记录的关键字除a[s]之外均满足堆的定义,本函数
//调整a[s]关键字,使a[s..m]成为一个大顶堆(对其中记录的关键字而言)

	int j;
	int ac=a[s];
	for(j=2*s;j<=m;j*=2)
	{// 沿值较大的孩子结点向下筛选
		if(j<m&&a[j]<a[j+1])//如果j下标对应值有右兄弟且值小于右兄弟值 
			j++;// 更新j,j为值较大的记录的下标
		if(ac>=a[j])
			break;// ac应插入在位置s上
		a[s]=a[j];
		s=j;
	}
	a[s]=ac;// 插入
	
	//for(int i=1;i<=10;i++)
	//	printf("%d ",a[i]);
	//printf("\n");
}
void heapsort(int a[],int length)
{
	int i;
	int temp;
	for(i=length/2;i>0;i--)
		heapadjust(a,i,length);
	for(i=length;i>1;i--)
	{/*将堆顶记录和当前未经排序子序列a[1..i]中最后一个记录相互交
	换,之后i下标对应元素到位(排序后应该在的位置)*/
		temp=a[i];
		a[i]=a[1];
		a[1]=temp;
		heapadjust(a,1,i-1);// 将a[1..i-1]重新调整为大顶堆
	}
}

希尔排序

/*shell排序实际上是分组增量排序,一般取初始序列的一半为增量,以
后每次减半,直到增量为1*/ 
void shellsort(int a[],int n)
{
	int gap=n/2;
	int i,j;
	int temp;
	while(gap>0)
	{
		for(i=gap;i<n;i++)
		{//i为这组数第二个数的坐标,每一次前进一个数,分别和前面数作比较 
			/*如果序列为5 6 8 4 2
			则第一次为5 6 8 4 2
			第二次为5 6 8 4 2
			第三次为4 5 6 8 2
			第四次为2 4 5 6 8*/ 
			temp=a[i];
			for(j=i-gap;j>=0&&temp<a[j];j-=gap)
			{//如果temp>a[j]就不用再比较了,省时间 
				a[j+gap]=a[j];
			}
			a[j+gap]=temp;
		}
		gap/=2;
	}
}

测试函数

int main()
{
	int n;
	int *a,*b;
	int i;
	printf("请输入您数据的个数:");
	scanf("%d",&n);
	printf("请输入您的数据:");
	a=(int *)malloc((n)*sizeof(int));
	b=(int *)malloc((n+1)*sizeof(int));
	for(i=0;i<n;i++)
		scanf("%d",&a[i]);
	{
		printf("堆排序结果:");
		for(i=1;i<=n;i++)
			b[i]=a[i-1];
		heapsort(b,n);
		for(i=0;i<n;i++)
			printf("%d ",b[i+1]);
		printf("\n"); 
	}
	{
		printf("归并排序结果:");
		for(i=1;i<=n;i++)
			b[i]=a[i-1];
		mergesort(b,b,1,n);
		for(i=0;i<n;i++)
			printf("%d ",b[i+1]);
		printf("\n"); 
	}
	{
		printf("基数排序结果:");
		for(i=0;i<n;i++)
			b[i]=a[i];
		radixsort(b,n);
		for(i=0;i<n;i++)
			printf("%d ",b[i]);
		printf("\n"); 
	}
	{
		printf("快速排序结果:");
		for(i=0;i<n;i++)
			b[i]=a[i];
		int min=0;
		int max=n-1; 
		qsort(b,min,max);
		for(i=0;i<n;i++)
			printf("%d ",b[i]);
		printf("\n"); 
	}
	{
		printf("起泡排序结果:");
		for(i=0;i<n;i++)
			b[i]=a[i];
		poposort(b,n);
		for(i=0;i<n;i++)
			printf("%d ",b[i]);
		printf("\n"); 
	}
	{
		printf("希尔排序结果:");
		for(i=0;i<n;i++)
			b[i]=a[i];
		shellsort(b,n);
		for(i=0;i<n;i++)
			printf("%d ",b[i]);
		printf("\n"); 
	}
	{
		printf("选择排序结果:");
		for(i=0;i<n;i++)
			b[i]=a[i];
		selectsort(b,n);
		for(i=0;i<n;i++)
			printf("%d ",b[i]);
		printf("\n"); 
	}
	{
		printf("直接插入排序结果:");
		for(i=0;i<n;i++)
			b[i+1]=a[i];
		insertsort(b,n);
		for(i=0;i<n;i++)
			printf("%d ",b[i+1]);
		printf("\n"); 
	}
	{
		printf("折半插入排序结果:");
		for(i=0;i<n;i++)
			b[i]=a[i];
		zhebaninsertsort(b,n);
		for(i=0;i<n;i++)
			printf("%d ",b[i]);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值