20172328 2018-2019《Java軟件結構與數據結構》第八周學習總結

20172328 2018-2019《Java軟件結構與數據結構》第八周學習總結

概述 Generalization

本周學習了二叉樹的另一種有序擴展?是什么呢?你猜對了!ヾ(?°?°?)ノ゙就是堆。本章將講解堆的鏈表實現and數組實現,以及往堆中添加元素或從堆中刪除元素的算法;還將介紹對的一些用途,包括基本使用和優先隊列。

教材學習內容總結 A summary of textbook

  • (heap)就是具有兩個附加屬性的一顆二叉樹:
    • 第一點:它是一顆完全二叉樹 ,即葉子節點都在最后一層靠左側。
    • 第二點:對每一結點,它小于(大于)或等于其左孩子和右孩子。
  • 第二點中滿足大于的條件下形成的是一個最大堆(大頂堆),反之則為最小堆(小頂堆)
  • 最小堆將其最小元素存儲在該二叉樹的根處,且其跟的兩個孩子同樣還是最小堆。
  • 堆中的操作:
    1332971-20181110153342605-1476200578.png

  • addElement操作
    • addElement方法將給定的Comparable元素添加到堆的恰當位置處,且維持該堆的完全性屬性和有序屬性。

      • Little Tip:完全樹你還記得嗎?完全二叉樹就是所有葉子都位于h或者h-1層,其中h為log2(n),且n為樹中的元素數目,h層的所有葉子都位于該樹的左邊,那么該樹被認為是完全的。
    • 堆就是一棵完全的二叉樹,所以對于插入的新結點只存在一個正確的位置。要么是h層左邊的下一個空位置,要么是h+1層左邊的第一個位置(如果h層為滿的話)。
    • 將新結點定位到正確的位置后,我們就必須對這個堆進行排序來保持其有序屬性。方法就是對樹中的最末一片葉子進行跟蹤記錄,在一個addElement方法后,最末結點就被設定為插入結點。也就是通過上溯樹來保證樹的有序性.
  • removeMin操作
    • removeMin方法將刪除最小堆中的最小元素并返回它,由于最小元素是存儲在最小堆的根處,所以我們需要返回儲存在根處的元素并用堆中的另一元素替換它。
    • 要維持該樹的完全性,就是把儲存在樹中最末一片葉子上的元素用來替換根元素。
    • 將存儲在最末一片葉子上的元素移動到根處,就必須對該堆進行重新排序來維持該堆的排序屬性。
    • 要維持該堆的排序屬性,就要從根結點下溯樹。具體過程是將該新根元素與其較小的孩子進行比較,且如果孩子更小就將它們互換,沿著樹向下繼續這一過程,直至該元素要么位于某一葉子中,要么比它的兩個孩子都小。
  • findMin操作
    • findMin將返回一個指向最小堆中最小元素的引用,由于最小堆的最小元素就在根處,所以直接返回存儲在根處的元素即可。
  • 使用堆——堆排序heapSort
    • 堆排序是對簡單選擇排序的一種改進。
    • 改進著眼點:如何減少關鍵字的比較次數
      • 簡單選擇排序在一趟排序中僅選出最小關鍵字,但是沒有把一趟比較結果保存下來,因而比較次數較多。
      • 堆排序在選出最小關鍵字同時,也找出較小的關鍵字,從而減少了后面選擇中的比較次數,提高了整個排序效率。
  • 左右子樹都是大頂堆,如何調整根結點,使得整棵樹成為一個堆?
    1332971-20181110153429106-440613040.png
  • 堆調整 —— 篩選過程
    • 調整過程中,總是將根結點(被調整結點)與左右孩子比較;
    • 不滿足堆條件時,將根結點與左右孩子中較大者交換;
    • 這個調整過程一直進行到所有子樹都是堆或者交換到葉子為止。
    • 這個從堆頂到葉子的調整過程稱為“篩選”。
  • 對堆進行篩選完畢之后我們就要為保持其有序性而開始排序。
  • 堆排序-排序過程
    1332971-20181110153455796-969315280.png
    1332971-20181110153503796-181301810.png
    1332971-20181110153511397-646248335.png
    • 從無序序列的第[n/2]個元素開始(對應于完全二叉樹的最后一個非終端結點)進行篩選;
    • 當解決一個非終端結點(非葉子結點)的有序問題后,把此非終端結點看做一個葉子,然后繼續上溯,找到倒數第二個非終端結點,繼續進行有序替換,知道整個堆有序為止。
  • heapSort的復雜度為O(nlogn)
  • 使用堆:優先級隊列
  • 優先級隊列(Priority queue)就是遵循兩個排序規則的集合。
    • 首先,具有更高優先級的項目在先。
    • 其次,具有相同優先級的項目使用先進先出方法來確定其排序。

      • Little Tip:雖然最小堆根本就不是一個隊列,但是它卻提供了一個高效的優先級隊列實現。
  • 用鏈表實現堆
    • 因為我們要求在插入元素后能夠向上遍歷該樹,所以堆中的結點必須存儲在指向其雙親的指針。所以我們從創建一個HeapNode類開始我們的鏈表實現,該類對BinaryTreeNode進行了拓展并添加了一個雙親指針。
    • 鏈表實現的實例數據由指向HeapNode且稱為lastNode的單個引用組成,這樣我們就能夠跟蹤記錄該堆中最末一片葉子。public HeapNode lastNode;
    • addElement操作:
      • 在恰當的位置添加一個新元素
      • 對堆進行重排序以維持其排序屬性
      • 將lastNode指針重新設定指向新的最末結點
    • removeMin操作:
      • 用存儲在最末結點處的元素替換存儲在根處的元素
      • 對堆進行重排序
      • 返回原始的根元素
    • findMin操作:
      • 該方法僅僅返回一個指向存儲在堆根處元素的引用,因此復雜度為O(1)。
  • 用數組實現堆
    • 用數組實現堆不再需要創建一個HeapNode類對,而是通過用數組來保存堆中的數據。
    • 在二叉樹的數組實現中,樹的根位于位置0處,對于每一結點n,n的左孩子將位于數組的2n+1處,右孩子將位于數組的2n+2處。
    • addElement操作:
      • 在恰當的位置添加一個新元素
      • 對堆進行重排序以維持其排序屬性
      • 將count遞增1.
    • removeMin操作:
      • 用存儲在最末結點處的元素替換存儲在根處的元素
      • 對堆進行重排序
      • 返回原始的根元素
    • findMin操作:
      • 返回指向存儲在堆的根處或數組0位置處的元素。
  • 總結:鏈表實現和數組實現的addElement方法和removeElement方法時間復雜度都是O(logn)。但是,數組的實現還是更高效一些,因為在addElement操作中數組實現不用去確定插入雙親的結點,在removeElement操作中數組實現不需要確定新的最末一片葉子。

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

  • 問題1:周四晚上看用鏈表實現堆的添加操作代碼。剛剛看懂小伙伴仇夏來找我討論,討論了一會瞬間覺得自己沒有真正看懂,那段奇妙的代碼如下:
