C++ Merge sort(归并排序)

归并排序(merge sort)是一个时间复杂度为O(nlogn)的基于比较的排序算法(comparison based sorting algorithm)。 归并排序大多数实现(implementation)都将其实现成了一个stable sort, 所谓的stable sort的意思就是the implementation preserves the input order of equal elements in the sorted order。

merge sort 也采用了divide and conquer(分治技术) 的排序算法。 由John von Neumann于1945年发明的。

我们知道, 快排序的平均情况下时间复杂度是O(nlogn), 最坏情况下为O(n^2)。 归并排序的好处就是时间复杂度总是O(nlogn).。 所以归并排序在时间方面可以beats quick sort。

下面对merge sort做出详细说明:

例如, 我们想要对如下数组精心排序:

merge sort 的思想是将一个problem break into 2 subproblems。

(1)divide the array into 2 equal halves(假如分隔位置在数组的中间(记为mid位置), mid 之前为the first subarray, 之后为the second subarray):

(2) 现在假如我们somehow 将这两个子数组排好序了, 接下来我们的任务就是将这两个子数组merge称为一个大的排好序的数组。 注意这三个数组时独立位于内存之中的(可见merge sort 的空间复杂度会比较大)。

我们的merge算法如下。 现在我们将上图左边的数组记为L, 右边的数组记为R。  首先第一步,比较L的第一个未选中的数据和R中第一个未选中的数据, 找出最小的数据, 为位于L中的1. 我们将这个值放在A中。 然后移动L的索引到下一个元素2, R的索引记录不懂, 比较, 发现2大, 将2 放到A的第二个位置。 在移动L中的索引, 到达4, R的不动, 4 比3大, 所以将3 放在A的第三个位置, 移动R的索引记录到下一个元素。 以此类推, 直至R(或者L)的元素均位于A中, 然后将L(或者R)剩余的元素均拷贝到A中。
即完成排序。

上述算法的伪代码如下:

现在我们说说如何排序。

解决办法是我们可以进一步的将数组或者list 进行进一步的细分:

到达最后一步的时候, 然后开始从下网上归并(merge)。

最终结果如下:

归并排序的伪代码如下:

程序如下:

/* Merge sort in C++ */
#include <cstdio>
#include <iostream>

using namespace std;

// Function to Merge Arrays L and R into A.
// lefCount = number of elements in L
// rightCount = number of elements in R.
void Merge(int *A,int *L,int leftCount,int *R,int rightCount) {
	int i,j,k;

	// i - to mark the index of left aubarray (L)
	// j - to mark the index of right sub-raay (R)
	// k - to mark the index of merged subarray (A)
	i = 0; j = 0; k =0;

	while(i<leftCount && j< rightCount) {
		if(L[i]  < R[j]) A[k++] = L[i++];
		else A[k++] = R[j++];
	}
	while(i < leftCount) A[k++] = L[i++];
	while(j < rightCount) A[k++] = R[j++];
}

// Recursive function to sort an array of integers.
void MergeSort(int *A,int n) {
	int mid,i, *L, *R;
	if(n < 2) return; // base condition. If the array has less than two element, do nothing.

	mid = n/2;  // find the mid index.

	// create left and right subarrays
	// mid elements (from index 0 till mid-1) should be part of left sub-array
	// and (n-mid) elements (from mid to n-1) will be part of right sub-array
	L = new int[mid];
	R = new int [n - mid];

	for(i = 0;i<mid;i++) L[i] = A[i]; // creating left subarray
	for(i = mid;i<n;i++) R[i-mid] = A[i]; // creating right subarray

	MergeSort(L,mid);  // sorting the left subarray
	MergeSort(R,n-mid);  // sorting the right subarray
	Merge(A,L,mid,R,n-mid);  // Merging L and R into A as sorted list.
	// the delete operations is very important
	delete [] R;
	delete [] L;
}

int main() {
	/* Code to test the MergeSort function. */

	int A[] = {6,2,3,1,9,10,15,13,12,17}; // creating an array of integers.
	int i,numberOfElements;

	// finding number of elements in array as size of complete array in bytes divided by size of integer in bytes.
	// This won't work if array is passed to the function because array
	// is always passed by reference through a pointer. So sizeOf function will give size of pointer and not the array.
	// Watch this video to understand this concept - http://www.youtube.com/watch?v=CpjVucvAc3g
	numberOfElements = sizeof(A)/sizeof(A[0]);

	// Calling merge sort to sort the array.
	MergeSort(A,numberOfElements);

	//printing all elements in the array once its sorted.
	for(i = 0;i < numberOfElements;i++)
	   cout << " " << A[i];
	return 0;
}

运行结果为:

NOTE: 在code::blocks 下可以调试, 单步运行, 打开watches 窗口查看各个变量

也可以查看call stack:

C++ Merge sort(归并排序)

时间: 2024-10-07 00:02:52

C++ Merge sort(归并排序)的相关文章

【Sort】Merge Sort归并排序

