这是创建双重链表的有效方法吗?

时间:2012-11-12 14:33:39

标签: c doubly-linked-list

  

可能重复:
  context switch during doubly linked list creation

我正在阅读 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

我无法理解标记为12的陈述的目的。 1似乎有误,2看起来多余。

这是创建双向链表的有效方法吗?

3 个答案:

答案 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;

现在你很高兴。

**假设一个最初为空的列表。