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

本文是针对[数据结构基础系列(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;
}
时间: 2025-01-29 19:06:29

数据结构实践——置换-选择算法模拟的相关文章

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

本文是针对[数据结构基础系列(10):外部排序]中的实践项目. [项目]败者树归并模拟 编写程序,模拟改者树实现5路归并算法的过程. 设有5个文件,其中的记录的关键字如下: F0:{17,21,∞} F1:{5,44,∞} F2:{10,12,∞}F3: {29,32,∞} F4: {15,56,∞} 要求将其归并为一个有序段并输出. 假设这些输入文件数据保存在内存中,输出结果也不必输出到文件,而是在屏幕上输出即可. 参考解答 #include <stdio.h> #define MaxSiz

通过请求页式存储管理中页面置换算法模拟设计

问题描述 通过请求页式存储管理中页面置换算法模拟设计 (1)随机产生一个页面走向序列. (2)计算并输出下述各种算法在不同内存容量下的命中率. ①先进先出页面置换算法(FIFO): ②最近最久未使用页面置换算法(LRU): ③最佳淘汰算法(OPT): ④最不经常使用页面淘汰算法(LFU): ⑤最近没有使用页面淘汰算法(NUR).

给数据结构初学者:跨过算法和程序之间的鸿沟

[摘要]学习数据结构时,将各种基本操作通过程序实现,可以加深对算法的理解,也是提高编程能力的一种有效手段.针对初学者在搭建算法和程序之间联系困难的问题,本文以线性表部分为例,介绍了如何从读算法中找出实现程序的线索,围绕算法和程序之间的联系.抽象的描述和具体的实现之间的关系,引导读者学到抽象算法的精髓,最后对实践的路线.方案等进行了总结,并给出一些建议. [讲座和视频]见<讲座:跨过算法和程序之间的那道沟(带视频链接)> [正文] 计算机是算法的科学.学习IT的童鞋,在算法中下多大的功夫都不为过

系统-最差适配内存分配算法模拟

问题描述 最差适配内存分配算法模拟 最差适配内存分配算法模拟 1.目的 用程序实现可变分区内存管理过程,并按最差适配算法进行分配. 2.内容 (1)基本思想 可变分区是指系统不预先划分固定分区,而是在装入程序的时候划分内存区 域,使得为程序分配的分区大小恰好等于该程序的需求量,且分区的个数是可变 的.显然可变分区有较大的灵活性,较之固定分区能获得好的内存利用率. (2)数据结构 可变分区管理可以用两种数据结构实现,一种是已分配区表和空闲区表,也 就是用预先定义好的系统空间来存放空间分配信息. 另

Java 理论与实践: 非阻塞算法简介

[本文转载自Java 理论与实践: 非阻塞算法简介]Java 5.0 第一次让使用 Java 语言开发非阻塞算法成为可能,java.util.concurrent 包充分地利用了这个功能.非阻塞算法属于并发算法,它们可以安全地派生它们的线程,不通过锁定派生,而是通过低级的原子性的硬件原生形式 -- 例如比较和交换.非阻塞算法的设计与实现极为困难,但是它们能够提供更好的吞吐率,对生存问题(例如死锁和优先级反转)也能提供更好的防御.在这期的 Java 理论与实践 中,并发性大师 Brian Goet

从零开始_学_数据结构(一)——算法的基本概念

从零开始_学_数据结构(一)--算法   算法的定义: 解决问题的方法. 对于同一个问题,一个好的算法比一个差的算法,效率更高,更节约资源.   For Computer:算法是解决特定问题的求解步骤的描述,在计算机中,表示指令的有限序列,每条指令表示一个或者多个操作. 简单来说,算法就是输入代码,告诉计算机,你应该怎么解决这个问题.     算法的特性: (1)输入和输出.        光算出结果但不输出结果,跟没算没区别:要计算,总得有数据,不然没法计算. (2)有穷性:        能

c#-C# 数据结构 求 好点算法 ,

问题描述 C# 数据结构 求 好点算法 , 如下表, 给出一个任意 找到所有的父节点, ex 输入a1 找到 e,a 节点, id Category FatherID 2 a 0 3 b 0 5 c 2 6 d 2 7 e 2 8 f 6 9 g 5 10 a1 7 11 b1 7 12 c1 3 13 d1 12 15 dw 12 16 de 12 17 fe 16 18 cd 16 19 cg 16 解决方案 with t as ( select id, Category,FatherID,

Java代码实践12306售票算法(二)_java

周五闲来无事,基于上一篇关于浅析12306售票算法(java版)理论,进行了java编码实践供各位读者参考(以下为相关代码的简单描述) 1.订票工具类 1.1初始化一列车厢的票据信息 /** * 生成Ticket信息 * * @param train * @return */ public static List<Ticket> initTicketList(Train train) { List<Ticket> result = new ArrayList<Ticket&g

JAVA实现简单抢红包算法(模拟真实抢红包)_java

闲来无事,最近项目需求要写出用户登录首页来发现金红包,没有限额.我就自己稍微计算了一下如果有限额该怎么写.觉得这样与微信红包差不多.等项目需求完成以后.正好来博客贴一下我自己写的拆红包算法.个人觉得这个算法比较模拟现实抢红包规则.废话少说.先贴代码; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.ut