Java 数据结构与算法 二叉树的常见操作

下面通过一个实例来简单实现下二叉树的常见操作

创建一个树结构TreeNode类:

/**
 * 二叉树结构 - 子节点
 */
public class TreeNode {
    Object data;//泛型数据对象
    TreeNode lchild;//左子节点
    TreeNode rchild;//右子节点

    //默认构造方法
    public TreeNode(Object data,TreeNode lchild,TreeNode rchild) {
        this.data = data;
        this.lchild = lchild;
        this.rchild = rchild;
    }

    //不传参数,就调用默认上面的默认构造方法
    public TreeNode(){
        this(null,null,null);
    }

    //只传data参数,就调用默认上面的默认构造方法
    public TreeNode(Object data){
        this(data,null,null);
    }


    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("TreeNode{");
        sb.append("data=").append(data);
        if(lchild != null)
            sb.append(", lchild=").append(lchild);
        if(rchild != null)
            sb.append(", rchild=").append(rchild);
        sb.append('}');
        return sb.toString();
    }
}

对二叉树的各种操作具体实现OptionTree类

import java.util.*;

/**
 * 二叉树的操作
 */
public class OptionTree {
    //1.1前序遍历,递归实现
    public void preorder1(TreeNode root){
        if(root != null){
            System.out.print(root.data+"\t");
            preorder1(root.lchild);
            preorder1(root.rchild);
        }
    }

    //1.2前序遍历,迭代和栈实现
    public void preorder2(TreeNode root){
        if(root != null){
            Stack<TreeNode> stack = new Stack<>();
            stack.push(root);//初始化,先将头结点入栈

            while (!stack.isEmpty()){
                root = stack.pop();
                System.out.print(root.data+"\t");//打印根节点或者右节点
                while (root != null){
                    if(root.lchild != null)
                        System.out.print(root.lchild.data+"\t");//打印左节点
                    if(root.rchild != null)
                        stack.push(root.rchild);//右节点入栈
                    root = root.lchild;//遍历左节点直到为最后一个左节点
                }
            }
        }

    }

    //2.1中序遍历,递归实现
    public void inorder1(TreeNode root){
        if(root != null){
            inorder1(root.lchild);
            System.out.print(root.data+"\t");
            inorder1(root.rchild);
        }
    }

    //2.2中序遍历,迭代和栈实现
    public void inorder2(TreeNode root){
        if(root !=null){
            Stack<TreeNode> stack = new Stack<>();
            while (root != null || !stack.empty()){//遍历右子树
                while(root != null){//每次遍历将左子树入栈
                    stack.push(root);
                    root = root.lchild;
                }
                root = stack.pop();
                System.out.print(root.data+"\t");
                root = root.rchild;
            }

        }
    }

    //3.1后序遍历,递归实现
    public void backorder1(TreeNode root){
        if(root != null){
            backorder1(root.lchild);
            backorder1(root.rchild);
            System.out.print(root.data+"\t");
        }
    }

    //3.2后序遍历,迭代和栈实现
    public void backorder2(TreeNode root){
        Stack<TreeNode> stack1 = new Stack<>();
        Stack<Integer> stack2 = new Stack<>();
        int i = 1;
        while(root != null || !stack1.empty())
        {
            while (root != null)
            {
                stack1.push(root);
                stack2.push(0);
                root = root.lchild;
            }

            while(!stack1.empty() && stack2.peek() == i)
            {
                stack2.pop();
                System.out.print(stack1.pop().data + "\t");
            }

            if(!stack1.empty())
            {
                stack2.pop();
                stack2.push(1);
                root = stack1.peek();
                root = root.rchild;
            }
        }

    }

