题目描述:
这里有一个简易的电话号码本系统,请按要求实现其部分功能。电话号码本中可以存储若干个人的信息,信息包括姓名,电话,添加年月日三项内容。每条信息在系统中都有一个编号(从0开始)。
你要完成的功能包括节点的插入、删除及信息的输出。将n号信息加入到号码本意味着原有的n号变为n+1号,原有的n+1号变为n+2号,以此类推;将n号信息删除意味着原有的n+1号变为n号,原有的n+2号变为n+1号,以此类推。
输入格式: 第一行为一个整数n(0<=n<=100),初始时系统内共有n条记录。后边n行每一行为一条记录,格式为用空格分隔的两个字符串和3个整数(见输入样例),第一个字符串代表姓名(只包含小写字母且长度不超过15),第二个字符串代表电话号码(长度不超过15且只包含数字),三个数字依次代表年月日。各条记录按输入顺序编号,即第一个输入的编0号,第二个输入的编1号,依此类推。实际上你无需为它们编号,链表中的顺序就反应了它们的编号。
第n+1行为一个整数m(0<m<=100),代表后边共有m次操作。接下来共有m行,每行代表一次操作,如果增加操作,格式为用空格分隔的7个量,第一量固定为整数1,代表增加操作。第二个量也是一个整数,代表加入的编号。后五个量输入格式与前边输入信息时相同。如果是删除操作,则为两个用空格分隔的整数,第一个固定为2,代表删除操作。第二个整数代表被删除的编号。 测试用例保证合法。
输出格式: 为n行,每行一条信息,按编号由小到大输出,输出格式为用空格分隔的六个量,第一个为编号,后边5个与输入时格式一致(见输出样例)。
你要用链表及函数完成此任务,否则没有分。
提示:
要实现的函数接口只有一个,但你可以定义自己的函数以辅助实现此功能,比如链表的基本操作都可以定义为一个函数。
函数接口定义:
PERSON* phonebook() ;
函数没有参数。函数的返回值为所建链表头指针。
测试程序样例:
#include <stdio.h>
#include <stdlib.h>
typedef struct person
{
char name[16] ;
char phone[16] ;
int year , month , day ;
struct person *next ;
} PERSON ;
PERSON* phonebook() ;
int main()
{
PERSON *tempPtr, *headPtr = NULL ;
headPtr = phonebook() ;
//释放内存 ,所以你的函数中无需释放内存。
while ( headPtr != NULL )
{
tempPtr = headPtr ;
headPtr = headPtr->next ;
free(tempPtr) ;
}
return 0 ;
}
/* 请在这里填写答案 */
输入样例:
5
zhao 13012345678 2012 5 4
qian 13112345678 2013 5 3
sun 13212345678 2009 4 8
li 13312345678 2017 3 1
zhou 13412345678 2016 2 3
3
1 3 wu 13512345678 2011 5 5
1 5 zheng 13612345678 2016 10 5
2 4
输出样例:
0 zhao 13012345678 2012 5 4
1 qian 13112345678 2013 5 3
2 sun 13212345678 2009 4 8
3 wu 13512345678 2011 5 5
4 zheng 13612345678 2016 10 5
5 zhou 13412345678 2016 2 3
函数实现1(结构体数组实现):
PERSON* phonebook()
{
PERSON p[202]={0},*head; //数组p[]存储链表结点位置
head=NULL; //将头指针置空
int n; //结点数目
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%s%s%d%d%d",p[i].name,p[i].phone,&p[i].year,&p[i].month,&p[i].day);
}
int m,flag,node; //node为被操作的结点序号
scanf("%d",&m);
for(int i=0;i<m;i++)
{
scanf("%d%d",&flag,&node);
if(flag==1)
{
for(int j=n;j>node;j--)
{
p[j]=p[j-1];
} //插入结点
scanf("%s%s%d%d%d",p[node].name,p[node].phone,&p[node].year,&p[node].month,&p[node].day);
n+=1; //结点数目+1
}
if(flag==2)
{
for(int j=node;j<n;j++) //删除指定结点
{
p[j]=p[j+1];
}
n-=1; //结点数目-1
}
}
for(int i=0;i<n;i++)
{
printf("%d %s %s %d %d %d\n",i,p[i].name,p[i].phone,p[i].year,p[i].month,p[i].day);
}
head=&p[0]; //将链表首地址赋给头指针
return head; //返回链表头指针
}
注意:函数实现1中未使用链表中的struct person *next,故测试程序代码需改为如下:
#include <stdio.h>
#include <stdlib.h>
typedef struct person
{
char name[16] ;
char phone[16] ;
int year, month, day;
struct person *next ;
} PERSON ;
PERSON* phonebook() ;
int main()
{
PERSON *tempPtr, *headPtr = NULL ;
headPtr = phonebook() ;
//无需释放内存
tempPtr = NULL;
return 0 ;
}
函数实现2(指针实现):
PERSON* phonebook()
{
int n;
int i,j;
PERSON *head, *tail, *p;
head = tail = NULL;
scanf("%d",&n);
for(i=0;i<n;i++)
{
p=(PERSON*)malloc(sizeof(PERSON));
scanf("%s%s%d%d%d",p->name,p->phone,&p->year,&p->month,&p->day);
(head==NULL)?(head=p):(tail->next=p);
tail=p;
}
if(head!=NULL) //非空链表时
{
tail->next=NULL; //尾结点的下一结点置空
}
int m,flag,node;
scanf("%d",&m);
for(i=0;i<m;i++)
{
scanf("%d%d",&flag,&node);
PERSON *temp;
temp=head;
if(flag==1)
{
p=(PERSON*)malloc(sizeof(PERSON));
scanf("%s%s%d%d%d",p->name,p->phone,&p->year,&p->month,&p->day);
if(node==0)
{
p->next=head;
head=p;
}
else
{
for(j=0;j<node-1;j++)
{
temp=temp->next;
}
p->next=temp->next;
temp->next=p;
}
}
if(flag==2)
{
if(node==0)
{
head=temp->next;
}
else
{
PERSON *front;
front=NULL;
for(j=0;j<node;j++)
{
front=temp;
temp=temp->next;
}
front->next=temp->next;
}
}
}
i=0;
for(p=head;p!=NULL;p=p->next)
{
printf("%d %s %s %d %d %d\n",i,p->name,p->phone,p->year,p->month,p->day);
i++;
}
return head;
}