簡介
棧應該是一種非常簡單並且非常有用的資料結構了。棧的特點就是先進後出FILO或者後進先出LIFO。
實際上很多虛擬機器的結構都是棧。因為棧在實現函式呼叫中非常的有效。
今天我們一起來看學習一下棧的結構和用法。
棧的構成
棧一種有序的線性表,只能在一端進行插入或者刪除操作。這一端就叫做top端。
定義一個棧,我們需要實現兩種功能,一種是push也就是入棧,一種是pop也就是出棧。
當然我們也可以定義一些其他的輔助功能,比如top:獲取棧上最頂層的節點。isEmpty:判斷棧是否為空。isFull:判斷棧是否滿了之類。
先看下入棧的動畫:
再看下出棧的動畫:
棧的實現
具有這樣功能的棧是怎麼實現呢?
一般來說棧可以用陣列實現,也可以用連結串列來實現。
使用陣列來實現棧
如果使用陣列來實現棧的話,我們可以使用陣列的最後一個節點作為棧的head。這樣在push和pop棧的操作的時候,只需要修改陣列中的最後一個節點即可。
我們還需要一個topIndex來儲存最後一個節點的位置。
實現程式碼如下:
public class ArrayStack {
//實際儲存資料的陣列
private int[] array;
//stack的容量
private int capacity;
//stack頭部指標的位置
private int topIndex;
public ArrayStack(int capacity){
this.capacity= capacity;
array = new int[capacity];
//預設情況下topIndex是-1,表示stack是空
topIndex=-1;
}
/**
* stack 是否為空
* @return
*/
public boolean isEmpty(){
return topIndex == -1;
}
/**
* stack 是否滿了
* @return
*/
public boolean isFull(){
return topIndex == array.length -1 ;
}
public void push(int data){
if(isFull()){
System.out.println("Stack已經滿了,禁止插入");
}else{
array[++topIndex]=data;
}
}
public int pop(){
if(isEmpty()){
System.out.println("Stack是空的");
return -1;
}else{
return array[topIndex--];
}
}
}
使用動態陣列來實現棧
上面的例子中,我們的陣列大小是固定的。也就是說stack是有容量限制的。
如果我們想構建一個無限容量的棧應該怎麼做呢?
很簡單,在push的時候,如果棧滿了,我們將底層的陣列進行擴容就可以了。
實現程式碼如下:
public void push(int data){
if(isFull()){
System.out.println("Stack已經滿了,stack擴容");
expandStack();
}
array[++topIndex]=data;
}
//擴容stack,這裡我們簡單的使用倍增方式
private void expandStack(){
int[] expandedArray = new int[capacity* 2];
System.arraycopy(array,0, expandedArray,0, capacity);
capacity= capacity*2;
array= expandedArray;
}
當然,擴容陣列有很多種方式,這裡我們選擇的是倍增方式。
使用連結串列來實現
除了使用陣列,我們還可以使用連結串列來建立棧。
使用連結串列的時候,我們只需要對連結串列的head節點進行操作即可。插入和刪除都是處理的head節點。
public class LinkedListStack {
private Node headNode;
class Node {
int data;
Node next;
//Node的建構函式
Node(int d) {
data = d;
}
}
public void push(int data){
if(headNode == null){
headNode= new Node(data);
}else{
Node newNode= new Node(data);
newNode.next= headNode;
headNode= newNode;
}
}
public int top(){
if(headNode ==null){
return -1;
}else{
return headNode.data;
}
}
public int pop(){
if(headNode ==null){
System.out.println("Stack是空的");
return -1;
}else{
int data= headNode.data;
headNode= headNode.next;
return data;
}
}
public boolean isEmpty(){
return headNode==null;
}
}
本文的程式碼地址:
本文已收錄於 http://www.flydean.com/10-algorithm-stack/
最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!
歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!