private HeapNode<T> getNextParentAdd(){HeapNode<T> result = lastNode;while ((result != root) && (result.getParent().getLeft() != result))result = result.getParent();if (result != root)if (result.getParent().getRight() == null)result = result.getParent();else{result = (HeapNode<T>)result.getParent().getRight();while (result.getLeft() != null)result = (HeapNode<T>)result.getLeft();}elsewhile (result.getLeft() != null)result = (HeapNode<T>)result.getLeft();return result;}

這段代碼是返回將要插入結點的雙親結點的方法,當時我和仇夏討論的是有兩種情況。因為我們知道插入操作為了保證樹的完全性,所以要在h層的從左開始數的第一個空結點插入或者在h+1層的最左邊插入(如果樹是滿的話),但是在循環體中不滿足我們的要求。

  • 問題1的解決:
  • 問題的重點是“下一個將要插入結點的雙親結點”,之前一直理解的是新插入結點的雙親結點,所以當然不對。在理解正確之后,畫出幾種插入的可能情況,再跟著上述代碼理解幾遍,就慢慢清晰明朗了。
    1332971-20181110153639776-14310583.jpg

  • 問題2:之前在學習棧的時候感覺一直在和堆一起被提起,所以堆和棧之間到底是什么關系?
  • 問題2的解決:
  • 簡單的說: Java把內存劃分成兩種:一種是棧內存,一種是堆內存。
  • 在函數中定義的一些基本類型的變量和對象的引用變量都在函數的棧內存中分配。 當在一段代碼塊定義一個變量時,Java就在棧中為這個變量分配內存空間,當超過變量的作用域后,Java會自動釋放掉為該變量所分配的內存空間,該內存空間可以立即被另作他用。
  • 堆內存用來存放由new創建的對象和數組。在堆中分配的內存,由Java虛擬機的自動垃圾回收器來管理。
  • 堆和棧的區別比較:
    • 1.棧(stack)與堆(heap)都是Java用來在Ram中存放數據的地方。與C++不同,Java自動管理棧和堆,程序員不能直接地設置棧或堆。
    • 2.棧的優勢是,存取速度比堆要快,僅次于直接位于CPU中的寄存器。但缺點是,存在棧中的數據大小與生存期必須是確定的,缺乏靈活性。另外,棧數據可以共享,詳見第3點。堆的優勢是可以動態地分配內存大小,生存期也不必事先告訴編譯器,Java的垃圾收集器會自動收走這些不再使用的數據。但缺點是,由于要在運行時動態分配內存,存取速度較慢。
    • 3.Java中的數據類型有兩種。 一種是基本類型(primitive types), 共有8種,即int, short, long, byte, float, double, boolean, char(注意,并沒有string的基本類型)。這種類型的定義是通過諸如int a = 3; long b = 255L;的形式來定義的,稱為自動變量。值得注意的是,自動變量存的是字面值,不是類的實例,即不是類的引用,這里并沒有類的存在。如int a = 3; 這里的a是一個指向int類型的引用,指向3這個字面值。這些字面值的數據,由于大小可知,生存期可知(這些字面值固定定義在某個程序塊里面,程序塊退出后,字段值就消失了),出于追求速度的原因,就存在于棧中。

