这里有一道C语言题目,大神能给一下代码吗?
分析题目,程序需要实现以下功能:
1、链表节点的插入/新建(新建和插入可整合在一个函数中),通过位置参数n,决定末尾新建还是在指定位置插入。
2、链表节点删除,删除就是将链表指针断开重新连接(由于节点是动态创建,断开目标节点后还要释放其内存)。
下面是我写给你的演示代码:
主要3个函数,分别是1、显示链表及菜单;2、插入新节点;3、删除指定节点;
PS:插入和删除成功,函数都会返回目标位置前一个节点,你可以利用这个返回值写撤销功能(撤销插入只要直接重新连接链表指针并释放内存,而撤销删除,你需要在调用删除前用变量保存一个节点备份)。
选择插入时,如链表已满,可直接跳转到删除功能。
#include<stdio.h>
#include<string.h>
#include<malloc.h>
#define N 4//链表最大长度
#define L 8//字符串长度
typedef struct stu
{
char id[L+1];
char name[L+1];
struct stu *next;
}STU;
int cnt=0;//当前链表的实际节点数量,不超过N
//insert2List:在链表第n个节点的位置插入新节点nStu。成功返回插入位置的前一个节点(可用于撤销)。失败返回NULL
STU *insert2List(STU nStu,STU *stusHead,int n);
//delFormList:删除第n个节点(释放内存)。成功删除位置的前一个节点(可用于撤销)。失败返回NULL
STU *delFormList(STU *stusHead,int n);
void showList(STU *stusHead);//打印链表
int init(STU *stusHead);//初始化一批测试数据,该函数可以不使用删除
int main()
{
STU sHead;
sHead.next=NULL;
init(&sHead);
while(1)
{
system("cls");
showList(&sHead);
}
return 0;
}
int init(STU *stusHead)
{
int i=0,n=1;
STU nStu[5];
strcpy(nStu[i].id,"101");
strcpy(nStu[i].name,"小王");
nStu[i].next=NULL;
insert2List(nStu[i++],stusHead,n++);
strcpy(nStu[i].id,"102");
strcpy(nStu[i].name,"小陈");
nStu[i].next=NULL;
insert2List(nStu[i++],stusHead,n++);
strcpy(nStu[i].id,"103");
strcpy(nStu[i].name,"小李");
nStu[i].next=NULL;
insert2List(nStu[i++],stusHead,4);
strcpy(nStu[i].id,"104");
strcpy(nStu[i].name,"小涛");
nStu[i].next=NULL;
insert2List(nStu[i++],stusHead,2);
return 1;
}
void showList(STU *stusHead)
{
char c;
int i,ln,n=-1;
STU *sHead=stusHead,nStu;
if(stusHead)
{
printf(" ");
while(sHead->next)
{
for(i=0;i<L+2;printf("-"),i++);
printf("%s",sHead->next->next?" ":"");
sHead=sHead->next;
}
printf("\n");
sHead=stusHead;
printf("姓名:");
while(sHead->next)
{
ln=strlen(sHead->next->name);
printf("|%*s%s%*s|%s",(L-ln)/2,"",sHead->next->name,(L-ln)/2+(L-ln)%2,"",sHead->next->next?" => ":"");
sHead=sHead->next;
}
printf("\n");
sHead=stusHead;
printf("学号:");
while(sHead->next)
{
ln=strlen(sHead->next->id);
printf("|%*s%s%*s|%s",(L-ln)/2,"",sHead->next->id,(L-ln)/2+(L-ln)%2,"",sHead->next->next?" => ":"");
sHead=sHead->next;
}
printf("\n");
sHead=stusHead;
printf(" ");
while(sHead->next)
{
for(i=0;i<L+2;printf("-"),i++);
printf("%s",sHead->next->next?" ":"");
sHead=sHead->next;
}
}
while(n!=1 && n!=2)
printf("\n选择操作(输入1或者2。1、插入 2、删除):"),scanf("%d",&n);
switch(n)
{
case 1:
if(cnt<N)
{
printf("请输入学号(小于等于%d个字符):",L);
scanf("%s",nStu.id);
printf("请输入姓名(小于等于%d个字符):",L);
scanf("%s",nStu.name);
nStu.next=NULL;
n=0;
printf("请输入第几个位置(1~%d):",N);
while(n<1 || n>N)scanf("%d",&n);
insert2List(nStu,stusHead,n);
break;
}
else
{
c=0;
printf("链表已满,是否要先删除?(Y/N):\n");
while(c!='Y' && c!='N')scanf("%c",&c);
if(c=='N') break;
}
case 2:
n=0;
if(cnt>0)
{
printf("请输入要删除第几个学生节点(1~%d):",cnt);
while(n<1 || n>cnt)scanf("%d",&n);
delFormList(stusHead,n);
}
else
printf("无数据删除\n");
break;
}
}
STU *delFormList(STU *stusHead,int n)
{
int i=0;
STU *stu_prev=NULL,*delStu=NULL;
if(!stusHead)return NULL;
while(stusHead->next)
{
i++;
printf("1111\n");
if(i==n)
{
delStu=stusHead->next;
stu_prev=stusHead;
stu_prev->next=stusHead->next->next;
free(delStu);
cnt--;
break;
}
stusHead=stusHead->next;
}
return stu_prev;
}
STU *insert2List(STU nStu,STU *stusHead,int n)
{
int i=0;
STU *stu_new=NULL,*stu_prev=NULL;
if(cnt==N)
{
printf("错误:链表已满(最大长度4),请先删除旧节点后再插入新节点\n");
return NULL;
}
if(n>N)
{
printf("错误:插入的位置超出链表返回(链表长度受限,不超过4个节点)\n");
return NULL;
}
if(!stusHead)return NULL;
if(!(stu_new=(STU *)malloc(sizeof(STU))))return NULL;
strcpy(stu_new->name,nStu.name);
strcpy(stu_new->id,nStu.id);
stu_new->next=NULL;
stu_prev=stusHead;//stu_prev表示链表当前节点的前一个节点,用于遍历链表插入时连接
cnt++;
if(n>=cnt)//插入点大于等于(当前最大节点数+1),直接插入在链表末尾
{
while(stusHead->next)
{
stu_prev=stusHead->next;
stusHead=stusHead->next;
}
stu_prev=stusHead;
stu_prev->next=stu_new;
}
else
while(stusHead->next)//新节点插入指定位置(第n个节点的位置)
{
i++;
if(i==n)
{
stu_prev=stusHead;
stu_new->next=stusHead->next;
stu_prev->next=stu_new;
break;
}
stusHead=stusHead->next;
}
return stu_prev;
}