递归求二叉树的层数和递归打印二叉树的树形结构

来源:互联网 发布:自行车销量排行榜 知乎 编辑:程序博客网 时间:2024/06/04 18:19
以下是打印二叉树树形结构的要求:
第二部分为表达式树的显示,如样例输出所示。如果该二叉树是一棵满二叉树,则最底部的叶子结点,分别占据横坐标的第1、3、5、7……个位置(最左边的坐标是1),然后它们的父结点的横坐标,在两个子结点的中间。如果不是满二叉树,则没有结点的地方,用空格填充(但请略去所有的行末空格)。每一行父结点与子结点中隔开一行,用斜杠(/)与反斜杠(\)来表示树的关系。/出现的横坐标位置为父结点的横坐标偏左一格,\出现的横坐标位置为父结点的横坐标偏右一格。也就是说,如果树高为m,则输出就有2m-1行。

例如下图:


思路是递归:
打印根结点-->打印左/右连接符-->递归打印左子树/递归打印右子树。
而且每次执行递归,打印的内容其实只是根结点和左右连接符。

假设二叉树有n层,那么第一层的结点位置是2^(n-1)(水平坐标从1开始、垂直坐标从0开始),它的左右儿子与它的水平距离是2^(n-2)。

有一个问题是,如何求得二叉树的层数
递归,还是递归。直接上代码:
int calc_tree_layers(btn *root){    int left_way_layers, right_way_layers;        if(root==NULL)    return 0;    //递归出口,空结点的层数是0    else    {            left_way_layers=1+calc_tree_layers(root->leftc);    //从左路返上来的层数            right_way_layers=1+calc_tree_layers(root->right);     //从右路返上来的层数            if(left_way_layers>right_way_layers) return left_way_layers;            else return right_way_layers;    }}

有了层数,便可计算根结点和左右儿子的水平位置,下面来递归打印二叉树。
void print_tree(btn *root, int root_x, int root_y, int r_c_interval, char disp_buf[][MAXCOL])/*参数从左至右依次为:根结点、根结点的水平位置、根结点的竖直位置、当前根结点与其左右儿子的水平间距、用于暂存打印内容的缓存*/{    int left_child, right_child;    left_child=root_x - r_c_interval;    right_child=root_x + r_c_interval;    if(root==NULL) return;     //递归出口    else    {        //打印根结点        disp_buf[root_y][root_x-1]=root->data;        //左子树非空,打印左连接符        if(root->leftc!=NULL)    disp_buf[root_y+1][root_x-2]='/';                //右子树非空,打印右连接符        if(root->rightc!=NULL) disp_buf[root_y+1][root_x]='\\';        //递归打印左子树。注意左子树根结点的位置,以及左子树根结点与其儿子的水平距离        print_tree(root->leftc, left_child, root_y+2, (r_c_interval>>1), disp_buf);        //递归打印右子树        print_tree(root->rightc, right_child, root_y+2, (r_c_interval>>1), disp_buf);    }}

注意buffer的预处理用空格填满
char dispbuf[MAXBUFROW][MAXBUFCOL];int i, j;for (i=0; i<MAXBUFROW; ++i){    for (j=0; j<MAXBUFCOL; ++j)    {        dispbuf[i][j]=' ';    }}

注意buffer的后处理:删除多余的行(无效行),删除有效行实际内容之后多余的空格。
int effective_line=0;for (i=0; i<MAXBUFROW; ++i){   j=MAXBUFCOL-1;   while(dispbuf[i][j]==' ' && j>=0) --j;   if (j>-1)   {       dispbuf[i][j+1]='(';//随便赋一个值作为终止标记       ++effective_line;       continue;   }   else      break;} 

显示打印的树形结构,即输出buffer的内容:
for (i=0; i<effective_line; ++i){    for (j=0; j<MAXBUFCOL; ++j)    {        if (dispbuf[i][j] != '(') cout<<dispbuf[i][j];        else break;    }    cout<<endl;}

1 0
原创粉丝点击