4.二叉树的遍历(C++版)

二叉树的递归

1.二叉树递归遍历

二叉树的递归序

递归序过程:

  • 两个注释1之间的代码代表第一次来到一个节点的时候,会判断一下这个节点是否为空;
  • 来到这个节点的左树去遍历。
  • 遍历完第二次回到本函数,进行两个注释2之间进行操作,两个注释2之间可以进行某些操作也可以不进行某些操作,但是一定会返回本函数
  • 来到这个节点的右树去遍历。
  • 遍历完第三次回到本函数,进行两个注释3之间进行操作,两个注释3之间可以进行某些操作也可以不进行某些操作,但是一定会返回本函数
  • 本函数结束,返回。
void traversal(TreeNode *root) {
    //1
    if (root == nullptr) {
        return;
    }
    //1
    
    traversal(root->left);
    //2
    
    //2
    
    traversal(root->right);
    //3
    
    //3
}

例:进行下棵树的递归序

用递归方法进行二叉树的遍历,每个节点都会返回三次,可能每次返回的时候可能什么都没干,但一定会回到这个节点的。在递归序的基础上可以加工出二叉树的三种遍历。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JauQbrGG-1646122976972)(C:\Users\ThinkStation K\AppData\Roaming\Typora\typora-user-images\1646104345527.png)]

①二叉树的先序遍历

对递归序第一次来到一个节点时打印,第2、3次来到一个节点什么都不做,产生的就是先序遍历。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M2PBsWzT-1646122976973)(C:\Users\ThinkStation K\AppData\Roaming\Typora\typora-user-images\1646105038682.png)]

void preOrderTraversal(TreeNode *root) {
    //1
    if (root == nullptr) {
        return;
    }
    cout << root->val << " ";
    //1
    
    traversal(root->left);
    //2
    
    //2
    
    traversal(root->right);
    //3
    
    //3
}
//打印1 2 4 5 3 6 7

②二叉树的中序遍历

对递归序第二次来到一个节点时打印,第2、3次来到一个节点什么都不做,产生的就是先序遍历。

void midOrderTraversal(TreeNode *root) {
    //1
    if (root == nullptr) {
        return;
    }
    //1
    
    traversal(root->left);
    //2
    cout << root->val << " ";
    //2
    
    traversal(root->right);
    //3
    
    //3
}
//打印:4 2 5 1 6 3 7

③二叉树的后续遍历

对递归序第三次来到一个节点时打印,第2、3次来到一个节点什么都不做,产生的就是先序遍历。

void posOrderTraversal(TreeNode *root) {
    //1
    if (root == nullptr) {
        return;
    }
    //1
    
    traversal(root->left);
    //2

    //2
    
    traversal(root->right);
    //3
    cout << root->val << " ";
    //3
}
//打印:4 5 2 6 7 3 1

2.二叉树的非递归遍历

任何递归都能改成非递归,递归遍历就是系统帮你压栈,非递归就是自己压栈。

①二叉树的先序遍历

非递归的先序遍历过程为每次进行如下操作:

  • 从栈中弹出一个节点cur
  • 打印(处理)cur
  • 如果cur有右节点,先将右节点压栈;如果cur有左节点,再将左节点压栈。
  • 重复上述行为。

代码为:

void preOrderTraversal(TreeNode *root) {
    if (root == nullptr) return;
    stack<TreeNode*> st;
    st.push(root);
    while (!st.empty()) {
        //从栈中弹出一个节点cur
        TreeNode *node = st.top();
        st.pop();
        //打印(处理)cur
        cout << node->val << " ";
        //如果cur有右节点,先将右节点压栈;如果cur有左节点,再将左节点压栈。
        if (root->right) {
            st.push(root->right);
        }
        if (root->left) {
            st.push(root->left);
        }
    }
}

②二叉树的后序遍历

非递归的中序遍历过程先准备两个栈,一个压栈,一个收集栈。为每次进行如下操作:

  • 从栈中弹出一个节点cur
  • cur放入收集栈
  • 如果cur有左节点,先将左节点压栈;如果cur有右节点,再将右节点压栈。
  • 重复上述行为。

整个过程结束之后,将收集栈节点弹出,便是后续遍历。

void posOrderTraversal(TreeNode *root) {
    stack<TreeNode*> st1;
    stack<TreeNode*> st2;
    if (root == nullptr) return;
    st1.push(root);
    while (!st.empty()) {
        TreeNode *node = st.top();
        st.pop();
        st2.push(node);
        if (node->left) {
            st1.push(node->left);
        }
        if (node->right) {
            st1.push(node->right);
        }
    }
    while (!st2.empty()) {
        TreeNode *node = st2.top();
        st2.pop();
        cout << node->val << " ";
    }
}

③中序遍历

非递归的中序遍历过程是每棵子树进行如下操作:

  • 整棵树的左边界进栈。
  • 依次弹出节点的过程中打印(操作),对弹出节点的右树周而复始。

代码如下:

void midOrderTraversal(TreeNode *root) {
    if (root == nullptr) {
        return;
    }
    stack<TreeNode*> st;
    TreeNode *node = root;
    while (!st.empty() || node) {
		if (node) {
            st.push(node);
            node = node->left;
        } else {
         	node = st.top();
            st.pop();
            cout << node->val << " ";
            node = node->right;
        }
    } 
}

3.二叉树的层序遍历

void traversal(TreeNode *root) {
    queue<TreeNode*> que;
    if (root == nullptr) {
        return nullptr;
    }
    que.push(root);
    
    while (!que.empty()) {
        TreeNode *node;
        node = st.top();
        st.pop();
        cout << node->val << " ";
        if (node->left) {
            que.push(node->left);
        }
        if (node->right) {
            que.push(node->right);
        }
    }
}
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值