排序算法之归并排序(java、python和C++实现)

原创 2018年04月16日 01:13:03

一、基本思想

     归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)而且充分利用了完全二叉树的深度是log2n + 1的特性,因此效率比较高。其算法原理如下:对于给定的一组记录,利用递归与分治技术将数据序列划分成为越来越小的子序列,再对子序列排序,最后再用递归方法将排好序的子序列合并成为越来越大的有序序列

二、复杂度分析

       一趟归并需要将数组 a[]中相邻的长度为h的有序序列进行两两归并.并将结果放到temp[]中,这需要将待排序列中的所有记录扫描一遍,因此耗费O(n),而又完全二叉树的深度可知,整个归并排序需要进行log2n次。因此总的时间复杂度为O(nlogn),而且这是归并排序算法中最好、最坏、平均的时间性能。

       由于归并排序在归并过程中需要与原始序列同样数量的存储空间存放归并结果以及递归时深度为log2n,空间复杂度为O(n+logn).

三、图文分析

以数组a[] = {14,12,15,13,11,16}为例,

经归并排序后得到的期望值:a[] = {11, 12, 13, 14, 15, 16}

以下拆分与归并过程图解:

注:图文来自另一篇博客:点击打开链接

四、算法设计思路

分而治之(divide - conquer);每个递归过程涉及三个步骤

第一, 分解: 把待排序的 n 个元素的序列分解成两个子序列, 每个子序列包括 n/2 个元素.

第二, 治理: 对每个子序列分别调用归并排序MergeSort, 进行递归操作

第三, 合并: 合并两个排好序的子序列,生成排序结果.

五、代码实现

1.java代码实现:

package merge;

import java.util.Arrays;

public class MergeSort {
	public static void main(String[] args) {
		int[] a = {14,12,15,13,11,16};
		//归并排序
		mergeSort(a,0,a.length - 1);
		//打印数组
		System.out.println(Arrays.toString(a));
	}
	//归并排序
	public static void mergeSort(int[] a, int low, int high){		
		if(low < high){
			int mid = low + (high - low)/2;//从中间拆分成左右两边
			mergeSort(a, low, mid);  //继续递归拆分左边的序列
			mergeSort(a, mid + 1, high);//继续递归拆分右边边的序列
			merge(a, low, mid, high);  //将两边的数据归并
		}
	}
	//归并算法
	private static void merge(int[] a, int low, int mid, int high) {
	        int i = low, j = mid + 1,k = 0;
                int[] temp = new int[high - low + 1];
                //左右边比较,数值小的数放入temp数组
                while(i <= mid && j <= high){
                    if(a[i] < a[j]) {
                        temp[k++] = a[i++];
                    }else{
                        temp[k++] = a[j++];
                    }
                }
                // 把左边剩余的数移入数组
                while(i <= mid)  temp[k++] = a[i++];
                // 把右边边剩余的数移入数组
                while(j <= high) temp[k++] = a[j++];
        
                // 把temp数组中的数覆盖a数组
                for (int k2 = 0; k2 < temp.length; k2++) {
                    a[k2 + low] = temp[k2];
                }
	}
}

2.python实现:

#归并排序
def mergeSort(a, low, high):
    if low < high:
        mid = (high + low) // 2     #取要排序的序列的中间位置
        mergeSort(a, low, mid)      #继续递归拆分左边序列
        mergeSort(a, mid + 1, high)  #继续递归拆分右边序列
        merge(a, low, mid, high)     #拆分后归并排序
        
#归并函数        
def merge(a, low, mid, high):
    i = low
    j = mid + 1   
    temp = []
    #左右边比较,数值小的数放入temp数组
    while i <= mid and j <= high :
        if a[i] < a[j] :
            temp.append(a[i])       
            i += 1 
        else:
            temp.append(a[j])
            j += 1
    #把左边剩余的数移入数组
    while i <= mid:
        temp.append(a[i])
        i += 1
    #把右边边剩余的数移入数组
    while j <= high:
        temp.append(a[j])
        j += 1
    #将temp列表中的数全部复制到原列表a中对应的索引位置
    for k in range(len(temp)):
        a[k + low] = temp[k]

a = [14,12,15,13,11,16]  #要排序的列表
mergeSort(a, 0, len(a) - 1)   
print(a)
3.C++实现(与java代码基本一致)
#include <iostream>
using namespace std;
	
//打印数组
void printArray(int a[], int len)
{
	for(int i = 0;i < len;i++)
	{
		cout<<a[i]<<" ";
	}
}

