2010-12-04 78 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()); 
} 
相關問題