隊列。queue,就是現實生活中的排隊。java
一、簡單隊列:算法
public class Queqe { private int array[]; private int front; private int end; private int number; private int max; private Queqe(int maxsize){ array = new int[maxsize]; max = maxsize; front = 0; end = 0; number = 0; } private void insert(int item){ if(isFull()){ System.out.println("is full,can not insert"); return; } array[end++] = item; number++; } private int remove(){ if(isEmpty()){ System.out.println("is empty,can not remove"); return -1; } number--; return array[front++]; } private boolean isFull(){ return number == max; } private boolean isEmpty(){ return number == 0; } private int size(){ return number; } private int peekFront(){ return array[front]; } public static void main(String[] args) { Queqe q = new Queqe(4); System.out.println("queqe is empty:"+q.isEmpty()); q.insert(1); q.insert(2); q.insert(3); q.insert(4); q.insert(5); System.out.println(q.size()); System.out.println("front is "+q.peekFront()); while(!q.isEmpty()) System.out.println(q.remove()); } } result: queqe is empty:true is full,can not insert 4 front is 1 1 2 3 4
先進的元素排在前面,那麼移除的時候就是先移除隊頭,達到先進先出的效果。·插入和移除並不用移動整個數組,僅僅需改變隊頭和隊列的指向,因此時間複雜度和棧同樣都是O(1)。express
二、不用number以後的方法改變
數組
前面用了number統計隊列中元素個數,事實上不用這個變量。單靠隊頭和隊尾也是可以實現隊列。數據結構
private boolean isFull(){ return end == max; } private boolean isEmpty(){ return (front ==0&&end ==0)||front == max; } private int size(){ return end -front; }
而推斷是否是滿了更簡單,隊尾移到數組尾部便是滿了。數據結構和算法
空的話會複雜一些,一種是一開始front爲零,但是有元素插入,此時end不爲零。假設二者爲零那就是空了。還有就是不停remove以後,front移到最後,證實以前的元素全部remove掉了,此時也爲空。post
做者依據的是front和end的變化。而後再insert和remove中直接改變front和end的值,在isEmpty和isFull中,好比在isFull()中:spa
private boolean isFull(){ return end+2 == front||(front+max-2==end); }
這樣更復雜。.net
因爲這樣類似循環隊列,超出以後又重頭開始插入。code
事實上在isEmpty和isFull中直接進行推斷就可以了。
而後真的超出的時候直接打印錯誤後return。
三、優先級隊列
銀行辦業務固然要排隊,但是。銀行的vip用戶不需要,因爲他存的錢比你多。銀行重視這種客戶。優先級高,因此他儘管比你晚來到銀行。但是排號的時候拿到的號比你還前。
那這種話,優先級隊列就像是一開始就依據優先級排列好順序的隊列。
private void insert(int item){ if(isFull()){ System.out.println("is full,can not insert"); return; } if(end == 0){ array[end++] = item; }else{ int i; for ( i = number-1; i >=0; i--) { if(item > array[i]){ array[i+1] = array[i]; } } array[i+1]= item; end++; } number++; } result: queqe is empty:true size:0 is full,can not insert queqe is empty:false size:4 front is 4 4 3 2 1
這樣插入元素的同一時候,就已經依照優先級從大到小的順序排好序了(前:prefix expression 中:infix expression 後:postfix expression)。
四、算術表達式的解析
1+2+3=?
因爲咱們從小接受的教育就是從左到右,有括號計算括號中面,先乘除後加減這種思路。而後看到上面那個算式的時候一會兒就得出結果,這是中綴表達式。
也就是咱們腦裏面計算算式的方式。
從左到右,1+2看後面,是+號。那可以直接算1+2的值爲3,3+3後面是=號了,直接計算3+3=6。
1+2*3=?
從左到右,1+2看後面,是*號,那不能直接算1+2的值,先計算2*3=6。再看後面爲=。因此計算1+6=7。
1*(2+3)=?
從左到右,1後面是*,因此原本先計算的,但是後面是(因此先看括號,括號中面是2+3=5後面是=,因此直接計算1*5=5。
但是計算機並不像人腦這麼聰明。一眼看過去基本可以心算。計算機認後綴表達式比較easy,假設咱們從小就接受的是後綴表達式的方式的話。那對於咱們來講同樣可以。
後綴表達式的話就用符號a,b,c表示了。因爲多位數字的話,寫成1242132+,根本就不知道是那兩個數字相加,那麼就要有分隔符,但是無疑會添加難度。
a+b-c轉後綴:
讀a。讀到+,繼續讀到b,寫成ab。再讀到-號可以將+放在ab後面。即ab+,讀入c,後面結束了則ab+c-。
a+b*c轉後綴:
讀a,讀+,讀b,放置爲ab,再讀後面,*優先級大於+號。臨時不能放+,再讀c,c後面結束。因此可以放入*,在放+。即abc*+。
a*(b+c)轉後綴:
讀a,讀*,後面發現(不能放置*,(裏比*優先級高,讀b+c,後面爲),可變爲bc+,再和a*合。即abc+*。
這篇儘管講得是隊列。但是要用到的結構是棧,因爲進來進去的。這裏的算數不用壓入棧,直接輸出。
a+b-c轉後綴:
直接輸出a。讀+。棧空壓入棧,再輸出b。棧非空。彈出+,讀到-,+優先級>= -,輸出+,壓-入棧,輸出c,結束了,彈出-。
最後結果:ab+c-。
a+b*c轉後綴:
直接輸出a,讀+。棧空壓入棧,再輸出b,棧非空,彈出+,讀到*,+優先級< -。因此先+壓入棧,再壓*,輸出c,結束了,彈出*,再彈+。
最後結果:abc*+。
a*(b+c)轉後綴:
直接輸出a。讀*。棧空壓入棧。讀到(壓(入棧,輸出b,讀+。壓入棧。輸出c。讀),發現後面結束可以彈出+並輸出。彈出(不輸出,彈出*。
最後結果:abc+*。看了這個分析過程以後,就是利用棧,對操做符進行棧的壓入和彈出。
假設純粹用高級語言寫計算器,直接使用中綴表達式就能夠,但是到了底層的編譯器。就是需要後綴表達式實現。還要考慮到位數和其它操做符,可想代碼遠遠比上面的複雜。
整體的思路就是這樣,代碼的實現就是經過棧和條件推斷進行入棧和出棧就能夠。