您的位置:首页 > 编程语言 > Java开发

排序算法七:归并排序

2015-01-26 20:59 253 查看

归并排序

归并排序(Merge Sort)同快速排序一样,同样是采用分治策略(Divide and Conquer)的一种较为快速的排序算法。它与快速排序的最大不同,也即其特点体现在快速排序是从大到小的层层分割,直到把每一部分分割到最小,而归并排序则是由小到大的层层合并,直到全部内容合并为一个整体。也因为这种关系,我把归并排序放在了快速排序的后面来写。

归并排序的实现思路为,首先将数组分割成最小的模块,连续的两块分别排序放置到一申请的临时数组空间上,临时的数组空间最后将排好序的内容复制到原数组上,实现一趟排序。数组中连续的两块比较方式为,分别依次比较两部分的小者往临时数组中放置,直到其中之一放置完毕,将另一没有放置完毕的数组剩余元素都放置到临时数组中,完成一次合并动作。完成一趟归并排序后,执行递归,并最终达到实现全部内容归并到一个数组为止。

下面是略作修改的百度百科Java代码(其思路和自己所想几乎一致,故拿来主义,也避免重复):

/**
* <pre>
* 二路归并
* 原理:将两个有序表合并和一个有序表
* </pre>
* @param data
* @param firstStart
* 第一个有序表的起始下标
* @param secondStart
* 第二个有序表的起始下标
* @param secondEnd
* 第二个有序表的结束小标
* @return
* */
private static void merge(int[] data, int firstStart, int secondStart, int secondEnd) {
//临时数组元素
int[] tmp = new int[secondEnd - firstStart + 1];
int i = firstStart, j = secondStart, k = 0;
//将两个有序表中的元素按顺序放入临时数组,(事实上其中之一的元素必完全放入临时数组中)
while (i < secondStart && j <= secondEnd) {
if (data[i] <= data[j]) {
tmp[k] = data[i];
k++;
i++;
} else {
tmp[k] = data[j];
j++;
k++;
}
}
//如果第一个有序数组仍有元素剩余,将第一个有序数组的剩余元素全部放入临时数组
while(i<secondStart){
tmp[k]=data[i];
i++;
k++;
}
//如果第二个有序数组仍有元素剩余,将第二个有序数组的剩余元素全部放入临时数组
while (j <= secondEnd) {
tmp[k] = data[j];
j++;
k++;
}
//将临时数组中的元素都复制到原数组相应位置中
System.arraycopy(tmp, 0, data, firstStart, tmp.length);
}

/**
* 二路归并排序
* @param data:数据
* @param start:起点坐标
* @param width:每次归并的有序集合的宽度
*/
public static void mergeSort(int[] data, int start, int width) {
int size = data.length;
//可分成的两两的合并数据块的个数
int mid = size / (width << 1);
//取余数,判断是否数据是否已经整除
int c = size & ((width << 1) - 1);
// -------归并到只剩一个有序集合的时候结束算法-------//
if (mid == 0)
return;
// ------进行一趟归并排序-------//
for (int i = 0; i < mid; i++) {
start = i * 2 * width;
merge(data, start, start + width, (width << 1) + start - 1);
}
// -------将剩下的数和倒数一个有序集合归并-------//
if (c != 0)
merge(data, size - c - 2 * width, size - c, size - 1);
// -------递归执行下一趟归并排序------//
mergeSort(data, 0, 2 * width);
}


毫无疑问这也是递归写法,其初始入参为要排序的入参data,起点坐标 0 ,起始有序队列的宽度 1,明显来看其代码写起来相较于快速排序已经复杂了不少。相对于快速排序,归并排序的在算法复杂度上和前者一致,但是速度上略慢,并且需要O(n)的空间复杂度,但是归并排序适合外部排序,无需一次将数据全部拿入内存来使用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息