2018-2019-20172329 《Java軟件結構與數據結構》第三週學習總結

2018-2019-20172329 《Java軟件結構與數據結構》第三週學習總結

教材學習內容總結

《Java軟件結構與數據結構》第五章-隊列

一、概述

  • 1、隊列是什麼?

隊列是種線性集合,其元素從一端加入,從另一端刪除;注:隊列是按照先進先出的方式處理的。從隊列中刪除元素的次序,與放置元素的次序是一樣的。

  • 2、隊列的構成

(1)方法:

操作 描述
enqueue 向隊列末端添加一個元素
dequeue 從隊列前段刪除一個元素
first 考察隊列前端的那個元素
isempty 判定隊列是否爲空
size 確定隊列的元素數目

(2)過程

  • 3、其他內容

(1)隊列是一種可存儲重複編碼密鑰的便利集合。

(2)通常用表示排隊的隊列來實現模擬。

二、用鏈表實現隊列

  • 1、概述

(1)那兩個分別指向鏈表首元素、鏈表末元素的引用方便隊列的鏈表實現。

(2)爲了從鏈表的末端出列,必須把一個臨時變量設置爲指向鏈表末端的元素。

  • 2、鏈表實現的過程圖
  • 3、enqueue操作

(1)enqueue操作要求將新元素放到鏈表末端。

(2)注:新結點的next引用無需顯示的進行設置。

  • 4、dequeue操作

(1)enqueue和dequeue操作作用於隊列的對立端。

三、用數組實現隊列

  • 1、概述

(1)由於隊列操作會修改集合的兩端,因此將一端固定於索引0處要求移動元素。

(2)非環形數組實現的元素移位,將產生O(n)的複雜度。

(3)把數組看成環形的,可以出去在隊列的數組實現中把元素移位的需要。

  • 2、環形數組

(1)概述:簡單來講就是如果數組的最後一個索引後面跟的是第一個索引,就可用作環形數組。

(2)注:當添加和刪除元素時,不需要移動哪個元素,但是一定要小心維護front和rear的值。

教材學習中的問題和解決過程

  • 問題1:在用鏈表實現隊列的時候,我們所需要的有兩個front結點和rear的結點,但是他們是否實際存在,或者另一種表達就是是否可以給其賦值?
  • 問題1解決過程:

(1)首先,對於只有一端的隊列而言,符合的應當是先進先出的原則,所以最先進入的就應當是最先出去的元素,在進入多個元素以後,這一個先進入的元素就會變成一個隊列的隊尾,所以在書中有這樣一句話:

“爲了從鏈表的末端出列,必須把一個臨時變量設置爲指向鏈表末端的元素,然後把tail指針設置爲指向當前末端之前的結點。”

所以對於隊尾來講,有這樣一個rear的結點進行“管理”,防止元素丟失。
(2)而對於首來講,更是重要,它需要去確定每一個元素的位置,防止整個隊列元素的丟失。所以下圖的展示很能夠體現隊列的這樣一種不同於鏈表的結構。

簡單表達就是頭結點其實相當於隊列第一個元素所在結點的前一個結點,通過其來確定整個隊列內部元素的位置

  • 問題2:對於循環數組整個流程到底是如何進行的?
  • 問題2解決方案:(該解決方法爲搬運,來源已在參考資料中顯示,參考原文請到參考文獻查看)
  • 在學習了循環數組以及循環隊列以後,我發現其原理很相似,所以進行圖示,方便理解;

(1)在我們數組的實現方式中,用兩個int型變量用於記錄隊頭和隊尾的索引。

圖一:

(2)一個隊列的初始狀態,head和tail都指向初始位置(索引爲0處)。head永遠指向該隊列的隊頭元素,tail則指向該隊列最後一個元素的下一位置,當有入隊操作時:

圖2:

圖3:

(3)當有出隊操作時:

圖4:

(4)當遇到出隊操作時,head會移向下一元素位置。當然,對於這種方式入隊和出隊,隊空的判斷條件顯然是head=tail,隊滿的判斷條件是tail=array.length(數組最後一個位置的下一位置)。顯然,這種結構最致命的缺陷就是,tail只知道向後移動,一旦到達數組邊界就認爲隊滿,但是隊列可能時刻在出隊,也就是前面元素都出隊了,tail也不知道。例如:

圖5:

(5)此時tail判斷隊滿,我們暫時認爲資源利用是可以接受的,但是如果接下來不斷髮生出隊操作:

圖6:

