arrays - Delphi - TStack 容量困惑

标签 arrays delphi stack undo redo

我一直在与 TStack 合作,尝试在我的程序中实现简单的撤消/重做功能。这背后的想法是,当执行一个操作时,程序的当前状态将被保存 - 即推送到堆栈。当用户单击“撤消”时,程序的最后状态将被重新加载 - 即从堆栈中弹出。

这个想法的缺陷是堆栈不能永远增长,这意味着在达到容量值后,最旧的项目(位于堆栈底部的项目)应该被删除,因为新项目被推到顶部。

Delphi 中的 TStack 对象包含一个容量属性,我认为该属性会自动执行此“清理”操作,但是当我使堆栈重载时(例如,将 11 个项目推送到容量为 10 的项目),容量会更新以容纳更多项目。

任何人都可以为我提供有关如何在这种情况下更有效地使用 TStack 的建议吗?我知道另一种选择是使用数组结构,但我喜欢使用堆栈的预期易用性。

问候

最佳答案

实际上,TStack 由动态数组提供支持。
如果你真的愿意,你可以滥用这个事实,让堆栈从底部删除项目,但现在你会与堆栈作斗争。

我认为使用循环列表是一个更好的主意。

一个简单的设计可能会像这样工作。

type
  TCircularList<T> = class(TObject);
  private
    FStorage: TList<T>;
    FCapacity: cardinal;  //duplication for performance reasons
    FCurrentIndex: cardinal;
  protected
    function GetItem(index: cardinal): T;
    procedure SetItem(index: cardinal; const Value: T);
  public
    constructor Create(Size: cardinal = 10);
    destructor Destroy; override;
    procedure Add(const Item: T);
    property Items[index: cardinal]: T read GetItem write SetItem; default;
  end;

constructor TCircularList<T>.Create(Size: cardinal = 10);
begin
  inherited Create;
  Assert(Size >= 2);
  FStorage:= TList<T>.Create;
  FCapacity:= Size;
  FStorage.Capacity:= Size;
end;

destructor TCircularList<T>.Destroy;
begin
  FStorage.Free;
  inherited;
end;

procedure TCircularList<T>.Add(const Item: T);
begin
  FCurrentIndex:= (FCurrentIndex + 1) mod FCapacity;
  FStorage[FCurrentIndex]:= Item;
end;

function TCircularList<T>.GetItem(index: cardinal): T;
var
  cIndex: cardinal;
begin
  cIndex:= Index mod FCapacity;
  Result:= FStorage[index]; 
end;

procedure TCircularList<T>.SetItem(index: cardinal; const Value: T);
var
  cIndex: cardinal;
begin
  cIndex:= index mod FCapacity;
  FStorage[index]:= Value;
end;

显然,您需要更多方法,例如最后一个和删除方法,但我将其留给您,您应该能够从这里推断。

可用性备注
我不得不说,从用户体验的角度来看,我认为撤消/重做功能的想法很糟糕。
为什么不拥有一个快照列表,您可以及时前后移动,就像您在磁盘上保存了许多备份文件的情况一样。
撤消功能要求您准确记住最后 x 步所做的事情,这不能很好地扩展。
我也不明白为什么必须有一个限制,为什么不允许在内存/磁盘空间允许的情况下允许尽可能多的撤消/快照?

关于arrays - Delphi - TStack 容量困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39367022/

相关文章:

c - 交换两个相邻元素的功能不起作用

java - 对于已排序的 200 万元素数组,Arrays.sort(...) 的效率如何

arrays - 用列表和元组索引 Numpy 数组会给出不同的结果?

delphi - 从 .ocx ActiveX 向 Javascript 公开函数

c++ - 如何让 C++ 堆栈具有多种数据类型?

MySQL 表作为 FIFO/队列

javascript - 如何使用underscore js进行IN(SQL)操作?

Delphi 2010 - 无法加载 SSL 库

Delphi 2009 - 在自定义 Delphi 组件中设置默认属性值

c - 结构程序停止,没有任何错误