c# - 为什么 C# 中的 Stack<T> 类允许 ElementAt(index) 而它是一个 ADT?

标签 c# data-structures stack adt

Stack 是一种抽象数据类型 (ADT),它应该有一个密封的操作列表,如 Push()、Pop()、Peek() 等,以执行后进先出(LIFO) ) 原则。

但它有 ElementAt(index) 允许我访问堆栈中的任何元素。根据我的理解,Stack 对不在表面的元素的可见性应该较低。不是吗?

最佳答案

ElementAt()通过 Linq 的 Enumerable.ElementAt() 提供,而不是通过 Stack<T>界面。

这是有效的,因为 Stack<T>工具 IEnumerable<T>这就是实现 ElementAt() 所需的全部内容因为它所做的只是遍历通过 IEnumerable<T> 提供的所有元素直到其中 N 个被访问。

对于 Stack<T>这是一个 O(N) 操作。如果你使用 ElementAt()比如说,一个List<T>然后内部优化将其转换为 O(1) 操作。

至于为什么Stack<T>工具 IEnumerable<T> - 只有一位设计师能真正回答这个问题。因为它是一个非变异操作,所以它并没有真正违反堆栈的任何基本原则。我会猜测它是为了方便而提供的。

正如/u/Damien_The_Unbeliever 在他的回答中指出的那样,代码可以在没有 IEnumerable 接口(interface)的情况下确定第 N 个元素,方法是将 N 个元素弹出到另一个堆栈,然后以相反的顺序将它们全部推回,从而使原始堆栈保持不变。

美中不足的是微软没有记录 Stack 的IEnumerable 的顺序。返回它的元素。您可以检查源代码以查看它确实以 LIFO 顺序返回元素 - 但这根本没有记录。

这在 this question 的答案中进行了讨论.

无论如何,为您所说的抽象堆栈定义的 ADT 接口(interface)在哪里?我认为对此没有明确的答案。严格来说,你可以说一个栈只有Push()。和 Pop() .然而大多数实现还提供 Count .

作为the article about Stack on Wikipedia states :

In many implementations, a stack has more operations than "push" and "pop". An example is "top of stack", or "peek", which observes the top-most element without removing it from the stack.

Since this can be done with a "pop" and a "push" with the same data, it is not essential. An underflow condition can occur in the "stack top" operation if the stack is empty, the same as "pop". Also, implementations often have a function which just returns whether the stack is empty.

所以从根本上说,你的问题的答案是:

库设计者决定添加一些非变异的便捷方法,除了只有变异方法 Push()Pop() .

关于c# - 为什么 C# 中的 Stack<T> 类允许 ElementAt(index) 而它是一个 ADT?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50482637/

相关文章:

c# - 如何绘制数学符号?

c# - 在客户端/服务器应用程序中将 DTO 对象图映射回 Entity Framework 对象图的优雅方式

data-structures - 堆栈和队列,为什么?

C# HttpClient POST'ing 异步

c# - 模板 10 : Modal not closing

algorithm - 是否可以在 O(logn) 中测试一个数是否为素数?

c++ - std::set<T>::insert,重复元素

C编程: I have an error in creating a binary search tree using C

java - 扩展堆栈库

function - Postgresql:插入/更新后触发函数:堆栈深度限制错误