归并排序(二叉树理解递归 JAVA实现)

归并排序(二叉树理解递归 JAVA实现)

概念

  • 归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略
  • 分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)

过程 图解

在这里插入图片描述在这里插入图片描述

代码解释

  • 归并排序需要一个额外的数组 shuZu(int[] a) 是创建额外数组的方法
  • 排序块讲解
 while (i <= mid && j <= right) {
if (a[i] > a[j]) {
b[g] = a[j];g++; j++;} else {
b[g] = a[i];g++;i++;}
判断当前组别left元素与mid+1元素的大小 将小的存放进b中 并将b的数组下标自增1 i自增1 确保当前分块的元素全部都被比较
 while (i <= mid) {
b[g] = a[i];g++;i++;}
while (j <= right) {
b[g] = a[j];g++;j++;}
如果左右两组 一组存放完成 剩下的一组其他元素按它在自己块内的顺序依次存放在b中
 g = 0;int tl = left;while (tl <= right) {
 a[tl] = b[g];tl++;g++;}
 由于我们运用了递归 接下来会重点讲这个过程
 所以要边排边存 只存放排好序的 其他未发生排序变动的位置不发生改变
  • 递归!!!!!!

     public static void fenKuai(int[] a, int[] b, int left, int right) {
            if (left < right) {
                int mid = (left + right) / 2;
                fenKuai(a, b, left, mid);
                fenKuai(a, b, mid + 1, right);
                paiXu(a, b, left, mid, right);
            }
        }
    

    过程比较繁琐 我们可以用二叉树来帮忙理解
    在这里插入图片描述

    如图
    第一次进去的数字是 left 0   right  7
    mid=7/2---3 java中取3
    分为了0--3  4--7 这两组
    先进行的是0--3这一组的遍历递归
    进行 fenKuai(a, b, left, mid);
    第二次进去的数字是 left 0   right  3
    mid=3/2---1
    分为了0--1  2--3这两组
    先进行的是0--1这一组的遍历递归
    进行 fenKuai(a, b, left, mid);
    第二次进去的数字是 left 0   right 1
    mid=1/2---0
    因为0不小于0 所以 左支走完了 接着进行右支
    进行的是2--3这一组的遍历递归
    步骤同上
    完成后 返回0--3》》》0--7》》4--7
    接着进行的是4--7这一组的遍历递归
    步骤同上
    这就是二叉树理解递归的主要思想 二叉树的遍历
    
    

代码

import java.util.Arrays;

public class GuiBing {
    public static void main(String[] args) {
        int[] a = {555, 99, 518, 231, 159, 48, 23, 66};
        int[] b = shuZu(a);
        fenKuai(a, b, 0, a.length - 1);
        System.out.println("排序后的结果为:" + Arrays.toString(a));
    }

    public static int[] shuZu(int[] a) {
        int[] b = new int[a.length];
        return b;


    }

    public static void fenKuai(int[] a, int[] b, int left, int right) {
        if (left < right) {
            System.out.println("计算mid" + "左边:" + left + "\t" + "右边:" + right);
            int mid = (left + right) / 2;
            System.out.println("初始" + mid);
            fenKuai(a, b, left, mid);
            System.out.println("1号操作:" + "左边:" + left + "\t" + "中间" + mid + "\t");
            fenKuai(a, b, mid + 1, right);
            System.out.println("2号操作:" + "右边:" + right + "\t" + "中间" + (mid + 1) + "\t");

            System.out.println("左边:" + left + "\t" + "中间" + mid + "\t" + "右边:" + right + "进入函数");
            paiXu(a, b, left, mid, right);
            System.out.println("左边:" + left + "\t" + "中间" + mid + "\t" + "右边:" + right + "函数结束");
        }
        System.out.println("出去的步骤:左边:" + left + "\t" + "右边:" + right + "结果为:break!");

    }

    public static void paiXu(int[] a, int[] b, int left, int mid, int right) {

        int i = left;
        int j = mid + 1;
        int g = 0;
        while (i <= mid && j <= right) {
            if (a[i] > a[j]) {
                b[g] = a[j];
                System.out.println("判断大小的值jj小" + a[j]);
                g++;
                j++;
            } else {
                b[g] = a[i];
                System.out.println("判断大小的值ii大" + a[i]);
                g++;
                i++;
            }
        }
        while (i <= mid) {
            b[g] = a[i];
            System.out.println("左边剩余值" + a[i]);
            g++;
            i++;
        }
        while (j <= right) {
            b[g] = a[j];
            System.out.println("右边剩余值" + a[j]);
            g++;
            j++;
        }
        System.out.println("左边:" + left + "\t" + "中间:" + mid + "\t" + "右边:" + right + "\t" + "个体分块结果为:" + Arrays.toString(b));
        g = 0;
        int tl = left;
        while (tl <= right) {
            a[tl] = b[g];
            tl++;
            g++;
        }
        System.out.println("左边:" + left + "\t" + "中间" + mid + "\t" + "右边:" + right + "\t" + "整体分块结果为:" + Arrays.toString(a));

    }
}
运行结果:
计算mid左边:0	右边:7
初始3
计算mid左边:0	右边:3
初始1
计算mid左边:0	右边:1
初始0
出去的步骤:左边:0	右边:0结果为:break!
1号操作:左边:0	中间0	
出去的步骤:左边:1	右边:1结果为:break!
2号操作:右边:1	中间1	
左边:0	中间0	右边:1进入函数
判断大小的值jj小99
左边剩余值555
左边:0	中间:0	右边:1	个体分块结果为:[99, 555, 0, 0, 0, 0, 0, 0]
左边:0	中间0	右边:1	整体分块结果为:[99, 555, 518, 231, 159, 48, 23, 66]
左边:0	中间0	右边:1函数结束
出去的步骤:左边:0	右边:1结果为:break!
1号操作:左边:0	中间1	
计算mid左边:2	右边:3
初始2
出去的步骤:左边:2	右边:2结果为:break!
1号操作:左边:2	中间2	
出去的步骤:左边:3	右边:3结果为:break!
2号操作:右边:3	中间3	
左边:2	中间2	右边:3进入函数
判断大小的值jj小231
左边剩余值518
左边:2	中间:2	右边:3	个体分块结果为:[231, 518, 0, 0, 0, 0, 0, 0]
左边:2	中间2	右边:3	整体分块结果为:[99, 555, 231, 518, 159, 48, 23, 66]
左边:2	中间2	右边:3函数结束
出去的步骤:左边:2	右边:3结果为:break!
2号操作:右边:3	中间2	
左边:0	中间1	右边:3进入函数
判断大小的值ii大99
判断大小的值jj小231
判断大小的值jj小518
左边剩余值555
左边:0	中间:1	右边:3	个体分块结果为:[99, 231, 518, 555, 0, 0, 0, 0]
左边:0	中间1	右边:3	整体分块结果为:[99, 231, 518, 555, 159, 48, 23, 66]
左边:0	中间1	右边:3函数结束
出去的步骤:左边:0	右边:3结果为:break!
1号操作:左边:0	中间3	
计算mid左边:4	右边:7
初始5
计算mid左边:4	右边:5
初始4
出去的步骤:左边:4	右边:4结果为:break!
1号操作:左边:4	中间4	
出去的步骤:左边:5	右边:5结果为:break!
2号操作:右边:5	中间5	
左边:4	中间4	右边:5进入函数
判断大小的值jj小48
左边剩余值159
左边:4	中间:4	右边:5	个体分块结果为:[48, 159, 518, 555, 0, 0, 0, 0]
左边:4	中间4	右边:5	整体分块结果为:[99, 231, 518, 555, 48, 159, 23, 66]
左边:4	中间4	右边:5函数结束
出去的步骤:左边:4	右边:5结果为:break!
1号操作:左边:4	中间5	
计算mid左边:6	右边:7
初始6
出去的步骤:左边:6	右边:6结果为:break!
1号操作:左边:6	中间6	
出去的步骤:左边:7	右边:7结果为:break!
2号操作:右边:7	中间7	
左边:6	中间6	右边:7进入函数
判断大小的值ii大23
右边剩余值66
左边:6	中间:6	右边:7	个体分块结果为:[23, 66, 518, 555, 0, 0, 0, 0]
左边:6	中间6	右边:7	整体分块结果为:[99, 231, 518, 555, 48, 159, 23, 66]
左边:6	中间6	右边:7函数结束
出去的步骤:左边:6	右边:7结果为:break!
2号操作:右边:7	中间6	
左边:4	中间5	右边:7进入函数
判断大小的值jj小23
判断大小的值ii大48
判断大小的值jj小66
左边剩余值159
左边:4	中间:5	右边:7	个体分块结果为:[23, 48, 66, 159, 0, 0, 0, 0]
左边:4	中间5	右边:7	整体分块结果为:[99, 231, 518, 555, 23, 48, 66, 159]
左边:4	中间5	右边:7函数结束
出去的步骤:左边:4	右边:7结果为:break!
2号操作:右边:7	中间4	
左边:0	中间3	右边:7进入函数
判断大小的值jj小23
判断大小的值jj小48
判断大小的值jj小66
判断大小的值ii大99
判断大小的值jj小159
左边剩余值231
左边剩余值518
左边剩余值555
左边:0	中间:3	右边:7	个体分块结果为:[23, 48, 66, 99, 159, 231, 518, 555]
左边:0	中间3	右边:7	整体分块结果为:[23, 48, 66, 99, 159, 231, 518, 555]
左边:0	中间3	右边:7函数结束
出去的步骤:左边:0	右边:7结果为:break!
排序后的结果为:[23, 48, 66, 99, 159, 231, 518, 555]

进程已结束,退出代码0

结束

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值