?? 排課最新版.cpp
字號:
#include <cstdlib>
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <cstring>
#pragma warning(disable : 4786)
using namespace std;
class BadInput{
public:
BadInput(){}
};
template<class T>//堆棧類
class LinkedStack;
template<class T>
class Node{
friend LinkedStack<T>;
private:
T data;
Node<T> *link;
};
template<class T>
class LinkedStack{
public:
LinkedStack(){top=0;}
~LinkedStack(){
//析構函數
Node<T> *next;
while(top){
next=top->link;
delete top;
top=next;}
}
bool IsEmpty() const{return top==0;}
T Top() const{
return top->data;
}
LinkedStack<T>& Add(const T& x){
//添加元素x
Node<T> *p=new Node<T>;
p->data=x;
p->link=top;
top=p;
return *this;
}
LinkedStack<T>& Delete(T& x){
//刪除棧頂元素,并將其送入x
if(IsEmpty()) {cout<<"堆棧以空"<<endl;exit(0);}
x=top->data;
Node<T> *p=top;
top=top->link;
delete p;
return *this;
}
private:
Node<T> *top;//指向棧頂節點
};
template<class T>//函數involve測試向量g中是否包含i,返回一個布爾值
bool involve(vector<T> g,T i){
for(int d=0;d<g.size();d++){
if(g[d]==i)
return true;}
return false;
}
template<class T>//鄰接矩陣實現的有向圖類
class AdjacencyDigraph{
public:
AdjacencyDigraph(int Vertices,T noEdge);
template<class T>
void Delete2DArray(T ** &x,int rows){
for(int i=0;i<rows;i++)
delete [] x[i];
delete [] x;
x=0;
}
template<class T>
void Make2DArray(T ** &x,int rows,int cols){
x=new T * [rows];
for(int i=0;i<rows;i++)
x[i]=new int [cols];
}
~AdjacencyDigraph(){Delete2DArray(a,n+1);}
AdjacencyDigraph<T>& Add(int i,int j,const T& wi){//向鄰接矩陣中加一條邊
if(i<1||j<1||i>n||j>n||i==j||a[i][j]==1)
throw BadInput();
a[i][j]=wi;
e++;
return *this;
}
void InitializePos(){pos=new int [n+1];}
void DeactivatePos(){delete [] pos;}
int Begin(int i);//i的第一個鄰接至的點
int NextVertex(int i);//i的下一個鄰接至的點
bool Topological(int v[]);//測試是否存在拓撲序列,返回一個布爾值
void devide(vector<string> vec,ofstream& outstr,int flag){//把可以放到一個學期的課程放到一起
//分學期
vector<int> *term=new vector<int> [n];
vector<int> g;
int s=0;
int *InDegree=new int [n+1];
for(int f=1;f<=n;f++)
InDegree[f]=0;
InitializePos();
for(int k=1;k<=n;k++){
int u=Begin(k);
while(u){
InDegree[u]++;
u=NextVertex(k);
}
}
while(static_cast<int>(g.size())!=n){
for(int i=1;i<=n;i++){
if((InDegree[i]==0)&&(!involve(g,i))){
term[s].push_back(i);
g.push_back(i);
}
}
for(unsigned int s1=0;s1<term[s].size();s1++){
int u1=Begin(term[s][s1]);
while(u1){
InDegree[u1]--;
u1=NextVertex(term[s][s1]);
}
}
s++;
}
//輸出各個學期課程,這是學期數最少的排法
for(int c=0;c<n;c++){
if(term[c].size()!=0){
outstr<<endl;
outstr<<"第"<<(c+1)<<"個學期課程:\n";
if(flag==1)
cout<<"第"<<(c+1)<<"個學期課程:\n";
for(unsigned int j=0;j<term[c].size();j++){
if(flag==1)
cout<<vec[(term[c][j]-1)]<<" ";
outstr<<vec[(term[c][j]-1)]<<" ";
}
if(flag==1)
cout<<endl;
}
}
DeactivatePos();
delete [] InDegree;
delete [] term;
}
private:
T NoEdge;
int n;
int e;
T **a;
int *pos;
};
template<class T>
AdjacencyDigraph<T>::AdjacencyDigraph(int Vertices,T
noEdge){
n=Vertices;
e=0;
NoEdge=noEdge;
Make2DArray(a,n+1,n+1);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
a[i][j]=NoEdge;
}
template<class T>
int AdjacencyDigraph<T>::Begin(int i){
for(int j=1;j<=n;j++)
if(a[i][j]!=NoEdge){
pos[i]=j;
return j;
}
pos[i]=n+1;
return 0;
}
template<class T>
int AdjacencyDigraph<T>::NextVertex(int i){
for(int j=pos[i]+1;j<=n;j++)
if(a[i][j]!=NoEdge){
pos[i]=j;
return j;
}
pos[i]=n+1;
return 0;
}
template<class T>
bool AdjacencyDigraph<T>::Topological(int v[]){
int *InDegree=new int [n+1];
InitializePos();
for(int f=1;f<=n;f++)
InDegree[f]=0;
for(int r=1;r<=n;r++){
int u=Begin(r);
while(u){
InDegree[u]++;
u=NextVertex(r);
}
}
LinkedStack<int> S;
for(int i=1;i<=n;i++)
if(!InDegree[i]) S.Add(i);
int t=0;
while(!S.IsEmpty()){
int w;
S.Delete(w);
v[t++]=w;
int q=Begin(w);
while(q){
InDegree[q]--;
if(!InDegree[q]) S.Add(q);
q=NextVertex(w);
}
}
DeactivatePos();
delete [] InDegree;
return (t==n);
}
void newline(ifstream& iutstr1)//讀取下一行
{
char symbol;
do{
iutstr1.get(symbol);
}while(symbol!='\n');
}
void new_line()//讀取下一行
{
char symbol;
do{
cin.get(symbol);
}while(symbol!='\n');
}
void redeal(char file[]){//修改已有課程
vector<string> vec;
char course[5]="課程",xianxu[5]="先序",kebiao[5]="課表";
char co[18],xi[18],keb[18];
strcpy(co,file); strcpy(xi,file); strcpy(keb,file);
strcat(co,course); strcat(xi,xianxu); strcat(keb,kebiao);
ifstream iutstr;
iutstr.open(co);
if(iutstr.fail()){
cout<<"文件打開失敗!\n";
exit(1);
}
string next,str("e");
iutstr>>next;
while(!next.empty()){
if(!involve(vec,next))
vec.push_back(next);
else
cout<<"提示: "<<next<<" 是重復輸入,只計算一次。\n";
iutstr>>next;
}
AdjacencyDigraph<int> course1(static_cast<int>(vec.size()),0);
if(vec.size()==0)
cout<<"沒有輸入課程!\n";
ifstream iutstr1;
iutstr1.open(xi);
if(iutstr1.fail()){
cout<<"文件打開失敗!\n";
exit(1);
}
string next1,next2;
for(unsigned int i=0;i<vec.size();i++){
vector<string> m;
iutstr1>>next2;
if(!next2.empty()&&involve(vec,next2)){
iutstr1>>next1;
while(next1!=str&&!next1.empty()){
if((!involve(m,next1))&&(next1!=vec[i])&&(involve(vec,next1))){
m.push_back(next1);
}
else if(involve(m,next1))
cout<<"提示: "<<next1<<" 是重復輸入,只計算一次。\n";
else if(next1==vec[i])
cout<<"提示: "<<next1<<" 不能是自己的先行課,將不予計算。\n";
else if(!involve(vec,next1))
cout<<"提示: "<<next1<<" 不在剛才輸入的課程之內,將不予計算。\n";
iutstr1>>next1;
}
for(int w=0;w<m.size();w++){
for(unsigned int j=0;j<vec.size();j++){
if(m[w]==vec[j]){
course1.Add(j+1,i+1,1);}
}
}
}
else if(!involve(vec,next2)){
cout<<next2<<"不在課程中,不予計算!\n";
//newline(iutstr1);
}
}
ofstream iutstr2;
iutstr2.open(keb);
if(iutstr2.fail()){
cout<<"文件打開失敗!\n";
exit(1);
}
int *v=new int[vec.size()];
if(course1.Topological(v)){
course1.devide(vec,iutstr2,0);
cout<<endl;cout<<endl;
}
else{
cout<<"先序關系中存在環!無法排課。\n";
iutstr2<<"先序關系中存在環!無法排課。\n";
cout<<endl;cout<<endl;
}
delete [] v;
iutstr.close(); iutstr1.close(); iutstr2.close();
}
void deal(char file[]){//處理輸入的待排課程
vector<string> vec;
cout<<"輸入課程清單,結束輸入“e”\n";
string next,str("e");
cin>>next;
while(next!=str){
if(!involve(vec,next))
vec.push_back(next);
else
cout<<"提示: "<<next<<" 是重復輸入,只計算一次。\n";
cin>>next;
}
char course[5]="課程",xianxu[5]="先序",kebiao[5]="課表";
char co[18],xi[18],keb[18];
strcpy(co,file); strcpy(xi,file); strcpy(keb,file);
strcat(co,course); strcat(xi,xianxu); strcat(keb,kebiao);
ofstream outstr;
outstr.open(co);
if(outstr.fail()){
cout<<"文件打開失敗!\n";
exit(1);
}
for(unsigned int is=0;is<vec.size();is++){
outstr<<vec[is]<<" ";
}
new_line();
AdjacencyDigraph<int> course2(static_cast<int>(vec.size()),0);
if(vec.size()==0)
cout<<"沒有輸入課程!\n";
else
cout<<"輸入各個課程的先行課,結束或沒有輸入“e”\n";
ofstream outstr1;
outstr1.open(xi);
if(outstr1.fail()){
cout<<"文件打開失敗!\n";
exit(1);
}
for(unsigned int i=0;i<vec.size();i++){
cout<<vec[i]<<" 的先行課: \n";
outstr1<<vec[i]<<" ";
vector<string> m;
string next1;
cin>>next1;
while(next1!=str){
if((!involve(m,next1))&&(next1!=vec[i])&&(involve(vec,next1))){
m.push_back(next1);
outstr1<<next1<<" ";
}
else if(involve(m,next1))
cout<<"提示: "<<next1<<" 是重復輸入,只計算一次。\n";
else if(next1==vec[i])
cout<<"提示: "<<next1<<" 不能是自己的先行課,將不予計算。\n";
else if(!involve(vec,next1))
cout<<"提示: "<<next1<<" 不在剛才輸入的課程之內,將不予計算。\n";
cin>>next1;
}
outstr1<<str<<" ";
outstr1<<endl;
new_line();
for(int w=0;w<m.size();w++){
for(unsigned int j=0;j<vec.size();j++){
if(m[w]==vec[j]){
course2.Add(j+1,i+1,1);}
}
}
}
ofstream outstr2;
outstr2.open(keb);
if(outstr2.fail()){
cout<<"文件打開失敗!\n";
exit(1);
}
int *v=new int[vec.size()];
if(course2.Topological(v)){
course2.devide(vec,outstr2,1);
cout<<endl;cout<<endl;
}
else{
cout<<"先序關系中存在環!無法排課。\n";
outstr2<<"先序關系中存在環!無法排課。\n";
cout<<endl;cout<<endl;
}
delete [] v;
outstr.close(); outstr1.close(); outstr2.close();
}
void liuout(char co[]){
ifstream instr;
instr.open(co);
while(instr.fail()){
cout<<"不是已有組!\n";
exit(1);
}
char next;
instr.get(next);
while(!instr.eof()){
cout<<next;
instr.get(next);
}
instr.close();cout<<endl;
}
void fileout(char teamname2[]){
char course[5]="課程",xianxu[5]="先序",kebiao[5]="課表";
char co[18],xi[18],keb[18];
strcpy(co,teamname2); strcpy(xi,teamname2); strcpy(keb,teamname2);
strcat(co,course); strcat(xi,xianxu); strcat(keb,kebiao);
cout<<"課程清單:\n";
liuout(co);
cout<<"先序關系(每一行后面都是第一個的先行課,e表示沒有):\n";
liuout(xi);
cout<<"課表:\n";
liuout(keb);
}
int main(){
using namespace std;
vector<string> team;//讀入已有組的組名,以確保可以調用
ifstream inteam;
char ru[10]="組名.txt";
inteam.open(ru);
if(inteam.fail()){
cout<<"不存在組文件!\n";
exit(1);
}
string nextt;
inteam>>nextt;
while(!nextt.empty()){
team.push_back(nextt);
inteam>>nextt;
}
inteam.close();
bool flag1=true;
do{
cout<<endl<<endl<<"1 新建一組 2 調用已有組 3 修改已有組 4 退出\n";
string num,st1("1"),st2("2"),st3("3"),st4("4"),st("e");
cin>>num;
if(num==st1){
cout<<"輸入組名: 退出新建輸“e” ";
char teamname[18];
cin>>teamname;
string na(teamname);
while(involve(team,na)&&na!=st){
cout<<"已有這個組!重輸: 退出新建輸“e” ";
cin>>teamname;
na=teamname;
}
if(!involve(team,na)&&na!=st){
team.push_back(na);
ofstream outteam;
outteam.open(ru,ios::app);
if(outteam.fail()){
cout<<"文件打開失敗!\n";
exit(1);
}
outteam<<endl<<na<<endl;
outteam.close();
deal(teamname);cout<<endl;
}
}
else if(num==st2){
cout<<"輸入組名: 退出調用輸“e” ";
char teamname1[18];
cin>>teamname1;
string sd=teamname1;
while(!involve(team,sd)&&sd!=st){
cout<<"沒有這個組!重輸: 退出調用輸“e” ";
cin>>teamname1;
sd=teamname1;
}
if(involve(team,sd)&&sd!=st)
fileout(teamname1);
}
else if(num==st3){
cout<<"輸入組名: 退出修改輸“e” ";
char teamname2[18];
cin>>teamname2;
string na2(teamname2);
while(!involve(team,na2)&&na2!=st){
cout<<"沒有這個組!重輸: 退出修改輸“e” ";
cin>>teamname2;
na2=teamname2;
}
if(involve(team,na2)&&na2!=st){
team.push_back(na2);
cout<<"請在當前目錄中的 "<<na2<<"課程 和 "<<na2<<"先序 文件修改并保存。\n確定已修改輸入‘e’\n";
string ah,ss("e");
cin>>ah;
while(ah!=ss){
cout<<"確定已修改輸入‘e’:";
cin>>ah;
}
if(ah==ss){
redeal(teamname2);
fileout(teamname2);
}
}
}
else if(num==st4)
flag1=false;
else
cout<<"輸入錯誤!重輸:\n";
}while(flag1==true);
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -