算法數據結構 06】先進先出的隊列 —— 順序隊列 || 循環隊列 || 鏈式隊列 大盤點

      網友投稿 1717 2025-03-31

      寫在前面:大家好!我是【AI 菌】,一枚愛彈吉他的程序員。我熱愛AI、熱愛分享、熱愛開源! 這博客是我對學習的一點總結與思考。如果您也對 深度學習、機器視覺、算法、C++、Python 感興趣,可以關注我的動態,我們一起學習,一起進步~

      我的博客地址為:【AI 菌】的博客

      上一篇:【算法與數據結構 05】“霸道“ 的棧——先進后出

      在上一篇中,我們學習了后進先出的數據結構——棧,與之對應的是一種先進先出的數據結構——隊列。今天,我們就一起來學習隊列,掌握順序隊列、循環隊列和鏈式隊列中數據的基本操作。

      文章目錄

      1. 什么是隊列

      2. 順序隊列中的數據操作

      (1)增操作

      (2)刪操作

      (3)越界問題

      3. 循環隊列的數據操作

      4. 鏈式隊列的數據操作

      (1)增操作

      (2)刪操作

      (3)查操作

      1. 什么是隊列

      簡單來說,隊列就是一個FIFO(先進先出)的系統。元素只能從隊尾插入,且最先插入的元素最先被刪除。

      就如同在食堂排隊就餐,先進入隊伍的人先取到餐,且從隊首離開,即先進先出;而所有人只能從隊尾加入隊列,從隊首離開,即元素只能從隊尾插入,隊首刪除。

      相信說到這里,大家對隊列已經有了一個基本的了解!那么,下面我們更深一步挖掘~

      從本質上來說,隊列也是一種特殊的線性表,與線性表的不同之處體現在對數據的增刪操作上。

      隊列的特點是先進先出:

      先進,表示隊列的數據新增操作只能在末端進行,不允許在隊列的中間某個結點后新增數據;

      先出,隊列的數據刪除操作只能在始端進行,不允許在隊列的中間某個結點后刪除數據。

      也就是說,隊列的增和刪的操作只能分別在這個隊列的隊尾和隊頭進行。

      除此之外,與線性表、棧一樣,隊列也存在這兩種存儲方式,即順序隊列和鏈式隊列:

      順序隊列,依賴數組來實現,其中的數據在內存中也是順序存儲。

      鏈式隊列,則依賴鏈表來實現,其中的數據依賴每個結點的指針互聯,在內存中并不是順序存儲。鏈式隊列,實際上就是只能尾進頭出的線性表的單鏈表。

      對單鏈表、鏈式結構還不了解的同學,墻裂建議先看看這篇文章:【算法與數據結構 04】多圖講解——線性表、順序表、鏈表

      在學習隊列的增刪查操作之前,我們需要簡單了解一下隊列中指針與節點的關系,下面以鏈式隊列為例:

      如下圖所示,一般情況,我們將隊頭指針front指向鏈式隊列的頭結點,隊尾指針rear指向終端結點。

      當隊列為空時,front 和 rear 必須都指向頭結點,如下圖所示:

      實際上,不管是哪種實現方式,一個隊列都依賴隊頭(front)和隊尾(rear)兩個指針進行唯一確定。

      理解了這個之后,我們正式進入:隊列對于數據的增刪查處理!

      2. 順序隊列中的數據操作

      隊列從隊頭(front)刪除元素,從隊尾(rear)插入元素

      。前面已經談到過鏈式列表;那么,對于一個順序隊列的數組來說,也會設置一個 front 指針來指向隊頭,并設置另一個 rear 指針指向隊尾。當我們不斷進行插入刪除操作時,頭尾兩個指針都會不斷向后移動。

      (1)增操作

      下面以順序鏈表為例,為了實現一個有 k 個元素的順序存儲的隊列,我們需要建立一個長度比 k 大的數組,以便把所有的隊列元素存儲在數組中。

      隊列新增數據的操作,就是利用 rear 指針在隊尾新增一個數據元素

      。過程如下圖所示:

      因為這個過程不會影響其他數據,所以時間復雜度為 O(1)。

      (2)刪操作

      隊列刪除數據的操作與棧不同。隊列元素出口在隊列頭部,即下標為 0 的位置。當利用 front 指針刪除一個數據時,隊列中剩余的元素都需要向前移動一個位置,以保證隊列頭部下標為 0 的位置不為空,過程如下圖所示:

      因為剩余的元素都需要向前移動一個位置,此時時間復雜度就變成 O(n) 。

      我們看到,front 指針刪除數據的操作引發了時間復雜度過高的問題,那么我們該如何解決呢?

      (3)越界問題

      我們可以通過移動指針的方式來刪除數據,這樣就不需要移動剩余的數據了。但是,這樣的操作,也可能會產生數組越界的問題。接下來,我們來詳細討論一下。

      首先,我們來看一個例子:利用順序隊列,持續新增數據和刪除數據

      1)初始時,定義了長度為 5 的數組,front 指針和 rear 指針相等,且都指向下標為 0 的位置,隊列為空隊列。

      2)當 A、B、C、D 四條數據加入隊列后,front 依然指向下標為 0 的位置,而 rear 則指向下標為 4 的位置。過程如下圖所示:

      3)當 A 出隊列時,front 指針指向下標為 1 的位置,rear 保持不變。其后 E 加入隊列,front 保持不變,rear 則移動到了數組以外,如下圖所示:

      假設這個列隊的總個數不超過 5 個,但是目前繼續接著入隊,因為數組末尾元素已經被占用,再向后加,就會產生我們前面提到的數組越界問題。而實際上,我們列隊的下標 0 的地方還是空閑的,這就產生了一種 “假溢出” 的現象。

      這種問題在采用順序存儲的隊列時,是一定要小心注意的。兩個簡單粗暴的解決方法就是:

      不惜消耗 O(n) 的時間復雜度去移動數據;

      或者開辟足夠大的內存空間確保數組不會越界。

      3. 循環隊列的數據操作

      顯然,上面的兩個方法都不太友好。其實,數組越界問題可以通過隊列的一個特殊變種來解決,叫作循環隊列。

      循環隊列進行新增數據元素操作時,首先判斷隊列是否為滿。如果不滿,則可以將新元素賦值給隊尾,然后讓 rear 指針向后移動一個位置。如果已經排到隊列最后的位置,則 rear指針重新指向頭部。

      循環隊列進行刪除操作時,首先判斷隊列是否為空,然后將隊頭元素賦值給返回值,front 指針向后移一個位置。如果已經排到隊列最后的位置,就把 front 指針重新指向到頭部。這個過程就好像鐘表的指針轉到了表盤的尾部 12 點的位置后,又重新回到了表盤頭部 1 點鐘的位置。這樣就能在不開辟大量存儲空間的前提下,不采用 O(n) 的操作,也能通過移動數據來完成頻繁的新增和刪除數據。

      好啦,我們繼續回到前面提到的例子中。對于一般的隊列,末尾元素已經被占用,再向后加,就會產生我們前面提到的越界問題。

      當我們使用循環隊列時,rear 指針就可以重新指向下標為 0 的位置,如下圖所示:

      如果這時再新增了 F 進入隊列,就可以放入在下標為 0 的位置,rear 指針指向下標為 1 的位置。這時的 rear 和 front 指針就會重合,指向下標為 1 的位置,如下圖所示:

      此時,又會產生新的問題,即當隊列為空時,有 front 指針和 rear 指針相等。而現在的隊列是滿的,同樣有 front 指針和 rear 指針相等。那么怎樣判斷隊列到底是空還是滿呢?常用的方法是,設置一個標志變量 flag 來區別隊列是空還是滿。

      4. 鏈式隊列的數據操作

      我們再看一下鏈式隊列的數據操作。鏈式隊列就是一個單鏈表,同時增加了 front 指針和 rear 指針。鏈式隊列和單鏈表一樣,通常會增加一個頭結點,并讓 front 指針指向頭結點。頭結點不存儲數據,只是用來輔助標識。

      (1)增操作

      鏈式隊列進行新增數據操作時,比如要新增數據X,要將擁有數值 X 的新結點 s 賦值給原隊尾結點的后繼,即 rear.next。然后把當前的 s 設置為隊尾結點,指針 rear 指向 s。如下圖所示:

      (2)刪操作

      當鏈式隊列進行刪除數據操作時,實際刪除的是頭結點的后繼結點。這是因為頭結點僅僅用來標識隊列,并不存儲數據。因此,出隊列的操作,就需要找到頭結點的后繼,這就是要刪除的結點。接著,讓頭結點指向要刪除結點的后繼。過程如下圖所示:

      需要注意的是:如果這個鏈表除去頭結點外只剩一個元素,那么刪除僅剩的一個元素后,rear 指針就變成野指針了。這時候,需要讓 rear 指針指向頭結點。也許你前面會對頭結點存在的意義產生懷疑,似乎沒有它也不影響增刪的操作。那么為何隊列還特被強調要有頭結點呢?

      這主要是為了防止刪除最后一個有效數據結點后, front 指針和 rear 指針變成野指針,導致隊列沒有意義了。有了頭結點后,哪怕隊列為空,頭結點依然存在,能讓 front 指針和 rear 指針依然有意義。

      (3)查操作

      對于隊列的查找操作,不管是順序還是鏈式,隊列都沒有額外的改變。跟線性表一樣,它也需要遍歷整個隊列來完成基于某些條件的數值查找。因此時間復雜度也是 O(n)。

      【算法與數據結構 06】先進先出的隊列 —— 順序隊列 || 循環隊列 || 鏈式隊列 大盤點

      相關文章推薦

      【C++養成計劃】隊列 —— 快速上手STL queue類(Day13)

      【算法與數據結構 04】多圖講解——線性表、順序表、鏈表

      【算法與數據結構 05】“霸道“ 的棧——先進后出

      AI 數據結構

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:WPS輕松辦公—如何不覆蓋數據隨意調換表格行列(wps更換行列)
      下一篇:我的WPS怎么每次保存都都會出現一個副本怎么回事呢?(每保存一次,桌面就會出現一個wps表格)
      相關文章
      亚洲熟女综合一区二区三区| 亚洲日韩精品一区二区三区无码| 久久九九亚洲精品| 爱爱帝国亚洲一区二区三区| 亚洲日韩一区二区一无码| 亚洲中文字幕无码一去台湾| 亚洲H在线播放在线观看H| 亚洲六月丁香六月婷婷色伊人 | 亚洲日本在线观看视频| 亚洲国产精品碰碰| 亚洲人成影院在线观看| 亚洲综合色视频在线观看| 亚洲人午夜射精精品日韩| 在线A亚洲老鸭窝天堂| 一本色道久久综合亚洲精品| 亚洲人成人77777网站| 亚洲V无码一区二区三区四区观看| 国产亚洲婷婷香蕉久久精品| 亚洲va久久久噜噜噜久久男同| 亚洲AV午夜成人片| 亚洲专区先锋影音| 亚洲欧洲日产国码在线观看| 亚洲乱人伦精品图片| 亚洲性无码AV中文字幕| 国产精品国产亚洲区艳妇糸列短篇| 狠狠入ady亚洲精品| 在线日韩日本国产亚洲| 人人狠狠综合久久亚洲88| 亚洲国产高清视频| 亚洲精品视频免费看| 久久久久精品国产亚洲AV无码| 亚洲kkk4444在线观看| 亚洲精品无码你懂的| 亚洲成人高清在线| 亚洲午夜久久久影院伊人 | 亚洲精品伦理熟女国产一区二区| 日本系列1页亚洲系列| 国产亚洲av片在线观看18女人| 亚洲Av永久无码精品三区在线 | 亚洲综合成人网在线观看| 亚洲偷自精品三十六区|