轉自 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類型表示節點,對於紅節點,採用默認的橢圓圖形。函數
比較才能看到進步,咱們比較下新舊兩種方法的輸出:學習
![](http://static.javashuo.com/static/loading.gif)
在看下生成的dot文件(Ubuntu下用XDot打開)測試
![](http://static.javashuo.com/static/loading.gif)
下面這種的優越性,一目瞭然。這個方法目前有個缺點是沒有將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文件:
![](http://static.javashuo.com/static/loading.gif)
完整的代碼在個人github上 ,能夠去下面路徑去取:
https://github.com/manuscola/rbtree
參考文獻:
1 Drawing graphs with dot