归并排序 c语言详解

如何设计一个归并排序的函数?

首先我们来了解它的原理。

归并排序运用了分治的思想,也就是分而治之。将一个问题不断细分成为求解方法类似的小规模问题,通过小规模问题进而求解。

//下列程序讲述如何将两段有序数列合为一段有序数列,即“合”

假如我们现在有两组有序数列

我们如何将他们有序的放到一个数组中呢?

我们用i指向第一个数组作为下标,j指向第二个数组作为下标;

设置一段空间 arr[]:

 

以k作为下标。

放置第一个元素时比较s[i]与t[j]的大小

当s[i]<t[j], arr[k] = s[i]; 并且相对的i++;k++;(也可表示为arr[k++]=s[i++],下式同理)

当s[i]>t[j], arr[k] = t[j]; 并且相对的j++;k++;

不断地循环,直到  i或者j  到达最大值(由此可知在之前我们需要得到他们的最大值)退出循环;

退出循环以后,可能仍有一个数组剩余元素,将剩下元素一一赋值给新数组arr即能得到一个新的有序数列。

 

现在我们已经知道如何将两段有序数列合为一段有序数列了,那么我们怎样才能得到两端有序数列呢?//“分”

我们现在有一组无序数列

我们把他分为两段:

 

此时仍为无序数列,可是如果一直拆分直到每组数列只剩一个呢??

我们就可以得到归并排序的大致思路:

对于一段无序数列,找出中间值,根据中间值将它分为左边一组与右边一组,然后分别又对左边与右边继续拆分。直到最后数组只剩下一个元素。那么我们就得到了无数个“有序”数组。根据上面写的合并的思路,两两合并逐渐得到有序数组。

 

 

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>

void merge(int* a, int left, int mid, int right)
{
	int i = left;//i指向第一组数组,范围left~mid
	int j = mid + 1;//j指向第二组数组,范围mid+1~right
	int k = left;
	int arr[100];

	while (i <= mid && j <= right)//谁小放谁
	{
		if (a[i] < a[j])
		{
			arr[k++] = a[i++];
		}
		else
		{
			arr[k++] = a[j++];
		}
	}

	//剩余元素
	while (i <= mid)
	{
		arr[k++] = a[i++];
	}
	while (j <= right)
	{
		arr[k++] = a[j++];
	}

	//将arr的值赋给a数组
	k = left;
	while (k <= right)
	{
		a[k] = arr[k];
		k++;
	}
}

void merge_sort(int* a, int left, int right)
{
	int mid = (left + right) / 2;
	if (left < right)
	{
		merge_sort(a, left, mid);
		merge_sort(a, mid + 1, right);
		merge(a, left, mid, right);
	}

}

int main()
{
	int a[] = {1,9,6,8,3,5,2,4};
	int n = sizeof(a) / sizeof(a[0]);
	int left = 0;
	int right = n - 1;
	merge_sort(a,left,right);

	for (int i = 0; i <= right; i++)
	{
		printf("%d ",a[i]);
	}
	return 0;
}

 

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值