2010-12-04 80 views
2

我有一个集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循环?

回答

1

使用出队,而不是一个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(); 
     ... 
    } 
} 
+0

将如何与一个HashSet 这项工作? – Makara 2010-12-04 12:56:19

+0

@Makara添加了一个例子,我使用Queue来保存未处理的项目,并使用HashSet来避免重复项目。 – CodesInChaos 2010-12-04 12:59:40

0

循环迭代增加更多工作是很常见的;只需将队列作为参数传递给方法,并添加到它应该工作正常。

的问题是,OU应该使用出列:

while(queue.Count>0) { 
    DoSomeWork(queue.Dequeue()); 
} 
3

你正在做的是使用迭代器来改变集合。这是不好的做法,因为某些集合在执行此操作时会引发异常(例如枚举期间集合不应更改)。

使用下面的方法,它不使用新的项目,以及:

while (queue.Count > 0) 
{ 
    DoSomeWork(queue.Dequeue()); 
} 
相关问题