数据结构实践——置换-选择算法模拟

简介: 本文是针对[数据结构基础系列(10):外部排序]中的实践项目。【项目 】置换-选择算法模拟   编写程序,模拟置换-选择算法生成初始归并段的过程。   设大文件中的记录共有18个: 15 4 97 64 17 32 108 44 76 9 39 82 56 31 80 73 255 68   内存工作区可以容纳5个记录,输出产生的归并段文件。   在模拟中,输

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

【项目 】置换-选择算法模拟
  编写程序,模拟置换-选择算法生成初始归并段的过程。
  设大文件中的记录共有18个: 15 4 97 64 17 32 108 44 76 9 39 82 56 31 80 73 255 68
  内存工作区可以容纳5个记录,输出产生的归并段文件。
  在模拟中,输入文件数据和输出的归并段数据均直接置在内存中即可。

参考解答

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#define MaxSize 50          //每个文件最多记录数
#define MAXKEY 32767        //最大关键字值∞
#define W 5                 //内存工作区可容纳的记录个数
typedef int LoserTree[W];   //败者树是完全二叉树且不含叶子,可采用顺序存储结构
typedef int InfoType;       //定义其他数据项的类型
typedef int KeyType;        //定义关键字类型为整型
typedef struct              //记录类型
{
    KeyType key;            //关键字项
    InfoType otherinfo;     //其他数据项,具体类型在主程中定义
} RecType;
typedef struct
{
    RecType rec;            //存放记录
    int rnum;               //所属归并段的段号
} WorkAreaType;
typedef WorkAreaType WorkArea[W];               //内存工作区,容量为W
typedef struct
{
    RecType recs[MaxSize];  //存放文件中的数据项
    int length;             //存放文件中实际记录个数
    int currec;             //存放当前位置
} FileType;                 //文件类型
FileType Fi;                //定义输入文件,为全局变量
FileType Fo;                //定义输出文件,为全局变量
void initial()              //输入输出文件初始化
{
    int n=19,i;
    KeyType a[]= {15,4,97,64,17,32,108,44,76,9,39,82,56,31,80,73,255,68,MAXKEY};
    for (i=0; i<n; i++)
        Fi.recs[i].key=a[i];
    Fi.length=n;
    Fi.currec=-1;
    Fo.currec=-1;
    Fo.length=0;
}
void Select_MiniMax(LoserTree ls, WorkArea wa,int q)
//从wa[q]起到败者树的根比较选择最小记录,并由q指示它所在的归并段
{
    int p,s,t;
    for (t=(W+q)/2,p=ls[t]; t>0; t=t/2,p=ls[t])
        if ((wa[p].rnum<wa[q].rnum) || (wa[p].rnum==wa[q].rnum && wa[p].rec.key<wa[q].rec.key))
        {
            s=q;
            q=ls[t];        //q指示新的胜者
            ls[t]=s;
        }
    ls[0]=q;
}
void Construct_Loser(LoserTree ls,WorkArea wa)
//输入W个记录到内存工作区wa,建败者树ls,选最小的记录并由s指示其在wa中的位置
{
    int i;
    for(i=0; i<W; i++)
        wa[i].rnum=wa[i].rec.key=ls[i]=0;       //工作区初始化
    for(i=W-1; i>=0; i--)
    {
        Fi.currec++;                            //从输入文件读入一个记录
        wa[i].rec=Fi.recs[Fi.currec];
        wa[i].rnum=1;                           //其段号为1
        Select_MiniMax(ls,wa,i);                //调整败者
    }
}
void get_run(LoserTree ls,WorkArea wa,int rc,int &rmax)
//求得一个初始归并段
{
    int q;
    KeyType minimax;                //当前最小关键字
    while (wa[ls[0]].rnum==rc)      //选得的当前最小记录属当前段时
    {
        q=ls[0];                    //q指示当前最小记录在wa中的位置
        minimax=wa[q].rec.key;
        Fo.currec++;                //将刚选得的当前最小记录写入输出文件
        Fo.length++;
        Fo.recs[Fo.currec]=wa[q].rec;
        Fi.currec++;                //从输入文件读入下一记录
        wa[q].rec=Fi.recs[Fi.currec];
        if (Fi.currec>=Fi.length-1) //输入文件结束,虚设记录(属rmax+1段)
        {
            wa[q].rnum=rmax+1;
            wa[q].rec.key=MAXKEY;
        }
        else                        //输入文件非空时
        {
            if(wa[q].rec.key<minimax)
            {
                rmax=rc+1;          //新读入的记录属下一段
                wa[q].rnum=rmax;
            }
            else                    //新读入的记录属当前段
                wa[q].rnum=rc;
        }
        Select_MiniMax(ls,wa,q);    //选择新的当前最小记录
    }
}
void Replace_Selection(LoserTree ls,WorkArea wa)
//在败者树ls和内存工作区wa上用置换-选择排序求初始归并段
{
    int rc,rmax;
    RecType j;                          //j作为一个关键字最大记录,作为一个输出段结束标志
    j.key=MAXKEY;
    Construct_Loser(ls,wa);             //初建败者树
    rc=1;                               //rc指示当前生成的初始归并段的段号
    rmax=1;                             //rmax指示wa中关键字所属初始归并段的最大段号
    while(rc<=rmax)                     //rc=rmax+1标志输入文件的置换-选择排序已完成
    {
        get_run(ls,wa,rc,rmax);         //求得一个初始归并段
        Fo.currec++;                    //将段结束标志写入输出文件
        Fo.recs[Fo.currec]=j;
        Fo.length++;
        rc=wa[ls[0]].rnum;              //设置下一段的段号
    }
}

