我在大学的老师教我们这个堆栈的实现。但这个是完全递归的,我在网上的任何地方都没有看到这样的东西。所以我想知道这是多么好或有效。正如我已经看到很多带有链接列表的堆栈(最有效的)和使用数组的实现。
public class Stack<T>
{
private T top;
private Stack<T> base;
public Stack(){
top = null;
base = null;
}
public Stack(T data, Stack<T> base){
top = data;
this.base = base;
}
public boolean isEmpty(){
return top == null;
}
public T top(){
return top;
}
public T push(T data){
if (isEmpty()){
top = data;
base = new Stack<T>();
} else {
base = new Stack<T>(top, base);
top = data;
}
return data;
}
public T pop(){
T res = null;
if (!isEmpty()){
res = top;
top = base.top;
base = base.base;
}
return res;
}
}
我想听听你的意见,因为我真的没有看到任何其他的这种实施。请随意解释复杂性!
答案 0 :(得分:1)
正如其他人所评论的那样,这个实现使用单链表,而典型的实现使用数组来保存堆栈。
首先是复杂性:所以我想知道这是多么好或有效。
最佳/平均/最差情况时间复杂度为O(1)
。
最佳/平均/最差情况下的空间复杂度为O(N)
。
比较复杂性:
最佳案例时间复杂度与数组实施相同:O(1)
。
最佳情况下的空间复杂度在数组实现中是相同的:O(N)
。
平均和最坏情况复杂性的比较有点棘手,因为基于数组的度量取决于堆栈的数组是否/如何在堆栈增长和收缩时重新分配。这是特定于实现的。
比较表现(最佳情况):
推送链表版本更加昂贵,因为每次push
调用都会创建一个新对象。 (在基于阵列的版本的最佳情况下,阵列中有一个空闲插槽......因此不需要重新分配。)
Popping间接成本更高,因为它导致对象无法访问。
基于列表的实现的最佳空间使用率肯定更高。堆栈条目由具有2个引用的对象表示。这是2&#34;字&#34;加上对象标题加上填充。在64位JVM中......可能是24个字节。相比之下,基于阵列的解决方案在数组中使用1个引用...每个条目使用8个字节....
由于上述原因,难以比较平均和最差情况下的性能和空间使用情况。
从API设计的角度来看:API提供了一个非泄漏的抽象。我唯一的狡辩是弹出一个空堆栈应该一个错误。如果调用方未测试意外(或预期)pop()
结果,则返回null
的{{1}}方法可能会导致问题(NPE)。此外,您无法将null
放入堆栈。
(实际上,那里有一个错误!如果你试图推送一个null
,那么&#34;工作&#34;,然后null
会报告堆栈是空的如果您尝试推送Stack.isEmpty()
...或至少保护数据结构,push
方法应该抛出异常。)
请随时解释复杂性!
如果您自己动手,您将了解更多信息。
但这个是完全递归的......
有争议的。数据结构在某种意义上是递归的,但算法并不需要递归。