C#を使用して.Net環境で作業しています。Stack データ構造の代わりが必要です。ある種のバインドされたスタック。コレクション内の要素の数は、特定の固定数を超えてはなりません。そして、その数が達成され、新しい要素がプッシュされた場合、最も古い要素よりも削除する必要があります。元に戻す/やり直し戦略のコマンドを保存するためにこれが必要です。
5 に答える
循環バッファがその仕事をするはずです。リストまたは配列をラップするのは簡単ですが、AFAIKには何も組み込まれていません。
Johnny Coder はここに実装しています: http://johnnycoder.com/blog/2008/01/07/undo-functionality-with-a-limited-stack/
これは、容量が制限されたスタックの実装です。所定の容量に達した後、容量を超えるスタックの一番下のアイテムは破棄されます。含まれているオブジェクトを反復処理し、新しいアイテムをスタックにプッシュするときに複数のエントリを一度に破棄するために、インデックスを特定の位置 (巻き戻しなど) に設定することができます。
これは、履歴をさかのぼって再度進む必要がある場合に複数のリストを処理できないようにするいくつかの機能を備えた独自の実装です (組み込み)。
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 を使用して実装する必要があります (上で提案したように)。したがって、このような場合、バッファの最大値が高い場合は List をラップするよりも、LinkedList のアイデアの方が適している可能性があります。
また、Push()、Pop() などをインターフェイス (IStack など) にパックすることもお勧めします。悲しいことに、.Net で定義済みの IStack インターフェイスはありません (afaik)。
.Net は、コレクションのタイプがかなり不足しています。ここにコレクション ライブラリがあります。CircularQueueを使用します。
フレームワークには、このための組み込みクラスはありません。(データを自動的に削除することは想定していません)。しかし、必要に応じて Stack クラスを拡張し、 Push/Popやその他のメソッドをオーバーライドすることができます。