二叉树-DFS-BFS-递归-非递归

二叉树-DFS-BFS-递归-非递归

BFS

BFS一般使用非递归的模式访问相对简单,其递归的模式相当于是非递归模式,按每一层打标签访问的结果。使用list保存每一层的需要访问的节点,可以将代码写成递归形式。

非递归形式

主要思想:从根节点以此访问左右子树,然后将访问到的节点按访问顺序依次存储在队列之中,在队列非空的情况下,一直按照这种方案进行即可完成BFS的非递归访问。

#include <iostream>
#include <vector>
#include <stack>
#include <cmath>
#include <map>
#include <string>
#include <list>
using namespace std;

struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int vall){
        val = vall;
        left = NULL;
        right = NULL;
    }
};

vector<int> BFSNoRecursive(TreeNode *root){
    vector<int> ans;
    list<TreeNode *> llist;
    if(root == NULL){
        return ans;
    }
    else{
        llist.push_back(root);
    }
    while(!llist.empty()){
        TreeNode *temp = llist.front();
        ans.push_back(temp->val);
        if(temp->left){
            llist.push_back(temp->left);
        }
        if(temp->right){
            llist.push_back(temp->right);
        }
        llist.pop_front();
    }
    return ans;
}

int main(int argc, const char * argv[]) {
    TreeNode *r1 = new TreeNode(1);
    TreeNode *r2 = new TreeNode(2);
    TreeNode *r3 = new TreeNode(3);
    TreeNode *r4 = new TreeNode(4);
    TreeNode *r5 = new TreeNode(5);
    TreeNode *r6 = new TreeNode(6);
    TreeNode *r7 = new TreeNode(7);
    r1->left = r2;
    r1->right = r3;
    r2->left = r4;
    r2->right = r5;
    r3->left = r6;
    r6->right = r7;
    
    vector<int> ans = BFSNoRecursive(r1);
    for(int i = 0; i < ans.size(); i++){
        cout << ans[i] << " ";
    }
    return 0;
}

递归形式

主要思想:用一个二维数组记录下每一层的指针,这个过程可以用递归来实现,其实在记录过程中,采用的是dfs的套路。记录完成之后,按层访问每一个节点即可。

#include <iostream>
#include <vector>
#include <stack>
#include <cmath>
#include <map>
#include <string>
#include <list>
using namespace std;

struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int vall){
        val = vall;
        left = NULL;
        right = NULL;
    }
};

void bfs(TreeNode *root, int level, vector<vector<TreeNode *> >& llist){
    if(root == NULL){
        return;
    }
    if(level >= llist.size()){
        vector<TreeNode *> listTemp;
        listTemp.push_back(root);
        llist.push_back(listTemp);
    }
    else{
        llist[level].push_back(root);
    }
    bfs(root->left, level+1, llist);
    bfs(root->right, level+1, llist);
}
vector<int> BFSRecursive(TreeNode *root){
    vector<int> ans;
    vector<vector<TreeNode *> > llist;
    if(root == NULL){
        return ans;
    }
    else{
        bfs(root, 0, llist);
    }
    for(int i = 0; i < llist.size(); i++){
        for(int j = 0; j < llist[i].size(); j++){
            ans.push_back(llist[i][j]->val);
        }
    }
    return ans;
}

int main(int argc, const char * argv[]) {
    TreeNode *r1 = new TreeNode(1);
    TreeNode *r2 = new TreeNode(2);
    TreeNode *r3 = new TreeNode(3);
    TreeNode *r4 = new TreeNode(4);
    TreeNode *r5 = new TreeNode(5);
    TreeNode *r6 = new TreeNode(6);
    TreeNode *r7 = new TreeNode(7);
    r1->left = r2;
    r1->right = r3;
    r2->left = r4;
    r2->right = r5;
    r3->left = r6;
    r6->right = r7;
    
    vector<int> ans = BFSRecursive(r1);
    for(int i = 0; i < ans.size(); i++){
        cout << ans[i] << " ";
    }
    return 0;
}

DFS

DFS的访问模式总共是分为三种,即先序,中序,后序。其中,先中后是相对于根节点而言的。

先序:根,左,右

中序:左,根,右

后序:左,右,根

这三种方式都有递归和非递归两种实现方法,比较简洁理想的是采用递归方式,非递归方式需要借助栈进行实现。

递归形式

只在递归的顺序上有很小的调整!!

先序

