算法例子:二叉树的基本操作(Java)


平时我们也会经常见到二叉树这样的数据结构,这里就对二叉树的基本操作简单的实现:
1.二叉树的创建
2.二叉树的插入数据(遵循left<root<=right)
3.打印二叉树所有结点(中序遍历,有序的)
4.打印二叉树的深度
5.打印指定层级的所有结点.
6.使用示例
这里简单的举个例子:
例如,顺序插入数组中的数据:
int[] array = new int[]{50, 23, 45, 70, 63, 36, 80, 99, 12};
插入的时候,保证left<root<=right.
最后的效果为:
在这里插入图片描述
打印结果:

中序遍历:[12,23,36,45,50,63,70,80,99]3层所有结点:[12,45,63,80]
深度:4

如果有误还请大家给指点迷津.

1.创建二叉树

这个创建二叉树,就是创建指定的数据结构.
二叉树结点:

class TreeNode {
    public int value;//当前结点值
    TreeNode left;//左子树
    TreeNode right;//右子树

    public TreeNode(int value) {
        this.value = value;
    }

    public TreeNode(int value, TreeNode left, TreeNode right) {
        this.value = value;
        this.left = left;
        this.right = right;
    }
}

二叉树:

class TwoBranchTree {
    private TreeNode root;//根结点
    private int mTreeDepth;//深度
}

2.二叉树的插入数据

2.1:插入使用的是有序插入(值比较):保证左子树<根结点<=右子树
2.2.插入顺序
(1)插入50.
在这里插入图片描述
(2)插入23.
23<50,则放在50的左子树
在这里插入图片描述
(3)插入45.
45<50,则查看其左子树,45大于了23,所以要插入23的右子树.
在这里插入图片描述

(4)插入70.
70大于50,所以要插入到50的右子树
在这里插入图片描述

(5)插入63,36,80,99,12
后面就不一一的插入了,遵循以上的插入规则,插入后面所有结点,最终形成的二叉树为:
在这里插入图片描述
下面对二叉树的所有操作方法:都封装到TwoBranchTree类.

/**
     * 有序插入结点:左中右,  左子树<根结点<=右节点
     * 如果是有序遍历打印出,那么就要调用:中序遍历
     *
     * @param v 插入的结点的值
     */
    public void insertOrderByLmr(int v) {
        //1.先查看root结点是否为null
        if (root == null) {
            TreeNode node = new TreeNode(v, null, null);
            root = node;
        } else {
            TreeNode temp = root;
            //2.先找到插入的位置
            while (temp != null) {
                if (v < temp.value) {
                    //3.如果插入的结点值小于比较的结点,那么就查找其左子树
                    if (temp.left == null) {
                        //3.1.找到为空的,则将结点插入到当前结点left
                        temp.left = new TreeNode(v, null, null);
                        break;
                    }
                    //3.2继续往下找
                    temp = temp.left;
                } else if (v >= temp.value) {
                    //4.如果插入的结点值大于等于比较的结点,那么就查找其右子树
                    if (temp.right == null) {
                        //4.1.找到为空的,则将结点插入到当前结点left
                        temp.right = new TreeNode(v, null, null);
                        break;
                    }
                    //4.2继续往下找
                    temp = temp.right;
                }
            }

        }
    }

3.打印二叉树所有结点

因为插入的时候规则left<root<=right,所以要使用打印出的是有序的,则需要使用中序遍历:
中序遍历:
先打印left,打印root,打印right.
下面是遍历过程:先从树的根结点遍历.
先请忽略手画图的遍历过程,暂时还没找到合适的画曲线的工具.以后找到合适工具再补充上,如果大家有推荐的工具,还请留言,谢谢了.
在这里插入图片描述

12->23->36->45->50->63->70->80->99

/**
     * 打印:中序遍历
     */
    public void printlnMiddleOrder() {
        //存储排序的结果
        StringBuilder middlerResult = new StringBuilder();
        //现将root赋给临时变量,防止改变root结点
        TreeNode temp = root;
        //开始中序遍历
        middleOrder(temp, middlerResult);
        //打印遍历的结果
        int length = middlerResult.toString().length();
        if (length > 0) {
            //去掉最后一个逗号(,)
            middlerResult.deleteCharAt(length - 1);
        }
        //组装打印格式,使用[]包起来
        middlerResult.insert(0, "[");
        middlerResult.append("]");
        System.out.println("中序遍历:" + middlerResult.toString());
    }

    /**
     * 中序遍历
     *
     * @param node   作为开始遍历的结点
     * @param result 存储遍历的所有结点的值
     */
    private void middleOrder(TreeNode node, StringBuilder result) {
        if (node != null) {
            //先遍历起左子树
            middleOrder(node.left, result);
            //打印根结点
            result.append(node.value).append(",");
            //遍历右子树
            middleOrder(node.right, result);
        }
    }

