1. 程式人生 > >大話資料結構(五)——棧的兩種java實現方式

大話資料結構(五)——棧的兩種java實現方式

在我們生活當中經常會看到這樣一種操作,比如我們往一個空羽毛球盒子裡面放羽毛球(個人比較喜歡羽毛球,嘿嘿),放完後再將羽毛球一個一個取出的時候會發現,最先放進去的羽毛球往往最後才取出來,相反,最後放入的羽毛球往往最先取出。這個例子形象的說明了棧的操作方式,下面我們來看看什麼是棧,以及棧的一些操作。

那麼什麼是棧呢?棧就是限定在表尾進行插入和刪除操作的線性表。我們將允許插入和刪除的一端稱為棧頂(top),而另一端就稱之為棧底(bottom),當棧中無任何資料元素時稱作空棧。由上面的例子可以知道羽毛球的放入和取出為後進先出的,那麼棧與之相同,也是後進先出的(LIFO)結構。

棧是一個線性表,它具有線性關係,即前驅後繼的關係。由於棧限定了線性表插入和刪除的位置,所以棧底也是固定的。線上性表中表頭是棧底,表我是棧頂。最先入棧的只能在棧底。下面我們來看看棧的兩種操作——進棧和出棧:

進棧(push):棧的插入操作,也可稱為壓棧或者入棧,操作過程就類似上述的放羽毛球的過程。

出棧(pop):棧的刪除操作,也可稱為彈棧,操作過程就類似上述的取羽毛球的過程。
在表尾進行插入和刪除操作的線性表

我們可以看看圖片理解理解:
這裡寫圖片描述
上面也說到了棧是一種線性表,而線性表有順序儲存結構和鏈式儲存結構,所以棧的實現方式也有兩種,即順序棧和鏈式棧。

首先我們來看看順序棧
這裡寫圖片描述

package ArrayStack;

import java.util.Arrays;

/**
 * Created by jiangxs on 17-5-24.
 */
public class
ArrayStack<T> {
private final int DEFAULT_SIZE = 10;//設定預設尺寸 private int capacity;//儲存當前陣列長度 private int addCapacity;//設定當超出原陣列長度時增加的長度 private Object[] elements;//初始化順序棧陣列 private int size;//儲存順序棧中元素的個數 //建立預設長度的空順序棧 public ArrayStack(){ capacity = DEFAULT_SIZE; elements = new
Object[capacity]; } //建立指定長度的空順序棧 public ArrayStack(int capacity){ this.capacity = capacity; elements = new Object[capacity]; } /** * 建立指定長度的空順序棧,並指定超出陣列範圍後的增量 * @param capacity 設定指定長度 * @param addCapacity 設定增量 */ public ArrayStack(int capacity,int addCapacity){ this.capacity = capacity; this.addCapacity = addCapacity; elements = new Object[capacity]; } //獲取順序棧的長度 public int getSize(){ return size; } //判斷順序棧是否為空棧 public boolean isEmpty(){ return size == 0; } //確保陣列長度,如果超出就進行拓展 private void ensureCapacity(int inputCapacity){ //如果輸入的陣列長度大於原有陣列的長度 if (inputCapacity > capacity) { //若果有設定陣列增量 if (addCapacity > 0) while (inputCapacity > capacity) //按照增量擴容,直到大於所需的陣列容量 capacity += inputCapacity; //如果未設定陣列增量 else while (inputCapacity > capacity) //將capacity左移,使其為大於所需容量 capacity <<= 1; //擴容後,將原陣列複製到新陣列中 elements = Arrays.copyOf(elements, capacity); } } //進棧 public void push(T element){ //確保陣列長度 ensureCapacity(size+1); //元素進棧 elements[size++] = element; } //出棧 //同時返回彈出的元素 public T pop(){ //如果是空棧 if (isEmpty()) return null; T element = (T) elements[size-1]; //釋放棧頂元素並將長度減一 elements[--size] = null; return element; } //獲取棧頂元素 public T getTop(){ return (T)elements[size-1]; } //清空順序棧 public void clear(){ for (int i = 0;i<size;i++) elements[i] = null; size = 0; } public String toString(){ if (isEmpty()) return "[]"; else { StringBuilder sb = new StringBuilder("["); for (int i = size-1;i >= 0;i--) sb.append(elements[i].toString()+" "); sb.append("]"); int len = sb.length(); return sb.delete(len-2,len-1).toString(); } } }

測試程式碼:

package ArrayStack;

/**
 * Created by jiangxs on 17-5-24.
 */
