归并排序

来源:互联网 发布:空间地理基础数据库 编辑:程序博客网 时间: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,且计算可得层数为

那么,即为总的执行时间。由于算法的时间复杂度由其最大阶决定。所以得出结论:归并排序的时间复杂度为


(欢迎评论指导,共同进步!)



原创粉丝点击