归并排序——分治思想

1 概述

归并排序是指利用归并操作的一种排序方法。规定是指将两个或两个以上的有序表组合成一个新的有序表的过程。

2 基本思想

归并排序的基本思想是将n个元素的初始序列看成n个成都为1的子序列,两两归并,得到n/2个长度为2或1的子序列,再两两归并,直到得到一个长度为n的有序序列为止。归并排序的核心操作时归并,而整个归并排序的处理过程可用递归方式完成。
具体原理如下:
1)有一数组如下,我们使用归并排序对其进行排序,首先将数组分成两个子序列,n/2;
在这里插入图片描述
2)这个时候我们就会想,如果把左边子序列和右边子序列各自都排好序,然后一合并是不是就可以了呢!那么怎么排呢,是不是可以同样参照上面的做法,把左边子序列又分成两个小的子序列呢,左边如此,右边也一样,如下图:
在这里插入图片描述
3)是不是可以重复第2)步呢,直到每一个小的子序列都只有一个元素,如下图:
在这里插入图片描述
4)然后此时,对每一个小的子序列,我们就不需要对其进行排序了,只需要对每两个子序列进行归并即可,即,将两个有序的序列进行归并然后放回原数组中。
在这里插入图片描述
5)重复第4步,直到结束
在这里插入图片描述

3 如何归并

也就是如何将两个有序的序列合并成一个序列并放回原数组,步骤如下:
假设现在需要合并数组 p 中 i 位置到j位置,j+1 位置到 k 位置的两个序列。
1)建立一个空数组,temp,长度为k-i+1;
2)首先,两个不同的指针指向两个序列的首位,然后比较两个元素的大小,如果第一个序列中的元素不大于第二个序列中的元素,那么将这个元素添加到temp中,同时指向第一个序列的指针向后移动一位,指向第二个序列的指针保持不动;
3)重复第2)步,直到两个序列中的某一个序列元素遍历结束;
4)上述步骤走完,应该会有其中一个序列是还剩下元素的,然后直接添加到temp后面即可。
5)将temp中元素放回原数组。

4 代码演示
// 先进的排序方法
//  归并排序 
#include<stdio.h>

int main()
{
	int arr[]={47,34,66,100,70,19,22,47},*p=arr;
	int i,j,len;
	printf("请将以下数据升序排列!\n");
	len = sizeof(arr)/sizeof(arr[0]);
	for(i=0;i<len;i++){
		printf("%-4d",*(arr+i));
	}
	
	void mergesort(int *p,int s,int t);
	mergesort(p,1,len);
	
	printf("\n排序后的序列如下!\n");
	for(i=0;i<len;i++){
		printf("%-4d",*(p+i));
	}
	return 0;
} 


void merge(int *p, int i, int j, int k)  // 合并p中i位置到j位置,j+1位置到k位置的两个数组 
{
	int m=i-1,n=j;  // 因为i,j,k代表的是位置,真正索引的时候应该是位置减去1;
	int temp[k-i+1],l=0;  // temp是一个临时的空数组,l是用来记录数组的 
	for(;m<j && n<k;l++){  // 因为每循环一次,都会往temp中增加一个数 
		if(p[m]<=p[n]){
			temp[l]=p[m];
			m++;
		}else{
			temp[l]=p[n];
			n++;	
		}	
	}
	// 因为上述循环走完,应该会有其中一个数组是还剩下元素的,直接添加到temp后面即可
	while(m<j){
		temp[l++]=p[m++];
	} 
	while(n<k){
		temp[l++]=p[n++];
	} 
	// 做完以后,将temp放回p对应的i到k位置中
	for(m=i-1;m<k;m++){
		p[m]=temp[m-i+1];
	} 
} 


void mergesort(int *p,int s,int t)
{
	if(s<t){
		int m=(s+t)/2;  // 分治 
		mergesort(p,s,m);  // 左分且归并 
		mergesort(p,m+1,t);  //  右分且归并 
		merge(p,s,m,t);  
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhangpaopao0609

看星空看日落不如看我的眼眸

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值