数据结构实践——索引文件

本文是针对[数据结构基础系列(11):文件]中的实践项目。

【项目】索引文件

有若干学生的成绩数据如下,将这些数据保存到st数组中:

  学号     姓名    年龄 性别 语文 数学 英语
    1      陈华    20   男   78   90   84
    5      张明    21   男   78   68   92
    8      王英    20   女   86   81   86
    3      刘丽    21   女   78   92   88
    2      许可    20   男   80   83   78
    4      陈军    20   男   78   88   82
    7      马胜    21   男   56   67   75
    6      曾强    20   男   78   89   82

基于这些数据,编程序实现下面的功能:

(1)将st数组中学生记录写入stud.dat文件作为主文件

(2)输出主文件中的学生记录

(3)建立与主文件相对应的索引文件,其中每个记录由两个字段组成:学号和该学生记录在数据文件中的位移量(例:上面列出数据中学号为2的学生许可,其位移量是5。由于本例用定长文件,可以根据位移量计算记录在主文件中的相对地址)。索引文件按学号有序。

(4)输出索引文件中的全部记录

(5)根据用户输入的学号,利用索引文件,用二分查找法找到对应的记录号,再通过主文件输出该记录

(6)是否有想法,将这个项目再扩充了?加大数据量、哈希文件、多关键字文件……

[参考解答]

