#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 邻接表
typedef struct node {
int adjvex; //邻接点域
node* Next; //指向下一个邻边节点的指针域
}edgeNode;//邻接表结点
//顶点表结点
typedef struct {
char Date[10]; //课程编号
int Credit; //节点学分(每门课学分)
char name[10];//课程名字
edgeNode* edgenext; //指向邻接表第一个邻边节点的指针域
int InDegree; //课程入度
}vertexnode;
//每学期的学期信息
typedef struct {
int classnumber; //学期数
int termnum; //每学期学分上限 题目为要求8
}Message;
//图
typedef struct {
vertexnode* Vertics; //邻接表域
int VexNum; //节点数 题目要求有11门课程
int ArcNum; //边数
Message* infor; //学期与课程信息
}Graph;
int Locate(char* ch) { //将C1C2C3……等变为1 2 3...
return (2 == strlen(ch)) ? ch[1] - '1' : (ch[1] - '0') * 10 + ch[2] - '1';
}
void search(Graph *G) { //从文件读取课程信息
FILE* fp = fopen("D123.txt", "r");
if (NULL == fp) {
printf("文件路径有误!!!");
exit(1);
}
G->Vertics = (vertexnode*)malloc(sizeof(vertexnode) * G->VexNum);
for (int i = 0; i < G->VexNum; i++)
G->Vertics[i].edgenext = NULL; //初始化
for (int i = 0; i < 11; i++) { //读取课程信息,循环11次
fscanf(fp, "%s%s%d", G->Vertics[i].Date,G->Vertics[i].name, &G->Vertics[i].Credit); //读取课程名称和学分
while ('\n' != fgetc(fp)) { //根据先修课程建立邻接表结点
char str[4];
int s;
fscanf(fp, "%s", str);
s = Locate(str);
if (s < 0 || s > G->VexNum) { //判断课程是否有错误
printf("%s输入错误!\n", G->Vertics[i].Date);
exit(1);
}
edgeNode* p = (edgeNode*)malloc(sizeof(edgeNode)); //更新邻接表结点
p->adjvex = i;
p->Next = G->Vertics[s].edgenext;
G->Vertics[s].edgenext = p;
G->ArcNum++;
}
}
printf("请输入查询课程名称:\n");
//查询课程信息
char name[10];
scanf("%s",&name);
if(strcmp(G->Vertics[0].name,name)==0)
printf("%s %d\n",G->Vertics[0].Date,G->Vertics[0].Credit);
else if(strcmp(G->Vertics[1].name,name)==0)
printf("%s %d\n",G->Vertics[1].Date,G->Vertics[1].Credit);
else if(strcmp(G->Vertics[2].name,name)==0)
printf("%s %d\n",G->Vertics[2].Date,G->Vertics[2].Credit);
else if(strcmp(G->Vertics[3].name,name)==0)
printf("%s %d\n",G->Vertics[3].Date,G->Vertics[3].Credit);
else if(strcmp(G->Vertics[4].name,name)==0)
printf("%s %d\n",G->Vertics[4].Date,G->Vertics[4].Credit);
else if(strcmp(G->Vertics[5].name,name)==0)
printf("%s %d\n",G->Vertics[5].Date,G->Vertics[5].Credit);
else if(strcmp(G->Vertics[6].name,name)==0)
printf("%s %d\n",G->Vertics[6].Date,G->Vertics[6].Credit);
else if(strcmp(G->Vertics[7].name,name)==0)
printf("%s %d\n",G->Vertics[7].Date,G->Vertics[7].Credit);
else if(strcmp(G->Vertics[8].name,name)==0)
printf("%s %d\n",G->Vertics[8].Date,G->Vertics[8].Credit);
else if(strcmp(G->Vertics[9].name,name)==0)
printf("%s %d\n",G->Vertics[9].Date,G->Vertics[9].Credit);
else if(strcmp(G->Vertics[10].name,name)==0)
printf("%s %d\n",G->Vertics[10].Date,G->Vertics[10].Credit);
else{
printf("输入的课程名称不对");
exit(1);
};
fclose(fp);
for (int i = 0; i < G->VexNum; i++) //更新入度
G->Vertics[i].InDegree=0;
for (int i = 0; i < G->VexNum; i++) {
for (edgeNode* p = G->Vertics[i].edgenext; NULL != p; p = p->Next) {
G->Vertics[p->adjvex].InDegree++;
}
}
}
void input(Graph* G) { //输入学期 6或7
G->infor = (Message*)malloc(sizeof(Message)); //初始化指针
printf("请输入需要排课学期总数(输入6或7) \n");
scanf("%d", &G->infor->classnumber);
G->infor->termnum=8;//题目要求每学期学分为8
G->VexNum=11;//题目要求共有11个课程
}
//拓扑排序算法
void Top(vertexnode g[], int n,vertexnode *temp) //用有入度域的aov网进行拓扑排序,输出并存到数组temp中
{
int i, j, k, top, m = 0;
edgeNode* p;
top = -1; //链栈初始化,-1为栈尾
for(i = 0; i < n; i ++) //将入度为0的顶点链接成链栈
if (g[i].InDegree == 0)
{
g[i].InDegree = top;
top = i;
}
while (top != -1) //当链栈非空时
{
j = top; //将栈顶顶点记为j
top = g[top].InDegree; //栈顶指针指向弹出栈后下一个入度为0的顶点
temp[m] = g[j]; //将顶点信息有序保存到数组
m++; //记录已输出的顶点个数
p = g[j].edgenext;
while (p != NULL) //删除顶点j的所有出边
{
k = p->adjvex;
g[k].InDegree--; //将顶点j的邻接边节点k入度减1
if (g[k].InDegree == 0) //若顶点k入度为零则入链栈
{
g[k].InDegree = top;
top = k;
}
p = p->Next; //查找下一个邻接边节点
}
}
if (m < n)
printf("有错误");
}
void Sort1(vertexnode* t, Message* s, int VexNum) //按各学期负担均匀输出并保存教学计划
{
FILE* fp = fopen("D123.txt", "r");
int c = 0; //用于输出课程信息
for (int i = 0; i < s->classnumber; i++)
{
int b = 0; //累计每学期学分
printf("\n第%d个学期的课程为:", i + 1);
for (int j = 0; j < VexNum / s->classnumber; j++)
{
if (b + t[c].Credit <= s->termnum) //判断是否超过最大学分
{
if (c == VexNum)break;
printf("%s ", t[c].Date); //输出课程
fprintf(fp, "%s ", t[c].Date);
b = b + t[c].Credit; //学分累计
c++; //指向下一课程
}
}
if (i < VexNum % s->classnumber) //加入平均后多余的课程
{
if (c == VexNum)break;
printf("%s ", t[c].Date); //输出课程
fprintf(fp, "%s ", t[c].Date);
b = b + t[c].Credit; //学分累计
c++; //指向下一课程
}
}
}
int main() {
Graph G;
search(&G); //从文件读取课程信息并查询
input(&G);//输入学期6或7
vertexnode s[99]; //拓扑排序
Top(G.Vertics, G.VexNum, s); //拓扑排序
Sort1(s, G.infor, G.VexNum); //排列算法
return 0;
}
07-21
07-01
05-11
10-09