转自 http://blog.chinaunix.net/uid-24774106-id-3506024.htmlcss
在我前面的一篇博文数据结构之红黑树中,提到了数据结构之可视化的重要性。 由于若是咱们能将二叉树可视化,也能提升加快调试,减小bug。原文给出了print_tree函数,会打印二叉树,可是旋转了90度,不优美,不友好。最近学习了下Graphviz这个软件,学了下怎么用这个软件绘制图片,基本解决了二叉树的可视化问题。html
我仍是以个人红黑树代码为例子,写测试代码,看下如何将咱们插入产生的红黑树可视化。node
咱们看下代码:git
- typedef unsigned long long ULL;
- void __tree2dot(struct rbtree_node* node,FILE* stream)
- {
- if(node->color == RB_BLACK)
- {
- fprintf(stream,"%llu [shape=box];n",*(ULL*)(node->key));
- }
- if(node->left)
- {
-
- fprintf(stream," %llu -> %llu;n",*(ULL*)(node->key),*(ULL*)(node->left->key));
- __tree2dot(node->left,stream);
- }
- if(node->right)
- {
- fprintf(stream," %llu -> %llu;n",*(ULL*)(node->key),*(ULL*)(node->right->key));
- __tree2dot(node->right,stream);
- }
- }
- int tree2dot(struct rbtree* tree,char* filename)
- {
- assert(tree != NULL && filename != NULL);
- FILE* stream = fopen(filename,"w+");
- if(stream == NULL)
- {
- fprintf(stderr, "open failed n");
- return -1;
- }
- fprintf(stream,"digraph {n");
- __tree2dot(tree->root,stream);
- fprintf(stream,"}n");
- fclose(stream);
- return 0;
-
- }
tree2dot接受一个二叉树和一个文件名做为入参。负责建立文件 关闭文件和填写dot文件有向图的格式头和尾。github
__tree2dot是递归调用,添加父节点到子节点的有向链接。咱们由于是红黑树,因此添加了这部分处理红黑结点的代码:数据结构
- if(node->color == RB_BLACK)
- {
- fprintf(stream,"%llu [shape=box];n",*(ULL*)(node->key));
- }
这部分代码的做用对于黑节点,采用box类型表示节点,对于红节点,采用默认的椭圆图形。函数
比较才能看到进步,咱们比较下新旧两种方法的输出:学习

在看下生成的dot文件(Ubuntu下用XDot打开)测试

下面这种的优越性,一目了然。这个方法目前有个缺点是没有将NULL节点处理,致使421看不出是386左孩子仍是右孩子,咱们改进下:ui
- void process_null_node(struct rbtree_node* node, int nullcount, FILE* stream)
- {
- fprintf(stream, " null%d [shape=hexagon];n", nullcount);
- fprintf(stream, " %llu -> null%d;n",*(ULL*)(node->key), nullcount);
- }
- void __tree2dot(struct rbtree_node* node,FILE* stream)
- {
- static int null_node_cnt = 0;
- if(node->color == RB_BLACK)
- {
- fprintf(stream,"%llu [shape=box];n",*(ULL*)(node->key));
- }
- if(node->left)
- {
-
- fprintf(stream," %llu -> %llu;n",*(ULL*)(node->key),*(ULL*)(node->left->key));
- __tree2dot(node->left,stream);
- }
- else
- {
- process_null_node(node,null_node_cnt++,stream);
- }
- if(node->right)
- {
- fprintf(stream," %llu -> %llu;n",*(ULL*)(node->key),*(ULL*)(node->right->key));
- __tree2dot(node->right,stream);
- }
- else
- {
- process_null_node(node,null_node_cnt++,stream);
- }
- }
咱们将NULL节点处理成六边形,这样就能完整的看出红黑树的状况了,请看生成的dot文件:

完整的代码在个人github上 ,能够去下面路径去取:
https://github.com/manuscola/rbtree
参考文献:
1 Drawing graphs with dot