    //4 层序遍历 - 使用队列来存储每一层的左右子结点
    public void levelorder(TreeNode root){
        if(root != null){
            Queue<TreeNode> queue = new LinkedList<>();
            queue.offer(root);//最开始将头结点添加到队列
            while (!queue.isEmpty()){
                //每次取出队列头部元素,并更新root的最新位置
                root = queue.poll();
                System.out.print(root.data+"\t");
                if(root.lchild != null)
                    queue.offer(root.lchild);
                if(root.rchild != null)
                    queue.offer(root.rchild);
            }
        }
    }

   // 使用前序遍历查找指定结点
    public void searchBypreorder(TreeNode root,Object data){
        if(root != null){
            if(root.data == data){
                System.out.println("找到该节点:"+root);
                return;
            }
            searchBypreorder(root.lchild,data);
            searchBypreorder(root.rchild,data);
        }
    }

    // 使用前序遍历统计结点个数
    public int countNodesBypreorder(TreeNode root){
        int count = 0;
        if(root != null){
            count++;//遍历到当前结点,就+1
            count += countNodesBypreorder(root.lchild);//遍历左节点,最终个数加到count
            count += countNodesBypreorder(root.rchild);//遍历右节点,最终个数加到count
        }
        return count;
    }

    // 求二叉树的深度 - 递归实现
    public int getDeep1(TreeNode root){
        if(root!=null){
            int left =  getDeep1(root.lchild);
            int right =  getDeep1(root.rchild);
            return left>right ? left+1 : right+1;
        }
        return 0;
    }

    /**
     * 求二叉树的深度 - 广度优先迭代实现
     * 参考层序遍历,每遍历一层,变量+1
     */
    public int getDeep2(TreeNode root){
        if(root !=null){
            int res = 0;//记录层数
            Queue<TreeNode> queue = new LinkedList<>();
            queue.offer(root);
            while (!queue.isEmpty()){
                int size = queue.size();
                while (size > 0){
                    TreeNode nowfloor = queue.poll();//当前层的第一个结点
                    if(nowfloor.lchild!= null)
                        queue.offer(nowfloor.lchild);
                    if(nowfloor.rchild != null)
                        queue.offer(nowfloor.rchild);
                    size--;
                }
                res++;//当前层遍历完,层数就+1
            }
            return res;
        }
        return 0;
    }
}

测试类:Test

/**
 * 假设二叉树结构如下
 *              50
 *            /    \
 *          45      70
 *         /  \    /  \
 *       30   55  65   80
 *      /  \
 *    20    25
 */

public class Test {
    public static void main(String[] args) {
        //初始化各节点
        TreeNode treeNode5 = new TreeNode(55);
        TreeNode treeNode6 = new TreeNode(65);
        TreeNode treeNode7 = new TreeNode(80);
        TreeNode treeNode8 = new TreeNode(20);
        TreeNode treeNode9 = new TreeNode(25);
        //给四个有子结点的进行赋值的同时赋值子结点
        TreeNode treeNode4 = new TreeNode(30,treeNode8,treeNode9);
        TreeNode treeNode3 = new TreeNode(70,treeNode6,treeNode7);
        TreeNode treeNode2 = new TreeNode(45,treeNode4,treeNode5);
        TreeNode root = new TreeNode(50,treeNode2,treeNode3);



        OptionTree optionTree = new OptionTree();
//        optionTree.preorder1(root);
//        System.out.println("");
//        optionTree.preorder2(root);
//        System.out.println("");

//        optionTree.inorder1(root);
//        System.out.println("");
//        optionTree.inorder2(root);
//        System.out.println("");

//        optionTree.backorder1(root);
//        System.out.println("");
//        optionTree.backorder2(root);
//        System.out.println("");

//        optionTree.levelorder(root);

//        optionTree.searchBypreorder(root,45);

//        System.out.println( optionTree.countNodesBypreorder(root));

//        System.out.println("\n"+optionTree.getDeep1(root));
//        System.out.println(optionTree.getDeep2(root));
    }
}

猜你喜欢

转载自blog.csdn.net/c_o_d_e_/article/details/110327256
今日推荐