计算机的 内存 是 有限的,无法 存入 庞大的数据。当 遇到 大数据需要排序时,我们 需要 将 这些 数据
分段 从 硬盘里 读到 内存中,排好序,再 写入到 硬盘中,这些段 叫做 归并段。最后将 这些 分段 合并 成 一个 最终 完整 有序的 数据。
这里 操作的 时间 = 内部 排序 时间 + 外存读写时间 + 内部归并所需时间。
其中 外存 读写时间 最耗时,外存读写时间 = 读写次数 * 读写数据的时间 ,读写 数据的时间 因 设备 性能 而 影响,我们 无法控制,我们 只能 控制 读写次数。读写 次数 和 归并过程 有关。 当 我们 采用 2路 归并 和 5路 归并,显然 5路 归并的 所 读写的 次数 更少。(具体 看 课本)。可是 当 我们扩大 归并的 路树的同时,内部 归并的 时间 却 因此 上升。
我们 用 败者树 来解决 由 归并的 路数 增加 而 导致的 内部归并 时间 上升的 问题。
败者树 和 胜者树是 个 相反的概念,败者树的 父节点 保存 失败者,而 胜者树 的 父节点 保存 胜利者。他们 都是 完全二叉树,并且 都是 将 胜利者 继续 根 上层 继续 比较。
下面 给出 败者树的 代码:
欢迎指出 代码不足
// LoseTree.cpp : 定义控制台应用程序的入口点。 //败者树,父节点保存失败者的信息,胜利者继续 比赛 #include "stdafx.h" #include <climits> #define K 5//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},
};
最终 归并 这些 数据的 结果为:
时间: 2024-10-10 16:43:43