2021/05/08 归并排序

本文探讨了如何通过递归实现归并排序,首先介绍了博主@一只菜菜的小鸟的通俗代码,随后作者结合书本知识优化了代码,减少空间消耗。重点在于理解递归过程和归并操作,以及空间效率的提升。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

学习新算法的时候总会让我感慨学海无涯以及自己的无知。

折腾了整整一天啊。。看了书上的伪码看半天愣是没搞懂,后面还是感谢csdn上博主@一只菜菜的小鸟  看了他的代码 通俗易懂 我才整明白了。

后面也是结合书上的伪码以及他的代码自己实现出来了。

归并排序的思路网上和书上都有很多。

我就不去网上拷图放在这里了。

重点在于:通过递归将原序列切半直到只剩下两个数据 还有一个能将它们合成排序新序列的函数

我将贴上两段代码,第一段是借鉴那位启蒙我的博主的代码

第二段则是我个人结合他与书上的伪码自己实现出来的代码。

 

这是第一段:

​#include<stdio.h>
#define MAX 100
//数组a看成两半,每一半都是已排序的序列,将它们两个归并起来并排好序放在数组t中  
void merge(int a[],int t[],int left,int mid,int right)   
{
	int i,j,k;
	i=left;j=mid+1;k=left;
	while(i<=mid&&j<=right)
	{
		if(a[i]<a[j])
		t[k++]=a[i++];
		else
		t[k++]=a[j++];
	}
	while(i<=mid)
	t[k++]=a[i++];
	while(j<=right)
	t[k++]=a[j++];                   //到此数组t已经被排好序 
}
 //通过递归将一个完整的序列不断分成左右两个序列,直到序列只剩下一个数据(即left==right) 
void msort(int a[],int t[],int left,int right)       
{
	int s[MAX];
	int mid;
	if(left==right)
	t[left]=a[right];
	else
	{
		mid=(left+right)/2;
		msort(a,s,left,mid); //处理左边      
		msort(a,s,mid+1,right);//处理右边
		merge(s,t,left,mid,right); 
        //s是左右两边合并起来的新序列,通过merge函数将它们归并排序成t序列 
	}
}
int main()
{
	int a[10]={9,8,7,6,5,4,3,2,1},i;
	msort(a,a,0,8);
	for(i=0;i<9;i++)
	printf("%d ",a[i]);
	return 0;
 } 

​

 

上面这一段代码通俗易懂,但是有个缺点,那就是在msort函数中申请了中间序列t[] 由于是递归,所以当数据庞大时会造成空间浪费。好在它确实好懂。

 

下面第二段是我个人的:

#include<stdio.h>
#include<stdlib.h>
 /*merge函数 用来将两个已排好序的序列合成一个顺序序列  
 它的函数参数是固定的,即一个预排列的序列a[] 一个中间序列temp[]用来存放合成的新序列
  序列a[]的左端指针left,中部指针mid,右端指针right*/ 
void merge(int a[],int temp[],int left,int mid,int right)  
{
	int i,j,k;
	i=left;j=mid+1;k=left;
	while(i<=mid&&j<=right)      //这一段是排序算法 
	{
		if(a[i]<=a[j])
		temp[k++]=a[i++];
		else
		temp[k++]=a[j++];
	}
	while(i<=mid)
	temp[k++]=a[i++];
	while(j<=right)
	temp[k++]=a[j++];
	for(k=left;k<=right;k++)  //再将已排好的序列复制回a[] 
	a[k]=temp[k];
}
/*  msort函数 核心函数 使用递归让原序列分割 
 初始状态下分成n个 然后两两合并,排序
 它的参数也是固定的 即一个原序列a[] 一个中间序列t[] 序列a[]的左、右端指针 left 和right */ 
void msort(int a[],int t[],int left,int right)
{
	int mid;
	if(left<right)
	{
		mid=(left+right)/2;
		msort(a,t,left,mid);    //先处理左半部分 
		msort(a,t,mid+1,right); //再处理右半部分 
		merge(a,t,left,mid,right); //归并排序 
	}
}
/*最终我们需要申请一个中间序列 它在调用msort函数以及merge函数要用上,最后可以把它free
可以节省空间 
当然我们也可以不用写这个函数 而是直接在主函数调用的时候申请即可*/ 
void MergeSort(int a[],int n)
{
	int *t;
	t=(int*)malloc(sizeof(int)*n);
	if(n>0)
	{
	msort(a,t,0,n-1);
	free(t); //节省空间	
	}
		 
}
int main()
{
	int a[10]={9,8,7,6,5,4,3,2,1},i;
/*	int t[10];              这一段就是没有写最后的函数可以这样用 只是t[]用完其实就没用了 可以free掉 
	msort(a,t,0,8);*/
	MergeSort(a,9);
	for(i=0;i<9;i++)
	printf("%d\n",a[i]);
	return 0;
}

 

1
2
3
4
5
6
7
8
9

--------------------------------
Process exited after 0.1098 seconds with return value 0
请按任意键继续. . .


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值