我使用C#在.Net环境中工作。我需要一些替代堆栈数据结构。某种绑定堆栈。集合中元素的数量不应超过某个固定的指定数量。并且,如果实现了该数字并且推送了新元素,则必须删除大多数旧元素。我需要这个来存储撤消/重做策略的命令。
答案 0 :(得分:7)
circular buffer应该做的工作;很容易包装列表或数组,但没有内置在AFAIK中。
答案 1 :(得分:5)
Johnny Coder在这里有一个实现:http://johnnycoder.com/blog/2008/01/07/undo-functionality-with-a-limited-stack/
答案 2 :(得分:2)
.Net在收藏类型上相当缺乏。你会找到一个集合库here。使用 CircularQueue。
答案 3 :(得分:2)
这是具有约束容量的堆栈的实现。 达到给定容量后,超出容量的堆栈底部项目将被丢弃。可以迭代包含的对象并将索引设置为特定位置(如倒带),以便在将新项目推送到堆栈时立即丢弃多个条目。
这是一个自己的实现,如果您需要返回历史记录并再次转发(内置),则会阻止您处理多个列表。
public class DiscardingStack<TObject> : IEnumerable<TObject>
{
private readonly int capacity;
private readonly List<TObject> items;
private int index = -1;
public DiscardingStack(int capacity)
{
this.capacity = capacity;
items = new List<TObject>(capacity);
}
public DiscardingStack(int capacity, IEnumerable<TObject> collection)
: this(capacity)
{
foreach (var o in collection)
{
Push(o);
}
}
public DiscardingStack(ICollection<TObject> collection)
: this(collection.Count, collection)
{
}
public void Clear()
{
if (items.Count >= 0)
{
items.Clear();
index = items.Count - 1;
}
}
public int Index
{
get { return index; }
set
{
if (index >= 0 && index < items.Count)
{
index = value;
}
else throw new InvalidOperationException();
}
}
public int Count
{
get { return items.Count; }
}
public TObject Current
{
get { return items[index]; }
set { index = items.IndexOf(value); }
}
public int Capacity
{
get { return capacity; }
}
public TObject Pop()
{
if (items.Count <= 0)
throw new InvalidOperationException();
var i = items.Count - 1;
var removed = items[i];
items.RemoveAt(i);
if (index > i)
index = i;
return removed;
}
public void Push(TObject item)
{
if (index == capacity - 1)
{
items.RemoveAt(0);
index--;
}
else if (index < items.Count - 1)
{
var removeAt = index + 1;
var removeCount = items.Count - removeAt;
items.RemoveRange(removeAt, removeCount);
}
items.Add(item);
index = items.Count - 1;
}
public TObject Peek()
{
return items[items.Count-1];
}
public TObject this[int i]
{
get { return items[i]; }
}
public IEnumerator<TObject> GetEnumerator()
{
return items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
无论如何,如果列表很大(避免复制),应该使用LinkedList(如上所述)构建一个在达到最大容量时丢弃元素的堆栈。因此,在这种情况下,LinkedList的想法可能会更好,而不是在缓冲区最大值为高值时包装List。
我还建议将Push(),Pop()等打包到一个接口(例如IStack)中。遗憾的是,.Net(afaik)中没有预定义的IStack接口。
答案 4 :(得分:1)
Framework中没有内置类。 (我们不希望自动删除数据)。但您可以扩展 Stack类和覆盖推/弹以及其他方法以满足您的需求。