递归画树(Qt实现)


    

1.       问题描述

用递归算法绘制一棵树

 

2.       解决思路

用二叉树的数据结构来描述树的结构,首先创建一个二叉树,创建时要初始化节点的一些信息,伪代码如下:

If  current depth is last
    then  return null
End If 
Create a branch 
If current branch is left
    then initial the branch as a left branch 
Else
    then initial the branch as a right branch
End If
Create the left branch of  this recursively
Create the right branch of  this recursively
return the root branch
 

然后再遍历二叉树,遍历的同时绘制树枝,伪代码如下:

If  current branch has left branch
    then paint the left branch
End If 
If current branch has right branch
    then paint the left branch
End If
Paint the left branch of  this recursively
Paint the right branch of  this recursively


3.       代码实现

创建树的代码:

  1. Branch *DrawTrees::createTree(Branch *preRoot, bool isLeft)  
  2. {  
  3.     if(preRoot->depth > depth)//判断是否到达设置的深度  
  4.         return NULL;  
  5.    
  6.     Branch *root = new Branch();  
  7.     if(!root)  
  8.         return NULL;  
  9.    
  10.     root->depth = preRoot->depth + 1;  
  11.     if(root->depth < 3)  
  12.     {//最底下三层的树枝角度较小  
  13.         if(isLeft)  
  14.         {  
  15.            root->angle = preRoot->angle + qrand()%15;  
  16.            root->length = preRoot->length - preRoot->length / (3+qrand()%7);  
  17.         }  
  18.         else  
  19.         {  
  20.            root->angle = preRoot->angle - qrand()%15;  
  21.            root->length = preRoot->length - preRoot->length / (3+qrand()%7);  
  22.         }  
  23.         root->width = preRoot->width * 0.8;  
  24.     }  
  25.     else  
  26.     {  
  27.         if(branchNumCount[root->depth] >= maxBranchNum[root->depth])  
  28.             return NULL;  
  29.         else  
  30.         {  
  31.             if(isLeft)  
  32.                 root->angle = preRoot->angle+(45-root->depth*3+qrand()%(40-root->depth*2));  
  33.             else  
  34.                 root->angle = preRoot->angle-(45-root->depth*3+qrand()%(40-root->depth*2));  
  35.    
  36.             root->length = preRoot->length-preRoot->length/(3+qrand()%7);  
  37.             root->width = preRoot->width * 0.618;  
  38.             branchNumCount[root->depth]++;  
  39.         }  
  40.    
  41.     }  
  42.      //计算当前树枝起点的坐标  
  43.     root->x= preRoot->x + root->length*cos(root->angle*ONEANGLE);  
  44.     root->y= preRoot->y - root->length*sin(root->angle*ONEANGLE);  
  45.      //当树枝宽带减小到1时不再减小  
  46.     if(root->width < 1)  
  47.         root->width = 1;  
  48.    
  49.     root->left = createTree(root, true);  //递归创建左子树  
  50.     root->right = createTree(root, false); //递归创建右子树  
  51.    
  52.     return root ;  
  53.    
  54. }  


 

绘制树的代码:

  1. void DrawTrees::paintTree(Branch *root)  
  2. {  
  3.     if(!root)  
  4.         return;  
  5.   
  6.     int dstX,dstY;  
  7.   
  8.     if(!root->left)   
  9.     {//左子树为空则画叶子  
  10.         dstX=root->x+1;  
  11.         dstY=root->y+1;  
  12.   
  13.         painter->setPen(QPen(QBrush(QColor(0,140,0,255)),  
  14.                              LEAVE_WIDTH,  
  15.                              Qt::SolidLine,  
  16.                              Qt::RoundCap));  
  17.   
  18.         painter->drawLine(root->x,root->y,dstX,dstY);  
  19.   
  20.     }  
  21.     else  
  22.     {//否则画树枝  
  23.         dstX=root->left->x;  
  24.         dstY=root->left->y;  
  25.   
  26.         painter->setPen(QPen(QColor(160, 82, 45),  
  27.                              root->width,  
  28.                              Qt::SolidLine,  
  29.                              Qt::RoundCap));  
  30.         painter->drawLine(root->x,root->y,dstX,dstY);  
  31.     }  
  32.   
  33.     if(!root->right)  
  34.     {  
  35.         dstX=root->x+1;  
  36.         dstY=root->y+1;  
  37.   
  38.         painter->setPen(QPen(QBrush(QColor(0,140,0,255)),  
  39.                                     LEAVE_WIDTH,  
  40.                                     Qt::SolidLine,  
  41.                                     Qt::RoundCap));  
  42.         painter->drawLine(root->x,root->y,dstX,dstY);  
  43.     }  
  44.     else  
  45.     {  
  46.         dstX=root->right->x;  
  47.         dstY=root->right->y;  
  48.   
  49.         painter->setPen(QPen(QColor(160, 82, 45),  
  50.                              root->width,  
  51.                              Qt::SolidLine,  
  52.                              Qt::RoundCap));  
  53.         painter->drawLine(root->x,root->y,dstX,dstY);  
  54.     }  
  55.   
  56.     paintTree(root->left);//递归绘制左子树  
  57.     paintTree(root->right);//递归绘制右子树  
  58.   
  59. }  


 

4.       运行结果

 

5.       小结

主要思路就是使用二叉树创建一棵树,然后遍历。为了使显示效果更好,加入一个随机控制,比如控制树枝的角度和每层节点的数量,使最终效果不是一个完全二叉树,这样使每层上都有叶子。


源代码:点击打开链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值