C++代码实现二叉树遍历算法(中序、前序、后序、中序非递归、层次遍历、计算二叉树高度、叶子数、交换左右子树)


算法逻辑可能并不严谨,欢迎各位大佬批评指正!


一、问题分析及数据结构设计

1、问题分析

首先编写函数建立二叉树,在已有二叉树的基础上编写函数实现二叉树的中序递归遍历、二叉树的中序非递归遍历算法、借助队列实现二叉树的层次遍历算法、求二叉树的高度、求二叉树的结点个数、求二叉树的叶子个数及交换二叉树每个结点的左子树和右子树,最后在主函数中利用分支语句将上面的函数连起来。

2、数据结构设计

  1. 结构体TreeNode:用于表示二叉树的节点结构,包含一个字符数据成员data,以及左子树和右子树的指针成员left和right。
  2. 函数设计包括以下几个主要函数:
    InOrderTraversal:实现中序遍历二叉树的递归函数。
    PreOrderTraversal:实现前序遍历二叉树的递归函数。
    PostOrderTraversal:实现后序遍历二叉树的递归函数。
    InorderNonRecursiveTraversal:实现中序非递归遍历二叉树的函数,使用了栈来辅助遍历。
    LevelOrderTraversal:实现层次遍历二叉树的函数,使用了队列来辅助遍历。
    getHeight:计算二叉树的高度,使用了递归计算左右子树的高度,并返回较大值加1。
    getNodeCount:计算二叉树的结点个数,使用了递归计算左右子树的结点个数,并返回左右子树结点个数之和加1。
    getLeafCount:计算二叉树的叶子个数,使用了递归计算左右子树的叶子个数,并返回左右子树叶子个数之和。
    SwapBinaryTree:交换二叉树的左右子树,采用递归实现。
    FreeBinaryTree:释放二叉树的内存空间。

二、算法设计

1 中序(前序、后序)递归遍历算法

定义三个递归函数InOrderTraversal、PreOrderTraversal和PostOrderTraversal,用于分别实现中序、前序和后序遍历二叉树。在每一轮递归中,先递归遍历左子树,然后输出当前节点的值,最后递归遍历右子树。通过调用这三个遍历函数,可以分别实现对二叉树的中序、前序和后序遍历。

1.1 中序递归算法流程图(前序、后序类似)

在这里插入图片描述

1.2 算法

// 中序遍历二叉树
void InOrderTraversal(TreeNode* root) {
    if (root == nullptr) {
        return;
    }
    InOrderTraversal(root->left);
    cout << root->data << " ";
    InOrderTraversal(root->right);
}

// 前序遍历二叉树
void PreOrderTraversal(TreeNode* root) {
    if (root == nullptr) {
        return;
    }
    cout << root->data << " ";
    PreOrderTraversal(root->left);
    PreOrderTraversal(root->right);
}

// 后序遍历二叉树
void PostOrderTraversal(TreeNode* root) {
    if (root == nullptr) {
        return;
    }
    PostOrderTraversal(root->left);
    PostOrderTraversal(root->right);
    cout << root->data << " ";
}

2 中序非递归遍历算法

定义一个栈保存节点,模拟递归的过程:从根节点开始,将左子树节点逐个入栈,直到叶子节点;然后弹出栈顶节点并访问,之后处理右子树。重复步骤,直到栈为空且当前节点也为空。

2.1 算法流程图

在这里插入图片描述

2.2 算法

// 中序非递归遍历二叉树
void InorderNonRecursiveTraversal(TreeNode* root) {
    stack<TreeNode*> nodeStack;
    TreeNode* curr = root;
    while (curr != nullptr || !nodeStack.empty()) {
        while (curr != nullptr) {
            nodeStack.push(curr);
            curr = curr->left;
        }
        curr = nodeStack.top();
        nodeStack.pop();
        cout << curr->data << " ";
        curr = curr->right;
    }
}

3 层次遍历算法(借助队列)

定义一个队列nodeQueue,用于存储每一层的节点。将根节点入队,并在每一轮循环中,将队首节点出队,并输出该节点的值。如果节点有左子树,则将左子树的节点入队;如果节点有右子树,则将右子树的节点入队。重复上述步骤,直到队列为空且所有节点都已访问。

3.1 算法流程图

在这里插入图片描述

3.2 算法

// 层次遍历二叉树
void LevelOrderTraversal(TreeNode* root) {
    if (root == nullptr)
        return;

    queue<TreeNode*> nodeQueue;
    nodeQueue.push(root);

    while (!nodeQueue.empty()) {
        TreeNode* curr = nodeQueue.front();
        nodeQueue.pop();
        cout << curr->data << " ";

        if (curr->left != nullptr)
            nodeQueue.push(curr->left);

        if (curr->right != nullptr)
            nodeQueue.push(curr->right);
    }
}

4 计算二叉树的高度

定义一个递归函数getHeight,用于计算二叉树的高度。在每一轮递归中,分别计算左子树和右子树的高度,并返回较大值加1作为当前子树的高度。

4.1 流程图

在这里插入图片描述

4.2 算法

// 求二叉树的高度
int getHeight(TreeNode* root) {
    if (root == nullptr) {
        return 0;
    }

    int leftHeight = getHeight(root->left);
    int rightHeight = getHeight(root->right);

    return max(leftHeight, rightHeight) + 1;
}

5 计算二叉树的叶子个数

定义一个递归函数getLeafCount,用于计算二叉树的叶子个数。在每一轮递归中,如果当前节点是叶子节点(即左子树为空且右子树为空),返回1。否则,分别计算左子树和右子树的叶子个数,并返回左右子树叶子个数之和作为当前子树的叶子个数。

5.1流程图

在这里插入图片描述

5.2 算法

// 求二叉树的叶子个数
int getLeafCount(TreeNode* root) {
    if (root == nullptr) {
        return 0;
    }

    if (root->left == nullptr && root->right == nullptr) {
        return 1;
    }

    int leftCount = getLeafCount(root->left);
    int rightCount = getLeafCount(root->right);

    return leftCount + rightCount;
}

6 交换二叉树每个结点的左子树和右子树

定义一个递归函数SwapBinaryTree,用于交换二叉树的左右子树。在每一轮递归中,交换当前节点的左右子树,并分别对左子树和右子树进行交换。

6.1 流程图

在这里插入图片描述

6.2 算法

// 交换二叉树左右子树
void SwapBinaryTree(TreeNode*& root) {
    if (root == nullptr) {
        return;
    }
    swap(root->left, root->right);
    SwapBinaryTree(root->left);
    SwapBinaryTree(root->right);
}

三、整体算法复杂度

  1. 创建二叉树的复杂度为O(n),其中n为序列的长度。
  2. 递归遍历二叉树的复杂度为O(n),其中n为节点个数。
  3. 非递归遍历二叉树、求二叉树的高度、节点个数、叶子个数、交换左右子树和释放二叉树内存空间的复杂度都为O(n)。

四、附程序完整代码

二叉树遍历程序完整代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值