归并排序
来源:互联网 发布:空间地理基础数据库 编辑:程序博客网 时间:2024/06/06 04:00
归并排序是建立在归并操作上的一种有效的排序算法。
该算法是采用分治法(分而治之)的一个非常典型的应用。
思想:
先将数据分开排序,然后将两个已排序的子序列合并。
问题:
① 对于一组数据,怎么把数据分开并排序?或者说,把数据一分为二,分到什么地步为止?
② 对于两个已经排好序的序列,怎么合并为一个有序的序列?
解释:
回答① :最后每个子序列只有一个元素,自然就是有序的。
回答② :先理解一个模型,道理是一样的。(帮助理解合并操作)
假设桌面上有两堆已排序好的的牌,且每一堆都正面朝下放置。然后我们分别从两堆牌中选取顶上的一张牌(选取之后,堆顶端又会露出新的顶牌),选取较小的一张,放入输出堆,另一张放回原来的位置。
重复这一步骤,最后直到一堆牌为空。由于两堆牌都是已排序,所以可知,只要将剩下的那堆牌盖到输出堆即完成整个排序过程。
步骤:
step 1 : 将n个元素分成两个含n/2个元素的子序列;
step 2 : 将两个子序列递归排序(最后可以将整个原序列分解成n个子序列);
step 3 : 合并两个已排序好的序列。
代码实现:(JAVA)
package com.algorithm;
public class MergeSort {
/**
* @author 朱剑锋爱秦霞
*
* @version 将数组分开并排序的功能
*
* @param arr[]待排序的数组
* @param low起始下标
* @param high终止下标
*
*/
public void mergeSort(int[] arr, int low,int high) {
int mid;
if(low != high) {
mid = (low + high)/2;
mergeSort(arr, low, mid);
mergeSort(arr, mid + 1, high);
merge(arr, low, high, mid);
}
}
/**
* @author 朱剑锋爱秦霞
*
* @version 将两个已排序的子序列合并
*
* @param arr[]待排序的数组
* @param low起始下标
* @param high终止下标
*
*/
public void merge(int[] arr, int low,int high,int mid) {
int[]temp =new int[high - low + 1];
int i = low;
int j = mid + 1;
int k = 0;
//分别从左右两堆数中选取第一个数,取较小的数,放入输出数组,另一个放回原来的位置。
while(i <= mid && j <= high) {
if(arr[i] < arr[j]) {
temp[k++] = arr[i++];
} else {
temp[k++] = arr[j++];
}
}
//如果左边还有剩余的数,直接依次放入输出数组
while(i <= mid) {
temp[k++] = arr[i++];
}
//如果右边还有剩余的数,直接依次放入输出数组
while(j <= high) {
temp[k++] = arr[j++];
}
//最后,输出数组覆盖原数组
for (int n = 0; n <temp.length; n++) {
arr[n + low] = temp[n];
}
}
//main方法
public static void main(String[] args) {
int[] arr = {3,6,68,9,20,0,1};
MergeSort mSort = new MergeSort();
mSort.mergeSort(arr, 0, arr.length - 1);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] +" ");
}
}
}
时间复杂度分析:
public void mergeSort(int[] arr, int low,int high) {
int mid;
if(low != high) {
mid = (low + high)/2;
mergeSort(arr, low, mid);
mergeSort(arr, mid + 1, high);
merge(arr, low, high, mid);
}
}
假设待排序的序列长度为n
易知:归并操作(merge(arr, low, high, mid))的时间复杂度为O(n),这里不做解释。
所以:
设O(1)等于c
得出下图:
从图中,我们可以发现,每一层的总时间之和均为cn,且计算可得层数为。
那么,即为总的执行时间。由于算法的时间复杂度由其最大阶决定。所以得出结论:归并排序的时间复杂度为
(欢迎评论指导,共同进步!)