数据结构与算法(Java)之二叉树

Posted 达少Rising

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法(Java)之二叉树相关的知识,希望对你有一定的参考价值。

二叉树

package com.weeks.tree;

/**
 * @author 达少
 * @version 1.0
 *
 * 实现二叉树数据结构
 */
public class BinaryTreeDemo {
    public static void main(String[] args) {
        //定义二叉树
        BinaryTree binaryTree = new BinaryTree();
        //定义二叉树的节点对象
        HeroNode node1 = new HeroNode(1, "宋江");
        HeroNode node2 = new HeroNode(2, "吴用");
        HeroNode node3 = new HeroNode(3, "卢俊义");
        HeroNode node4 = new HeroNode(4, "林冲");
        HeroNode node5 = new HeroNode(5, "关胜");
        //这里先使用手动创建二叉树,以后可以使用递归方式创建
        binaryTree.setRoot(node1);
        node1.setLeft(node2);
        node1.setRight(node3);
        node3.setRight(node4);
        node3.setLeft(node5);

        //测试前序遍历
//        System.out.println("前序遍历");
//        binaryTree.preOrder();//1,2,3,5,4

        //测试中序遍历
//        System.out.println("中序遍历");
//        binaryTree.infixOrder();//2,1,5,3,4

        //测试后续遍历
//        System.out.println("后续遍历");
//        binaryTree.postOrder();//2,5,4,3,1

        //测试前序查找
//        HeroNode resNode = binaryTree.preOrderSearch(5);
//        HeroNode resNode = binaryTree.infixOrderSearch(5);
//        HeroNode resNode = binaryTree.postOrderSearch(5);
//        if(resNode != null){
//            System.out.printf("找到了结点id = %d, name = %s\\n", resNode.getNo(), resNode.getName());
//        }else{
//            System.out.println("没有找到要查找的结点!!!");
//        }

        System.out.println("删除前的二叉树(前序遍历)");
        binaryTree.preOrder();
        //删除no=5的结点
        binaryTree.delNode(5);
        System.out.println("删除后的二叉树(前序遍历)");
        binaryTree.preOrder();
    }
}

//定义二叉树类
class BinaryTree{
    private HeroNode root;//根结点

    public HeroNode getRoot() {
        return root;
    }

    public void setRoot(HeroNode root) {
        this.root = root;
    }

    //前序遍历
    public void preOrder(){
        if(root == null){
            return;
        }
        root.preOrder();
    }

    //中序遍历
    public void infixOrder(){
        if(root == null){
            return;
        }
        root.infixOrder();
    }

    //后序遍历
    public void postOrder(){
        if(root == null){
            return;
        }
        root.postOrder();
    }

    //前序查找
    public HeroNode preOrderSearch(int no){
        if(root == null){
            return null;
        }
        return root.preOrderSearch(no);
    }

    //中序查找
    public HeroNode infixOrderSearch(int no){
        if(root == null){
            return null;
        }
        return root.infixOrderSearch(no);
    }

    //后序查找
    public HeroNode postOrderSearch(int no){
        if(root == null){
            return null;
        }
        return root.postOrderSearch(no);
    }

    //删除结点
    public void delNode(int no){
        //判断二叉树是否为空
        if(root == null){
            return;
        }
        //判断根节点是否符合删除条件,符合则将整棵树置空后返回
        if(root.getNo() == no){
            root = null;
            return;
        }else{//否则执行HeroNode中的delNode操作
            root.delNode(no);
        }
    }
}

//定义树的结点对象类
class HeroNode{
    private int no;
    private String name;
    private HeroNode left;
    private HeroNode right;

    public HeroNode(int no, String name){
        this.no = no;
        this.name = name;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public HeroNode getLeft() {
        return left;
    }

    public void setLeft(HeroNode left) {
        this.left = left;
    }

    public HeroNode getRight() {
        return right;
    }

    public void setRight(HeroNode right) {
        this.right = right;
    }

    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\\'' +
                '}';
    }

    //前序遍历
    public void preOrder(){
        //先输出当前结点
        System.out.println(this);
        //递归遍历左子树
        if(this.left != null){
            this.left.preOrder();
        }
        //递归遍历右子树
        if(this.right != null){
            this.right.preOrder();
        }
    }

    //中序遍历
    public void infixOrder(){
        //递归遍历左子树
        if(this.left != null){
            this.left.infixOrder();
        }
        //输出当前结点
        System.out.println(this);
        //递归遍历右子树
        if(this.right != null){
            this.right.infixOrder();
        }
    }

    //后序遍历
    public void postOrder(){
        //递归遍历左子树
        if(this.left != null){
            this.left.postOrder();
        }
        //递归遍历右子树
        if(this.right != null){
            this.right.postOrder();
        }
        //输出当前结点
        System.out.println(this);
    }

    //前序查找
    /**
     *
     * @param no 需要查找的编号
     * @return 找到就返回该结点,否则返回null
     */
    public HeroNode preOrderSearch(int no){
        //判断该结点是否为查找的结点
        if(this.no == no){
            return this;//找到就返回该结点
        }

        HeroNode resNode = null;
        //如果不是当前结点就递归左子树查找
        if(this.left != null){
            resNode = this.left.preOrderSearch(no);
        }
        //如果在左子树找到就返回
        if(resNode != null){
            return resNode;
        }

        //在左子树没有找到,那么向右子树查找
        if(this.right != null){
            resNode = this.right.preOrderSearch(no);
        }

        //无论找没找到最后返回
        return resNode;//返回不为空就是找打了,返回空就是没有找到
    }

