①问题描述
在高校的教学改革中,有很多学校实行了本科生导师制。一个班级的学生被分给几个老师,每个老师带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(); }