二叉树的遍历分为以下三种:
1、先序遍历:遍历顺序为【根左右】
2、中序遍历:遍历顺序为【左根右】
2、中序遍历:遍历顺序为【左右根】
所谓的先序遍历中的【根左右】是什么意思呢?
即:(1)访问根节点;
(2)先序遍历左子树;
(3)先序遍历右子树。
举个例子,看下图
这个树的前序遍历:ABDEGHCF |
中序遍历:DBGEHACF |
后序遍历:DGHEBFCA |
层次遍历:ABCDEFGH |
二叉树的递归遍历
- 先序递归遍历算法
首先考虑递归的终止条件: 如果该节点处为空节点,则为空。
然后执行每个子子任务:
1、访问根节点,即输出根节点的值。
2、先序遍历左子树。
3、先序遍历右子树。
代码如下(此为leetcode上的算法题):
class Solution {
public:
vector<int>res;
vector<int> inorderTraversal(TreeNode* root)
{
if(root)
{
res.push_back(root->val);
inorderTraversal(root->left);
inorderTraversal(root->right);
}
return res;
}
};
- 中序递归遍历算法
首先考虑递归的终止条件: 如果该节点处为空节点,则为空。
然后执行每个子子任务:
1、中序遍历左子树。
2、输出根节点的值。
3、中序遍历右子树。
class Solution {
public:
vector<int>res;
vector<int> inorderTraversal(TreeNode* root)
{
if(root)
{
inorderTraversal(root->left);
res.push_back(root->val);
inorderTraversal(root->right);
}
return res;
}
};
- 后续递归遍历算法
首先考虑递归的终止条件: 如果该节点处为空节点,则为空。
然后执行每个子子任务:
1、中序遍历左子树。
2、中序遍历右子树。
3、输出根节点的值。
class Solution {
public:
vector<int> res;
vector<int> postorderTraversal(TreeNode* root)
{
if(root!=NULL)
{
postorderTraversal(root->left);
postorderTraversal(root->right);
res.push(root->val);
}
return res;
}
};
二叉树的非递归遍历
非递归进行二叉树的遍历时,我们需要用到 栈这种 后进先出的存储结构,通过迭代进行遍历。
1、前序遍历
首先我们应该创建一个Stack用来存放节点,首先我们想要打印根节点的数据,此时Stack里面的内容为空,所以我们优先将头结点加入Stack,然后打印。
之后我们应该先打印左子树,然后右子树。所以先加入Stack的就是右子树,然后左子树。
此时你能得到的流程如下:
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root)
{
vector<int> res;
TreeNode* p=root;
stack<TreeNode*> S;
while(p!=NULL||!S.empty())
{
while(p!=NULL)
{
res.push_back(p->val);
S.push(p);
p=p->left;
}
if(!S.empty)
{
p=S.top();
s.pop();
p=p->right;
}
}
return res;
};
第二种方法:
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root)
{
vector<int> res;
stack<TreeNode *>S;
if(root==NULL)
return res;
S.push(root);
while(!S.empty())
{
TreeNode *p=S.top();
S.pop();
res.push_back(p->val);
if(p->right!=NULL) S.push(p=p->right);
if(p->left!=NULL) S.push(p=p->left);
}
return res;
}
};
2、中序遍历
代码如下
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root)
{
vector<int> res;
TreeNode* p=root;
stack<TreeNode*> S;
while(p!=NULL||!S.empty())
{
while(p!=NULL)
{
S.push(p);
p=p->left;
}
if(!S.empty())
{
p=S.top();
S.pop();
res.push_back(p->val);
p=p->right;
}
}
return res;
}
};
3、后序遍历
代码如下
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root)
{
vector<int> res;
if(root==null) return res;
TreeNode* p=root;
stack<TreeNode*> S1;
stack<TreeNode*> S2;
S1.push(p);
while(!S1.empty())
{
p=S1.top();
S1.pop();
S2.push(p);
if(p->left!=null) S1.push(p->left);
if(p->right!=null) S2.push(p->right);
}
while(!S2.empty())
{
p=S2.top();
S2.pop();
res.push_back(p->val);
}
return res;
}
};
具体的代码解释,改天在写。