zoukankan      html  css  js  c++  java
  • 二叉树的三序遍历

    如题。

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

    // 递归遍历很简单。
        // 跟着下面的,另外两个也很容易写。
        public void front()// 递归-前序遍历
        {
            System.out.print(v + "	");
            if (left != null)
            {
                left.front();
            }
            if (right != null)
            {
                right.front();
            }
        }
    
        // 中序后序,验证用。。。。。。。。。。。。。。。开始
        public void mid()
        {
            if (left != null)
            {
                left.mid();
            }
            System.out.print(v + "	");
            if (right != null)
            {
                right.mid();
            }
        }
    
        public void back()
        {
            if (left != null)
            {
                left.back();
            }
            if (right != null)
            {
                right.back();
            }
            System.out.print(v + "	");
        }
        // 中序后序,验证用。。。。。。。。。。。。。。。结束
    
        // 栈式前序遍历相对简单,每一轮压栈完成,栈顶都是可输出的节点,输出即可。
        // 对于后续有子节点的节点,拆散了按“右左根”的顺序(即先序遍历的反序)压栈。
        // 中序和后序就不太好写了。
        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 + "	");
            }
        }
    
        // 中序
        // 判断栈内节点是否是可输出的节点,需要对比它后一个节点是不是它的右节点。
        // (为什么不跟它前面的节点比较?因为它前面的节点会在操作中被打乱,无法直接判断)
        // 但考虑到某根节点的右子树为空,则无法确定它的左子树是否已经入栈(如根节点右子树为空,左子树已全部入栈;不是根节点,则未入栈)。
        //也就无法确定该点应该输出或压栈。
      //所以,上述想法仅对于满二叉树有效。
    //一种思路: //在某子树分“右根左”三部分入栈的时候,如果考虑把根节点的左右指针全部打断,它也就变相成了一个“能够输出”的标记。 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 + " "); } 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 + " "); } 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 + "	");
                    }
                    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 + "	");
                    }
                    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);
                        }
                    }
                }
            }

    前序遍历道理类似。

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

    大家可以自行完成。


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

  • 相关阅读:
    (转)HTTP协议
    函数深入理解---函数的定义方式
    DOM模型和事件处理---事件处理
    DOM模型和事件处理---节点操作
    DOM模型和事件处理---基本操作
    常用知识
    窗口对象
    简单的事件处理
    Grunt
    基本操作
  • 原文地址:https://www.cnblogs.com/wanjinliu/p/13971990.html
Copyright © 2011-2022 走看看