任务描述
本关任务:学生需要选修一定数目的课程才能毕业,这些课程之间有先导关系。假设所有的课程在每学期都能提供学生选修,学生每学期可以选修的课程不限。给出一些课程以及课程之间的关系,安排一个计划,用最少的学期修完所有的课程。
问题解析
可以将该问题转化成拓扑排序问题,在拓扑排序时按批输出满足条件的结点,即入度为0的结点。具体流程如下:
- 每一批就是一个学期可以选修的课程;
- 可以设置两个队列q1和q2,一个队列保存一个学期的课。
- 没有先导课程的课在第一学期都可以选,因此先让入度为0的所有结点进入队列q1,这是第一学期可以选修的课。
- 将q1的元素依次出队,将它们的后继的入度减1。
- 如果后继的入度减到0,则让它进入队列q2,表示是第二学期可以选修的课。
- 将q2中的元素依次出栈,将它们后继的入度减1。
- 如果后继结点的入度减到了0,则让它进入队列q1,表示第三学期可以选修的课。
- 重复上述过程,直到所有的课程都已经被选修。
编程要求
根据提示,在编辑器补充代码,完成课程选修问题。
#include <iostream>
using namespace std;
#include"LQueue.h"
template<class TypeOfEdge>
class graph{
public:
virtual bool insert(int u,int v,TypeOfEdge w)=0;
virtual bool remove(int u,int v)=0;
virtual bool exist(int u,int v) const=0;
int numOfVer() const{return Vers;}
int numOfEdge() const{return Edges;}
protected:
int Vers,Edges;
};
template<class TypeOfVer,class TypeOfEdge>
class adjListGraph:public graph<TypeOfEdge>{
public:
int Vers,Edges;
adjListGraph(int vSize,const TypeOfVer d[]);
bool insert(int u,int v,TypeOfEdge w);
bool remove(int u,int v);
bool exist(int u,int v)const;
~adjListGraph();
void findLessTime()const;
private:
struct edgeNode{
int end;
TypeOfEdge weight;
edgeNode *next;
edgeNode(int e,TypeOfEdge w,edgeNode *n=NULL){end=e;weight=w;next=n;}
};
struct verNode{
TypeOfVer ver;
edgeNode *head;
verNode(edgeNode *h=NULL){head=h;}
};
verNode *verList;
};
//构造函数和折构函数
template<class TypeOfVer,class TypeOfEdge>
adjListGraph<TypeOfVer,TypeOfEdge> :: adjListGraph(int vSize,const TypeOfVer d[])
{
Vers=vSize;
verList=new verNode[vSize];
for(int i=0;i<Vers;++i)verList[i].ver=d[i];
}
template<class TypeOfVer,class TypeOfEdge>
adjListGraph<TypeOfVer,TypeOfEdge> ::~adjListGraph(){
int i;
edgeNode *p;
for(i=0;i<Vers;++i)
while((p=verList[i].head)!=NULL){
verList[i].head=p->next;
delete p;
}
delete[]verList;
}
template<class TypeOfVer,class TypeOfEdge>
bool adjListGraph<TypeOfVer,TypeOfEdge> :: insert(int u,int v,TypeOfEdge w){
verList[u].head=new edgeNode(v,w,verList[u].head);
++Edges;
return true;
}
template<class TypeOfVer,class TypeOfEdge>
bool adjListGraph<TypeOfVer,TypeOfEdge> :: remove(int u,int v){
edgeNode *p=verList[u].head, *q;
if(p==NULL)return false;
if(p->end==v){
verList[u].head=p->next;
delete p;--Edges;
return true;
}
while(p->next!=NULL&&p->next->end!=v)p=p->next;
if(p->next==NULL)return false;
q=p->next;p->next=q->next;delete q;
--Edges;
return true;
}
template<class TypeOfVer,class TypeOfEdge>
bool adjListGraph<TypeOfVer,TypeOfEdge> :: exist(int u,int v)const{
edgeNode *p=verList[u].head;
while(p!=NULL&&p->end!=v)p=p->next;
if(p==NULL)return false;else return true;
}
template<class TypeOfVer,class TypeOfEdge>
void adjListGraph<TypeOfVer,TypeOfEdge>::findLessTime()const
//Insert Your Code
{
cout<<"课程安排为:"<<endl;
LQueue<int>q1,q2;
edgeNode*p;
int current,semester=1;
int *inDegree=new int [Vers];
for(int i=0;i<Vers;++i)
{
inDegree[i]=0;
}
for( int i=0;i<Vers;++i)
for(p=verList[i].head;p!=NULL;p=p->next)
++inDegree[p->end];
for(int i=0;i<Vers;++i)
if(inDegree[i]==0) q1.enQueue(i);
while(true){
if(semester==1)cout<<"第"<<semester<<"学期的课为:";
while(!q1.isEmpty())
{
current=q1.deQueue();
cout<<verList[current].ver<<" ";
for(p=verList[current].head;p!=NULL;p=p->next)
if(--inDegree[p->end]==0)
q2.enQueue(p->end);
}
cout<<endl;
if(q2.isEmpty()) break;
++semester;
cout<<"第"<<semester<<"学期的课为:";
while(!q2.isEmpty())
{
current=q2.deQueue();
cout<<verList[current].ver<<" ";
for(p=verList[current].head;p!=NULL;p=p->next)
if(--inDegree[p->end]==0)
q1.enQueue(p->end);
}
if(q1.isEmpty())break;
++semester;
cout<<endl;
if(semester>1)
{cout<<"第"<<semester<<"学期的课为:";}
}
/*//尝试用1个队列解决问题,fail
template<class TypeOfVer,class TypeOfEdge>
void adjListGraph<TypeOfVer,TypeOfEdge>::findLessTime()const
//Insert Your Code
{
cout<<"课程安排为:"<<endl;
LQueue<int>q1,q2;
edgeNode*p;
int current,semester=1;
int *inDegree=new int [Vers];
for(int i=0;i<Vers;++i)
{
inDegree[i]=0;
}
for( int i=0;i<Vers;++i)
for(p=verList[i].head;p!=NULL;p=p->next)
++inDegree[p->end];
for(int i=0;i<Vers;++i)
if(inDegree[i]==0) q1.enQueue(i);
while(true){
cout<<"第"<<semester<<"学期的课为:";
while(!q1.isEmpty())
{
current=q1.deQueue();
cout<<verList[current].ver<<" ";
}
for(p=verList[current].head;p!=NULL;p=p->next)
if(--inDegree[p->end]==0)
q1.enQueue(p->end);
cout<<endl;
if(q1.isEmpty()) break;
++semester;
}
*/
/*
cout<<"第"<<semester<<"学期的课为:";
while(!q2.isEmpty())
{
current=q2.deQueue();
cout<<verList[current].ver<<" ";
for(p=verList[current].head;p!=NULL;p=p->next)
if(--inDegree[p->end]==0)
q1.enQueue(p->end);
}
if(q1.isEmpty())break;
++semester;
cout<<endl;
if(semester>1)
{cout<<"第"<<semester<<"学期的课为:";}
}
/*
template<class TypeOfVer,class TypeOfEdge>
void adjListGraph<TypeOfVer,TypeOfEdge>::findLessTime()const
//Insert Your Code
{
cout<<"课程安排为:"<<endl;
LQueue<int>q1,q2;
edgeNode*p;
int current,semester=1;
int *inDegree=new int [Vers];
for(int i=0;i<Vers;++i)
{
inDegree[i]=0;
}
for( int i=0;i<Vers;++i)
for(p=verList[i].head;p!=NULL;p=p->next)
++inDegree[p->end];
for(int i=0;i<Vers;++i)
if(inDegree[i]==0) q1.enQueue(i);
while(true){
if(semester==1)cout<<"第"<<semester<<"学期的课为:";
while(!q1.isEmpty())
{
current=q1.deQueue();
cout<<verList[current].ver<<" ";
for(p=verList[current].head;p!=NULL;p=p->next)
if(--inDegree[p->end]==0)
q2.enQueue(p->end);
}
cout<<endl;
if(q2.isEmpty()) break;
++semester;
cout<<"第"<<semester<<"学期的课为:";
while(!q2.isEmpty())
{
current=q2.deQueue();
cout<<verList[current].ver<<" ";
for(p=verList[current].head;p!=NULL;p=p->next)
if(--inDegree[p->end]==0)
q1.enQueue(p->end);
}
if(q1.isEmpty())break;
++semester;
cout<<endl;
if(semester>1)
{cout<<"第"<<semester<<"学期的课为:";}
}
*/
/*{
cout<<"课程安排为:"<<endl;
int tmp=1;
int i;
LQueue<int>q;
edgeNode *p;
int current,*inDegree;
inDegree=new int [Vers];
for(i=0;i<Vers;++i) inDegree[i]=0;
for(i=0;i<Vers;++i)
for(p=verList[i].head;p!=NULL;p=p->next)
++inDegree[i];
/*for(i=0;i<Vers;++i) if(inDegree[i]==0)
q.enQueue(i);*/
/* int y;
int num=Vers;
while(num!=0)
{
y=0;
for(i=0;i<Vers;i++)
{
if(inDegree[i]==tmp-1)
{
q.enQueue(i);
num--;
y++;
}
}
cout<<"第"<<tmp<<"学期的课为:";
for(i=0;i<y+1;i++)
{
current=q.deQueue();
cout<<verList[current].ver<<" ";
}
tmp=tmp+1;
}
*/
/*
while(!isEmpty())
{
cout<<"第"<<tmp<<"学期的课为:";
current=q.deQueue();
cout<<verList[current].ver<<" ";
cout<<endl;
for(p=verList[current].head;p!=NULL;p=p->next)
if(--inDegree[p->end]==0)
{
q.enQueue(p->end);
}
tmp=tmp+1;
}
*/
return ;
}
被注释符号注释掉的区域为思路历程,欢迎大家探讨!