Linux C编程连载【5】- 关于双链表“掉链子”的问题

 【问题】用双链表实现贪吃蛇时,用gcc编译后,执行发生段错误。用gdb调试发现错误位于删除操作,后检查发现真正的原因出在插入操作。如题所示,双链表掉链子了,没接上。

【分析】

如图1所示,在插入C之前,A和B节点是链接的,现在要在节点A和B节点之间插入一节点C,参照教科书的算法如下:

(1) C->prev=A

(2) C->next=B

(3) A->next=C

(4) B->prev=C

错误代码实现如下:


 

上述代码step 4就是导致段错误的“真凶”。下面具体分析为什么错了:

在插入C节点前,A->next = B(表示A->next指向B)是成立的。但执行步骤3后,A->next链子断开了,此时A->next=C,即A->next指向了C,此时再用A->next->prev = C,就相当于C->prev = C。图1所示操作4显然没有实现,双链表B->prev=C “掉链子"了。有趣的是,gdb调试时常找不到段错误真正的原因。

如何修改?

很简单,改为C->next->prev=C或者A->next->next->prev = C就可以了。

图1 双链表插入操作(1)

如图2所示,下面我们改变链接的顺序,看看代码有和变化。

step 1 B->prev=C

此时A->next=B成立,故

step 2 C->prev=A

step 3 C->next=B,经过step1,2后,B->prev链子断开了,但A->next链子没有断开,此时A->next=B仍成立【注:此前发布的博文,此处有错误,修改时间2011-11-18

step 4 A->next=C

 

图2 双链表插入操作(2)

 

【双链表操作原则】节点A和B相互链接,保证A->next=B,B->prev=A。

无论进行何种操作,都要保证相互链接的节点满足上述原则。

posted @ 2011-10-29 19:55  j2ee技术  阅读(144)  评论(0编辑  收藏  举报