使用graphviz绘制双向链表

Posted

技术标签:

【中文标题】使用graphviz绘制双向链表【英文标题】:Draw doubly linked list using graphviz 【发布时间】:2022-01-23 05:58:36 【问题描述】:

我使用 Graphviz(点)绘制了一个双向链表,如下所示,但节点未对齐。如何对齐节点?

digraph "Doubly Linked List" 
        rankdir=LR;
        node [shape=record];
        e [label="nil" shape=circle];
        a [label=" <ref1> | <data> 1 | <ref2>  "]
        b [label=" <ref1> | <data> 5 | <ref2>  "];
        c [label=" <ref1> | <data> 7 | <ref2>  "];
        d [label="nil" shape=circle];
        e -> a:ref1:c      [arrowhead=dot, arrowtail=vee, dir=both, headclip=false];
        a:ref2:c -> b:data:n [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
        b:ref2:c -> c:data:n [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
        c:ref2:c -> d      [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
        c:ref1:c -> b:data:s [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
        b:ref1:c -> a:data:s [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];

【问题讨论】:

【参考方案1】:

Sroush提供了类似html形状的解决方案,但我找到了一种使用记录节点here的方法,如下:

digraph "Doubly Linked List" 
        rankdir=LR;
        node [shape=record];
        e [label="nil" shape=circle];
        a [label=" <ref1> | <data> 1 | <ref2>  "]
        b [label=" <ref1> | <data> 5 | <ref2>  "];
        c [label=" <ref1> | <data> 7 | <ref2>  "];
        d [label="nil" shape=circle];
        e -> a:ref1:c      [arrowhead=dot, arrowtail=vee, dir=both, headclip=false];
        a:ref2:c -> b:data:n [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
        b:ref2:c -> c:data:n [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
        c:ref2:c -> d      [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
        c:ref1:c -> b:data:s [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
        c:ref1:c -> b:data:w[weight = 100, style = invis]; <- add this
        b:ref1:c -> a:data:s [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
        b:ref1:c -> a:data:w[weight = 100, style = invis]; <- add this

【讨论】:

【参考方案2】:

在高层次上,答案是rank=same ... nodes here ... 但是,记录形状的节点和排名相同的边缘会产生点烧心,或者更准确地说会产生以下错误消息:

Warning: flat edge between adjacent nodes one of which has a record shape - replace records with HTML-like labels
  Edge e -> a
Error: lost e a edge
Error: lost a b edge
Error: lost b a edge
Error: lost b c edge
Error: lost c b edge
Error: lost c d edge

因此,如果我们将节点更改为“类似 html”的形状 (https://graphviz.org/doc/info/shapes.html#href),您会得到:

digraph "Doubly Linked List" 
        node [shape=plaintext]  // for correct display of table
    rank=same              // all on same rank
        e [label="nil" shape=circle];
        a [label=<<table border="0" cellspacing="0" cellborder="1"><tr>
          <td port="ref1"   fixedsize="true"></td>
      <td port="data"   fixedsize="true">1</td>
      <td port="ref2"   fixedsize="true"></td>
          </tr></table>>]

        b [label=<<table border="0" cellspacing="0" cellborder="1"><tr>
      <td port="ref1"   fixedsize="true"></td>
      <td port="data"   fixedsize="true">5</td>
      <td port="ref2"   fixedsize="true"></td></tr>
          </table>>]

        c [label=<<table border="0" cellspacing="0" cellborder="1"><tr>
      <td port="ref1"   fixedsize="true"></td>
      <td port="data"   fixedsize="true">7</td>
      <td port="ref2"   fixedsize="true"></td>
          </tr></table>>]

        d [label="nil" shape=circle];
    
        e -> a:ref1:c        [arrowhead=dot, arrowtail=vee, dir=both, headclip=false];
        a:ref2:c -> b:data:n [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
        b:ref2:c -> c:data:n [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
        // added :w to straighten edge
        c:ref2:c -> d:w        [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
        c:ref1:c -> b:data:s [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];
        b:ref1:c -> a:data:s [arrowhead=vee, arrowtail=dot, dir=both, tailclip=false];

(对不起),但它会给你:

【讨论】:

以上是关于使用graphviz绘制双向链表的主要内容,如果未能解决你的问题,请参考以下文章

带头节点的双向链表

双向链表

❤️数据结构入门❤️(1 - 4)- 双向链表

数据结构(链表——双向链表的实现)

双向链表的原理与实现

数据结构之带头结点的循环双向链表详细图片+文字讲解