一文帶你認識隊列數據結構

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​​​​​​​​​​​​","attrs":{}},{"type":"link","attrs":{"href":"https://bbs.huaweicloud.com/blogs/272460?utm_source=infoq&utm_medium=bbs-ex&utm_campaign=other&utm_content=content","title":"","type":null},"content":[{"type":"text","text":"【本期推薦】8歲小朋友的兒童節,有點硬核,一起來認識這些小小程序員,看他們如何coding出一個與衆不同的童年。","attrs":{}}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/3a/3a12f861f931c59a2256b56e3efe83d3.jpeg?x-oss-process=image/resize,p_80/auto-orient,1","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"摘要:對於隊列來說數據結構相比棧複雜一些,但是也不是很難,搞懂先進先出然後用數組或者鏈表實現即可。","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文分享自華爲雲社區","attrs":{}},{"type":"link","attrs":{"href":"https://bbs.huaweicloud.com/blogs/272827?utm_source=infoq&utm_medium=bbs-ex&utm_campaign=other&utm_content=content","title":"","type":null},"content":[{"type":"text","text":"《手寫各種隊列,一文搞定》","attrs":{}}]},{"type":"text","text":",原文作者:bigsai  。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"前言","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"棧和隊列是一對好兄弟,棧的機制相對簡單,後入先出,就像進入一個狹小的山洞,山洞只有一個出入口,只能","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"後進先出(在外面的先出去,堵在裏面先進去的就有點倒黴)","attrs":{}},{"type":"text","text":"。而隊列就好比是一個隧道,後面的人跟着前面走,","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"前面人先出去(先入先出)","attrs":{}},{"type":"text","text":"。日常的排隊就是隊列運轉形式的一個描述!","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"棧是一種喜新厭舊的數據結構,來了新的就會處理新的把老的先停滯在這(我們找人、約人辦事最討厭這種人),隊列就是大公無私的一種數據結構,排隊先來先得,講究","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"順序","attrs":{}},{"type":"text","text":"性,所以這種數據結構在程序設計、中間件等都非常廣泛的應用,例如消息隊列、FIFO磁盤調度、二叉樹層序遍歷、BFS寬度優先搜索等等。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"隊列的核心理念就是:","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"先進先出!","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"隊列的概念","attrs":{}},{"type":"text","text":":隊列是一種特殊的線性表,特殊之處在於它只允許在表的前端(front)進行刪除操作,而在表的後端(rear)進行插入操作,和棧一樣,隊列是一種操作受限制的線性表。進行插入操作的端稱爲隊尾,進行刪除操作的端稱爲隊頭。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/c1/c198fa7143e6cb867fff5c7e8ce972bd.jpeg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"隊列介紹","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們設計隊列時候可以選擇一個標準,這裏就拿力扣622設計循環隊列作爲隊列設計的標準。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"隊頭front","attrs":{}},{"type":"text","text":":刪除數據的一端。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"隊尾rear","attrs":{}},{"type":"text","text":" :插入數據的一端。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"對於數組","attrs":{}},{"type":"text","text":",從數組後面插入更容易,數組前面插入較困難,所以一般用數組實現的隊列隊頭在數組前面,隊尾在數組後面;而對於","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"鏈表","attrs":{}},{"type":"text","text":",插入刪除在兩頭分別進行那麼頭部(前面)刪除尾部插入最方便的選擇。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/33/33d22a079641087bb722d1885399b96d.jpeg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​實現方法:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"MyCircularQueue(k): 構造器,設置隊列長度爲 k 。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Front: 從隊首獲取元素。如果隊列爲空,返回 -1 。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Rear: 獲取隊尾元素。如果隊列爲空,返回 -1 。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"enQueue(value): 向循環隊列插入一個元素。如果成功插入則返回真。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"deQueue(): 從循環隊列中刪除一個元素。如果成功刪除則返回真。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"isEmpty(): 檢查循環隊列是否爲空。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"isFull(): 檢查循環隊列是否已滿。","attrs":{}}]}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"普通隊列","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"按照上述的介紹,我們很容易知道數組實現的方式。用數組模擬表示隊列。要考慮初始化,插入,問題。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/87/870383888a6ca52adcb8576b391d05d5.jpeg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​在這個普通隊列一些操作需要注意的有:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"初始化","attrs":{}},{"type":"text","text":":數組的front和rear都指向0. (front和rear下標相等的時候說明隊列爲空)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"入隊","attrs":{}},{"type":"text","text":":隊不滿,數組不越界,先隊尾位置傳值,再隊尾下標+1(隊尾rear實際上超前一位,爲了區分空隊列情況)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"出隊","attrs":{}},{"type":"text","text":":隊不空,先取隊頭位置元素,在隊頭+1。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但是很容易發現","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"問題","attrs":{}},{"type":"text","text":",每個空間域只能利用一次,造成空間極度浪費,非常容易越界!","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/cf/cfbea9971ed7b602ef6ad397e0ba6b86.jpeg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"循環隊列(數組實現)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"針對上述的問題。有個較好的解決方法!就是對","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"已經申請","attrs":{}},{"type":"text","text":"的(數組)內存重複利用。這就是我們所說的循環隊列。循環隊列的一個好處是我們可以利用這個隊列之前用過的空間。在一個普通隊列裏,一旦一個隊列滿了,我們就不能插入下一個元素,即使在隊列前面仍有空間。但是使用循環隊列,我們能使用這些空間去存儲新的值。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"數組實現的循環隊列就是在","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"邏輯上","attrs":{}},{"type":"text","text":"作修改。因爲我們隊列中只需要front和rear兩個指針。rear在邏輯上在後面,front在邏輯上是在前面的,但實際上它們不一定誰在前誰在後,在計算距離的時候需要給rear先補上數組長度減去front,然後求餘即可。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/0f/0fe11f6b5afebf1b8403e29f843f4d84.jpeg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"初始化","attrs":{}},{"type":"text","text":":數組的front和rear都指向0. 這裏需要注意的是:front和rear位於同一個位置時候,證明隊列裏面是空的。還有在這裏我具體實現時候將數組申請大了一個位置空出來,防止隊列滿的情況又造成front和rear在同一個位置。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"入隊","attrs":{}},{"type":"text","text":":隊不滿,先隊尾位置傳值,再rear=(rear+ 1) % maxsize;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"出隊","attrs":{}},{"type":"text","text":":隊不空,先取隊頭位置元素,front=(front+ 1)% maxsize;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏出隊入隊指標相加如果遇到最後需要轉到頭位置,這裏直接+1求餘找到位置(相比判斷是否在最後更加簡潔),其中","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"maxsize","attrs":{}},{"type":"text","text":"是數組實際大小。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"是否爲空","attrs":{}},{"type":"text","text":":returnrear == front;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"大小","attrs":{}},{"type":"text","text":":return(rear+maxsize-front)%maxsize;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏很容易理解,一張圖就能解釋清楚,無論是front實際在前在後都能滿足要求。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/ff/ffb439a5af144dfe9a8b994d1ff725ae.jpeg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​這裏面有幾個大家需要注意的,就是指標相加如果遇到最後需要轉到頭的話。可以判斷是否到數組末尾位置。也可以直接+1求餘。其中","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"maxsize","attrs":{}},{"type":"text","text":"是數組實際大小。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"具體實現:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"public class MyCircularQueue {\n private int data[];// 數組容器\n private int front;// 頭\n private int rear;// 尾\n private int maxsize;// 最大長度\n public MyCircularQueue(int k) {\n data = new int[k+1];\n front = 0;\n rear = 0;\n maxsize = k+1;\n }\n\n public boolean enQueue(int value) {\n if (isFull())\n return false;\n else {\n data[rear] = value;\n rear=(rear + 1) % maxsize;\n }\n return true;\n }\n\n public boolean deQueue() {\n if (isEmpty())\n return false;\n else {\n front=(front+1)%maxsize;\n }\n return true;\n }\n\n public int Front() {\n if(isEmpty())\n return -1;\n return data[front];\n }\n\n public int Rear() {\n if(isEmpty())\n return -1;\n return data[(rear-1+maxsize)%maxsize];\n }\n\n public boolean isEmpty() {\n return rear == front;\n }\n\n public boolean isFull() {\n return (rear + 1) % maxsize == front;\n }\n}","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"循環隊列(鏈表實現)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於鏈表實現的隊列,要根據先進先出的規則考慮頭和尾的位置","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們知道隊列是先進先出的,對於鏈表,我們能採用單鏈表儘量採用單鏈表,能方便儘量方便,同時還要兼顧效率。使用鏈表大概有兩個實現方案:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"方案一","attrs":{}},{"type":"text","text":" 如果隊列頭設在鏈表尾,隊列尾設在鏈表頭。那麼","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"隊尾進隊插入","attrs":{}},{"type":"text","text":"在鏈表頭部插入沒問題,容易實現,但是如果","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"隊頭刪除","attrs":{}},{"type":"text","text":"在鏈表尾部進行,如果不設置尾指針要遍歷到隊尾,但是設置尾指針刪除需要將它前驅節點","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"需要雙向鏈表","attrs":{}},{"type":"text","text":",都挺麻煩的。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"方案二","attrs":{}},{"type":"text","text":"如果隊列頭設在鏈表頭,隊列尾設在鏈表尾,那麼","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"隊尾進隊插入","attrs":{}},{"type":"text","text":"在鏈表尾部插入沒問題(用尾指針可以直接指向next),容易實現,如果","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"隊頭刪除","attrs":{}},{"type":"text","text":"在鏈表頭部進行也很容易,就是我們前面常說的","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"頭節點刪除節點","attrs":{}},{"type":"text","text":"。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所以我們最終採取的是方案2的帶頭節點、帶尾指針的單鏈表!","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"主要操作爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"初始化","attrs":{}},{"type":"text","text":":設立一個頭結點,是front和rear都先指向它。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"入隊","attrs":{}},{"type":"text","text":":rear.next=va;rear=va;(va爲被插入節點)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/25/25432396a0f1724811556d3e0d08e941.jpeg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"出隊","attrs":{}},{"type":"text","text":":隊不空,front.next=front.next.next;經典帶頭節點刪除,但是如果僅有一個節點刪除時候,需要多加一個rear=front,不然rear就失聯啦。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/95/957dcdbec4339061da50668a6ff83edc.jpeg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"是否爲空","attrs":{}},{"type":"text","text":":returnrear == front;或者自定義維護len判斷returnlen==0","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"大小","attrs":{}},{"type":"text","text":":節點front遍歷到rear的個數,或者自定義維護len直接返回(這裏並沒實現)。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"實現代碼:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"public class MyCircularQueue{\n class node {\n int data;// 節點的結果\n node next;// 下一個連接的節點\n public node() {}\n public node(int data) {\n this.data = data;\n }\n }\n node front;//相當於head 帶頭節點的\n node rear;//相當於tail/end\n int maxsize;//最大長度\n int len=0;\n public MyCircularQueue(int k) {\n front=new node(0);\n rear=front;\n maxsize=k;\n len=0;\n }\n public boolean enQueue(int value) {\n if (isFull())\n return false;\n else {\n node va=new node(value);\n rear.next=va;\n rear=va;\n len++;\n }\n return true;\n }\n public boolean deQueue() {\n if (isEmpty())\n return false;\n else {\n front.next=front.next.next;\n len--;\n //注意 如果被刪完 需要將rear指向front\n if(len==0)\n rear=front;\n }\n return true;\n }\n\n public int Front() {\n if(isEmpty())\n return -1;\n return front.next.data;\n }\n\n public int Rear() {\n if(isEmpty())\n return -1;\n return rear.data;\n }\n\n public boolean isEmpty() {\n return len==0;\n //return rear == front;\n }\n\n public boolean isFull() {\n return len==maxsize;\n } \n}","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"雙向隊列(加餐)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"設計實現雙端隊列,其實你經常使用的ArrayDeque就是一個經典的雙向隊列,其基於數組實現,效率非常高。我們這裏實現的雙向隊列模板基於力扣641 設計循環雙端隊列 。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你的實現需要支持以下操作:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"MyCircularDeque(k):構造函數,雙端隊列的大小爲k。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"insertFront():將一個元素添加到雙端隊列頭部。 如果操作成功返回 true。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"insertLast():將一個元素添加到雙端隊列尾部。如果操作成功返回 true。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"deleteFront():從雙端隊列頭部刪除一個元素。 如果操作成功返回 true。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"deleteLast():從雙端隊列尾部刪除一個元素。如果操作成功返回 true。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"getFront():從雙端隊列頭部獲得一個元素。如果雙端隊列爲空,返回 -1。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"getRear():獲得雙端隊列的最後一個元素。 如果雙端隊列爲空,返回 -1。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"isEmpty():檢查雙端隊列是否爲空。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"isFull():檢查雙端隊列是否滿了。","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其實有了上面的基礎,實現一個雙端隊列非常容易,有很多操作和單端的循環隊列是一致的,只有多了一個","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"隊頭插入","attrs":{}},{"type":"text","text":"和","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"隊尾刪除","attrs":{}},{"type":"text","text":"的操作,兩個操作分別簡單的分析一下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"隊頭插入","attrs":{}},{"type":"text","text":":隊友front下標位置本身是有值的,所以要將front退後一位然後再賦值,不過要考慮是否爲滿或者數組越界情況。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"隊尾刪除","attrs":{}},{"type":"text","text":":只需要rear位置減1,同時也要考慮是否爲空和越界情況。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"具體實現代碼:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"public class MyCircularDeque {\n private int data[];// 數組容器\n private int front;// 頭\n private int rear;// 尾\n private int maxsize;// 最大長度\n /*初始化 最大大小爲k */\n public MyCircularDeque(int k) {\n data = new int[k+1];\n front = 0;\n rear = 0;\n maxsize = k+1;\n }\n\n /** 頭部插入 */\n public boolean insertFront(int value) {\n if(isFull())\n return false;\n else {\n front=(front+maxsize-1)%maxsize;\n data[front]=value;\n }\n return true;\n }\n\n /** 尾部插入 */\n public boolean insertLast(int value) {\n if(isFull())\n return false;\n else{\n data[rear]=value;\n rear=(rear+1)%maxsize;\n }\n return true;\n }\n\n /** 正常頭部刪除 */\n public boolean deleteFront() {\n if (isEmpty())\n return false;\n else {\n front=(front+1)%maxsize;\n }\n return true;\n }\n\n /** 尾部刪除 */\n public boolean deleteLast() {\n if(isEmpty())\n return false;\n else {\n rear=(rear+maxsize-1)%maxsize;\n }\n return true;\n }\n\n /** Get the front item */\n public int getFront() {\n if(isEmpty())\n return -1;\n return data[front];\n }\n\n /** Get the last item from the deque. */\n public int getRear() {\n if(isEmpty())\n return -1;\n return data[(rear-1+maxsize)%maxsize];\n }\n\n /** Checks whether the circular deque is empty or not. */\n public boolean isEmpty() {\n return front==rear;\n }\n\n /** Checks whether the circular deque is full or not. */\n public boolean isFull() {\n return (rear+1)%maxsize==front;\n }\n}","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"總結","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於隊列來說數據結構相比棧複雜一些,但是也不是很難,搞懂先進先出然後用數組或者鏈表實現即可。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於數組,隊尾tail指向的位置是空的,而鏈表的front(head一樣)爲頭指針爲空的,所以在不同結構實現相同效果的方法需要注意一下。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"數組實現的循環隊列能夠很大程度利用數組空間,而雙向隊列則是既能當隊列又能當棧的一種高效數據結構,掌握還是很有必要的。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://bbs.huaweicloud.com/blogs?utm_source=infoq&utm_medium=bbs-ex&utm_campaign=other&utm_content=content","title":"","type":null},"content":[{"type":"text","text":"點擊關注,第一時間瞭解華爲雲新鮮技術~","attrs":{}}]}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章