归并排序算法【归并排序】C代码

归并排序算法【归并排序】C代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void arrPrintf(int* data, int length)
{
	for (size_t i = 0; i < length; i++)
	{
		if (i == length - 1)
			printf("%2d\n", data[i]);
		else
			printf("%2d, ", data[i]);
	}

}

//交换
void swap(int* data, int i, int j)
{
	int temp = data[i];
	data[i] = data[j];
	data[j] = temp;
}

//归并排序,先分区,在合并排序
void _mergeSort(int* data, int left, int right, int* tmp)
{
	static int index = 0;
	//先递归,不断分解数组
	//直到数组只剩下一个元素为止
	if (left == right) return;
	index++;
	printf(" [Index : %2d] ", index);

	//分成2段:[left,mid] [mid+1,right]
	//递归分割:
	int mid = (left + right) / 2;

	//打印
	for (int i = left; i <= right; i++)
	{
		if (i == left)
			printf("{ %2d, ", data[i]);
		else if (i == right)
			printf("%2d }\n", data[i]);
		else
			printf("%2d, ", data[i]);
	}

	_mergeSort(data, left, mid, tmp);
	_mergeSort(data, mid + 1, right, tmp);

	//归并处理,注意到这里就开始合并了
	//从左侧开始合并,将数据保存到临时数组里
	int begin1 = left, end1 = mid;
	int begin2 = mid + 1, end2 = right;
	int i = left;
	//2个有序数组合并
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (data[begin1] < data[begin2])
		{
			tmp[i++] = data[begin1++];
		}
		else
		{
			tmp[i++] = data[begin2++];
		}
	}
	
	//当剩余没有走完的,需要进行处理,
	//比如[1,2] [3,4] 进行合并时,当2进入临时数组后,此时下标已不满足要求
	//上面的while循环将会跳出,这时[3,4]还没进入临时数组,故需要继续处理
	while (begin1 <= end1)
	{
		tmp[i++] = data[begin1++];
	}

	while (begin2 <= end2)
	{
		tmp[i++] = data[begin2++];
	}
	
	//将tmp临时数组中相应区间的数据拷贝回原数组
	memcpy(data + left, tmp + left, sizeof(int) * (right - left + 1));
	
	//打印
	for (int i = left; i <= right; i++)
	{
		if (i == left)
			printf("【 %2d, ", data[i]);
		else if (i == right)
			printf("%2d 】\n", data[i]);
		else
			printf("%2d, ", data[i]);
	}

}

//归并排序
void mergeSort(int* data, int length)
{
	//申请临时内存
	int* tmp = (int*)malloc(sizeof(int) * length);
	if (tmp == NULL)
	{
		printf("malloc err!");
		return;
	}
	_mergeSort(data, 0, length - 1, tmp);

	//释放内存
	free(tmp);
	tmp = NULL;
}

int main()
{
	//归并排序
	printf("归并排序算法\n");

	/*
	稳定:若有2个相等的键值元素,在排序前后它们的相对位置保持不变,比如【2,3,5_a,5_b】(这里5_a,5_b为值相同的元素)
		  在排序后5_a依然在5_b前面,则相对位置保持;否则称为不稳定
	归位:比较过就可以确定元素的位置

	归并排序:稳定,不归位

	思路:
	1.将数组分割成2个数组,再分别将这2个数组再细分成2个数组,直到最后每一个数组都只有一个元素
	2.将分割的有序数组进行排序,排成有序数组后继续为上一个分割它的数组合并,直到数组合并成原来的数组
	3.排序完成后,最后将临时数组拷贝到原数组。

	在合并的时候,跟合并两个有序链表的操作差不多

	*/
	int data[] = { 2,5,29,15,39,98,41,3,55,55,20,78,18,88 };
	arrPrintf(data, sizeof(data) / sizeof(data[0]));
	mergeSort(data, sizeof(data) / sizeof(data[0]));
	arrPrintf(data, sizeof(data) / sizeof(data[0]));
	/*
	归并排序算法
	 2,  5, 29, 15, 39, 98, 41,  3, 55, 55, 20, 78, 18, 88
	 [Index :  1] {  2,  5, 29, 15, 39, 98, 41,  3, 55, 55, 20, 78, 18, 88 }
	 [Index :  2] {  2,  5, 29, 15, 39, 98, 41 }
	 [Index :  3] {  2,  5, 29, 15 }
	 [Index :  4] {  2,  5 }
	【  2,  5 】
	 [Index :  5] { 29, 15 }
	【 15, 29 】
	【  2,  5, 15, 29 】
	 [Index :  6] { 39, 98, 41 }
	 [Index :  7] { 39, 98 }
	【 39, 98 】
	【 39, 41, 98 】
	【  2,  5, 15, 29, 39, 41, 98 】
	 [Index :  8] {  3, 55, 55, 20, 78, 18, 88 }
	 [Index :  9] {  3, 55, 55, 20 }
	 [Index : 10] {  3, 55 }
	【  3, 55 】
	 [Index : 11] { 55, 20 }
	【 20, 55 】
	【  3, 20, 55, 55 】
	 [Index : 12] { 78, 18, 88 }
	 [Index : 13] { 78, 18 }
	【 18, 78 】
	【 18, 78, 88 】
	【  3, 18, 20, 55, 55, 78, 88 】
	【  2,  3,  5, 15, 18, 20, 29, 39, 41, 55, 55, 78, 88, 98 】
	*/

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值