二叉树深度优先遍历详解

二叉树的遍历(每一种遍历次序有递归实现(简捷)和迭代实现两种方式)

二叉树深度优先遍历详解_第1张图片

深度优先遍历

1.递归实现

中根遍历的递归实现

 

    vector result;
    vector inorderTraversal(TreeNode* root) {
        inorder(root);
        return result;
    }
    void inorder(TreeNode* root){
        if(root == nullptr){
            return;
        }
        inorder(root->left);
        result.push_back(root->val);
        inorder(root->right);     

}

 

其他顺序的遍历只需调换顺序即可。

 

2.迭代实现 

先根遍历(先序遍历)

例如下图中左边的单元,在先根遍历中,打印1,然后进入以2为根节点的下一个单元,倘若2为NULL,那么便进入3为根节点的下一个单元。

根节点→左子节点→右子节点,1,2,4,7,3,5,8,6

思路:迭代实现最重要的就是对路径的保存与回溯,如果不考虑上述内容,单单对每一次的迭代步骤进行实现,然后一路向下。

先根遍历实现的代码为:

 

If(cur!= NULL)  cout << cur->val;  
If(cur->left != NUll)cur=cur->left
Else cur = cur->right;

加入对路径的记忆,将1到2的路径记为第一路径,将1到3的路径记为第二路径。将路径的终点按照第一路径在上,第二路径在下的顺序压入栈中。

 

加入对路径的记忆和提取

 

cur = s.top();  s.pop(); //从堆栈中提取路径
cout << cur->val;     //打印,打印后的路径不用记忆
if(cur->right != NULL) s.push(cur->right);  
if(cur->left != NULL) s.push(cur->left);               //记忆路径用于下一步的迭代

完整代码

 

 

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


中根遍历(中序遍历)

 

顾名思义,中根遍历的根位于结果序列的中间

左子节点→根节点→右子节点,4,7,2,1,3,5,8,6

 

以下图为例,在中根遍历中,直接进入以2为根节点的单元,若2为空,打印1,进入以3为根节点的单元。                 

先根遍历的基本逻辑实现为:

 

If(cur!= nullptr) cur = cur->left
Else cout << cur; cur = cur->right;

 

加入对于路径的记忆和提取,只需要在进入左子节点之前记录根节点即可。

 

If(cur != nullptr) {
    S.push_back(cur);
    cur = cur->left;
}else
{
    cur = s.top();
    s.pop();
    result.push_back(cur->val);
    cur = cur->right;
}

完整代码为

 

 

vector inorderTraversal(TreeNode* root) {
        vector result;
        stack s;
        const TreeNode *cur = root;
        while(!s.empty() || cur != nullptr){
            if(cur!= nullptr)
            {
                s.push(cur);
                cur = cur->left;
            }else
            {
                cur = s.top();
                s.pop();
                result.push_back(cur->val);
                cur = cur->right;
            }
        }
        return result;
    }


后根遍历(后序遍历)

 

左子节点→右子节点→根节点

N、7、4、N、2、5、8、N、6、3、1

后根遍历和先根遍历的顺序是完全相反的,所以可以依据先根遍历的算法,得到结果后,再将结果反转过来即可。另外一种方法,太复杂,思路上屡不清,算了。

 

vector postorderTraversal(TreeNode* root) {
    vector v;
    if (!root) return v;
    stack s;
    s.push(root);
    TreeNode *p = NULL;
    while(!s.empty()) {
        p = s.top();
        s.pop();
        v.insert(v.begin(), p->val);
        if (p->left) s.push(p->left);
        if (p->right) s.push(p->right);
    }
    return v;
    }

 

 

 

 

 

你可能感兴趣的:(C/C++)