二叉树的前序遍历,中序遍历,后序遍历和层序遍历

二叉树的前序遍历,中序遍历,后序遍历和层序遍历

144. 二叉树的前序遍历 - 力扣(LeetCode)

94. 二叉树的中序遍历 - 力扣(LeetCode)

145. 二叉树的后序遍历 - 力扣(LeetCode)

102. 二叉树的层序遍历 - 力扣(LeetCode)

1. 二叉树的实现:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct TreeNode {
    int data;
    struct TreeNode *left, *right;
}node;
node *GetNewNode(int val){
    node *newnode = (node *)malloc(sizeof(node));
    newnode->left = NULL;
    newnode->right = NULL;
    newnode->data = val;
    return newnode;
}
void TreeNodeClear(node *root){
    if(root == NULL){
        return;
    }
    TreeNodeClear(root->left);
    TreeNodeClear(root->right);
    free(root);
    return;
}
node *Insert(node *root, int val){
    if(root == NULL){
        return GetNewNode(val);
    }
    if(rand() % 2){
        root->left = Insert(root->left, val);
    }else{
        root->right = Insert(root->right, val);
    }
    return root;
}
//广度优先遍历bfs
node *queue[15];
int head = 0, tail = 0;
void bfs(node *root){
    queue[tail++] = root;
    while(head < tail){
        node *node = queue[head];
        printf("\nnode : %d\n", node->data);
        if(node->left){
            queue[tail++] = node->left;
            printf("\t%d->%d (left)\n", node->data, node->left->data);
        }
        if(node->right){
            queue[tail++] = node->right;
            printf("\t%d->%d (right)\n", node->data, node->right->data);
        }
        head++;
    }
    return;
}
int main()
{
    srand(time(0));
    node *root = NULL;
    for(int i = 0 ; i < 10 ; i++){
        root = Insert(root, rand() % 100);
    }
    bfs(root);
    return 0;
}

2. 二叉树的前序遍历

123

【前序遍历】如果二叉树为空,则直接返回。否则,先访问根结点,再递归前序遍历左子树,再递归前序遍历右子树。

code:

void pre_order(node *root){
    if(root == NULL){
        return;                //(1)
    }
    printf("%d ", root->data); //(2)
    pre_order(root->left);     //(3) 
    pre_order(root->right);    //(4)
    return;
}
  • (1) 待访问结点为空时,直接返回;
  • (2)先访问当前树的根;
  • (3)再前序遍历左子树;
  • (4)最后前序遍历右子树;

3. 二叉树的中序遍历

123

【中序遍历】如果二叉树为空,则直接返回。否则,先递归中序遍历左子树,再访问根结点,再递归中序遍历右子树。

code:

void in_order(node *root){
    if(root == NULL){
        return;                //(1)
    }
    pre_order(root->left);     //(2)
    printf("%d ", root->data); //(3)
    pre_order(root->right);    //(4)
    return;
}
  • (1) 待访问结点为空时,直接返回;
  • (2) 先中序遍历左子树;
  • (3) 再访问当前树的根;
  • (4) 最后中序遍历右子树;

4. 二叉树的后序遍历

后序遍历

void post_order(node *root){
    if(root == NULL){
        return;                 //(1)
    }
    post_order(root->left);     //(2)
   	post_order(root->right);    //(3)
    printf("%d ", root->data);  //(4)
    return;
}
  • (1)待访问结点为空时,直接返回;
  • (2) 先后序遍历左子树;
  • (3)再后序遍历右子树;
  • (4) 再访问当前树的根;

5.力扣三种遍历的练习

144. 二叉树的前序遍历 - 力扣(LeetCode)

94. 二叉树的中序遍历 - 力扣(LeetCode)

145. 二叉树的后序遍历 - 力扣(LeetCode)

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

示例 1:image-20240419194744770

输入:root = [1,null,2,3]
输出:[1,2,3]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]

示例 4:image-20240419194806431

输入:root = [1,2]
输出:[1,2]

示例 5:image-20240419194829310

输入:root = [1,null,2]
输出:[1,2]
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
void pre_order(struct TreeNode* root, int *ret, int* returnSize){
    if(root == NULL){
        return;
    }
    ret[(*returnSize)++] = root->val;
    pre_order(root->left, ret, returnSize);
    pre_order(root->right, ret, returnSize);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    int *ret = (int *)malloc(sizeof(int) * 100);
    *returnSize = 0;
    pre_order(root, ret, returnSize);
    return ret;
}

