二叉树遍历

二叉树遍历

  依据根节点的访问次序分为先序遍历、中序遍历、后序遍历、层序遍历。中序遍历即以左节点、根节点、右节点的顺序遍历,根节点放在中间,其它方式依此类推。下面介绍三种中序遍历算法。

递归

  递归法简单明了,但是效率较低。下面为中序遍历,前序遍历和后序遍历同理。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */

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

栈方法

  • 前序遍历

vector<int> inorderTraversal(TreeNode* root) {
     vector<int> res;
        vector<TreeNode*> stk;
        TreeNode* cur = root;
        while(cur != NULL || stk.size() != 0){
            if(cur != NULL) {
                res.push_back(cur->val);
                stk.push_back(cur);
                cur = cur->left;
            }
            else {
                cur = stk.back();
                stk.pop_back();
                cur = cur->right;
            }
        }
        return res;
}
  • 中序遍历

vector<int> inorderTraversal(TreeNode* root) {
      vector<int> res;
        vector<TreeNode*> stk;
        TreeNode* cur = root;
        while(cur != NULL || stk.size() != 0){
            if(cur != NULL) {
                stk.push_back(cur);
                cur = cur->left;
            }
            else {
                cur = stk.back();
                res.push_back(cur->val);
                stk.pop_back();
                cur = cur->right;
            }
        }
        return res;
}                        
  • 后续遍历

vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        if(root == NULL) return res;
        stack<TreeNode*> tree;
        while(root != NULL || tree.size() != 0) {
            if(root != NULL) {
                tree.push(root);
                res.insert(res.begin(), root->val); //因为是后续遍历,节点需要从队头插入,并且先遍历右子树,加入的顺序是中-右-左,这样最终的顺序就是左-右-中
                root = root->right;
            }
            else {
                root = tree.top()->left;
                tree.pop();
            }
        }
        return res;
    }

莫里斯遍历

  该方法通过设置根节点作为其前驱节点的右孩子,来构造线索二叉树,这样在遍历完左子树时,遍历前驱结点的右孩子就可以跳转到根节点继续遍历右子树。下面是中序遍历实现,前序遍历通过更改res.push_back()的位置即可,后续遍历可以用上述思想,将前序遍历修改为头部插入,并且先遍历右子树。

vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        TreeNode* pre;
        while(root){
            if(root->left){
                pre = root->left;
                while(pre->right && pre->right != root) pre = pre->right;
                if(pre->right == NULL){  //说明root第一次作为当前根节点出现,其左子树没有遍历过,则为其前驱结点设置线索,进入左子树。
                    pre->right = root;
                    root = root->left;
                    continue;
                }
          //说明root是通过前驱结点->right跳转到的,左子树已经遍历完成,需要删除线索,进入右子树。 pre
->right = NULL; res.push_back(root->val); root = root->right; } else{ res.push_back(root->val); root = root->right; } } return res; }

 

posted @ 2020-02-15 16:05  对影无眠  阅读(166)  评论(0编辑  收藏  举报