1. 编写函数,完成在第n个节点的后增加节点的功能,n值由键盘输入。(注意健壮性,要求能够对不同的n值做出恰当的处理)。
2. 编写函数,完成在第n个节点的后删除节点的功能,n值由键盘输入。(注意健壮性,要求能够对不同的n值做出恰当的处理)。
3. 编写函数,删除所有数据值为奇数的节点。(注意健壮性,奇数节点可以在任意位置,头、尾、中间,删除了之后可能删光了)。
4. 要求每次增删节点后可以显示更新后的链表元素个数及每个节点的信息。
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define L sizeof(struct link)
int len;
struct link
{
int data;
struct link* next;
};
struct link *appendnode(struct link *head); //建立链表,添加节点
void display(struct link *head); //输出链表所有信息
struct link *insertnode(struct link *head); //插入节点
struct link *deletenode(struct link *head); //删除节点
struct link *deleteodd(struct link *head); //删除data为奇数的节点
void display(struct link* head)
{
struct link *p=head; //链表类型的指针变量为首地址
int j=1;
while(p!=NULL)
{
printf("%5d%8d\n",j,p->data);
j++;
p=p->next;
}
}
int main()
{
int x=1;
printf("how long node do you append\n");
scanf("%d",&len);
struct link *head=NULL;
head=appendnode(head); //先自己手动创建一个链表
display(head);
while(x) //展示菜单功能
{
printf(" 1:insertnode!\n"); //完成在第n个节点的后增加节点的功能,n值由键盘输入
printf(" 2:deletenode!\n"); //完成删除第n个节点的功能,n值由键盘输入
printf(" 3:deleteodd!\n"); //删除data为奇数的节点
printf(" 0:finish!\n");
printf("Please your choice!\n");
scanf("%d",&x);
switch(x)
{
case 1:
head=insertnode(head);
display(head);
break;
case 2:
head=deletenode(head);
display(head);
break;
case 3:
head=deleteodd(head);
display(head);
break;
case 0:
exit(0);
}
if(head==NULL)
break;
}
return 0;
}
struct link *appendnode(struct link *head) //创建链表
{
struct link *p=NULL,*pr=head;
int data,i;
for(i=1; i<=len; i++)
{
p=(struct link*)malloc(L); //为每一个节点申请空间
if(p==NULL)
{
printf("no enough memory to allocate!");
exit(0);
}
if(head==NULL)
{
head=p;
pr=head;
}
else
{
pr->next=p; //把p的地址赋值给pr的下一个地址
pr=pr->next;
}
printf("Input data\n");
scanf("%d",&data);
p->data=data;
if(i==len)
p->next=NULL; //最后一个节点的下一个地址为空
}
return head;
};
struct link *insertnode(struct link *head) //完成在第n个节点的后增加节点的功能,n值由键盘输入
{
int n,i,data;
struct link *p=NULL,*pr=head,*temp=NULL;
printf("Which node do you want to insert?(1~%d)\n",len);
scanf("%d",&n);
while(n<1||n>len)
{
printf("Please input again!\n");
scanf("%d",&n);
}
p=(struct link *)malloc(L); //为要插入的节点申请空间
if(p==NULL)
{
printf("no enough memory to allocate!\n");
exit(0);
}
for(i=1; i<n; i++) //将当前pr指向第n个节点的位置
{
pr=pr->next;
}
if(n<len) //输入的n不是最后一个节点
{
p->next=pr->next;
pr->next=p;
}
else //如果输入的n是链表最后一个节点,申请的空间p下一个地址指向NULL
{
pr->next=p;
p->next=NULL;
}
printf("Input data!\n");
scanf("%d",&data);
p->data=data;
len++;
return head;
};
struct link *deletenode(struct link *head) //完成删除第n个节点的功能,n值由键盘输入
{
struct link *p=head,*pr=head;
int i,n;
printf("Which node do you want to delete?(1~%d)\n",len);
scanf("%d",&n);
while(n<1||n>len)
{
printf("Please input again!\n");
scanf("%d",&n);
}
if(len==1&&n==1) //如果链表只有一个节点
{
head=NULL;
free(p); //释放当前节点的内存
len--;
printf("Linked list is completely deleted!\n"); //链表里的节点都被删除
return head;
}
if(n==1)
{
head=p->next; //如果n为1,头节点就为下一个节点
free(p);
len--;
return head;
}
for(i=1; i<n-1; i++) //如果n不为1,pr指向第n-1个节点
{
pr=pr->next;
}
for(i=1; i<n; i++) //如果n不为1,p指向第n个节点
{
p=p->next;
}
pr->next=p->next; //把p的下一个地址赋值给pr的下一个地址
free(p);
len--;
return head;
};
struct link *deleteodd(struct link *head) //删除data为奇数的节点
{
struct link *p=head,*pr=head,*temp=head,*text=head;
int i,j=1,k=0;
for(i=1; i<len; i++) //先处理前n-1个节点
{
if(p->data%2==1) //data为奇数
{
if(p==head)
{
head=p->next; //如果是头节点,头节点就指向p的下一个地址
free(p);
p=head,pr=head;
}
else
{
pr->next=p->next;
free(p); //删除data为奇数的节点
p=pr->next;
}
k++;
}
else
{
j++;
p=p->next;
}
if(j>2)
pr=pr->next;
}
len-=k;
temp=head,text=head; //处理第n个节点
for(i=1; i<len; i++)
temp=temp->next;
if(temp->data%2==1)
{
if(len==1) //仅剩下一个节点
{
head=NULL;
free(temp);
len--;
printf("Linked list is completely deleted!\n"); //链表里的节点都被删除
}
else
{
for(j=1; j<len-1; j++)
text=text->next;
text->next=NULL;
free(temp);
len--;
}
}
return head;
};
时刻把握好pr 、p 和
head 的位置,这类问题就能轻松解决。