(6)此時tail依然通過判斷,認爲隊滿,不能入隊,這時數組的利用率我們是不能接受的,這樣浪費很大。所以,我們引入循環隊列,tail可以通過mode數組的長度實現迴歸初始位置,下面我們具體來看一下。

按照我們的想法,一旦tail到達數組邊界,那麼可以通過與數組長度取模返回初始位置,這種情況下判斷隊滿的條件爲tail=head

圖7:

(7)此時tail的值爲8,取模數組長度8得到0,發現head=tail,此時認爲隊列滿員。這是合理的,但是我們忽略了一個重要的點,判斷隊空的條件也是head=tail,那麼該怎麼區分是隊空還是隊滿呢?解決辦法是,空出隊列中一個位置,如果(tail+1)%array.length=head,我們就認爲隊滿,下面說明其合理性。

上面遇到的問題是,tail指向了隊尾的後一個位置,也就是新元素將要被插入的位置,如果該位置和head相等了,那麼必然說明當前狀態已經不能容納一個元素入隊(間接的說明隊滿)。因爲這種情況是和隊空的判斷條件是一樣的,所以我們選擇捨棄一個節點位置,tail指向下一個元素的位置,我們使用tail+1判斷下一個元素插入之後,是否還能再加入一個元素,如果不能了說明隊列滿,不能容納當前元素入隊(其實還剩下一個空位置),看圖:

圖8:

(8)tail通過取模,迴歸到初始位置,我們判斷tail+1是否等於head,如果等於說明隊滿,不允許入隊操作,當然這是犧牲了一個節點位置來實現和判斷隊空的條件進行區分。上述文字基本完成了隊循環隊列的理論介紹,下面我們看在Java中對該數據結構的具體實現是怎樣的。

代碼調試中的問題和解決過程

  • 問題1:最近在編寫代碼的過程中,感覺遇到的最多的就是空指針這個異常,如下圖,我在這裏分享一些我一般而言解決這一系列問題的一些技巧。

  • 問題1解決方案:

(1)首先,在下面的地方可以看見出錯的地方在哪裏,因爲爲什麼會出現空指針呢,就是因爲我們想要索引的地方就是一個null,所以肯定就會出現異常,因此呢,就一般而言我就再找一個新指針,作爲一個測試指針,找到出錯在哪一步。(這裏肯定會有人說爲什麼不用bug,因爲我覺得這個找錯也是一種方法,但是就我個人而言,我覺得bug一點一點的又點慢,所以就找了新方法)

(2)然後我一般而言會在循環裏找問題,因爲有時候就是因爲多移了一步可能就導致了這一個問題,所以我們可以給他減或加一次循環進行查看,結果是否可以成功輸出。

上週考試錯題總結

由於上週沒有進行測試,所以沒有錯題總結

代碼鏈接

結對及互評

  • 本週結對學習情況
  • 博客中值得學習的或問題:
    • 內容詳略得當;
    • 代碼調試環節比較詳細;
  • 基於評分標準,我給本博客打分:5分。得分情況如下:
  1. 正確使用Markdown語法(加1分):
  2. 模板中的要素齊全(加1分)
  3. 教材學習中的問題和解決過程, 一個問題加1分
  4. 代碼調試中的問題和解決過程, 一個問題加1分

  • 博客中值得學習的或問題:
    • 內容詳略得當;
    • 代碼調試環節比較詳細;
  • 基於評分標準,我給本博客打分:9分。得分情況如下:
  1. 正確使用Markdown語法(加1分):
  2. 模板中的要素齊全(加1分)
  3. 教材學習中的問題和解決過程, 一個問題加1分
  4. 代碼調試中的問題和解決過程, 一個問題加1分

感悟

我覺得這個中秋節過的非常充實,希望自己自己儘快再找到更好的狀態去面對新的學期,讓自己可以學到更多知識,可以讓自己在這學期可以有更多的收穫。

學習進度條

代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積)
目標 5000行 30篇 400小時
第一週 0/0 1/1 6/6
第二週 1313/1313 1/2 20/26
第三週 901/2214 1/3 20/46

補充作業

技能 課前評估 課後評估
對編程整體的理解 2 6
架構設計、模塊化設計、接口設計 2 6
效能分析及改進 2 6
處理大數據 1 6
處理命令行參數和文件系統 1 6
自主學習的能力 5 7

參考資料

藍墨雲班課
Java程序設計
深入理解循環隊列----循環數組實現ArrayDeque

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章