    //中序查找
    public HeroNode infixOrderSearch(int no){
        HeroNode resNode = null;
        //向左子树递归查找
        if(this.left != null){
            resNode = this.left.infixOrderSearch(no);
        }
        //如果在左子树找到则返回
        if(resNode != null){
            return resNode;
        }

        //判断该节点是否为查找的结点
        if(this.no == no){
            return this;
        }

        //向左右子树遍历查找
        if(this.right != null){
            resNode = this.right.infixOrderSearch(no);
        }
        return resNode;
    }

    //后序查找
    public HeroNode postOrderSearch(int no){
        HeroNode resNode = null;
        //向左子树递归查找
        if(this.left != null){
            resNode = this.left.postOrderSearch(no);
        }
        //如果在左子树找到则返回
        if(resNode != null){
            return resNode;
        }
        //向左右子树遍历查找
        if (this.right != null){
            resNode = this.right.postOrderSearch(no);
        }
        //判断该节点是否为查找的结点
        if(this.no == no){
            return this;
        }
        return resNode;
    }

    //删除结点
    /**
     * 约定:
     * 如果删除的是叶子结点,则直接删除
     * 如果不是也只结点直接删除以该节点为父节点的子树
     */
    public void delNode(int no){
        /**
         * 1.因为要现在创建的二叉树是单向的,要删除只能找到父节点分别判断左右结点是否符合
         *   删除的条件,所以首先判断左子树是否有符合删除的条件的结点,递归实现
         * 2.接下来是递归判断右子树中是否有符合删除条件的结点
         */
        //判断该节点是否有左子树并判断左子树是否符合删除条件
        if(this.left != null && this.left.no == no){
            //如果左子树符合删除条件,将左子树置空,并返回
            this.left = null;
            return;
        }
        //判断该节点是否有右子树并判断右子树是否符合删除条件
        if(this.right != null && this.right.no == no){
            //如果右子树符合删除条件,将右子树置空,并返回
            this.right = null;
            return;
        }
        //递归判断左子树
        if(this.left != null){
            this.left.delNode(no);
        }

        //递归判断右子树
        if(this.right != null){
            this.right.delNode(no);
        }
    }
}

顺序存储二叉树

package com.weeks.tree;

import java.util.ArrayList;

/**
 * @author 达少
 * @version 1.0
 *
 * 顺序存储二叉树
 */
public class ArrayBinaryTreeDemo {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5, 6, 7};
        ArrayBinaryTree arrayBinaryTree = new ArrayBinaryTree(arr);
//        arrayBinaryTree.preOrder();
//        arrayBinaryTree.infixOrder();
        arrayBinaryTree.postOrder();
    }
}

//顺序存储二叉树,就是使用数组存储二叉树,并保留前中后序遍历的特点
class ArrayBinaryTree{
    private int[] arr;

    public ArrayBinaryTree(int[] arr){
        this.arr = arr;
    }

    //前序遍历
    /**
     *
     * @param index 从数组的index下标开始遍历
     */
    public void preOrder(int index){
        //判断数组是否为空,为空则返回
        if(arr == null){
            return;
        }
        //输出当前结点的值
        System.out.println(arr[index]);
        //递归遍历左子树,在数组中左子树的下标是(2 * index + 1)
        if((2 * index + 1) < arr.length){//要判断下标是否越界数组
            preOrder(2 * index + 1);
        }
        //递归遍历左子树,在数组中左子树的下标是(2 * index + 2)
        if((2 * index + 2) < arr.length){
            preOrder(2 * index + 2);
        }
    }

    //我们一般都是从根节点开始遍历,所以一般index = 0
    //重载preOrder函数方便调用,不用传入参数
    public void preOrder(){
        preOrder(0);
    }

    //仿照前序遍历,写出中序遍历
    public void infixOrder(int index){
        if(arr == null){
            return;
        }
        if((2 * index + 1) < arr.length){
            infixOrder(2 * index + 1);
        }
        System.out.println(arr[index]);
        if((2 * index + 2) < arr.length){
            infixOrder(2 * index + 2);
        }
    }
    public void infixOrder(){
        infixOrder(0);
    }

    //后序遍历
    public void postOrder(int index){
        if(arr == null){
            return;
        }
        if((2 * index + 1) < arr.length){
            postOrder(2 * index + 1);
        }
        if((2 * index + 2) < arr.length){
            postOrder(2 * index + 2);
        }
        System.out.println(arr[index]);
    }
    public void postOrder(){
        postOrder(0);
    }
}

线索二叉树

package com.weeks.tree.threadedbinarytree;

/**
 * @author 达少
 * @version 1.0
 * 线索化二叉树
 */
public class ThreadedBinaryTreeDemo {
    public static void main(String[] args) {
        HeroNode node1 = new HeroNode(1, "tom");
        HeroNode node2 = new HeroNode(3, "jack");
        HeroNode node3 = new HeroNode(6, "smith");
        HeroNode node4 = new HeroNode(8, "milan");
        HeroNode node5 = new HeroNode(10, "adair");
        HeroNode node6 = new 

以上是关于数据结构与算法(Java)之二叉树的主要内容,如果未能解决你的问题,请参考以下文章

JAVA数据结构与算法之二叉树

java数据结构与算法之二叉树的最大宽度和最大深度问题

java数据结构与算法之二叉树的最大宽度和最大深度问题

java数据结构与算法之二叉树深度优先和广度优先遍历

数据结构与算法之二叉树

数据结构与算法实验报告之二叉树高度的求解