二叉树的控制台图形打印(c/c++)

 2024-03-18 05:02:55  阅读 0

二叉树作为一种常见的数据结构,在学习过程中经常被使用。

我们在做课程设计的时候,能够图形化打印二叉树无疑是一个加分项,所以今天我们就来讨论一下如何图形化打印二叉树。

目录

如何在分析阶段打印

要完成二叉树的打印,我们至少要保证所有的节点都能不冲突地打印到屏幕上,而一棵二叉树节点最多的情况就是满二叉树。 所以我们只需要考虑如何打印满二叉树即可。

打印二叉树需要基于二叉树的遍历。 如果我们想打印出每个节点,就需要遍历每个节点。 遍历二叉树时,递归顺序(中序、后序)比较简单。 打印到控制台时,只能逐行打印,所以我们可以先将要打印的图形存储在一个数组中。

如果数组存在,它必须有一个大小。 数组的大小取决于二叉树的高度。

一棵只有一个根节点的二叉树只需要一个1×1的数组来存储它。

当有根节点及其左右子节点时,我们需要一个5×3的数组来存储(出于美观原因添加了斜杠和反斜杠)

让我们添加另一个级别。 当二叉树达到三层时,就需要一个13×7的数组来存储。

通过总结规则,我们发现,为了打印完整二叉树,宽度应该以最后一行叶子节点的数量为基础。 为了使其看起来对称,我们将每个叶节点设置为相距三个宽度。 计算后存储二叉树所需的数组宽度为

宽度=(2^(n-1)-1)*3+2^(n-1) n为层数

化简可得

宽度=2^(n+1)-3 n为层数

接下来,计算高度。 二叉树的每一层节点只需要一个高度,但层与层之间的连接高度确实不同。 从上到下看时,当总层数只有两层时,第一层和第二层的连接占据一格高。 当层数为三时,第一层与第二层的连接处占据三格高。 因此,从上到下看,很难找到联系。 线条所占高度的规则。

这时候不妨从下往上搜索。 可以发现,倒数第二层与倒数第二层之间的连线高度必须为1,倒数第二层与倒数第二层之间的连线高度必须为3。倒数第二层与倒数第二层之间的连线高度必须为3。为3。第三层和倒数第四层之间的连接高度必须为7。从这里我们可以总结出一个规则,层与层之间的连接高度必须为2的n次方减1。

最后我们得出这个数组需要申请的内存大小为

宽度=2^(n+1)-3
高度=2^n-1
n为层数

如何将数据存储到打印数组中

生成打印数组时,我们可以先将根节点放在整个数组的第0行中间,然后检查是否有左右孩子。 如果有,则将左右子节点作为新的根节点进行递归。

代码实现存储结构定义

我们使用二叉链表作为二叉树的存储结构

typedef struct TreeNode{
    char data; //数据域
    struct TreeNode * lchild,* rchild; //左右孩子指针
}TreeNode,*P_Node;

二叉树的创建

我们将通过从控制台读取字符串来创建二叉树

规则如下:

将二叉树写成前序遍历字符串,由根-左子-右子组成

每个节点都是一个字符

如果该节点没有子节点,则写为“.”

上图中的二叉树可以写为:ABC..DE.G..F...

//创建树,将输入的字符串以先序的形式存入二叉树
void CreateTree(P_Node &T)
{
    char ch;
    scanf("%c",&ch);
    if(ch == '\n')
    {
        return;
    }
    if(ch == '.')
    {
        T = NULL;
        return;
    }
    T = (P_Node)malloc(sizeof(TreeNode));
    T->data = ch;
    CreateTree(T->lchild);
    CreateTree(T->rchild);
}

寻找深度

生成打印数组时,我们需要用到二叉树的深度,也就是层数,所以我们还需要实现求深度的功能(递归实现)

//求深度
int DeepTree(P_Node T)
{
    if(!T)
    {
        return 0;
    }
    return DeepTree(T->lchild)>DeepTree(T->rchild)?DeepTree(T->lchild)+1:DeepTree(T->rchild)+1;
//关键代码:如果该节点的左子树深度大于右子树则将左子树的深度加一返回,这个返回值便是以该节点做根节点的树的深度,右子树深度大时则相反
}

打印功能的代码实现

做好了准备工作之后,本文的重点就来了。

首先设置全局变量 width 和 。 这两个值在两个函数中都会用到,所以设置为全局的。

int width,height;

同时我们规定数组类型为char,用一串连续空格来代替二维数组。 数组中存储的值和打印的效果对应如下表。

-1

打印'/'

打印'\'

打印空间

其他

直接打印字符

为了实现打印功能,我们需要将需要递归的部分分离出来作为递归函数。 该函数的作用是按顺序遍历二叉树,同时将内容填充到打印数组中。

//T为二叉树的根节点,a是数组的起始地址,i,j是当前节点在数组中的位置
//如果节点有孩子,其孩子的j坐标为 j±(height-i+1)/2
void fillArray(P_Node &T,char *a,int i, int j)
{
    int ti,tj;
    if(T) //如果该位置有节点
    {
        *(a+(i*width)+j) = T->data; //向数组该点填入字符
        if(T->lchild) //有左右孩子给对应的连接线,左右孩子的值在下一层递归赋
        {
            //将该点与其左孩子之间的连线全部填上'/'
            for(ti=i+1,tj=j-1;tj>j-(height-i+1)/2;tj--)
            {
                *(a+((ti)*width)+tj) = -1;
                ti++;
            }
        }
        if(T->rchild)
        {
            for(ti=i+1,tj=j+1;tjlchild, a, ti, j-(height-i+1)/2);
        fillArray(T->rchild, a, ti, j+(height-i+1)/2);
    }
}

计算宽度和高度并实现打印功能的函数

void printBiTree(P_Node &T)
{
    int i,j;
    int n = DeepTree(T); //计算出深度n
    //在计算机中数据以二进制形式存储,所以一个数据左移1位就相当于乘以2的1次方
    width = (2<

测试运行

用例 1:AB..B..

用例 2:ABC..C..BC..C..

用例 3:ABCD..D..CD..D..BCD..D..CD..D..

用例 4:

标签: 打印 数组 节点

如本站内容信息有侵犯到您的权益请联系我们删除,谢谢!!


Copyright © 2020 All Rights Reserved 京ICP5741267-1号 统计代码