【问题标题】:Implement Stack Using Array in Java在 Java 中使用数组实现栈
【发布时间】:2016-07-18 12:27:18
【问题描述】:

我正在尝试在 Java 中使用数组作为其核心来实现堆栈。这只是学习和理解堆栈工作原理的目的。

我的想法是使用 Array(而不是 ArrayList)并尝试模仿 Stack 结构。此实现将具有静态大小。有一个以 -1 开头的指针表示空堆栈。指针会随着我们添加元素而增加,我们不必担心删除元素,因为一旦我们需要该空间(索引),我们将覆盖该值。

以下是我的源代码,后面还有一些问题:

import java.util.*;

public class stackUsingArray{

   private int[] myStack;
   private int pointer;

   /**
    -Constructor
   */
   public stackUsingArray()
   {
       myStack = new int[10];
       pointer = -1;//keep track of where the top element is on the stack.
   }

   /**
    -Pop method
   */
   public int pop()
  {      
      if(pointer==-1)
      {
          //throw exception here
      }
      return myStack[pointer--];
  }

  /**
  -Push when the stack is not empty.
  */

   public void push(int num)
   {
       if(pointer== myStack.size()-1)
       {
           //throw exception here
       }
       else
       {
            myStack[++pointer] = num;//add to the stack           
        }       
   }

/**
-return the top element of the stack
*/
   public void peek()
   {
       return pointer;
   }

/**
-return false if there is not more element on the stack
*/
   public boolean isEmpty()
   {
       return (pointer == -1)? true : false;
   }

   public static void main(String [] arg)
   {
       stackUsingArray newStack = new stackUsingArray();
       newStack.push(1);
       newStack.push(2);
       newStack.push(3);

       System.out.println(newStack.pop());
   }
}

在我注释为抛出异常的部分:

public int pop()
      {      
          if(pointer==-1)
          {
              //throw exception here
          }
          return myStack[pointer--];
      }

您认为哪种例外情况最合乎逻辑?大多数时候,我只是在屏幕上打印出来。不过,我很想学习如何抛出异常。

这部分:

 public void push(int num)
   {
       if(pointer== myStack.size()-1)
       {
           //throw exception here
       }
       else
       {
            myStack[++pointer] = num;//add to the stack           
        }       
   }

程序本身必须执行 myStack.size() -1 的操作。我想知道在班级中有一个私人成员来保持大小-1是否更好?我的意思是效率。

另外,如果我们要使用 ArrayList 来实现这个 Stack。它会更有效地运行吗?我的意思是,ArrayList 有很多开销,例如方法的内部调用。

最后,我知道我的代码不是很好,所以请给我一些建议,让它变得更好!

【问题讨论】:

  • 你知道 Java 已经有一个 Stack 类吗? tutorialspoint.com/java/java_stack_class.htm
  • @SPlatten 他只是想更好地了解它的工作原理。
  • @SPlatten U 在提问之前应该先阅读我写的内容。无论如何,谢谢你的链接。
  • @indjev99 : 谢谢你给他解释,哈哈!

标签: java arrays algorithm performance data-structures


【解决方案1】:

我会抛出从 RuntimeException 派生的自定义 StackEmptyException / StackFullException ,因此它们不会被选中。如果未选中,您的用户不必在 try/catch 中包围每个 pop()。如果您抛出一个检查异常,他们将不得不尝试/捕获每个弹出,或者将他们自己的方法声明为抛出异常。有关更多信息,请参阅此讨论:Java: checked vs unchecked exception explanation

程序本身必须执行 myStack.size() -1 的操作。我想知道在班级中有一个私人成员来保持大小-1是否更好?我的意思是效率。

根本不会引起注意,不要进行只会节省一两个处理器周期的优化,而是降低算法复杂性或 I/O 操作数的优化。

另外,如果我们要使用 ArrayList 来实现这个 Stack。它会更有效地运行吗?我的意思是,ArrayList 有很多开销,例如方法的内部调用。

如果您开始在内部扩展数组,它将与您自己的实现一样运行。

最后,我知道我的代码不是很好,所以请给我一些建议,让它变得更好!非常感谢!

这对于一个学习项目来说非常好,继续努力;)

【讨论】:

    【解决方案2】:

    当堆栈为空时抛出的最合乎逻辑的异常值得商榷,但我会选择 IllegalStateException。

    throw new IllegalStateException("An empty stack cannot be popped.");
    

    我也会使用 ArrayList 而不是直接使用数组。对于数组,您必须自己处理索引溢出,而 ArrayList 在内部非常有效地为您处理。每次您将某些内容附加到 ArrayList 并且它会用完数组大小时,它会将数据复制到一个新数组,该数组的大小是旧数组的两倍。由于事件的相对稀有性,这仍然为您提供了 O(1) 的摊销添加时间。

    如果您确实使用 ArrayList,那么您可能会摆脱堆栈计数器,因为您可以检查 ArrayList 的大小。您可能会失去不必从弹出堆栈中删除条目的好处(我不记得 ArrayList 是否自行优化)。

    作为代码风格问题,使用大写的类名是 Java 约定,因此您应该重命名类以符合约定。

    你的 peek 方法被声明为 void,并且应该返回 myStack[pointer]。同样在你调用 myStack.size() 的 push 方法中,这对于数组是不正确的。如果您不切换到使用 ArrayList,请使用 myStack.length。

    【讨论】:

    • 使代码更清晰的个人偏好是给“指针”一个更清晰的名称来说明它的含义。如果可能将其称为 nextFreeElement 并将其初始化为 0。
    • @jvalli +1 ArrayList 的时间复杂度! +2 命名约定和错误!非常感谢您的帮助!
    • @matthelliwell 我同意你的命名!下次我会记住这一点。我要指出的一点是,因为我使用了Array,并且索引从0(零)开始,所以我不能使用0作为起始值。
    • 如果它指向下一个空闲槽而不是最高使用槽,则将其初始化为 0 将起作用。无论如何,这是一个小问题。
    猜你喜欢
    • 2020-10-24
    • 2016-11-25
    • 2021-06-06
    • 2015-08-17
    • 2021-10-22
    • 1970-01-01
    • 2014-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多