一、概述
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]
源码下载地址:点击打开链接