二叉树的几种遍历的方法(后序遍历的另外一种递归实现还需要思考)

来源:互联网 发布:js获取input文本框宽度 编辑:程序博客网 时间:2024/05/22 04:41
二叉树的几种遍历方法的非递归实现方式都采用的是栈来实现的,需要注意

1、中序遍历:94. Binary Tree Inorder Traversal

Given a binary tree, return the inorder traversal of its nodes' values.
For example:
Given binary tree [1,null,2,3],
   1    \     2    /   3

return [1,3,2].

(1)非递归的方法,时间空间复杂度均为O(n)

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

(2)非递归的方法

(3)递归的方法

vector<int> inorderTraversal(TreeNode* root) {        vector<int> result;        inorderTraversal(root,result);        return result;            }    void inorderTraversal(TreeNode* root,vector<int> &result)    {        if(root)        {            inorderTraversal(root->left,result);            result.push_back(root->val);            inorderTraversal(root->right,result);        }    }

2、先序遍历:144. Binary Tree Preorder Traversal

Given a binary tree, return the preorder traversal of its nodes' values.

For example:
Given binary tree {1,#,2,3},

   1    \     2    /   3

return [1,2,3].


(1)递归的方法

vector<int> preorderTraversal(TreeNode* root) {        vector<int> result;        preorderTraversal(root,result);        return result;    }        void preorderTraversal(TreeNode* root, vector<int> &result) {        if(root)        {            result.push_back(root->val);            preorderTraversal(root->left,result);            preorderTraversal(root->right,result);        }    }

(2)非递归的方法

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

3、后序遍历:145. Binary Tree Postorder Traversal

Given a binary tree, return the postorder traversal of its nodes' values.

For example:
Given binary tree {1,#,2,3},

   1    \     2    /   3

return [3,2,1].

Note: Recursive solution is trivial, could you do it iteratively?

(1)递归的方法

void postorderTraversal(TreeNode* root, vector<int> &result)    {        if(root)        {            postorderTraversal(root->left,result);            postorderTraversal(root->right,result);            result.push_back(root->val);        }    }        vector<int> postorderTraversal(TreeNode* root) {        vector<int> result;        postorderTraversal(root,result);        return result;    }

(2)非递归的方法

代码一、有序前序遍历时NLR,后序遍历时LRN,则可更改前序遍历,将前序遍历改为NRL,然后可将得到的改变后的前序遍历NRL的结果进行逆序就可以

得到后序遍历LRN

vector<int> postorderTraversal(TreeNode* root) {        if(NULL == root)            return vector<int>();                stack<TreeNode*> sta;        sta.push(root);        vector<int> result;        while(!sta.empty())        {            TreeNode* temp = sta.top();            result.push_back(temp->val);//将当前的节点压进栈,并打印            sta.pop();            if(temp->left != NULL)//将当前节点的左孩子压进栈                sta.push(temp->left);            if(temp->right != NULL)//将当前节点的右孩子压进栈                sta.push(temp->right);           }        reverse(result.begin(),result.end());//倒置即可得到最后的结果        return result;    }

代码二、

前序后序中序遍历都会用到栈这个结构,这也是由树这种数据结构的特点决定的。比较特殊的是,后序遍历的顺序是"左子树->右子树->根",

它要求左子树和右子树都在根之前输出。根据这个特点,可以这样来进行,每次记录一个pre和cur,cur表示当前节点,pre表示上次输出

节点(是上次输出的节点,不是上次访问的节点),如果pre正好是cur的左子树或者右子树,那么就可以输出cur,否则,说明还有cur的左子树

或者右子树等待输出,也就是还没到cur输出的时候。这是第一个可以让cur输出的条件。另外可以可以让cur输出的条件是,cur是叶子节点。

vector<int> postorderTraversal(TreeNode* root) {        if(NULL == root)            return vector<int>();                stack<TreeNode*> sta;        sta.push(root);        TreeNode* pre = NULL;        vector<int> result;        while(!sta.empty())        {            TreeNode* temp = sta.top();            if((temp->left == NULL && temp->right == NULL)||((pre!=NULL)&&(pre==temp->left||pre==temp->right)))            {                result.push_back(temp->val);                sta.pop();                pre = temp;//注意这里,pre仅仅在输出了cur的时候下才更新。            }            else            {                if(temp->right != NULL)                    sta.push(temp->right);                if(temp->left != NULL)                    sta.push(temp->left);            }                    }                return result;    }



1 0