题目:
归并排序从小到大排序
我们总是可以将一个数组一分为二,然后二分为四,直到每一组只有两个元素,这可以理解为个递归的过程,然后将两个元素进行排序,之后再将两个元素为一组进行排序。直到所有的元素都排序完成。
归并算法的思想
归并算法其实可以分为递归法和迭代法(自底向上归并),两种实现对于最小集合的归并操作思想是一样的。区别在于如何划分数组,我们先介绍下算法最基本的操作:
1.申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;
2.设定两个指针,最初位置分别为两个已经排序序列的起始位置;
3.比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
4.重复步骤 3 直到某一指针到达序列尾;
5.将另一序列剩下的所有元素直接复制到合并序列尾。
代码:
public class MergeSort {
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
private static void printArr(int[] arr) {
for (int anArr : arr) {
System.out.print(anArr + " ");
}
}
private static void mergeSort(int[] arr) {
if (arr == null)
return;
mergeSort(arr, 0, arr.length - 1);
}
private static void mergeSort(int[] arr, int start, int end) {
if (start >= end)
return;
// 找出中间索引
int mid = start + (end - start >> 1);
// 对左边数组进行递归
mergeSort(arr, start, mid);
// 对右边数组进行递归
mergeSort(arr, mid + 1, end);
// 合并
merge(arr, start, mid, end);
}
private static void merge(int[] arr, int start, int mid, int end) {
// 先建立一个临时数组,用于存放排序后的数据
int[] tmpArr = new int[arr.length];
int start1 = start, end1 = mid, start2 = mid + 1, end2 = end;
// 创建一个下标
int pos = start1;
// 缓存左边数组的第一个元素的索引
int tmp = start1;
while (start1 <= end1 && start2 <= end2) {
// 从两个数组中取出最小的放入临时数组
if (arr[start1] <= arr[start2])
tmpArr[pos++] = arr[start1++];
else
tmpArr[pos++] = arr[start2++];
}
// 剩余部分依次放入临时数组,实际上下面两个 while 只会执行其中一个
while (start1 <= end1) {
tmpArr[pos++] = arr[start1++];
}
while (start2 <= end2) {
tmpArr[pos++] = arr[start2++];
}
// 将临时数组中的内容拷贝回原来的数组中
while (tmp <= end) {
arr[tmp] = tmpArr[tmp++];
}
}
public static void main(String[] args) {
int[] arr = {6, 4, 2, 1, 8, 3, 7, 9, 5};
mergeSort(arr);
printArr(arr);
}
}