⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 排课最新版.cpp

📁 排课表
💻 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 + -