【知识整理|树(一)】二叉树的构建、深度、宽度

二叉树

节点的定义和创建

当我们对动态内存的申请和释放的写法没有把握时,可以利用静态数组,将数组元素分配给相应节点。

struct Node{
    Node *lchild;//左
    Node *rchild;//右
    char c;//节点信息
}Tree[50];//静态内存分配数组

int loc;//静态数组中已经分配的节点数,在创建一棵树前记得初始化为0

Node *create(){//申请一个节点空间,并返回指向该节点的指针
    Tree[loc].lchild = Tree[loc].rchild = NULL;
    return &Tree[loc++];
}
二叉树的构建

前/后序序列+中序序列可以唯一确定一个二叉树
我们可以根据给出的两个遍历序列(必包含中序)来构造二叉树。

string str1, str2;//str1: 前序遍历的输出,str2: 中序遍历的输出

Node *build(int s1, int e1, int s2, int e2){//根据前序和中序便利的到的输出构建BST
    Node *r = create();
    r->c = str1[s1];//前序遍历的第一个字符一定为根节点
    int rIndex;
    for(int i = s2; i <= e2; i++){//在中序序列中找到根节点,他左边为它的左子树,右边为它的右子树
        if(str2[i]==str1[s1]){
            rIndex = i;
            break;
        }
    }
    //左右子树在create()函数中已经初始化成了NULL
    if(rIndex != s2)//左子树不为空
        r->lchild = build(s1+1,s1+(rIndex-s2),s2,rIndex-1);//递归还原左子树
    if(rIndex != e2)//右子树不为空
        r->rchild = build(s1+(rIndex-s2)+1,e1,rIndex+1,e2);//递归还原右子树
    return r;
}

int main(){
    while(cin>>str1){
        cin>>str2;
        loc = 0;//初始化静态内存空间中已使用节点个数为0
        Node *T = build(0,str1.length()-1,0,str2.length()-1);//记得结尾下标=长度-1
        //可以遍历输出看一下构建的二叉树
    }
    return 0;
}
二叉树的高度/深度

我们从根节点和左右子树来理解二叉树的深度:对于任意一棵非空二叉树,有如下四种情况:

  1. 如果一颗树只有一个节点,它的深度是1;
  2. 如果根节点只有左子树而没有右子树,则二叉树的深度为其左子树的深度+1;
  3. 如果根节点只有右子树而没有左子树,则二叉树的深度为其右树的深度+1;
  4. 如果根节点既有左子树又有右子树,则二叉树的深度为其左右子树的深度较大值+1;

递归实现

int getHight(Node *T){
    if(T==NULL) return 0;
    int lhight = getHight(T->lchild);//左子树高度
    int rhight = getHight(T->rchild);//右子树高度
    return lhight>rhight? lhight+1:rhight+1;
}
二叉树的宽度

宽度:具有最多结点数的层中包含的结点数。
我们需要记录每一层的节点数,来获取宽度(可以保留所有层,也可以只保留上一层)。所以需要用到二叉树的层次遍历,即广度优先周游。

广度优先周游:按层次从上到下,从左到右的逐层访问,可以利用队列实现。

  1. 首先把二叉树的根节点送入队列;
  2. 队首节点出队列并访问,然后把它的左右子节点分别入队列;
  3. 重复上面两步操作,直至队空。
int getWidth(Node *T){
    if(T==NULL) return 0;
    int preWidth = 0, curWidth = 0, width;
    queue<Node*> q;
    Node *temp = NULL;
    q.push(T);//根节点入队
    width = 1;
    while(!q.empty()){
        while(preWidth--){//依次取出这一层的所有节点
            temp = q.front();//取出队首
            q.pop();
            if(temp->lchild!=NULL) q.push(temp->lchild);//左右子树入队
            if(temp->rchild!=NULL) q.push(temp->rchild);
        }
        curWidth = q.size();
        width = curWidth>width? curWidth:width;//比较宽度
        preWidth = curWidth;//记录本层宽度,给下层使用
    }
    return width;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值