#include <iostream>
#include <vector>
#include <stack>
#include <cmath>
#include <map>
#include <string>
#include <list>
using namespace std;

struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int vall){
        val = vall;
        left = NULL;
        right = NULL;
    }
};

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

int main(int argc, const char * argv[]) {
    TreeNode *r1 = new TreeNode(1);
    TreeNode *r2 = new TreeNode(2);
    TreeNode *r3 = new TreeNode(3);
    TreeNode *r4 = new TreeNode(4);
    TreeNode *r5 = new TreeNode(5);
    TreeNode *r6 = new TreeNode(6);
    TreeNode *r7 = new TreeNode(7);
    r1->left = r2;
    r1->right = r3;
    r2->left = r4;
    r2->right = r5;
    r3->left = r6;
    r6->right = r7;
    
    vector<int> ans;
    DFSRecursive(r1, ans);
    for(int i = 0; i < ans.size(); i++){
        cout << ans[i] << " ";
    }
    return 0;
}

中序

#include <iostream>
#include <vector>
#include <stack>
#include <cmath>
#include <map>
#include <string>
#include <list>
using namespace std;

struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int vall){
        val = vall;
        left = NULL;
        right = NULL;
    }
};

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

int main(int argc, const char * argv[]) {
    TreeNode *r1 = new TreeNode(1);
    TreeNode *r2 = new TreeNode(2);
    TreeNode *r3 = new TreeNode(3);
    TreeNode *r4 = new TreeNode(4);
    TreeNode *r5 = new TreeNode(5);
    TreeNode *r6 = new TreeNode(6);
    TreeNode *r7 = new TreeNode(7);
    r1->left = r2;
    r1->right = r3;
    r2->left = r4;
    r2->right = r5;
    r3->left = r6;
    r6->right = r7;
    
    vector<int> ans;
    DFSRecursive(r1, ans);
    for(int i = 0; i < ans.size(); i++){
        cout << ans[i] << " ";
    }
    return 0;
}

后序

#include <iostream>
#include <vector>
#include <stack>
#include <cmath>
#include <map>
#include <string>
#include <list>
using namespace std;

struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int vall){
        val = vall;
        left = NULL;
        right = NULL;
    }
};

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

int main(int argc, const char * argv[]) {
    TreeNode *r1 = new TreeNode(1);
    TreeNode *r2 = new TreeNode(2);
    TreeNode *r3 = new TreeNode(3);
    TreeNode *r4 = new TreeNode(4);
    TreeNode *r5 = new TreeNode(5);
    TreeNode *r6 = new TreeNode(6);
    TreeNode *r7 = new TreeNode(7);
    r1->left = r2;
    r1->right = r3;
    r2->left = r4;
    r2->right = r5;
    r3->left = r6;
    r6->right = r7;
    
    vector<int> ans;
    DFSRecursive(r1, ans);
    for(int i = 0; i < ans.size(); i++){
        cout << ans[i] << " ";
    }
    return 0;
}

非递归形式

需要借助于栈结构,在向下查询的过程中,访问不到的节点先存储在栈中

先序

1、从根节点一路向左访问,并将访问到的每一个节点的指针存储在栈中。

2、由于是先序遍历,则在一路向左访问过程中,首先将每个根节点数据存储在ans中。

3、访问到最左以后,使用栈模拟回溯过程,依次对栈中每一个节点的右子树进行先序遍历。

#include <iostream>
#include <vector>
#include <stack>
#include <cmath>
#include <map>
#include <string>
#include <list>
using namespace std;

struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int vall){
        val = vall;
        left = NULL;
        right = NULL;
    }
};

vector<int> DFSNoRecursive(TreeNode *root){
    vector<int> ans;
    if(root == NULL){
        return ans;
    }
    stack<TreeNode*> s;
    TreeNode *temp = root;
    while(temp != NULL || !s.empty()){
        while(temp != NULL){
            ans.push_back(temp->val);
            s.push(temp);
            temp = temp->left;
        }
        if(!s.empty()){
            temp = s.top();
            s.pop();
            temp = temp->right;
        }
    }
    return ans;
}

