数据结构实践——败者树归并模拟

简介: 本文是针对[数据结构基础系列(10):外部排序]中的实践项目。【项目】败者树归并模拟   编写程序,模拟改者树实现5路归并算法的过程。   设有5个文件,其中的记录的关键字如下:   F0:{17,21,∞} F1:{5,44,∞} F2:{10,12,∞}F3: {29,32,∞} F4: {15,56,∞}   要求将其归并为一个有序段并输出。   假设这些

本文是针对[数据结构基础系列(10):外部排序]中的实践项目。

【项目】败者树归并模拟
  编写程序,模拟改者树实现5路归并算法的过程。
  设有5个文件,其中的记录的关键字如下:
  F0:{17,21,∞} F1:{5,44,∞} F2:{10,12,∞}F3: {29,32,∞} F4: {15,56,∞}
  要求将其归并为一个有序段并输出。
  假设这些输入文件数据保存在内存中,输出结果也不必输出到文件,而是在屏幕上输出即可。

参考解答

#include <stdio.h>
#define MaxSize 20          //每个文件中最多记录
#define K 5                 //5路平衡归并
#define MAXKEY 32767        //最大关键字值∞
#define MINKEY -32768       //最小关键字值-∞
typedef int InfoType;
typedef int KeyType;
typedef struct              //记录类型
{
    KeyType key;            //关键字项
    InfoType otherinfo;     //其他数据项,具体类型在主程中定义
} RecType;
typedef struct
{
    RecType recs[MaxSize];
    int currec;
} FileType;                 //文件类型
typedef int LoserTree[K];   //败者树是完全二叉树且不含叶子
RecType b[K];               //b中存放各段中取出的当前记录
FileType F[K];              //存放文件记录的数组
void initial()
{
    int i;                  //5个初始文件,当前读记录号为-1
    F[0].recs[0].key=17;
    F[0].recs[1].key=21;
    F[0].recs[2].key=MAXKEY;
    F[1].recs[0].key=5;
    F[1].recs[1].key=44;
    F[1].recs[2].key=MAXKEY;
    F[2].recs[0].key=10;
    F[2].recs[1].key=12;
    F[2].recs[2].key=MAXKEY;
    F[3].recs[0].key=29;
    F[3].recs[1].key=32;
    F[3].recs[2].key=MAXKEY;
    F[4].recs[0].key=15;
    F[4].recs[1].key=56;
    F[4].recs[2].key=MAXKEY;
    for (i=0;i<K;i++)
        F[i].currec=-1;
}
void input(int i,int &key)  //从F[i]文件中读一个记录到b[i]中
{
    F[i].currec++;
    key=F[i].recs[F[i].currec].key;
}
void output(int q)      //输出F[q]中的当前记录
{
    printf("输出F[%d]的关键字%d\n",q,F[q].recs[F[q].currec].key);
}
void Adjust(LoserTree ls,int s)
//沿从叶子节点b[s]到根节点ls[0]的路径调整败者树
{
    int i,t;
    t=(s+K)/2;          //ls[t]是b[s]的双亲节点
    while(t>0)
    {
        if(b[s].key>b[ls[t]].key)
        {
            i=s;
            s=ls[t];    //s指示新的胜者
            ls[t]=i;
        }
        t=t/2;
    }
    ls[0]=s;
}
void display(LoserTree ls)  //输出败者树
{
    int i;
    printf("败者树:");
    for (i=0;i<K;i++)
        if (b[ls[i]].key==MAXKEY)
            printf("%d(∞) ",ls[i]);
        else if (b[ls[i]].key==MINKEY)
            printf("%d(-∞) ",ls[i]);
        else
            printf("%d(%d) ",ls[i],b[ls[i]].key);
    printf("\n");
}
void CreateLoserTree(LoserTree ls)      //建立败者树
{
    int i;
    b[K].key=MINKEY;    //b[K]置为最小关键字
    for (i=0;i<K;i++)
        ls[i]=K;        //设置ls中“败者”的初值,全部为最小关键字段号
    for(i=K-1;i>=0;--i) //依次从b[K-1],b[K-2],…,b[0]出发调整败者
        Adjust(ls,i);
}
void K_Merge(LoserTree ls)  //利用败者树ls将进行K路归并到输出
{
    int i,q;
    for(i=0;i<K;++i)        //分别从k个输入归并段读入该段当前第一个记录的关键字到b
        input(i,b[i].key);
    CreateLoserTree(ls);    //建败者树ls,选得最小关键字为b[ls[0]].key
    display(ls);
    while(b[ls[0]].key!=MAXKEY)
    {
        q=ls[0];            //q指示当前最小关键字所在归并段
        output(q);          //将编号为q的归并段中当前(关键字为b[q].key)的记录输出
        input(q,b[q].key);  //从编号为q的输入归并段中读人下一个记录的关键字
        if (b[q].key==MAXKEY)
            printf("从F[%d]中添加关键字∞并调整\n",q);
        else
            printf("从F[%d]中添加关键字%d并调整\n",q,b[q].key);
        Adjust(ls,q);       //调整败者树,选择新的最小关键字
        display(ls);
    }
}
int main()
{
    LoserTree ls;
    initial();
    K_Merge(ls);
    printf("\n");
    return 0;
}
目录
相关文章
|
29天前
|
算法
数据结构之博弈树搜索(深度优先搜索)
本文介绍了使用深度优先搜索(DFS)算法在二叉树中执行遍历及构建链表的过程。首先定义了二叉树节点`TreeNode`和链表节点`ListNode`的结构体。通过递归函数`dfs`实现了二叉树的深度优先遍历,按预序(根、左、右)输出节点值。接着,通过`buildLinkedList`函数根据DFS遍历的顺序构建了一个单链表,展示了如何将树结构转换为线性结构。最后,讨论了此算法的优点,如实现简单和内存效率高,同时也指出了潜在的内存管理问题,并分析了算法的时间复杂度。
49 0
|
2月前
|
存储 算法 C语言
通义灵码在考研C语言和数据结构中的应用实践 1-5
通义灵码在考研C语言和数据结构中的应用实践,体验通义灵码的强大思路。《趣学C语言和数据结构100例》精选了五个经典问题及其解决方案,包括求最大公约数和最小公倍数、统计字符类型、求特殊数列和、计算阶乘和双阶乘、以及求斐波那契数列的前20项和。通过这些实例,帮助读者掌握C语言的基本语法和常用算法,提升编程能力。
88 4
|
22天前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
43 5
|
1月前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
75 16
|
29天前
|
算法
数据结构之文件系统模拟(树数据结构)
本文介绍了文件系统模拟及其核心概念,包括树状数据结构、节点结构、文件系统类和相关操作。通过构建虚拟环境,模拟文件的创建、删除、移动、搜索等操作,展示了文件系统的基本功能和性能。代码示例演示了这些操作的具体实现,包括文件和目录的创建、移动和删除。文章还讨论了该算法的优势和局限性,如灵活性高但节点移除效率低等问题。
47 0
|
2月前
|
存储 算法 关系型数据库
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
这篇文章主要介绍了多路查找树的基本概念,包括二叉树的局限性、多叉树的优化、B树及其变体(如2-3树、B+树、B*树)的特点和应用,旨在帮助读者理解这些数据结构在文件系统和数据库系统中的重要性和效率。
31 0
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
|
2月前
|
存储 搜索推荐 算法
【用Java学习数据结构系列】七大排序要悄咪咪的学(直接插入,希尔,归并,选择,堆排,冒泡,快排)以及计数排序(非比较排序)
【用Java学习数据结构系列】七大排序要悄咪咪的学(直接插入,希尔,归并,选择,堆排,冒泡,快排)以及计数排序(非比较排序)
29 1
|
2月前
|
Java C++
【数据结构】探索红黑树的奥秘:自平衡原理图解及与二叉查找树的比较
本文深入解析红黑树的自平衡原理,介绍其五大原则,并通过图解和代码示例展示其内部机制。同时,对比红黑树与二叉查找树的性能差异,帮助读者更好地理解这两种数据结构的特点和应用场景。
38 0
|
2月前
|
存储
探索数据结构:单链表的实践和应用
探索数据结构:单链表的实践和应用