【无标题】

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;    
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值