从二叉树的角度理解——归并排序

归并排序

这篇文章将从二叉树的角度理解归并排序。归并排序的本质是采用递归的方式将一个数组分为若干个子数组,直到子数组分为一个个独立的数据的时候,开始进行有序的合并排序。

归并排序的执行流程

①、不断的将当前序列平均分割成2个子序列,直到不能再分割(子序列中只剩一个元素);
②、不断的将2个子序列合并成为一个有序的序列,直到最后合并为一个序列。

在这里插入图片描述

对于归并排序的总结思考

先对左右子数组进行排序,然后进行合并(有序,类似于合并有序链表的逻辑),仔细想一想像不像二叉树的后序遍历,将整个数组看作根节点,然后通过中间值进行前后子数组的划分,然后进行依次有序合并。

//对比二叉树的前中后序递归遍历问题与归并排序的递归左右子数组的划分问题

//二叉树的前、中、后序的遍历
public void process(TreeNode root){
  if(root == null){
    return;
  }
  //前序遍历的位置
  process(root.left);
  //中序遍历的位置
  process(root.right);
  //后序遍历的位置
}

//归并排序左右子数组的划分问题
 public void mergeSort(int[] arr, int left, int right){
        if(left >= right){
            return;
        }
        //在前序遍历获取到,中间值
        int mid = (right-left)/2+left;
        
        //像不像递归左子树部分和右子树部分
        mergeSort(arr,left,mid);
        mergeSort(arr,mid+1,right);
        
        //在后序遍历进行排序合并
        merge(arr,left,mid,right);
    }

合并的方法就是采用merge将左右子数组进行有序的合并

    public void merge(int[] arr, int left, int mid, int right){
    	//开辟一个新的数组,用于做辅助数组,暂时存放有序数据
        int[] help = new int[right-left+1];
        int index = 0;
        int p1 = left;
        int p2 = mid+1;
        
        //将左右子数组进行比较,将比较后的数据存放在辅助数组当中。
        while(p1 <= mid && p2 <= right){
            help[index++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
        }
       
        //右子数组为空,左子数组不为空
        while(p1 <= mid){
            help[index++] = arr[p1++];
        }
        
        //左子数组为空,右子数组不为空
        while(p2 <= right){
            help[index++] = arr[p2++];
        }
        
        //将辅助数组中的数据存储到之前的数组当中
        for(int i = 0; i < help.length; i++){
            arr[left+i] = help[i]; 
        }
    }

完整代码

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 将给定数组排序
     * @param arr int整型一维数组 待排序的数组
     * @return int整型一维数组
     */
    public int[] MySort (int[] arr) {
        // write code here
        if(arr.length < 2){
            return arr;
        }
        megerSort(arr,0,arr.length-1);
        return arr;
    }
    
    public void mergeSort(int[] arr, int left, int right){
        if(left >= right){
            return;
        }
        //在前序遍历获取到,中间值
        int mid = (right-left)/2+left;
        
        //像不像递归左子树部分和右子树部分
        mergeSort(arr,left,mid);
        mergeSort(arr,mid+1,right);
        
        //在后序遍历进行排序合并
        merge(arr,left,mid,right);
    }
    
    public void merge(int[] arr, int left, int mid, int right){
        int[] help = new int[right-left+1];
        int index = 0;
        int p1 = left;
        int p2 = mid+1;
        
        while(p1 <= mid && p2 <= right){
            help[index++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
        }
        
        while(p1 <= mid){
            help[index++] = arr[p1++];
        }
        
        while(p2 <= right){
            help[index++] = arr[p2++];
        }
        
        for(int i = 0; i < help.length; i++){
            arr[left+i] = help[i]; 
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值