基于哈夫曼编码的文件压缩解压+拓扑实现学生选课排课系统

本文介绍了如何使用哈夫曼编码实现文件压缩和解压,以及如何利用拓扑排序算法管理课程信息,包括读取课程数据、选课操作和生成课程排课顺序。
摘要由CSDN通过智能技术生成

前言:

  1. 程序运行环境: DevC++
  2. 文件组成说明:头文件main.h:包含结构体定义,函数声明、源文件Huffman.cpp:总代码,数据文件Optional-course.txt选修课课程信息,Require-course.txt必修课课程信息、说明文件readme.txt,图片文件等。

一、基于哈夫曼编码的文件压缩解压

要实现的功能包括:构建哈夫曼树,生成字符的哈夫曼编码,压缩文件,解压文件。压缩文件功能为:系统读取输入文件,通过哈夫曼编码将其压缩,并输出压缩后的文件。解压文件功能为:系统读取已压缩的文件,使用对应字符的哈夫曼译码将其解压为原始文件,并输出解压后的文件。

//定义哈夫曼树数据结构
struct HuffmanNode 
{ 
	unsigned char data;            //定义一个字符
    long frequency;                 //字符出现频率
    long parent,leftch,rightch;        //创建哈夫曼树 
    char bits[256];             //哈夫曼结点
}header[512],tmp; 
//读取ifp文件内容 
	while(!feof(ifp))               
    { 
        fread(&c,1,1,ifp);           //按位读取文件
        header[c].frequency++;           //记录文件的字符总数
        flength++; 
    } 
    flength = -1;                   
    header[c].frequency = -1;             //读取文件结束
	//构造哈弗曼树,初始结点的设置
	for(i=0;i<512;i++)                
    { 
        if(header[i].frequency != 0) 
			header[i].data = (unsigned char)i; 
        else 
			header[i].data = 0; 
		header[i].parent = -1; 
		header[i].leftch = header[i].rightch = -1; 
    } 
    //按结点出现的次数排序
	for(i=0;i<256;i++)         
    { 
        for(j=i+1;j<256;j++) 
    	{ 
            if(header[i].frequency < header[j].frequency) 
        	{ 
                tmp=header[i]; 
                header[i] = header[j]; 
                header[j] = tmp; 
        	} 
    	} 
    } 
	//统计不同字符的数量
	for(i=0;i<256;i++) 
		if(header[i].frequency==0) 
			break; 
    n=i; 
    m=2*n-1; 
    for(i=n;i<m;i++) 
    { 
        min1=999999999; 
        for(j=0;j<i;j++) 
    	{ 
            if(header[j].parent!=-1) 
                continue; 
            if(min1>header[j].frequency) 
        	{ 
                pt1=j; 
                min1=header[j].frequency; 
                continue; 
        	} 
    	} 
        header[i].frequency=header[pt1].frequency; 
        header[pt1].parent=i; 
        header[i].leftch=pt1; 
        min1=999999999; 
        for(j=0;j<i;j++) 
    	{ 
            if(header[j].parent!=-1)
                continue; 
            if(min1>header[j].frequency) 
        	{ 
                pt1=j; 
                min1=header[j].frequency; 
                continue; 
        	} 
    	} 
        header[i].frequency+=header[pt1].frequency; 
        header[i].rightch=pt1; 
        header[pt1].parent=i; 
    }
//构造哈夫曼树,设置字符编码
    for(i=0;i<n;i++) 
    { 
        f = i; 
        header[i].bits[0] = 0; 
        while(header[f].parent != -1) 
    	{ 
        	j = f; 
            f = header[f].parent; 
            if(header[f].leftch==j) 
        	{ 
                j = strlen(header[i].bits); 
                memmove(header[i].bits+1,header[i].bits,j+1); 
                header[i].bits[0]='0'; 
        	} 
        	else 
        	{ 
                j=strlen(header[i].bits); 
                memmove(header[i].bits+1,header[i].bits,j+1); 
                header[i].bits[0]='1'; 
        	} 
    	} 
    } 

二、拓扑排序实现学生选课排课

功能包括:课程信息管理、选课管理、输出已选课程列表、课程排课顺序。要实现的功能包括:从指定文件读取课程信息(包括课程名称、课程编号、课程学分以及所需选修课程等信息)、将课程信息用带入度域的邻接表存储下来;从键盘读取拟添加的选修课信息、删除已选的选修课、输出已选修课程列表、统计选修课总学分、将已选课程列表输出到屏幕上、统计不同类型课程的学分数值;使用拓扑排序算法对已选课程进行排序,生成课程的排课顺序并输出。

// 定义课程结构体
typedef struct Course {
    char code[MAX_NAME];
    char name[MAX_NAME];
    float credit;
    int numPrerequisites;
    struct Course* prerequisites[MAX_COURSES];
} Course;
// 读取课程信息
void readCourseInfo(char* filename, Course* courses, int* numCourses) 
{
    FILE* file = fopen(filename, "r");
    if (file == NULL) {
        printf("无法打开文件 %s\n", filename);
        exit(1);
    }

    char line[100];
    while (fgets(line, sizeof(line), file)) {
        sscanf(line, "%s %s %f", courses[*numCourses].code, courses[*numCourses].name, &courses[*numCourses].credit);

        // 解析先修课程
        char prerequisites[100];
        sscanf(line, "%*s %*s %*f %[^\n]", prerequisites);
        char* prereq = strtok(prerequisites, " ,");
        while (prereq != NULL) {
            for (int i = 0; i < *numCourses; i++) {
                if (strcmp(prereq, courses[i].code) == 0) {
                    courses[*numCourses].prerequisites[courses[*numCourses].numPrerequisites] = &courses[i];
                    courses[*numCourses].numPrerequisites++;
                }
            }
            prereq = strtok(NULL, " ,");
        }

        // 添加对选修课学分的判断
        if (courses[*numCourses].credit >= 20) {
            electiveCourses[numElectiveCourses++] = courses[*numCourses];
        }

        (*numCourses)++;
    }

    fclose(file);
}

三、最终效果 

写在最后:

欢迎大家一起交流讨论,需要源码可以私我或者给我留评论!

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值