归并排序
归并排序介绍:
归并排序是利用归并的思想实现的排序方法,该算法采用经典的分治策略,将问题分成小的问题然后递归求解,而治的阶段则将分的阶段得到的各答案修补在一起,即分而治之。
基本思想
其主要算法操作可以分为以下步骤:
Step 1:将n个元素分成两个含n/2元素的子序列
Step 2:用MS将两个子序列递归排序(最后可以将整个原序列分解成n个子序列)
Step 3:合并两个已排序好的序列
易知,MS的关键在于Merge过程。对于这一过程的理解,算法导论中给出了一个形象的模型。
即假设桌面上有两堆已排序好的的牌,且每一堆都正面朝下放置。然后我们分别从两堆牌中选取顶上的一张牌(选取之后,堆顶端又会露出新的顶牌),选取较小的一张,放入输出堆,另一张放回。
重复这一步骤,最后直到一堆牌为空。由于两堆牌都是已排序,所以可知,只要将剩下的那堆牌盖到输出堆即完成整个排序过程。
最主要的步骤是合并的过程
如上图所示,我们将分的两个序列,两个序列都是有序的,因为我们分的最小的是一个元素,设置两个指针,分别指向两个序列的头部,然后比较大小,将小的移动到我们的临时数组,然后指针后移,直到将所有的元素全部移动到临时数组为止。
最后将临时数组中的有序队列拷贝到原数组。
代码
package sort.merge;
public class MergeSort {
/**
* 对数组进行拆分,然后归并
* @param arr 数组
* @param left 数组的最左边的索引
* @param right 数组的最右边的索引
*/
public static void mergeSort(int[] arr, int left, int right) {
//数组的中轴
int mid = (left + right) / 2;
//如果分的数组的长度大于1
if (left < right) {
//向左递归排序
mergeSort(arr, left, mid);
//向右递归排序
mergeSort(arr, mid + 1, right);
//排序
merge(arr, left, right);
}
}
/**
* 对分组进行归并
* @param arr 需要合并的数组
* @param left 最左的值
* @param right 数组最右的值
*/
public static void merge(int[] arr, int left, int right) {
int[] temp = new int[arr.length]; //建立一个等长的数组用来存储有序的数组
//中轴
int mid = (left + right) / 2;
int l = left;
int r = mid + 1;
int index = 0;
//将有序的值存储到临时数组中 直到左边或者右边存储完
while (l <= mid && r <= right) {
if (arr[l] <= arr[r]) {
temp[index] = arr[l];
l++;
index++;
} else {
temp[index] = arr[r];
index++;
r++;
}
}
//将没存储玩的另一边存储到临时数组
while (l <= mid) {
temp[index] = arr[l];
l++;
index++;
}
while (r <= right) {
temp[index] = arr[r];
index++;
r++;
}
index = 0;
int tempLeft = left;
//将有序数拷贝到原来的数组中
while (tempLeft <= right) {
arr[tempLeft] = temp[index];
index++;
tempLeft++;
}
// System.out.println(Arrays.toString(arr));
}
}