Java内部排序(八)-(归并排序)

归并排序的基本思想是:将两个(或以上)有序的序列合并成一个新的有序序列。细化来说,归并排序现将长度为n的无序序列看成是n个长度为 1 的有序子序列,首先要做两两合并,得到n/2个长度为2的有序子序列,在做两两合并,……不断重复这个过程,最终得到一个长度为n的有序序列。

对于归并排序而言,关键还是在于合并两个有序子序列。合并算法的具体步骤如下:

1、定义变量 i ,i 从 0 开始,依次等于 A 序列中元素的索引。

2、定义变量 j ,j 从 0 开始,依次等于 B 序列中元素的索引。

3、拿A序列中索引 i 处的元素跟 B序列中 j 索引处的元素进行大小比较,将小的复制到一个临时数组中。

4、如果 i 处索引的值小, i ++;如果 j 索引处的值小,j ++;

重复上面四个过程,即可将A、B俩个序列中的元素复制到临时数组中,直到其中一个数组中的所有元素都被复制到临时数组中,再把另外一个数组中的剩下的元素全部复制到临时数组中,合并即完成,再将临时数组中的元素复制回去即可。

下面是合并操作的实现细节:



归并排序实现:

模拟数据:-56, -21, 56, -21*, 20, 56*, -123, 9, 26, 33


  1. public class MergeSort {  
  2.     public static void mergeSort(DataWrap[] data){  
  3.         sort(data, 0, data.length - 1);  
  4.     }  
  5.       
  6.     /** 
  7.      * 归并排序 
  8.      * @param data 待排序的数组元素 
  9.      * @param left  待排序的数组段的起始索引 
  10.      * @param right 待排序的数组的结束索引 
  11.      */  
  12.     public static void sort(DataWrap[] data, int left, int right){  
  13.         if(left < right){  
  14.             int center = (left + right) / 2;  
  15.             sort(data, left, center);  
  16.             sort(data, center + 1, right);  
  17.             merge(data, left, right);  
  18.         }  
  19.     }  
  20.     /** 
  21.      * 合并操作 
  22.      * @param data 数组对象 
  23.      * @param left  左数组的第一个元素索引 
  24.      * @param right 右数组的最后一个元素索引 
  25.      */  
  26.     public static void merge(DataWrap[] data, int left, int right){  
  27.         //临时存放比较过后较小的数据项数组  
  28.         DataWrap[]  tempArr = new DataWrap[data.length];  
  29.         int center = (left + right) / 2;  
  30.         int mid = center + 1;  
  31.           
  32.         int tempIndex = left;  
  33.         int tempStart = left;  
  34.           
  35.         //只要有一组还有数据项没有复制完成就不断地比较复制  
  36.         while(left <= center && mid <= right){  
  37.             if(data[left].compareTo(data[mid]) <= 0){ //左边小或者相等,这个等 很重要,它关系到归并排序算法的稳定性  
  38.                 tempArr[tempIndex ++] = data[left ++];  
  39.             }else{  
  40.                 tempArr[tempIndex ++] = data[mid ++];  
  41.             }  
  42.         }  
  43.           
  44.         //将某一组中还剩的数据项都复制到临时数组中,它可能是左边的也有可能是右边的  
  45.         while(left <= center){  
  46.             tempArr[tempIndex ++] = data[left ++];  
  47.         }  
  48.           
  49.         while(mid <= right){  
  50.             tempArr[tempIndex ++] = data[mid ++];  
  51.         }  
  52.           
  53.         //将临时数组的left~right数据项复制到data 中  
  54.         for(int i = tempStart; i <= right; i ++){  
  55.             data[i] = tempArr[i];  
  56.         }  
  57.         /*while(tempStart <= right){ 
  58.             data[tempStart] = tempArr[tempStart ++]; 
  59.         }*/  
  60.     }  
  61.       
  62.     public static void main(String[] args){  
  63.         DataWrap[] data = {new DataWrap(-56,""),  
  64.                 new DataWrap(-21,""),  
  65.                 new DataWrap(56,""),  
  66.                 new DataWrap(-21,"*"),  
  67.                 new DataWrap(20,""),  
  68.                 new DataWrap(56,"*"),  
  69.                 new DataWrap(-123,""),  
  70.                 new DataWrap(9,""),  
  71.                 new DataWrap(26,""),  
  72.                 new DataWrap(33,"")};  
  73.         System.out.println("-排序前-"+java.util.Arrays.toString(data));  
  74.   
  75.         mergeSort(data);  
  76.   
  77.         System.out.println("-排序后-"+java.util.Arrays.toString(data));  
  78.     }  
  运行结果为:


从上面的算法实现可以看出,归并排序算法需要递归的进行分解。合并,每进行一趟归并排序需要调用merger()方法一次,每次执行merge()方法需要比较 n 次,一次归并排序算法的时间复杂度为O(N*Log2N) .

但其空间效率较差,它需要一个与原始序列同样大小的辅助序列。

归并排序算法是稳定的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值