二叉樹可視化

轉自 http://blog.chinaunix.net/uid-24774106-id-3506024.htmlcss

在我前面的一篇博文數據結構之紅黑樹中,提到了數據結構之可視化的重要性。 由於若是咱們能將二叉樹可視化,也能提升加快調試,減小bug。原文給出了print_tree函數,會打印二叉樹,可是旋轉了90度,不優美,不友好。最近學習了下Graphviz這個軟件,學了下怎麼用這個軟件繪製圖片,基本解決了二叉樹的可視化問題。html

    我仍是以個人紅黑樹代碼爲例子,寫測試代碼,看下如何將咱們插入產生的紅黑樹可視化。node

    咱們看下代碼:git

  1. typedef unsigned long long ULL;
  2. void __tree2dot(struct rbtree_node* node,FILE* stream)
  3. {
  4.     if(node->color == RB_BLACK)
  5.     {
  6.         fprintf(stream,"%llu [shape=box];n",*(ULL*)(node->key));
  7.     }
  8.     if(node->left)
  9.     {
  10.         
  11.         fprintf(stream," %llu -> %llu;n",*(ULL*)(node->key),*(ULL*)(node->left->key));
  12.         __tree2dot(node->left,stream);
  13.     }
  14.     if(node->right)
  15.     {
  16.         fprintf(stream," %llu -> %llu;n",*(ULL*)(node->key),*(ULL*)(node->right->key));
  17.         __tree2dot(node->right,stream);
  18.     }
  19. }
  20. int tree2dot(struct rbtree* tree,char* filename)
  21. {
  22.     assert(tree != NULL && filename != NULL);
  23.     FILE* stream = fopen(filename,"w+");
  24.     if(stream == NULL)
  25.     {
  26.         fprintf(stderr, "open failed n");
  27.         return -1;
  28.     }
  29.     fprintf(stream,"digraph {n");
  30.     __tree2dot(tree->root,stream);
  31.     fprintf(stream,"}n");
  32.     fclose(stream);
  33.     return 0;
  34.     
  35. }

    tree2dot接受一個二叉樹和一個文件名做爲入參。負責建立文件 關閉文件和填寫dot文件有向圖的格式頭和尾。github

    __tree2dot是遞歸調用,添加父節點到子節點的有向鏈接。咱們由於是紅黑樹,因此添加了這部分處理紅黑結點的代碼:數據結構

  1.     if(node->color == RB_BLACK)
  2.     {
  3.         fprintf(stream,"%llu [shape=box];n",*(ULL*)(node->key));
  4.     }

這部分代碼的做用對於黑節點,採用box類型表示節點,對於紅節點,採用默認的橢圓圖形。函數

比較才能看到進步,咱們比較下新舊兩種方法的輸出:學習

在看下生成的dot文件(Ubuntu下用XDot打開)測試

下面這種的優越性,一目瞭然。這個方法目前有個缺點是沒有將NULL節點處理,致使421看不出是386左孩子仍是右孩子,咱們改進下:ui

 

  1. void process_null_node(struct rbtree_node* node, int nullcount, FILE* stream)
  2. {
  3.         fprintf(stream, " null%d [shape=hexagon];n", nullcount);
  4.         fprintf(stream, " %llu -> null%d;n",*(ULL*)(node->key), nullcount);
  5. }
  6. void __tree2dot(struct rbtree_node* node,FILE* stream)
  7. {
  8.     static int null_node_cnt = 0;
  9.     if(node->color == RB_BLACK)
  10.     {
  11.         fprintf(stream,"%llu [shape=box];n",*(ULL*)(node->key));
  12.     }
  13.     if(node->left)
  14.     {
  15.         
  16.         fprintf(stream," %llu -> %llu;n",*(ULL*)(node->key),*(ULL*)(node->left->key));
  17.         __tree2dot(node->left,stream);
  18.     }
  19.     else
  20.     {
  21.         process_null_node(node,null_node_cnt++,stream);
  22.     }
  23.     if(node->right)
  24.     {
  25.         fprintf(stream," %llu -> %llu;n",*(ULL*)(node->key),*(ULL*)(node->right->key));
  26.         __tree2dot(node->right,stream);
  27.     }
  28.     else
  29.     {
  30.         process_null_node(node,null_node_cnt++,stream);
  31.     }
  32. }

咱們將NULL節點處理成六邊形,這樣就能完整的看出紅黑樹的狀況了,請看生成的dot文件:

 

完整的代碼在個人github上 ,能夠去下面路徑去取:

https://github.com/manuscola/rbtree

 

參考文獻:

1 Drawing graphs with dot

相關文章
相關標籤/搜索