在上一篇文章中,咱們詳細介紹了鏈式存儲結構,並結合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老師數據結構課程