用C语言编程: 要求:其中有些课程可以直接修读,有些课程需要一定的基础知识必须在选了其他一些课程的基础上才能修读。 每个学生所修的学分数的下限是给定的。现在编写一个“学生选课系统”,任意给定一种课程体系(总课程数,课程之间的修读先后制约关系,学生毕业要求修的课程学分数),该系统能帮助学生找出一种选课方案,使得他所选课程数目最少,并获得毕业所需学分,并且必须满足先修课程优先的原则。 具体功能如下: 1.将课程体系存放为课程体系文件 CourseHierarchy.txt ; 2.将课程体系文件 CourseHierarchy.txt 转换左孩子右兄弟二叉树表示; 3.在此基础上对二叉树进行先序、中序、后序遍历。 4. 给出选课方案。
时间: 2024-02-06 15:11:36 浏览: 80
这是一个比较复杂的问题,需要进行多个步骤的实现。下面是一个基本的实现思路,供参考:
1. 定义课程结构体
首先,我们需要定义一个课程结构体,包括课程编号、课程名称、先修课程编号、学分数等信息。
```c
typedef struct course {
int id; // 课程编号
char name[20]; // 课程名称
int pre_course_id; // 先修课程编号
int credit; // 学分数
struct course *child; // 左子节点(下一个先修课程)
struct course *sibling; // 右兄弟节点(同级别下的下一个课程)
} Course;
```
其中,`child`表示下一个先修课程,`sibling`表示同级别下的下一个课程。
2. 读取课程体系文件并转换为二叉树表示
读取课程体系文件 CourseHierarchy.txt,将其中的课程信息存储到课程结构体中,并将课程结构体转换为左孩子右兄弟二叉树表示。
具体实现可以采用递归的方式,对每个课程分别进行处理,并将处理后的结果链接起来。代码如下:
```c
Course* create_course_hierarchy(char *filename) {
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
printf("Failed to open file %s\n", filename);
return NULL;
}
Course *root = NULL;
char line[100];
while (fgets(line, sizeof(line), fp) != NULL) {
int id, pre_course_id, credit;
char name[20];
sscanf(line, "%d %s %d %d", &id, name, &pre_course_id, &credit);
Course *course = (Course*)malloc(sizeof(Course));
course->id = id;
strcpy(course->name, name);
course->pre_course_id = pre_course_id;
course->credit = credit;
course->child = NULL;
course->sibling = NULL;
// 如果是根节点,直接赋值给root
if (pre_course_id == -1) {
root = course;
} else {
// 否则将课程添加到对应的先修课程的child节点下
Course *pre_course = find_course(root, pre_course_id);
if (pre_course == NULL) {
printf("Error: pre_course not found for course %d %s\n", id, name);
free(course);
continue;
}
if (pre_course->child == NULL) {
pre_course->child = course;
} else {
// 如果该先修课程已经有了子节点,向右遍历到最后一个节点,将新课程作为其兄弟节点
Course *sibling = pre_course->child;
while (sibling->sibling != NULL) {
sibling = sibling->sibling;
}
sibling->sibling = course;
}
}
}
fclose(fp);
return root;
}
```
其中,`find_course`函数可以在课程树中查找指定编号的课程节点。具体实现可以采用递归的方式进行遍历,代码如下:
```c
Course* find_course(Course *root, int id) {
if (root == NULL) {
return NULL;
}
if (root->id == id) {
return root;
}
Course *course = find_course(root->child, id);
if (course != NULL) {
return course;
}
return find_course(root->sibling, id);
}
```
3. 对二叉树进行先序、中序、后序遍历
二叉树的先序、中序、后序遍历可以采用递归的方式进行实现。代码如下:
```c
void preorder_traversal(Course *root) {
if (root == NULL) {
return;
}
printf("%d %s\n", root->id, root->name);
preorder_traversal(root->child);
preorder_traversal(root->sibling);
}
void inorder_traversal(Course *root) {
if (root == NULL) {
return;
}
inorder_traversal(root->child);
printf("%d %s\n", root->id, root->name);
inorder_traversal(root->sibling);
}
void postorder_traversal(Course *root) {
if (root == NULL) {
return;
}
postorder_traversal(root->child);
postorder_traversal(root->sibling);
printf("%d %s\n", root->id, root->name);
}
```
4. 给出选课方案
给出选课方案需要实现一个算法,可以采用深度优先搜索或广度优先搜索,遍历课程二叉树,找出最少的选课方案,满足先修课程优先的原则,同时满足学分数的要求。
具体实现可以采用递归的方式进行搜索。对于每个课程,分别考虑选和不选两种情况,如果选了该课程,则需要依次选其先修课程,如果不选,则直接考虑下一个课程。同时,需要记录已选的课程编号和已选的学分数,以及最少的选课方案信息。
代码如下:
```c
void search(Course *root, int selected[], int *selected_count, int *selected_credits, int required_credits, int *min_selected[], int *min_selected_count, int *min_selected_credits) {
if (root == NULL) {
// 搜索到了叶子节点,更新最少的选课方案信息
if (*selected_credits >= required_credits && (*min_selected_count == -1 || *selected_count < *min_selected_count)) {
*min_selected_count = *selected_count;
*min_selected_credits = *selected_credits;
for (int i = 0; i < *selected_count; i++) {
(*min_selected)[i] = selected[i];
}
}
return;
}
// 先不选该课程
search(root->sibling, selected, selected_count, selected_credits, required_credits, min_selected, min_selected_count, min_selected_credits);
// 选该课程
selected[*selected_count] = root->id;
*selected_count += 1;
*selected_credits += root->credit;
search(root->child, selected, selected_count, selected_credits, required_credits, min_selected, min_selected_count, min_selected_credits);
*selected_credits -= root->credit;
*selected_count -= 1;
// 如果该课程已经选了,直接跳过
for (int i = 0; i < *selected_count; i++) {
if (selected[i] == root->id) {
return;
}
}
// 如果该课程没有先修课程,直接选该课程
if (root->pre_course_id == -1) {
selected[*selected_count] = root->id;
*selected_count += 1;
*selected_credits += root->credit;
search(root->sibling, selected, selected_count, selected_credits, required_credits, min_selected, min_selected_count, min_selected_credits);
*selected_credits -= root->credit;
*selected_count -= 1;
return;
}
// 如果该课程有先修课程,依次选其先修课程
Course *pre_course = find_course(root, root->pre_course_id);
while (pre_course != NULL) {
selected[*selected_count] = pre_course->id;
*selected_count += 1;
*selected_credits += pre_course->credit;
pre_course = find_course(root, pre_course->pre_course_id);
}
selected[*selected_count] = root->id;
*selected_count += 1;
*selected_credits += root->credit;
search(root->sibling, selected, selected_count, selected_credits, required_credits, min_selected, min_selected_count, min_selected_credits);
*selected_credits -= root->credit;
*selected_count -= 1;
}
```
最后,在主函数中调用上述函数,获取最少的选课方案,并打印出来即可。
完整代码如下:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct course {
int id; // 课程编号
char name[20]; // 课程名称
int pre_course_id; // 先修课程编号
int credit; // 学分数
struct course *child; // 左子节点(下一个先修课程)
struct course *sibling; // 右兄弟节点(同级别下的下一个课程)
} Course;
Course* create_course_hierarchy(char *filename);
Course* find_course(Course *root, int id);
void preorder_traversal(Course *root);
void inorder_traversal(Course *root);
void postorder_traversal(Course *root);
void search(Course *root, int selected[], int *selected_count, int *selected_credits, int required_credits, int *min_selected[], int *min_selected_count, int *min_selected_credits);
int main() {
Course *root = create_course_hierarchy("CourseHierarchy.txt");
if (root == NULL) {
return -1;
}
printf("Preorder traversal:\n");
preorder_traversal(root);
printf("Inorder traversal:\n");
inorder_traversal(root);
printf("Postorder traversal:\n");
postorder_traversal(root);
int required_credits = 50;
int selected[100];
int selected_count = 0;
int selected_credits = 0;
int *min_selected = (int*)malloc(100 * sizeof(int));
int min_selected_count = -1;
int min_selected_credits = -1;
search(root, selected, &selected_count, &selected_credits, required_credits, &min_selected, &min_selected_count, &min_selected_credits);
printf("Minimum selected courses:\n");
for (int i = 0; i < min_selected_count; i++) {
Course *course = find_course(root, min_selected[i]);
printf("%d %s\n", course->id, course->name);
}
printf("Minimum selected credits: %d\n", min_selected_credits);
return 0;
}
Course* create_course_hierarchy(char *filename) {
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
printf("Failed to open file %s\n", filename);
阅读全文