简体   繁体   English

二叉树上的左右BFS穿越

[英]left-right BFS travesal on a binary tree

This is not a home work. 这不是家庭作业。 I was thinking of some new questions in tree traversal and this seems to be very obvious so thought of solving it. 我当时在想树遍历中的一些新问题,这似乎很明显,因此想解决它。

Question is very similar to level order traversal like BFS. 问题与BFS之类的级别顺序遍历非常相似。 In BFS, we normally travel left to right in each level of tree, but here if we are travelling left to right at level i then level (i-1) and (i+1) need to be traveled from right to left. 在BFS中,我们通常在树的每个级别中从左到右移动,但是在这里,如果我们在级别i处从左到右移动,则级别(i-1)和(i + 1)需要从右到左移动。

For Example: 例如:

           2
          / \
         7   5
        / \   \
       2   6   9
          / \   \
         5  11   4

In normal BFS, we output: 2, 7, 5, 2, 6, 9, 5, 11, 4 在普通BFS中,我们输出:2、7、5、2、6、9、5、11、4

But i am looking a solution where we output: 2, 5, 7, 2, 6, 9, 4, 11, 5 但是我正在寻找一个解决方案,我们输出:2,5,7,2,6,9,9,4,11,5

I am able to come up a solution. 我能够提出解决方案。 But, i want to see if any one come up better solution then mine. 但是,我想看看是否有人提出了比我更好的解决方案。 I am particularly looking optimization in space complexity (stack size) as well. 我特别希望在空间复杂度(堆栈大小)方面进行优化。

Please give your logic in accordance with C++ language. 请按照C ++语言给出您的逻辑。 I will greatly appreciate if you do not use any containers or STL in your solution. 如果您在解决方案中不使用任何容器或STL,将不胜感激。


Based on comments here, i have come up a solution using two stacks. 根据此处的评论,我提出了使用两个堆栈的解决方案。 My solution is as below. 我的解决方案如下。

  • Create stack S1 and S2 and queue Q. Queue Q will hold the final ans. 创建堆栈S1和S2以及队列Q。队列Q将保存最后的ans。
  • Note that before pushing in any stack (S1 or S2) we will first enqueue it into queue Q. 请注意,在压入任何堆栈(S1或S2)之前,我们首先将其排入队列Q。
  • Whatever we pop from stack s1, we will push its (first) right child and (then) left child (in this order)into stack s2. 无论我们从堆栈s1弹出什么内容,我们都将(按此顺序)将其(第一个)右子级和(然后)左子级推入堆栈s2中。 (Be remember point 2) (请记住第二点)
  • Whatever we pop from stack s2, we will push its (first) left child and (then) right child (in this order) into stack s1. 无论我们从堆栈s2中弹出什么内容,我们都将其(第一个)左孩子和(然后)右孩子(按此顺序)推入堆栈s1中。 (Be remember point 2) (请记住第二点)
  • Pop from one stack and push it to another untill both the stacks are empty. 从一个堆栈中弹出并推入另一堆栈,直到两个堆栈都空了。 final entries in Queue will be the ans. Queue中的最后一个条目将是ans。

/*
Create Stack S1, S2; // for tmp itr. Both of size log<n>
Create Queue Q; // It will hold ans
*/ 


Q.enqueue(root); //Enqueue the root nood;
S1.enqueue(root); //Fill the stack with somthing to start.



  while(S1||S2){                        // keep spinning untill both stack are empty.
        while(s1){                      //take care of stack S1.
            Node* tmp = S1.pop();       //take top elem;

        if(tmp->right){
            Q.enqueue(tmp->right);
            S2.push(tmp->right);
        }

        if(tmp->left){
            Q.enqueue(tmp->left);
            S2.push(tmp->left);
        }
    }

    while(S2){ //while S2 is not empty
        Node* tmp = S2.pop();

        if(tmp->left){
            Q.enqueue(tmp->left);
            S1.push(tmp->left);
        }

        if(tmp->right){
            Q.enqueue(tmp->right);
            S1.push(tmp->right);
        }

    }
} //End of outher while

while(Q){
    cout<< Q.pop()->data;   //output the entries in desired format.
}

It seems Ok to me (let me know if it is not). 对我来说似乎还可以(如果不是,请告诉我)。 But still wondering if there can be any other solution possible (better than this). 但是仍然想知道是否还有其他解决方案(比这更好)。

Rather than use a single queue, use a pair of stacks. 而不是使用单个队列,而是使用一对堆栈。 When the current stack is empty, start popping nodes off the other one, and pushing their children onto a now-empty one. 当前堆栈为空时,开始将节点弹出另一个节点,然后将其子节点推入现在为空的节点。

So you have 所以你有了

  • Push 2 onto one of the stacks. 将2推入堆栈之一。
  • Pop 2 off of it, push 7 5 onto other one. 从其中弹出2,将7 5推到另一个。 Swap the stacks. 交换堆栈。
  • Pop 5, push 9. 弹出5,按9。
  • Pop 7, push 6 2. Swap the stacks. 弹出7,按6。2.交换堆栈。

Etc. 等等。

You need a state variable to decide whether to push left or right first, as well. 您还需要一个状态变量来决定是先向左还是向右推。

I just tried the above suggestion given by Potatoswatter in C#.I have not tried running it. 我只是在C#中尝试了Potatoswatter给出的上述建议,但没有尝试运行它。 Please correct me, if something needs to be modified. 如果需要修改某些内容,请纠正我。

void BFSTraversePrintzigzag(Node root)  

{  
    bool bLeftToRight = true;  
    Stack<Node> stack1=new Stack<Node>();  
    Stack<Node> stack2=new Stack<Node>();  
    stack1.Push(root);  
    //loop until both the stacks are empty  
    while(stack1.Count>0 ||stack2.Count>0)  
    {  
        //Stack1 will be empty when all the nodes on a level are traversed.   
        if (stack1.Count==0 && stack2.Count>0)  
        {  
            //Swap stack1 and stack2, if stack1 is empty  
            stack1= stack2;  
            while(stack2.Count>0)  
                stack2.Pop();  
            bLeftToRight=!bLeftToRight;  
            //This is the state variable to switch the order from left to right and from Right to left  
        }  
        root=stack1.Pop();  
        Console.WriteLine(root.data) ;  
        if(bLeftToRight)      
        {        
            if(root.left!=null)  
                stack2.Push(root.left);  
            if(root.right!=null)  
                stack2.Push(root.right);  
        }  
        else  
        {  
            if(root.right!=null)  
                stack2.Push(root.right);  
            if(root.left!=null)  
                stack2.Push(root.left);  
        }  
    }  
}  

If I understand what you want, I'd use a priority queue instead of a stack. 如果我了解您想要什么,那么我将使用优先级队列而不是堆栈。 As keys for your priority queue, you need to store the level in the tree of the node and the order within that level. 作为优先级队列的键,您需要将级别存储在节点的树中以及该级别内的顺序。 The comparison function will use the level as the primary key. 比较功能将使用级别作为主键。 For even levels, it'll use the order as the secondary key directly, but for odd levels it'll negate it. 对于偶数级别,它将直接使用订单作为辅助键,但对于奇数级别,它将取反。 Depending on whether you consider the root of the tree level 0 or level 1, you may need to reverse which levels get used directly vs. negated. 根据您是否考虑树的根级别0或1,可能需要反转直接使用哪个级别或否定哪个级别。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM