我有点学习数据结构,所以请原谅新手问题。问题是,我在C#中使用Stack类,我想随机访问元素。我知道我可以使用ElementAt随机访问:
Stack<int> mystack = new Stack<int>(4);
...//assume the stack is filled here
int value = mystack.ElementAt(2) // if I wanted element 2
但我只能获得价值,我无法修改它。我的意思是,在List中,我可以将随机元素修改为:
List<int> mylist = new List<int>(4);
mylist[2] = 35;
我想对Stack做同样的事情,但它没有索引器。也许这是不可能的,如果是这样,我也想知道原因。我知道当需要随机访问时,通常不会使用堆栈,但在解决问题时我仍然需要它。我最终找到了一个更好的方法,但我仍然想知道。 最后,关于ElementAt(),它是O(1)或O(N)??
答案 0 :(得分:6)
我想对Stack做同样的事情,但它没有索引器。也许这是不可能的,如果是的话,我也想知道原因。
不,这是不可能的。 Stack<T>
不提供允许随机访问的任何成员(直接指向基础列表数据)。同样,Stack<T>
的公共接口只能确保可以修改堆栈的顶部,而不是任何其他项目 - 这反过来意味着不必以适合自己的方式实现类随机访问(例如内部数组),但可以以随机访问不是非常高效的方式实现(例如链表)。因此,Stack<T>
故意仅实现ICollection<T>
interface,而IList<T>
不提供随机访问的任何成员,而List<T>
实际上是一个随机随机的集合访问。
最可能的原因是,正如你所说:
当需要随机访问时,通常不会使用堆栈
至于你的具体情况:
但在解决问题时我仍然需要它
在这种情况下,您显然不需要堆栈(LIFO列表),因此只需使用ElementAt
。
最后,关于ElementAt(),它是O(1)或O(N)??
与前面提到的Stack<T>
类型相关,并且没有检查enumerator的实现,我会假设ElementAt
使用堆栈提供的IEnumerable<T>
并迭代堆栈中的元素,直到达到指定的索引,因此在这种情况下,它的行为为O(N)。
请注意,在一般情况下,这不一定是真的; ElementAt
很有可能以首先检查传递给它的IList<T>
是否也实现indexer defined for that interface的方式实现,在这种情况下它可以使用{{3}},在这种情况下可能会达到O(1)的复杂性。