您的位置:首页 > 其它

二叉树的遍历:先序,中序,后序,递归,非递归,层次遍历

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;
}

};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