棧(Stack源碼分析)

棧(stack)

  1. 從數(shù)據(jù)結(jié)構(gòu)的角度理解:是一組數(shù)據(jù)的存放方式,特點為LIFO沮榜,即后進(jìn)先出(Last in, first out)坎吻。在這種數(shù)據(jù)結(jié)構(gòu)中,數(shù)據(jù)像積木那樣一層層堆起來晓铆,后面加入的數(shù)據(jù)就放在最上層。使用的時候绰播,最上層的數(shù)據(jù)第一個被用掉骄噪,這就叫做"后進(jìn)先出"。
  1. 從代碼運行方式角度理解:是調(diào)用棧蠢箩,表示函數(shù)或子例程像堆積木一樣存放腰池,以實現(xiàn)層層調(diào)用尾组。程序運行的時候,總是先完成最上層的調(diào)用示弓,然后將它的值返回到下一層調(diào)用讳侨,直至完成整個調(diào)用棧,返回最后的結(jié)果奏属。
  2. 從內(nèi)存區(qū)域的角度上理解:是存放數(shù)據(jù)的一種內(nèi)存區(qū)域跨跨。程序運行的時候,需要內(nèi)存空間存放數(shù)據(jù)囱皿。一般來說勇婴,系統(tǒng)會劃分出兩種不同的內(nèi)存空間:一種叫做stack(棧),另一種叫做heap(堆)嘱腥。
    參考鏈接:Stack的三種含義

(圖片均來源于網(wǎng)絡(luò))


本文所述是站在數(shù)據(jù)結(jié)構(gòu)的角度耕渴。
棧可以通過鏈表和數(shù)組實現(xiàn)齿兔,先看通過數(shù)組實現(xiàn)的方式橱脸。


可以通過查看Stack源碼學(xué)習(xí)

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

里面主要是如下方法

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

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;
    }

就是調(diào)用了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);
    }
  

就是判斷是否擴(kuò)容,然后賦值即可

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];
    }

先調(diào)用peek()得到需要出棧的對象沟突,也就是數(shù)組頂部的對象柒爸,在調(diào)用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類簡介


接下來看看使用鏈?zhǔn)降姆绞綄崿F(xiàn)


鏈?zhǔn)浇Y(jié)構(gòu)

代碼表示:

     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++;
    }

出棧

出棧:根據(jù)出棧的對象得到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;
    }
}

參考連接:
淺談算法和數(shù)據(jù)結(jié)構(gòu): 一 棧和隊列


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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市催什,隨后出現(xiàn)的幾起案子涵亏,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件气筋,死亡現(xiàn)場離奇詭異拆内,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)宠默,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進(jìn)店門麸恍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人搀矫,你說我怎么就攤上這事抹沪。” “怎么了瓤球?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵融欧,是天一觀的道長。 經(jīng)常有香客問我卦羡,道長噪馏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任虹茶,我火速辦了婚禮逝薪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蝴罪。我一直安慰自己董济,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布要门。 她就那樣靜靜地躺著虏肾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪欢搜。 梳的紋絲不亂的頭發(fā)上封豪,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天,我揣著相機(jī)與錄音炒瘟,去河邊找鬼吹埠。 笑死,一個胖子當(dāng)著我的面吹牛疮装,可吹牛的內(nèi)容都是我干的缘琅。 我是一名探鬼主播,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼廓推,長吁一口氣:“原來是場噩夢啊……” “哼刷袍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起樊展,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤呻纹,失蹤者是張志新(化名)和其女友劉穎堆生,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雷酪,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡淑仆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了太闺。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片糯景。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖省骂,靈堂內(nèi)的尸體忽然破棺而出蟀淮,到底是詐尸還是另有隱情,我是刑警寧澤钞澳,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布怠惶,位于F島的核電站,受9級特大地震影響轧粟,放射性物質(zhì)發(fā)生泄漏策治。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧服鹅,春花似錦、人聲如沸履腋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽遵湖。三九已至,卻和暖如春晚吞,著一層夾襖步出監(jiān)牢的瞬間延旧,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工槽地, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留迁沫,地道東北人。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓捌蚊,卻偏偏與公主長得像集畅,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子逢勾,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 從三月份找實習(xí)到現(xiàn)在,面了一些公司藐吮,掛了不少溺拱,但最終還是拿到小米逃贝、百度、阿里迫摔、京東沐扳、新浪、CVTE句占、樂視家的研發(fā)崗...
    時芥藍(lán)閱讀 42,246評論 11 349
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法沪摄,類相關(guān)的語法,內(nèi)部類的語法纱烘,繼承相關(guān)的語法杨拐,異常的語法,線程的語...
    子非魚_t_閱讀 31,631評論 18 399
  • JVM內(nèi)存模型Java虛擬機(jī)(Java Virtual Machine=JVM)的內(nèi)存空間分為五個部分擂啥,分別是: ...
    光劍書架上的書閱讀 2,509評論 2 26
  • (一)Java部分 1哄陶、列舉出JAVA中6個比較常用的包【天威誠信面試題】 【參考答案】 java.lang;ja...
    獨云閱讀 7,104評論 0 62
  • 我還是擅長,胡思亂想哺壶,尤其是對心儀的姑娘/往往屋吨,她隨口一句話,我心理活動就一大筐/胡思亂想山宾,一不小心至扰,都會把氣氛搞...
    狗奴才樂隊閱讀 181評論 0 0