算法導論讀書筆記(未完成)

堆排序

總覽

   我想了想,仍是結合書中的每一句話來解釋一下他們的前因後果吧,首先堆排序的時間複雜度是O(nlgn),也就是咱們所說的大O時間複雜度。爲何說是nlgn的時間複雜度呢?首先咱們須要知道max-heapfify的時間複雜度是lgn,也就是咱們一般所說的log2n,由於數據結構當中的堆本質上還二叉樹。那麼這個n從哪裏來呢?每一次Max-heapify都是一個調整堆成爲最大堆的過程,每一次只能調整一個元素,由於堆中有n個元素,因此咱們要調整n次才能把全部元素調整到正確的地方,這很像冒泡排序,可是實際上這並非冒泡排序。稍後會跟你們詳細說一下。api

  那麼說到堆排序,咱們首先應該去思考一下,什麼是堆?既然堆是二叉樹,那麼堆確定會知足二叉樹相關的性質。另外這裏所說的堆,並非Java的JVM所說的堆,這裏所說的堆,僅僅限於數據結構。若是用數組來進行表示的話,須要注意一點,堆中的有效元素,並非整個數組,它有可能會小於這個數組的元素個數,那麼爲何會是這樣的呢?具體能夠參考這篇文章。數組

  堆當中有3個比較重要的概念,一個是根節點,一個是左子樹,一個是右子樹。而堆通常分爲最大堆和最小堆,通常來講:堆排序所說的,都是最大堆,而最小堆通常用於構造優先隊列。那麼下面咱們仍是拿最大堆來講一下,最大堆,顧名思義,根節點是最大的,它應該比左子樹和右子樹的節點值都要大,這不只僅說是比它的孩子大,並且這個操做是遞歸的。也就是說沒有任何一個節點可以比根節點更大。那麼左子樹和右子樹之間有沒有什麼關係呢?若是用數組來表示的話,我以爲只是一個物理存儲位置之間的關係。二叉樹的遍歷相關的知識點你們能夠去百度上搜一下,永遠記住這麼一點,二叉樹的完美之處是在於它利用了計算機的原理,也就是二進制移位,這樣能夠大大提升效率,這就是爲何計算機只有2叉樹,沒有三叉樹,四叉樹的緣由了。在最大堆當中,根節點的值永遠大於或等於子節點的值。數據結構

 

維護堆的性質

  這一節來看看怎麼維護堆的正確性。先來看一段僞代碼吧,下面這段代碼是不能獨立的,它依賴於i的位置。也就是說,i實際上是根節點(咱們所認爲的),其實它在樹當中不必定是根節點,還有一點想跟你們闡述的是:根節點是相對的,相對於它的子樹來講,只要是非葉子節點,均可以認爲是根節點。而下面的代碼,實際上只是根據最大堆的性質,把大的往上移而已;注意最後一句話,它是一個遞歸,也就是說,它的做用是把大的節點儘量地往根上面靠攏,直到不能再交換位置爲止。遞歸的終止條件就是largets==i.
spa

 建堆

  固然也就是建立一個堆了,本質上來講,建堆其實也就是一個不斷調整元素的過程,使其達到最大堆,由於若是一個數組是未排序的,若是想按照堆排序來進行排序,那麼就要利用下面的代碼。注意一下,爲何是a.lenght/2呢?仍是回到以前提到的二叉堆的性質,MAX-HEAPIFY是向下進行遍歷的,而A.lenght/2剛好是葉子節點的父節點。這樣作的好處,就是能夠把每個節點都放到正確的位置上,就像這樣來解釋:曾祖父,爺爺,父親,你,兒子,孫子。這幾個的順序是亂的,假設先從兒子開始,兒子發現他的位置比孫子小(也就是兒子是子節點,孫子是父節點),而後交換順序,第一次循環結束,第二次發現你竟然比兒子的順序要小,而後交換你和兒子的順序,繼續查找,發現孫子竟然排在你的前面了,趕忙交換位置,而後你和兒子和孫子都在正確的位置上了。這麼不停循環,直到曾祖父,你們最後都在了正確的位置上,因此建堆的時間複雜度是外層循環n和內層MAX-HEAPIFY的一個乘積。.net

 

 

   

 

快速排序

相關文章
相關標籤/搜索