初学C语言简单链表的问题,书上说p要指向head才能使用链表,我直接p=&a 发现结果和p=head一样,为什么

作者&投稿:枝界 (若有异议请与网页底部的电邮联系)
c语言带空头结点的单链表删除 free(p)后为什么还要p==null~

这是c语言的问题。其实楼上说的很清楚。free只是释放了p所指向的堆地址,p还是指向的这个地址。这个操作是让操作系统知道这片堆地址已经从原来的被占用,变成了可使用。这时候你其实还是可以用p去操作这个地址。但是这操作是不安全的。因为操作系统默认这片堆地址可以随意使用。当其他程序刚好调用这个地址时,系统会毫不犹豫的把这地址分配给它。这就会导致很多问题。所以你释放后,一定要把指针指向空值。不要使用这种“野指针”

从head节点开始搜索,找到A的前驱节点B,即B→next=A
将A的前驱节点的后继节点修改为A的后继节点
即B→next=A→next
释放A占用的空间,即free(A)

head 是链表规范的写法,p一般做为游动指针,你若这样写结果上是没错的,但是给阅读程序的人带来不便,你要知道,真正的程序代码不是这么几行的,所以基本就约定俗称了链表头有专门的head 表示,你把链表头赋给了p,若在程序的某个地方再次需要操作链表,就需要链表头,只要链表头才能把整个链表联系起来进行操作,而你此时的p已经到NULL了,链表头丢失,无法操作,且随便用字母声明的变量在专业的程序里是极不赞成的,因该使用有一定意义的单词或字母的组合同时兼顾大小写,这样的程序别人看了一目了然,且日后你看的时候也不至于忘了当初这个变量代表啥,所以head就表示为链表头了。
给你随便找了一个链表的程序,看了你就会知道head 的重要性。
#include <stdlib.h>
#include <stdio.h>
#define NULL 0
#define LEN sizeof(struct student)

struct student
{
long num; /*学号*/
float score; /*分数,其他信息可以继续在下面增加字段*/
struct student *next; /*指向下一节点的指针*/
};

int n; /*节点总数*/

/*
==========================
功能:创建节点
返回:指向链表表头的指针
==========================
*/
struct student *Create()
{
struct student *head; /*头节点*/
struct student *p1=NULL; /*p1保存创建的新节点的地址*/
struct student *p2=NULL; /*p2保存原链表最后一个节点的地址*/

n = 0; /*创建前链表的节点总数为0:空链表*/
p1 = (struct student *)malloc(LEN); /*开辟一个新节点*/
p2 = p1; /*如果节点开辟成功,则p2先把它的指针保存下来以备后用*/

if (p1 == NULL) /*节点开辟不成功*/
{
printf("\nCann't create it, try it again in a moment!\n");
return NULL;
}
else /*节点开辟成功*/
{
head = NULL; /*开始head指向NULL*/

printf("Please input %d node -- num,score: ",n+1);
scanf("%ld,%f",&(p1->num),&(p1->score)); /*录入数据*/
}

while(p1->num != 0) /*只要学号不为0,就继续录入下一个节点*/
{
n += 1; /*节点总数增加1个*/

if (n==1) /*如果节点总数是1,则head指向刚创建的节点p1*/
{
head = p1;
/*
注意:
此时的p2就是p1,也就是p1->next指向NULL。
这样写目的是与下面else保持一致。
*/
p2->next = NULL;
}
else
{
p2->next = p1; /*指向上次下面刚开辟的节点*/
}

p2 = p1; /*把p1的地址给p2保留,然后p1去产生新节点*/

p1 = (struct student *)malloc(LEN);
printf("Please input %d node -- num,score: ",n+1);
scanf("%ld,%f",&(p1->num),&(p1->score));
}
p2->next = NULL; /*此句就是根据单向链表的最后一个节点要指向NULL*/

free(p1); /*释放p1。用malloc()、calloc()的变量都要free()*/
p1 = NULL; /*特别不要忘记把释放的变量清空置为NULL,否则就变成"野指针",即地址不确定的指针。*/
return head; /*返回创建链表的头指针*/
}

