①问题描述
在高校的教学改革中,有很多学校实行了本科生导师制。一个班级的学生被分给几个老师,每个老师带n个学生,如果该老师还带研究生,那么研究生也可直接带本科生。本科生导师制问题中的数据元素具有如下形式:
-
导师带研究生
(老师,((研究生1,(本科生1,…,本科生m1)),(研究生2,(本科生1,…,本科生m2))…)) -
导师不带研究生
(老师,(本科生1,…,本科生m))
导师的自然情况只包括姓名、职称;研究生的自然情况只包括姓名、班级;本科生的自然情况只包括姓名、班级。
②基本要求
要求完成以下功能:
-
建立:建立导师广义表。
-
插入:将某位本科生或研究生插入到广义表的相应位置。
-
删除:将某本科生或研究生从广义表中删除。
-
查询:查询导师、本科生(研究生)的情况。
-
统计:某导师带了多少个研究生和本科生。
-
输出:将某导师所带学生情况输出。
-
退出:程序结束。
③设计提示
本实验使用的数据结构是广义表,广义表采用头尾链表存储结构来实现。
定义教师、学生结点结构体如下:
typedef struct GLNode
{
char name[100]; /*教师或学生的姓名*/
char prof[100]; /*教师结点表示职称,学生结点表示班级*/
int type; /*结点类型:0-教师,1-研究生,2-本科生*/
struct {struct GLNode *hp, *tp;} ptr;
/*hp指向同级的下一结点,tp指向下级的首结点*/
}GList;
人员信息的表示形式为:高老师-教授-0、李刚-二班-1、李明-二班-2.
人员信息中的姓名、职称、班级、人员类型用“-”隔开,如高老师-教授-0,“高老师”表示姓名,“教师”表示职称,“0”表示人员的类型是教师;李刚-二班-1,“李刚”表示姓名,“二班”表示班级,“1”表示人员的类型是研究生;李明-二班-2,“李明”表示姓名,“二班”表示班级,“2”表示人员的类型是本科生。
广义表((高老师-教授-0,(李明-一班-2,王平-二班-2)),(李老师-副教授-0,(白梅-二班-1,(李刚-一班-2)))可以用图3表示。
图3 导师制用广义表实现示例
④思考
可以考虑对程序做如下完善:
-
可以将学生从一个导师组转到另一个导师组。
-
可以在同一个导师组内修改本科生的研究生负责人。
-
当研究生带本科生时,如果要删除该研究生,可根据情况,将本科生平均分配给该导师的其他研究生,如果没有其他研究生,则由导师直接负责。
-
增加删除导师的功能。
-
查询时,如果待查人员是导师,除了输出本人信息外,还输出他所指导的学生信息;如果待查人员是研究生,除了输出其导师和本人信息外,还输出他所负责的本科生信息。
#include<iostream>
#include<string.h>
using namespace std;
class LS
{
private:
struct Node//建立结点
{
string name;
string prof;
int type;
Node * right,*down;//每个节点有向右和向下的指针
Node():right(NULL),down(NULL) {}
Node(string name1 , string prof1 , int a)
{
name = name1;
prof = prof1;
type = a;
right = NULL;
down = NULL;
}
};
Node * head;
Node * cur;
public:
int number0 = 0 ,number1 = 0,number2 = 0;//教授人数、导师人数、学生人数
int nameflag = 0;//名字标记
LS()
{
Node * p = new Node();//建立头节点
head = p;
}
void dfs(Node * cur)//dfs
{
if(cur->type==0)
{
number0++;
cout<<cur->name<<" "<<cur->prof<<" "<<cur->type<<endl;
}
if(cur->type==1)
{
number1++;
cout<<cur->name<<" "<<cur->prof<<" "<<cur->type<<endl;
}
if(cur->type==2)
{
number2++;
cout<<cur->name<<" "<<cur->prof<<" "<<cur->type<<endl;
}
if(cur->right)dfs(cur->right);
if(cur->down)dfs(cur->down);
}
Node *findname(Node * cur,string name)//查询姓名
{
if(cur->name==name){cout<<"find"<<endl;
cout<<cur->name<<" "<<cur->prof<<" "<<cur->type<<endl;
nameflag = 1;
return cur;}
if(cur->right)findname(cur->right,name);
if(cur->down)findname(cur->down,name);
if(nameflag == 0)return 0;
}
void all_function()
{
cout<<"please input boss's name prof type"<<endl;
string Name,Prof;
int Type;
cin>>Name>>Prof>>Type;
Node * p = new Node(Name,Prof,Type);//输入第一个节点
head -> down = p;
cur = p;
while(1)
{
cout<<"please input:"<<endl;
cout<<"1 show now node"<<endl;//打印当前节点信息
cout<<"2 insert right"<<endl;//在当前节点往右插入
cout<<"3 insert down"<<endl;//在当前节点往下插入
cout<<"4 return boss"<<endl;//返回头节点
cout<<"5 moveright"<<endl;//当前节点往右移动
cout<<"6 movedown"<<endl;//当前节点往下移动
cout<<"7 delete now Node"<<endl;//删除当前节点
cout<<"8 tongji now node renshu"<<endl;//统计所有结点
cout<<"9 chaxun xingming"<<endl;//查询姓名
cout<<"10 print all student"<<endl;//打印当前节点的所有学生
cout<<"0 break"<<endl;//结束循环
int n;
cin>>n;
if(n==0)break;
string Name,Prof;
int Type;
switch (n)
{
case 1://打印当前节点信息
{
cout<<"now Node is:"<<endl;
cout<<cur->name<<" "<<cur->prof<<" "<<cur->type<<endl;
break;
}
case 2://在当前节点往右插入
{
cout<<"now Node is:"<<endl;
cout<<cur->name<<" "<<cur->prof<<" "<<cur->type<<endl;
cout<<"please input right numbers"<<endl;//插入几个
int insertright;
cin>>insertright;
for(int i = 0 ; i < insertright ; i++)
{
cout<<"please input Node name prof type"<<endl;
cin>>Name>>Prof>>Type;
Node * p = new Node(Name,Prof,Type);
cur->right = p;
cur = cur -> right;
}
cur = head -> down;
break;
}
case 3://在当前节点往下插入
{
cout<<"now Node is:"<<endl;
cout<<cur->name<<" "<<cur->prof<<" "<<cur->type<<endl;
cout<<"please input down numbers"<<endl;//插入几个
int insertdown;
cin>>insertdown;
for(int i = 0 ; i < insertdown ; i++)
{
cout<<"please input Node name prof type"<<endl;
cin>>Name>>Prof>>Type;
Node * p = new Node(Name,Prof,Type);
cur->down = p;
cur = cur -> down;
}
cur = head -> down;
break;
}
case 4://返回头节点
{
cur = head->down;
break;
}
case 5://当前节点往右移动
{
cout<<"now Node is:"<<endl;
cout<<cur->name<<" "<<cur->prof<<" "<<cur->type<<endl;
cout<<"after movedown Node is:"<<endl;
cur = cur -> right;
cout<<cur->name<<" "<<cur->prof<<" "<<cur->type<<endl;
break;
}
case 6://当前节点往下移动
{
cout<<"now Node is:"<<endl;
cout<<cur->name<<" "<<cur->prof<<" "<<cur->type<<endl;
cout<<"after movedown Node is:"<<endl;
cur = cur -> down;
cout<<cur->name<<" "<<cur->prof<<" "<<cur->type<<endl;
break;
}
case 7://删除当前节点
{
cout<<"the Node will be delete is:"<<endl;
cout<<cur->name<<" "<<cur->prof<<" "<<cur->type<<endl;
int flag1 = 0,flag2 = 0;
Node * p1;
Node * p2;
if(cur -> right !=NULL)
{
p1 = cur -> right;
flag1 = 1;
}
if(cur -> down != NULL)
{
p2 = cur ->down;
flag2 = 1;
}
if(flag1&&flag2)//右边和下边都有元素的话,把右边的节点赋值给当前要删除的节点,并且把下面的元素连接到当前节点
{
cur -> name = p1 -> name;
cur -> prof = p1 -> prof;
cur -> type = p1 -> type;
delete p1;
cur ->down = p2;
}
else if(flag1)//只有右边有元素,把右边的节点赋值给当前要删除的节点
{
cur -> name = p1 -> name;
cur -> prof = p1 -> prof;
cur -> type = p1 -> type;
delete p1;
}
else if(flag2)//只有下边有元素,把下边的节点赋值给当前要删除的节点
{
cur -> name = p2 -> name;
cur -> prof = p2 -> prof;
cur -> type = p2 -> type;
delete p2;
}
break;
}
case 8://统计所有结点
{ number0 = 0;number1 = 0;number2 = 0;
dfs(cur);
cout<<"jiaoshou yanjiusheng xuesheng number:"<<number0<<" "<<number1<<" "<<number2<<endl;
break;
}
case 9://查询姓名(dfs)
{
string name;
cout<<"please chaxun name"<<endl;
cin>>name;
if(!findname(cur,name))
{
cout<<"can not find"<<endl;
}
nameflag = 0;
break;
}
case 10://打印当前节点的所有学生
{
dfs(cur);
break;
}
}
}
}
};
int main()
{
LS dusk;
dusk.all_function();
}