我正在阅读 The Design of the UNIX Operating System (Maurice Bach) 。
他给出了以下双重链接列表的例子。
struct queue{
//pointers (back and forward)
//other data
}*bp, *bp1
bp1->forp = bp->forp; //1
bp1->backp = bp; //makes sense
bp->forp = bp1; //makes sense
bp1->forp->backp = bp1; //2
我无法理解标记为1
和2
的陈述的目的。 1
似乎有误,2
看起来多余。
这是创建双向链表的有效方法吗?
答案 0 :(得分:3)
代码是正确的。
bp
是一个双重链接列表。
您希望将bp1
插入bp
作为列表中的第二项(代码所做的)。
要做到这一点,你需要设置4个指针:
bp1->forp
应指向列表中的第二项bp->forp
(上面//1
)
bp1->backp
应指向列表中的第一项bp
bp->forp
应指向插入的项bp1
第二项bp1->forp->backp
的后退指针应指向插入的项目bp1
。 (//2
以上)
修改:
让我们调用结构A,B,C,D ......
列表(由bp
指向由插入前的A,C,D ...组成。我们想要插入B(由bp1
指向。
<->
表示前向和后向指针。
在:
bp --> A <-> C <-> D <-> E <-> ...
bp1--> B
后:
bp--> A <-> B <-> C <-> D <-> E <-> ...
答案 1 :(得分:1)
将项目插入双向链接列表时,必须更改指向新元素的两个指针和指向新元素的两个指针。
标有//1
的行将插入位置后的下一个指针设置为下一个指针。标记为//2
的行将下一个元素的前一个指针设置为新元素,完成它们之间的双向链接。
请注意,当新元素添加到列表末尾时,此代码将出现段错误。在这种情况下,bp1->forp
将为NULL,因此bp1->forp->backp
将尝试取消引用空指针。
修改强>
开头:
bp ->forp = next
next->backp = bp
bp1 ->forp = null
bp1 ->backp = null
The list looks like this. bp and next are linked, bp1 is outside of the list.
/---\/
[bp] [next] [bp1]
/\---/
行//1
bp ->forp = next
next->backp = bp
bp1 ->forp = next
bp1 ->backp = null
the forward pointer of bp1 points to the next element, but nothing points
to bp1 yet:
/------------\/
/ /----\/
[bp] [bp1] [next]
/\------------/
行[{1}}
之前//2
行bp ->forp = bp1
bp1 ->forp = next
bp1 ->backp = bp
next->backp = bp
The link from next to bp1 hasn't been updated yet - it still points to bp:
/---\/ /---\/
[bp] [bp1] [next]
/\----/ /
/\-----------/
//2
答案 2 :(得分:1)
Is this a valid way to create a doubly linked-list?
**不,现在,这段代码只会给你一个分段错误。很明显,如果你在每一步之后添加以下行,原因很简单:
printf("bp = %#x\n\tbp->forp=%#x\n\tbp->backp=%#x\n", bp, bp->forp, bp->backp);
printf("bp1 = %#x\n\tbp1->forp=%#x\n\tbp1->backp=%#x\n", bp1, bp1->forp, bp1->backp);
首先,您需要分配和初始化您的结构:
bp = malloc(sizeof(struct queue));
bp->forp = NULL;
bp->backp = NULL;
bp1 = malloc(sizeof(struct queue));
bp1->forp = NULL;
bp1->backp = NULL;
然后我们打印你会看到这样的值:
bp = 0x804b008
bp->forp=0 //forward and back pointers are not pointing anywhere, good start
bp->backp=0
bp1 = 0x804b018
bp1->forp=0
bp1->backp=0
在以下几行之后:
bp1->forp = bp->forp; //bp1->forp is pointing no where (NULL), neither is bp->forp
// so this does nothing really...
bp1->backp = bp;
bp->forp = bp1;
现在你有类似的东西:
bp = 0x804b008
bp->forp=0x804b018
bp->backp=0
bp1 = 0x804b018
bp1->forp=0
bp1->backp=0x804b008
正如你所说,这是有道理的。现在我们尝试下一行了吗?
bp1->forp->backp = bp1; //2
^
|
+------ That's NULL, and a seg fault.
在此之前你还需要一行:
bp1->forp-> = bp;
bp1->forp->backp = bp1;
现在你很高兴。
**假设一个最初为空的列表。