/*
===========================
功能:输出节点
返回: void
===========================
*/
void Print(struct student *head)
{
struct student *p;

printf("\nNow , These %d records are:\n",n);
p = head;
if(head != NULL) /*只要不是空链表,就输出链表中所有节点*/
{
printf("head is %o\n", head); /*输出头指针指向的地址*/
do
{
/*
输出相应的值:当前节点地址、各字段值、当前节点的下一节点地址。
这样输出便于读者形象看到一个单向链表在计算机中的存储结构,和我们
设计的图示是一模一样的。
*/
printf("%o %ld %5.1f %o\n", p, p->num, p->score, p->next);
p = p->next; /*移到下一个节点*/
}
while (p != NULL);
}
}

/*
==========================
功能:删除指定节点
(此例中是删除指定学号的节点)
返回:指向链表表头的指针
==========================
*/

/*
单向链表的删除图示:
---->[NULL]
head

图3:空链表

从图3可知,空链表显然不能删除

---->[1]---->[2]...---->[n]---->[NULL](原链表)
head 1->next 2->next n->next

---->[2]...---->[n]---->[NULL](删除后链表)
head 2->next n->next

图4:有N个节点的链表,删除第一个节点
结合原链表和删除后的链表,就很容易写出相应的代码。操作方法如下:
1、你要明白head就是第1个节点,head->next就是第2个节点;
2、删除后head指向第2个节点,就是让head=head->next,OK这样就行了。

---->[1]---->[2]---->[3]...---->[n]---->[NULL](原链表)
head 1->next 2->next 3->next n->next

---->[1]---->[3]...---->[n]---->[NULL](删除后链表)
head 1->next 3->next n->next

图5:有N个节点的链表,删除中间一个(这里图示删除第2个)
结合原链表和删除后的链表,就很容易写出相应的代码。操作方法如下:
1、你要明白head就是第1个节点,1->next就是第2个节点,2->next就是第3个节点;
2、删除后2,1指向第3个节点,就是让1->next=2->next。
*/
struct student *Del(struct student *head, long num)
{
struct student *p1; /*p1保存当前需要检查的节点的地址*/
struct student *p2; /*p2保存当前检查过的节点的地址*/

if (head == NULL) /*是空链表(结合图3理解)*/
{
printf("\nList is null!\n");
return head;
}

/*定位要删除的节点*/
p1 = head;
while (p1->num != num && p1->next != NULL) /*p1指向的节点不是所要查找的,并且它不是最后一个节点,就继续往下找*/
{
p2 = p1; /*保存当前节点的地址*/
p1 = p1->next; /*后移一个节点*/
}

if (num == p1->num) /*找到了。(结合图4、5理解)*/
{
if (p1 == head) /*如果要删除的节点是第一个节点*/
{
head = p1->next; /*头指针指向第一个节点的后一个节点,也就是第二个节点。这样第一个节点就不在链表中,即删除。*/
}
else /*如果是其它节点,则让原来指向当前节点的指针,指向它的下一个节点,完成删除*/
{
p2->next = p1->next;

}

free(p1); /*释放当前节点*/
p1 = NULL;
printf("\ndelete %ld success!\n",num);
n -= 1; /*节点总数减1个*/
}
else /*没有找到*/
{
printf("\n%ld not been found!\n",num);
}

return head;

你改过之后运行过吗?我运行后结果是不一样的。

这是没改过的

这是改过后的结果



p=head调用子函数


c语言的链表怎么理解
回答: 你不是说C语言的链表吗?就得自己写个数据结构。C++默认的链表类是基于STL的。建议你看一下书。 追问: 啊?我C语言都没有学好,就去看C++? 回答: 呵呵,不是这个意思。刚才那个程序是C的。C++的STL中有自带的链表类,建议你以后学习。把握链表,核心是结点,结点核心就是数据+指针。多...

一口气玩转链表(C语言版)
支持双向循环链表则同时支持正向和反向遍历。这些高级结构的创建和使用示例也在文中提供。结论本文详细介绍了链表的基本概念、创建过程以及各种操作,包括静态链表、双向链表和循环链表。这些内容都包含在一套通俗易懂的C语言教程中,适合有一定C语言基础的学习者深入学习数据结构和算法。

链表的创建(C语言完整实现)
使用链表时,我们可以遍历链表获取数据,如果链表包含头结点,可能需要特殊处理。例如,一个带头结点的链表输出结果会包含头结点的值。总之,链表是一种灵活的数据结构,通过C语言的实现,无论是链表的创建还是使用,都提供了丰富的可能性。我的原创教程,以通俗易懂的方式讲解,适合C语言基础的读者深入学习...

C语言中怎样用链表保存结构体数据(动态数据结构)
单向链表很简单的,你这几这么就可以了:struct client{ char account[14]; \/\/账号 char name[10]; \/\/名字 char identity[20]; \/\/身份证号 char address[15]; \/\/地址 long int money; \/\/存款(可存可取)client* pNext; \/\/指向下一个节点,如果是最后一个节点则为NULL ...

C语言链表的使用方法
下面的程序是单链表的建立与输出,都有详细的注释,相信你能看的懂 但要想学习链表必须得掌握了一定的C语言基础 下面这个链表的作用是建立5个结点的单链表,5个结点的值输入以后,依次输出各个结点的值 include<stdio.h> include<stdlib.h> \/\/链表的建立与输出 struct node\/\/定义结点的类型 { int ...

如何用C语言创建一个链表,实现增、删、改、查?
\/\/1、写出建立一个带头结点的线性链表的函数,其中每个结点包括学号、姓名、分数三个数据域。函数形式如下:NODE *creat_link(int direction){ NODE *head,*p,*tail;int xh,i=1;if(direction==1) \/\/当direction的值为1时,新建立的结点连到尾部 { tail=head=(NODE *)malloc(sizeof(NODE));h...

用c语言建立100个节点的链表
include <stdio.h>#include <stdlib.h>typedef struct nodeA numNode;struct nodeA{ int num; numNode* up; numNode* down;};int nodeNum;numNode* top = NULL;numNode* bottom = NULL;numNode* NumNode_new(int num){ numNode* node = malloc(sizeof(numNode)); node-...

c语言的链表是干嘛的。
用来存储的,和数组相对应,数组是连续存储的,就是数组的各个元素是按顺序排列的,但是链表就不同了,可以不是连续的,存储方式比较灵活,通过指针来寻找下一个元素

c语言链表高手帮下忙 谢(请用通俗的话)
你要将这个新结点插入到p所指结点的后面,那么:1,s的next指针和p原先的next指针所指向的结点(也就是原先p所指结点的后一个结点)拉手(s->next=p->next;)2.p的next指针和s拉手(p->next=s;)。然后结点就插入了链表。s是首址,指向你刚刚开辟的新结点(你要在链表中插入,肯定得先开辟一个...

自学完C后,就学数据结构(C语言版的)里面的一个链表的例子里面有的个stat...
1 Status可能是一个typedef的类型,它只是代表插入成功与失败,完全可以用bool类型代替,这个对功能无影响;2 LinkList &L表示L的一个引用,引用作为形参,参数就不是“值传递”了,如在函数中改变形参的值,则被引用的变量值也相应改变。c语言中支持引用;3 void main()或许可以编译通过,但是不规范...

灵石县15642073439: C语言 链表 程序的相关问题 p = h - >next; h - >next = p;区别是什么 ?还有如下问题 -
谈志北豆: 不是很好讲,指针操作很基础,其它的又是逻辑操作.首先,标题的两个赋值语句,区别就是被赋值的不一样,等号左侧被赋值,也就是被改变,右侧的不变.在你的例子中,两个语句中间,实际上p进行了大量改变,也就是最后将h->next改变了.其次,指针链表操作,每一本基础语法书上都有详细讲解,比这里两句话说的明白的多,类似的例子会在书上专门讲解,建议基础问题看书.最后,逻辑上确实绕混,r = q->next; q->next = p;p = q;q = r; 这其实是实现了指针链表中两个相邻节点的位置互换.逻辑上有点像汉诺塔,r这个临时变量只是为了中间接手记录一下地址.

灵石县15642073439: C语言链表问题,初学者看不懂,求大神解释下这个程序的每一步. -
谈志北豆: NODE * fun(NODE *h) //NODE是节点结构体定义,函数应该是返转一个链表,也就是头节点变成尾,尾变成头 { NODE *p, *q, *r;p = h; //p指向传进来的节点h,应该是头节点if (p == NULL) //假如传进来的链表节点h为空,说明是空链表,没法反...

灵石县15642073439: C语言链表的使用方法 -
谈志北豆: 下面的程序是单链表的建立与输出,都有详细的注释,相信你能看的懂 但要想学习链表必须得掌握了一定的C语言基础 下面这个链表的作用是建立5个结点的单链表,5个结点的值输入以后,依次输出各个结点的值#include<stdio.h>#include<...

灵石县15642073439: C语言链表概念 -
谈志北豆: 简单说来,就是通过指针指向,把两个结构体连接起来.比如定义下面这个结构体 struct node { int data; struct node *next; } 可以看到结构体里面定义了一个自身类型的指针,通过让指针指向另外一个结构体,我们就能通过结构体里面的next变量访问下个结构体里面的内容,而通过下一个结构体,同样可以通过下一个结构体的next指向,找到下一个这种类型的结构体,这样就形成了所谓的链表.

灵石县15642073439: 一个关于链表的问题!~1求教c大神 -
谈志北豆: 第一个问题,我觉得你那书上印错了,\r\n要不然就是 scanf(\"%s\",new->nam...

灵石县15642073439: C语言里面关于链表的一个函数 -
谈志北豆: 你的代码是错的,这是尾插法建立链表的程序 head=(NODE*)malloc(sizeof(NODE)); q=head; //申请一个头结点 这是一个带头结点的链表 for(i=1;i { p=(NODE*)malloc(sizeof(NODE)); printf("Enter a element\n"); q->next=p; //这里应该是q->next 表示将新申请的结点p加到原表尾 q=p; //新结点p成为新的表尾 }

灵石县15642073439: C语言单链表问题
谈志北豆:你的问题好像不是很清楚,如果是调试时一闪而过的话应该是creat函数中的scanf()搞的鬼,在scanf中的最后一个回车被当做是合法字符传递给getch(),导致一闪而过.可以试一下下面的方法:在main函数中的getch();这句话前面加上一句:fflush(stdin);目的是清除输入缓冲区.应该可以解决问题. 如果还有其他的问题的话,可以再提出来. 按照上面改了之后再输入 102,25 0,0 显示正确,没有任何问题 不客气,我是在devc++上实验的,而且运行结果无误.估计你是初学c语言,希望你再接再厉,继续加油奥!

灵石县15642073439: 问个C语言链表问题
谈志北豆: #include"stdio.h" #include"conio.h" #include"stdlib.h"struct node { int num; struct node *next; }; typedef struct node node;node *list(void) { node *head,*p,*q; int i,n; printf("Input List Length:"); scanf("%d",&n); while (n<0) { printf("Input...

灵石县15642073439: 请教c语言中链表的基本知识. -
谈志北豆: List是指向Node(struct node)的节点的指针,List *pist中的pist是指向Node(struct node)的双指针,即Node **pist; 后面的话没太看懂,其实那句 typedef Node *List 完全可以在定义node结构体的时候就为其指定别名,即 typedef struct node{ Item item; struct node *next; }Node,*List; 这样完全可以

灵石县15642073439: c语言单链表操作问题 -
谈志北豆: #include<stdio.h>/*建立一个链表*/#include<malloc.h>#define NULL 0#define LEN sizeof(struct student)#define INSERT 0/*INSERT为零时,删除;为一时,插入*/ struct student { long num; char name[20]; struct student *next; }; int n; struct student ...

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网