敗者樹多路排序

2021-08-08 22:00:13 字數 3278 閱讀 2115

定義:

敗者樹是乙個完全二叉樹,非葉子節點記錄失敗者。那麼相對於勝者樹,具有訪存小的優勢。勝者樹勝者拿走後,整條通路(從葉子到根)所有記錄的勝者資訊失效,那麼新加入節點需要從葉子一直遍歷到根,有可能每次都要寫入(更新新的勝者)。而敗者樹,新加入的節點可以利用整條路徑的敗者資訊。

敗者樹構建

構建過程:

① 初始四個陣列,1,2,3,4,內部節點為-1;構建完全後,內部節點記錄陣列編號。

② 陣列4中元素18與父節點比較,父節點為-1,更新為4,退出;等待後面元素更新父節點。

③ 陣列3中元素11與父節點記錄的敗者4(陣列4中元素18)比較,記錄敗者4,勝者3上浮,更新,遇到-1停止上浮,退出。

④ 陣列2中元素6與父節點比較,父節點為-1,更新為2,退出;等等後面元素更新父節點。

⑤ 陣列1中元素7與父節點記錄的敗者2(陣列2中元素6)比較,記錄敗者1,勝者2上浮與父節點記錄的3比較。

⑥ 陣列2(6)與陣列3(11)比較,記錄敗者3,將最終勝者2單獨記錄。

⑦ 至此,敗者樹構建完畢。

敗者樹排序

規定:小於等於為勝利者。

① 勝者為陣列1,拿掉5以後,陣列1彈出乙個元素。

② 陣列1中新元素12與父節點比較(即陣列2中元素6比較),記錄敗者1,勝者2上浮,與陣列3比較,取得勝利。

③ 勝者為陣列2,拿掉6以後,陣列2彈出乙個元素。

④ 陣列2中新元素9與父節點比較(即資料1中元素12比較),記錄敗者1,勝者2上浮,與陣列3比較,取得勝利。

⑤ 勝者為陣列2,拿掉9以後,陣列2彈出乙個元素。

⑥ 陣列2中新元素12與與父節點比較(即陣列1中元素12比較),記錄敗者1,勝者2上浮,與陣列3比較,失敗。

⑦ 勝者為陣列3,拿掉11以後,陣列3彈出乙個元素。

⑧ 陣列3中新元素15與父節點比較後(即陣列4中元素18比較),記錄敗者4,勝者3上浮,與陣列2比較,失敗。

⑨ 勝者為陣列2.

**實現

#ifndef _loser_tree_h_

#define _loser_tree_h_

#include

#include

class player ;

class losertree ;

losertree();

~losertree();

// addplayer takes the ownership of player.

void addplayer(player* player);

bool playnextgame();

element getwinner();

private:

bool buildtree();

void buildimpl(const

int players_slot);

bool is_build_;

std::vector

players_;

std::vector

inner_node_;

};#endif

#include "loser_tree.h"

#include

#define loser_tree_sentinel -1

#define loser_tree_max_value int_max

losertree::losertree()

losertree::~losertree()

}void losertree::addplayer(player* player)

}bool losertree::buildtree()

// init inner node.

inner_node_.reserve(players_.size());

for (size_t i = 0; i < players_.size(); ++i)

for (int i = players_.size() - 1; i >= 0; --i)

return

true;

}void losertree::buildimpl(const

int player_slot)

// winner becomes loser, record loser.

if (players_[winner_slot]->value() >

players_[parent_slot]->value())

} // update winner.

inner_node_[0] = winner_slot;

}bool losertree::playnextgame()

if (inner_node_.empty())

int winner_slot = inner_node_[0];

if (winner_slot == loser_tree_sentinel ||

players_[winner_slot]->value() == loser_tree_max_value)

players_[winner_slot]->next();

buildimpl(winner_slot);

return players_[inner_node_[0]]->value() != loser_tree_max_value;

}losertree::element losertree::getwinner()

player::player(const

std::vector

& container)

: container_(container)

player::~player()

void player::next()

int player::value() else

}

#include "loser_tree.h"

#include

#include

using

namespace

std;

int main()

return

0;}

敗者樹與外部多路歸併排序

在處理大資料量的排序時,由於資料無法全部載入到記憶體,內部排序無法對整個資料集進行排序,需要到外部排序。外部排序有一些特點,跟記憶體容量和讀寫檔案有關 1.讀寫檔案,需要考慮 io 時間 2.從無序到逐步有序的過程中,需要多個中間檔案外部排序有多種,常見的歸併排序的如下 輸入為大檔案 f 排序過程分...

7 7 3 多路平衡歸併與敗者樹

歸併趟數s logm r 向下取整 從而增加歸併路數m可以減少歸併趟數s,進而減少訪問外存的次數 i o次數 然而,當增加歸併路數m時,內部歸併時間將增加。做內部歸併時,在m個元素中選擇關鍵字最小的記錄需要比較m 1次。每趟歸併n個元素最多需要作 n 1 m 1 次比較,s趟歸併總共需要的比較次數為...

外部排序 勝者樹與敗者樹

參考 引子 前面講到的google面試題 賽馬問題 我一直在想,會不會有一種演算法能講得更清楚,更明白呢。後來我發現賽馬問題和外部排序之歸併排序很相似。賽馬問題中由於賽道只能一次賽5匹馬,就好比我們要對25匹馬進行排序,但是發現計算機記憶體不夠 賽道是賽5匹馬的 最多同時只能排序5匹馬,所以要用外部...