代碼實現時的問題作答 Exercise

  • 問題1:用堆實現隊列?樹中給的堆是由數組和鏈表實現的,那么我們應該用ArrayHeap還是Linkedheap實現呢?又該如何實現?
  • 問題1的解決:首先,我們知道在第十章中隊列的實現可以由鏈表或者循環數組實現,并且堆可以由鏈表和數組實現,因此是否可以推出隊列可以由數組實現的堆或者鏈表實現的堆來實現呢?
  • 首先,我先用鏈表實現的堆來實現隊列。通過在enqueue方法中調用addElement方法,就能夠實現隊列的入隊,但是在入隊后進行了堆的插入中的排序?隊列是符合先進先出原則的,那么我就修改了堆中的插入方法,將其中的排序刪掉。同理,當出隊時也不應該去考慮排序的問題。但是當我刪除掉刪除的排序后,再執行刪除隊列中前兩個元素,我卻發現刪除的并不一定是隊列的前兩個值,反而刪除掉了最開始跟的值和最末一個葉子,這是由堆的性質決定的。所以想要保持先進先出,我們就要找到堆頂的左孩子然后刪除。所以我們需要改變一下堆中的排序方法。鏈表的實現方法很麻煩,而且要改變刪除的排序算法需要考慮很多種情況,在做了兩小時還是不能完整正確的情況下,讓我們把目光投向數組。
    1332971-20181110153709226-1861657092.png

  • 數組中只需要將刪除后的最末結點變成null就可以達到效果。
    1332971-20181110153722436-1884810174.png

上周測試活動錯題改正 Correction

  • 1.In removing an element from a binary search tree, another node must be ___________ to replace the node being removed.
    A .duplicated
    B .demoted
    C .promoted
    D .None of the above
  • 正確答案選 B。當在二叉查找樹上刪除一個結點時,后面的結點需要向上移動來補全。當時,以為越靠近根結點說明深度越低,所以是降級了;但是看完答案好像人家的意思是向上補全。題意理解不準確哈哈
  • 2.In removing an element from a binary search tree, another node must be demoted to replace the node being removed.
    A .True
    B .Flase
  • 正確答案選 A ,和第一題一模一樣好嗎?哭
  • 3.One of the uses of trees is to provide simpler implementations of other collections.
    A .True
    B .Flase
  • 正確答案選 B 。這道題確實是我自己不太懂的。通過搜索得知,java中樹的應用主要有:菜單樹,還有權限樹,商品分類列表也是樹結構。在這幾章的學習中,好像確實沒有通過樹來簡單實現其他集合,樹提供的方便性可以用于查找、排序等等。
  • 4.Insertion sort is an algorithm that sorts a list of values by repetitively putting a particular value into its final, sorted, position.
    A .true
    B .false
  • 正確答案選 B ,我當時選了A。我覺得還是題意理解的問題。我理解的題意是“插入排序是一種重復的將特殊值插入后面,然后排序,然后安置的算法”我覺得插入排序就是這樣一個流程,所以我也不知道出現了什么問題。

碼云鏈接

代碼量(截圖)

1332971-20181110153751722-1556700772.png

