万金流
以码会友。 吾Q:578751655。 水平有限,轻喷,谢!
随笔 - 189,  文章 - 0,  评论 - 7,  阅读 - 14万

如题。

二叉树类代码的基础上,三序遍历JAVA代码如下:

复制代码
// 递归遍历很简单。
    // 跟着下面的,另外两个也很容易写。
    public void front()// 递归-前序遍历
    {
        System.out.print(v + "\t");
        if (left != null)
        {
            left.front();
        }
        if (right != null)
        {
            right.front();
        }
    }

    // 中序后序,验证用。。。。。。。。。。。。。。。开始
    public void mid()
    {
        if (left != null)
        {
            left.mid();
        }
        System.out.print(v + "\t");
        if (right != null)
        {
            right.mid();
        }
    }

    public void back()
    {
        if (left != null)
        {
            left.back();
        }
        if (right != null)
        {
            right.back();
        }
        System.out.print(v + "\t");
    }
    // 中序后序,验证用。。。。。。。。。。。。。。。结束

    // 栈式前序遍历相对简单,每一轮压栈完成,栈顶都是可输出的节点,输出即可。
    // 对于后续有子节点的节点,拆散了按“右左根”的顺序(即先序遍历的反序)压栈。
    // 中序和后序就不太好写了。
    public void front_Stack()// 栈-前序遍历
    {
        Stack<MyBinaryNode> stack_treenode = new Stack<MyBinaryNode>();
        MyBinaryNode t;
        stack_treenode.push(this);
        while (!stack_treenode.empty())
        {
            t = stack_treenode.pop();
            if (t.right != null)
            {
                stack_treenode.push(t.right);
            }
            if (t.left != null)
            {
                stack_treenode.push(t.left);
            }
            System.out.print(t.v + "\t");
        }
    }

    // 中序
    // 判断栈内节点是否是可输出的节点,需要对比它后一个节点是不是它的右节点。
    // (为什么不跟它前面的节点比较?因为它前面的节点会在操作中被打乱,无法直接判断)
    // 但考虑到某根节点的右子树为空,则无法确定它的左子树是否已经入栈(如根节点右子树为空,左子树已全部入栈;不是根节点,则未入栈)。
    //也就无法确定该点应该输出或压栈。
  //所以,上述想法仅对于满二叉树有效。
//一种思路: //在某子树分“右根左”三部分入栈的时候,如果考虑把根节点的左右指针全部打断,它也就变相成了一个“能够输出”的标记。 public void middle_Stack() { Stack<MyBinaryNode> stack_treenode = new Stack<MyBinaryNode>(); MyBinaryNode t; stack_treenode.push(this); while (!stack_treenode.empty()) { t = stack_treenode.pop(); if (t.right == null && t.left == null)/* 它可输出 */ { System.out.print(t.v + "\t"); } else { if (t.right != null) { stack_treenode.push(t.right); } stack_treenode.push(t); if (t.left != null) { stack_treenode.push(t.left); } t.left=t.right=null;/*再弹出这个节点的时候就可以输出了*/ } } } //后序遍历思想类似 public void back_Stack() { Stack<MyBinaryNode> stack_treenode = new Stack<MyBinaryNode>(); MyBinaryNode t; stack_treenode.push(this); while (!stack_treenode.empty()) { t = stack_treenode.pop(); if (t.right == null && t.left == null)/* 它可输出 */ { System.out.print(t.v + "\t"); } else { stack_treenode.push(t); if (t.right != null) { stack_treenode.push(t.right); } if (t.left != null) { stack_treenode.push(t.left); } t.left=t.right=null;/*再弹出这个节点的时候就可以输出了*/ } } }
复制代码

这样做会带来问题,以下用C#进行说明和演示:

复制代码
//可这样操作会破坏树结构。
        //验证:运行mid_Stack()之后运行back_Stack()。
        //解决这个问题,可以为这个树结构的每个节点引入一个标志位,来说明这个节点是否可以输出。
        //也可以用另一个栈来专门存储状态,和这个栈同进同出。

        //中序
        public void middle_Stack1()
        {
            Stack<MyBinaryNode> stack_treenode = new Stack<MyBinaryNode>();
            //本栈存放对应节点的状态(T/F),表示它是否应直接输出。
            Stack<bool> stack_status = new Stack<bool>();
            MyBinaryNode t;
            bool status;
            stack_treenode.Push(this);
            stack_status.Push(false);
            while (!(stack_treenode.Count == 0))
            {
                t = stack_treenode.Pop();
                status = stack_status.Pop();
                if (t.right == null && t.left == null||status==true)/* 它可输出 */
                {
                    Console.Write(t.v + "\t");
                }
                else
                {
                    if (t.right != null)
                    {
                        stack_treenode.Push(t.right);
                        stack_status.Push(false);
                    }
                    stack_treenode.Push(t);
                    stack_status.Push(true);
                    if (t.left != null)
                    {
                        stack_treenode.Push(t.left);
                        stack_status.Push(false);
                    }
                }
            }
        }
        //后序
        public void back_Stack1()
        {
            Stack<MyBinaryNode> stack_treenode = new Stack<MyBinaryNode>();
            //本栈存放对应节点的状态(T/F),表示它是否应直接输出。
            Stack<bool> stack_status = new Stack<bool>();
            MyBinaryNode t;
            bool status;
            stack_treenode.Push(this);
            stack_status.Push(false);
            while (!(stack_treenode.Count == 0))
            {
                t = stack_treenode.Pop();
                status = stack_status.Pop();
                if (t.right == null && t.left == null || status == true)/* 它可输出 */
                {
                    Console.Write(t.v + "\t");
                }
                else
                {
                    stack_treenode.Push(t);
                    stack_status.Push(true);
                    if (t.right != null)
                    {
                        stack_treenode.Push(t.right);
                        stack_status.Push(false);
                    }
                    if (t.left != null)
                    {
                        stack_treenode.Push(t.left);
                        stack_status.Push(false);
                    }
                }
            }
        }
复制代码

前序遍历道理类似。

在树节点中使用标志位道理也类似。

大家可以自行完成。


 层序遍历,借助队列很容易完成,此处略。

 

posted on   万金流  阅读(204)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现

点击右上角即可分享
微信分享提示