package jxau.blueDot.lyx;
/**
*
* @author lyx
*@上午10:48:38
* @TODO:
* 归并排序
*/
/**
* 归并排序只要是二路归并排序。
* 基本思想是:设数组a中存放了n个数据元素,初始时将它们看成是n个长度为1的有序
* 数组,然后从第一个子数组开始,把相邻子数组两两合并,得到n/2的整数上界个长度为2
* 的新的有序子数组(当n为奇数时最后一个新的有序子数组的长度为1);对这些新的有序
* 子数组再两两归并,最终得到长度为n的有序数组为止,多路归并排序与二路归并排序类似。
*
* 工作原理:
*
*1、申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
*
*2、设定两个指针,最初位置分别为两个已经排序序列的起始位置
*
*3、比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
*
*4、重复步骤3直到某一指针达到序列尾
*
*5、将另一序列剩下的所有元素直接复制到合并序列尾
*
*/
/**
* 把若干个长度为k的相邻有序子数组从前向后两两进行归并,得到个数减半的长度为
* 2k的子数组,当归并到:
* (1)若元素大于k而小于2k个,把前k个元素作为一个子数组,把剩余元素作为最后
* 一个子数组:例子如下
*
* 初始关键字序列
* 72 73 71 23 94 16 5 68 64 《-------64为另一个子数组
* 第一次归并结果
* 72 73 23 71 16 94 5 68 64
* 第二次归并结果
* 23 71 72 73 5 16 68 94 64
* 第三次归并结果
* 5 16 23 68 71 72 73 94 64
* 第四次归并结果
* 5 16 23 64 68 71 72 73 94
*/
/**
*
* 算法时间代价:
* 对n个元素进行一次归并 次数约为logn 任何一次的二路归并比较次数都为n-1
* 所以O(nlogn)
* 由于排序时使用了n个临时内存单元存放数据元素,空间复杂度为O(n)
*/
public class MergeSort {
public static void mergeSort(int[] data) {
sort(data, 0, data.length - 1);
}
public static void sort(int[] data, int left, int right) {
if (left >= right)
return;
// 找出中间索引
int center = (left + right) / 2;
// 对左边数组进行递归
sort(data, left, center);
// 对右边数组进行递归
sort(data, center + 1, right);
// 合并
merge(data, left, center, right);
print(data);
}
/**
* 将两个数组进行归并,归并前面2个数组已有序,归并后依然有序
*
* @param data
* 数组对象
* @param left
* 左数组的第一个元素的索引
* @param center
* 左数组的最后一个元素的索引,center+1是右数组第一个元素的索引
* @param right
* 右数组最后一个元素的索引
*/
public static void merge(int[] data, int left, int center, int right) {
// 临时数组
int[] tmpArr = new int[data.length];
// 右数组第一个元素索引
int mid = center + 1;
// third 记录临时数组的索引
int third = left;
// 缓存左数组第一个元素的索引
int tmp = left;
while (left <= center && mid <= right) {
// 从两个数组中取出最小的放入临时数组
if (data[left] <= data[mid]) {
tmpArr[third++] = data[left++];
} else {
tmpArr[third++] = data[mid++];
}
}
// 剩余部分依次放入临时数组(实际上两个while只会执行其中一个)
while (mid <= right) {
tmpArr[third++] = data[mid++];
}
while (left <= center) {
tmpArr[third++] = data[left++];
}
// 将临时数组中的内容拷贝回原数组中
// (原left-right范围的内容被复制回原数组)
while (tmp <= right) {
data[tmp] = tmpArr[tmp++];
}
}
public static void print(int[] data) {
for (int i = 0; i
System.out.print(data[i] + "\t");
}
System.out.println();
}
}