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

简介: 本文是针对[数据结构基础系列(11):文件]中的实践项目。【项目】索引文件 有若干学生的成绩数据如下,将这些数据保存到st数组中: 学号 姓名 年龄 性别 语文 数学 英语 1 陈华 20 男 78 90 84 5 张明 21 男 78 68 92 8

本文是针对[数据结构基础系列(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;
}
目录
相关文章
|
7月前
|
存储 算法 关系型数据库
深入理解InnoDB索引数据结构和算法
1. **索引定义**:索引是提升查询速度的有序数据结构,帮助数据库系统快速找到数据。 2. **索引类型**:包括普通索引、唯一索引、主键索引、空间索引和全文索引,每种有特定应用场景。 3. **数据结构**:InnoDB使用B+树作为索引结构,确保所有节点按顺序排列,降低查询时的磁盘I/O。 4. **B+树特性**:所有数据都在叶子节点,非叶子节点仅存储索引,提供高效范围查询。 5. **索引优势**:通过减少查找数据所需的磁盘I/O次数,显著提高查询性能。 **总结:**InnoDB索引通过B+树结构,优化了数据访问,使得查询速度快,尤其适合大数据量的场景。
377 0
深入理解InnoDB索引数据结构和算法
|
7月前
|
存储 关系型数据库 MySQL
7. 索引的底层数据结构了解过嘛 ?
了解MySQL存储引擎,主要对比了MyISAM和InnoDB。MyISAM支持256TB数据,无事务和外键支持;InnoDB支持64TB数据,提供事务和外键功能。
37 0
|
2月前
|
存储 算法 C语言
通义灵码在考研C语言和数据结构中的应用实践 1-5
通义灵码在考研C语言和数据结构中的应用实践,体验通义灵码的强大思路。《趣学C语言和数据结构100例》精选了五个经典问题及其解决方案,包括求最大公约数和最小公倍数、统计字符类型、求特殊数列和、计算阶乘和双阶乘、以及求斐波那契数列的前20项和。通过这些实例,帮助读者掌握C语言的基本语法和常用算法,提升编程能力。
69 4
|
2月前
|
存储
探索数据结构:单链表的实践和应用
探索数据结构:单链表的实践和应用
|
7月前
|
SQL 算法 关系型数据库
【MySQL】索引介绍、索引的数据结构
【MySQL】索引介绍、索引的数据结构
65 0
|
7月前
|
机器学习/深度学习 算法
数据结构小实践
【4月更文挑战第13天】数据结构小实践
58 1
|
7月前
|
存储 SQL 关系型数据库
MySQL 底层数据结构 聚簇索引以及二级索引 Explain的使用
MySQL 底层数据结构 聚簇索引以及二级索引 Explain的使用
69 0
|
7月前
|
机器学习/深度学习 存储 人工智能
数据结构与算法设计:深度解析与实践
数据结构与算法设计:深度解析与实践
135 0
|
7月前
|
存储 关系型数据库 数据库
7. 索引的底层数据结构了解过嘛 ?
了解数据库索引吗?不同存储引擎索引实现各异。MyISAM和InnoDB仅支持B+ TREE索引,而MEMORY/HEAP引擎则兼容HASH和BTREE。
33 0