#include <stdio.h>
#include <string.h>
#include <malloc.h>
#define MaxRec 100          //最多的记录个数
typedef struct Index        //定义索引文件结构
{
    int no;                 //学号
    long offset;            //主文件中的记录号
} Index;
typedef struct
{
    int no;                 //学号
    char name[10];          //姓名
    int age;                //年龄
    char sex[3];            //性别
    int deg1,deg2,deg3;     //课程1-课程3成绩
} StudType;
void InsertSort(Index R[],int n) //采用直接插入排序法对R[0..n-1]按学号递增排序
{
    int i,j;
    Index temp;
    for (i=1; i<n; i++)
    {
        temp=R[i];
        j=i-1;
        while (j>=0 && temp.no<R[j].no)
        {
            R[j+1]=R[j];    //将关键字大于R[i].key的记录后移
            j--;
        }
        R[j+1]=temp;        //在j+1处插入R[i]
    }
}
void CreatIdxFile()         //建立索引文件
{
    FILE *mfile,*idxfile;
    Index idx[MaxRec];
    StudType st;
    int n=0,i;
    if ((mfile=fopen("stud.dat","rb"))==NULL)
    {
        printf("  提示:不能打开主文件\n");
        return;
    }
    if ((idxfile=fopen("index.dat","wb"))==NULL)
    {
        printf("  提示:不能建立索引文件\n");
        return;
    }
    i=0;
    while ((fread(&st,sizeof(StudType),1,mfile)))
    {
        idx[i].no=st.no;
        idx[i].offset=++n;
        i++;
    }
    InsertSort(idx,n);  //对idx数组按no值排序
    rewind(idxfile);
    for (i=0; i<n; i++)
        fwrite(&idx[i],sizeof(Index),1,idxfile);
    fclose(mfile);
    fclose(idxfile);
    printf("  提示:索引文件建立完毕\n");
}
void OutputMainFile()   //输出主文件全部记录
{
    FILE *mfile;
    StudType st;
    int i=1;
    if ((mfile=fopen("stud.dat","rb"))==NULL)
    {
        printf("  提示:不能读主文件\n");
        return;
    }
    printf("                ----学生成绩表----\n");
    printf("记录号  学号     姓名   年龄 性别 语文 数学 英语\n");
    while ((fread(&st,sizeof(StudType),1,mfile))==1)
    {
        printf("%6d%5d%10s%6d%5s%5d%5d%5d\n",i,st.no,st.name,st.age,st.sex,st.deg1,st.deg2,st.deg3);
        i++;
    }
    fclose(mfile);
}
void OutputIdxFile()    //输出索引文件全部记录
{
    FILE *idxfile;
    Index irec;
    printf("     ----学生索引表----\n");
    printf("\t学号  记录号\n");
    if ((idxfile=fopen("index.dat","rb"))==NULL)
    {
        printf("  提示:不能读索引文件\n");
        return;
    }
    while ((fread(&irec,sizeof(Index),1,idxfile))==1)
        printf("\t%5d%6ld\n",irec.no,irec.offset);
    fclose(idxfile);
}
void ReadIndexFile(Index idx[MaxRec],int &n)    //读索引文件数据存入idx数组中
{
    int j;
    FILE *idxfile;
    if ((idxfile=fopen("index.dat","rb"))==NULL)
    {
        printf("  提示:索引文件不能打开\n");
        return;
    }
    fseek(idxfile,0,2);
    j=ftell(idxfile);       //j求出文件长度
    rewind(idxfile);
    n=j/sizeof(Index);      //n求出文件中的记录个数
    fread(idx,sizeof(Index),n,idxfile);
    fclose(idxfile);
}
int SearchNum(Index idx[],int n,int no) //在含有n个记录的索引文件idx中查找学号为no的记录对应的记录号
{
    int mid,low=0,high=n-1;
    while (low<=high)                   //二分查找
    {
        mid=(low+high)/2;
        if (idx[mid].no>no)
            high=mid-1;
        else if (idx[mid].no<no)
            low=mid+1;
        else    //idx[mid].no==no
            return idx[mid].offset;
    }
    return -1;
}
void FindStudent()          //输出指定学号的记录
{
    int no;
    FILE *mfile;
    Index idx[MaxRec];
    StudType st;
    int i,n;
    if ((mfile=fopen("stud.dat","rb+"))==NULL)
    {
        printf("  提示:主文件中没有任何记录\n");
        return;
    }
    ReadIndexFile(idx,n);       //读取索引数组idx
    printf("输入学号:");
    scanf("%d",&no);
    i=SearchNum(idx,n,no);      //在idx中查找
    if (i==-1)
        printf("  提示:学号%d不存在\n",no);
    else
    {
        fseek(mfile,(i-1)*sizeof(StudType),SEEK_SET); //由记录号直接跳到主文件中对应的记录
        fread(&st,sizeof(StudType),1,mfile);
        printf("%5d%10s%6d%5s%5d%5d%5d\n",st.no,st.name,st.age,st.sex,st.deg1,st.deg2,st.deg3);
    }
    fclose(mfile);
}
void WriteFile(StudType st[], int n)  //将st数组中的n个学生记录写入stud.dat文件中
{
    int i;
    FILE *fp;
    if ((fp=fopen("stud.dat","wb"))==NULL)
    {
        printf("\t提示:不能创建stud.dat文件\n");
        return;
    }
    for (i=0; i<n; i++)
        fwrite(&st[i],1,sizeof(StudType),fp);
    fclose(fp);
    printf("  提示:文件stud.dat创建完毕\n");
}
int main()
{
    int n=8,sel;        //n为实际学生人数
        StudType st[]= {{1,"陈华",20,"男",78,90,84},
        {5,"张明",21,"男",78,68,92},
        {8,"王英",20,"女",86,81,86},
        {3,"刘丽",21,"女",78,92,88},
        {2,"许可",20,"男",80,83,78},
        {4,"陈军",20,"男",78,88,82},
        {7,"马胜",21,"男",56,67,75},
        {6,"曾强",20,"男",78,89,82}
    };
    printf("建立主文件\n");
    WriteFile(st,n);        //建立主文件
    do
    {
        printf("1:输出主文件 2:建索引文件 3:输出索引文件 4:按学号查找 0:退出:");
        scanf("%d",&sel);
        switch(sel)
        {
        case 1:
            OutputMainFile();
            break;
        case 2:
            CreatIdxFile();
            break;
        case 3:
            OutputIdxFile();
            break;
        case 4:
            FindStudent();
            break;
        }
    }
    while (sel!=0);
    return 0;
}
时间: 2024-10-29 19:08:09

数据结构实践——索引文件的相关文章

数据结构实践——操作文件

本文是针对[数据结构基础系列(11):文件]中的实践项目. [项目1]操作文件 有若干学生的成绩数据如下,将这些数据保存到st数组中: 学号 姓名 年龄 性别 语文 数学 英语 1 陈华 20 男 78 90 84 5 张明 21 男 78 68 92 8 王英 20 女 86 81 86 3 刘丽 21 女 78 92 88 2 许可 20 男 80 83 78 4 陈军 20 男 78 88 82 7 马胜 21 男 56 67 75 基于这些数据,编程序实现下面的功能: (1)将st数组中

Solr4.8.0源码分析(10)之Lucene的索引文件(3)

