左右BFS遍历二叉树

时间:2010-10-05 20:01:20

标签: c++ algorithm binary-tree breadth-first-search

这不是家庭作业。我正在考虑树遍历中的一些新问题,这似乎非常明显,所以想到解决它。

问题与BFS等级别顺序遍历非常相似。在BFS中,我们通常在树的每个级别从左到右行进,但是如果我们在级别i从左到右行进,那么级别(i-1)和(i + 1)需要从右到左行进。

例如:

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

在正常的BFS中,我们输出:2,7,5,2,6,9,5,11,4

但我正在寻找一个解决方案,我们输出:2,5,7,2,6,9,4,11,5

我能够找到解决方案。但是,我想看看是否有人提出了更好的解决方案。我特别关注空间复杂度(堆栈大小)的优化。

请根据C ++语言提供您的逻辑。如果您在解决方案中不使用任何容器或STL,我将不胜感激。


根据这里的评论,我提出了一个使用两个堆栈的解决方案。我的解决方案如下。

  • 创建堆栈S1和S2以及队列Q.队列Q将保留最终的ans。
  • 请注意,在推入任何堆栈(S1或S2)之前,我们会先将其排入队列Q.
  • 无论我们从堆栈s1弹出什么,我们都会将其(第一个)右子和(然后)左子(按此顺序)推入堆栈s2。 (记住第2点)
  • 无论我们从堆栈s2弹出什么,我们都会将其(第一个)左子节点和(然后)右子节点(按此顺序)推入堆栈s1。 (记住第2点)
  • 从一个堆栈弹出并将其推送到另一个堆栈,直到两个堆栈都为空。队列中的最终条目将是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.
}

对我来说似乎没关系(如果不是,请告诉我)。但仍然想知道是否可以有任何其他解决方案(比这更好)。

3 个答案:

答案 0 :(得分:2)

不使用单个队列,而是使用一对堆栈。当前堆栈为空时,开始从另一个节点弹出节点,并将他们的孩子推到现在空的节点上。

所以你有

  • 将2推入其中一个堆栈。
  • 弹出2,将7 5推到另一个上。交换堆栈。
  • 弹出5,按9。
  • Pop 7,push 6 2.交换筹码。

你需要一个状态变量来决定是先向左还是向右推。

答案 1 :(得分:1)

我刚刚尝试了Potatoswatter在C#中给出的上述建议。我没有尝试过运行它。如果需要修改某些内容,请纠正我。

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);  
        }  
    }  
}  

答案 2 :(得分:0)

如果我理解你想要什么,我会使用优先级队列而不是堆栈。作为优先级队列的密钥,您需要将级别存储在节点的树中以及该级别中的顺序。比较函数将使用级别作为主键。对于偶数级别,它将直接使用订单作为辅助密钥,但对于奇数级别,它将否定它。根据您是否考虑树级别0或级别1的根,您可能需要反转哪些级别直接使用而不是否定。