結對及互評Group Estimate

  • 點擊進入結對小伙伴20172301郭愷的博客
  • 點擊進入結對小伙伴20172304段志軒的博客

點評模板:

  • 博客中值得學習的或問題:
    • 20172301:這周的實驗四完全沒有思路,是最后看了郭愷同學的作業勉強理解了然后寫的。所以說,佩服佩服。對鏈表堆和數組堆的優缺點分析的很透徹。
    • 20172304:圖很多,但是排版有點混亂,不是特別美觀可以繼續改進。內容還是有點少,沒有上周博客好喲!一起繼續加油!

其他(感悟、思考等,可選)Else

Crossing miles of frustrations and rivers a raging,picking up stones I found along the way.

怕不輕松,怕太輕松。
再也不用覺得工作日長,因為每天好像都是工作日。想忙里偷閑就忙里偷閑,想抓緊做事就抓緊做事。

我將每天告訴自己:請對專業課程更加虔誠一點。

學習進度條Learning List

代碼行數(新增/累積)博客量(新增/累積)學習時間(新增/累積)
目標5000行30篇400小時
第一周0/01/18/8
第二周621/6211/212/20
第三周678/12991/310/30
第四周2734/40331/420/50
第五周1100/51331/520/70
第六周1574/67072/715/85
第七周1803/85101/820/105
第八周2855/113652/1025/130

參考資料Reference

  • [Java軟件結構與數據結構](第四版)
  • 堆這種數據結構
  • 讓你徹底明白JAVA中堆與棧的區別
  • java數據結構:基于樹的堆

轉載于:https://www.cnblogs.com/LXY462283007/p/9939573.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/250272.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/250272.shtml
英文地址,請注明出處:http://en.pswp.cn/news/250272.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

javascript --- 函數的柯里化 Vue 2.x中柯里化的使用

函數式編程部分重點 參考資料: 函數式編程 柯里化 只傳遞給函數一部分參數來調用它,讓它返回一個函數去處理剩下的參數 var add function (x) {return function(y) {return x y} }var increment add(1) var addTen add(10)increment(2) // 3addTen(10) // 12判斷元素:V…

MYSQL重置ROOT密碼

背景 mysql 服務器長時間未使用&#xff0c;管理員當時設置的root 密碼忘記&#xff0c;需要重置 root 密碼&#xff0c;并加以妥善保存。 步驟 關閉 mysql 服務以跳過密碼驗證的方式啟動 mysql 服務mysqld --skip-grant-tables本地登陸后設置新的root 密碼 update mysql.user …

javascript --- Vue初始化 模板渲染

不帶響應式的Vue縮減實現 模板 現有模板如下: <div id "app"><div class"c1"><div titlett1 id"id">{{ name }}</div><div titlett2 >{{age}}</div><div>hello3</div></div><ul>…

#RANK_1 極其簡單的遞歸——騎士與金幣

2000:金幣 總時間限制: 1000ms內存限制: 65536kB描述國王將金幣作為工資&#xff0c;發放給忠誠的騎士。第一天&#xff0c;騎士收到一枚金幣&#xff1b;之后兩天&#xff08;第二天和第三天&#xff09;里&#xff0c;每天收到兩枚金幣&#xff1b;之后三天&#xff08;第四、…

動手動腦4

