user-0 提问: C语言单向链表增加新的结点

回复:
user: user-1
content: 结点我的理解是一块内存区域，它包含两部分：一是数据域，存放的是数据，二是指针域，存放的是指针，指向下一结点的地址。 增加结点，首先申请一块新的内存区域，大小是链表结构体大小。然后原链表的尾指向这块新申请的内存区域（以尾添加为例），最后将这块内存区域的指针域指向NULL,就完成了新增加结点的操作。

user: user-2
content: 节点存储的有用的信息，就是你使用链表的最原始驱动，你需要处理的信息都可以塞进去，额外加一个指针域用来把节点连接起来； 不用那么麻烦，你就把单向链表想象成在排队的一群人，后面的人把手搭在前面的人的肩膀上，这时候你要插队要先把你的手放在即将插入位置的前一位肩膀上，再把这位肩膀上别人的手挪到你的肩膀上，队就插成了，肩膀就好比链表节点的指针域，告诉下一位是谁； 现在在看代码就能看明白未来插入节点各种指针的备份。

user: user-0
content: 引用 7 楼 user-3的回复:插入1 2 3的步骤，LZ可以自己简单画个图 head----NULL tail-------NULL  插入第一个节点 p---------1(next=NULL) //生成新节点 head=p, tail=p就是 (head/tail)----1(next=NULL)  插入第二个节点 p---------2(next=NULL) //生成新节点 tail->next=p就是 (head/tail)-------1(next------p(2,next=NULL)) tail=p就是 head----1(next------tail(2,next=NULL)) //tail变成最后  插入第三个节点 p---------3(next=NULL) //生成新节点 tail->next=p就是 head-------1(next------tail(2,next------p(3,next=NULL))) tail=p就是 head----1(next--------------2,next------tail(3,next=NULL)) //tail变成最后  看链表里的p和tail的移动 请问有没有删除结点的例子？

user: user-1
content: 链表自己画一下图会理解的更清楚一些，尤其是在中间插入、删除结点的时候。

user: user-0
content: 引用 6 楼 user-3的回复:[quote=引用 4 楼 其实一开始我是拒绝的 的回复:] 4 插入p之后，p就是最后一个节点了，所以要修改tail指向p，即tail=p  插入p后为什么要tail=p，我知道最后的结点为NUll 是因为tail为NULL？ 因为tail永远指向链表最后一个节点，就像head永远指向第一个节点一样，所以tail不是NULL（也就是tail指向最后一个节点），而tail->next才是NULL（最后一个节点因为没有后续的节点了，所以next指针指向空）  比如插入 1 2 3 开始的时候，head是NULL，tail是NULL  插入第一个节点，首先生成节点p，然后给节点赋值 p->data=1, p->next=NULL 此时因为head是NULL，进入if(head==NULL)分支，执行head=p，此时head->data=1, head->next=NULL，也就是head指向了第一个节点1 接着因为p此时是最后一个节点（当前链表只有1个节点，p既是第一个节点，也是最后一个节点），所以要修改tail指向p，即执行tail=p, 此时tail->data=1, tail->next=NULL，也就是tail也指向了第一个节点1 到此，插入第一个节点结束，此时head指向了节点1，tail也指向了节点1，显然符合插入第一个节点的要求  插入第二个节点，首先生成节点p，然后给节点赋值 p->data=2, p->next=NULL 此时因为head不是NULL（而是指向节点1了），所以进入if(head==NULL)的else分支，执行tail->next=p, 也就是让tail的next指向新节点p，相当于把新节点连接在tail的后面，此时tail->data=1, tail->next=p(p->data=2, p->next=NULL) 此时可以发现p变成了最后一个节点（因为p连接在tail的后面），所以要修改tail指向最后一个节点（因为tail才应该是链表的最后），即执行tail=p, 此时tail->data=2, tail->next=NULL，也就是tail指向了新节点2 到此，插入第二个节点结束，此时head保持指向节点1不变，tail变成了指向节点2，显然符合head指向头一个节点1，tail指向最尾节点2的要求  插入第三个节点，首先生成节点p，然后给节点赋值 p->data=3, p->next=NULL 然后和插入第二个节点一样，先让tail->next=p，也就是新节点连接在tail的后面，然后再修改tail指向最后一个节点，即tail=p, 此时tail->data=3, tail->next=NULL，也就是tail指向了新节点3 到此，插入第三个节点结束，此时此时head保持指向节点1不变，tail变成了指向节点2，显然符合head指向头一个节点1，tail指向最尾节点3的要求 [/quote] 谢谢，我搞清楚了

user: user-3
content: 插入1 2 3的步骤，LZ可以自己简单画个图 head----NULL tail-------NULL  插入第一个节点 p---------1(next=NULL) //生成新节点 head=p, tail=p就是 (head/tail)----1(next=NULL)  插入第二个节点 p---------2(next=NULL) //生成新节点 tail->next=p就是 (head/tail)-------1(next------p(2,next=NULL)) tail=p就是 head----1(next------tail(2,next=NULL)) //tail变成最后  插入第三个节点 p---------3(next=NULL) //生成新节点 tail->next=p就是 head-------1(next------tail(2,next------p(3,next=NULL))) tail=p就是 head----1(next--------------2,next------tail(3,next=NULL)) //tail变成最后  看链表里的p和tail的移动