4.打印二叉树的深度

找到结点的层级,其中最深的那个就是树的深度.

/**
     * 打印深度,从1开始的
     */
    public int printTreeDepth() {
        TreeNode r = root;
        calDepth(r, 0);
        System.out.println("深度:" + mTreeDepth);
        return mTreeDepth;
    }

    /**
     * 计算深度
     * 使用的是递归办法寻找最深的结点的层级,最深的层级,就是树的结点深度
     *
     * @param node  开始遍历的开始结点
     * @param depth 当前结点的所在的层级
     */
    private void calDepth(TreeNode node, int depth) {
        if (node != null) {
            int d = depth;
            d++;
            //开始比较,当前的结点
            if (mTreeDepth < d) {
                mTreeDepth = d;
            }
            //遍历左子树
            calDepth(node.left, d);
            //遍历右子树
            calDepth(node.right, d);
        }
    }

非递归方法获取树的深度:
这是一个按照层级遍历树,每遍历一层,深度变量+1.

 /**
     * 非递归获取树的深度
     *
     * @return
     */
    public int getDepth() {
        int depth = 0;
        //1.先拿到根结点
        TreeNode temp = root;
        //2.存储同层的结点队列,尾插入
        Queue<TreeNode> queue = new LinkedList();
        //队尾:入队
        queue.offer(temp);
        //3.遍历队列
        while (!queue.isEmpty()) {
            //当前层级结点数
            int len = queue.size();
            //层级+1
            depth++;
            while ((len--) > 0) {
                //队头:出队列
                TreeNode node = queue.poll();
                if (node != null && node.left != null) {
                    //队尾:入队
                    queue.offer(node.left);
                }
                if (node != null && node.right != null) {
                    //队尾:入队
                    queue.offer(node.right);
                }
            }
        }
        return depth;
    }

5.打印指定层级的所有结点.

遍历找到指定层级结点,然后打印,我这里是先放在stringbuilder中,然后到最后才打印.


    /**
     * 打印指定高度的结点
     *
     * @param level 指定的层级
     */
    public void printNodesByLevel(int level) {
        TreeNode r = root;
        StringBuilder sb = new StringBuilder();
        //开始查找指定层的结点
        calAllNodeByLevel(r, 0, level, sb);

        int length = sb.toString().length();
        if (length > 0) {
            sb.deleteCharAt(length - 1);
        }
        sb.insert(0, "[");
        sb.append("]");
        System.out.println("第" + level + "层所有结点:" + sb.toString());

    }

    /**
     * 计算指定层的所有结点
     * 使用递归方法找到指定深度的节点,然后存储到字符串中
     *
     * @param node
     * @param depth
     * @param level
     * @param sb
     */
    private void calAllNodeByLevel(TreeNode node, int depth, int level, StringBuilder sb) {
        if (node != null) {
            int d = depth;
            d++;
            //找到了指定层级的结点,然后存储到sb中
            if (d == level) {
                sb.append(node.value).append(",");
            }
            calAllNodeByLevel(node.left, d, level, sb);
            calAllNodeByLevel(node.right, d, level, sb);
        }
    }

6.使用示例

lass Demo {
    public static void main(String[] agrs) {
        TwoBranchTree tree = new TwoBranchTree();
        int[] array = new int[]{50, 23, 45, 70, 63, 36, 80, 99, 12};
        //插入数据
        for (int i = 0, size = array.length; i < size; i++) {
            tree.insertOrderByLmr(array[i]);
        }
        //中序遍历
        tree.printlnMiddleOrder();
        //打印指定层的结点
        tree.printNodesByLevel(3);
        //打印深度
        tree.printTreeDepth();
    }

}
中序遍历:[12,23,36,45,50,63,70,80,99]
第3层所有结点:[12,45,63,80]
深度:4

7.扩展

1.这里是插入结点时按照(left<root<=right)规则插入,那么要想有序打印出,那么则要使用中序遍历.(left->root->right)
2.大家也可以根据例子,自己编写:
根据(left<right<=root)插入,若要有序打印出,则要使用后序遍历.
根据(root<left<=right)插入,若要有序打印出,则要使用前序遍历.

代码下载

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值