本章涉及的三種數據存儲類型:棧、隊列和優先級隊列。java
不一樣類型的結構程序員
程序員的工具
算法
數組是已經介紹過的數據存儲結構,和其餘結構(鏈表、樹等等)同樣,都適用於數據應用中做數據記錄。數據庫
然而,本章要講解的是數據結構和算法更多的是做爲程序員的工具來運用。它們組要做爲構思算法的輔助工具,而不是徹底的數據存儲工具。這些數據結構的生命週期比那些數據庫類型的結構要短的多。在程序操做執行期間它們才被建立,一般它們去執行某項特殊的任務,當完成以後,它們就被銷燬。
數組
受限訪問數據結構
在數組中,只要知道下標就能夠訪問數據項。或順序訪問等。數據結構和算法
而本章的數據結構中,訪問時受限制的,即在特定時刻只有一個數據項能夠被讀取或者被刪除(除非「做弊」);
工具
這些結構接口的設計加強了這種受限訪問。訪問其餘數據項(理論上)是不容許的。
spa
更加抽象設計
棧、隊列和優先級隊列是比數組和其餘數據存儲結構更爲抽象的結構。主要經過接口對棧、隊列和優先級隊列進行定義,這些接口代表經過他們能夠完成的操做,而它們的主要實現機制對用戶來講是不可見的。
例如,棧的主要機制能夠用數組來實現,但它也能夠用鏈表了實現。優先級隊列的內部實現能夠用數組或一種特別的書———堆來實現。
棧
棧只容許訪問一個數據項:即最後插入的數據項。移除這個數據項後才能訪問倒數第二個插入的數據,以此類推。
棧的Java代碼
public class Stack { private int maxSize; private long[] stackArray; private int top; public Stack(int s){ maxSize = s; stackArray = new long[maxSize]; top=-1; } public void push(long j){ stackArray[++top] = j; } public long pop(){ return stackArray[top--]; } public long peek(){ return stackArray[top]; } public boolean isEmpty(){ return (top==-1); } public boolean isFull(){ return top==maxSize-1; } }
public static void main(String[] args) { Stack theStack = new Stack(10); theStack.push(10); theStack.push(20); theStack.push(30); theStack.push(40); while(!theStack.isEmpty()){ long value = theStack.pop(); System.out.print(value); System.out.print(" "); } } //輸出: 40 30 20 10
棧的效率
棧操做所耗的時間不依賴與棧中數據項的個數,所以操做時間很短。棧不須要比較和移動操做。
隊 列
「隊列」(queue)這個單詞是英國人說的「排」(line)(一種等待服務的方式)。
隊列是一種數據結構,有點相似棧,只是在隊列中第一個插入的數據項也會最早被移除(先進先出,FIFO),而在棧中,最後插入的數據項最早移除。
隊列的Java代碼
public class Queue { private int maxSize; private long[] queueArray; private int front; private int rear; private int nItems; public Queue(int s){ maxSize = s; queueArray = new long[maxSize]; front = 0; rear = -1; nItems = 0; } public void insert(long j){ if(rear == maxSize-1) rear = -1; queueArray[++rear]=j; nItems++; } public long remove(){ long temp = queueArray[front++]; if(front==maxSize) front = 0; nItems--; return temp; } public long peekfront(){ return queueArray[front]; } public boolean isEmpty(){ return nItems ==0; } public boolean isFull(){ return nItems == maxSize; } public int size(){ return nItems; } }
public static void main(String[] args) { Queue theQueue = new Queue(5); theQueue.insert(10); theQueue.insert(20); theQueue.insert(30); theQueue.insert(40); theQueue.remove(); theQueue.remove(); theQueue.remove(); theQueue.insert(50); theQueue.insert(60); theQueue.insert(70); theQueue.insert(80); theQueue.insert(90); theQueue.insert(100); while(!theQueue.isEmpty()){ long n = theQueue.remove(); System.out.print(n); System.out.print(" "); } System.out.println(""); }
隊列的效率
和棧同樣,隊列中插入數據項和移除數據項的時間複雜度均爲O(1)。
雙端隊列
雙端隊列,就是一個兩端都是結尾的隊列。隊列的 每一端均可以插入數據項和移除數據項。這些方法能夠叫作insertLeft()和insertRight(),以及removeLeft()和removeRight()。
雙端隊列與棧或隊列相比,是一種多用途的數據結構,在容器類庫中有時會用雙端隊列來提供棧和隊列的兩種功能。可是,雙端隊列不像棧和隊列那麼經常使用。。。。。。。
優先級隊列
優先級隊列是比棧和隊列更專用的數據結構。但它在不少的狀況下都頗有用。像普通隊列同樣,優先級隊列有一個對頭和一個隊尾,而且也是從頭移除數據項。不過在優先級隊列中,數據項按關鍵字的值有序,這樣關鍵字最小的數據項(或者在某些實現中關鍵字最大的數據項)老是在隊頭。數據項插入的時候會按照順序插入到合適的位置以確保隊列的順序。
優先級隊列Java代碼
public class PriorityQueue { private int maxSize; private long[] queueArray; private int nItems; public PriorityQueue(int s){ maxSize = s; queueArray = new long[maxSize]; nItems = 0; } public void inser(long item) { int i; if(nItems==0) queueArray[nItems++] = item; else { for (i = nItems-1; i>=0; i--) { if(item>queueArray[i]) queueArray[i+1] = queueArray[i]; else break; } queueArray[i+1] = item; nItems++; } } public long remove(){ return queueArray[--nItems]; } public long meekMin(){ return queueArray[nItems-1]; } public boolean isEmpty(){ return nItems ==0; } public boolean isFull(){ return nItems==maxSize; } }
public static void main(String[] args) { PriorityQueue queue = new PriorityQueue(5); queue.inser(30); queue.inser(50); queue.inser(10); queue.inser(40); queue.inser(20); while(!queue.isEmpty()){ long item = queue.remove(); System.out.print(item); System.out.print(" "); } System.out.println(""); } //輸出:10 20 30 40 50
在main()方法中隨機插入5個數據項,隨後移除並顯示它們。最小的數據項老是最早移除,因此輸出是:
10 20 30 40 50
優先級隊列的效率
在本章實現的優先級隊列中,插入操做須要O(N)的時間,而刪除則須要O(1)的時間。
解析算術表達式
後綴表達法
平常算術表達式是將操做符(operator)(+,-,*,/)放在兩個操做數(operands)(數字或表明數字的字母)之間的。由於操做符寫在操做數的中間,因此把這表寫法成爲中綴表達法。
在後綴表達式中【也稱爲波蘭逆序表達式(Reverse Polish Natation),或者RPN】,它是由覺得波蘭數學家發明的,操做符跟在兩個操做數的後面。這樣,A+B就成爲AB+,A/B成爲AB/。更復雜的以下表:
中綴表達式 | 後綴表達式 |
A+B-C | AB+C- |
A*B/C | AB*C/ |
A+B*C | ABC*+ |
A*B+C | AB*C+ |
A*(B+C) | ABC+* |
A*B+C*D | AB*CD*+ |
(A+B)*(C-D) | AB+CD-* |
((A+B)*C)-D | AB+C*D- |
A+B(C-D/(E+F)) | ABCDEF+/-*+ |
後綴表達式求職。。。。。
小 結
棧、隊列和優先級隊列是常常用於簡化某些程序操做的數據結構。
在這些數據結構中,只有一個數據項能夠被訪問。
棧容許訪問最後一個插入的數據項。
棧中重要的操做是在棧頂插入(壓入)一個數據項,以及從棧頂移除(彈出)一個數據項。
隊列只容許訪問第一個插入的數據項。
隊列的重要操做是在隊尾插入數據項和在隊頭移除數據項。
隊列能夠實現爲循環隊列,它基於數組,數組下標能夠從數組末端迴繞到數組的開始位置。
優先級隊列容許訪問最小(或者有時是最大)的數據項。
優先級隊列的重要操做是有序地插入新數據項和移除關鍵字最小的數據項。
這些數據結構能夠用數組實現,也能夠用其餘機制(例如鏈表)來實現。
普通算術表達式是用中綴表達法表示的,這種命名的緣由是操做符寫在兩個操做的中間。
在後綴表達法中,操做符跟在兩個操做數的後面。
算術表達式求值一般都是先轉換成後綴表達式,而後再求後綴表達式的值。
在中綴表達式轉換到後綴表達式以及求後綴表達式的值過程裏,棧都是頗有用的工具。