无法使用基础列表推送到队列

Cant push to queue with underlying list

本文关键字:队列 列表      更新时间:2023-10-16

以我的教授为例,使用基于列表的队列遍历图:

void breadthFirst (Point* root)
{
   queue<list<Point*> > q;
   q.push (root);
 }
error: no matching function for call to ‘std::queue<std::list<Point*> >::push(Point*&)’
    q.push (root);

类似:

void breadthFirstTraversal (const Point& start)
{
  queue<list<Point> > q;
  q.push (start); 
}      
error: no matching function for call to ‘std::queue<std::list<Point> >::push(const Point&)’
   q.push (start); 

我复习了关于指针和引用的材料,并尝试了不同的传递变量的方法。

根据文档,构造函数可能是不正确的std::queue<int,std::list<int>

查看可靠的文档:

template<
    class T,
    class Container = std::deque<T>
> class queue;

我们看到std::queue需要定义为

std::queue<type of element, type of container to base queue on> nameOfQueue;

有两种方法:

queue<Point, list> q;

指定Points中的queue,其中queue用于存储Points的容器是list

 queue<list<Point>>

其中我们有一个queue,它包含Points中的lists。我现在忽略指针,因为它们只是分散注意力。

OP及其教员的代码并不能明确使用哪种变体。正如OP所发现的,不能将Point推送到queue<list<Point>>,因为Point不是list<Point>

让我们停下来看看提供给OP的示例:

void breadthFirst (TreeNode* root)
{
   queue<list<TreeNode*> > q;
   q.push (root); // impossible. root is not list<TreeNode*>
   while (!q.empty())
     {
      v = q.front (); // type of v not specified. Based on usage, assuming TreeNode *
      q.pop ();
      for (int i = 0; i < v->numChildren(); ++i)
        {
         TreeNode* w = v->child[i];
         if (w != 0)
           q.push (w);
        }
     }
}

我能看到教练把他们的头向后扭的地方。我想他们想要

void breadthFirst(std::list<std::list<std::list<...>*>*>* root)

那。。。表示无限模板递归。祝你好运。教练明智地避免了掉进兔子洞里。

用结构抽象这种混乱

struct TreeNode
{
    std::list <TreeNode* > children;
};

是正确的想法。教练只需要坚持到底。

现在我们可以定义

std::queue<TreeNode*> q;

q.push(root);

基于对树遍历和现代C++的预先存在的理解(举个这样的例子,如果没有预先存在的知识,那就太糟糕了),我们得到了类似的东西

#include <list>
#include <queue>
#include <iostream>
void breadthFirst(TreeNode* root)
{
    std::queue<TreeNode*> q;
    q.push(root);
    while (!q.empty())
    {
        TreeNode*v = q.front();
        q.pop();
        std::cout << v->name; // added to visually demonstrate. Do stuff here
        for (TreeNode * w: v->children) // visit all children in order
        {
            // no need to check for nulls. list doesn't need to contain empty slots
            // this was likely a left over from a previous C implementation
            q.push(w);
        }
    }
    std::cout << std::endl;
}

快速测试仪:

int main()
{
    TreeNode A('A');
    TreeNode B('B');
    TreeNode C('C');
    TreeNode D('D');
    TreeNode E('E');
    A.children.push_back(&B);
    A.children.push_back(&D);
    B.children.push_back(&E);
    E.children.push_back(&C);
    breadthFirst(&A);
}

五个节点A包含B,D.B包含C.C包含E.

 A
B D
C
E

在广度优先中,遍历访问根,然后按顺序访问根的所有子级,然后按次序访问子级的子级,因此

ABDCE

附带说明:根据您的运行方式,考虑到现代处理器的预测和缓存能力,std::list可能不是这里使用的最佳容器。比如说,使用std::向量,处理器总是知道下一个要访问的元素是哪个,以及在哪里查找它,所以CPU在读取第一个元素时可以预加载下一个或接下来的几个项目。有了列表,项目通常会被打乱,使CPU在内存中来回跳动,在这里和那里读一点,但永远没有机会超越自己。