本週學習了第12章優先隊列與堆php
操做 說明 addElement 將給定元素添加到該堆中 removeMin 刪除堆的最小元素 findMin 返回一個指向堆中最小元素的引用
如圖是一個最小堆
html
addElement方法將給定的Comparable元素添加到堆中的恰當位置處,且維持該堆的徹底性屬性和有序性屬性node
若是一棵二叉樹是平衡的,及全部葉子都位於h或者h-1層,其中h爲log2n,n是樹中的元素數目,以及全部h層中的葉子都位於該樹的左邊,那麼該樹就被認爲是徹底的。由於堆是一棵徹底樹,因此對於新插入的結點只存在一個正確的位置,要麼是h層左邊的下一個空位置,要麼就是h+1層左邊的第一個位置(若是h層是滿的話)git
removeMin操做將刪除最小堆中的最小元素並返回他,最小堆中的元素便是它的根結點,爲了保持樹的合法性,須要有一個能替換根的合法元素,且它是樹中最末一片葉子上的元素。將最末一片葉子移至根處以後,又須要將該堆進行從新排序。排序方法須要將該結點與最小孩子進行比較而後逐漸下沉到合適的位置。借用上圖,若是將根結點1刪去,那麼最末葉子6就將成爲新的根結點,它將與二、5進行比較最終落在5如今的位置,而2將成爲新的根結點。web
問題1:鏈表實現堆的過程當中的addElement操做第一步要肯定要插入結點的雙親,爲何在最壞的狀況下要從堆的右下結點遍歷到根結點以後還要再從根結點遍歷到堆的左下結點?數組
問題1解決方案:這個問題我思考了小半個小時,添加的第一步須要肯定插入結點的雙親,由於須要比較雙親結點的值與新結點的值,決定新結點是否要上浮。因此最壞的狀況應該是新結點一直上浮到根結點,此時按最小堆的定義來看,添加元素這一操做應該是中止了,由於堆頂是最小元素了,它的左孩子和右孩子的值都應該比它要小,因此不須要繼續遍歷它的左孩子直到左下結點了吧。和同窗討論以後,才發現個人理解錯在哪裏了。它這裏指的是遍歷的最壞狀況須要從右下結點一直到根再到左下結點,而不是結點互相之間的比較須要讓結點上浮以後再次下沉(事實上跟我分析的同樣,他也沒法作到)。它這裏指的是查找肯定新結點的雙親結點的最壞狀況
如上醜圖,添加元素時恰好碰見滿樹的狀況,須要從右下最後一片葉子開始找起,一直到左下結點,才最終肯定要插入的元素的雙親結點。數據結構
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(); } else while (result.getLeft() != null) result = (HeapNode<T>) result.getLeft(); return result;
首先教材講到,這是一個返回指向插入結點的雙親結點的引用。因此就容易理解到,這個方法就是肯定新插入結點的雙親結點。也就經過此來決定新添加元素的位置。
一開始,新設一個變量result指向lastNode,即指向最後一片葉子的引用。
接下來經過判斷最後一片葉子的狀況來肯定插入結點的雙親結點,當最後一片葉子不是根結點且同時不是左孩子的時候,就將result的父結點付給result,直到不知足兩個條件之一跳出循環。當最後一片葉子是根結點時,已經肯定了新結點的雙親結點,能夠進入下一步,而若是最後一片葉子是右結點,就說明當前父結點是滿的,不能再在當前父結點下添加新元素,因此將result指向result的父親,方便尋找一個沒有滿的父結點。下一步,此時result跳出while循環,要麼它是根結點,要麼它是左孩子。若是它是左孩子,即進入if語句內,判斷它的兄弟結點是否爲null,若是返回true,那麼新添加元素的雙親結點就肯定了是result的父結點,而新結點將做爲result的右孩子添加到堆中,若是返回false,result將指向這個右孩子,並找到它的最左下的位置添加。若是result是指向根結點的,那麼也一直循環到它的最左下位置,添加新元素。
這個問題的解決參考了於欣月同窗的博客,她在解釋時運用了圖文結合的形式,對我理解該問題起了很大幫助ide
問題1:測試LinkedHeap類,實現層序輸出、前序中序後序各類輸出,很不巧的是它出現了亂碼的狀況
學習
問題1解決方案:這個問題的出現充分說明我還沒能掌握迭代器的精髓,首先方法的使用就是徹底錯誤的,我還把它看成簡單的toString方法在加以使用。因此天然輸出不來須要的結果,標準的應該是如圖,先設置一個迭代器的對象,經過for循環一個一個調用迭代器裏的內容,如圖
測試
排序方法 時間複雜度 選擇排序 O(n^2) 插入排序 O(n^2) 冒泡排序 O(n^2)
在個人鞭策與督促之下,某同窗的博客又恢復到了以往的超高水平。(他在教材問題中提到了一個
實現優先級隊列的二叉堆、d堆、左式堆、斜堆、二項堆都是什麼意思?
我翻了一下書,好像沒有找到哪裏提到了這些概念,因此若是是查找的資料裏提到的,但願也能貼出連接來,讓我學習學習,不至於落下太多
方藝雯的博客寫的很棒,提出了不少我沒考慮過的問題。
基於評分標準,我給譚鑫的博客打分:6分。得分狀況以下:
正確使用Markdown語法(加1分)
模板中的要素齊全(加1分)
教材學習中的問題和解決過程, 一個問題加1分
代碼調試中的問題和解決過程, 三個問題加3分
基於評分標準,我給方藝雯的博客打分:8分。得分狀況以下
正確使用Markdown語法(加1分):
模板中的要素齊全(加1分)
教材學習中的問題和解決過程, 兩個問題加2分
代碼調試中的問題和解決過程, 四個問題加4分
這周的教材學習比較容易,因此花的時間相對較少,可是實驗使人難受。
代碼行數(新增/累積) | 博客量(新增/累積) | 學習時間(新增/累積) | 重要成長 | |
---|---|---|---|---|
目標 | 5000行 | 30篇 | 400小時 | |
第一週 | 0/0 | 1/1 | 8/8 | |
第二週 | 470/470 | 1/2 | 12/20 | |
第三週 | 685/1155 | 2/4 | 10/30 | |
第四周 | 2499/3654 | 2/6 | 12/42 | |
第六週 | 1218/4872 | 2/8 | 10/52 | |
第七週 | 590/5462 | 1/9 | 12/64 | |
第八週 | 993/6455 | 1/10 | 12/76 | |
第九周 | 1192/7467 | 2/12 | 10/86 |