C#中有没有类似可扩展队列的东西?
问题描述:
我有一个集ID上,我做了一些操作:C#中有没有类似可扩展队列的东西?
Queue<string> queue = new Queue<string>();
queue.Enqueue("1");
queue.Enqueue("2");
...
queue.Enqueue("10");
foreach (string id in queue)
{
DoSomeWork(id);
}
static void DoSomeWork(string id)
{
// Do some work and oooo there are new ids which should also be processed :)
foreach(string newID in newIDs)
{
if(!queue.Contains(newID)) queue.Enqueue(newID);
}
}
是否有可能增加一些新的项目,在DoSomeWork()
queue
这也将处理贝主要的foreach循环?
答
使用出队,而不是一个foreach循环。当底层容器发生变化时,大多数枚举器都会失效。 En-/Dequeue是队列上的自然操作。否则,你可以使用List<T>
或HashSet<T>
while(queue.Count>0)
{
var value=queue.Dequeue();
...
}
要检查的项目已经被处理的HashSet<T>
是一个快速的解决方案。在这些情况下,我通常使用HashSet和Queue的组合。这个解决方案的优点是它是O(n),因为检查和添加到HashSet
是O(1)。您的原始代码是O(n^2),因为上的Contains
是O(n)。
Queue<string> queue=new Queue<string>();
HashSet<string> allItems=new HashSet<string>();
void Add(string item)
{
if(allItems.Add(item))
queue.Enqueue(item);
}
void DoWork()
{
while(queue.Count>0)
{
var value=queue.Dequeue();
...
}
}
答
循环迭代增加更多工作是很常见的;只需将队列作为参数传递给方法,并添加到它应该工作正常。
的问题是,OU应该使用出列:
while(queue.Count>0) {
DoSomeWork(queue.Dequeue());
}
答
你正在做的是使用迭代器来改变集合。这是不好的做法,因为某些集合在执行此操作时会引发异常(例如枚举期间集合不应更改)。
使用下面的方法,它不使用新的项目,以及:
while (queue.Count > 0)
{
DoSomeWork(queue.Dequeue());
}
将如何与一个HashSet这项工作? –
Makara
2010-12-04 12:56:19
@Makara添加了一个例子,我使用Queue来保存未处理的项目,并使用HashSet来避免重复项目。 – CodesInChaos 2010-12-04 12:59:40