Looking at reliable documentation:
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,其中包含lists 或Points。我暂时忽略指针,因为它们只是分散注意力。
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
在广度上,先遍历root,然后依次访问root的所有孩子,再依次访问孩子的孩子,所以
ABDCE
旁注:根据您的运行方式,鉴于现代处理器的预测和缓存能力,std::list 可能不是此处使用的最佳容器。例如,使用 std::vector,处理器总是知道下一个要访问的元素以及在哪里查找它,因此 CPU 可以在读取第一个元素时预加载下一个或下几个元素。使用列表时,项目通常会被打乱,使 CPU 在内存中反弹,在这里读一点,那里读一点,永远没有机会真正超越自己。