(Java)二叉树建立、递归遍历、非递归遍历(栈回溯)

数据结构与算法——二叉树建立、递归遍历、非递归遍历(栈回溯)

二叉树的建立与遍历

定义节点 Tree Node

public class TreeNode {
    Integer data;
    TreeNode leftNode;
    TreeNode rightNode;

    public TreeNode(Integer data) {
        this.data = data;
    }
}

二叉树的建立与遍历

/**
 * 构建二叉树
 */
public class BinaryTree {

    /**
     * 利用递归的思路前序构造二叉树
     * List没有removeFirst removeLast
     * LinkedList具有
     */
    public static TreeNode createBinaryTree(LinkedList<Integer> treeList){
        //需要构建的列表不为空
        if (treeList.isEmpty()||treeList==null){
            return null;
        }
        //声明一个节点
        TreeNode node = null;
        //从列表依次取出元素
        Integer data = treeList.removeFirst();
        if (data!=null){
            //构造一个节点的值
           node = new TreeNode(data);
           //构造一个节点的左节点,creatBinaryTree方法本身为取值并构造TreeNode,因而这里实现了自身的调用,实现了递归
           node.leftNode = createBinaryTree(treeList);
           node.rightNode = createBinaryTree(treeList);
        }
        return node;
    }


    /**
     * 实现前序遍历
     */
    public static void prefixOut(TreeNode node){
        if (node == null){
           return;
        }
        System.out.print(node.data);
        prefixOut(node.leftNode);
        prefixOut(node.rightNode);
    }
    /**
     * 实现中序遍历
     */
    public static void infixOut(TreeNode node){
        if (node == null){
            return;
        }
        infixOut(node.leftNode);
        System.out.print(node.data);
        infixOut(node.rightNode);
    }

    /**
     * 实现后续遍历
     */
    public static void suffixOut(TreeNode node){
        if (node == null){
            return;
        }
        suffixOut(node.leftNode);
        suffixOut(node.rightNode);
        System.out.print(node.data);
    }

    /**
     * 二叉树非递归实现前序遍历
     * 利用栈回溯的性质,从根节点开始入栈,左节点元素依次入栈,
     * 当左节点某个元素没有子节点时候出栈,这样可以访问其父节点的右子节点,
     * 因为父节点在能访问了左右节点已经无用,所以出栈,右子节点继续按之前步骤进行,
     * 直到栈空,遍历完所有的元素
     */
    public static void stackPrefixOut(TreeNode node){
        Stack<TreeNode> stack = new Stack<>();
        TreeNode treeNode = node;
        while (treeNode != null || !stack.empty()){
            //遍历访问左节点,入栈
            while (treeNode!=null){
                System.out.print(treeNode.data);
                stack.push(treeNode);
                treeNode = treeNode.leftNode;
            }
            //如果没有左节点,则弹出栈顶节点,访问其右节点
            if (!stack.empty()){
                treeNode = stack.pop();
                treeNode = treeNode.rightNode;
            }
        }
    }

    /**
     * 非递归中序遍历
     *
     */
    public static void stackInfixOut(TreeNode node){
        Stack<TreeNode> stack = new Stack<>();
        TreeNode treeNode = node;
        while (treeNode != null || !stack.empty()){
            //遍历访问左节点,入栈
            while (treeNode!=null){
                stack.push(treeNode);
                treeNode = treeNode.leftNode;
            }
            //如果左节点为空,则出栈,访问节点数据,向右节点继续访问
            //如果右节点为空就会出栈,访问的即是上一个节点
            if (!stack.empty()){
                treeNode = stack.pop();
                System.out.print(treeNode.data);
                treeNode = treeNode.rightNode;
            }
        }
    }

    /**
     * 非递归后序遍历:
     * 不同前两种情况,后序遍历需要保留上一次访问的节点,
     * 同时对当前节点右子节点做出判断
     * 视频讲解:
     * https://www.bilibili.com/video/BV18i4y1Z7am?spm_id_from=333.880.my_history.page.click&vd_source=c14320ad01bf4cf70bfe310257773013
     */
    public static void stackSuffixOut(TreeNode node){
        Stack<TreeNode> stack = new Stack<>();
        TreeNode curNode = node;//定义当前节点
        TreeNode preNode = node;//保留上一个访问的节点
        while (curNode != null || !stack.empty()){
            //遍历访问左节点,入栈
            while (curNode!=null){
                stack.push(curNode);
                curNode = curNode.leftNode;
            }
            //当左节点为空时,取栈顶元素(此时栈顶元素为当前)
            curNode = stack.peek();
            //访问右节点如果不为null,继续访问右节点
            if (curNode.rightNode != null && curNode.rightNode != preNode){ //(1)
                curNode = curNode.rightNode;
            }else{
                //右节点为空  访问当前节点数据
                System.out.print(curNode.data);
                preNode = curNode; //记录当前访问的节点,防止在回溯的过程中即(1)中出现判断失误导致回溯失败
                curNode = null; //当前节点设置为null防止重复访问
                stack.pop();
            }
        }
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值