//归并算法
void merge(int a[], int low, int mid, int high) 
{
	 int i = low, j = mid + 1, k = 0, len = high - low + 1;
     int *temp = new int[len];
     //左右边比较,数值小的数放入temp数组
     while(i <= mid && j <= high)
	 {
		if(a[i] < a[j]) {
            temp[k++] = a[i++];
        }
		else{
            temp[k++] = a[j++];
        }
     }
     // 把左边剩余的数移入数组
     while(i <= mid)   temp[k++] = a[i++];
     // 把右边边剩余的数移入数组
     while(j <= high)  temp[k++] = a[j++];
        
     // 把temp数组中的数覆盖a数组
     for (int w = 0; w < len; w++) 
	 {
         a[w + low] = temp[w];
     }
}

//归并排序
void mergeSort(int a[], int low, int high)
{		
	if(low < high)
	{
		int mid = low + (high - low)/2;//从中间拆分成左右两边
		mergeSort(a, low, mid);  //继续递归拆分左边的序列
		mergeSort(a, mid + 1, high);//继续递归拆分右边边的序列
		merge(a, low, mid, high);  //将两边的数据归并
	}	
}


int main(int argc, char* argv[])
{
	int a[] = {14,12,15,13,11,16};
	int len = sizeof(a)/sizeof(int);  //计算数组a的长度
	mergeSort(a, 0 , len-1);    //归并排序
	printArray(a, len);          //打印数组
	return 0;
}

排序算法Java实现——归并排序

归并排序(也可以叫合并排序),其实归并排序的本质就是合并排序。 它是与插入排序、交换排序、选择排序不同的一类排序方法,不同之处在于: 它要求:待排序序列是由若干个有序子序列组成。 那么究竟什么是归并排...
  • singit
  • singit
  • 2017-04-25 22:09:04
  • 974

算法设计之归并排序(C++实现)

归并排序遵循分治法的思想:将
  • u011426031
  • u011426031
  • 2014-08-23 07:27:47
  • 3502

c++实现的归并排序算法

归并排序算法是一种稳定且速度仅次于快速排序的算法!
  • code_sdk2
  • code_sdk2
  • 2015-12-10 16:22:06
  • 564

【排序算法】归并排序原理及Java实现

归并排序就是利用归并的思想实现的排序方法。而且充分利用了完全二叉树的深度特性,因此效率比较高。其基本原理如下:对于给定的一组记录,利用递归与分治技术将数据序列划分成为越来越小的半子表,在对半子表排序,...
  • jianyuerensheng
  • jianyuerensheng
  • 2016-04-27 17:35:43
  • 17757

用Python实现八大排序算法--归并排序

一、归并排序概述1.归并排序将待排序序列R[0…n-1]看成是n个长度为1的有序序列,将相邻的有序表成对归并,得到n/2个长度为2的有序表;将这些有序序列再次归并,得到n/4个长度为4的有序序列;如此...
  • chibangyuxun
  • chibangyuxun
  • 2016-11-02 21:02:58
  • 842

[排序算法]--归并排序的Java实现

归并排序(2-路归并):归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用,归并排序将两个已排序的表合并成一个表。 下面先看...
  • u010853261
  • u010853261
  • 2017-02-06 16:14:50
  • 2003

快速排序、归并排序、大顶堆排序、希尔排序代码实现

快速排序 O(n*log2_n) O(log2_n) 不稳定 归并排序 O(n*log2_n) O(n) 稳定 大顶堆排序 O(n*log2_n) O(1) 不稳定 希尔排序 O(n*log2_n) ...
  • ls667
  • ls667
  • 2016-09-08 00:15:07
  • 344

【排序】归并排序(递归和非递归版本)

#include using namespace std; void merge(int* a, int* temp, int begin, int middle, int end){ int i...
  • ruan875417
  • ruan875417
  • 2016-05-14 13:47:36
  • 1122

C++ 排序算法(2)---归并

归并排序归并排序作为复杂度O(nlogn)的稳定排序方法在效率上是远超一般排序方法的。合并数组在说归并排序之前我们先考虑一个问题,如何合并两个有序数列并使其结果仍有序? 现在在一数组a中,前一半是递...
  • BIG_C_GOD
  • BIG_C_GOD
  • 2016-12-01 18:24:26
  • 1324

【Java常用排序算法】归并排序(二路归并排序)

归并排序 二路归并排序 Java实现
  • donggua3694857
  • donggua3694857
  • 2017-02-27 23:17:10
  • 3096
收藏助手
不良信息举报
您举报文章:排序算法之归并排序(java、python和C++实现)
举报原因:
原因补充:

(最多只允许输入30个字)