简体   繁体   中英

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) .

  • The best / average / worst case space complexity is O(N) .

Comparing complexities:

  • The best-case time complexity is the same as in an array-implementation: O(1) .

  • The best-case space complexity is the same in an array-implementation: 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. (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. That is 2 "words" plus object headers plus padding. In a 64 bit JVM ... probably 24 bytes. By contrast, the array-based solutions use 1 reference in the array ... 8 bytes ... for each entry.

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. 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. Also, you can't put a null onto the stack.

(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.)


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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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