在 C++ 中使用队列构造二叉树

Posted

技术标签:

【中文标题】在 C++ 中使用队列构造二叉树【英文标题】:Constructing a binary tree using queue in C++ 【发布时间】:2014-12-03 20:52:44 【问题描述】:

我正在尝试用 C++ 编写一些数据结构硬件。当我尝试使用队列构造二叉树时,不知何故被指针问题弄糊涂了。

class Tree
private:
    struct TreeNode
    int val;
    TreeNode* left;
    TreeNode* right;

    TreeNode(int x) :val(x), left(NULL), right(NULL) 
;
public:
    TreeNode* root = NULL;       
    Tree();
    Tree(queue<int>& val);       
    ~Tree();
    string toString_bf();
;


Tree(queue<int> &vals)
    if (vals.empty())
        return;

    root = new TreeNode(vals.front());
    vals.pop();
    queue<TreeNode**> pts;       // what is the meaning of this? Why should use pointers to pointer?

    pts.push(&(root->left));     // also have doubts here, about the reference used in the parameter
    pts.push(&(root->right));
    while (!vals.empty())
        TreeNode* t = new TreeNode(vals.front());
        *(pts.front()) = t;      // and here
        pts.pop();
        vals.pop();
        pts.push(&(t->left));
        pts.push(&(t->right));
    

按照我的理解,left和right都是指针,为什么不能直接传值呢?

【问题讨论】:

【参考方案1】:

变量pts 是一个指针队列,指向稍后需要放置子树的位置。这些位置本身就是指向TreeNode 的指针(每个都是leftright 数据成员,类型为TreeNode *),因此您需要TreeNode ** 来指向它们是有道理的。

换句话说,每次执行*(pts.front()) = t; 时,先前构造的TreeNodeleftright 成员都会被设置为指向最近构造的节点。

您可以创建一个typedef TreeNode *TreePtr;,使用它可能看起来更干净。


进一步澄清发生了什么:

每次“while”循环开始时:

root 是正在构建的树的根,包含 n+1 个节点,每个节点保存一个取自输入队列 @9​​87654333@ 的值(其中 n 是 while 循环的次数已经运行)

vals 包含尚未放入树中的所有剩余值(如果有)

pts 包含一组指向树中节点内指针的指针;它包含指向所有尚未分配子树的指针的指针;其中有 n+2 个。

所以每个循环都会创建一个新节点,使这些未分配的指针之一指向新节点,然后将新节点的未分配指针添加到队列中。

注意,当操作结束时,pts中总是有n+2个指针,被丢弃。通过知道需要多少节点 (= vals.size()),一旦完成足够多的操作,就可以停止执行 pts.push 操作,这将所需的临时空间量减少了约 50%:

      vals.pop();
      if( pts.size() < vals.size()) 
           pts.push(&(t->left));
           pts.push(&(t->right))
        // otherwise we have enough for all remaining vals.

【讨论】:

我只是对此感到困惑:我可以使用 queue 代替 queue 吗?相应地,下面的代码中不要使用引用? @greggo 如果你想把t-&gt;left放到一个队列中,那么它看起来像这样。但是代码的工作方式,t-&gt;leftt-&gt;right 在它被放入队列时总是有一个 NULL 值,所以这显然没有用。队列的重点是记住需要稍后设置的指针变量的位置 或者,您可以创建一个结构,其中包含 (a) TreeNode*(已构建的节点)和 (b) 指示它是该节点中需要设置的左指针还是右指针;并把它们排成一个队列。但是,当您将它们放入队列时,您会将 't' 设置为 (a) 部分,然后包含 pts.front() 的代码行将变为 if 语句,并完成两个可能的分配。本质上,您正在创建一个特殊的指针,用于选择现有节点和该节点内的位置。不过,我仍然不确定为什么您对现在的代码方式不满意。 哦,我明白了。在这种情况下,我试图复制一个空 ptr。这就是我需要使用它的参考的原因。感谢您的友好解释。这很有帮助。@greggo

以上是关于在 C++ 中使用队列构造二叉树的主要内容,如果未能解决你的问题,请参考以下文章

数据结构 | 线索二叉树2 | 中序线索二叉树的构造(计算机408统考)

二叉树:构造一棵最大的二叉树

二叉树19:构造二叉树两道题

构造一棵二叉树,并分别输出其先序遍历、中序遍历和后序遍历的结果

构造二叉树

二叉树--根据遍历构造二叉树