
typedef struct ooo{ //定义链表结构体 int value; struct ooo* next; }node; typedef struct _list{ //代表头结点 node* head; }list; //声明结点创建函数 add void add(int data,list* list); //主函数 int main() { list list; list.head = NULL; //定义头结点,并初始化为空 int data; //录入数据,输入-1 代表结束 do { scanf("%d",&data); if (data!=-1) { add(data,&list); } }while(data!=-1); return 0; } //定义新结点函数 add void add(int data,list* list) { node* new=(node*)malloc(sizeof(node)); //创建新结点并录入数据 new->value=data; new->next = NULL; //寻找已创建结点中的最后一个结点 node* last= list->head; //让最后一个结点等于此时的头结点 if(last) //遍历所有存在的结点,直到到达最后一个 { while(last->next) { last=last->next; } last->next = new; //链接最后一个结点和新结点 new } else { list->head=new; //最初创建第一个新结点 new 时,让 head 头结点=该结点。 } } 问题:看到最后可得知头结点 head 应该永远等于第一次创建的 new 结点, 即 head->next=new->next=NULL,并且每次进入 add 函数,last 都会等于 head,那么 last->next 也应该是 NULL, 所以头结点 head 的 next 永远是 NULL,那它到底是怎么和后边的结点连上的??? 而进来 add 函数以后,last 每个结点间又是怎么连上的呢?? 想了很久头都大了,仍然不得其解!!只能寄望于 v2 大佬了!!本小白先谢过啦!!!!
1 wutiantong 2019-05-14 19:43:52 +08:00 都有注释了还看不懂么? 要不你调试一遍,观察一下变量值的变化。 |
2 wutiantong 2019-05-14 19:45:31 +08:00 话说你的问题描述真是够迷糊的了。。。 |
3 maichael 2019-05-14 19:47:24 +08:00 " last->next = new; //链接最后一个结点和新结点 new" 这不就是了吗。 |
4 across 2019-05-14 19:49:59 +08:00 via iPhone 放 ide 里面单步调试一步步看。 估计你是没理解中间 while 内容,每次都从头遍历一遍,找到最后一个节点 |
5 b00tyhunt3r OP ** @wutiantong 抱歉重新组织了一下语言! 问题:看到最后可得知头结点 head 应该永远等于第一次创建的 new 结点, 即 head->next=new->next=NULL, 并且每次进入 add 函数,都会令 last 等于 head,那么 last->next 此时也应该是 NULL, 所以头结点 head 的 next 永远是 NULL,那它到底是怎么和后边的结点连上的??? 问题 2: 而进入到 add 函数以后, ``` last->next = new; //找到最后的结点后,链接到新结点 new 上 ``` 这一段可以看出是用 last 链接了新结点,但是在找 last 的过程中,一上来 last 自身的 next 为 NULL,那么是怎么一步步遍历到最后一个结点上的呢?!?!** |
6 atx 2019-05-14 19:52:58 +08:00 重点在这句 while(last->next) |
7 kiddult 2019-05-14 19:54:49 +08:00 |
8 xiri 2019-05-14 19:56:18 +08:00 楼主你这是不懂链表还是不懂 C 啊,,,,,, “看到最后可得知头结点 head 应该永远等于第一次创建的 new 结点”,你好好看看 add()函数最后一个代码块,连 if{}else{}怎么运行的都不知道了吗? 第一次运行的时候 last 为 null,所以直接把 head 赋值为这个新建的节点 new,然后 head 就不为空了,再次执行 add()函数的时候 last 就也不为空了,那 list->head=new 还会执行??? |
9 ysc3839 2019-05-14 19:59:45 +08:00 via Android @b00tyhunt3r 问题 2,“ last 自身的 next 为 NULL ”,说明这就是最后一个节点。 |
10 chashao 2019-05-14 20:00:09 +08:00 via Android 在第一次 add 时,last 是 NULL 所以把 head=new,第二次 add 就会用 while 来遍历了 |
11 bp0 2019-05-14 20:04:38 +08:00 last 指向 list->head,只有第一次进入的时候是 NULL。后面再进入就不再是 NULL 了。 你不能理解的原因可能是因为 “ if(last) //遍历所有存在的结点,直到到达最后一个 ” 这个注释是错误的,正确的注释应该是:“ 判断链表是否为空”。 如果链表为空,list->head = new。不是空则循环到链表尾部并把新节点挂入。 这程序好多问题,建议你看看其他书吧,别被耽误了。 |
12 akira 2019-05-14 20:09:25 +08:00 "并且每次进入 add 函数,last 都会等于 head" 这句话有问题 当自己的理解和实际代码运行不一致的时候 ,一定是你的理解有问题,单步调试看是哪里理解错了 啊 |
13 xiri 2019-05-14 20:11:41 +08:00 @xiri 算了,直接讲太麻烦了,我直接给你口头模拟一边链表连接的过程。 1. head 为空,执行 add 函数时新建了一个节点 new,last=head=NULL,所以这时候直接执行 else 后面的代码,head 指向新建的节点 new,不再为空 2. head 不再为空,但此时只有一个节点,head->next=NULL此时执行 add 函数,last=head,不为空,执行 if 后面的代码块,此时先遇到 while 循环,由于 last->next=head->next=NULL,所以直接跳过,然后 last->next=new 将新节点加在最后面,这时整个链表有两个节点 3. head 不再为空,head->next 也不为空,执行 add 函数,last=head,不为空,执行 if 后面代码块。此时 last->next 也不为空,执行 while 循环,直至 last->next=NULL 时结束(也就是说 last 指向链表最后一个节点时结束),再然后 last->next=new 又新节点加在最后面,这时整个链表有三个节点 ...... 后面就跟第三步时完全一样的,关键点在那个 while 循环,它会让 last 指向最后一个节点,之后再执行 last->next=new,也就是将节点加在链表最后面了 |
14 iceheart 2019-05-14 20:40:54 +08:00 via Android 甭管单向链表双向链表还是异或链表都应该是俩指针,一头一尾。 单指针链表要么当栈使,要么追加元素复杂度是 O(n)的。这个是后者,重新找一段代码学霸吧 |
15 ThomasZ 2019-05-14 20:50:36 +08:00 via Android 调试一把,看看数据变化就知道咋回事了 |
16 JerryCha 2019-05-14 21:08:06 +08:00 每一次 add 在创建好新节点后,会从头开始遍历到最后一个节点为止,然后把新节点接上。 这写法还真是简洁,涨姿势了。 |
17 vx2018 2019-05-15 11:10:48 +08:00 只有一个节点时直接插 next, 多个节点时用临时指针遍历到最后一个插到 next 嘛 |
18 b00tyhunt3r OP 感谢各位大哥!!我真辣鸡啊! |