int main()
{
    int i=0,rno=1;
    initial();
    LoserTree ls;
    WorkArea wa;
    printf("大文件的记录为:\n  ");
    while (Fi.recs[i].key!=MAXKEY)
    {
        printf("%d ",Fi.recs[i].key);
        i++;
    }
    printf("\n");
    Replace_Selection(ls,wa);       //用置换-选择排序求初始归并段
    printf("产生的归并段文件的记录如下:\n");
    printf("  归并段%d:",rno);     //输出所有的归并段
    for (i=0; i<Fo.length; i++)
        if (Fo.recs[i].key==MAXKEY)
        {
            printf("∞");
            if (i<Fo.length-1)
            {
                rno++;
                printf("\n  归并段%d:",rno);
            }
        }
        else
            printf("%d ",Fo.recs[i].key);
    printf("\n  共产生%d个归并段文件\n",rno);
    return 0;
}
目录
相关文章
机器学习/深度学习 算法 自动驾驶
1501 0
|
10月前
|
消息中间件 缓存 NoSQL
Redis各类数据结构详细介绍及其在Go语言Gin框架下实践应用
这只是利用Go语言和Gin框架与Redis交互最基础部分展示;根据具体业务需求可能需要更复杂查询、事务处理或订阅发布功能实现更多高级特性应用场景。
532 86
|
10月前
|
算法 API 数据安全/隐私保护
深度解析京东图片搜索API:从图像识别到商品匹配的算法实践
京东图片搜索API基于图像识别技术,支持通过上传图片或图片URL搜索相似商品,提供智能匹配、结果筛选、分页查询等功能。适用于比价、竞品分析、推荐系统等场景。支持Python等开发语言,提供详细请求示例与文档。
|
存储 监控 安全
企业上网监控系统中红黑树数据结构的 Python 算法实现与应用研究
企业上网监控系统需高效处理海量数据,传统数据结构存在性能瓶颈。红黑树通过自平衡机制,确保查找、插入、删除操作的时间复杂度稳定在 O(log n),适用于网络记录存储、设备信息维护及安全事件排序等场景。本文分析红黑树的理论基础、应用场景及 Python 实现,并探讨其在企业监控系统中的实践价值,提升系统性能与稳定性。
768 1
|
存储 监控 算法
基于跳表数据结构的企业局域网监控异常连接实时检测 C++ 算法研究
跳表(Skip List)是一种基于概率的数据结构,适用于企业局域网监控中海量连接记录的高效处理。其通过多层索引机制实现快速查找、插入和删除操作,时间复杂度为 $O(\log n)$,优于链表和平衡树。跳表在异常连接识别、黑名单管理和历史记录溯源等场景中表现出色,具备实现简单、支持范围查询等优势,是企业网络监控中动态数据管理的理想选择。
301 0
|
监控 算法 安全
公司电脑监控软件关键技术探析:C# 环形缓冲区算法的理论与实践
环形缓冲区(Ring Buffer)是企业信息安全管理中电脑监控系统设计的核心数据结构,适用于高并发、高速率与短时有效的多源异构数据处理场景。其通过固定大小的连续内存空间实现闭环存储,具备内存优化、操作高效、数据时效管理和并发支持等优势。文章以C#语言为例,展示了线程安全的环形缓冲区实现,并结合URL访问记录监控应用场景,分析了其在流量削峰、关键数据保护和高性能处理中的适配性。该结构在日志捕获和事件缓冲中表现出色,对提升监控系统效能具有重要价值。
368 1
|
监控 算法 数据处理
基于 C++ 的 KD 树算法在监控局域网屏幕中的理论剖析与工程实践研究
本文探讨了KD树在局域网屏幕监控中的应用,通过C++实现其构建与查询功能,显著提升多维数据处理效率。KD树作为一种二叉空间划分结构,适用于屏幕图像特征匹配、异常画面检测及数据压缩传输优化等场景。相比传统方法,基于KD树的方案检索效率提升2-3个数量级,但高维数据退化和动态更新等问题仍需进一步研究。未来可通过融合其他数据结构、引入深度学习及开发增量式更新算法等方式优化性能。
323 17
|
存储 算法 安全
如何控制上网行为——基于 C# 实现布隆过滤器算法的上网行为管控策略研究与实践解析
在数字化办公生态系统中,企业对员工网络行为的精细化管理已成为保障网络安全、提升组织效能的核心命题。如何在有效防范恶意网站访问、数据泄露风险的同时,避免过度管控对正常业务运作的负面影响,构成了企业网络安全领域的重要研究方向。在此背景下,数据结构与算法作为底层技术支撑,其重要性愈发凸显。本文将以布隆过滤器算法为研究对象,基于 C# 编程语言开展理论分析与工程实践,系统探讨该算法在企业上网行为管理中的应用范式。
354 8
|
存储 监控 算法
基于 C# 时间轮算法的控制局域网上网时间与实践应用
在数字化办公与教育环境中,局域网作为内部网络通信的核心基础设施,其精细化管理水平直接影响网络资源的合理配置与使用效能。对局域网用户上网时间的有效管控,已成为企业、教育机构等组织的重要管理需求。这一需求不仅旨在提升员工工作效率、规范学生网络使用行为,更是优化网络带宽资源分配的关键举措。时间轮算法作为一种经典的定时任务管理机制,在局域网用户上网时间管控场景中展现出显著的技术优势。本文将系统阐述时间轮算法的核心原理,并基于 C# 编程语言提供具体实现方案,以期深入剖析该算法在局域网管理中的应用逻辑与实践价值。
334 5
|
存储 机器学习/深度学习 算法
C 408—《数据结构》算法题基础篇—链表(下)
408考研——《数据结构》算法题基础篇之链表(下)。
642 30

热门文章

最新文章