归并排序算法剖析,附java源代码

思路:

所谓的归并排序就是将二分查找和动态规划相结合的算法。

假设当前为顺序排序

通过对m个元素的数组进行排序,排序到n次,将产生n个有序数组,遍历第n+1次,通过二分查找在n个有序数组中找到比当前m[n+1]的数最左侧的数【2分查找】,记录该元素位置知道遍历m次整个数组都是有序的【动态规划】

归并排序过程样例:

初始数组

[3,6,8,7,4,1,5,11,9,39,21,34,52,12,32]

3,6,8,7,4,1,5,11,9,39,21,34,52,12,32,第1次排序;

比较过程 比较开始—[compare,mid0|,3:6]—-比较结束.i:1,mid:0,low:1,high:0…

本次比较不需要位移

当次数组值为:3,6,8,7,4,1,5,11,9,39,21,34,52,12,32,

3,6,8,7,4,1,5,11,9,39,21,34,52,12,32,第2次排序;

比较过程 比较开始—[compare,mid0|,3:8][compare,mid1|,6:8]—-比较结束.i:2,mid:1,low:2,high:1…

本次比较不需要位移

当次数组值为:3,6,8,7,4,1,5,11,9,39,21,34,52,12,32,

3,6,8,7,4,1,5,11,9,39,21,34,52,12,32,第3次排序;

比较过程 比较开始—[compare,mid1|,6:7][compare,mid2|,8:7]—-比较结束.i:3,mid:2,low:2,high:1…

开始进行移动:从下标2开始移动至3结束move,

当次数组值为:3,6,7,8,4,1,5,11,9,39,21,34,52,12,32,

3,6,7,8,4,1,5,11,9,39,21,34,52,12,32,第4次排序;

比较过程 比较开始—[compare,mid1|,6:4][compare,mid0|,3:4]—-比较结束.i:4,mid:0,low:1,high:0…

开始进行移动:从下标1开始移动至4结束move,move,move,

当次数组值为:3,4,6,7,8,1,5,11,9,39,21,34,52,12,32,

3,4,6,7,8,1,5,11,9,39,21,34,52,12,32,第5次排序;

比较过程 比较开始—[compare,mid2|,6:1][compare,mid0|,3:1]—-比较结束.i:5,mid:0,low:0,high:-1…

开始进行移动:从下标0开始移动至5结束move,move,move,move,move,

当次数组值为:1,3,4,6,7,8,5,11,9,39,21,34,52,12,32,

1,3,4,6,7,8,5,11,9,39,21,34,52,12,32,第6次排序;

比较过程 比较开始—[compare,mid2|,4:5][compare,mid4|,7:5][compare,mid3|,6:5]—-比较结束.i:6,mid:3,low:3,high:2…

开始进行移动:从下标3开始移动至6结束move,move,move,

当次数组值为:1,3,4,5,6,7,8,11,9,39,21,34,52,12,32,

1,3,4,5,6,7,8,11,9,39,21,34,52,12,32,第7次排序;

比较过程 比较开始—[compare,mid3|,5:11][compare,mid5|,7:11][compare,mid6|,8:11]—-比较结束.i:7,mid:6,low:7,high:6…

本次比较不需要位移

当次数组值为:1,3,4,5,6,7,8,11,9,39,21,34,52,12,32,

1,3,4,5,6,7,8,11,9,39,21,34,52,12,32,第8次排序;

比较过程 比较开始—[compare,mid3|,5:9][compare,mid5|,7:9][compare,mid6|,8:9][compare,mid7|,11:9]—-比较结束.i:8,mid:7,low:7,high:6…

开始进行移动:从下标7开始移动至8结束move,

当次数组值为:1,3,4,5,6,7,8,9,11,39,21,34,52,12,32,

1,3,4,5,6,7,8,9,11,39,21,34,52,12,32,第9次排序;

比较过程 比较开始—[compare,mid4|,6:39][compare,mid6|,8:39][compare,mid7|,9:39][compare,mid8|,11:39]—-比较结束.i:9,mid:8,low:9,high:8…

本次比较不需要位移

当次数组值为:1,3,4,5,6,7,8,9,11,39,21,34,52,12,32,

1,3,4,5,6,7,8,9,11,39,21,34,52,12,32,第10次排序;

比较过程 比较开始—[compare,mid4|,6:21][compare,mid7|,9:21][compare,mid8|,11:21][compare,mid9|,39:21]—-比较结束.i:10,mid:9,low:9,high:8…

开始进行移动:从下标9开始移动至10结束move,

当次数组值为:1,3,4,5,6,7,8,9,11,21,39,34,52,12,32,

1,3,4,5,6,7,8,9,11,21,39,34,52,12,32,第11次排序;

比较过程 比较开始—[compare,mid5|,7:34][compare,mid8|,11:34][compare,mid9|,21:34][compare,mid10|,39:34]—-比较结束.i:11,mid:10,low:10,high:9…