user: user-3
content: 引用 4 楼 其实一开始我是拒绝的 的回复:4 插入p之后，p就是最后一个节点了，所以要修改tail指向p，即tail=p  插入p后为什么要tail=p，我知道最后的结点为NUll 是因为tail为NULL？ 因为tail永远指向链表最后一个节点，就像head永远指向第一个节点一样，所以tail不是NULL（也就是tail指向最后一个节点），而tail->next才是NULL（最后一个节点因为没有后续的节点了，所以next指针指向空）  比如插入 1 2 3 开始的时候，head是NULL，tail是NULL  插入第一个节点，首先生成节点p，然后给节点赋值 p->data=1, p->next=NULL 此时因为head是NULL，进入if(head==NULL)分支，执行head=p，此时head->data=1, head->next=NULL，也就是head指向了第一个节点1 接着因为p此时是最后一个节点（当前链表只有1个节点，p既是第一个节点，也是最后一个节点），所以要修改tail指向p，即执行tail=p, 此时tail->data=1, tail->next=NULL，也就是tail也指向了第一个节点1 到此，插入第一个节点结束，此时head指向了节点1，tail也指向了节点1，显然符合插入第一个节点的要求  插入第二个节点，首先生成节点p，然后给节点赋值 p->data=2, p->next=NULL 此时因为head不是NULL（而是指向节点1了），所以进入if(head==NULL)的else分支，执行tail->next=p, 也就是让tail的next指向新节点p，相当于把新节点连接在tail的后面，此时tail->data=1, tail->next=p(p->data=2, p->next=NULL) 此时可以发现p变成了最后一个节点（因为p连接在tail的后面），所以要修改tail指向最后一个节点（因为tail才应该是链表的最后），即执行tail=p, 此时tail->data=2, tail->next=NULL，也就是tail指向了新节点2 到此，插入第二个节点结束，此时head保持指向节点1不变，tail变成了指向节点2，显然符合head指向头一个节点1，tail指向最尾节点2的要求  插入第三个节点，首先生成节点p，然后给节点赋值 p->data=3, p->next=NULL 然后和插入第二个节点一样，先让tail->next=p，也就是新节点连接在tail的后面，然后再修改tail指向最后一个节点，即tail=p, 此时tail->data=3, tail->next=NULL，也就是tail指向了新节点3 到此，插入第三个节点结束，此时此时head保持指向节点1不变，tail变成了指向节点2，显然符合head指向头一个节点1，tail指向最尾节点3的要求

user: user-0
content: 引用 1 楼 chxchxkkk的回复:结点我的理解是一块内存区域，它包含两部分：一是数据域，存放的是数据，二是指针域，存放的是指针，指向下一结点的地址。 增加结点，首先申请一块新的内存区域，大小是链表结构体大小。然后原链表的尾指向这块新申请的内存区域（以尾添加为例），最后将这块内存区域的指针域指向NULL,就完成了新增加结点的操作。 我对指针对指向好乱，能讲讲？

user: user-0
content: 4 插入p之后，p就是最后一个节点了，所以要修改tail指向p，即tail=p  插入p后为什么要tail=p，我知道最后的结点为NUll 是因为tail为NULL？

user: user-0
content: 引用 2 楼 user-3的回复:新增节点有两种方法，一种是把新增的节点插入到链表的结尾，一种是把新增的节点插入到链表的开头 插入到链接结尾的方法(也就是你贴图的代码和流程图，这里给你用文字解释一下) 1 申请一个新节点的内存p，并给新节点的字段赋值 2 如果链表的头节点为空，说明p是第一个插入的节点，所以head=p（最头的节点） 3 如果链表的头节点不为空，所以p不是第一个插入的节点，所以p应该插入tail的next，即tail->next=p 4 插入p之后，p就是最后一个节点了，所以要修改tail指向p，即tail=p  也就是如果数据 1 2 3 插入链表，数据的顺序还是保持 1 2 3 （即头节点是1，尾节点是3）  插入到链表开头的方法（其实和上面差不多，只是插入点相反而已） 1 申请一个新节点的内存p，并给新节点的字段赋值 2 如果链表的尾节点为空，说明p是第一个插入的节点，所以tail=p（最尾的节点） 3 如果链表的尾节点不为空，所以p不是第一个插入的节点，所以p应该插入head的前面，即p->next=head; 4 插入p之后，p就是最前一个节点了，所以要修改head指向p，即head=p  也就是如果数据 1 2 3 插入链表，数据的顺序还是保持 3 2 1（即头节点是3，尾节点是1） 我被那些什么 head=p，还有p-＞next=head搞混了， p-＞next=head什么意思，是p里面next的地址改变了？那p的地址和p里面的数据改变？

user: user-3
content: 新增节点有两种方法，一种是把新增的节点插入到链表的结尾，一种是把新增的节点插入到链表的开头 插入到链接结尾的方法(也就是你贴图的代码和流程图，这里给你用文字解释一下) 1 申请一个新节点的内存p，并给新节点的字段赋值 2 如果链表的头节点为空，说明p是第一个插入的节点，所以head=p（最头的节点） 3 如果链表的头节点不为空，所以p不是第一个插入的节点，所以p应该插入tail的next，即tail->next=p 4 插入p之后，p就是最后一个节点了，所以要修改tail指向p，即tail=p  也就是如果数据 1 2 3 插入链表，数据的顺序还是保持 1 2 3 （即头节点是1，尾节点是3）  插入到链表开头的方法（其实和上面差不多，只是插入点相反而已） 1 申请一个新节点的内存p，并给新节点的字段赋值 2 如果链表的尾节点为空，说明p是第一个插入的节点，所以tail=p（最尾的节点） 3 如果链表的尾节点不为空，所以p不是第一个插入的节点，所以p应该插入head的前面，即p->next=head; 4 插入p之后，p就是最前一个节点了，所以要修改head指向p，即head=p  也就是如果数据 1 2 3 插入链表，数据的顺序还是保持 3 2 1（即头节点是3，尾节点是1）