简体   繁体   English

堆栈递归实现的复杂性

[英]Stack Recursive Implementation Complexity

My teacher at the University has taught us this implementation of a Stack. 我大学的老师曾教过我们堆栈的实现。 But this one is fully recursive and I haven't seen anything like this anywhere on the web. 但这是完全递归的,在网络上的任何地方我都没有看到这样的东西。 So I was wondering how good or efficient this is. 所以我想知道这有多好或有效率。 As I have seen lots of implementations of Stacks with Linked List(been the most efficient one) and using arrays. 正如我所看到的,许多使用链表(成为最有效的方法)并使用数组的堆栈的实现。

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;
    }
}

Please I would like to hear your opinion, as I really haven't seen this kind of implementation ANYWHERE else. 拜托,我想听听您的意见,因为我真的没有其他地方看到过这种实现。 Please feel free to explain the complexity ! 请随时解释其复杂性!

As others have commented, this implementation uses a singly linked list, whereas typical implementations use an array to hold the stack. 正如其他人所评论的那样,此实现使用单链表,而典型的实现使用数组来保存堆栈。

So I was wondering how good or efficient this is. 所以我想知道这有多好或有效率。

Complexity first: 复杂度优先:

  • The best / average / worst case time complexity is O(1) . 最佳/平均/最坏情况下的时间复杂度为O(1)

  • The best / average / worst case space complexity is O(N) . 最佳/平均/最坏情况下的空间复杂度为O(N)

Comparing complexities: 比较复杂度:

  • The best-case time complexity is the same as in an array-implementation: O(1) . 最佳情况下的时间复杂度与数组实现中的相同: O(1)

  • The best-case space complexity is the same in an array-implementation: O(N) . 最佳情况下的空间复杂度在数组实现中相同: O(N)

  • The comparison of the average and worst-case complexities is a bit tricky, because the array-based measures depend on whether / how the stack's array is reallocated as the stack grows and shrinks. 平均和最坏情况下的复杂度的比较有点棘手,因为基于数组的度量取决于堆栈是否随着堆栈的增长和缩小而重新分配。 And that is implementation specific. 那是特定于实现的。

Comparing performance (best case): 比较性能(最佳情况):

  • Pushing with the linked list version is more expensive because each push call creates a new object. 使用链表版本进行push会更加昂贵,因为每个push调用都会创建一个新对象。 (In the best case for the array-based version, there is a free slot in the array ... so no reallocation is required.) (对于基于阵列的版本,最好的情况是阵列中有一个空闲插槽……因此不需要重新分配。)

  • Popping is indirectly more expensive because it causes an object to become unreachable. 弹出会间接地增加成本,因为它会导致对象无法到达。

  • Best-case space usage is definitely greater for the list-based implementation. 对于基于列表的实现,最佳情况下的空间使用肯定更大。 Stack entry is represented by an object with 2 references. 堆栈条目由具有2个引用的对象表示。 That is 2 "words" plus object headers plus padding. 那就是2个“单词”加上对象标题加上填充。 In a 64 bit JVM ... probably 24 bytes. 在64位JVM中...可能为24个字节。 By contrast, the array-based solutions use 1 reference in the array ... 8 bytes ... for each entry. 相比之下,基于数组的解决方案在数组中为每个条目使用1个引用... 8个字节...。

Performance and space usage for the average and worst cases is difficult to compare for the reason stated above. 由于上述原因,一般情况和最坏情况下的性能和空间使用情况很难进行比较。

From an API design perspective: the API is providing a non-leaky abstraction. 从API设计的角度来看:API提供了一种非泄漏的抽象。 The only quibble I would have is that popping an empty stack should be an error. 我唯一的疑问是弹出一个空堆栈应该是一个错误。 A pop() method that returns null can lead to problems (NPEs) if the caller doesn't test for unexpected (or expected) null results. 如果调用者不测试意外(或预期)的null结果,则返回null pop()方法可能导致问题(NPE)。 Also, you can't put a null onto the stack. 另外,您不能将null放入堆栈。

(Actually, there's a bug there! If you try to push a null , it "works", but then Stack.isEmpty() will report that the stack is empty. The push method should throw an exception if you attempt to push null ... or at least protect the data structure.) (实际上,那里有一个错误!如果您尝试将null推送,它会“工作”,但是然后Stack.isEmpty()将报告堆栈为空。如果您尝试推送nullpush方法应该引发异常。 ..或至少保护数据结构。)


Please feel free to explain the complexity ! 请随时解释其复杂性!

You will learn more if you work it out for yourself. 如果自己解决问题,您将学到更多。

But this one is fully recursive ... 但这是完全递归的...

Debatable. 值得商榷。 The data structure is recursive in a sense, but the algorithms don't entail recursion. 从某种意义上说,数据结构是递归的,但是算法不需要递归。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM