【问题标题】:Java implementation for stack堆栈的 Java 实现
【发布时间】:2019-11-11 15:04:28
【问题描述】:

Java 中是否有一个类从数据结构书籍中实现 Stack 的概念,意思是 LIFO,pop 是 O(1),push in O(1)?

我读了一点java.util.Stack 的代码,push 似乎不是 O(1) - push 可以调用 Vector.grow() 并且它可能需要 O(n) (我知道它摊销了 O (1) 但我一直在寻找 O(1) )

我想了解为什么 java.util.Stack 是按原样设计的,而不是按堆栈的理论原理设计的

【问题讨论】:

  • 您可以使用节点编写自己的代码 - 这就像 100 行代码
  • 回复:更新 - 请ask one question per post
  • “我想了解为什么 java.util.Stack 是按原样设计的”你问的是设计的哪一部分?请记住:Stack 是一个非常古老的类;从那时起,对类设计的理解有了很大的发展,所以部分答案(无论你问的是设计的哪个部分)是“因为他们当时并不知道更好”。

标签: java data-structures stack time-complexity


【解决方案1】:

ArrayDeque 优于 LinkedList

因为它由数组支持,而不是将单个元素存储在单独的节点实例中,所以它的性能要高得多。

LinkedList 的作者 Josh Bloch 在tweets 中表示:

真的有人使用 LinkedList 吗?我写的,我从来没用过。

and

ArrayDeque 是一个很棒的堆栈、队列或双端队列

【讨论】:

    【解决方案2】:

    您可以使用实现Deque 接口的LinkedListArrayDeque,并且该接口具有类似堆栈的方法poppush。因为LinkedListArrayDeque 实现了这个接口,所以我们可以像使用Stack 一样使用它们。

    来自Deque 的文档:

    双队列也可以用作 LIFO(后进先出)堆栈。应优先使用此接口,而不是旧的 Stack 类。当双端队列用作堆栈时,从双端队列的开头推送和弹出元素。

    如您所见,Deque 的实现应该优先于旧的Stack 类。

    【讨论】:

    • ArrayDeque Javadoc 注释(部分)当用作堆栈时,此类可能比 Stack 快,当用作队列时,它可能比 LinkedList 快。
    • @ElliottFrisch "...并且比 LinkedList 快 当用作队列时" 但这个问题是关于将其用作堆栈 (LIFO) 所以我不确定是否引用在这里适用,因为第一部分是关于java.util.Stack,第二部分是关于队列(代表先进先出——如果我没记错的话)。
    • @Pshemo 双端队列是一个双端队列;例如它既是 LIFO Stack 也是 FIFO Queue,具体取决于您的使用方式。
    • @ElliottFrisch 澄清一下,我并不是说 LinkedList 比 ArrayQueue 更好。我的观点是,尽管 deque 也可以用作 LIFO,但引用的部分是关于将其用作队列 (FIFO) 的优势。
    【解决方案3】:

    tl;博士

    Stack 现在是旧代码

    java.util.Stack 类现在是 legacy,从另一个旧类 java.util.Vector 扩展而来。您不应该使用这些类。你也不应该把它们当作光辉的例子来研究。

    Java 集合框架

    这两个类都在 20 年前被 Java Collections Framework 取代。

    对于LIFO 行为,您应该查看实现queue interfacesdeque interfaces 的类。

    java.util.Queue 接口在许多与 Java 捆绑在一起的类中实现。

    • 抽象队列
    • ArrayBlockingQueue
    • ArrayDeque
    • ConcurrentLinkedDeque
    • ConcurrentLinkedQueue
    • 延迟队列
    • LinkedBlockingDeque
    • LinkedBlockingQueue
    • 链表
    • LinkedTransferQueue
    • PriorityBlockingQueue
    • 优先队列
    • 同步队列

    您可能会发现 LIFO 集合在 3rd 方库的其他地方实现,可能是 Google Guava

    LinkedList

    正如其他人所提到的,首先要考虑的是 LinkedList 用于在 How is LinkedList's add(int, E) of O(1) complexity? 上讨论的 O(1) 行为。

    【讨论】:

      【解决方案4】:

      Stack 或 Queue 都可以用 Linkedlist 来实现。

      pop ( ) : 移除栈顶元素。

      push():向栈顶添加一项。

      public class MyStack<T> {
      
         private StackNode<T> top;
          private static class StackNode<T> {
      
              private T data;
              private StackNode<T> next;
      
              public StackNode(T data) {
                  this.data = data;
              }
          }
      
          public T pop() {
              if (top == null) throw new EmptystackException();
              T item = top.data;
              top = top.next;
              return item;
          }
      
          public void push(T item) {
      
              StackNode<T> t = new StackNode<T>(item);
              t.next = top;
              top = t;
          }
      }
      

      【讨论】:

        【解决方案5】:

        栈是一个线性数据结构。它在 LIFO(后进先出机制)下工作,它有 3 个基本操作:Pop()、Push() 和 peek()。 Push 和 Pop 操作只能在称为 top 的一端执行。 peek() 操作是显示堆栈中的元素。

        下面是堆栈的 JAVA 实现。我们将存储在 Stack 中的数据类型是 String

        当堆栈满时,称为'OVERFLOW',当堆栈为空时,我们称之为'UNDERFLOW'

        public class StackOfString {
        
        int top = -1;
        String[] myStack;
        
        public StackOfString() {
            this.myStack = new String[5];
        }
        
        public void pop() {
            if (top != -1) {
                System.out.println("Item to be Poped: " + myStack[top]);
                myStack[top] = null;
                top -= 1;
            } else {
                System.out.println("Stack is UNDERFLOW!!!");
            }
        }
        
        public void push(String str) {
            if (isFull()) {
                top += 1;
                myStack[top] = str;
            }else {
                System.out.println("Stack is OVERFLOW!!!");
            }
            
        
        }
        
        public boolean isFull() {
            if (top < (myStack.length -1)) {
                return true;
            } else {
                return false;
            }
        }
        
        public void peek() {
            for (String string : myStack) {
                if (string != null)
                    System.out.println(string);
            }
        }}
        

        public class Client {
        
        public static void main(String[] args) {
            // TODO Auto-generated method stub
        
            StackOfString stackOfString = new StackOfString();
        
            stackOfString.pop();
        
            stackOfString.push("A");
            stackOfString.push("B");
            stackOfString.push("C");
            stackOfString.push("D");
            stackOfString.push("E");
            stackOfString.peek();
            stackOfString.push("F");
        
            stackOfString.pop();
            stackOfString.pop();
            stackOfString.pop();
            stackOfString.pop();
            stackOfString.pop();
            stackOfString.pop();
        }}
        

        这是输出:

        【讨论】:

          猜你喜欢
          • 2021-06-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-01-25
          • 2020-10-24
          • 1970-01-01
          • 2016-04-16
          • 2010-11-27
          相关资源
          最近更新 更多