在 .dot 树中强制执行水平节点排序

2024-03-20

我正在尝试使用 GraphViz 重新创建二叉搜索树的示例图。它最终应该是这样的:

这是我的第一次尝试:

digraph G {
    nodesep=0.3;
    ranksep=0.2;
    margin=0.1;
    node [shape=circle];
    edge [arrowsize=0.8];
    6 -> 4;
    6 -> 11;
    4 -> 2;
    4 -> 5;
    2 -> 1;
    2 -> 3;
    11 -> 8;
    11 -> 14;
    8 -> 7;
    8 -> 10;
    10 -> 9;
    14 -> 13;
    14 -> 16;
    13 -> 12;
    16 -> 15;
    16 -> 17;
}

但不幸的是 GraphViz 不关心树的水平位置,所以我得到:

如何添加约束以使顶点的水平位置反映它们的总顺序?


您可以按照添加不可见节点和不可见边的常用方法,并按照建议使用边权重等。graphviz 关于平衡树的常见问题解答 https://forum.graphviz.org/t/how-to-get-trees-more-balanced/966。在一些简单案例 https://stackoverflow.com/q/3105923/63733, 这就够了。

但有一个更好的解决方案:Graphviz 附带了一个名为 Graphviz 的工具gvpr (图模式扫描和处理语言)这允许

将输入图形复制到其输出,可能会转换其结构和属性、创建新图形或打印任意信息

自从Emden R. Gansner 通过创建一个脚本来完成所有工作,该脚本可以很好地布局二叉树 https://mailman.research.att.com/pipermail/graphviz-interest/2010q2/007101.html,具体方法如下(所有功劳归 ERG 所有):

将以下 gvpr 脚本保存到名为的文件中tree.gv :

BEGIN {
  double tw[node_t];    // width of tree rooted at node
  double nw[node_t];    // width of node
  double xoff[node_t];  // x offset of root from left side of its tree
  double sp = 36;       // extra space between left and right subtrees
  double wd, w, w1, w2; 
  double x, y, z;
  edge_t e1, e2;
  node_t n;
}
BEG_G {
  $.bb = "";
  $tvtype=TV_postfwd;   // visit root after all children visited
}
N {
  sscanf ($.width, "%f", &w);
  w *= 72;  // convert inches to points
  nw[$] = w;
  if ($.outdegree == 0) {
    tw[$] = w;
    xoff[$] = w/2.0;
  }
  else if ($.outdegree == 1) {
    e1 = fstout($);
    w1 = tw[e1.head];    
    tw[$] = w1 + (sp+w)/2.0;
    if (e1.side == "left")
      xoff[$] = tw[$] - w/2.0;
    else
      xoff[$] = w/2.0;
  }
  else {
    e1 = fstout($);
    w1 = tw[e1.head];    
    e2 = nxtout(e1);
    w2 = tw[e2.head];    
    wd = w1 + w2 + sp;
    if (w > wd)
      wd = w;
    tw[$] = wd;
    xoff[$] = w1 + sp/2.0;
  }
}
BEG_G {
  $tvtype=TV_fwd;   // visit root first, then children
}
N {
  if ($.indegree == 0) {
    sscanf ($.pos, "%f,%f", &x, &y);
    $.pos = sprintf("0,%f", y);
  }
  if ($.outdegree == 0) return;
  sscanf ($.pos, "%f,%f", &x, &y);
  wd = tw[$];
  e1 = fstout($);
  n = e1.head;
  sscanf (n.pos, "%f,%f", &z, &y);
  if ($.outdegree == 1) {
    if (e1.side == "left")
      n.pos = sprintf("%f,%f",  x - tw[n] - sp/2.0 + xoff[n], y);
    else
      n.pos = sprintf("%f,%f", x + sp/2.0 + xoff[n], y);
  }
  else {
    n.pos = sprintf("%f,%f", x - tw[n] - sp/2.0 + xoff[n], y);
    e2 = nxtout(e1);
    n = e2.head;
    sscanf (n.pos, "%f,%f", &z, &y);
    n.pos = sprintf("%f,%f", x + sp/2.0 + xoff[n], y);
  }
}

