二叉树的先序、后序、中序排序(C++)

目录

        二叉树数据结构定义

        利用递归遍历二叉树,在遍历每个节点的不同位置打印对应不同的遍历顺序。

一、先序遍历(对于每一颗子树先打印头结点,再打印左节点,最后打印右节点)

1、递归遍历

2、非递归的方式进行先序遍历(利用栈)

二、中序遍历(对于每一颗子树先打印左节点,再打印头节点,最后打印右节点)

1、递归遍历

2、非递归的方式进行中序遍历(利用栈)

三、后序遍历(对于每一颗子树先打印左节点,再打印右节点,最后打印头节点)

1、递归遍历

2、非递归的方式进行后序遍历(利用栈)

四、宽度优先遍历(利用栈逐层遍历)


二叉树数据结构定义

 struct TreeNode {
     int val;
     TreeNode *left;
     TreeNode *right;
     TreeNode() : val(0), left(nullptr), right(nullptr) {}
     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 };

利用递归遍历二叉树,在遍历每个节点的不同位置打印对应不同的遍历顺序。

void f(TreeNode *head, vector<int>& ans){
    //第一次进入该节点
    if(head == nullptr)
        return;
    //第一次回到自己
    f(head->left, ans);
    //第二次进入该节点
    
    //第二次回到自己
    f(head->right, ans);
    //第三次进入该节点

    //第三次回到自己
}

一、先序遍历(对于每一颗子树先打印头结点,再打印左节点,最后打印右节点)

 深度优先遍历即为先序遍历

1、递归遍历

第一次遍历到每个节点时打印对应先序遍历。

 vector<int> ans 中存放的就是对应的遍历顺序。

//递归函数
void f(TreeNode *head, vector<int>& ans){
    if(head == nullptr)
        return;
    ans.push_back(head->val);
    f(head->left, ans);
    f(head->right, ans);
}
//调用递归,返回前序遍历顺序
vector<int> preorderTraversal(TreeNode* root) {
    vector<int> ans;
    f(root, ans);
    return ans;
}

2、非递归的方式进行先序遍历(利用栈)

整体流程

先给栈中压入根节点

(栈不为空循环下述操作)

  1. 弹出栈中节点
  2. 对该节点进行操作
  3. 将节点右节点左节点先后压入栈中(没有跳过)
vector<int> preorderTraversal(TreeNode* root) {
    vector<int> ans;
    stack<TreeNode*> stackTreeNode;
    if(root == NULL) return {};
    stackTreeNode.push(root);
    while(stackTreeNode.size()){
        TreeNode *cur = stackTreeNode.top();
        stackTreeNode.pop();
        ans.push_back(cur->val);
        if(cur->right != NULL) stackTreeNode.push(cur->right);
        if(cur->left != NULL) stackTreeNode.push(cur->left);
    }
    return ans;
}

二、中序遍历(对于每一颗子树先打印左节点,再打印头节点,最后打印右节点)

1、递归遍历

第二次遍历到每个节点时打印对应中序遍历。

void f(TreeNode *head, vector<int>& ans){
    if(head == nullptr)
        return;
    f(head->left, ans);
    ans.push_back(head->val);
    f(head->right, ans);
}

2、非递归的方式进行中序遍历(利用栈)

整体流程

压入顺序左右头

每棵树左边界压入栈,依次弹出节点的过程中对弹出节点的右树重复上述操作。

(栈1不为空循环下述操作)

  1. 弹出中节点
  2. 对该节点进行操作
  3. 对该节点右树重复
vector<int> inorderTraversal(TreeNode* root) {
    vector<int> ans;
    if(root == NULL) return {};
    stack<TreeNode*> s;
    TreeNode *cur = root;
    while(s.size() || cur!= NULL)
    {
        if(cur != NULL){
            s.push(cur);
            cur = cur->left;
        }
        else{
            cur = s.top();
            s.pop();
            ans.push_back(cur->val);
            cur = cur->right;
        }
    }
    return ans;
}

三、后序遍历(对于每一颗子树先打印左节点,再打印右节点,最后打印头节点)

1、递归遍历

第三次遍历到每个节点时打印对应后序遍历。

void f(TreeNode *head, vector<int>& ans){
    if(head == nullptr)
        return;
    f(head->right, ans);
    f(head->left, ans);
    ans.push_back(head->val);
}

2、非递归的方式进行后序遍历(利用栈)

整体流程

需要两个栈

先给栈1压入根节点

(栈1不为空循环下述操作)

  1. 弹出栈1中节点
  2. 对该节点进行操作
  3. 将该节点放入栈1
  4. 将节点左节点右节点先后压入栈1中(没有跳过)
vector<int> postorderTraversal(TreeNode* root) {
    vector<int> ans;
    if(root == NULL) return {};
    stack<TreeNode*> s1;
    stack<TreeNode*> s2;
    s1.push(root);
    while(s1.size()){
        TreeNode *cur = s1.top();
        s1.pop();
        s2.push(cur);
        if(cur->left!=NULL) s1.push(cur->left);
        if(cur->right!=NULL) s1.push(cur->right);
    }
    while(s2.size())
    {
        TreeNode *cur = s2.top();
        ans.push_back(cur->val);
        s2.pop();
    }
    return ans;

}

四、宽度优先遍历(利用栈逐层遍历)

    void levelOrder(TreeNode* root) {
        if(root == NULL) return;
        queue<TreeNode*> q;
        q.push(root);
        while(q.size())
        {
            TreeNode *cur = q.front();
            q.pop();
            if(cur->left != NULL) q.push(cur->left);
            if(cur->right != NULL) q.push(cur->right);
        }
        return;
    }

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值