import java.io.*; public class ThrowMultiExceptionsDemo { public static void main(String[] args) { try { throwsTest(); } catch(IOException e) { System.out.println("捕捉異常"); }}private static void throwsTest() throws ArithmeticException,IOExcep…

javascript --- 對象原型

對象原型 參考 - MDN Javascript中的原型 在Javascript中,每一個函數都有一個特殊的屬性,叫做原型 下面獲取函數的原型fn.prototype function f1(){} console.log(f1.prototype) /*{constructor: f f1()__proto__:{constructor: f Object()__defineGetter__: f __defineGe…

從零認識單片機(9)

keil軟件&#xff1a; IDE:IDE是集成開發環境&#xff0c;就是用來開發的完整的軟件系統。 keil和mdk: keil:只能用來開發單片機 mdk:基于keil 拓展ARM的開發&#xff0c;主要用來開發ARM-cortex-m系列單片機的程序。 使用keil打開已有的工程項目&#xff1a; 1、IDE開發軟件&a…

javascript --- vue2.x中原型的使用(攔截數組方法) 響應式原理(部分)

說明 在Vue2.x中,利用了對原型鏈的理解,巧妙的利用JavaScript中的原型鏈,實現了數組的pop、push、shift、unshift、reverse、sort、splice等的攔截. 你可能需要的知識 參考 - MDN 原型鏈 JavaScript常被描述為一種基于原型的語言(prototype-based language),每個對象擁有一…

dubbo-admin構建報錯

dubbo-admin構建報錯 意思是maven庫里沒有dubbo2.5.4-SNAPSHOT.jar這個版本的dubbo的jar包&#xff0c;把dubbo-admin項目的pom.xml的   <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>${proje…

javascript --- 手寫Promise、快排、冒泡、單例模式+觀察者模式

手寫promise 一種異步的解決方案, 參考 Promise代碼基本結構 function Promise(executor){this.state pending;this.value undefined;this.reason undefined;function resolve(){}function reject(){} } module.exports Promisestate保存的是當前的狀態,在Promise狀態發…

PyCharm 通過Github和Git上管理代碼

1.Pycharm中設置如圖: 2.配置Git,通過網頁 https://www.git-scm.com/download/win 下載 3. 轉載于:https://www.cnblogs.com/0909/p/9956406.html

【BZOJ】2395: [Balkan 2011]Timeismoney

題解 最小乘積生成樹&#xff01; 我們把&#xff0c;x的總和和y的總和作為x坐標和y左邊&#xff0c;畫在坐標系上 我們選擇兩個初始點&#xff0c;一個是最靠近y軸的A&#xff0c;也就是x總和最小&#xff0c;一個是最靠近x軸的B&#xff0c;也就是y總和最小 連接兩條直線&…

http --- http與https相關概念小結

網絡協議 參考 HTTP的特性 HTTP協議構建于TCP/IP協議之上,是一個應用層協議,默認端口是80HTTP是無連接無狀態的 HTTP報文 請求報文 HTTP協議是以ASCII碼傳輸,建立在 TCP/IP 協議之上的應用層規范。規范把HTTP請求分為三個部分:狀態行、請求頭、消息主體。 <method>…

Spring AOP注解方式實現

簡介 上文已經提到了Spring AOP的概念以及簡單的靜態代理、動態代理簡單示例&#xff0c;鏈接地址&#xff1a;https://www.cnblogs.com/chenzhaoren/p/9959596.html 本文將介紹Spring AOP的常用注解以及注解形式實現動態代理的簡單示例。 常用注解 aspect&#xff1a;定義切面…

享元模式-Flyweight(Java實現)

享元模式-Flyweight 享元模式的主要目的是實現對象的共享,即共享池,當系統中對象多的時候可以減少內存的開銷,通常與工廠模式一起使用。 本文中的例子如下: 使用享元模式: 小明想看編程技術的書, 就到家里的書架上拿, 如果有就直接看, 沒有就去買一本, 回家看. 看完了就放到家里…

算法 --- 回溯法

回溯法 參考 - 劍指Offer 回溯法可以看成蠻力法的升級版,它從解決問題每一步的所有可能選項里系統地選擇出一個可行的解決方案. 回溯法解決的問題的特性: 可以形象地用樹狀結構表示: 節點: 算法中的每一個步驟節點之間的連接線: 每個步驟中的選項,通過每一天連接線,可以到達…

013.Zabbix的Items(監控項)

一 Items簡介 Items是從主機里面獲取的所有數據&#xff0c;可以配置獲取監控數據的方式、取值的數據類型、獲取數值的間隔、歷史數據保存時間、趨勢數據保存時間、監控key的分組等。通常情況下item由key參數組成&#xff0c;如監控項中需要獲取cpu信息&#xff0c;則需要一個對…

Cookie 和 Session的區別

pass 下次再寫轉載于:https://www.cnblogs.com/nieliangcai/p/9073520.html

算法 --- 記一道面試dp算法題

題目: 給定一個數組(長度大于1),如下 let a [1,4,3,4,5] // 長度不確定,數值為整數要求寫一個函數,返回該數組中,除本身數字之外其他元素的成積.即返回如下: // 過程[4*3*4*5, 1*3*4*5, 1*4*4*5, 1*4*3*5, 1*4*3*4] // 結果[240, 60, 80, 60, 48]題目要求不使用除法,且時間…

編碼

一、什么是編碼&#xff1f;首先&#xff0c;我們從一段信息即消息說起&#xff0c;消息以人類可以理解、易懂的表示存在。我打算將這種表示稱為“明文”&#xff08;plain text&#xff09;。對于說英語的人&#xff0c;紙張上打印的或屏幕上顯示的英文單詞都算作明文。其次&a…