假设包含图形的点文件被称为binarytree.gv,您可以执行以下行:

dot binarytree.gv | gvpr -c -ftree.gv | neato -n -Tpng -o binarytree.png

结果是:

通过在脚本中切换一两行,您甚至可以让单个子节点位于左侧而不是右侧。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 .dot 树中强制执行水平节点排序 的相关文章

  • 使用 Java 和递归进行二叉树的级别顺序遍历

    我在使用递归时遇到二叉树的级别顺序遍历问题 我输入以下值 50 60 70 30 20 10 这是我正在使用的代码 public void levelOrder Node localRoot if localRoot null if loc
  • Graphviz - 如何使标签中的文本左对齐?

    我正在使用 graphviz 来可视化我正在解析的语言的 AST 我想包含源代码 作为标签 但 graphviz 对齐标签内的文本 这会扰乱我的缩进 并且代码对缩进敏感 这是问题的示例 第二行代码不应缩进 这是生成的 dot 文件的相关部分
  • 什么Python代码为二元运算符生成所有可能的分组(树)

    正如几个 SO 问题中所解释的 更抽象的是数学世界 http mathworld wolfram com BinaryBracketing html 加泰罗尼亚数字的序列恰好对应于可以为任何给定数量的运算符生成的括号分组的数量 但我还没有找
  • 使用点语言在 Graphviz 中压缩有向图

    我正在尝试实现特定图 对称排列群的凯莱图 的可视化 就像此处所做的那样 但使 用 Graphviz 2 28 和 Dot source euclideanspace com http www euclideanspace com maths
  • Graphviz安装Ubuntu 14.04

    我正在尝试使用创建一个点文件京东项目 http javaddlib sourceforge net jdd 它需要安装 Graphviz 我尝试使用控制台安装它 sudo apt get install graphviz 在这种情况下 虽然
  • 如何控制 graphviz 中的节点放置(即避免边缘交叉)

    我正在使用 graphviz 点 生成您可以在下面看到的图表 左下角的节点 红色椭圆 会引起烦恼 因为它的边缘与相邻节点的多个边缘交叉 有没有办法将节点放置限制在某个区域 您可以创建一个不可见的约束 以使红色节点出现在所有其他节点的左侧 r
  • 如何可视化 sklearn GradientBoostingClassifier?

    我训练过一个梯度提升分类器 http scikit learn org stable modules generated sklearn ensemble GradientBoostingClassifier html sklearn en
  • graphviz dot:如何将箭头从节点插入到箭头中心

    我尝试使用 graphviz 包中的 dot 创建用于 MPLUS 分析的图表 有人有使用点可视化结构方程模型 潜在类混合模型的经验吗 特别是有一个功能我不知道如何做得漂亮 我需要从节点到另一个箭头中心的箭头 例如 C V A gt B 我
  • graphviz 绘图太宽

    我正在做练习 在 jupyter 笔记本中使用 graphviz 创建决策树 然而 决策树过于宽泛 这是代码 from sklearn tree import export graphviz export graphviz tree out
  • 如何通过层序遍历创建二叉树?

    Given a level order列表 其中可以包括None值 如何构建二叉树 None列表中的值即None节点不能有任何子节点 left or right值 from typing import List Optional class
  • 如何更改 graphviz 的默认字体大小?

    我使用 doxygen graphviz 来记录我的代码 graphviz 在生成图像方面做得很好 有什么方法可以更改 graphviz 的默认字体大小吗 默认值为 14 但我想使用 12 更改单个元素 例如节点 子图 边缘等 的字体大小确
  • 如何非递归地获取二叉树中叶节点的数量?

    我有一个练习问题被难住了 在不使用递归的情况下获取二叉树中叶节点的数量 我已经四处寻找一些想法 我已经看到了一些想法 例如将节点传递到堆栈 但我不知道当有多个分支时如何做到这一点 任何人都可以提供指针吗 NumberOfLeafNodes
  • 设置预定义的节点样式?

    在过去的 15 分钟里 我一直在谷歌上搜索 试图找到这个问题的答案 但我似乎无法弄清楚 我的任务是为我在工作中开发的一些应用程序构建一些小流程图 他们不需要任何花哨的东西 因为他们将在 vizio 中将其转换为他们喜欢的格式 他们甚至说我们
  • 2 个二叉树的交集会引发堆栈溢出错误

    我试图将两个二叉树相交 并使用相同的节点创建一个新的二叉树 但以下内容会产生 stackOverflow 错误 谁能帮我 private OrderedSet
  • 将边权重传递给networkx中的graphviz_layout

    每个人都找不到如何将权重列表的属性名称传递给networkx中的graphviz layout 像这样的事情 nx spring layout G weight weight sum 但与nx graphviz layout G 也许有人会
  • 使用霍夫曼代码压缩文件的步骤

    我知道有很多涉及霍夫曼代码的问题 包括我自己的另一个问题 但我想知道实际编码文本文件的最佳方法是什么 减压看似微不足道 遍历树 在 0 处向左 在 1 处向右 打印字符 但是 如何进行压缩呢 以某种方式将字符的位表示存储在树的节点中 每次遇
  • 从节点内部开始一条边

    digraph foo a label
  • 如何在 O(n) 时间内遍历二叉树而不需要额外的内存

    给定一棵带有整数 左指针和右指针的二叉树 如何在 O n 时间和 O 1 额外内存 无堆栈 队列 递归 内遍历该树 This guy http nandacumar blogspot com 2006 06 traversing tree
  • 生成所有可能的树

    给定以下数据类型定义 data FormTree Empty Node FormTree FormTree deriving Show 我想编写一个函数 它生成一个无限列表 其中包含按长度排序的所有可能的树 例如节点数量 下面的代码几乎满足
  • Graphviz:能够接受更大文件的在线工具[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有谁知道有一个很好的在线网站来渲染 graphviz 点文件 该文件将需要更大的文件 例如 200 行

随机推荐

  • String.split() *不*用于正则表达式?

    Since String split 使用正则表达式 这个片段 String s str str argh s split r 产量 s t s t a g h 分割这个字符串的最优雅的方法是什么r 序列 以便它产生 st st argh
  • Java EE7 中的多个 Web 套接字端点或单个 Web 套接字端点哪个更好

    Java EE 7 允许您通过注释非常轻松地创建新端点 但是 我想知道使用多个端点来处理每种消息类型是一个好主意 还是应该只使用一个端点外观来处理所有内容 我倾向于拥有一个单一端点外观 其理论基础是每个端点都会创建一个到客户端的新套接字连接
  • 如何在没有通用视图的 post_save_redirect 参数的情况下重定向到 Django 中新创建的对象

    我正在尝试将用户重定向到新创建的对象object get absolute url 保存表格后 我没有使用通用视图 所以我不能使用post save redirect争论 的相关部分view就像这样 if form is valid for
  • MemorySharp 设置地址偏移量不起作用

    好的 我正在使用MemorySharp用于读取 写入游戏内存的库 我的问题是 当我尝试将偏移量添加到基指针地址时 Visual Studio 在运行时会引发错误 这是基本代码 using var m new MemorySharp Appl
  • 无法比较飞行中的 ping 时间

    我尝试以下命令失败 sdiff lt ping www nato int lt ping www reuters com 有什么办法可以实时比较 ping 时间吗 通常我只是并排打开两个 xterm 然后在每个 xterm 中运行 ping
  • 使用可滚动结果集在休眠中批量读取数据

    我正在阅读一篇关于使用休眠进行批量获取的博客http java dzone com articles bulk fetching hibernate http java dzone com articles bulk fetching hi
  • 编译错误:Lambda 目标类型交集类型

    public class X Object o I J gt interface I public void foo interface J public void foo public void bar Oracle 编译器抛出错误 X
  • WCF服务路由,瓶颈?

    我们的应用程序服务器体系结构经过设置 以便每个服务调用都经过自定义构建的 WCF 服务路由器 一个使用请求消息标头中嵌入的信息将传入请求分发到适当服务的服务 我们在使用此 WCF 服务路由器时遇到性能问题 对并发用户进行负载测试时超时 我们
  • WinRT 中的应用程序间通信

    Windows 8 上有两个 WinRT 应用程序 C Xaml 如果有的话 第一个应用程序应该接收一些数据并将其发送到第二个应用程序中 最好的方法是什么 可以使用WCF吗 编辑 第一个应用程序知道第二个应用程序 实际上第二个应用程序是一个
  • 使用 JDBC 进行批量插入的有效方法

    在我的应用程序中 我需要进行大量插入 它是一个 Java 应用程序 我使用普通 JDBC 来执行查询 数据库是Oracle 不过 我启用了批处理 因此它节省了执行查询的网络延迟 但查询作为单独的 INSERT 串行执行 insert int
  • 模拟来自developer.sandbox.com的recurring_ payment_skipped IPN

    当定期付款失败时 我需要模拟 IPN 然后 我的应用程序可以创建待处理发票并将其发送给客户 我搜索并发现我需要设置将在下面处理的 IPNtxn type recurring payment skipped recurring payment
  • 验证货币输入的最佳方法?

    我创建了 TextBox 和 CompareValidator 我认为它们将允许以下形式的输入 5 5 00 5 00 不幸的是 它不允许带有美元符号的版本 如果不允许美元符号 那么对货币进行类型检查有什么意义呢 有没有办法允许这个符号
  • 如何对总和为 100% 的一组数字进行四舍五入

    今天 我的一位朋友向我展示了网站上的一个错误 Link http img594 imageshack us img594 7605 mrul png 您可以看到百分比之和为 100 1 49 20 7 10 9 7 5 5 7 100 1
  • JQuery 验证未验证

    我正在尝试使用 JQuery 验证器插件来验证 Rails 应用程序 但它既不会抛出任何错误 也不会验证任何内容 我不知道我的代码还有什么问题 任何帮助将不胜感激 document ready function theform valida
  • 如何解决“值对于 dtype('float32') 来说太大?”

    我读了很多与此类似的问题 但仍然无法弄清楚 clf DecisionTreeClassifier clf fit X train y train X to predict array 1 37097033e 002 0 00000000e
  • 是否可以有一个函数接受任意数量、任意类型的变量?

    我有一个简单的函数 它接受一个字符串并用该字符串向我发送一封电子邮件 该函数在调试实时站点时使用 public void errEmailV1 string strVars sendEmail me email emailSubject s
  • 测试控制器有意义吗

    我有一个简单的 MVC 应用程序 由视图 gt 控制器 gt 服务 gt 模型组成 我的控制器真的很瘦 他们所做的就是调用服务方法并填充 ModelAndView 对控制器进行单元测试以确保它们在完全模拟服务的同时在 ModelAndVie
  • 查询以搜索所有包中的表和/或列

    是否可以运行查询来搜索所有包以查看包中是否使用了特定的表和 或列 包太多 无法打开每个包并查找我正在寻找的值 你可以这样做 select from user source where upper text like upper SOMETE
  • 困惑:Django“无法导入app.views”但可以导入app,在WSGI中?

    我遇到了一个奇怪的 Django 问题 使用 mod wsgi 运行 Django 姜戈正在寻找urls py 然后说 ViewDoesNotExist Could not import app views Error was No mod
  • 在 .dot 树中强制执行水平节点排序

    我正在尝试使用 GraphViz 重新创建二叉搜索树的示例图 它最终应该是这样的 这是我的第一次尝试 digraph G nodesep 0 3 ranksep 0 2 margin 0 1 node shape circle edge a