線性表數據結構解讀(三)棧結構Stack

    在上一篇文章中,咱們詳細介紹了鏈式存儲結構,並結合LinkedList源碼進行了分析,相關文章你們能夠點擊這裏回看個人博客:線性表數據結構解讀(二)鏈式存儲結構LinkedListjava

棧的定義

    棧是一種特殊的線性表,其所有操做都被限制在表的固定一端進行,並且構成棧的元素必須是同一數據類型。數組

棧的特色

    容許插入和刪除的一端稱爲棧頂(top),另外一端稱爲棧底(bottom),不含任何數據元素的棧稱爲空棧。棧又稱爲後進先出的線性表安全

棧的操做

    棧的經常使用操做包括創建棧、元素入棧、元素出棧、取棧頂元素等。markdown

空棧

    當創建一個棧時,不包括任何元素,此時稱其爲空棧。棧爲空時top和bottom共同指向棧底。向棧中插入元素成爲入棧,使top指向的元素退出棧,稱爲出棧,出棧和入棧操做所有是針對棧頂元素進行操做的。數據結構

這裏寫圖片描述

棧的存儲結構

● 順序棧
    將棧在順序存儲結構下所獲得的結構成爲順序棧。順序棧類相似於數組,所以可使用數組實現順序棧的相關運算,一般棧底是下標爲0的一端。this

這裏寫圖片描述

● 鏈式棧
    將棧在鏈式存儲結構下所獲得的結構,稱爲鏈式棧。鏈式棧相似於指針,在java中能夠經過類的對象引用實現指針運算。spa

這裏寫圖片描述

鏈式棧的入棧操做

把top的引用指向新的結點,新結點的下一個引用指向原來的top結點.net

這裏寫圖片描述

鏈式棧的出棧操做

把top的引用指向原棧頂元素的下一個元素,並釋放原棧頂元素的引用線程

這裏寫圖片描述

棧結構在Android中的應用

能夠參考個人博客:完全弄懂Activity四大啓動模式scala

在Android中,咱們常見具備表明性的棧結構爲Stack,下面咱們進行分析,看看它內部是如何實現入棧和出棧操做的。

public class Stack<E> extends Vector<E> {

    private static final long serialVersionUID = 1224463164541339165L;

    /** * 無參構造方法 */
    public Stack() {
    }

    /** * 判斷是否爲空 * Returns whether the stack is empty or not. * @return {@code true} if the stack is empty, {@code false} otherwise. */
    public boolean empty() {
        return isEmpty();
    }

    /** * 返回棧頂的元素 * Returns the element at the top of the stack without removing it. * @return the element at the top of the stack. * @throws EmptyStackException if the stack is empty. * @see #pop */
    @SuppressWarnings("unchecked")
    public synchronized E peek() {
        try {
            return (E) elementData[elementCount - 1];
        } catch (IndexOutOfBoundsException e) {
            throw new EmptyStackException();
        }
    }

    /** * 彈出棧 * Returns the element at the top of the stack and removes it. * @return the element at the top of the stack. * @throws EmptyStackException if the stack is empty. * @see #peek * @see #push */
    @SuppressWarnings("unchecked")
    public synchronized E pop() {
        if (elementCount == 0) {// 若是爲0則爲空棧
            throw new EmptyStackException();// 拋出空棧異常
        }
        // index是被彈出棧元素的下標(先減再賦值)
        final int index = --elementCount;
        final E obj = (E) elementData[index];
        elementData[index] = null;// 把彈出棧的元素值設爲空
        modCount++;
        return obj;
    }

    /** * 推入棧操做 * Pushes the specified object onto the top of the stack. * @param object The object to be added on top of the stack. * @return the object argument. * @see #peek * @see #pop */
    public E push(E object) {
        // 添加一個元素
        addElement(object);
        return object;
    }

    /** * 查詢操做,該方法必定要是線程安全的,不能一邊遍歷一邊增刪 * Returns the index of the first occurrence of the object, starting from * the top of the stack. * @return the index of the first occurrence of the object, assuming that * the topmost object on the stack has a distance of one. * @param o the object to be searched. */
    public synchronized int search(Object o) {
        final Object[] dumpArray = elementData;
        // 非空棧元素的數量
        final int size = elementCount;
        if (o != null) {// 若是傳進來的元素不等於空
            for (int i = size - 1; i >= 0; i--) {// 從棧頂遍歷下去
                if (o.equals(dumpArray[i])) {//若是傳進來的元素等於dumpArray[i]
                    return size - i;
                }
            }
        } else {
            for (int i = size - 1; i >= 0; i--) {
                if (dumpArray[i] == null) {// 若是dumpArray[i]等於null
                    return size - i;
                }
            }
        }
        return -1;
    }
}

咱們注意到源碼中push方法中用到了父類的addElement(),這裏咱們去Stack的父類Vector中一探究竟。

addElement方法

/** * 添加元素方法 * Adds the specified object at the end of this vector. * @param object the object to add to the vector. */
    public synchronized void addElement(E object) {
        // 容量長度和非空元素數量相同
        if (elementCount == elementData.length) {
            growByOne();
        }
        elementData[elementCount++] = object;
        modCount++;
    }

growByOne方法

/** * JIT optimization */
    private void growByOne() {
        int adding = 0;
        if (capacityIncrement <= 0) {
            // 判斷是不是空棧,若是爲空增長1
            if ((adding = elementData.length) == 0) {
                adding = 1;
            }
        } else {// 不然擴容capacityIncrement
            adding = capacityIncrement;
        }
        // 新建立一個數組,把數組長度擴容,而後數組複製
        E[] newData = newElementArray(elementData.length + adding);
        System.arraycopy(elementData, 0, newData, 0, elementCount);
        elementData = newData;
    }

參考來源:動腦學院Danny老師數據結構課程

相關文章
相關標籤/搜索