`

归并算法详解

    博客分类:
  • java
阅读更多

MergeSort归并排序

[1] 归并排序的原理

1.1 将两个有序数组合并成一个有序数组

两个数组,每一个数组内部都是有序的,比如:
a{5,7} 和 b{6,11,37}

我们申请足够大的空间,来放排好序的数组。比如这个数组叫 c{}。

每次取两个数组中最小的数,进行比较,小的取出放入 c{}。
如此将两个数组中的元素都取完,全部放入 c{},c{} 中就是一个有序的数组。比如:

第1次:5和6比较,5较小,所以 a{7}, b{6,11,37} -> c{5}
第2次:7和6比较,6较小,所以 a{7}, b{11,37} -> c{5,6}
第3次:7和11比较,7较小,所以 a{}, b{11,37} -> c{5,6,7}
第4次:a{} 空了,所以 b{} 中剩下的都是排好序的大的,所以 a{}, b{} -> c{5,6,7,11,37}

1.2 递归产生有序数组

每次:把一个无序数组,分成前后两半(根据数组中的元素个数,就可以确定到哪里是一半),首先对前一半进行递归调用,然后对后一半进行递归调用。最后归并,产生一个完整的有序数组。

比如:{7, 5, 37, 6, 11},

一共有5个元素,5/2=2,所以分成 {7,5} {37,6,11}。

   对{7,5} 进行递归调用,一共有2个元素,2/2=1,所以分成 {7} {5}。
   对{7} 进行递归调用,发现到头了,返回。
   对{5} 进行递归调用,发现到头了,返回。
   于是归并 {7} {5},得到有序数组 {5,7},返回。

   对{37,6,11} 进行递归调用,一共有3个元素 3/2=1,所以分成 {37} {6,11}。
   对{37} 进行递归调用,发现到头了,返回。

   对{6,11} 进行递归调用,一共有2个元素 2/2=1,所以分成 {6} {11}。
     对{6} 进行递归调用,发现到头了,返回。
     对{11} 进行递归调用,发现到头勒,返回。
     于是归并 {6} {11},得到有序数组 {6,11},返回。

   于是归并 {37} {6,11},得到有序数组 {6,11,37},返回。

于是归并 {5,7} {6,11,37},得到有序数组 {5,6,7,11,37},返回。排序完成。

[2] 归并排序的实现

package testAlgorithm;

import java.util.Arrays;

/**
 * @author derek zhan
 * @version 
 */
@SuppressWarnings("unchecked")
public class MergeSortTest
{
    //排序中的临时数组
    private Comparable [] tmpArray ;
    
    public static void main(String[] args)
    {
        Integer [] obj = {1,4,7,2,5,8};
        MergeSortTest mst = new MergeSortTest();
        mst.sort(obj);
        System.out.println(Arrays.toString(obj));
        Integer[] obj2 = {8,5,2,7,4,1};
        mst.mergeSort2(obj2);
        System.out.println(Arrays.toString(obj2));
    }
    
    /** 
    * *利用归并排序算法对数组obj进行排序 
    */ 
    public void sort(Comparable[] obj) { 
        tmpArray = new Comparable[obj.length];// 初始化中间数组 
        mergeSort1(obj, 0, obj.length - 1); // 归并排序 
        tmpArray = null; 
    } 
    
    //第一个种方法
    /**
     * 递归划分成2个数组
     * @param obj 要排序的数组
     * @param left 数组中第一个元素下标
     * @param right 数组最后一个元素的下标
     */
    public void mergeSort1(Comparable[] obj,int left,int right){
        if(left < right){//只要不是数组的最后一个元素
            int center = (left+right)/2;
            mergeSort1(obj, left, center); //划分成左数组
            mergeSort1(obj, center+1, right);//划分成右数组
            merge1(obj, left, center, right);//合并2一个数组并排序
        }
    }
    //第二种方法
    public void mergeSort2(Comparable[] obj){
        int n = obj.length;
        if(n<=1) return; //如果只有一个元素则返回.
        Comparable left[] = new Comparable[n/2]; //左数组
        Comparable right[] = new Comparable[n-n/2];  //右数组
        for(int i=0,leftPos=left.length; leftPos<obj.length; i++,leftPos++){
            if(i<left.length){ //给左数组赋值
                left[i] = obj[i];
            }
            //给右数组赋值
            right[i] = obj[leftPos];
            
        }
        mergeSort2(left);
        mergeSort2(right);
        merge2(obj, left, right);
    }
    
    /**
     * 合并数组并排序
     * @param obj 要合并的数组
     * @param left 左边数组第一个元素下标
     * @param center 左边数组最后一个元素下标
     * @param right 右边数组最后一个元素下标
     */
    public void merge1(Comparable[] obj,int left,int center,int right){
        int midd = center+1;
        int temp = left;
        int third = left;
        while(left <= center && midd <= right){
            if(obj[left].compareTo(obj[midd])<=0){ //比较2个数组中的值,把小值放入临时数组
                tmpArray[third++] = obj[left++]; 
            }else{
                tmpArray[third++] = obj[midd++]; 
            }
        }
        //如果第一个数组已经全部比较完了,那么我们只要直接复制第二个数组的条目到合并数组中即可 
        while(midd<=right){
            tmpArray[third++] = obj[midd++]; 
        }
        //如果第二个数组已经全部比较完了,那么我们只要直接复制第一个数组的条目到合并数组中即可 
        while(left <= center){
            tmpArray[third++] = obj[left++]; 
        }
        //拷贝bridge to obj数组
        while(temp<=right){
            obj[temp] = tmpArray[temp];
            temp++;
        }
    }
    
    //第二种合并方法
    public void merge2(Comparable[] obj,Comparable[] left,Comparable[] right){
        int leftLength = left.length-1;
        int rightLength = right.length-1;
        int k=0; 
        int leftPos=0,rightPos=0; // left数组下标, right数组下标 
        while(leftPos<=leftLength||rightPos<=rightLength){ 
            Comparable temp = null; 
            if(leftPos>leftLength){  //如果第一个数组已经全部比较完了,那么我们只要直接复制第二个数组的条目到合并数组中即可 
                temp=right[rightPos++]; 
            }else if(rightPos>rightLength){  //如果第二个数组已经全部比较完了,那么我们只要直接复制第一个数组的条目到合并数组中即可 
                temp=left[leftPos++]; 
            }else if(left[leftPos].compareTo(right[rightPos])>0){  //把比较的两个条目中关键值小的放到合并数组中 
                temp=right[rightPos++]; 
            }else{ 
                temp=left[leftPos++]; 
            } 
            obj[k++]=temp; //把比较完的值放入数组
            } 
        } 
}

  

最后执行结果:

[1, 2, 4, 5, 7, 8]
[1, 2, 4, 5, 7, 8]

 

分享到:
评论

相关推荐

    归并算法思想总结

    ### 归并算法思想深度解析 归并算法是一种典型的分治策略在排序领域的应用,其核心思想在于将一个大规模的问题分解成若干个较小的、容易解决的子问题,然后将这些子问题的解合并,得到整个问题的解。在归并排序中,...

    归并排序算法详解与实现.zip

    `归并排序算法详解与实现.pdf`很可能是对归并排序算法的详细解释,包括原理、步骤、伪代码和可能的实现方式。而`项目说明.pdf`可能包含了如何使用这些源代码以及在不同场景下优化归并排序的建议。 通过深入学习这些...

    C语言实现排序算法之归并排序详解

    归并排序是一种基于分治策略的排序算法,它将大问题分解为小问题来解决,然后将小问题的结果合并以得到最终的解。在C语言中实现归并排序,主要涉及以下几个关键点: 1. **归并排序原理**: 归并排序的基本思想是将...

    归并排序算法实现

    ### 归并排序算法实现详解 #### 一、引言 归并排序是一种经典的排序算法,采用分治法的思想,将待排序数组分为若干个子序列,这些子序列是已排序的,然后再按照一定的方式合并这些子序列得到最终排序后的数组。...

    史上最清晰、最详细的归并排序算法详解:Java示例代码和逻辑解析 保证你是小白也能看懂

    **归并排序详解** 归并排序(Merge Sort)是一种基于分治策略的高效排序算法,它的核心思想是将大问题分解为小问题,再将小问题的解组合成原问题的解。具体来说,归并排序的过程包括两个主要步骤:分割(Divide)和...

    java 中归并排序算法详解

    Java 中归并排序算法详解 Java 中归并排序算法是一种时间复杂度为 O(N logN) 的排序算法,因而其在平常生活工作中应用非常广泛。下面是对 Java 中归并排序算法的详细解释: 算法思想 归并排序算法顾名思义,是一...

    算法详解课件

    【算法详解课件】 这份"算法详解课件"是一份非常适合初学者和在校生学习算法分析的资源。它深入浅出地介绍了算法的基础知识,帮助理解算法的核心概念和应用,对于期末复习尤其有帮助。算法是计算机科学的灵魂,是...

    C++实现的归并排序算法详解

    "C++实现的归并排序算法详解" 归并排序算法是建立在归并操作上的一种有效的排序算法,采用分治法(Divide and Conquer)来实现排序。该算法将已有序的子序列合并,得到完全有序的序列。其主要步骤包括:将待排序...

    C语言——链表的归并_c语言链表详解

    标题“C语言——链表的归并_c语言链表详解”和描述“用c语言写链表归并”明确指出了本文的主要内容:使用C语言实现链表的归并操作,并对C语言中的链表进行详细讲解。 #### 代码解析 ##### 1. 结构体定义 ```c ...

    经典7大排序算法详解

    ### 经典七大排序算法详解 #### 一、冒泡排序 冒泡排序是一种简单的排序算法,通过重复地遍历列表,比较每对相邻元素,若顺序错误则交换它们。遍历列表的工作会重复进行直到没有更多的交换需要,也就是说列表已经...

    C语言算法之归并排序C语言算法之归并排序

    ### C语言中的归并排序详解 #### 一、归并排序的基本概念与原理 归并排序是一种基于**分而治之**策略的经典排序算法。它将一个数组分成两半,递归地对每一半进行排序,然后将排序后的两部分合并成一个有序数组。 ...

    归并排序_归并排序_

    归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案&quot...

    C++归并排序详解以及代码实现

    归并排序(Merge Sort)是一种高效的排序算法,它利用了分治法的思想,将大问题分解为小问题来解决。其基本步骤包括分解、求解和合并。 1. 分解:归并排序首先将待排序的数组不断地平均分为两半,这个过程一直持续...

    数据结构实验报告-线性表-两个有序线性表的归并算法

    本次实验的主题是“数据结构实验报告-线性表-两个有序线性表的归并算法”。实验的主要目的是让学生掌握两个有序线性表的归并算法。具体来说,实验要求学生通过键盘输入数据来建立两个有序线性表,并最终将这两个有序...

    《Python算法详解》读书笔记模板.pptx

    "《Python算法详解》读书笔记模板.pptx" 《Python算法详解》读书笔记模板.pptx是基于Python算法的读书笔记模板,涵盖了Python算法的核心技术和知识点。本书共13章,涵盖了算法、数据结构、常用的算法思想、线性表、...

    源代码Python算法详解

    【源代码Python算法详解】是一份深度探讨Python编程语言中算法实现的资源,旨在帮助学习者深入理解并掌握各种常用算法。这份资料涵盖了从基础到高级的多种算法,结合源代码解析,使得学习过程更加直观和高效。在...

    12种排序算法详解(寒小阳博客转出PDF版)

    除了插入排序,本次详解还包括了其他11种常见的排序算法。这些算法根据其工作原理和性能特点被广泛应用于各种场景中: 1. 二分插入排序(Binary Insertion Sort):与普通插入排序相似,但在已排序部分使用二分查找...

Global site tag (gtag.js) - Google Analytics