棧(Stack源碼分析)

棧(stack)

  1. 從數據結構的角度理解:是一組數據的存放方式,特點為LIFO,即后進先出(Last in, first out)。在這種數據結構中,數據像積木那樣一層層堆起來,后面加入的數據就放在最上層。使用的時候,最上層的數據第一個被用掉,這就叫做"后進先出"。
  1. 從代碼運行方式角度理解:是調用棧,表示函數或子例程像堆積木一樣存放,以實現層層調用。程序運行的時候,總是先完成最上層的調用,然后將它的值返回到下一層調用,直至完成整個調用棧,返回最后的結果。
  2. 從內存區域的角度上理解:是存放數據的一種內存區域。程序運行的時候,需要內存空間存放數據。一般來說,系統會劃分出兩種不同的內存空間:一種叫做stack(棧),另一種叫做heap(堆)
    參考鏈接:Stack的三種含義

(圖片均來源于網絡)


本文所述是站在數據結構的角度。
棧可以通過鏈表和數組實現,先看通過數組實現的方式。


可以通過查看Stack源碼學習

可以看到StackVector的子類,Vector本身是一個可增長的線程安全的對象數組( a growable array of objects)

里面主要是如下方法

E push(E item)   
         把項壓入堆棧頂部。   
E pop()   
         移除堆棧頂部的對象,并作為此函數的值返回該對象。   
E peek()   
         查看堆棧頂部的對象,但不從堆棧中移除它。   
boolean empty()   
         測試堆棧是否為空。    
int search(Object o)   
         返回對象在堆棧中的位置,以 1 為基數。  

push

 /**
     * Pushes an item onto the top of this stack. This has exactly
     * the same effect as:
     * <blockquote><pre>
     * addElement(item)</pre></blockquote>
     *
     * @param   item   the item to be pushed onto this stack.
     * @return  the <code>item</code> argument.
     * @see     java.util.Vector#addElement
     */
    public E push(E item) {
        addElement(item);

        return item;
    }

就是調用了VectoraddElement

/**
     * Adds the specified component to the end of this vector,
     * increasing its size by one. The capacity of this vector is
     * increased if its size becomes greater than its capacity.
     *
     * <p>This method is identical in functionality to the
     * {@link #add(Object) add(E)}
     * method (which is part of the {@link List} interface).
     *
     * @param   obj   the component to be added
     */
    public synchronized void addElement(E obj) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = obj;
    }

/**
     * This implements the unsynchronized semantics of ensureCapacity.
     * Synchronized methods in this class can internally call this
     * method for ensuring capacity without incurring the cost of an
     * extra synchronization.
     *
     * @see #ensureCapacity(int)
     */
    private void ensureCapacityHelper(int minCapacity) {
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }


    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
  

就是判斷是否擴容,然后賦值即可

poppeek

/**
     * Removes the object at the top of this stack and returns that
     * object as the value of this function.
     *
     * @return  The object at the top of this stack (the last item
     *          of the <tt>Vector</tt> object).
     * @throws  EmptyStackException  if this stack is empty.
     */
    public synchronized E pop() {
        E       obj;
        int     len = size();

        obj = peek();
        removeElementAt(len - 1);

        return obj;
    }

 /**
     * Looks at the object at the top of this stack without removing it
     * from the stack.
     *
     * @return  the object at the top of this stack (the last item
     *          of the <tt>Vector</tt> object).
     * @throws  EmptyStackException  if this stack is empty.
     */
    public synchronized E peek() {
        int     len = size();

        if (len == 0)
            throw new EmptyStackException();
        return elementAt(len - 1);
    }

Vector

 /**
     * Deletes the component at the specified index. Each component in
     * this vector with an index greater or equal to the specified
     * {@code index} is shifted downward to have an index one
     * smaller than the value it had previously. The size of this vector
     * is decreased by {@code 1}.
     *
     * <p>The index must be a value greater than or equal to {@code 0}
     * and less than the current size of the vector.
     *
     * <p>This method is identical in functionality to the {@link #remove(int)}
     * method (which is part of the {@link List} interface).  Note that the
     * {@code remove} method returns the old value that was stored at the
     * specified position.
     *
     * @param      index   the index of the object to remove
     * @throws ArrayIndexOutOfBoundsException if the index is out of range
     *         ({@code index < 0 || index >= size()})
     */
    public synchronized void removeElementAt(int index) {
        modCount++;
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                                     elementCount);
        }
        else if (index < 0) {
            throw new ArrayIndexOutOfBoundsException(index);
        }
        int j = elementCount - index - 1;
        if (j > 0) {
            System.arraycopy(elementData, index + 1, elementData, index, j);
        }
        elementCount--;
        elementData[elementCount] = null; /* to let gc do its work */
    }
    
