java归并排序超级详细

 

           0             mid                             right= nums.length-1       mid=(right+left)/2
    递 : 34   51     78   88        9  11  37   32 
                     /\                               /\
          34  51     78  88          9   11    37  32
              /\            /\               /\            /\
           34   51     78  88       9   11      32  37
   归         \/            \/              \/             \/        递归出口:   if(left==right)  return;
           34 51      78   88        9  11       32  37
                     \/                              \/
           34  51  78  88           9   11  32  37
                                     \/
                 9   11  32  37  34  51  78  88  
      递:   sort  =sort1(0,mid)  ,sort1(mid+1,right)
      归:   merge(int nums[],int left,int mid,int right,int tmp[])   即合并
                               
             merge 详解    以归的最后一步说明
              tmp数组           34  51  78  88    9   11  32  37 
                                      left                                     right
            int tmp[]=new   int [nums.length] 
           先把刚刚声明的数组用原数据拷贝
            for(int k=left;k<=right;k++){
                      tmp[k]=nums[k];}
               若遍历i之后   i的值为mid+1,说明左边的拷贝完,j之后的数据就可以直接拷到nums数组了。
               若遍历j之后   j的值为mid+1,说明右边的拷贝完,左边的数据就可以直接拷到nums数组了。
               若i,j没有到边界(即上面那两个值),则再进行比较:
               1.若      tmp[i]比tmp[j]还大,   那么我们将小的 tmp[i]拷贝到nums数组,不要忘了i++。
               2.反之,即tmp[i]比tmp[j]还小,我们 将小的tmp[j]拷贝到nums数组,同时加j++。  
package  stack;
import java.util.Arrays;
public class GuiBing {
    public void sort(int nums[]) {
        int tmp[]=new int[nums.length];      //这里申请一个数组,避免每次申请数组,造成空间上的浪费
        sort1(nums,0,nums.length-1,tmp);    
    }

    private void sort1(int[] nums, int left, int right, int[] tmp) {
        if(left==right) {
            return;
        }
        int mid=(left+right)/2;
        sort1(nums,left,mid,tmp);     //问题1
        sort1(nums,mid+1,right,tmp);
        merge(nums,left,mid,right,tmp);    
    }

    private void merge(int[] nums, int left, int mid, int right, int[] tmp) {
         for(int i=left;i<=right;i++){
                                       tmp[i]=nums[i];
          }
         int i=left;
                                   int j=mid+1;
        for(int k=left;k<=right;k++) {      
            if(i==mid+1) { 
                 nums[k]=tmp[j++];        
            }
            else if(j==right+1) {
                nums[k]=tmp[i++];
            }
            else if(tmp[i]<=tmp[j] ) {        
                   nums[k]=tmp[i++];
            }
            else {
                   nums[k]=tmp[j++];
            }    
                                       }    
    }
    public static void main(String args[]) {
        GuiBing  GB=new GuiBing();
        int nums[]= {34,51,78,88,9,11,37,32};
        GB.sort(nums);
        System.out.println(Arrays.toString(nums));    
    }    
}

从归并排序再次体会编程的递归思想分治:
当程序递归到left==right 时,即此时的数组只有一个元素,那么进行归的操作,上一步是系统栈存的是两个元素的数组,进行sort1方法中
的merge,这里注意每次merge调用两次,因为大问题拆分为了两个小的子问题。


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值