-
归并排序
-
@author dingwei2
*/
public class MergeSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
testMergeSort();
// int[] a = new int[] {2,5,16,21,1,4,7,10,22 };
// int[] tmp = new int[a.length];
// merge(a,0,4,8, tmp);
// testMerge();
}
/**
- 测试案例
*/
public static void testMergeSort() {
int[] a = new int[] {1,8,7,16,4,9,15,12};
testMergeSort(a);
int[] b = new int[] {1};
testMergeSort(b);
int[] c = new int[] {1,7,9,5,6,7,9};
testMergeSort©;
}
private static void testMergeSort(int[] a) {
System.out.println(“待排序序列:”);
for(int i : a) {
System.out.print(i + " ");
}
System.out.println("");
int[] tmp = new int[a.length];
mergeSort(a, 0, a.length -1, tmp);
System.out.println(“排序后的序列:”);
for(int i : a) {
System.out.print(i + " ");
}
System.out.println("");
}
/**
- 归并排序,
*/
public static final void mergeSort(int[] source, int startInx, int endInx, int[] tmp) {
if( startInx != endInx ) { // startInx == endInx,说明不可再分
// mid 所在的元素放在下半区 [startInx, mid) [mid,endInx]
int mid = ((endInx - startInx ) >> 1) + 1 + startInx;
mergeSort(source, startInx, mid - 1, tmp); // 将左边部分继续拆分 mid 所在元素放下半区 [startInx, mid)
mergeSort(source, mid, endInx, tmp); // 将右边部分继续拆分 mid 所在元素放下半区 [mid,endInx]
merge(source, startInx, mid, endInx, tmp);
//为什么是放在这里呢?就是归并排序的第一阶段,就是拆分元成一个有序序列(包含单个元素)。分解后的的元素,其实可以看出如下图
/*
-
待排序序列 1,5,6,2,3,7,4
-
递归排序的拆分与合并实例图
-
(1,5,6,2,3,7,4) 根节点 第0层
-
/ \
-
/ \
-
/ \
-
(1,5,6,2) (3,7,4) 第1层
-
/ \ / \
-
/ \ / \
-
(1,5) (6,2) 3 (7, 4) 第2层
-
/\ /\ / \
-
/ \ / \ / \
-
1 5 6 2 7 4 第3层
-
那是如何进行合并的呢?从叶子节点所在层开始进行合并(合并孩子)
-
第3层 (1,5) (2,6) (4,7)
-
第2层 (1,2,5,6) (3,4,7)
-
第1层 (1,2,3,4,5,6,7)
*/
} // 如果不可分,则跳出递归(递归的出口在这里)(startInx == endInx)
}
/**
-
归并排序的合并部分(合并两个有序序列)
-
@param a
-
@param stInx 开始合并下标
-
@param midInx 中间位置
-
@param endInx 结束下标
-
@param tmp 临时空间,等于带排序长度,在一次归并排序中,共用一个临时空间。
*/
public static final void merge(int[] a, int stInx, int midInx, int endInx, int[] tmp) {
int alen = midInx > stInx ? midInx - stInx : 0;
int blen = endInx - midInx + 1;
int len = alen + blen;
int aIndex = stInx;
int bIndex = midInx;
alen += stInx; //
blen += midInx; // 这里主要是为了 aIndex < alen && bIndex < blen 服务的
int al = 0;
while( al < len ) {
if(aIndex < alen && bIndex < blen) {
if(a[ aIndex ] >= a[bIndex]) {
tmp[al] = a[bIndex];
bIndex ++;
} else {
tmp[al] = a[aIndex];
aIndex ++;
}
} else if(aIndex < alen) {
tmp[al] = a[aIndex];
aIndex ++;
} else {
tmp[al] = a[bIndex];
bIndex ++;
}
al++;
}
System.arraycopy(tmp, 0, a, stInx, len); // 将tmp拷贝到source数组,该部门元素的排序
}
/**
-
先实现 合并算法,然后转换为 merge 方法的实现
-
该方法为草稿类,主要合并两个已排序序列算法,进而演变为 merge(int[] a, int stInx, int midInx, int endInx, int[] tmp)
*/
public static final void testMerge() {
int[] a = new int[]{ 1,4,7,10,22};
int[] b = new int[] {2,5,16,21};
int len = a.length + b.length;
int[] c = new int[len];
int aIndex = 0;
int bIndex = 0;
int al = 0;
while( al < len ) {
if(aIndex < a.length && bIndex
《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》
【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享
< b.length) {
if(a[ aIndex ] >= b[bIndex]) {
c[al] = b[bIndex];
bIndex ++;
} else {
c[al] = a[aIndex];
aIndex ++;
}
} else if(aIndex < a.length) {
c[al] = a[aIndex];
aIndex ++;
} else {