归并排序
归并排序用到了分治法的思想。用代码实现时,按从小到大排序为例,主要的思路分为分解和合并两大步骤:
分解:
- 第一次分解时,根据数组的头尾下标,得出分界线的位置,即:mid=(left+right)/2;
- 向左递归分解:就是将数组的头下标和分界线的下标当做新序列的头尾下标再次分解;
- 向右递归分解:就是将分界线的下标后一位(mid+1)和数组的尾下标当做新序列的头尾下标再次分解;
- 分解结束后(即头尾相等时)开始合并操作。
合并:
- 初始化左边序列的开始下标:i=left;右边序列的开始下标:j=mid+1;
- 左右下标对应的当前值依次比较,将较小的值放入临时数组中,然后每次从较小值的那边开始继续移动下标;
- 第2步操作结束后会出现三种情况:1)左右序列的数据全部放入临时数组中了;2)左边序列还剩数据没有放入临时数组中;3)右边序列还剩数据没有放入临时数组中。考虑后两种情况,将剩下的数据复制到临时数组中;
- 将临时数组复制到原始数组。
上述如有错误之处,还望指出,我会及时改正。其代码如下:
package com.sort.mergetSort;
import java.util.Arrays;
public class MergeSortDemo2 {
public static void main(String[] args) {
int array[] = { 8, 4, 5, 7, 1, 3, 6, 2 };
int temp[] = new int[array.length];// 归并排序需要一个额外空间
System.out.println("排序前:" + Arrays.toString(array));
mergeSort(array, 0, array.length - 1, temp);
System.out.println("排序后:" + Arrays.toString(array));
}
/**
* 归并排序
*
* @param array
* @param left
* @param right
* @param temp
*/
public static void mergeSort(int[] array, int left, int right, int[] temp) {
if (left >= right) {
return;
}
int mid = (left + right) / 2;
// 向左递归分解
mergeSort(array, left, mid, temp);
// 向右递归分解
mergeSort(array, mid + 1, right, temp);
// 合并
merge(array, left, mid, right, temp);
}
/**
* 合并操作
*
* @param array 原始数组
* @param left 左边有序序列的初始下标
* @param mid 中间值的下标 ,分界线
* @param right 最右边下标
* @param temp 临时数组
*/
public static void merge(int[] array, int left, int mid, int right, int[] temp) {
// 1.定义左边序列和右边序列开始下标
int i = left;
int j = mid + 1;
int t = 0;// 记录临时数组的下标
// 2.比较左右两个序列中的值
while (i <= mid && j <= right) {
// 2.1如果左边序列的当前值小于等于右边序列的当前值,就将左边序列当前值暂存在临时数组
if (array[i] <= array[j]) {
temp[t] = array[i];
t++;
i++;
} else {// 2.2反之,如果右边序列的当前值大于左边序列的当前值,就将右边序列的当前值暂存在临时数组
temp[t] = array[j];
t++;
j++;
}
}
// 3.上面循环结束时,可能会出现两种情况
// 3.1右边序列遍历完了,但是左边序列还剩数据
while (i <= mid) {
temp[t] = array[i];
t++;
i++;
}
// 3.2左边序列遍历完了,右边序列还剩数据
while (j <= right) {
temp[t] = array[j];
t++;
j++;
}
// 4.数据全部放到临时数组后,开始将temp复制给array
// 4.1.下标位置重新置为0
t = 0;
// 4.2.定义array数组的下标,每次从left开始放
int tempLeft = left;
// 4.3.开始复制数组
while (tempLeft <= right) {
array[tempLeft] = temp[t];
tempLeft++;
t++;
}
}
}