public class ArrayStackTest {
    public static void main(String[] args) {
        ArrayStack<String> ll = new ArrayStack<String>();
        System.out.println("原棧中的元素: "+ll);
        System.out.println("----------進棧啦----------");
        //壓棧
        ll.push("haha");
        ll.push("hehe");
        ll.push("xixi");
        ll.push("hiahia");
        ll.push("heihei");
        System.out.println("壓棧後棧中所含元素: "+ll);
        //獲取棧頂元素
        System.out.println("棧頂元素為: "+ll.getTop());
        //獲取棧中元素個數
        System.out.println("當前棧中元素個數為: "+ll.getSize());
        //出棧
        System.out.println("----------出棧啦----------");
        ll.pop();
        System.out.println("出棧後棧中所含元素: "+ll);
        //獲取棧頂元素
        System.out.println("棧頂元素為: "+ll.getTop());
        //獲取棧中元素個數
        System.out.println("當前棧中元素個數為: "+ll.getSize());
    }
}

測試結果

原棧中的元素: []
----------進棧啦----------
壓棧後棧中所含元素: [heihei hiahia xixi hehe haha]
棧頂元素為: heihei
當前棧中元素個數為: 5
----------出棧啦----------
出棧後棧中所含元素: [hiahia xixi hehe haha]
棧頂元素為: hiahia
當前棧中元素個數為: 4

Process finished with exit code 0

下面我們再來看看鏈棧:

鏈棧的入棧操作如下圖:
這裡寫圖片描述
鏈棧的出棧如下圖:
這裡寫圖片描述
下面我們來看看鏈棧的程式碼實現

鏈棧LinkStack

其中棧頂為結點top,類中包含入棧,出棧,清空等操作

package LinkListStack;

/**
 * Created by jiangxs on 17-5-24.
 */
public class LinkListStack<T> {

    //定義一個內部類Node代表單鏈表的結點
    private class Node{
        private T element;
        private Node next;

        //初始化空構造器
        public Node(){}

        //初始化含引數構造器
        public Node(T element,Node next){
            this.element = element;
            this.next = next;
        }
    }

    private Node top;//存放棧頂結點
    private int size;//存放棧中結點數

    //初始化空棧
    public LinkListStack(){}

    //獲取棧長度
    public int getSize(){
        return size;
    }

    //判斷棧是否為空棧
    public boolean isEmpty(){
        return size == 0;
    }

    //進棧
    public void push(T element){
        //進棧時,新結點的後驅指標next指向舊top
        Node newNode = new Node(element,top);
        //進來的新結點更新為top
        top = newNode;
        size++;
    }

    //出棧
    //返回彈出的元素
    public T pop(){
        //如果彈出時棧為空則返回空
        if (isEmpty())
            return null;
        //用一個結點儲存原頭結點
        Node p = top;
        //將現在的頭結點更新為原結點的下一個結點
        top = top.next;
        //將原頭結點釋放
        p.next = null;
        size--;
        return p.element;
    }

    //獲取棧頂元素
    public T getTop(){
        //如果為空棧則返回空
        if (isEmpty())
            return null;
        return top.element;
    }

    //清空棧
    public void clear(){
        top = null;
        size = 0;
    }

    public String toString(){
        if (isEmpty())
            return "[]";
        else {
            StringBuilder sb = new StringBuilder("[");
            for (Node current = top;current != null;current = current.next)
                sb.append(current.element.toString()+"->");
            sb.append("]");
            int len = sb.length();
            return sb.delete(len-3,len-1).toString();
        }
    }
}

測試程式碼:


package LinkListStack;

/**
 * Created by jiangxs on 17-5-24.
 */
public class LinkListStackTest {
    public static void main(String[] args) {
        LinkListStack<String> ll = new LinkListStack<String>();
        System.out.println("原棧中的元素: "+ll);
        System.out.println("----------進棧啦----------");
        //壓棧
        ll.push("haha");
        ll.push("hehe");
        ll.push("xixi");
        ll.push("hiahia");
        ll.push("heihei");
        System.out.println("壓棧後棧中所含元素: "+ll);
        //獲取棧頂元素
        System.out.println("棧頂元素為: "+ll.getTop());
        //獲取棧中元素個數
        System.out.println("當前棧中元素個數為: "+ll.getSize());
        //出棧
        System.out.println("----------出棧啦----------");
        ll.pop();
        System.out.println("出棧後棧中所含元素: "+ll);
        //獲取棧頂元素
        System.out.println("棧頂元素為: "+ll.getTop());
        //獲取棧中元素個數
        System.out.println("當前棧中元素個數為: "+ll.getSize());
    }
}

測試結果:

原棧中的元素: []
----------進棧啦----------
壓棧後棧中所含元素: [heihei->hiahia->xixi->hehe->haha]
棧頂元素為: heihei
當前棧中元素個數為: 5
----------出棧啦----------
出棧後棧中所含元素: [hiahia->xixi->hehe->haha]
棧頂元素為: hiahia
當前棧中元素個數為: 4

Process finished with exit code 0

轉載:https://blog.csdn.net/u013393958/article/details/72675276