大家平时写C程序有没有种把内存里的数据结构全给画出来的冲动呢?数据量小的话,画起来还蛮简单,用viso,我前面的文章都用viso画的。之前写红黑树代码的时候,用的是命令行把整个树打印出来,不过只是一些小片段,很丑,还得自己手动再在纸上画一遍,非常麻烦,要是用程序就能把图画出来那就爽了。好了,推荐使用 Graphviz这个东东,so 一下就知道啦,功能挺丰富的,也提供了很多库(c,php,python等),下面画一颗简单的红黑树(红黑树代码参考我前面的代码,下面只写画树的代码)直接看效果图:
这树怎么画的呢?参考官网 http://www.graphviz.org/Documentation.php
1.编写规则文件(可以用Graphviz自带的lib,如cgraph等生成,或者直接就用fprintf生成,可以简单看下中文的翻译 简单的dot规则)
2.用Graphviz自带的一些工具例如dot等解析一下规则文件,然后生成图片(ps,jpg,png等)或者其它格式的文件。
下面是实现。
t.c//测试代码,用到的函数参考我前面写的红黑树文章的代码。
void rbtree_fprint_node(rbtree_node * t,FILE *fp){
if(t->color == RB_BLACK){
fprintf(fp,"node[shape=record,style=filled,color=black,fontcolor=white];\n");
}else{
fprintf(fp,"node[shape=record,style=filled,color=red,fontcolor=white];\n");
}
fprintf(fp,"%d[label=\" | %d | \"];\n",t->key.value,t->key.value);
}
void rbtree_fprint_tree(rbtree_node * t,FILE *fp){
if(rb_nil == t) return;
if(t->parent == rb_nil){//root
rbtree_fprint_node(t,fp);
}
if(t->left != rb_nil){
rbtree_fprint_node(t->left,fp);
fprintf(fp,"%d:f0:sw->%d:f1;\n",t->key.value,t->left->key.value);
}
if(t->right != rb_nil){
rbtree_fprint_node(t->right,fp);
fprintf(fp,"%d:f2:se->%d:f1;\n",t->key.value,t->right->key.value);
}
rbtree_fprint_tree(t->left,fp);
rbtree_fprint_tree(t->right,fp);
}
int main(int argc,char *argv[]){
rbtree_node *t,*p,*max,*min;
int arr[] = {9,8,11,18,2,5,16,1,7,999,234,7662,387,928,454};
int i;
rbtree_init_nil();
t = rbtree_create(15);
t->color = RB_BLACK;
for(i=0;i<15;i++){
rbtree_add(&t,arr[i]);
}
//rb tree print
FILE *fp;
fp = fopen("g2.dot","w+");
fprintf(fp,"digraph G{\n");
rbtree_fprint_tree(t,fp);
fprintf(fp,"}");
fclose(fp);
}
digraph G{
node[shape=record,style=filled,color=black,fontcolor=white];
9[label=" | 9 | "];
node[shape=record,style=filled,color=black,fontcolor=white];
5[label=" | 5 | "];
9:f0:sw->5:f1;
node[shape=record,style=filled,color=red,fontcolor=white];
18[label=" | 18 | "];
9:f2:se->18:f1;
node[shape=record,style=filled,color=black,fontcolor=white];
2[label=" | 2 | "];
5:f0:sw->2:f1;
node[shape=record,style=filled,color=black,fontcolor=white];
8[label=" | 8 | "];
5:f2:se->8:f1;
node[shape=record,style=filled,color=red,fontcolor=white];
1[label=" | 1 | "];
2:f0:sw->1:f1;
node[shape=record,style=filled,color=red,fontcolor=white];
7[label=" | 7 | "];
8:f0:sw->7:f1;
node[shape=record,style=filled,color=black,fontcolor=white];
15[label=" | 15 | "];
18:f0:sw->15:f1;
node[shape=record,style=filled,color=black,fontcolor=white];
999[label=" | 999 | "];
18:f2:se->999:f1;
node[shape=record,style=filled,color=black,fontcolor=white];
11[label=" | 11 | "];
15:f0:sw->11:f1;
node[shape=record,style=filled,color=black,fontcolor=white];
16[label=" | 16 | "];
15:f2:se->16:f1;
node[shape=record,style=filled,color=red,fontcolor=white];
387[label=" | 387 | "];
999:f0:sw->387:f1;
node[shape=record,style=filled,color=black,fontcolor=white];
7662[label=" | 7662 | "];
999:f2:se->7662:f1;
node[shape=record,style=filled,color=black,fontcolor=white];
234[label=" | 234 | "];
387:f0:sw->234:f1;
node[shape=record,style=filled,color=black,fontcolor=white];
928[label=" | 928 | "];
387:f2:se->928:f1;
node[shape=record,style=filled,color=red,fontcolor=white];
454[label=" | 454 | "];
928:f0:sw->454:f1;
}