學(xué)生選課系統(tǒng)
大學(xué)里實(shí)行學(xué)分制。每門課都有一定的學(xué)
分
。每個學(xué)生均需要修滿規(guī)定數(shù)量的課程才能畢業(yè)。其中有些課程可以直接修讀,有些課程需要一定的基礎(chǔ)知識,必須在選了其他一些課程的基礎(chǔ)上才能修讀。例如,《數(shù)據(jù)結(jié)構(gòu)》必須在選修了《高級語言程序設(shè)計》之后才能選修。我們稱《高級語言程序設(shè)計》是《數(shù)據(jù)結(jié)構(gòu)》的“先修課”。在我們的大學(xué)里,假定每門課的直接先修課至多只有一門,兩門課可能存在相同的先修課。例如:
課號
|
先修課號
|
學(xué)分
|
1
|
0
|
1
|
2
|
1
|
1
|
3
|
2
|
3
|
4
|
0
|
3
|
5
|
2
|
4
|
?
上例中,1是2的先修課,即如果要選修2,則1必定被選。
學(xué)生不可能學(xué)完大學(xué)里開設(shè)的所有課程,因此每個學(xué)生必須在入學(xué)時選定自己要學(xué)的課程。每個學(xué)生可選課程的總數(shù)目是給定的。現(xiàn)在請你們小組編寫一個“學(xué)生選課系統(tǒng)”,任意給定一種課程體系(總課程數(shù),課程之間的修讀先后制約關(guān)系,學(xué)生畢業(yè)要求修的課程數(shù)目),該系統(tǒng)能幫助學(xué)生找出一種選課方案,使得他能得到的學(xué)分最多,并且必須滿足先修課程優(yōu)先的原則
具體實(shí)現(xiàn)如下:?
?
1.
????????
將課程體系存放為課程體系文件
CourseHierarchy.txt
;
2.
????????
將課程體系文件
CourseHierarchy.txt
轉(zhuǎn)換左孩子右兄弟二叉樹表示;
3.
????????
在此基礎(chǔ)上對二叉樹進(jìn)行先序、中序、后序遍歷。
4.?????? 給出最多學(xué)分選課方案。
將課程體系文件轉(zhuǎn)換為二叉樹
思想:從
CourseHierarchy.txt
頭部開始掃描,第一個先修課為
0
(即沒有先修課)的課程為整棵二叉樹的根節(jié)點(diǎn)
i
。從
CourseHierarchy.txt
頭部開始掃描,所有
i
的后續(xù)課程作為
i
的左子樹;課程體系中,其他先修課為
0
的節(jié)點(diǎn),及其后續(xù)課程構(gòu)成
i
的右子樹。第一個先修課為
i
的節(jié)點(diǎn)作為
i
的左子樹的根節(jié)點(diǎn)
,從
CourseHierarchy.txt
頭部開始掃描,其他以
i
為先修課的課程構(gòu)成
的右子樹。如此低歸構(gòu)造出課程體系二叉樹。
步驟
1
:從文件
CourseHierarchy.txt
生成課程鏈表
Course_Slist
(參數(shù)表)。
步驟
2
:將指針
CousreSystem_root
指引的
課程鏈表遞歸轉(zhuǎn)換為課程體系二叉樹
步驟
3
:先序輸出二叉樹,以驗(yàn)證生成的二叉樹是否正確
實(shí)現(xiàn)代碼
tree_binary.cpp
// tree_binary.cpp : 定義控制臺應(yīng)用程序的入口點(diǎn)。
//
#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本程序的作用是從文件(文件內(nèi)容可按需求改寫)"<<endl
??<<"??????? 中讀取信息,放到鏈表中,最后生成二叉樹,"<<endl
??<<"??????? 然后先序中序,后續(xù)遍歷二叉樹."<<endl;
?InitList(L);
?cout<<"讀出的文件內(nèi)容:"<<endl;
?OpenFile(L,file_name);
?cout<<"生成鏈表后的結(jié)果:"<<endl;
?PrintLinkLIst(L);
??? CreateBiTree(L,T,0);//生成二叉樹
?cout<<"先序遍歷二叉樹的結(jié)果:";
?PreOrder(T);
?cout<<endl<<"中序遍歷二叉樹的結(jié)果:";
?InOrder(T);
?cout<<endl<<"后序遍歷二叉樹的結(jié)果:";
??? BackOrder(T);
?cout<<endl;
?return 0;
}
?
tree_binaryHF.h
#include"cao.hpp"
//*************************************//
//打開文件,并讀取里面的所有內(nèi)容
Status OpenFile(LinkList&L,char file_name[])//由于這里需要把數(shù)據(jù)插入鏈表中
{
?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)//讀取三個數(shù)據(jù)(課程編碼,學(xué)分,先修課)
?{
??cout<<CNum<<"\t"<<PreScore<<"\t"<<"\t"<<CScore<<endl;?//放到節(jié)點(diǎn)中
??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)//把新得到的結(jié)點(diǎn)插入鏈表,從頭結(jié)點(diǎn)處插入
{
?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)//打印整個鏈表,右指針指向后繼結(jié)點(diǎn),左指針空
{
?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;//生成根節(jié)點(diǎn)
??delet(L,c);//刪除p結(jié)點(diǎn)
??CreateBiTree(L,T->lchild,T->CNumber);//構(gòu)造左子樹
??CreateBiTree(L,T->rchild,T->PreCourse);//構(gòu)造右子樹
?}
?//}
?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)
?{
?? //訪問結(jié)點(diǎn)
? cout<<T->CNumber<<" ";
? PreOrder(T->lchild);?? //遍歷左子樹
? PreOrder(T->rchild);?? //遍歷右子樹
?//cout<<endl;
?}
}?
//中序遍歷的遞歸
void InOrder(LinkList T)
{
?if(T)
?{
? InOrder(T->lchild);?? //遍歷左子樹
?? //訪問結(jié)點(diǎn)
? 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[]);
//打開文件,并且插入節(jié)點(diǎn)
//*************************//
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);//查找節(jié)點(diǎn)
//*********************************************//
void delet(LinkList&L,Status c);//刪除節(jié)點(diǎn)
//*************************************//
Status EmptyLinkList(LinkList L);//檢查鏈表是否為空(沒用到)
//***********************************//
//先序遍歷二叉樹
void PreOrder(LinkList T);
//***********************************//
void InOrder(LinkList T);//中序遍歷二叉樹
//*****************************//
void BackOrder(LinkList T);//后續(xù)遍歷二叉樹
CourceSource.txt
1?2?2
2?0?1
3?0?4
4?2?1
5?7?1
6?7?6
7?2?2
運(yùn)行結(jié)果
先序遍歷二叉樹:3 2 7 6 5 4 1
中序遍歷二叉樹:3 6 5 7 4 1 2
后序遍歷二叉樹:5 6 1 4 7 2 3