开始进行移动:从下标10开始移动至11结束move,

当次数组值为:1,3,4,5,6,7,8,9,11,21,34,39,52,12,32,

1,3,4,5,6,7,8,9,11,21,34,39,52,12,32,第12次排序;

比较过程 比较开始—[compare,mid5|,7:52][compare,mid8|,11:52][compare,mid10|,34:52][compare,mid11|,39:52]—-比较结束.i:12,mid:11,low:12,high:11…

本次比较不需要位移

当次数组值为:1,3,4,5,6,7,8,9,11,21,34,39,52,12,32,

1,3,4,5,6,7,8,9,11,21,34,39,52,12,32,第13次排序;

比较过程 比较开始—[compare,mid6|,8:12][compare,mid9|,21:12][compare,mid7|,9:12][compare,mid8|,11:12]—-比较结束.i:13,mid:8,low:9,high:8…

开始进行移动:从下标9开始移动至13结束move,move,move,move,

当次数组值为:1,3,4,5,6,7,8,9,11,12,21,34,39,52,32,

1,3,4,5,6,7,8,9,11,12,21,34,39,52,32,第14次排序;

比较过程 比较开始—[compare,mid6|,8:32][compare,mid10|,21:32][compare,mid12|,39:32][compare,mid11|,34:32]—-比较结束.i:14,mid:11,low:11,high:10…

开始进行移动:从下标11开始移动至14结束move,move,move,

当次数组值为:1,3,4,5,6,7,8,9,11,12,21,32,34,39,52,

代码样例:

package com.qunar;

 

import java.util.Collection;

import java.util.Collections;

import java.util.HashMap;

import java.util.List;

 

/**

* Created by yubin.qi on 2015/4/29.

*/

public class DichotomySort {

 

// 算法思想简单描述: 在插入第i个元素时,对前面的0~i-1元素进行折半,先跟他们 中间的那个元素比,如果小,则对前半再进行折半,否则对后半 进行折半,直到left>right,然后再把第i个元素前1位与目标位置之间 的所有元素后移,再把第i个元素放在目标位置上。

// 二分法排序最重要的一个步骤就是查找要插入元素的位置,也就是要在哪一个位置上放我们要准备排序的这个元素。

// 当我们查找到位置以后就很好说了,和插入排序一样,将这个位置以后的所有元素都向后移动一位。这样就实现了二分法排序。

//   然后是怎么查找着一个位置呢,就是不断的比较已排序的序列中的中间元素和要排序元素,如果大于的话,说明这个要排

// 序的元素在已排序序列中点之前的序列。

 

public static void main(String args[]) {

 

int[] is = new int[]{3, 6, 8, 7, 4, 1, 5, 11, 9, 39, 21, 34, 52, 12, 32};

 

DichotomySort(is);

 

for (int temp : is) {

System.out.println(temp);

}

 

}

 

 

//

 

public static void DichotomySort(int[] array) {

 

int i, j;

int low, high, mid;

mid = 0;

int temp;

for (= 1; i < array.length; i++) {

 

temp = array[i];

low = 0;

high = i - 1;

for (int temp1 : array) {

System.out.print(temp1 + ",");

 

}

//该算法的精髓是确定需要移动几位到中间值 每次排序能保证中间值之前是有序的所以考虑当前值移动几位到中间值

//如果起始游标 小于或者等于结束游标时一致循环直到结束游标大于起始游标

//例子

//------>起------<结 (循环)

//------<结>起------ (完毕)

System.out.println("第" + (i) + "次排序;");

boolean x = true;

while (low <= high) {

if (x) {

= false;

System.out.print("比较过程 比较开始---");

}

 

//每次该变量均会在上一次折半的基础上再次折半

mid = (low + high) / 2;

System.out.print("[compare,mid" + mid + "|," + array[mid] + ":" + temp + "]");

 

if (array[mid] > temp) {

//如果当前值大于需要比对的值,结束游标值在中值这块往前位移,找到比该值更小的值

high = mid - 1;

} else {

//如果当前值小于或者等于需要比对的值,起始游标值在中值这块往后挪动一位

low = mid + 1;

}

}

 

System.out.print("----比较结束");

 

System.out.print(".i:" + i + ",mid:" + mid + ",low:" + low + ",high:" + high + "...\r\n");

if (high == i - 1)

System.out.print("本次比较不需要位移");

else

System.out.print("开始进行移动:从下标" + (high+1) + "开始移动至下标"+i+"结束");

for (= i - 1; j > high; j--) {

System.out.print("move,");

array[+ 1] = array[j];

}

 

 

array[high + 1] = temp;

System.out.println();

System.out.print("当次数组值为:");

for (int temp1 : array) {

System.out.print(temp1 + ",");

 

}

System.out.println();

System.out.println();

 

}

 

}

 

}

点赞