给定一个二叉树的根节点 root ,返回 它的 中序 遍历

示例 1:image-20240419194939625

输入:root = [1,null,2,3]
输出:[1,3,2]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
void in_order(struct TreeNode* root, int* ret, int *returnSize){
    if(root == NULL){
        return;
    }
    in_order(root->left, ret, returnSize);
    ret[(*returnSize)++] = root->val;
    in_order(root->right, ret, returnSize);
}
int* inorderTraversal(struct TreeNode* root, int* returnSize) {
    int *ret = (int *)malloc(sizeof(int) * 100);
    *returnSize = 0;
    in_order(root, ret, returnSize);
    return ret;
}

给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历

示例 1:image-20240419195039866

输入:root = [1,null,2,3]
输出:[3,2,1]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
void post_order(struct TreeNode *root, int *ret, int *returnSize){
    if(root == NULL){
        return;
    }
    post_order(root->left, ret, returnSize);
    post_order(root->right, ret, returnSize);
    ret[(*returnSize)++] = root->val;
}
int* postorderTraversal(struct TreeNode* root, int* returnSize) {
    int *ret = (int *)malloc(sizeof(int) * 100);
    *returnSize = 0;
    post_order(root, ret, returnSize);
    return ret;
}

6. 二叉树的层序遍历

层序遍历所要解决的问题很好理解,就是按二叉树从上到下,从左到右依次打印每个节点中存储的数据。实现过程为:

  1. 创建一个队列。
  2. 将根节点入队。
  3. 取出队首元素,输出该元素的值,如果该元素有左孩子,将左孩子入队,如果该元素有右孩子,将右孩子入队。
  4. 重复步骤3,直到队列为空。

code:

node *queue[15];
int head = 0, tail = 0;
void bfs(node *root){
    queue[tail++] = root;
    while(head < tail){
        node *node = queue[head];
        printf("\nnode : %d\n", node->data);
        if(node->left){
            queue[tail++] = node->left;
            printf("\t%d->%d (left)\n", node->data, node->left->data);
        }
        if(node->right){
            queue[tail++] = node->right;
            printf("\t%d->%d (right)\n", node->data, node->right->data);
        }
        head++;
    }
    return;
}

输出结果:

image-20240419193951501

102. 二叉树的层序遍历 - 力扣(LeetCode)

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

image-20240419194148676

输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]
输入:root = [1]
输出:[[1]]
输入:root = []
输出:[]

code:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */
int** levelOrder(struct TreeNode* root, int* returnSize, int** returnColumnSizes) {
    typedef struct TreeNode node; 
    int **ret = (int **)malloc(sizeof(int *) * 2000);//申请一个二维数组,这个数组有两千行
    int returnCnt = 0;//定义一个要返回的ret这个二维数组的行数,并将它初始为0
    if(root == NULL){
        *returnSize = 0;
        return NULL;
    }//如果根节点为NULL,*returnSize = 0 并返回NULL
    int *returnColSize = (int *)malloc(sizeof(int) * 2000);//定义一个数组returnColsize,它的含义是ret二维数组每一行的列数
    node *queue[2000];
    int head = 0, tail = 0;
    queue[tail++] = root;//将根节点放入队列
    while(head < tail){
        int queueCurSize = tail - head;//计算当前队列的长度
        ret[returnCnt] = (int *)malloc(sizeof(int) * queueCurSize);//二叉树每层节点的数量是queueCurSize,并将每层节点的数量放入每层ret数组,即这个二维数组每层的列数应该是queueCurSize
        returnColSize[returnCnt] = queueCurSize;//ret数组每层的列数为queueCurSize
        for(int i = 0 ; i < queueCurSize ; i++){
            ret[returnCnt][i] = queue[head]->val;//将二叉树每层节点的值放入用来记录的二维数组
            if(queue[head]->left){
                queue[tail++] = queue[head]->left;
            }
            if(queue[head]->right){
                queue[tail++] = queue[head]->right;
            }
            head++;//遍历到当前根节点时,如果当前根节点有左右孩子节点,就压入队列,随后弹出当前根节点,继续遍历当前层的根节点,遍历完每一层都能将每一层节点的值放入ret数组,并将下一层节点压入队列
        }
        returnCnt++;//ret的行数returnCnt++
    }
    *returnSize = returnCnt;//要返回的ret数组的行数应该是returnCnt
    *returnColumnSizes = returnColSize;//要返回的ret数组的每行的列数的数组为returnColSize
    return ret;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值