【初阶数据结构题目】39. 归并排序

归并排序

归并排序算法思想:

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。 归并排序核心步骤:

45fedca89a7046dfaa8bd24a4bb1962d

思路:

数据:10 6 7 1 3 9 47个元素,下标0-6


定义left,right,mid三个变量

left指向下标0的元素

right指向下标6的元素

mid=(left+right)/2


[left,mid]:10 6 7 1

[mid+1,right]:3 9 4


然后可以继续像上面这样分,直到全部分成一个一个的数据。

递归的话也是递归到这个时候结束,然后往上返回。

12653da879b1489b83c1bee59b5dfe19

那么,对于10 6这两个数字组成的数组,我们怎么把他排序成6 10呢?


left指向下标0的元素

right指向下标1的元素

mid=(left+right)/2=0


[left,mid]:[0,0] 10

[mid+1,right]:[1,1] 6

其他几个数据也一样

然后我们新创建一个数组来存放这些数:6 10, 1 7, 3 9, 4

然后往上返回。

ff57a163facec37b1c08ffb00046f857

然后我们新创建一个数组来存放这些数:6 10 1 7, 3 9 4

然后往上返回。

4815ea9722df416e7c9556c5d54bcd0e

然后把tmp中的数据拷贝回arr

销毁tmp

代码:

Sort.h

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include<stdlib.h>
#include<time.h>
#include <stdbool.h>
#include <assert.h>

//打印
void PrintArr(int* arr, int n);
//归并排序
void MergeSort(int* arr, int n);

Sort.c

#include"Sort.h"

//打印
void PrintArr(int* arr, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}

//归并排序
void _MergeSort(int* arr, int left, int right, int* tmp)
{
	if (left >= right)//分解到只有一个数据的时候就结束了
	{
		return;
	}
	int mid = (left + right) / 2;//中间下标
	//[left,mid] [mid+1,right]
	//不断二分
	_MergeSort(arr, left, mid, tmp);
	_MergeSort(arr, mid + 1, right, tmp);


	//合并
	//[left,mid] [mid+1,right]
	//表示两个区间
	int begin1 = left, end1 = mid;
	int begin2 = mid + 1, end2 = right;
	int index = begin1;//定义tmp数组的下标

	while (begin1 <= end1 && begin2 <= end2)
	{
		if (arr[begin1] < arr[begin2])//比较arr[begin1] 和 arr[begin2]的大小
		{
			tmp[index++] = arr[begin1++];//先往tmp里面插入小的
		}
		else {
			tmp[index++] = arr[begin2++];//然后往tmp里面插入大的
		}
	}
	//跳出循环:要么begin1越界  要么begin2越界
	while (begin1 <= end1)//begin2越界,begin1没有越界
	{
		tmp[index++] = arr[begin1++];//继续插入
	}
	while (begin2 <= end2)//begin1越界,begin2没有越界
	{
		tmp[index++] = arr[begin2++];
	}

	//[left,mid] [mid+1,right]
	//把tmp中的数据拷贝回arr中
	for (int i = left; i <= right; i++)
	{
		arr[i] = tmp[i];
	}
}

void MergeSort(int* arr, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);//合并的放在新创建的新数组里,大小是原来数组的空间

	_MergeSort(arr, 0, n - 1, tmp);

	free(tmp);//使用完了要释放掉空间
}

test.c

#include"Sort.h"

int main()
{
	int a[] = { 5, 3, 9, 6, 2, 4, 7, 1, 8 };
	int n = sizeof(a) / sizeof(int);
	printf("排序前:");
	PrintArr(a, n);

	MergeSort(a, n);

	printf("排序后:");
	PrintArr(a, n);


	TestOP();

	return 0;
}

归并排序特性总结:

  1. 时间复杂度:O(nlogn)
  2. 空间复杂度:O(n)
  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值