【问题标题】:left-right BFS travesal on a binary tree二叉树的左右BFS遍历
【发布时间】:2010-10-05 20:01:19
【问题描述】:

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

Question 与 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,我将不胜感激。


基于此处的 cmets,我提出了一个使用两个堆栈的解决方案。我的解决方案如下。

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

对我来说似乎没问题(如果不是,请告诉我)。但仍然想知道是否还有其他可能的解决方案(比这更好)。

【问题讨论】:

  • 另外请不要更改树。
  • 查看您的代码,请明确显示 S1、S2、Q 的创建。对于一般的二叉树,堆栈将增长到 O(N) 大小; log(N) 是深度优先遍历 balanced 树所需要的;示例不平衡,甚至没有排序。需要检查S1.empty()||S2.empty() 作为循环条件。一致命名 S1 或 s1;大写。修复缩进。请在让我看之前先编译它。
  • 我想,你检查一下我在这里使用的概念,因为我没有使用任何变量来决定像你提到的那样向左/向右推。我不想让你成为编译器,因为我没有编写代码进行编译。

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


【解决方案1】:

与其使用单个队列,不如使用一对堆栈。当当前堆栈为空时,开始从另一个堆栈中弹出节点,并将其子节点推送到现在为空的堆栈中。

所以你有

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

等等

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

【讨论】:

  • 它会起作用吗?您如何在堆栈中推入树的中间项。
  • 好的。我认为,我们必须在这里使用两个堆栈。我已经了解您的解决方案并编写了一个算法来以最佳方式完成此任务。完成后我会在这里发布。
  • 根据您的评论,我提出了解决方案,已包含在我的问题下方。如果您有任何改进性能的建议,请查看并告诉我。
【解决方案2】:

我刚刚尝试了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);  
        }  
    }  
}  

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-01
      • 2022-11-11
      相关资源
      最近更新 更多