看数据结构写代码(66) 败者树

来源:互联网 发布:linux 代理客户端软件 编辑:程序博客网 时间:2024/05/29 18:42

计算机的 内存 是 有限的,无法 存入 庞大的数据。当 遇到 大数据需要排序时,我们 需要 将 这些 数据分段 从 硬盘里 读到 内存中,排好序,再 写入到 硬盘中,这些段 叫做 归并段。最后将 这些 分段 合并 成 一个 最终  完整 有序的 数据。 

这里 操作的 时间 =  内部 排序 时间 +  外存读写时间 + 内部归并所需时间。

其中 外存 读写时间 最耗时,外存读写时间 = 读写次数 * 读写数据的时间 ,读写 数据的时间 因 设备 性能 而 影响,我们 无法控制,我们 只能 控制 读写次数。读写 次数 和 归并过程 有关。 当 我们 采用 2路 归并 和 5路 归并,显然 5路 归并的 所 读写的 次数 更少。(具体 看 课本)。可是 当 我们扩大 归并的  路树的同时,内部 归并的 时间 却 因此 上升。

我们 用 败者树 来解决  由 归并的 路数 增加 而 导致的 内部归并 时间 上升的 问题。

败者树 和 胜者树是 个 相反的概念,败者树的 父节点  保存 失败者,而 胜者树 的 父节点 保存 胜利者。他们 都是 完全二叉树,并且 都是 将 胜利者 继续 根 上层 继续 比较。


下面 给出 败者树的 代码:

欢迎指出 代码不足

// LoseTree.cpp : 定义控制台应用程序的入口点。//败者树,父节点保存失败者的信息,胜利者继续 比赛#include "stdafx.h"#include <climits>#define K5//5路平衡归并#define MEM_SIZE 4//内存最多存储3组数据.(多加了一个最大值数据)typedef int LoseTree[K];//败者树的非终端节点typedef struct ExNode{//败者树的叶子节点int key;}External[K+1];//测试数组,假设 内存只能 放入 3组数据,并且 内存 已经将这些数据排好序了。//现在 需要归并这些数据static int testArray[K][MEM_SIZE] = {{10,15,16,INT_MAX},{9,18,20,INT_MAX},{20,22,40,INT_MAX},{6,15,25,INT_MAX},{12,37,48,INT_MAX},};//调整函数,和 所有 祖先比较,替换败者 和 最终胜利者 t[0]void adjust(LoseTree t,External ex,int i){int f = (i + K) / 2;while (f > 0){if (ex[i].key > ex[t[f]].key){int temp = i;i = t[f];//i 保存 胜利者,继续 比较t[f] = temp;//有新的败者了.}f = f / 2;}t[0] = i;//最终胜利者}//创建败者树..void createTree(LoseTree  tree,External  ex){for (int i = 0; i < K; i++){//初始化叶子节点ex[i].key = testArray[i][0];}ex[K].key = INT_MIN;//为了让第一次 所有 都是 失败者for (int i = 0; i < K; i++){//初始化非叶子节点,tree[i] = K;}for (int i = K-1; i >= 0; i--){//调整叶子节点,顺序不能反adjust(tree,ex,i);}}void inputNewKey(External ex,int winIndex){ex[winIndex].key = testArray[winIndex][1];//前移for (int i = 0; i < MEM_SIZE -1; i++){testArray[winIndex][i] = testArray[winIndex][i+1];}}//归并函数void K_Merge(){LoseTree t;//非叶子节点External ex;//叶子节点createTree(t,ex);int winIndex = t[0];//胜利者 坐标while (ex[winIndex].key != INT_MAX){printf("%d\t",ex[winIndex].key);inputNewKey(ex,winIndex);adjust(t,ex,winIndex);winIndex = t[0];}}int _tmain(int argc, _TCHAR* argv[]){K_Merge();return 0;}


假设 内存 一次 只能 载入 3 个数据(INT_MAX不算):

static int testArray[K][MEM_SIZE] = {
{10,15,16,INT_MAX},
{9,18,20,INT_MAX},
{20,22,40,INT_MAX},
{6,15,25,INT_MAX},
{12,37,48,INT_MAX},
};

最终 归并 这些 数据的 结果为:




1 0
原创粉丝点击