學生選課系統
大學里實行學分制。每門課都有一定的學
分
。每個學生均需要修滿規定數量的課程才能畢業。其中有些課程可以直接修讀,有些課程需要一定的基礎知識,必須在選了其他一些課程的基礎上才能修讀。例如,《數據結構》必須在選修了《高級語言程序設計》之后才能選修。我們稱《高級語言程序設計》是《數據結構》的“先修課”。在我們的大學里,假定每門課的直接先修課至多只有一門,兩門課可能存在相同的先修課。例如:
課號
|
先修課號
|
學分
|
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 閱讀(1381)
評論(0) 編輯 收藏 所屬分類:
數據結構與算法設計