1

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

问题与 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点)
  • 从一个堆栈弹出并将其推送到另一个堆栈,直到两个堆栈都为空。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.
}

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

4

3 回答 3

2

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

所以你有了

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

等等。

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

于 2010-10-05T20:19:40.363 回答
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);  
        }  
    }  
}  
于 2012-09-09T12:20:52.203 回答
0

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

于 2010-10-05T20:36:54.680 回答