Bin Tree Post Order Traversal,No recursion,no node flag

时间:2010-08-05 08:32:33

标签: c# algorithm iteration binary-tree tree-traversal

还有其他办法吗?花了2个小时试图解决它。我有一个解决方案(参见下面的DumpPostOrder)但是,有更好或更有效的方法吗?感觉可能有。规则是 - 没有递归,节点不能有访问标志。即,你只能使用左+右成员。

我的方法是在这个过程中破坏树。通过将每一边的子节点设置为null,您可以将节点标记为遍历一次,但我也会查看每个节点有两次子节点:(。有更好的更快方式吗?(对我的预订和顺序实现的评论表示赞赏)但没有必要(即投票,但没有标记答案)。谢谢!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BinaryTreeNoRecursion
{
    public class TreeNode<T>
    {
        public T Value { get; set; }

        public TreeNode<T> Left { get; set; }
        public TreeNode<T> Right { get; set; }

        public TreeNode(T inValue)
        {            
            Value = inValue;
        }

        public TreeNode(TreeNode<T> left, TreeNode<T> right, T inValue)
        {
            Left = left;
            Right = right;
            Value = inValue;
        }
    }

    public class BinaryTree<T>
    {
        private TreeNode<T> root;
        public TreeNode<T> Root
        {
            get { return root; }            
        }

        public BinaryTree(TreeNode<T> inRoot)
        {
            root = inRoot;
        }

        public void DumpPreOrder(T[] testme)
        {
            Stack<TreeNode<T>> stack = new Stack<TreeNode<T>>();
            stack.Push(root);
            int count =0;
            while (true)
            {
                if (stack.Count == 0) break;

                TreeNode<T> temp = stack.Pop();                

                if (!testme[count].Equals(temp.Value)) throw new Exception("fail");

                if (temp.Right != null)
                {
                    stack.Push(temp.Right);
                }

                if (temp.Left != null)
                {
                    stack.Push(temp.Left);
                }

                count++;
            }

        }

        public void DumpPostOrder(T[] testme)
        {

            Stack<TreeNode<T>> stack = new Stack<TreeNode<T>>();
            TreeNode<T> node = root;
            TreeNode<T> temp;
            int count = 0;
            while(node!=null || stack.Count!=0) 
            {   
                if (node!=null)
                {
                    if (node.Left!=null)
                    {                       
                        temp = node;
                        node = node.Left;
                        temp.Left = null;
                        stack.Push(temp);                        

                    }
                    else
                    if (node.Right !=null)
                    {
                        temp = node;
                        node = node.Right;
                        temp.Right= null;
                        stack.Push(temp);
                    }           
                    else //if the children are null
                    {
                        if (!testme[count].Equals(node.Value)) throw new Exception("fail");
                        count++;
                        if (stack.Count != 0)
                        {
                            node = stack.Pop();
                        }
                        else
                        {
                            node = null;
                        }
                    }       
                }
            }

        }

        public void DumpInOrder(T[] testme)
        {

            Stack<TreeNode<T>> stack = new Stack<TreeNode<T>>();            
            TreeNode<T> temp = root;
            int count = 0;
            while (stack.Count!=0 || temp!=null)
            {                
                if (temp != null)
                {                    
                    stack.Push(temp);
                    temp = temp.Left;
                }
                else
                {
                    temp = stack.Pop();
                    if (!testme[count].Equals(temp.Value)) throw new Exception("fail");
                    count++;          
                    temp = temp.Right;
                }

            }
        }

    }


    class Program
    {
        static void Main(string[] args)
        {
            //create a simple tree
            TreeNode<int> node = new TreeNode<int>(100);
            node.Left = new  TreeNode<int>(50);
            node.Right = new  TreeNode<int>(150);
            node.Left.Left = new TreeNode<int>(25);
            node.Left.Right = new TreeNode<int>(75);
            node.Right.Left  = new TreeNode<int>(125);
            node.Right.Right = new TreeNode<int>(175);
            node.Right.Left.Left = new TreeNode<int>(110);

            int[] preOrderResult = { 100, 50, 25, 75, 150, 125, 110, 175};
            int[] inOrderResult = { 25, 50, 75, 100, 110, 125, 150, 175};
            int[] postOrderResult = { 25, 75, 50, 110, 125, 175, 150, 100 };
            BinaryTree<int> binTree = new BinaryTree<int>(node);

            //do the dumps, verify output
            binTree.DumpPreOrder(preOrderResult);
            binTree.DumpInOrder(inOrderResult);
            binTree.DumpPostOrder(postOrderResult);
        }
    }
}

4 个答案:

答案 0 :(得分:1)

对我来说,在穿越它时摧毁树是非常残酷的。

您目前正在构建访问过的节点集合。

您通过将节点设置为null来将节点标记为已访问。

您是否可以通过检查收藏中的节点来检查访问情况?为了提高效率,您可能不需要使用Stack,但这是一个实现细节。

答案 1 :(得分:1)

如前所述,在这种情况下避免递归可能是一个坏主意。系统调用堆栈旨在处理这样的事情。销毁树是一种标记节点的形式。

如果您想使用自己的堆栈,那么您需要提供的信息不仅仅是节点。请记住,系统调用堆栈包含程序计数器以及函数参数(局部变量以及此处不重要的bu)。我们可以推送(PushMyChildren, node)(PrintMe, Node)格式的元组,当我们弹出(PushMyChildren, node)格式的节点时,我们会推送(PrintMe, Node),然后(PushMyChildren, right child),然后{ {1}}。如果左右儿童不存在则不要推他们。当我们弹出(PushMyChildren, left child)形式的节点时,我们打印节点。在伪C#(我不知道C#,没有时间查找正确的类型和语法)。

(PrintMe, Node)

答案 2 :(得分:1)

您可以将二叉树映射到一个数组(类似于将堆映射到数组的方式,如here所示),并在那里进行后序遍历。将二叉树转换为数组的操作可能会使用递归,但如果您正在控制树的初始构造方式(或者您只是在寻找一个有趣的想法),那么您可以将其构建为数组,并简化你的非递归后序遍历(没有标志)问题。

<强> 修改

我认为这是一个可行的选择:

1)保持指向树中节点的双向链接列表 2)从根节点开始 3)将根指针附加到列表 4)去右边的孩子 5)将当前节点指针附加到列表 6)重复步骤4和5,直到没有正确的孩子为止 7)将当前节点写入后订单遍历 8)将当前节点设置为列表中的最后一个节点 9)去左边的孩子 10)将当前音符指针附加到列表 11)重复步骤4到10,直到列表为空。

基本上,这会使树中的所有节点都有一个指向其父节点的指针。

答案 3 :(得分:0)

我刚刚使用遍历到宽度(使用队列)在Java中进行了下订单。

search_button = driver.execute_script('return document.querySelector("downloads-manager").shadowRoot.querySelector("downloads-toolbar").shadowRoot.querySelector("cr-search-field").shadowRoot.querySelector("#search-button")')
search_button.click()