在Java中使用数组实现堆栈

时间:2016-07-18 12:27:19

标签: java arrays algorithm performance data-structures

我正在尝试使用数组作为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有很多开销,比如内部调用方法。

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

2 个答案:

答案 0 :(得分:1)

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

  
    

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

  

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

  
    

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

  

如果您在内部开始增长数组,它将与您自己的实现相同。

  
    

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

  

这对学习项目来说非常好,保持良好的工作;)

答案 1 :(得分:1)

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

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

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

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

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

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