1. 程式人生 > >資料結構之棧及Java實現

資料結構之棧及Java實現

一、棧的基本介紹

棧是一種只允許在一端進行插入或刪除的線性表,也就是說先進後出。棧的操作端通常被稱為棧頂,另一端被稱為棧底,棧的插入操作稱為壓棧(push),棧刪除操作稱為出棧(pop)。壓棧是把新元素放到棧頂元素的上面,使之成為新的棧頂元素;出棧則是把棧頂元素刪除掉,使其相鄰的元素成為新的棧頂元素。
這裡寫圖片描述

二、棧的Java實現

棧的實現方式主要分為兩種,一種是基於陣列實現的,另一種則是基於連結串列。順序儲存的棧稱為順序棧;鏈式儲存的棧稱為鏈式棧。不管是基於何種形式,一般都要實現幾個方法,分別為檢查棧是否為空,是否已滿,壓棧操作和出棧操作,值得說明的是,在鏈式棧中無需檢測棧是否已滿,只要記憶體足夠大,原理上鍊式棧是不會滿的。下面分別介紹兩種方式的實現:

  1. 基於陣列的順序棧

public class ArrayStack<T> {
    private T data[];
    private int maxSize;
    private int top;
    //初始化棧
    public ArrayStack(int maxSize){
        this.maxSize = maxSize;
        data = (T[]) new Object[maxSize];
        this.top = -1;
    }
    //判斷棧是否已空
    public boolean isNull
(){ if(top == -1){ return true; } return false; } //判斷棧是否已滿 public boolean isFull(){ if(top == maxSize-1){ return true; } return false; } //將value壓棧 public boolean push(T value){ if(isFull()){ return
false; } top++; data[top] = value; return true; } //取出棧頂元素 public T pop(){ if(isNull()){ return null; } T tmp = data[top]; data[top] = null; top--; return tmp; } public static void main(String args[]){ ArrayStack<String> as = new ArrayStack<String>(4); as.push("sasa"); as.push("qwwq"); as.push("erer"); as.push("ddsd"); //測試棧已滿時的情況 System.out.println(as.push("hhhhh")); //測試出棧順序 System.out.println(as.pop()); System.out.println(as.pop()); System.out.println(as.pop()); System.out.println(as.pop()); } }

測試結果:

false
ddsd
erer
qwwq
sasa
  1. 基於連結串列的鏈式棧

public class NodeStack<T> {
    private Node<T> top = null;
    public NodeStack(){
        this.top = null;
    }
    //判斷棧是否為空
    public boolean isNull(){
        if(top == null){
            return true;
        }
        return false;
    }
    //壓棧
    public boolean push(T data){
        Node<T> node = new Node<T>(data);
        node.setNext(top);
        top = node;
        return true;
    }
    //出棧
    public T pop(){
        if(isNull()){
            return null;
        }
        T tmp = top.data;
        top = top.getNext();
        return tmp;

    }
    //取出棧頂的值
    public T peek(){
        if(isNull()){
            return null;
        }
        return top.data;
    }
    class Node<T>{
        private T data;
        private Node<T> next;
        public Node(T value){
            this.data = value;
        }
        public Node<T> getNext(){
            return this.next;
        }
        public void setNext(Node<T> n){
            this.next = n;
        }
        public T getData(){
            return this.data;
        }
        public void setData(T d){
            this.data = d;
        }
    }

    public static void main(String args[]){
        NodeStack<String> ns = new NodeStack<String>();

        //測試是否為空
        System.out.println(ns.isNull());
        //壓棧測試
        ns.push("asdwqewqewqea");
        ns.push("ewewwqsdsadsd");
        ns.push("ffddsfsdfdfdf");
        //測試是否為空
        System.out.println(ns.isNull());
        //出棧測試
        System.out.println(ns.pop());
        System.out.println(ns.pop());
        System.out.println(ns.pop());
        //測試是否為空
        System.out.println(ns.isNull());
    }



}

測試結果:

true
false
ffddsfsdfdfdf
ewewwqsdsadsd
asdwqewqewqea
true

三、棧相關演算法實現

括號匹配問題是棧的一個經典應用示例,輸入表示式即一個字串,判斷這個字串的括號是不是匹配。

思路如下所示:

1.迴圈遍歷字串,讀取字元每一個字元
    1.1如果是左括號,則入棧;
    1.2如果ch是右括號,則需要進一步判斷:
        如果棧空:
            說明多出右括號,直接返回false;
        如果棧不空,ch和棧頂比較:
            如果不同,返回false;
            如果匹配,則出棧一次;
2.迴圈結束後棧空,說明左括號匹配完了,則返回true,迴圈結束後棧不空,則返回false

實現程式碼


public class StrMatch {

    public boolean match(String str){
        NodeStack<Character> strMatch = new NodeStack<Character>();
        char tmp;
        //迴圈遍歷字串
        for(int i=0;i<str.length();i++){
            tmp = str.charAt(i);
            //判斷是否為左括號
            if(isLeft(tmp)){
                //左括號入棧
                strMatch.push(tmp);
            }
            //判斷是否為右括號
            else if(isRight(tmp)){
                //如果棧已空,則右括號不能匹配,返回false
                if(strMatch.isNull()){
                    return false;
                }
                //如果右括號與棧頂的左括號相匹配,移除棧頂的左括號
                if(corespd(strMatch.peek(),tmp)){
                    strMatch.pop();
                }
            }
        }
        //迴圈遍歷結束,如果棧已空,則說明匹配完畢,返回true
        if(strMatch.isNull()){
            return true;
        }
        //否則,返回false
        return false;
    }
    //判斷左右括號是否對應
    public boolean corespd(char a,char b){
        if(a == '('&&b ==')')
            return true;
        if(a == '['&&b==']')
            return true;
        if(a == '{'&&b == '}')
            return true;
        return false;
    }
    //判斷是否為左括號
    public boolean isLeft(char c){
        if(c == '(' || c == '[' ||c == '{'){
            return true;
        }
        return false;
    }
    //判斷是否為右括號
    public boolean isRight(char c){
        if(c == ')' || c==']' || c=='}'){
            return true;
        }
        return false;
    }
    public static void main(String[] args) {
        // 測試字串
        StrMatch sm = new StrMatch();
        String inputStr1 = "{[(2+4)+(3-5)/9]*4+1}*{[(2-4)+(3-5)*9]*(4+1)}";
        String inputStr2 = "{[(2+4)+(3-5)/9]*4+1}*{[(2-4)+(3-5)*9]*(4+1}";
        String inputStr3 = "{[(2+4)+(3-5)/9]*4+1}*[(2-4)+(3-5)*9]*(4+1)}";
        System.out.println(sm.match(inputStr1));
        System.out.println(sm.match(inputStr2));
        System.out.println(sm.match(inputStr3));
    }

}

輸出結果

true
false
false