java数据结构与算法-高级排序-归并排序

来源:互联网 发布:巨大物体恐惧症 知乎 编辑:程序博客网 时间:2024/06/16 14:05

一、概述

1、基本思想:归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,将每个子序列排成有序的。然后再把有序子序列合并为整体有序序列。
2、算法流程:(迭代+两个有序数列合并为一个有序数列)
3、时间复杂度:O(nlog(n)),归并算法是一种稳定排序算法。
4、归并排序示例:

 

二、归并排序实现代码如下:

package com.tool.wpn.quicksort;import android.util.Log;/** * Created by Xi on 2017/8/12. * 归并排序 */public class ArrayMerge {    private long[] theArray;//需排序的数组    private int nElems;//数组所函元素大小    public ArrayMerge(int max){        theArray=new long[max];        nElems=0;    }    /**     * 插入元素     * @param value     */    public void insert(long value){        theArray[nElems]=value;        nElems++;    }    /**     * 展示数组     */    public void display(){        StringBuilder sb=new StringBuilder();        sb.append("[");        for(int i=0;i<nElems;i++){            if(i==nElems-1)                sb.append(theArray[i]);            else {                sb.append(theArray[i]);                sb.append(",");            }        }        sb.append("]");        Log.v("ArrayMerge",sb.toString());    }    /**     * 归并开始排序     */    public void mergeSort(){        long[] workSpace=new long[nElems];//创建一个数组空间,用户归并排序使用        recMergeSort(workSpace,0,nElems-1);    }    /**     *左右拆分数组与归并     * 界限范围都使用的是数组下标     */    private void recMergeSort(long[] workSpace,int lowerBound,int upperBound){        if(lowerBound==upperBound)return;//若左边界==右边界,退出,即以划分为最小部分,无法再左右划分        else{            int mid=(lowerBound+upperBound)/2;            recMergeSort(workSpace,lowerBound,mid);//递归前半部分排序处理            recMergeSort(workSpace,mid+1,upperBound);//递归后半部分排序处理            merge(workSpace,lowerBound,mid+1,upperBound);        }    }    /**     * 将左右排序完的数组合并成一个     * @param workspace     * @param lowPtr     * @param highPtr     * @param upperBound     */    private void merge(long[] workspace,int lowPtr,int highPtr,int upperBound){        int j=0;        int lowerBound=lowPtr;        int mid=highPtr-1;        int n=upperBound-lowerBound+1;//要归并的数量,由于lowerBound代表的数组下角标,所以需要加1        while(lowPtr<=mid&&highPtr<=upperBound){//从左半部分的起点,又半部分起点,开始比对大小,直到左半部分或右半部分元素比对完即结束循环            if(theArray[lowPtr]<theArray[highPtr])                workspace[j++]=theArray[lowPtr++];            else                workspace[j++]=theArray[highPtr++];        }        while(lowPtr<=mid)//若左半部分未循环比较完,则将剩下的部分元素添加排序完的数组中            workspace[j++]=theArray[lowPtr++];        while(highPtr<=upperBound)//若右半部分未循环比较完,则将剩下的元素添加到排序完的数组中            workspace[j++]=theArray[highPtr++];        for(j=0;j<n;j++)            theArray[lowerBound+j]=workspace[j];//将排序完毕的元素复制到theArry真正在的位置中    }}


二、主调用函数如下:


 /**     * 归并排序,使用递归     * 原理为:使用递归原理,将数组从中间分为两部分,然后分别对左右两部分进行排序,然后再将左右两部分进行合并。     * 具体步骤就是,先将数组从中间利用递归分为左右,直到分成最小的左右部分,即左1个元素,右一个元素。     * 然后再将划分的最小部分进行合并,合并成有序。     * 按照上一步的合并办法,从小范围到大范围,最终合并成有序的数组。     * 时间复杂度为:O(N*logN),即需排序的数组大小为10000,则需要40000     */    private void sortMerge(){        ArrayMerge array=new ArrayMerge(20);        array.insert(20);        array.insert(10);        array.insert(30);        array.insert(40);        array.insert(5);        array.insert(7);        array.insert(50);        array.insert(90);        array.insert(110);        array.insert(8);        array.insert(130);        array.insert(70);        array.display();        array.mergeSort();        array.display();    }

日志打印如下:

08-15 10:35:17.334 25472-25472/com.tool.wpn.quicksort V/ArrayMerge: [20,10,30,40,5,7,50,90,110,8,130,70]
08-15 10:35:17.335 25472-25472/com.tool.wpn.quicksort V/ArrayMerge: [5,7,8,10,20,30,40,50,70,90,110,130]

源码下载地址:点击打开链接

原创粉丝点击