Solr4.8.0源码分析(10)之Lucene的索引文件(3) 1. .si文件 .si文件存储了段的元数据,主要涉及SegmentInfoFormat.java和Segmentinfo.java这两个文件.由于本文介绍的Solr4.8.0,所以对应的是SegmentInfoFormat的子类Lucene46SegmentInfoFormat. 首先来看下.si文件的格式 头部(header) 版本(SegVersion) doc个数(SegSize) 是否符合文档格式(IsCompoundF

Solr4.8.0源码分析(8)之Lucene的索引文件(1)

Solr4.8.0源码分析(8)之Lucene的索引文件(1) 题记:最近有幸看到觉先大神的Lucene的博客,感觉自己之前学习的以及工作的太为肤浅,所以决定先跟随觉先大神的博客学习下Lucene的原理.由于觉先大神主要介绍的是Lucene3.X系的,那我就根据源码以及结合觉先大神的来学习下4.X系的.内容可能会有些变化,且加入下我个人的理解. http://www.cnblogs.com/forfuture1978/archive/2009/12/14/1623597.html 一. 基本类型

kafka-Message、日志和索引文件、消费组、rebalance

记录下和kafka相关的Message.日志文件.索引文件.consumer记录消费的offset相关内容,文中很多理解参考文末博文.书籍还有前辈. kafka中的消息 kafka中的消息Message,在V1版本中是如下部分组成,主要关系key和value. (1)key:当需要将消息写入到某个topic下的指定partition分区时,需要给定key的值. (2)value:实际消息内容保存在这里. (3)其他均是消息的元数据,一般不用关心,对用户来说是透明的. 为了保存这些消息数据,kaf

十分钟入门pandas数据结构和索引

pandas数据结构和索引是入门pandas必学的内容,这里就详细给大家讲解一下,看完本篇文章,相信你对pandas数据结构和索引会有一个清晰的认识. 一.数据结构介绍 在pandas中有两类非常重要的数据结构,即序列Series和数据框DataFrame.Series类似于numpy中的一维数组,除了通吃一维数组可用的函数或方法,而且其可通过索引标签的方式获取数据,还具有索引的自动对齐功能:DataFrame类似于numpy中的二维数组,同样可以通用numpy数组的函数和方法,而且还具有其他灵

ubuntu 搭建maven库 2.14.2-01并配置离线索引文件

前提 安装JDK版本1.8或者以上 1 下载 http://www.sonatype.org/nexus/archived/  选择相应的版本 2 复制到/usr/local 下解压 sudo cp nexus-2.14.2-01-bundle.tar.gz /usr/local sudo tar -xzvf nexus-2.14.2-01-bundle.tar.gz 3 设置运行权限 sudo  chown  用户名 nexus-2.14.2-01 sudo chown 用户名 sonatyp

Solr4.8.0源码分析(12)之Lucene的索引文件(5)

Solr4.8.0源码分析(12)之Lucene的索引文件(5) 1. 存储域数据文件(.fdt和.fdx) Solr4.8.0里面使用的fdt和fdx的格式是lucene4.1的.为了提升压缩比,StoredFieldsFormat以16KB为单位对文档进行压缩,使用的压缩算法是LZ4,由于它更着眼于速度而不是压缩比,所以它能快速压缩以及解压. 1.1 存储域数据文件(.fdt) 真正保存存储域(stored field)信息的是fdt文件,该文件存放了压缩后的文档,按16kb或者更大的模块大

Solr4.8.0源码分析(11)之Lucene的索引文件(4)

Solr4.8.0源码分析(11)之Lucene的索引文件(4) 1. .dvd和.dvm文件 .dvm是存放了DocValue域的元数据,比如DocValue偏移量. .dvd则存放了DocValue的数据. 在Solr4.8.0中,dvd以及dvm用到的Lucene编码格式是Lucene45DocValuesFormat.跟之前的文件格式类似,它分别包含Lucene45DocValuesProducer 和Lucene45DocValuesConsumer来实现该文件的读和写. 1 @Ove

Solr4.8.0源码分析(9)之Lucene的索引文件(2)

Solr4.8.0源码分析(9)之Lucene的索引文件(2) 一. Segments_N文件 一个索引对应一个目录,索引文件都存放在目录里面.Solr的索引文件存放在Solr/Home下的core/data/index目录中,一个core对应一个索引. Segments_N例举了索引所有有效的segments信息以及删除的具体信息,一个索引可以有多个Segments_N,但是有效的往往总是N最大的那个,为什么会出现多个segments_N,主要是由于暂时无法删除它们或者有indexwriter