二叉树的遍历及应用(详细代码)

一、前言

很久没有写博客了,主要是因为懒。但是有些东西确实是比较好,值得分享。

二、二叉树的遍历(基础版)

        如果学过数据结构的话,应该都了解二叉树的遍历,所以这里对于遍历是什么就不做赘述了。本文的目的是对遍历的算法代码进行回顾和优化。

1、前序遍历

        如果我们将一棵二叉树的局部提取出来,所谓前序遍历就是按照“中左右的方式遍历”。有些朋友可能会搞混他们的关系,可以这样理解:什么序遍历就是“中”放的位置。怎么理解呢?如下*

前序遍历:中-->左-->右

中序遍历:左-->中-->右

后序遍历:左-->右-->中

        我们可以观察到,不管是什么遍历,“左右”的访问顺序是不变的,唯一变化的是中间节点的访问顺序,所以我们可以知道前序遍历就是中间节点在前面访问的遍历,中序遍历就是中间节点在中间访问的遍历。

        之后我们在来看看代码,最普遍的前序遍历方式是递归,代码如下:

C++
void traversal(TreeNode* cur, vector<int>& vec) {
     if (cur == NULL) return;
     vec.push_back(cur->val); 
     traversal(cur->left, vec); 
     traversal(cur->right, vec); 
}

写成非递归形式就是:

C++

vector<int> preorderTraversal(TreeNode* root) {
     stack<TreeNode*> st;
     vector<int> result;
     if (root == NULL) return result;
         st.push(root);
     while (!st.empty()) {
         TreeNode* node = st.top(); // 中
         st.pop();
         result.push_back(node->val);
         if (node->right) st.push(node->right);
         if (node->left) st.push(node->left); 
     }
     return result;
 }

2、中序遍历

递归形式:

C++
void traversal(TreeNode* cur, vector<int>& vec) {
     if (cur == NULL) return;
     traversal(cur->left, vec); 
     vec.push_back(cur->val); 
     traversal(cur->right, vec); 
}

        只是讲结果的push顺序改变而已。

非递归形式:

        中序遍历非递归的思路就又产生变化了。代码如下:

C++
        vector<int> mid_bianli(TreeNode*root){
            vector<int> result;
            stack<TreeNode*> st;
            TreeNode *cur=root;
            while(cur!=NULL||!st.empty()){
                if(cur!=NULL){
                    st.push(cur);
                    cur=cur->left;
                }else{
                    cur = st.top();
                    st.pop();
                    result.push_back(cur->val);
                    cur=cur->right;
                }
            }
            return result;
        }

3、后序遍历

递归形式:

C++
void traversal(TreeNode* cur, vector<int>& vec) {
     if (cur == NULL) return;
     traversal(cur->left, vec); 
     traversal(cur->right, vec); 
     vec.push_back(cur->val); 
}

非递归形式:

C++

        vector<int> pre_bianli(TreeNode*root){
            vector<int> result;
            stack<TreeNode*> st;
            TreeNode*cur=root;
            if(root==NULL)return NULL;
            st.push(cur);
            while(!st.empty()){
                cur=st.top();
                st.pop();
                if(cur->right)st.push(cur->right);
                if(cur->left)st.push(cur->left);
                result.push_back(cur->val);
            }
            return result;
        }

        非递归形式:这里需要注意的是,前序遍历的顺序是“中左右”,后序遍历的顺序是“左右中”。我们只需要对前序遍历的push顺序从“左右”变成“右左”,结果就变成了“中右左”,之后再反转一下数组,就得到了需要的“左右中”。

三、二叉树的统一遍历法

        上面的二叉树遍历方式,前序和后续还好,但是中序就有些不一样了。如果是记忆代码的话,可能就容易记错。因此,为了在手撸代码的时候可以更方便的写出遍历,有牛人想出了二叉树统一遍历法。代码如下:

        vector<int> DiedaiBianli(TreeNode*root){
            vector<int> result;
            stack<TreeNode*> st;
            if (root != NULL) st.push(root);
            while (!st.empty()) {
                TreeNode* node = st.top();
                if (node != NULL) {
                st.pop();
                st.push(node); // 中
                st.push(NULL);
                if (node->right) st.push(node->right); // 右
                if (node->left) st.push(node->left); // 左
                } else {
                    st.pop();
                    node = st.top();
                    st.pop();
                    result.push_back(node->val);
                }
            }
            return result
        }

这份代码可以通过调整push(node)的顺序来实现前中后遍历,真正实现了一码多用。

四、层次遍历

不多说,代码如下:

        vector<vector<int>> cengxu(TreeNode*root){
            queue<TreeNode*> que;
            vector<vector<int>> result;
            if(root!=NULL)
                que.push_back(root);
            while(!que.empty()){
                int size = que.size();
                vector<int>temp;
                for(int i=0;i<size;i++){
                    TreeNode* node = que.front();
                    que.pop();
                    temp.push_back(node->val);
                    if(node->left)que.push_back(node->left);
                    if(node->right)que.push_back(node->right);
                }
                result.push_back(temp);
            }
            //reverse(result.begin(), result.end());  在这⾥反转⼀下数组即可完成自底向上的层序遍历
            return result;
        }

五、结尾

        本次写这份博客的目的不在于解说,而是在于贴出与二叉树有关的代码模板供大家复制粘贴。因为时间关系,几乎只有C++版本的语言。为了适应不同语种人群,我将在后续完善java、python、JavaScript等语言的实现代码。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少๑渊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值