单项链表的建立和节点的删除
注意:
- scanf(" %c",&ans); //这个位置的空格不能省略。在使用%c格式读入字符时,空格字符和转义字符(包括回车)都会被当成有效字符,这是使用scanf()输入%c格式时需要格外注意的一点。
解决方式:在%c前面加入一个空格,忽略前面数据输入时存入缓冲区的回车符,避免被后面的字符型变量当做有效字符读入。 - if (head == NULL) //忘记写双等号了
- pr->next = p; //链上这个要放在else里面,两种情况,是或者不是头结点
- 竟然这些代码放到了else 中的while里面,这样如果是头结点那么就不会添加节点了,逻辑不够清晰。这是链上之后,向新结点添加数据,所以要放在if else条件判断之外,while循环的作用只是将pr的指向移动到尾结点(pr->next为空的节点)。
printf(“please input data:”);
scanf(" %d", &da);
p->data = da;
p->next = NULL;
return head;
5.这俩顺序不能换,要先将p保存到pr中,然后再顺着链表找下一个
pr = p;
p = p->next;
6.free§;//既然两个分支都有 ,那么就放到外面吧
7.head = DelNod(head,da); 在不把head作为返回值时候,这个程序就无限循环,可以看看head地址.。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct link *AppNod(struct link *head);
void DisLin(struct link *head);
void DelMem(struct link *head);
struct link *DelNod(struct link *head, int data);
struct link{
int data;
struct link *next;
};
int main()
{
struct link *head = NULL;
char ans;
int i=0;
int da;
printf("Do you want to add node to the link?(y/n)");
scanf(" %c",&ans);
while (ans == 'y')
{
i=i+1;
head = AppNod(head);
DisLin(head);
printf("Do you want to add node to the link?(y/n)");
scanf(" %c",&ans); //这个位置的空格不能省略
}
printf("The total number of nodes is %d\n",i);
printf("Please input the data that you want to delete:");
scanf("%d",&da);
head = DelNod(head,da); //在不把head作为返回值时候,这个程序就无限循环,为啥?
DisLin(head);
DelMem(head);
}
struct link *AppNod(struct link *head)
{
struct link *pr = head, *p = NULL;
int da;
p = (struct link *)malloc(sizeof(struct link));
if (p == NULL)
{
printf("There is no enough memory to allocate.");
exit(0);
}
warning: suggest parentheses around assignment used as truth value [-Wparentheses]|
if (head == NULL) //忘记写双等号了
{
head = p;
}
else
{
while (pr->next != NULL)
{
pr = pr->next;
}
pr->next = p; //链上这个要放在else里面
}
//竟然这些代码放到了while里面,这样如果是头结点那么就不会添加节点了
printf("please input data:");
scanf(" %d", &da);
p->data = da;
p->next = NULL;
return head;
};
//忘记加void也会警告,函数返回值的默认类型是整型,与函数原型声明中不同会报警
void DisLin(struct link *head)
{
struct link *p = head;
int j=1;
while (p != NULL)
{
printf("%d\t%d\n",j,p->data);
p = p->next;
j++;
}
}
void DelMem(struct link *head)
{
struct link *p = head, *pr = NULL;
while (p != NULL)
{
pr = p;
p = p -> next;
free(pr);
}
}
struct link *DelNod(struct link *head, int data)
{
struct link *p = head, *pr = head;
if (p == NULL)
{
printf("link is empty");
return head;
}
while (p->data != data && p->next != NULL)
{
pr = p; //这俩顺序不能换,要先将p保存到pr中,然后再顺着链表找下一个
p = p->next;
}
if (p->data == data)
{
if(p == head)
{
head = p->next;
}
else
{
pr->next = p->next;
}
free(p);//既然两个分支都有 ,那么就放到外面吧
}
else
{
printf("can't find the node");
}
return head;
}
附注:程序参考《C语言程序设计第三版》-苏小红P360-364,将删除链表节点的函数放到了主函数中,相比于书中P360代码,本文代码主函数增加了一个节点删除功能。