優先級隊列(Priority Queue)
優先級隊列也是個隊列,因此也是有這和隊列差不多的設計方法,唯一不同的就是多了一個優先級,普通的隊列是遵循FIFO原則,也就是先進先出,優先級隊列則是按照優先級高低進行出隊,比如將優先級最高的元素作為隊頭優先出列
優先級隊列的應用場景舉例
醫院的夜間門診
隊列元素是病人
優先級是病情的嚴重情況,掛號時間
操作系統的多任務調度
隊列元素是任務
優先級是任務類型
接口設計
int size();//元素的數量
boolean isEmpty();//是否為空
void enQueue(E element);//入隊
E deQueue();//出隊
E front;//獲取隊列的頭元素
void clear();//清空
優先隊列的底層實現
底層是直接利用二叉堆左右優先隊列實現的,通過Person自定義CompareTo方法,比較數字大小,從而定義優先級高低
哈夫曼編碼(Huffman Coding)
哈夫曼編碼,又稱為霍夫曼編碼,它是現代壓縮算法的基礎;
假設現在要把字符串[ABBBCCCCCCCCDDDDDDEE]轉成二進制編碼進行傳輸,可以轉成ASCII編碼(65~69,1000001~1000101),但是會發現結果有點冗長,于是我們可能想到用更短的約定的編碼格式來定義,例如:
A:000;B:001;C:010;D:011;E:100,這樣我們就可以簡單方面的將上面的字符串轉換成:
000 001001001 010010010010010010010010010 011011011011011011 100 一共20個字母,轉成了60個二進制位,使用哈夫曼編碼,可以壓縮成更少的二進制位;
哈法曼樹
先計算出每個字母出現的頻率(權值,這里直接用出現的次數)
利用這些權值,構建一棵哈弗曼樹(又稱為霍夫曼樹,最優二叉樹)
1.以權值作為根節點構建n棵二叉樹,組成森林
2.在森林中選出2個根節點最小的樹合并,并作為一棵新樹的左右子樹,且新樹的根節點為其左右子樹根節點之和
3.從森林中刪除剛才選取的2棵樹,并將新樹加入森林
4.重復2,3步驟,知道森林只剩一棵樹為止,該樹即為哈弗曼樹
上面的步驟轉化為如下圖所示:
構建哈夫曼編碼
left為0,right為1,可以得出A,B,C,D,E5個字母對應的哈弗曼編碼
[ABBBCCCCCCCCDDDDDDEE]的哈夫曼編碼是:1110110110110000000001010101010101111
哈夫曼編碼總結
n個權值構建出來的哈夫曼樹擁有n個葉子節點,每個哈夫曼編碼都不是另一個哈夫曼編碼的前綴,哈夫曼樹是帶權路徑長度最短的樹,權值較大的節點離根節點較近;(帶權路徑長度:樹中所有的子節點的權值乘上其到根節點的路徑長度,與最終的哈夫曼編碼總長度成正比關系)
Trie
Trie 也叫做字典樹,前綴樹(Prefix Tree),單詞查找樹;Trie搜索字符串的效率主要跟字符串的長度有關
Trie 接口設計
Trie 展示圖
上面的展示Trie村粗cat,dog,doggy,does,cast,add6個單詞
紅色代表單詞結束。
Trie實現代碼圖
構建節點代碼
parent:刪除時候由后往前刪除需要用到
HashMap<Character,Node<V>> children;存儲對象,Character代表字母作為key,也就是d o g,Node<V>作為value,存儲相關子節點數據
Character character:存儲的key,刪除時候使用
V value:紅色節點存儲的值,紅色節點也代表一個單詞介紹
boolean word;是否為單詞的結尾,代表單詞是否結束
獲取node代碼
會發現之后很多方法都會用到這個node方法,所以這里就不進一步作單詞的判斷,直接返回node節點按照外面的邏輯進行處理
獲取節點方法get和包含方法判斷
通過word是否為true來判斷要尋找的單詞是否存在
前綴方法
添加方法
添加單詞方法重點就是如果沒有子節點就創建子節點,如果有子節點的話,就判斷單詞是否存在,存在就替換,不存在就新增
刪除方法
刪除方法相對于增加方法來說,會稍微麻煩一點,需要判斷是否還有子節點,針對子節點是否存在的情況進行相關處理
Trie總結
Trie的優點:搜索前綴的效率主要跟前綴的長度有關
Trie的缺點:需要消耗大量的內存,因此還有待改進(一個字符對應一個節點,二叉樹一個單詞對應一個節點,所以相對來說內存消耗大)