转载

归并排序

归并排序

归并排序,是一种效率十分高的排序算法,并且它是稳定的,时间复杂度为O(n*log(n))

归并排序主要的思想就是分治(问题转换为子问题)

算法过程

假设我们有一个没有排好序的序列,那么首先我们使用分割的办法将这个序列分割成一个个已经排好序的子序列。然后再利用归并的方法将一个个的子序列合并成排序好的序列。分割和归并的过程可以看下面的图例。

图片

时间复杂度

总时间=分解时间+解决问题时间+合并时间。分解时间就是把一个待排序序列分解成两序列,时间为一常数,时间复杂度o(1).解决问题时间是两个递归式,把一个规模为n的问题分成两个规模分别为n/2的子问题,时间为2T(n/2).合并时间复杂度为o(n)。总时间T(n)=2T(n/2)+o(n).这个递归式可以用递归树来解,其解是o(nlogn).此外在最坏、最佳、平均情况下归并排序时间复杂度均为o(nlogn).从合并过程中可以看出合并排序稳定。

用递归树的方法解递归式T(n)=2T(n/2)+o(n):假设解决最后的子问题用时为常数c,则对于n个待排序记录来说整个问题的规模为cn。

从这个递归树可以看出,第一层时间代价为cn,第二层时间代价为cn/2+cn/2=cn…每一层代价都是cn,总共有logn+1层。所以总的时间代价为cn*(logn+1).时间复杂度是o(nlogn).

C++代码

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

int mergeSort(int *a, int start, int end) {
	if(start >= end) return 0;
	
    /*划分*/
	int mid = (start + end) >> 1;
	mergeSort(a, start, mid);
	mergeSort(a, mid+1, end);
	
   /*合并*/
	vector<int> b;
	int i = start, j = mid+1;
		
	while(i <= mid && j <= end) {
		if(a[j] < a[i]) {
			b.push_back(a[j]);
			j++;
		} else {
			b.push_back(a[i]);
			i++;
		}
	}
	
	while(i <= mid) {
		b.push_back(a[i]); i++;
	}
	while(j <= end) {
		b.push_back(a[j]); j++;
	}
	
	for(int k = start; k <= end; k++)
		a[k] = b[k-start];
		
	return 0;
}
int main() {
	int a[10] = {1, 2, 0, 1, 7, 6, 4, 7, 5, 5};
	mergeSort(a, 0, 9);
	
	for(int i = 0; i < 10; i++) printf("%d ", a[i]);
} 
正文到此结束
本文目录