二叉树图形显示(VC)

目的:为了调试查看二叉树的数据,最直观的方式就是以图形方式显示出来,一目了然

方式:

一,命令行程序中以黑窗口字符形式显示

二,windows窗口中以图形方式显示

提供一个类CTreeShow来实现显示指定的二叉树


显示时要解决的重点问题就是各个节点的位置按排,因此定义显示节点为

struct CTreeShowNode{
string text; //代表节点的文字

int x,y;//该节点的显示位置(x,y单位采用步长,而不是像素,便于显示时调整间距)

CTreeShowNode *left,*right;//左右节点
}

整个过程要分三步:

1,从原始二叉树数据重新构建CTreeShowNode的显示二叉树

重新构建时需要原始二叉树的结构,一般来说原始二叉树结构各人定义的不一致,如果我们要提供一个统一的二叉树显示功能类,则不能强制规定原始二叉树格式,需要协商一个接口办法。考虑先将原始二叉树序列化成字符串,再由CTreeShow类反序化构建新的显示树


2,安排CTreeShowNode树的各节点位置x,y

y代表深度位置,按树的层级很好实现。

x代表横向位置,一般左子树在左,根节点在中间,所以可以考虑采用中序遍历的递归方式,将左子树起点安排在x,y+1的位置,当前节点安排在newx(指左子树安排后的下一个位置),y的位置,右子树起点安排在newx+1,y+1的位置。

int arrange_pos(CTreeShowNode* p,int x,int y)//递归函数,中序遍历,安排各节点的显示位置x,y,返回新空位置
{
if(p==NULL) return x;
if(p->left) x=arrange_pos(p->left,x,y+1);
p->x=x; p->y=y; x++;
if(p->right) x=arrange_pos(p->right,x,y+1);
return x;
}

3,将CTreeShowNode树画在指定CDC上


整个文件TreeShow.h如下

#if !defined(AFX_TREESHOW_H__7B4BD16D_2BCC_48A4_9D8E_2B9E440B211D__INCLUDED_)
#define AFX_TREESHOW_H__7B4BD16D_2BCC_48A4_9D8E_2B9E440B211D__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <string>

//
class CTreeShow//二叉树显示类
{
private:
struct CTreeShowNode{//树显示节点
string text;int x,y;
CTreeShowNode *left,*right;
}*m_tree;
void loadtree(TreeNode* psrc,CTreeShowNode** pdst)//递归函数,复制树结构
{
if(psrc==NULL) return;
CString s;if(isoperator(psrc)) s.Format("%c",(int)psrc->value);else s.Format("%d",(int)psrc->value);
CTreeShowNode* p=new CTreeShowNode;if(p==NULL){puts("out of mem");return;}
p->text=s;p->x=p->y=0;p->left=p->right=NULL;*pdst=p;
//
loadtree(psrc->left,&p->left);loadtree(psrc->right,&p->right);
}
int arrange_pos(CTreeShowNode* p,int x,int y)//递归函数,中序遍历,安排各节点的显示位置x,y
{
if(p==NULL) return x;
if(p->left) x=arrange_pos(p->left,x,y+1);
p->x=x; p->y=y; x++;
if(p->right) x=arrange_pos(p->right,x,y+1);
return x;
}
CDC* m_pdc;int width_pad,height_pad;
void draw_tree(CTreeShowNode* p)//递归函数,前序遍历显示
{
if(p==NULL) return;
int x=p->x*width_pad,y=p->y*height_pad;
CRect rc(CPoint(x,y),m_pdc->GetTextExtent(p->text.c_str()));m_pdc->Rectangle(&rc);//画框
m_pdc->TextOut(x,y,p->text.c_str());
//画线
if(p->left){m_pdc->MoveTo(x,y);m_pdc->LineTo(p->left->x*width_pad,p->left->y*height_pad);}
if(p->right){m_pdc->MoveTo(x,y);m_pdc->LineTo(p->right->x*width_pad,p->right->y*height_pad);}
//
draw_tree(p->left);draw_tree(p->right);
}
void free_tree(CTreeShowNode* p)//递归函数,后序遍历删除
{
if(p==NULL) return;
free_tree(p->left);free_tree(p->right);delete p;
}
public:
CTreeShow():m_tree(NULL){}
virtual ~CTreeShow(){free_tree(m_tree);}//释放
void show_tree(TreeNode* pHead,CDC* pdc,int width_pad1=20,int height_pad1=40)
{
if(pHead==NULL || pdc==NULL) return;
m_pdc=pdc;width_pad=width_pad1;height_pad=height_pad1;

if(m_tree){free_tree(m_tree);m_tree=NULL;}//担心有人反复调用show_tree
loadtree(pHead,&m_tree);
arrange_pos(m_tree,0,0);
draw_tree(m_tree);
}
void refresh(){draw_tree(m_tree);}
};

#endif


用法:

将代码保存到TreeShow.h文件中,加入工程,使用时

#include "TreeShow.h"

CTreeShow show;show.show_tree(pHead,pdc);


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值