不幸的是,項目只能通過「pop」從堆棧中刪除。該堆棧沒有「刪除」方法或類似的東西,但我有一個堆棧(是的,我需要一個堆棧!),我需要從中刪除一些元素。如何刪除不在C#中堆棧頂部的堆棧項目
有沒有這樣做的把戲?
不幸的是,項目只能通過「pop」從堆棧中刪除。該堆棧沒有「刪除」方法或類似的東西,但我有一個堆棧(是的,我需要一個堆棧!),我需要從中刪除一些元素。如何刪除不在C#中堆棧頂部的堆棧項目
有沒有這樣做的把戲?
如果您需要刪除不在頂部的項目,那麼您需要的東西不是堆棧。
嘗試從List中自己實現一個堆棧。然後你可以實現自己的推送和彈出功能(在列表中添加&刪除)以及你自己特殊的PopFromTheMiddle功能。
例如
public class ItsAlmostAStack<T>
{
private List<T> items = new List<T>();
public void Push(T item)
{
items.Add(item);
}
public T Pop()
{
if (items.Count > 0)
{
T temp = items[items.Count - 1];
items.RemoveAt(items.Count - 1);
return temp;
}
else
return default(T);
}
public void Remove(int itemAtPosition)
{
items.RemoveAt(itemAtPosition);
}
}
圍繞現有容器進行自定義實現可以讓您做到所需。如果你需要像我這樣的雙端堆棧(destack),它還可以讓你編寫最令人敬畏的函數名稱:PushBottom(),PopBottom()和PeekBottom():)。 – xan 2009-04-14 16:41:40
考慮使用不同的容器。也許是一個LinkedList。 然後你可以使用
AddFirst AddLast RemoveLast RemoveFirst
就像流行/推從堆棧,你可以使用
Remove
從列表的中間
然後取出所有節點是不是堆疊對?堆棧是LAST in FIRST out
。 你將不得不寫一個自定義的或選擇其他的東西。
Stack temp = new Stack();
object x, y;
While ((x = myStack.Pop()) != ObjectImSearchingFor)
temp.Push(x);
object found = x;
While ((y = temp.Pop()) != null)
myStack.Push(y);
hmmmm ......我同意前面的兩個答案,但如果你正在尋找破解你的方式是流行,並保存所有元素,直到你得到你想要的,並重新推他們都
是是醜陋的,不好執行,可能奇怪的代碼,將需要很長的註釋解釋爲什麼,但你可以做到這一點....
在真正的堆棧,這隻能做一種方式 -
彈出所有的項目,直到你刪除你想要的,然後推回去以適當的順序到堆棧。
雖然這不是非常有效。
如果你真的想從任何位置移除,我建議從List,LinkedList或其他集合構建一個僞堆棧。這會讓你輕鬆控制。
也許一個擴展方法可行,但我懷疑完全需要一個不同的數據結構。
public static T Remove<T>(this Stack<T> stack, T element)
{
T obj = stack.Pop();
if (obj.Equals(element))
{
return obj;
}
else
{
T toReturn = stack.Remove(element);
stack.Push(obj);
return toReturn;
}
}
堆棧<>的構造函數的IEnumerable <>作爲參數。因此,可以執行以下操作:
myStack = new Stack<item>(myStack.Where(i => i != objectToRemove).Reverse());
這在很多方面都不具有高性能。
我在毛茸茸的情況下使用的一個技巧是向堆棧中的項目添加「棄用」標記。 當我想'刪除'一個項目時,我只需提出該標誌(並清理該對象所佔用的任何資源)。 然後,當Pop()ing項目時,我只是檢查標誌是否被提出,並在循環中再次彈出,直到找到一個未被棄用的項目。
do
{
obj = mQueue.Pop();
} while (obj.deprecated);
您可以管理自己的項目數知道許多「真實」的項目是如何仍在隊列中,顯然鎖定,如果這需要多線程解決方案應該被採用。
我發現,對於通過它們的不斷流動的隊列 - 物品推送和彈出 - 這樣更有效率,以最快速度獲得(支付O(1)用於從中間移除物品)和記憶方式,如果保留的對象很小,那麼如果項目以合理的速度流動,則大多數情況下不相關。
你可以使用一個LinkedList
列表基於去除將可能是低效率的。 通過引用刪除基於列表的堆棧將進行O(N)搜索和O(N)調整大小。 LinkedList搜索是O(N)並且移除是O(1)。 對於通過索引進行刪除,LinkedList應該進行O(N)遍歷和O(1)刪除,而List將由於調整大小而進行O(1)遍歷(因爲它是索引)和O(N)刪除。
除了效率,LinkedList實現將使您保持在標準庫中,打開代碼以獲得更大的靈活性,並讓您編寫更少的代碼。
這應該能夠處理彈出,推,並刪除
public class FIFOStack<T> : LinkedList<T>
{
public T Pop()
{
T first = First();
RemoveFirst();
return first;
}
public void Push(T object)
{
AddFirst(object);
}
//Remove(T object) implemented in LinkedList
}
我碰到這個問題就來了。在我的代碼創建了自己的擴展方法:
public static class StackExtensions
{
public static void Remove<T>(this Stack<T> myStack, ICollection<T> elementsToRemove)
{
var reversedStack = new Stack<T>();
while(myStack.Count > 0)
{
var topItem = myStack.Pop();
if (!elementsToRemove.Contains(topItem))
{
reversedStack.Push(topItem);
}
}
while(reversedStack.Count > 0)
{
myStack.Push(reversedStack.Pop());
}
}
}
,我打電話給我的方法是這樣的:
var removedReportNumbers =
selectedReportNumbersInSession.Except(selectedReportNumbersList).ToList();
selectedReportNumbersInSession.Remove(removedReportNumbers);
這是功課?如果是這樣,請忽略我的答案,這可能不是你所需要的,用Reed Copsey的答案來代替:http://stackoverflow.com/questions/748387/how-to-remove-a-stack-item-which-is-not 748409#748409 – 2009-04-14 16:43:03
不,它不是作業,它只是一個非常特殊的情況下的小型私人項目^^ – Enyra 2009-04-14 16:48:04
彈出堆棧並拋棄值? – belgariontheking 2009-04-14 16:49:50