不幸的是,只能通过“pop”从堆栈中删除项目。堆栈没有“删除”方法或类似的东西,但我有一个堆栈(是的,我需要一个堆栈!),我需要从中删除一些元素。
这样做有诀窍吗?
答案 0 :(得分:46)
如果您需要删除不在顶部的项目,那么您需要的不是堆栈。
尝试从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);
}
}
答案 1 :(得分:11)
考虑使用不同的容器。也许是LinkedList。 然后你可以使用
AddFirst AddLast RemoveLast RemoveFirst
就像从堆栈弹出/推送一样,你可以使用
Remove
从列表中间删除任何节点
答案 2 :(得分:6)
您可以使用LinkedList
基于列表的删除可能效率较低。 在通过引用移除基于列表的堆栈将具有O(N)搜索和O(N)调整大小。 LinkedList搜索是O(N),删除是O(1)。 对于按索引删除,LinkedList应该有O(N)遍历和O(1)删除,而List将有O(1)遍历(因为它是索引)和O(N)删除由于调整大小。
除了效率之外,LinkedList实现还会让您进入标准库,打开代码以获得更大的灵活性,让您的写作更少。
这应该能够处理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
}
答案 3 :(得分:5)
也许扩展方法可行,但我怀疑完全需要完全不同的数据结构。
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;
}
}
答案 4 :(得分:4)
在真正的堆栈中,这只能以一种方式完成 -
弹出所有项目,直到删除所需的项目,然后按适当顺序将它们推回到堆栈中。
但这并不是很有效率。
如果你真的想从任何位置删除,我建议从List,LinkedList或其他一些集合构建一个伪栈。这样可以让您轻松完成控制。
答案 5 :(得分:3)
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);
答案 6 :(得分:3)
我在毛茸茸的情况下使用的技巧是在堆栈中的项目中添加“已弃用”标志。 当我想“删除”一个项目时,我只需要提升该标志(并清理该对象所占用的任何资源)。 然后当Pop()项目时,我只是检查标志是否被引发,然后在循环中再次弹出,直到找到未弃用的项目。
do
{
obj = mQueue.Pop();
} while (obj.deprecated);
您可以管理自己的项目计数,以了解队列中仍有多少“真实”项目,如果多线程解决方案需要,则显然应该采用锁定。
我发现对于持续流过它们的队列 - 推送和弹出的项目 - 以这种方式处理它的效率要高得多,它可以获得最快的速度(支付O(1)从中间移除项目)并且如果保留的对象很小,那么如果物品以合理的速度流动,那么它几乎无关紧要。
答案 7 :(得分:2)
然后它不是堆栈对吗?堆栈为LAST in FIRST out
。
您必须编写自定义或选择其他内容。
答案 8 :(得分:1)
Stack&lt;&gt;的构造函数采用IEnumerable&lt;&gt;作为参数。因此可以执行以下操作:
myStack = new Stack<item>( myStack.Where(i => i != objectToRemove).Reverse() );
这在许多方面都不具备效果。
答案 9 :(得分:0)
是的,丑陋,表现不佳,可能是奇怪的代码需要长时间的评论来解释原因,但你可以做到....
答案 10 :(得分:0)
我遇到了这个问题。在我的代码中,我创建了自己的扩展方法:
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);
答案 11 :(得分:0)
我使用了一个列表并添加了一些扩展方法,例如
import bisect
import math
import pathlib
primes = []
last_prime = None
def _get_primes():
"""
Load all the primes in global primes. Set global last_prime to last prime
read.
"""
global primes
global last_prime
path_to_primes = pathlib.Path(__file__).parent \
.joinpath('../resources/primes.txt')
with path_to_primes.open() as file:
for line in file:
for n in line.split():
n = n.strip()
if n:
n = int(n)
primes.append(n)
last_prime = primes[-1]
def gen_primes_before(n):
"""
Generates all the primes before n in reverse order.
"""
assert n <= last_prime, "Maximum value for n is {}".format(last_prime)
pos = bisect.bisect_left(primes, n)
if pos:
yield from primes[:pos]
def gen_factors(n):
"""
Generates all the factors of a number. May return some values multiple
times. Values returned are not ordered.
"""
type_n = type(n)
assert type_n is int or (type_n is float and n.is_integer()), "Wrong type"
n = int(n)
r = int(math.sqrt(n)) + 1
assert r <= last_prime, "n is over limit"
yield 1
yield n
for prime in gen_primes_before(r):
partner = n/prime
if partner.is_integer():
yield from gen_factors(prime)
yield from gen_factors(partner)
def get_factors(n):
"""
Get all the factors of n as a sorted list.
"""
return sorted(set(gen_factors(n)))
_get_primes()
if __name__ == '__main__':
l = (1e9,)
for n in l:
print("The factors of {} are {}".format(n, get_factors(n)))
答案 12 :(得分:0)
这仍然处理整个堆栈,但它是删除条目的替代方法。不过按照这种方式,如果同一个条目在堆栈中多次出现,它会将它们全部删除。
using System.Collections.Generic;
namespace StackTest
{
class Program
{
static void Main(string[] args)
{
Stack<string> stackOne = new Stack<string>();
stackOne.Push("Five");
stackOne.Push("Four");
stackOne.Push("Three");
stackOne.Push("Two");
stackOne.Push("One");
deleteStackEntry(stackOne, @"Three");
deleteStackEntry(stackOne, @"Five");
}
static void deleteStackEntry(Stack<string> st, string EntryToDelete)
{
// If stack is empty
if (st.Count == 0) return;
// Remove current item
string currEntry = st.Pop();
// Remove other items with recursive call
deleteStackEntry(st, EntryToDelete);
// Put all items back except the one we want to delete
if (currEntry != EntryToDelete)
st.Push(currEntry);
}
}
}