Java 集合深刻理解(13):Stack 棧

點擊查看 Java 集合框架深刻理解 系列, - ( ゜- ゜)つロ 乾杯~html

今天心情不錯,再來一篇 Stack !java

數據結構中的 棧
數據結構中,棧是一種線性數據結構,聽從 LIFO(後進先出)的操做順序,全部操做都是在頂部進行api

有點像羽毛球筒:數組

棧一般有三種操做:markdown

push 入棧
pop 棧頂元素出棧,並返回
peek 獲取棧頂元素,並不刪除數據結構

咱們自定義一個 棧 時只要實現上述三個主要操做便可,本文中將使用 Java 中的 LinkedList 實現一個棧。
棧的使用場景:
棧最主要的意義就在於:入棧和出棧的對稱性。
在 Android 開發中,咱們常常須要開啓、回退一個 Activity,其實這裏就有棧的應用,每次開啓Activity,若是不是特殊的啓動模式,就會在棧頂加入一個 Activity,點擊返回後,以前的 Activity 出棧 。
其餘場景好比遞歸(斐波那契數列,漢諾塔)。oracle

Java 集合框架中的棧 Stack框架

Java 集合框架中的 Stack 繼承自 Vector:ide

因爲 Vector 有 4 個構造函數,加上 Stack 自己的一種,也就是說有 5 中建立 Stack 的方法
跟 Vector 同樣,它是 數組實現的棧。函數

Stack 的方法
Stack 中新建的方法比較少:

1.構造函數
//構建一個空棧
public Stack() {
}
2.入棧
//調用的 Vector.addElement()
public E push(E item) {
addElement(item);

return item;

}
Vector 的 addElement() 方法,就是在數組尾部添加元素:
public synchronized void addElement(E obj) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = obj;
}
3.獲取頂端元素,但不刪除
public synchronized E peek() {
//調用 Vector.size() 返回元素個數
int len = size();

if (len == 0)
    throw new EmptyStackException();
//調用 Vector.elementAt 獲得棧頂元素
return elementAt(len - 1);

}
Vector.elementAt(int):
public synchronized E elementAt(int index) {
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
}

return elementData(index);

}
Vector.elementData(int):
E elementData(int index) {
return (E) elementData[index];
}
4.出棧
public synchronized E pop() {
E obj;
int len = size();

//調用 peek() 獲取頂端元素,一下子返回
obj = peek();
//調用 Vector.removeElementAt 刪除頂端元素
removeElementAt(len - 1);

return obj;

}
Vector.removeElementAt(int):
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 */

}
5.查找元素是否在棧中
public synchronized int search(Object o) {
int i = lastIndexOf(o);

//返回的是棧頂到該元素出現的位置的距離
if (i >= 0) {
    return size() - i;
}
return -1;

}
6.是否爲空
public boolean empty() {
return size() == 0;
}
Vector.size():
public synchronized int size() {
return elementCount;
}
總結
Java 集合框架中的 Stack 具備如下特色:

繼承自 Vector
有 5 種建立 Stack 的方法
採用數組實現
除了 push(),剩下的方法都是同步的

用鏈表實現一個棧?
因爲 Stack 是用數組實現的,咱們用鏈表實現一下吧,這裏就選擇 LinkedList 來實現:
/**

  • description:LinkedList 模擬 Stack
  • <br/>
  • author: shixinzhang
  • <br/>
  • data: 10/23/2016
    */
    public class LinkedListStack extends LinkedList{
    public LinkedListStack(){
    super();
    }

    @Override
    public void push(Object o) {
    super.push(o);
    }

    @Override
    public Object pop() {
    return super.pop();
    }

    @Override
    public Object peek() {
    return super.peek();
    }

    @Override
    public boolean isEmpty() {
    return super.isEmpty();
    }

    public int search(Object o){
    return indexOf(o);br/>}
    }
    調用:
    @Test
    public void testPush() throws Exception {
    LinkedListStack stack = new LinkedListStack();
    System.out.println("棧是否爲空: " + stack.isEmpty());

    stack.push("shixin");
    stack.push("好帥");
    stack.push("技巧一流");
    stack.push("haha");

    System.out.println("棧中元素: " + stack);

    System.out.println("獲取頂端元素 peek :" + stack.peek());

    System.out.println("頂端元素出棧 pop :" + stack.pop());

    System.out.println("出棧後棧內元素:" + stack);

    System.out.println("search(好帥) 的位置:" + stack.search("好帥"));
    }
    }
    結果:

能夠看到,我其實都沒作什麼哈哈,都是 LinkedList 內部提供的方法,操做的都是在鏈表頭部的元素,而不是尾部。
其實 LinkedList 這個棧的特性也是繼承自 雙端隊列 Deque,官方也推薦在使用棧時優先使用 Deque,而不是 Stack,有興趣的能夠去了解下。
Thanks
https://docs.oracle.com/javase/8/docs/api/java/util/Stack.html
http://www.cnblogs.com/kaituorensheng/archive/2013/03/02/2939690.html
http://www.nowamagic.net/librarys/veda/detail/2298

相關文章
相關標籤/搜索