归并排序运行时间O(N log N),但是由于需要线性附加内存,所以很少用于主存排序. 算法核心在于以下三条语句,分治递归,分别对左半边和右半边的属组进行排序,然后把左右半边的属组一一进行比较放入数组 1 msort(nums,tmp,lp,center); 2 msort(nums,tmp,center+1,rp); 3 merge(nums,tmp,lp,center+1,rp); 下面是代码,主要包括三个函数: 1 void mergesort(int *nums,int n) 2 { 3

《算法导论》读书笔记之排序算法—Merge Sort 归并排序算法

自从打ACM以来也算是用归并排序了好久,现在就写一篇博客来介绍一下这个算法吧 :) 图片来自维基百科,显示了完整的归并排序过程.例如数组{38, 27, 43, 3, 9, 82, 10}. 在算法导论讲分治算法一章的时候提到了归并排序.首先,归并排序是一个分治算法. 归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表, 即把待排序序列分为若干个有序的子序列,再把有序的子序列合并为整体有序序列. merg() 函数是用来合并两个已有序的数组.  是整个算法的关键. 那么归并

[算法]——归并排序(Merge Sort)

归并排序(Merge Sort)与快速排序思想类似:将待排序数据分成两部分,继续将两个子部分进行递归的归并排序:然后将已经有序的两个子部分进行合并,最终完成排序.其时间复杂度与快速排序均为O(nlogn),但是归并排序除了递归调用间接使用了辅助空间栈,还需要额外的O(n)空间进行临时存储.从此角度归并排序略逊于快速排序,但是归并排序是一种稳定的排序算法,快速排序则不然. 所谓稳定排序,表示对于具有相同值的多个元素,其间的先后顺序保持不变.对于基本数据类型而言,一个排序算法是否稳定,影响很小,但是

排序算法二:归并排序(Merge sort)

归并排序(Merge sort)用到了分治思想,即分-治-合三步,算法平均时间复杂度是o(nlgn). (一)算法实现 1 private void merge_sort(int[] array, int first, int last) { 2 if (first + 1 < last) { 3 int mid = (first + last) / 2; 4 merge_sort(array, first, mid); 5 merge_sort(array, mid, last); 6 7 /

经典排序算法 - 归并排序Merge sort

经典排序算法 - 归并排序Merge sort 原理,把原始数组分成若干子数组,对每个子数组进行排序, 继续把子数组与子数组合并,合并后仍然有序,直到所有合并完,形成有序的数组 举例 无序数组[6 2 4 1 5 9] 先看一下每一个步骤下的状态,完了再看合并细节 第一步 [6 2 4 1 5 9]原始状态 第二步 [2 6] [1 4] [5 9]两两合并排序,排序细节后边介绍 第三步 [1 2 4 6] [5 9]继续两组两组合并 第四步 [1 2 4 5 6 9]合并完成,排序完成 输出结

1.7 逆序数与归并排序[inversion pairs by merge sort]

[本文链接] http://www.cnblogs.com/hellogiser/p/inversion-pairs-by-merge-sort.html [题目] 编程之美1.7光影切割问题可以进一步将问题转化为求逆序数问题. [分析] 求解逆序对问题与MergeSort类似,只需要对MergeSort稍作修改即可实现.MergeSort是采用分治法的思想,若需要排序A[p...r],则可以对半分成A[p...q]和A[q...r],然后将这有序的两部分Merge,而Merge的过程为Θ(n)

编程算法 - K路归并排序(k-way merge sort) 代码(C++)

K路归并排序(k-way merge sort) 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy K路归并排序作为经典的外部排序算法, 是程序员必须要掌握的. 知识概念参考: <数据结构> 主要思想: 在k个已排序的文件中, 选择第一个值, 采用败者树, 更新二叉树结构, 最终选择最优值. 代码仅供参考, 如最小值用(-1)代替, 最大值用(100)代替. /* * main.cpp * * Created on: 2014年9月11日 *

【 python 学习笔记 -- 数据结构与算法 】归并排序 Merge Sort

[归并排序]这里我们利用递归算法不断地将列表一分为二,base case就是列表中没有元素或者只剩一个元素,因为此时这个子列表必然是正序的:然后再逐步把两个排序完成的子列表合并成一个新的正序列表,直到所有元素排序完毕. [示意图]这是一个从下至上的过程(Bottom-Up) 将列表不断从中间分成两个子列表,直到到达最底部,子列表中只有一个元素 然后,从下至上不断合并两个子列表,将两个子列表的所有元素排序形成一个新的列表. [ implementation of merge sort ] 可以利用

排序 起泡排序(bubble sort),归并排序(merge sort)

1,起泡排序(bubble sort),大致有三种算法 基本版,全扫描. 提前终止版,如果发现前区里没有发生交换,就说明前区已经有序了,直接终止了.但是有个效率低下的地方,就是右边界hi是每次循环向前移动一个单元 跳跃版,在提前终止版的基础上,解决右边界hi移动效率低下的问题.解决思路:每次循环后,记录下最后一次的交换位置A,然后让hi=交换位置A,所以hi就可以跳跃移动多个单元了. 基本版代码实现 //冒泡排序(基本版 效率低下) template<typename T> void Vect