算法小白学习日记-4:二叉树

本文详细介绍了二叉树的四种操作:广度优先遍历、深度优先遍历、二叉树转广义表和广义表转二叉树,以及LeetCode中的层序遍历问题。展示了如何结合栈、队列和递归实现这些算法,并分享了LeetCode作为测试工具的使用技巧。
摘要由CSDN通过智能技术生成

本篇文章的主题是二叉树,首先介绍4个有关二叉树的操作,再分享1道二叉树的题目,最后再分享一个leetcode的隐藏用法,欢迎批评指正。

操作1:二叉树的广度优先遍历

问题分析

二叉树的广度优先遍历,即依次遍历二叉树的每层,可以通过队列结构实现。即建立一个队列,初始化队列的第一个元素是二叉树的根节点,之后每次将队列头部节点指向的根节点入队,之后将队列的头部节点出队,遍历直到队列为空。

样例输入

[3,9,21,2,4,null,7,null,null,2,6]

样例输出

3 9 21 2 4 7 2 6 

最终代码

void bfs(TreeNode *root){
    if(root == NULL) return ;
    queue<TreeNode *> p;
    p.push(root);//首先将根节点入栈
    while(!p.empty()){
        TreeNode *t = p.front();
        printf("%d ", t->val);
        if(t->left) p.push(t->left);//根据是否有左右节点判断是否入栈
        if(t->right) p.push(t->right);
        p.pop();//将头节点出栈
    }
}

操作2:二叉树的深度优先遍历

问题分析

二叉树的深度优先遍历,即从左到右依次遍历最深的节点,可以通过递归实现。从根节点开始递归,如果存在左子树,则继续遍历左子树,左子树遍历完成后,再遍历右子树,当节点为空时返回。

样例输入

[3,9,21,2,4,null,7,null,null,2,6]

样例输出

3 9 2 4 2 6 21 7 

最终代码

void dfs(TreeNode *root){
    if(root == NULL) return ;
    printf("%d ", root->val);
    if(root->left) dfs(root->left);
    if(root->right) dfs(root->right);
    return ;
}

操作3:二叉树转广义表

问题分析

可以用递归的方法实现二叉树转广义表,用字符串存储转换的结果。

  1. 从根节点开始遍历,如果存在左子树或右子树,则输出'(';
  2. 如果存在左子树,则遍历左子树的结果,后输出',';
  3. 如果存在右子树,则遍历右子树的结果,后输出')';
  4. 其间需要利用sprintf函数往字符串中输出结果,并用记录sprintf函数的返回值。

样例输入

[3,9,21,2,4,null,7,null,null,2,6]

样例输出

3(9(2,4(2,6)),21(,7))

最终代码

char buff[100];
int len = 0;//用len记录输入字符的偏移量
void serialize(TreeNode *root){
    if(root == NULL) return ;
    len += sprintf(buff + len, "%d", root->val);
    if(root->left || root ->right) {
        len += sprintf(buff + len, "(");
        if(root->left) serizlize(root->left);
        len += sprintf(buff + len, ",");
        if(root->right) serizlize(root->right);
        len += sprintf(buff + len, ")");
    }
    return ;
}

操作4:广义表转二叉树

问题分析

我们需要根据一段存储广义表信息的字符串,还原出二叉树。此问题中二叉树的父子节点是具有包含关系的,因此可以用来解决问题。

  1. 可从左到右依次遍历字符串,如果遇到数字,则需要判断下一个字符是否是数字,并将字符串形式的数字转换为int类型。并建立新的节点,初始化节点的数值;
  2. 如果遇到'(',则说明后面字符串代表的二叉树,是'('前的节点的子节点,因此将'('前的节点入栈;
  3. '('后再遇到数值,则将新的节点设置为栈顶节点的左子树;
  4. 如果遇到',',则代表后续的节点为栈顶节点的右子树;
  5. 如果遇到')',则说明栈顶节点的子树已经连接完成,因此将栈顶节点弹出;

样例输入

3(9(2,4(2,6)),21(,7))

样例输出

[3,9,21,2,4,null,7,null,null,2,6]

最终代码

TreeNode *deserialize(char *buff){
    if(buff[0] == 0) return NULL;
    int i = 0;
    int flag = 1;//1代表左子树,-1代表右子树
    stack<TreeNode *> sta;
    TreeNode *p, *root;
    while(buff[i]){
        printf("i = %d\n", i);
        if(buff[i] >= '0' && buff[i] <= '9'){
            int x = buff[i] - '0';
            while(buff[i + 1] >= '0' && buff[i + 1] <= '9'){//将字符串转换为数字
                i++;
                x = x * 10 + buff[i] - '0';
            }
            p = new TreeNode(x);
            if(!sta.empty()){//如果栈不为空则将p节点作为栈顶节点的子节点
                if(flag == 1) sta.top()->left = p;
                if(flag == -1) sta.top()->right = p;
            }
            else root = p;//如果栈为空,则将p作为根节点
        }
        if(buff[i] == '('){
            sta.push(p);
            flag = 1;
        }
        if(buff[i] == ','){
            flag = -1;
        }
        if(buff[i] == ')'){
            sta.pop();
        }
        i++;     
    }
    return root;
}

题目1:二叉树的层序遍历(leetcode-102)

问题描述

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

样例输入

[3,9,21,2,4,null,7,null,null,2,6]

样例输出

[[3],[9,21],[2,4,7],[2,6]]

问题分析

此问题在二叉树层序遍历的同时,要记录遍历元素的层数。因此可以在上文的代码基础上进行修改,增设一个新变量cnt,记录每一层的节点数。依次遍历每一层的节点,当一层节点遍历完成后,栈中有且只有下一层所有的节点。

最终代码

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        TreeNode *node;
        queue<TreeNode *> q;
        q.push(root);
        vector<vector<int>> ans;
        while(!q.empty()){
            if(root == NULL) return vector<vector<int>>();
            int cnt = q.size();
            vector<int> temp;
            for(int i = 0; i < cnt; i++){
                node = q.front();
                temp.push_back(node->val);
                if(node->left) q.push(node->left);
                if(node->right) q.push(node->right);
                q.pop();
            }
            ans.push_back(temp);
        }
        return ans;
    }
};

总结

二叉树可以和栈、递归等知识灵活结合,尤其是在处理二叉树的左右子树时。此外,在处理二叉树时,可通过各种操作记录信息,比如题目一中的层序遍历。

此处再分享一个leetcode系统的使用技巧。例如想测试操作1至操作4的代码,但是自己又不想写生成二叉树的代码,此时可以把代码复制到leetcode的某个以二叉树为输入的题目中,例如leecode-102。复制进入后,并编写一段输出结果的代码,运行后会在“标准输出”中显示出代码的运行结果,如下图所示:

此外,leetcode是可以自己初始化测试用例的,特别方便,点击“+”即可。(而且你会发现二叉树的示意图是根据初始化的数据实时更新的!)

因此,可以把leetcode作为测试代码的工具,不需要我们去设计初始化代码,且能够非常方便的初始化数据,但缺点是有时代码运行速度较慢。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值