/**
     * Returns the component at the specified index.
     *
     * <p>This method is identical in functionality to the {@link #get(int)}
     * method (which is part of the {@link List} interface).
     *
     * @param      index   an index into this vector
     * @return     the component at the specified index
     * @throws ArrayIndexOutOfBoundsException if the index is out of range
     *         ({@code index < 0 || index >= size()})
     */
    public synchronized E elementAt(int index) {
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
        }

        return elementData(index);
    }

@SuppressWarnings("unchecked")
    E elementData(int index) {
        return (E) elementData[index];
    }

先調用peek()得到需要出棧的對象,也就是數組頂部的對象,在調用VectorremoveElementAt移除。

empty

/**
     * Tests if this stack is empty.
     *
     * @return  <code>true</code> if and only if this stack contains
     *          no items; <code>false</code> otherwise.
     */
    public boolean empty() {
        return size() == 0;
    }

search

/**
     * Returns the 1-based position where an object is on this stack.
     * If the object <tt>o</tt> occurs as an item in this stack, this
     * method returns the distance from the top of the stack of the
     * occurrence nearest the top of the stack; the topmost item on the
     * stack is considered to be at distance <tt>1</tt>. The <tt>equals</tt>
     * method is used to compare <tt>o</tt> to the
     * items in this stack.
     *
     * @param   o   the desired object.
     * @return  the 1-based position from the top of the stack where
     *          the object is located; the return value <code>-1</code>
     *          indicates that the object is not on the stack.
     */
    public synchronized int search(Object o) {
        int i = lastIndexOf(o);

        if (i >= 0) {
            return size() - i;
        }
        return -1;
    }

參考鏈接:
java.util.Stack類簡介


接下來看看使用鏈式的方式實現


鏈式結構

代碼表示:

     private Node top = null;
    private int number = 0;

    class Node {
        public T Item;
        public Node Next;
    }

入棧

入棧:將top的指向換為入棧的對象,然后將這個入棧的對象指向上一個入棧的對象即可。

代碼表示:

public void push(T node) {
        Node oldFirst = top;
        top = new Node();
        top.Item = node;
        top.Next = oldFirst;
        number++;
    }

出棧

出棧:根據出棧的對象得到next,然后top指向即可。
代碼表示:

 public T pop() {
        T item = top.Item;
        top = top.Next;
        number--;
        return item;
    }

一個偽代碼類表示:

/**
 * Created by zzw on 2017/6/27.
 * Version:
 * Des:
 */

public class StackLinkedList<T> {

    private Node top = null;
    private int number = 0;

   class Node {
        public T Item;
        public Node Next;
    }

    public void push(T node) {
        Node oldFirst = top;
        top = new Node();
        top.Item = node;
        top.Next = oldFirst;
        number++;
    }

    public T pop() {
        T item = top.Item;
        top = top.Next;
        number--;
        return item;
    }
}

參考連接:
淺談算法和數據結構: 一 棧和隊列


水平有限,文中有什么不對或者有什么建議希望大家能夠指出,謝謝!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 從三月份找實習到現在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發崗...
    時芥藍閱讀 42,366評論 11 349
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,765評論 18 399
  • JVM內存模型Java虛擬機(Java Virtual Machine=JVM)的內存空間分為五個部分,分別是: ...
    光劍書架上的書閱讀 2,606評論 2 26
  • (一)Java部分 1、列舉出JAVA中6個比較常用的包【天威誠信面試題】 【參考答案】 java.lang;ja...
    獨云閱讀 7,142評論 0 62
  • 我還是擅長,胡思亂想,尤其是對心儀的姑娘/往往,她隨口一句話,我心理活動就一大筐/胡思亂想,一不小心,都會把氣氛搞...
    狗奴才樂隊閱讀 183評論 0 0