2018Final链表(龙舟队)
凤湖中学有一支优秀的龙舟队。在任意时刻,龙舟队里至少有3人,其中至少有1名鼓手。龙舟队的成员一直在调整中。鼓手的离队有可能导致队中暂时没有鼓手,这时,就要自动选择最有资历的队员作为鼓手。
现在用一个单链表来存储龙舟队成员的信息,每个成员信息包括是否为鼓手, 编号(所有成员的编号不相同)和年级:
链表中按先鼓手,后一般队员的顺序存储队员信息。如果有多个鼓手,则按他们的编号排序,编号较小者在前;一般队员也按编号从小到大的规则排序。
在自动选择鼓手时,优先选择年级最高的,如果有多位队员同时具有最高的年级号,则选择其中编号最小的那位作鼓手。
输入时,首先输入若干名队员信息,每条信息包括3项:是否鼓手(0否,1是),编号,年级。当输入-1时结束输入初始信息。接着,进行队员增减操作,每次增减操作最多可能包括4项:第一项为操作类型(0为减少,1为增加,-1为终止操作),如果第1项为-1,则终止输入;如果第1项为0,则输入离开的成员的编号(假设所输入的编号肯定在当前龙舟队中);如果第1项为1时,则输入新队员的3项信息:是否鼓手(0否,1是),编号(假设新加入成员的编号不会与现有成员相同),年级。
输出:在每次增减操作后,均输出当前龙舟队的前3位成员的信息(假设在建立链表后,任意时刻该链表中的结点数量均不会小于3)。
函数接口定义
Player *create();//建立链表
Player* addPlayer(Player* head, Player* q);//加链表里加入q指向的结点
Player* removePlayer(Player *head, int num);//从链表里删除编号为num的结点,如果删除导致缺少鼓手则自动选择一位新鼓手
裁判测试程序样例:
#include <iostream>
using namespace std;
struct Player{
bool drummer;
int num;
int grade;
Player* next;
};
void print(Player *head){
Player *p=head;
cout<<p->num<<' ';
p=p->next;
cout<<p->num<<' ';
p=p->next;
cout<<p->num<<endl;
}
/* 请在这里填写答案 */
int main(){
Player *head=NULL;
int task, d, num, grade;
head=create();
while(1){
cin>>task;
if(task<0) break;
if(task==1){
Player*q = new Player;
cin>>d>>q->num>>q->grade;
if(d==1) q->drummer=true; else q->drummer=false;
q->next = NULL;
head=addPlayer(head, q);
}
if(task==0){
cin>>num;
head=removePlayer(head, num);
}
print(head);
}
return 0;
}
输入样例:
1 0 7
0 5 9
0 3 8
0 16 8
1 20 9
-1
0 0
0 20
-1
输出样例:
20 3 5
5 3 16
Player* addPlayer(Player* head,Player* q);
Player* create()
{
int flag,num,grade;
cin>>flag;
Player* head=NULL;
while(flag>=0)
{
Player* q=new Player;
q->next=NULL;
if(flag)
q->drummer=true;
else
q->drummer=false;
cin>>q->num>>q->grade;
head=addPlayer(head,q);
cin>>flag;
}
return head;
}
Player* addPlayer(Player* head,Player* q)
{
if(head==NULL)//头结点为空
{
head=q;
return head;
}
else if((q->drummer&&head->drummer&&q->num<head->num)||(q->drummer&&!head->drummer)||(!q->drummer&&!head->drummer&&q->num<head->num))//新节点插入头结点
{
q->next=head;
head=q;
return head;
}
else//头结点不为空且新结点不插入头结点
{
Player* p=head;
while(p->next!=NULL)
{
if(q->drummer&&p->next->drummer&&q->num<p->next->num)
break;
if(q->drummer&&!p->next->drummer)
break;
if(!q->drummer&&!p->next->drummer&&q->num<p->next->num)
break;
p=p->next;
}
q->next=p->next;
p->next=q;
}
return head;
}
Player* removePlayer(Player* head,int num)
{
int headflag=0;
int count=0;//记录鼓手人数
Player* temp;//记录删除结点的前一结点
if(head->num==num)//删除的为头结点
{
headflag=1;
if(head->drummer)
count++;
temp=head;
delete temp;
head=head->next;
}
Player* p=head;
if(p->drummer)//判断头结点是否为鼓手
count++;
while(p->next!=NULL)//查询删除结点,统计链表中鼓手人数
{
if(p->next->num==num)
temp=p;
if(p->next->drummer)
count++;
p=p->next;
}
if(headflag&&count==1)//删除为头结点且需重新命名鼓手
{//重新命名鼓手
int h=head->grade;
Player* k=head;
Player* x=head;
while(x->next!=NULL)
{
if(x->next->grade>k->next->grade)
k=x;
x=x->next;
}
if(h>=k->next->grade)//头结点年级最大,直接改返回
{
head->drummer=true;
return head;
}
else//年级最大的不在头结点,删除原结点之后插入头结点
{
Player* w=k->next;
k->next=w->next;
w->next=head;
head=w;
w->drummer=true;
}
}
if(!headflag)//删除结点非头结点
{
int flag=0;
Player* t=temp->next;
if(t->drummer&&count==1)
flag=1;
temp->next=t->next;
delete t;
if(flag)//需重新命名鼓手
{
int h=head->grade;
Player* k=head;
Player* x=head;
while(x->next!=NULL)
{
if(x->next->grade>k->next->grade)
k=x;
}
if(h>=k->next->grade)//头结点年级最大,直接改返回
{
head->drummer=true;
return head;
}
else//年级最大的不在头结点,删除原结点之后插入头结点
{
Player* w=k->next;
k->next=w->next;
w->next=head;
head=w;
w->drummer=true;
}
}
}
return head;
}
完整代码
#include <iostream>
using namespace std;
struct Player{
bool drummer;
int num;
int grade;
Player* next;
};
void print(Player *head){
Player *p=head;
cout<<p->num<<' ';
p=p->next;
cout<<p->num<<' ';
p=p->next;
cout<<p->num<<endl;
}
/* 请在这里填写答案 */
Player* addPlayer(Player* head,Player* q);
Player* create()
{
int flag,num,grade;
cin>>flag;
Player* head=NULL;
while(flag>=0)
{
Player* q=new Player;
q->next=NULL;
if(flag)
q->drummer=true;
else
q->drummer=false;
cin>>q->num>>q->grade;
head=addPlayer(head,q);
cin>>flag;
}
return head;
}
Player* addPlayer(Player* head,Player* q)
{
if(head==NULL)//头结点为空
{
head=q;
return head;
}
else if((q->drummer&&head->drummer&&q->num<head->num)||(q->drummer&&!head->drummer)||(!q->drummer&&!head->drummer&&q->num<head->num))//新节点插入头结点
{
q->next=head;
head=q;
return head;
}
else//头结点不为空且新结点不插入头结点
{
Player* p=head;
while(p->next!=NULL)
{
if(q->drummer&&p->next->drummer&&q->num<p->next->num)
break;
if(q->drummer&&!p->next->drummer)
break;
if(!q->drummer&&!p->next->drummer&&q->num<p->next->num)
break;
p=p->next;
}
q->next=p->next;
p->next=q;
}
return head;
}
Player* removePlayer(Player* head,int num)
{
int headflag=0;
int count=0;//记录鼓手人数
Player* temp;//记录删除结点的前一结点
if(head->num==num)//删除的为头结点
{
headflag=1;
if(head->drummer)
count++;
temp=head;
delete temp;
head=head->next;
}
Player* p=head;
if(p->drummer)//判断头结点是否为鼓手
count++;
while(p->next!=NULL)//查询删除结点,统计链表中鼓手人数
{
if(p->next->num==num)
temp=p;
if(p->next->drummer)
count++;
p=p->next;
}
if(headflag&&count==1)//删除为头结点且需重新命名鼓手
{//重新命名鼓手
int h=head->grade;
Player* k=head;
Player* x=head;
while(x->next!=NULL)
{
if(x->next->grade>k->next->grade)
k=x;
x=x->next;
}
if(h>=k->next->grade)//头结点年级最大,直接改返回
{
head->drummer=true;
return head;
}
else//年级最大的不在头结点,删除原结点之后插入头结点
{
Player* w=k->next;
w->drummer=true;
k->next=w->next;
w->next=head;
head=w;
}
}
if(!headflag)//删除结点非头结点
{
int flag=0;
Player* t=temp->next;
if(t->drummer&&count==1)
flag=1;
temp->next=t->next;
delete t;
if(flag)//需重新命名鼓手
{
int h=head->grade;
Player* k=head;
Player* x=head;
while(x->next!=NULL)
{
if(x->next->grade>k->next->grade)
k=x;
}
if(h>=k->next->grade)//头结点年级最大,直接改返回
{
head->drummer=true;
return head;
}
else//年级最大的不在头结点,删除原结点之后插入头结点
{
Player* w=k->next;
k->next=w->next;
w->next=head;
head=w;
}
}
}
return head;
}
int main()
{
Player *head=NULL;
int task, d, num, grade;
head=create();
while(1){
cin>>task;
if(task<0) break;
if(task==1){
Player*q = new Player;
cin>>d>>q->num>>q->grade;
if(d==1) q->drummer=true; else q->drummer=false;
q->next = NULL;
head=addPlayer(head, q);
}
if(task==0){
cin>>num;
head=removePlayer(head, num);
}
print(head);
}
return 0;
}