如何在C#中删除不在堆栈顶部的堆栈项
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/748387/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to remove a stack item which is not on the top of the stack in C#
提问by Enyra
Unfortunately an item can only be removed from the stack by "pop". The stack has no "remove" method or something similar, but I have a stack (yes I need a stack!) from which I need to remove some elements between.
不幸的是,一个项目只能通过“弹出”从堆栈中删除。堆栈没有“删除”方法或类似的方法,但我有一个堆栈(是的,我需要一个堆栈!),我需要从中删除一些元素。
Is there a trick to do this?
有没有技巧可以做到这一点?
采纳答案by Binary Worrier
If you need to remove items that aren't on the top, then you need something other than a stack.
如果您需要删除不在顶部的项目,那么您需要的不是堆栈。
Try making your own implementation of a stack from a List. Then you get to implement your own push and pop functions (add & remove on the list), and your own special PopFromTheMiddle function.
尝试从列表中创建自己的堆栈实现。然后你可以实现你自己的推送和弹出函数(在列表中添加和删除),以及你自己的特殊 PopFromTheMiddle 函数。
For example
例如
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);
}
}
回答by Micha? Piaskowski
Consider using different container. Maybe a LinkedList. Then you can use
考虑使用不同的容器。也许是一个链表。然后你可以使用
AddFirst AddLast RemoveLast RemoveFirst
just like pop/push from stack and you can use
就像从堆栈弹出/推送一样,您可以使用
Remove
to remove any node from the middle of the list
从列表中间删除任何节点
回答by aJ.
Then it is not a stack right? Stack is LAST in FIRST out
.
You will have to write a custom one or choose something else.
那么它不是一个堆栈吗?堆栈是LAST in FIRST out
。您将不得不编写自定义程序或选择其他内容。
回答by Charles Bretana
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);
回答by webclimber
hmmmm...... I agree with the previous two answers but if you are looking to hack your way just pop and save all elements until you get to the one you want, and the re-push them all
嗯......我同意前两个答案,但如果你想破解你的方式,只需弹出并保存所有元素,直到你找到你想要的元素,然后重新推送它们
Yes is ugly, badly performing, probably weird code that will need a long comment explaining why, but you could do it....
是的很丑,性能很差,可能是奇怪的代码,需要很长的注释来解释原因,但你可以做到......
回答by Reed Copsey
In a true stack, this can only be done one way -
在真正的堆栈中,这只能以一种方式完成 -
Pop all of the items until you remove the one you want, then push them back onto the stack in the appropriate order.
弹出所有项目,直到移除您想要的项目,然后以适当的顺序将它们推回堆栈。
This is not very efficient, though.
但是,这不是很有效。
If you truly want to remove from any location, I'd recommend building a pseudo-stack from a List, LinkedList or some other collection. This would give you the control to do this easily.
如果您真的想从任何位置删除,我建议您从 List、LinkedList 或其他一些集合构建一个伪堆栈。这将使您能够轻松地控制它。
回答by tvanfosson
Perhaps an extension method would work, although, I suspect that a different data structure entirely is really needed.
也许扩展方法会起作用,但我怀疑确实需要完全不同的数据结构。
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;
}
}
回答by Phil Carson
The constructor of a Stack<> takes IEnumerable<> as a parameter. So it would be possible to perform the following:
Stack<> 的构造函数将 IEnumerable<> 作为参数。因此,可以执行以下操作:
myStack = new Stack<item>( myStack.Where(i => i != objectToRemove).Reverse() );
This is non performant in a number of ways.
这在许多方面都是无效的。
回答by Amit Bens
A trick I use in hairy situations is adding a 'deprecated' flag to the items in the stack. When I want to 'remove' an item, I simply raise that flag (and clean up any resources that are taken by the object). Then when Pop()ing items I simply check if the flag is raised, and pop again in a loop until a non-deprecated item is found.
我在多毛情况下使用的一个技巧是向堆栈中的项目添加“已弃用”标志。当我想“删除”一个项目时,我只需提升该标志(并清理该对象占用的任何资源)。然后当 Pop()ing 项目时,我只需检查标志是否被提升,然后在循环中再次弹出,直到找到一个非弃用的项目。
do
{
obj = mQueue.Pop();
} while (obj.deprecated);
You can manage your own item-count to know how many 'real' items are still in the queue, and obviously locking should be employed if this is required for multi-threaded solution.
您可以管理自己的项目计数以了解队列中还有多少“真实”项目,如果多线程解决方案需要,显然应该使用锁定。
I found that for queues that have constant flow through them - items pushed and popped - it's much more efficient to hanle it this way, its the fastest you can get (paying O(1) for removing an item from the middle) and memory wise if the object that is retained is small, it's mostly irrelevant if the items flow in a reasonable pace.
我发现对于流经它们的队列 - 推送和弹出的项目 - 以这种方式处理它的效率要高得多,这是您可以获得的最快(支付 O(1) 以从中间删除项目)和内存明智如果保留的对象很小,则项目是否以合理的速度流动几乎无关紧要。
回答by Benjamin Brown
You could use a LinkedList
您可以使用LinkedList
List based removal will likely be less efficient. In removal by reference List based stacks will have O(N) search and O(N) resizing. LinkedList search is O(N) and removal is O(1). For removal by index, LinkedList should have O(N) traversal and O(1) removal, while List will have O(1) traversal (because it is indexing) and O(N) removal due to resizing.
基于列表的删除可能效率较低。在通过引用删除基于列表的堆栈将有 O(N) 搜索和 O(N) 调整大小。LinkedList 搜索是 O(N),删除是 O(1)。对于按索引移除,LinkedList 应该有 O(N) 次遍历和 O(1) 次移除,而 List 将有 O(1) 次遍历(因为它正在索引)和 O(N) 次移除由于调整大小。
Besides efficiency, a LinkedList implementation will keep you in the standard library, opening your code to more flexibility and have you writing less.
除了效率之外,LinkedList 实现将使您保持在标准库中,使您的代码更加灵活,并且让您编写更少的代码。
This should be able to handle Pop, Push, and Remove
这应该能够处理 Pop、Push 和 Remove
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
}