二叉树的遍历:先序,中序,后序,递归,非递归,层次遍历
2017-04-24 19:48
381 查看
二叉树遍历的递归写法:
#include <iostream> #include <vector> #include <algorithm> #include <stack> using namespace std; struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x):val(x), left(NULL), right(NULL) {} }; // 先序遍历 void preOrder(TreeNode* root) { if(root == NULL) return; cout << root->val << " "; preOrder(root->left); preOrder(root->right); } // 中序遍历 void inOrder(TreeNode* root) { if(root == NULL) return; inOrder(root->left); cout << root->val << " "; inOrder(root->right); } // 后序遍历 void lastOrder(TreeNode* root) { if(root == NULL) return; lastOrder(root->left); lastOrder(root->right); cout << root->val << " "; }
非递归写法:
先序遍历题目链接
vector<int> preorderTraversal(TreeNode* root) { vector<int> res; stack<TreeNode*> temp; if(root == NULL) return res; temp.push(root); while(!temp.empty()) { TreeNode* pos = temp.top(); temp.pop(); res.push_back(pos->val); if(pos->right != NULL) temp.push(pos->right); if(pos->left != NULL) temp.push(pos->left); } return res; }
中序遍历
题目链接
// 只有当左子树已经访问完后,才能访问根节点 /* 对于任一节点 P 1) 若其左孩子不为空,则将 P 入栈并将 P 的左孩子置为当前 P , 然后对当前 P 再进行相同的处理; 2) 若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶节点, 然后将当前 P 置为栈顶节点的右孩子; 3) 直到 P 为 NULL 并且栈为空则遍历结束; */ vector<int> inOrderTraversal(TreeNode* root){ vector<int> res; stack<TreeNode*> temp; if(root == NULL) return res; TreeNode* pos = root; while(!temp.empty() || pos != NULL) { if(pos != NULL){ // push 左子树入栈 temp.push(pos); pos = pos->left; } else { pos = temp.top(); temp.pop(); res.push_back(pos->val); pos = pos->right; } } return res; }
后序遍历
题目链接
// 先入栈根,然后是右子树,最后左子树 // 要求最后访问根节点, 即访问该根节点时必须访问完左子树和右子树, // 我们只需要保证访问某一节点时,该节点的右子树已经被访问, 否则需要 // 将该节点重新压入栈。 /* 对于任一结点 P, 将其入栈, 然后沿其左子树一直往下搜索, 直到搜索到没有左孩子的结点, 此时该结点出现在栈顶,但是此时不能将其出栈并访问,因为其右孩子还没有被访问。 所以接下来按照相同的规则对其右子树进行相同的处理,当访问完其右孩子时,该结点又出现在 栈顶,此时可以将其出栈并访问。 这样就保证了正确的访问顺序。 可以看出,在这个过程中, 每个结点都两次出现在栈顶,并且只有第二次出现在栈顶时,才能访问它。 */ vector<int> postorderTraversal(TreeNode* root) { vector<int> res; stack<TreeNode*> tmp; if(root == NULL) return res; TreeNode* pos = root; // 记录正在访问的结点 TreeNode* pre = NULL; // 记录前一个访问的结点 do { while(pos != NULL) // 把左子树结点都压进栈 { tmp.push(pos); pos = pos->left; } pre = NULL; // 左结点压完后,初始化前一个访问结点为 NULL while(!tmp.empty()) { pos = tmp.top(); tmp.pop(); if(pos->right == pre) // 右孩子已经被访问 { res.push_back(pos->val); // 右孩子已经被访问,可以访问该结点 pre = pos; // 记录刚刚访问的结点 } else { tmp.push(pos); // 第一次访问该结点,再次放入栈中 pos = pos->right; break; } } } while(!tmp.empty()); return res; }
题目链接
/* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { } };*/ class Solution { public: vector<int> PrintFromTopToBottom(TreeNode* root) { vector<int> res; queue<TreeNode*> tmp; if(root == NULL) return res; TreeNode* pos = root; tmp.push(pos); while(!tmp.empty()) { pos = tmp.front(); tmp.pop(); res.push_back(pos->val); if(pos->left != NULL) tmp.push(pos->left); if(pos->right != NULL) tmp.push(pos->right); } return res; } };
题目链接
方法一:(思路) 在普通层次遍历的基础上,用 NULL 分隔各层。
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: vector<vector<int>> levelOrder(TreeNode* root) { vector<vector<int> > res; vector<int> level; queue<TreeNode*> tmp; if(root == NULL) return res; TreeNode* pos = root; tmp.push(pos); tmp.push(NULL); // 以 NULL 作为每层之间的分隔板 while(!tmp.empty()) { pos = tmp.front(); tmp.pop(); if(pos == NULL) { res.push_back(level); level.resize(0); if(tmp.size() > 0) // 注意当队列为空时不能再插入 NULL, 不然会无限循环。 tmp.push(NULL); // 当前层的所有子节点(下一层)都已加入队列,插入 NULL 进行分隔 } else { level.push_back(pos->val); if(pos->left != NULL) tmp.push(pos->left); if(pos->right != NULL) tmp.push(pos->right); } } return res; } };
方法二:(思路) 先序遍历, 全局数组记录各层结点的值。
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: vector<vector<int>> levelOrder(TreeNode* root) { if(root == NULL) return res; buildLevels(root, 0); return res; } private: vector<vector<int> > res; void buildLevels(TreeNode* pos, int depth) // 先序遍历 { if(pos == NULL) return; if(res.size() == depth) res.push_back(vector<int>()); // 每到一个新层,初始化这一层 res[depth].push_back(pos->val); buildLevels(pos->left, depth+1); buildLevels(pos->right, depth+1); } };
方法三: 上层完全出队后(此时下层完全入队),记录一下队列的大小。
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: vector<vector<int>> levelOrder(TreeNode* root) { vector<vector<int> > res; if(root == NULL) return res; TreeNode* pos = root; queue<TreeNode*> que; que.push(pos); while(!que.empty()) { int sz = que.size(); vector<int> temp; while(sz--) { pos = que.front(); que.pop(); temp.push_back(pos->val); if(pos->left != NULL) que.push(pos->left); if(pos->right != NULL) que.push(pos->right); } res.push_back(temp); } return res; } };
小进阶: 之字型打印二叉树
题目连接
// 方法一: 使用 reverse()
/* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { } }; */ class Solution { public: vector<vector<int> > Print(TreeNode* pRoot) { vector<vector<int> > res; if(pRoot == NULL) return res; vector<int> level; TreeNode* pos = pRoot; queue<TreeNode*> tmp; tmp.push(pos); tmp.push(NULL); // 以 NULL 作为隔板 bool flag = true; while (!tmp.empty()) { pos = tmp.front(); tmp.pop(); if(pos == NULL) { if(flag) res.push_back(level); else { reverse(level.begin(), level.end()); res.push_back(level); } level.resize(0); if(tmp.size() > 0) // 注意: 当 tmp为空时,不要再插入 NULL. 不然无限循环 tmp.push(NULL); flag = !flag; } else { level.push_back(pos->val); if(pos->left != NULL) tmp.push(pos->left); if(pos->right != NULL) tmp.push(pos->right); } } return res; } };
// 方法二: 祭出利器
deque
/* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { } }; */ class Solution { public: vector<vector<int> > Print(TreeNode* pRoot) { vector<vector<int> > res; if(pRoot == NULL) return res; deque<TreeNode*> deq; TreeNode* pos = pRoot; deq.push_back(pos); bool flag = true; while(!deq.empty()) { flag = !flag; int sz = deq.size(); vector<int> temp; while(sz--) { if(flag) // pop_front, push_back, right then left { pos = deq.front(); deq.pop_front(); temp.push_back(pos->val); if(pos->right != NULL) deq.push_back(pos->right); if(pos->left != NULL) deq.push_back(pos->left); } else // pop_back, push_front, left then right { pos = deq.back(); deq.pop_back(); temp.push_back(pos->val); if(pos->left != NULL) deq.push_front(pos->left); if(pos->right != NULL) deq.push_front(pos->right); } } res.push_back(temp); } return res; } };
相关文章推荐
- 二叉树 前序、中序、后序、层次遍历及非递归实现 查找、统计个数、比较、求深度的递归实现
- 二叉树 前序、中序、后序、层次遍历及非递归实现 查找、统计个数、比较、求深度的递归实现
- 用非递归实现二叉树的前序、中序、后序、层次遍历,用递归实现查找、统计个数、比较、求深度
- 数据结构(六)——二叉树 前序、中序、后序、层次遍历及非递归实现 查找、统计个数、比较、求深度的递归实现
- 采用二叉链表结构实现二叉树,并以递归遍历思想实现二叉树的创建、二叉树的遍历(先序、中序、后序和层次遍历)
- 【基础备忘】二叉树 前序、中序、后序、层次遍历及非递归实现 查找、统计个数、比较、求深度的递归实现
- 二叉树 前序、中序、后序、层次遍历及非递归实现 查找、统计个数、比较、求深度的递归实现
- 二叉树2:层次遍历方式及先序、中序、后序(递归与非递归)遍历方式
- (1)建立二叉树的二叉链表。 (2)写出对用二叉链表存储的二叉树进行先序、中序和后序遍历的递归和非递归算法。 (3)写出对用二叉链表存储的二叉树进行层次遍历算法。 (4)求二叉树的所有叶子及结点总数。
- 用java实现二叉树的前序、中序、后序、层次遍历(递归和非递归版)
- 二叉树非递归前序,中序,后序,层次遍历
- 数据结构(六)——二叉树 前序、中序、后序、层次遍历及非递归实现 查找、统计个数、比较、求深度的递归实现
- 数据结构——二叉树 前序、中序、后序、层次遍历及非递归实现 查找、统计个数、比较、求深度的递归实现
- 二叉树的前序、中序、后序、层次遍历的递归与非递归实现
- 二叉树的前中后层次遍历(递归+非递归)、创建树(数组、前序+中序、中序加后序)
- 二叉树的先序、中序、后序、层次遍历的递归和非递归解法
- 数据结构(一)——二叉树 前序、中序、后序、层次遍历及非递归实现 查找、统计个数、比较、求深度的递归实现
- 二叉树的先序,中序,后序,层次的递归及非递归遍历
- 数据结构(六)——二叉树 前序、中序、后序、层次遍历及非递归实现 查找、统计个数、比较、求深度的递归实现
- python实现二叉树的建立以及遍历(递归前序、中序、后序遍历,队栈前序、中序、后序、层次遍历)