最小堆、勝者樹和敗者樹


前言

本文介紹三種外部排序算法:最小堆、勝者樹和敗者樹,以及為什么外部排序往往用敗者樹。

最小堆

最小堆有以下特點:
1、最小堆是一顆完全二叉樹
2、每個父節點的值總是小於等於左右孩子節點的值
3、每個節點的子樹都是一個堆樹

示例圖:

最小堆樹

堆常用一維數組結構存儲,增刪改查的時間復雜度都是 log(n)。操作流程舉例:
1、插入操作
(1)將插入元素放到數組末尾
(2)從新插入元素位置開始,將數組頭方向開始調整,或者樹結構上說,就是向上調整

2、查詢操作
(1)取出堆頂元素,並將數組最后一個元素賦值到堆頂
(2)樹結構上,向下調整

勝者樹

勝者樹的特點:
1、勝者樹,是一棵完全二叉樹
2、每個葉子節點表示一個選手,記錄選手的標號
3、每個非葉子節點表示一場比賽,記錄勝者的標號,而每層也就表示一輪比賽

勝者樹示例(數值小的勝出,非葉子節點對應 b 后面的標號):

勝者樹結構

將 b3 替換成 11,勝者樹重構示例:

勝者樹重構

重構過程中,先取到父節點的值,拿到選手對應的標號,然后再根據標號拿到選手的值和新插入選手的值比較,勝者寫到父節點。

敗者樹

敗者樹:
1、敗者樹,也是一顆完全二叉樹
2、每個葉子節點表示一個選手,記錄選手的標號
3、每個非葉子節點表示一場比賽,記錄敗者的標號,勝者晉級上一層。並且,因為樹根節點記錄的是敗者的標號,會再新建一個節點記錄最終勝者的標號。

敗者樹示例(數值大的失敗):

敗者樹結構

將 b3 替換為 13,敗者樹重構示例:

敗者樹重構

重構上比勝者樹有優化,只需要取父節點的值並進行比較。

為什么外部排序往往用敗者樹

從歷史的發展上來看,首先選擇用來做外部排序的是最小堆。它的插入和查詢復雜度都是 log(n),可以說比較高效。不過,堆調整時,每個節點都需要和左右孩子進行比較,即需要兩次比較,在外部排序中,也就是需要讀取兩次外存,那能不能再優化下呢?

於是,研究出了勝者樹。勝者樹只需要和兄弟節點進行比較,減少了一般的比較量。但是,勝者樹還需要從父節點取一次值,並且,因為新插入的值取代了原先的最優勝者,這個新值向上調整的過程中,必定需要修改父節點的值,即必須要更新勝者。那能不能再優化呢?

既然有勝者樹,那自然也有敗者樹。敗者樹解決了勝者樹存在的弊端,只需要和父節點比較一次,並且新插入的值向上調整過程中,不一定要更新。

綜上所述,目前外部排序大多采用的都是敗者樹算法實現的。側面也反應出,外部排序(文件排序)的瓶頸在於訪存,而不是計算。

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM