归并排序
归并排序算法思想:
归并排序(
MERGE-SORT
)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer
)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。 归并排序核心步骤:
思路:
数据:
10 6 7 1 3 9 4
(7
个元素,下标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
然后可以继续像上面这样分,直到全部分成一个一个的数据。
递归的话也是递归到这个时候结束,然后往上返回。
那么,对于
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
然后往上返回。
然后我们新创建一个数组来存放这些数:
6 10 1 7, 3 9 4
然后往上返回。
然后把
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;
}
归并排序特性总结:
- 时间复杂度:O(nlogn)
- 空间复杂度:O(n)