int main(int argc, const char * argv[]) {
    TreeNode *r1 = new TreeNode(1);
    TreeNode *r2 = new TreeNode(2);
    TreeNode *r3 = new TreeNode(3);
    TreeNode *r4 = new TreeNode(4);
    TreeNode *r5 = new TreeNode(5);
    TreeNode *r6 = new TreeNode(6);
    TreeNode *r7 = new TreeNode(7);
    r1->left = r2;
    r1->right = r3;
    r2->left = r4;
    r2->right = r5;
    r3->left = r6;
    r6->right = r7;
    
    vector<int> ans = DFSNoRecursive(r1);
    for(int i = 0; i < ans.size(); i++){
        cout << ans[i] << " ";
    }
    return 0;
}

中序

基本和先序一致

1、从根节点一路向左访问,并将访问到的每一个节点的指针存储在栈中。

2、由于是中序遍历,则在一路向左访问过程中,不能将每个根节点数据存储在ans中,在回溯时,将根节点数据存储在ans中。

3、访问到最左以后,使用栈模拟回溯过程,依次对栈中每一个节点的右子树进行先序遍历。

#include <iostream>
#include <vector>
#include <stack>
#include <cmath>
#include <map>
#include <string>
#include <list>
using namespace std;

struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int vall){
        val = vall;
        left = NULL;
        right = NULL;
    }
};

vector<int> DFSNoRecursive(TreeNode *root){
    vector<int> ans;
    if(root == NULL){
        return ans;
    }
    stack<TreeNode*> s;
    TreeNode *temp = root;
    while(temp != NULL || !s.empty()){
        while(temp != NULL){
            s.push(temp);
            temp = temp->left;
        }
        if(!s.empty()){
            temp = s.top();
            s.pop();
            ans.push_back(temp->val);
            temp = temp->right;
        }
    }
    return ans;
}

int main(int argc, const char * argv[]) {
    TreeNode *r1 = new TreeNode(1);
    TreeNode *r2 = new TreeNode(2);
    TreeNode *r3 = new TreeNode(3);
    TreeNode *r4 = new TreeNode(4);
    TreeNode *r5 = new TreeNode(5);
    TreeNode *r6 = new TreeNode(6);
    TreeNode *r7 = new TreeNode(7);
    r1->left = r2;
    r1->right = r3;
    r2->left = r4;
    r2->right = r5;
    r3->left = r6;
    r6->right = r7;
    
    vector<int> ans = DFSNoRecursive(r1);
    for(int i = 0; i < ans.size(); i++){
        cout << ans[i] << " ";
    }
    return 0;
}

后序

先序和中序基本是一个套路,后序相对复杂一些,需要单独对当前访问树结构的根节点进行记录。相当于记录右子树的访问情况。因为此时,必须确定将左,右子树全部访问完,才访问根节点。

1、从根节点一路向左访问,并将访问到的每一个节点的指针存储在栈中。

2、在回溯过程中,首先将左子树的值记录下来,然后记录当前的根,然后判断右子树是否已经访问,如果未访问,则先访问右子树,最后再记录根节点的值。

#include <iostream>
#include <vector>
#include <stack>
#include <cmath>
#include <map>
#include <string>
#include <list>
using namespace std;

struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int vall){
        val = vall;
        left = NULL;
        right = NULL;
    }
};

vector<int> DFSNoRecursive(TreeNode *root){
    vector<int> ans;
    if(root == NULL){
        return ans;
    }
    stack<TreeNode*> s;
    TreeNode *temp = root;
    TreeNode *last = NULL;
    while(temp != NULL || !s.empty()){
        while(temp != NULL){
            s.push(temp);
            temp = temp->left;
        }
        if(!s.empty()){
            temp = s.top();
            if(temp->right == NULL || temp->right == last){
                ans.push_back(temp->val);
                s.pop();
                last = temp;
                temp = NULL;
            }
            else{
                temp = temp->right;
            }
        }
    }
    return ans;
}

int main(int argc, const char * argv[]) {
    TreeNode *r1 = new TreeNode(1);
    TreeNode *r2 = new TreeNode(2);
    TreeNode *r3 = new TreeNode(3);
    TreeNode *r4 = new TreeNode(4);
    TreeNode *r5 = new TreeNode(5);
    TreeNode *r6 = new TreeNode(6);
    TreeNode *r7 = new TreeNode(7);
    r1->left = r2;
    r1->right = r3;
    r2->left = r4;
    r2->right = r5;
    r3->left = r6;
    r6->right = r7;
    
    vector<int> ans = DFSNoRecursive(r1);
    for(int i = 0; i < ans.size(); i++){
        cout << ans[i] << " ";
    }
    return 0;
}
点赞