• 二叉树遍历


    概念

    二叉树的遍历有 先序、中序、后续遍历

    • 先序遍历
      当前节点 - 左子节点 - 右子节点
      a-b-d-e-c-f
    • 中序遍历
      左子节点 - 当前节点 - 右子节点
      d-b-e-a-f-c
    • 后续遍历
      左子节点 - 右子节点 - 当前节点
      d-e-b-f-c-a

    递归方式遍历

    这种方式比较简单

    // 先序遍历
    public static List visitBefore(BinaryNode root)
    {
        List list = new ArrayList<>();
        if (root == null)
        {
            return new ArrayList<>();
        }
        list.add(root.getData());
        // 遍历左子树
        list.addAll(visitBefore(root.getLeft()));
        // 遍历右子树
        list.addAll(visitBefore(root.getRight()));
        return list;
    }
    
    // 中序遍历
    public static List visitMiddle(BinaryNode root)
    {
        List list = new ArrayList<>();
        if (root == null)
        {
            return new ArrayList<>();
        }
        // 遍历左子树
        list.addAll(visitMiddle(root.getLeft()));
        list.add(root.getData());
        // 遍历右子树
        list.addAll(visitMiddle(root.getRight()));
        return list;
    }
    // 后序遍历
    public static List visitAfter(BinaryNode root)
    {
        List list = new ArrayList<>();
        if (root == null)
        {
            return new ArrayList<>();
        }
        // 遍历左子树
        list.addAll(visitAfter(root.getLeft()));
        // 遍历右子树
        list.addAll(visitAfter(root.getRight()));
        list.add(root.getData());
        return list;
    }
    

    非递归方式遍历

    使用P指针,指向root节点。用P来画个轨迹,遍历整个二叉树。

    1. 如果P有左子节点,将P入栈,P指向它的左子节点,该次循环结束
    2. 如果P有没有左子节点,有右子节点,P指向它的右子节点
    3. 如果P没有左子节点、也没有右子节点,说明已经走到了左下角。
      开始回溯,从栈中寻找有右子节点的元素,并将P指向右子节点
      P的运动轨迹为:
    // 非递归遍历,中序遍历
    public static List visitStackMiddle(BinaryNode root)
    {
        List list = new ArrayList<>();
        BinaryNode p = root;
        SeqStack<BinaryNode> stack = new SeqStack<>();
        while (p != null)
        {
            if (p.getLeft() != null) // 1.如果有左子节点,P节点入栈
            {
                stack.push(p);
                p = p.getLeft();
            }
            else // 2. 如果没有左子节点
            {
                // 2.1 访问当前节点
                list.add(p.getData());
    
                if (p.getRight() != null) // 如果有右子节点,访问右节点
                {
                    p = p.getRight();
                }
                else  // 若没有右节点,寻找栈顶元素直到找到有右节点的元素
                {
                    while (!stack.empty() && stack.top().getRight() == null)  // 栈顶元素没有右节点,直接访问
                    {
                        list.add(stack.pop().getData());
                    }
                    if (stack.empty())
                    {
                        break;
                    }
                    // 输出栈顶元素
                    list.add(stack.top().getData());
                    p = stack.pop().getRight();
                }
            }
        }
    
        return list;
    }
    
    // 非递归遍历,先序遍历
    public static List visitStackBefore(BinaryNode root)
    {
        List list = new ArrayList<>();
        BinaryNode p = root;
        SeqStack<BinaryNode> stack = new SeqStack<>();
        while (p != null)
        {
            // 先序遍历,首先输出当前节点
            list.add(p.getData());
            if (p.getLeft() != null) // 1.如果有左子节点,P节点入栈
            {
                stack.push(p);
                p = p.getLeft();
            }
            else // 2. 如果没有左子节点
            {
    
                if (p.getRight() != null) // 如果有右子节点,访问右节点
                {
                    p = p.getRight();
                }
                else  // 若没有右节点,寻找栈顶元素直到找到有右节点的元素
                {
                    while (!stack.empty() && stack.top().getRight() == null)  // 栈顶元素没有右节点,直接访问
                    {
                        stack.pop().getData();
                    }
                    if (stack.empty())
                    {
                        break;
                    }
                    // 输出栈顶元素
                    p = stack.pop().getRight();
                }
            }
        }
    
        return list;
    }
    
    // 非递归遍历,后序遍历
    public static List visitStackAfter(BinaryNode root)
    {
        List list = new ArrayList<>();
        BinaryNode p = root;
        SeqStack<BinaryNode> stack = new SeqStack<>();
        BinaryNode last = null;
        while (p != null)
        {
            if (p.getLeft() != null) // 1.如果有左子节点,P节点入栈
            {
                stack.push(p);
                p = p.getLeft();
            }
            else // 2. 如果没有左子节点
            {
                if (p.getRight() != null) // 如果有右子节点,访问右节点
                {
                    last = p;  // P节点未访问,需要寄存
                    p = p.getRight();
                }
                else  // 若没有右节点,寻找栈顶元素直到找到有右节点的元素
                {
                    // 访问当前元素
                    list.add(p.getData());  // 访问数据位置
                    while (!stack.empty() && stack.top().getRight() == null)  // 栈顶元素没有右节点,直接访问
                    {
                        // 如果栈顶元素没有右节点,直接访问,并弹出
                        list.add(stack.pop().getData());
                    }
                    if (stack.empty())
                    {
                        break;
                    }
                    if (last != null)
                    {
                        list.add(last.getData());
                    }
                    // 使用寄存器 存储上一个中间值
                    last = stack.top();
                    // 输出栈顶元素
                    p = stack.pop().getRight();
                }
            }
        }
        if (last != null)
        {
            list.add(last.getData());
        }
    
        return list;
    }
    

    逐层遍历

    使用队列,比较简单。

    // 层次遍历
    public static List visitLayer(BinaryNode root)
    {
        List list = new ArrayList<>();
        // 定义一个队列
        Queue<BinaryNode> queue = new LinkedBlockingDeque<>();
        if (root == null)
        {
            return new ArrayList<>();
        }
        queue.add(root);
        while (!queue.isEmpty())
        {
            // 处理一层,将队列中的所有元素逐个出列,并把该元素的子节点加入队列汇总
            int size = queue.size();
            for (int i = 0; i < size; i++)
            {
                BinaryNode peek = queue.poll();
                list.add(peek.getData());
                if (peek.getLeft() != null)
                {
                    queue.add(peek.getLeft());
                }
                if (peek.getRight() != null)
                {
                    queue.add(peek.getRight());
                }
            }
    
        }
        return list;
    }
    
  • 相关阅读:
    VUE项目开发流程
    vue-导入element-ui
    微信小程序开发-踩坑
    python-编码问题
    python-导入自定义模块
    maven安装配置
    npm修改源
    gitlab使用指南
    Wox使用指南
    Linux拷贝文件夹
  • 原文地址:https://www.cnblogs.com/zhuxiang1633/p/14165159.html
Copyright © 2020-2023  润新知