归并排序
归并排序
归并排序基本思想:
将原数组从中间分开,分成两个子数组,然后继续将子数组从中间分开,直到把所有子数组分解到只有
一个元素,此时分的过程就结束了
然后开始治,递归回退一层,将两个子数组合并成一个新的有序的数组,然后依次回退与其它子数组合并成
新的数组,直到合并成原始数组
归并排序基本思想示意图1:
归并排序基本思想示意图2:
代码实现
public static void mergeSort(int[] arr, int left, int right, int[] temp) {
if (left < right) {
int mid = (left + right) / 2;//中间索引,从此处将数组划分成两份
//向左递归进行分解
mergeSort(arr, left, mid, temp);
//向右递归进行分解
mergeSort(arr, mid + 1, right, temp);
//当分解到只有两个元素的数组时,就开始排序合并
merge(arr,left,mid,right,temp);
}
//只有一个元素了,就不能合并,则回退一层,再合并
}
/**
*@param arr 排序的原始数组
* @param left A有序数组的起始索引
* @param mid 中间索引,也就是A数组的最后一个索引
* @param right B数组的终止索引
* @param temp 合并的数组
*/
public static void merge(int[] arr, int left, int mid, int right, int[] temp) {
int i = left;//左边有序序列的初始索引
int j = mid + 1;//右边有序序列的初始索引
int t = 0;//t指向temp数组的当前索引
//(一)
//先把左右两边(有序)的数据按规则填充到temp数组
//直到左右两边有一边遍历结束
while (i <= mid && j <= right) {
//比较两数组中当前索引的数,哪个小就加入到temp
if (arr[i] <= arr[j]) {
temp[t++] = arr[i++];
} else {
temp[t++] = arr[j++];
}
}
//(二)
//将没有遍历完的数组的剩余元素依次全部填充到temp数组
//因为如果当前数组还有剩余,就说明另外一个数组已经遍历完成了
while (j <= right) {
temp[t++] = arr[j++];
}
while (i <= mid) {
temp[t++] = arr[i++];
}
t = 0;
//(三)
//将temp数组的元素拷贝到arr
//第一次合并是 left=0,right=1 left=2,right=3
//第二次合并是 left=0,right=3
//最后合并是 left=0,right=7
for (int k = left; k <= right; k++) {
arr[k] = temp[t++];
}
}