03归并排序

1.基本思想

归并排序(Merge Sort)的核心是分治,将一个复杂问题分解成多个相同或相似的子问题,然后把子问题分解成更小的问题,知道子问题可以简单地求解,最原始问题的解就是子问题解的合并。

一开始先将数组从中间分成两个子数组,一直递归把子数组划分成更小的子数组,直到子数组里只包含一个元素,这时才开始排序。排序的方法就是按照大小的顺序合并两个元素,接着依次按照递归返回的顺序,不断合并排好序的子数组,直到最后把整个数组的顺序排好。

例题:利用归并排序算法对数组 [2, 1, 7, 9, 5, 8] 进行排序。
归并排序动画

2.C++代码实现

编译环境:win10系统,vs2013

#include <iostream>
#include <vector>
using namespace std;

//合并函数
void merge(vector<int> &arr, int l, int m, int r) {
	vector<int> arr_copy(arr);

	//定义一个变量k,表示从什么位置开始改变原来的数组
	//i表示左边部分的起始位置的下标,j表示右边部分的起始位置的下标
	int k = l, i = l, j = m + 1;
	while (k <= r) {
		if (i > m) {
			arr[k++] = arr_copy[j++];
		}
		else if (j > r) {
			arr[k++] = arr_copy[i++];
		}
		else if (arr_copy[i] > arr_copy[j]) {
			arr[k++] = arr_copy[j++];
		}
		else {
			arr[k++] = arr_copy[i++];
		}
	}
}
//归并排序
void mergeSort(vector<int> &arr, int l, int r) {
	//判断是否只剩下一个元素
	if (l >= r) return;

	//将数组从中间分成两部分呢
	int m = l + (r - l) / 2;
	mergeSort(arr, l, m);
	mergeSort(arr, m + 1, r);

	//将排好序的左右两半合并
	merge(arr, l, m, r);
}

//打印vector
void printVector(vector<int> &v) {
	for (auto &i : v)
		cout << i << " ";
	cout << endl;
}
int main()
{
	vector<int> vec = { 2, 1, 7, 9, 5, 8 };
	cout << "给定数组为:";
	printVector(vec);

	mergeSort(vec, 0, vec.size() - 1);
	cout << "归并排序后:";
	printVector(vec);
	system("pause");
	return 0;
}

merge函数中,While 语句中,while的结束条件为k<=l,一共可能会出现四种情况。

  • 左半边的数都处理完毕,只剩下右半边的数,只需要将右半边的数逐个拷贝过去。
  • 右半边的数都处理完毕,只剩下左半边的数,只需要将左半边的数逐个拷贝过去就好。
  • 右边的数小于左边的数,将右边的数拷贝到合适的位置,j 指针往前移动一位。
  • 左边的数小于右边的数,将左边的数拷贝到合适的位置,i 指针往前移动一位。

输出

给定数组为:2 1 7 9 5 8
归并排序后:1 2 5 7 8 9
请按任意键继续. . .

3.算法分析

空间复杂度:O(n)
由于合并n个元素需要额外分配一个大小为n的数组,合并完成后释放,所以算法的空间复杂度为O(n)。归并排序也是稳定的排序算法
时间复杂度:O(nlogn)
归并排序是一种递归算法,时间复杂度可以表示为以下递归关系:T(n) = 2×T(n/2) + O(n)
公式解释:
举例:数组的元素个数是 n,时间复杂度是T(n)的函数。
解法:把这个规模为n的问题分解为两个规模为n/2的子问题,每个子问题的时间复杂度为T(n/2),则两个子问题的复杂度之和为2xT(n/2)。当两个子数组都排好序了,需要将它们合并,一共有n个元素,需要进行n-1次的比较,所以合并的复杂度为O(n)。因此递归复杂度的公式为:T(n) = 2×T(n/2) + O(n)

对于公式的求解,是将规模为n的问题分解为规模为n/2的问题,一直分解为规模为1。如果n为2,需要分1次,如果n为4,需要分2次,以此类推,如果规模就为n,则需要分logn次。而在每一次的合并中,所涉及到的元素就是数组中的所有元素,因此每次合并的复杂度都是O(n)。所有整体的复杂度为O(nlogn)

4.参考博客

  1. Merge Sort
发布了20 篇原创文章 · 获赞 16 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/m0_38059875/article/details/104147193