『數據結構與算法』棧:詳解與代碼實現

微信搜索:碼農StayUp
主頁地址:https://gozhuyinglong.github.io
源碼分享:https://github.com/gozhuyinglong/blog-demosjava

1. 棧(Stack)

棧又叫堆棧,是一種運算受限制的線性表,限定只能在一端進行插入和刪除操做,該端稱爲棧頂(Top),相對的另外一端叫棧底(Bottom)。git

根據棧的定義可知,最早進入棧的元素在棧底,最後進入棧的元素在棧頂。而刪除元素恰好相反,即刪除順序從棧頂到棧底github

對棧的操做只有兩種:數組

  • 入棧(push):又叫進棧或壓棧,即向棧插入一條新的元素,該元素爲新的棧頂元素。
  • 出棧(pop):又叫退棧,即從棧頂刪除(取出)最後入棧的元素,而其相鄰元素成爲新的棧頂元素。

棧的模型.jpg

棧是一個先進後出(FILO - First In Last Out)的有序列表。在上圖中描述了棧的模型,咱們對棧的操做只有pushpop,棧頂元素是該棧惟一可見的元素。微信

2. 代碼實現

因爲棧是一個表,所以任何實現表的方法都能實現棧。顯然咱們以前用到的《 數組 》和《 鏈表 》均可以實現棧。下面代碼是使用數組實現的一個棧。工具

size表示棧內元素的大小,棧頂元素爲 elementData[size - 1],棧底元素爲 elementData[0]。入棧時執行 size++,出站時執行 size--this

public class StackDemo {

    public static void main(String[] args) {

        System.out.println("-------------------入站");
        Stack<String> stack = new Stack<>(10);
        stack.push("a");
        stack.push("b");
        stack.push("c");
        stack.push("d");
        stack.push("e");
        stack.print();

        System.out.println("元素大小: " + stack.size());
        System.out.println("棧容量: " + stack.capacity());

        System.out.println("-------------------出站");
        System.out.println("出站元素: " + stack.pop());
        System.out.println("出站元素: " + stack.pop());
        stack.print();
        System.out.println("元素大小: " + stack.size());
        System.out.println("棧容量: " + stack.capacity());
    }

    private static class Stack<E> {
        private int size; // 元素大小
        private final int capacity; // 棧的容量
        transient Object[] elementData; // 元素數據

        public Stack(int capacity) {
            if (capacity <= 0) {
                throw new IllegalArgumentException("Illegal Capacity: " + capacity);
            } else {
                this.capacity = capacity;
                elementData = new Object[capacity];
            }
        }

        /**
         * 獲取棧的元素大小
         *
         * @return
         */
        public int size() {
            return size;
        }

        /**
         * 獲取棧的容量
         *
         * @return
         */
        public int capacity() {
            return capacity;
        }

        /**
         * 入棧
         *
         * @param e
         * @return
         */
        public boolean push(E e) {
            if (size >= capacity) {
                return false;
            }
            elementData[size++] = e;
            return true;
        }

        /**
         * 出棧
         *
         * @return
         */
        public E pop() {
            if (size <= 0) {
                return null;
            }
            return (E) elementData[--size];
        }

        /**
         * 打印元素數據
         */
        public void print() {
            System.out.print("站內元素: ");
            for (int i = 0; i < size; i++) {
                System.out.printf("%s\t", elementData[i]);
            }
            System.out.println();
        }
    }
}

輸出結果:.net

-------------------入站
站內元素: a	b	c	d	e	
元素大小: 5
棧容量: 10
-------------------出站
出站元素: e
出站元素: d
站內元素: a	b	c	
元素大小: 3
棧容量: 10

3. 棧的應用 - 平衡符號

編譯器檢查程序的語法錯誤時,經常會由於缺乏一個符號(如遺漏一個花括號等)引發編譯器上列出上百行的診斷,而真正的錯誤並無找出。在這種狀況下,若是能有一個工具可以檢測括號必須成對出現那就行了,這即可以使用棧進行解決。code

下面代碼使用了Java自帶的Stack類進行實現。字符串[ ( ) ]是合法的,而[ ( ] )是錯誤的。blog

代碼實現:

public class StackDemoBalancedChar {

    public static void main(String[] args) {

        BalancedChar balancedChar = new BalancedChar();
        String str = "[()][{}][][((()))]";
        boolean ok = balancedChar.isOk(str);
        System.out.printf("字符串:%s\t----> %s", str, ok);
    }

    private static class BalancedChar {
        private final char[] openArray = {'(', '[', '{'};  // 左括號
        private final char[] closeArray = {')', ']', '}'}; // 右括號

        /**
         * 判斷字符串是否正確
         *
         * @param str
         * @return
         */
        public boolean isOk(String str) {
            // 使用 Java 自帶的 Stack 類
            Stack<Character> stack = new Stack<>();

            boolean ok = true; // 判斷字符串是否正確

            for (char c : str.toCharArray()) {

                // 若不是平衡符則忽略
                if (!isBalancedChar(c)) {
                    continue;
                }

                // 若是是左括號,則入棧
                if (isOpen(c)) {
                    stack.push(c);
                    continue;
                }

                // 若是是右括號,而棧爲空則報錯
                if (stack.empty()) {
                    ok = false;
                    break;
                }
                // 若是是右括號,從棧中取出一個元素,並與當前元素判斷是不是一對,若不是一對則報錯
                Character open = stack.pop();
                if (!isTwain(open, c)) {
                    ok = false;
                }
            }

            return ok && stack.empty();
        }

        /**
         * 是否爲左括號
         *
         * @param c
         * @return
         */
        public boolean isOpen(char c) {
            return inArray(openArray, c);
        }

        /**
         * 是否爲右括號
         *
         * @param c
         * @return
         */
        public boolean isClose(char c) {
            return inArray(closeArray, c);
        }

        /**
         * 是不是平衡符
         */
        public boolean isBalancedChar(char c) {
            return isOpen(c) || isClose(c);
        }

        /**
         * 是否在數組中
         *
         * @param charArray
         * @param c
         * @return
         */
        public boolean inArray(char[] charArray, char c) {
            for (char c1 : charArray) {
                if (c1 == c) {
                    return true;
                }
            }
            return false;
        }

        /**
         * 是否一對平衡符
         *
         * @param open
         * @param close
         * @return
         */
        public boolean isTwain(char open, char close) {
            switch (open) {
                case '(':
                    if (close == ')') {
                        return true;
                    }
                case '[':
                    if (close == ']') {
                        return true;
                    }
                case '{':
                    if (close == '}') {
                        return true;
                    }
                default:
                    return false;
            }
        }

    }
}

輸出結果:

字符串:[()][{}][][((()))]	----> true
相關文章
相關標籤/搜索