归并排序(分治法)
归并排序,其实是采用常用的算法-分治法来实现的。 所谓的“分”,就是将一个问题分成很多小的问题来进行递归求解; "治",将各个阶段的小问题得到的答案,合并在一起,修补好,即所谓的分而治之。
下面我们来举一个简单的例子:
我们将排序一个数组:{5,2,1,4,6,8,3,7}
拆分阶段1:{5,2,1,4}, {6,8,3,7}
拆分阶段2:{5,2}, {1,4}, {6,8},{3,7}
处理拆分结果:{2,5}, {1,4}, {6,8},{3,7}
归并阶段1:{1,2,4,5},{3,6,7,8}
此时,我们可以得到两个有序的子序列,现在我们需要将这两个有序的子序列进行排序。
归并阶段2:
{1,2,4,5,3,6,7,8}
生命一个新的数组,存储最后的结果数组,比较子序列,值小的子序列指针右移:
①. 1 < 3 ,1将存入新数组,并且左边子序列指针右移 =》新数组:{1}
②. 2 < 3 , 2将存入新数组,并且左边子序列指针右移 =》新数组:{1,2}
③. 4 < 3 , 3将存入新数组,并且右边子序列指针右移 =》新数组:{1,2,3}
④. 4 < 6 , 4将存入新数组,并且左边子序列指针右移 =》新数组:{1,2,3,4}
⑤. 5 < 6 , 5将存入新数组,并且左边子序列指针右移 =》新数组:{1,2,3,4,5}
⑥. 最后将右边剩余的6,7,8依次存入新数组 =》新数组:{1,2,3,4,5,6,7,8}
其实,java中Arrays.sort()采用了一种名为TimSort的排序算法,就是归并排序的优化版本。
代码如下:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Test {
public static List<int[]> mergeArr = new ArrayList<int[]>();
public static int len;
public static void main(String[] args) {
Test test = new Test();
int []arr = {9,8,7,6,5,4,3,2,1};
len = arr.length;
test.points(arr);
arr = test.merge();
System.out.println();
for(int i=0; i<arr.length; i++){
System.out.print(arr[i]+" ");
}
}
/**
* 分
* @param
* @return
*/
public void points(int[] arr){
if(arr.length == 1){
mergeArr.add(arr);
return;
}
if(arr.length == 2){
Arrays.sort(arr);
mergeArr.add(arr);
return;
}
int arr1[];
int arr2[];
if(judgeParity(arr.length) == 1){
arr1 = new int[arr.length / 2 + 1];
arr2 = new int[arr.length / 2];
arr1 = arrayTransfer(0, arr.length / 2, arr);
arr2 = arrayTransfer(arr.length / 2 + 1, arr.length -1, arr);
}else{
arr1 = new int[arr.length / 2];
arr2 = new int[arr.length / 2];
arr1 = arrayTransfer(0, arr.length / 2 - 1 , arr);
arr2 = arrayTransfer(arr.length / 2, arr.length -1, arr);
}
points(arr1);
points(arr2);
}
/**
* 合
* @param
* @return
*/
public int[] merge(){
int arr[] = new int[len];
int n = 0;
for(int i=0; i<mergeArr.size(); i++){
for(int j=0; j<mergeArr.get(i).length; j++){
arr[n] = mergeArr.get(i)[j];
n++;
}
}
for(int i=0; i<arr.length; i++){
System.out.print(arr[i]+" ");
}
Arrays.sort(arr);
return arr;
}
/**
* 判断长度奇偶
* @param
* @return
*/
public int judgeParity(int length){
if(length%2 == 0){
return 2;
}else{
return 1;
}
}
/**
* 数组转移
* @param start 起始坐标,end 结束坐标
* @return
*/
public int[] arrayTransfer(int start, int end, int[] arr){
int length = end - start + 1;
int[] newArr = new int[length];
int j=0;
for(int i=start; i<=end; i++){
newArr[j] = arr[i];
j++;
}
return newArr;
}
}
希望小编写的东西对大家有所帮助,助大家学有所成。