基本思想:采用分治策略,将问题分解成小问题,然后递归求解,然后再将各个部分的答案修补在一起。 如:
8 4 5 7 1 3 6 2 分解:
8 4 5 7 - 1 3 6 2
8 4 - 5 7 -- 1 3 - 6 2
8-4 -- 5-7 --- 1-3 -- 6-2
合并:
4 8 - 5 7 -- 1 3 - 2 6
4 5 7 8 - 1 2 3 6
1 2 3 4 5 6 7 8
共合并了7次,最后一次就是合并两个有序数组,左右分别两个指针,如果某个序列已经填完,酒直接把另一个序列剩余元素全部填入。
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)
}
}
//合并的方法:
/*
arr是原始数组,left是左边有序序列的初始索引,mid是中间索引,right是右边索引,temp是中转数组。
*/
public static void merge(int[] arr, int left, int mid, int right, int[] temp)
{
int i = left;
int j = right;
int t = 0;//指向temp数组的当前索引
//先把左右两边有序数据按规则填充到temp数组中,直到左右两边序列中有一边处理完毕
while (i <= mid && j<= right)
{
if(arr[i] <= arr[j])
{
temp[t] = arr[i];
i += 1;
t += 1;
} else
{
temp[t] = arr[j];
j += 1;
t += 1;
}
}
//把剩余数据的一边的数据依次全部填充到temp中
while (i <= mid) //如果左边剩余,就全部填充到左边
{
temp[t] = arr[i];
t += 1;
i += 1;
}
while (j <= right)
{
temp[t] = arr[j];
t += 1;
j += 1;
}
//将temp数组的元素拷贝到arr中,但并不是每次都拷贝所有
t = 0;
int templeft = left;
while (templeft <= right)
{
arr[templeft] = temp[t];
t += 1;
templeft += 1;
}
}