学生选课系统
大学里实行学分制。每门课都有一定的学
分
。每个学生均需要修满规定数量的课程才能毕业。其中有些课程可以直接修读,有些课程需要一定的基础知识,必须在选了其他一些课程的基础上才能修读。例如,《数据结构》必须在选修了《高级语言程序设计》之后才能选修。我们称《高级语言程序设计》是《数据结构》的“先修课”。在我们的大学里,假定每门课的直接先修课至多只有一门,两门课可能存在相同的先修课。例如:
课号
|
先修课号
|
学分
|
1
|
0
|
1
|
2
|
1
|
1
|
3
|
2
|
3
|
4
|
0
|
3
|
5
|
2
|
4
|
上例中,1是2的先修课,即如果要选修2,则1必定被选。
学生不可能学完大学里开设的所有课程,因此每个学生必须在入学时选定自己要学的课程。每个学生可选课程的总数目是给定的。现在请你们小组编写一个“学生选课系统”,任意给定一种课程体系(总课程数,课程之间的修读先后制约关系,学生毕业要求修的课程数目),该系统能帮助学生找出一种选课方案,使得他能得到的学分最多,并且必须满足先修课程优先的原则
具体实现如下:
1.
将课程体系存放为课程体系文件
CourseHierarchy.txt
;
2.
将课程体系文件
CourseHierarchy.txt
转换左孩子右兄弟二叉树表示;
3.
在此基础上对二叉树进行先序、中序、后序遍历。
4. 给出最多学分选课方案。
将课程体系文件转换为二叉树
思想:从
CourseHierarchy.txt
头部开始扫描,第一个先修课为
0
(即没有先修课)的课程为整棵二叉树的根节点
i
。从
CourseHierarchy.txt
头部开始扫描,所有
i
的后续课程作为
i
的左子树;课程体系中,其他先修课为
0
的节点,及其后续课程构成
i
的右子树。第一个先修课为
i
的节点作为
i
的左子树的根节点
,从
CourseHierarchy.txt
头部开始扫描,其他以
i
为先修课的课程构成
的右子树。如此低归构造出课程体系二叉树。
步骤
1
:从文件
CourseHierarchy.txt
生成课程链表
Course_Slist
(参数表)。
步骤
2
:将指针
CousreSystem_root
指引的
课程链表递归转换为课程体系二叉树
步骤
3
:先序输出二叉树,以验证生成的二叉树是否正确
实现代码
tree_binary.cpp
// tree_binary.cpp : 定义控制台应用程序的入口点。
//
#pragma once
#include <iostream>
#include <tchar.h>
//#include<fstream>
//#include<iostream>
//#include<cstdlib>
#include"tree_binaryHF.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
char file_name[20]="CourseHierarchy.txt";
LinkList L;//链表的头指针
LinkList T;//树的根
cout<<"\t本程序的作用是从文件(文件内容可按需求改写)"<<endl
<<" 中读取信息,放到链表中,最后生成二叉树,"<<endl
<<" 然后先序中序,后续遍历二叉树."<<endl;
InitList(L);
cout<<"读出的文件内容:"<<endl;
OpenFile(L,file_name);
cout<<"生成链表后的结果:"<<endl;
PrintLinkLIst(L);
CreateBiTree(L,T,0);//生成二叉树
cout<<"先序遍历二叉树的结果:";
PreOrder(T);
cout<<endl<<"中序遍历二叉树的结果:";
InOrder(T);
cout<<endl<<"后序遍历二叉树的结果:";
BackOrder(T);
cout<<endl;
return 0;
}
tree_binaryHF.h
#include"cao.hpp"
//*************************************//
//打开文件,并读取里面的所有内容
Status OpenFile(LinkList&L,char file_name[])//由于这里需要把数据插入链表中
{
int CNum,CScore,PreScore;
ifstream in_stream;
in_stream.open(file_name);
if(in_stream.fail())//if the file is not opened successfully
{
cout<<"can't open the file of "<<file_name<<endl;
exit(0);
}
//i
cout<<"CNum"<<"\t"<<"PreScore"<<"\t"<<"CScore"<<endl;
while(in_stream>>CNum>>PreScore>>CScore)//读取三个数据(课程编码,学分,先修课)
{
cout<<CNum<<"\t"<<PreScore<<"\t"<<"\t"<<CScore<<endl; //放到节点中
LinkInsert(L,CNum,PreScore,CScore);//insert the node to the linklist L
}
in_stream.close();
return OK;
}
Status InitList(LinkList &L)
{
L= (LinkList)malloc(sizeof(LNode));
if(!L)
return ERROR;
L->lchild=NULL;
L->rchild=NULL;
L->CNumber=0;
L->CScore=0;
L->PreCourse=0;
return OK;
}
Status LinkInsert(LinkList &L,Status CNum,Status PreCourse,Status CScore)//把新得到的结点插入链表,从头结点处插入
{
LinkList p;
p=(LinkList)malloc(sizeof(LNode));
if(!p)
return ERROR;
p->CNumber=CNum;
p->CScore=CScore;
p->PreCourse=PreCourse;
p->lchild=NULL;
p->rchild=L->rchild;
L->rchild=p;
return OK;
}
Status PrintLinkLIst(LinkList &L)//打印整个链表,右指针指向后继结点,左指针空
{
LinkList p;
p=L->rchild;
while(p)
{
cout<<p->CNumber<<"\t"<<p->PreCourse<<"\t"<<"\t"<<p->CScore<<endl;
p=p->rchild;
}
return OK;
}
Status CreateBiTree(LinkList &L,LinkList&T,Status c)
{
LinkList p;
//while(!EmptyLinkList(L))
//{
if(!(p=Serach(L,c)))
T=NULL;
else
{
T=p;//生成根节点
delet(L,c);//删除p结点
CreateBiTree(L,T->lchild,T->CNumber);//构造左子树
CreateBiTree(L,T->rchild,T->PreCourse);//构造右子树
}
//}
return OK;
}
LinkList Serach(LinkList &L,Status c)
{
LinkList head,next;
head=L;
next=head->rchild;
while(next&&(next->PreCourse!=c))
{
head=next;
next=next->rchild;
}
if(next==NULL)
return NULL;//没有找到
else//找到了
return next;
}
void delet(LinkList &L,Status c)
{
LinkList head,next;
head=L;
next=head->rchild;
while(next&&(next->PreCourse!=c))
{
head=next;
next=next->rchild;
}
head->rchild=next->rchild;
//free(next);
}
Status EmptyLinkList(LinkList L)
{
if(L->rchild=NULL)
return OK;
else
return ERROR;
}
//先序遍历的递归
void PreOrder(LinkList T)
{
if(T)
{
//访问结点
cout<<T->CNumber<<" ";
PreOrder(T->lchild); //遍历左子树
PreOrder(T->rchild); //遍历右子树
//cout<<endl;
}
}
//中序遍历的递归
void InOrder(LinkList T)
{
if(T)
{
InOrder(T->lchild); //遍历左子树
//访问结点
cout<<T->CNumber<<" ";
InOrder(T->rchild); //遍历右子树
}
}
//后序遍历的递归
void BackOrder(LinkList T)
{
if(T)
{
BackOrder(T->lchild); //遍历左子树
BackOrder(T->rchild); //遍历右子树
cout<<T->CNumber<<" ";
}
}
cao.hpp
#include<fstream>
#include<iostream>
#include<cstdlib>
using namespace std;
typedef int Status;
#define OK 1
#define ERROR 0
typedef struct LNode
{
struct LNode *lchild;
struct LNode *rchild;
Status CNumber;
Status CScore;
Status PreCourse;
}LNode,*LinkList;
Status OpenFile(LinkList&L,char file_name[]);
//打开文件,并且插入节点
//*************************//
LinkInsert(LinkList &L,Status CNum,Status CScore,Status PreScore);
//insert the node to the linklist L
//*************************//
Status InitList(LinkList &L);//初始化链表
//****************************************//
Status PrintLinkList(LinkList &L);//输出链表
//********************************//
LinkList Serach(LinkList &L,Status c);//查找节点
//*********************************************//
void delet(LinkList&L,Status c);//删除节点
//*************************************//
Status EmptyLinkList(LinkList L);//检查链表是否为空(没用到)
//***********************************//
//先序遍历二叉树
void PreOrder(LinkList T);
//***********************************//
void InOrder(LinkList T);//中序遍历二叉树
//*****************************//
void BackOrder(LinkList T);//后续遍历二叉树
CourceSource.txt
1 2 2
2 0 1
3 0 4
4 2 1
5 7 1
6 7 6
7 2 2
运行结果
先序遍历二叉树:3 2 7 6 5 4 1
中序遍历二叉树:3 6 5 7 4 1 2
后序遍历二叉树:5 6 1 4 7 2 3
posted on 2006-10-29 14:57
matthew 阅读(1370)
评论(0) 编辑 收藏 所属分类:
数据结构与算法设计