三种遍历:先序、中序、后序
先序循环遍历:
// 先序遍历
void preOrderIterator(TreeNode *root){
if (root)
{
stack<TreeNode*> s;
while(root || !s.empty()){ // 只要root不为空
// 一路压栈
while(root){ // r非空
cout << root->_data << " ";
s.push(root);
root = root->_left; // 将r取为r的左节点
}
// 出栈 - 类似于dfs,在s栈空前一直寻找有右节点的,把右节点压栈输出然后继续寻找这个右节点的左节点
root = s.top();
s.pop();
root = root->_right;
}
}
}
中序循环遍历:
// 中序遍历
void midOrderIterator(TreeNode *root){
if (root)
{
stack<TreeNode*> s;
while(root || !s.empty()){ // 只要root不为空
// 一路压栈
while(root){ // r非空
s.push(root);
root = root->_left; // 将r取为r的左节点
}
// 出栈 - 类似于dfs,在s栈空前一直寻找有右节点的,把右节点压栈输出然后继续寻找这个右节点的左节点
root = s.top();
s.pop();
cout << root->_data << " ";
root = root->_right;
}
}
}
后序循环遍历:比较麻烦,使用cur记录当前的节点,使用pre记录上一个被输出的节点
如果满足当前节点没有子节点 或者 上一个输出的节点 |是当前节点的子节点| 即当前节点的子节点| 已经被访问过了,就可以输出当前节点
void postOrderIterator(TreeNode *root){
if (root)
{
stack<TreeNode*> s;
TreeNode* cur; // 当前节点
TreeNode* pre = NULL; // 上一次访问的节点
s.push(root);
while(!s.empty()){
cur = s.top();s.pop(); // 先取出栈顶的节点,得到节点的值
s.push(cur); // 再把节点放回去
// 如果当前节点没有子节点 或者 子节点都已经被访问过了
if ((cur->_left==NULL && cur->_right==NULL) || (pre!=NULL && (pre==cur->_left || pre==cur->_right)))
{
cout << cur->_data << " ";
s.pop();
pre = cur;
}else{
if (cur->_right != NULL) s.push(cur->_right);
if (cur->_left != NULL) s.push(cur->_left);
}
}
}
}
完整代码:
#include <iostream>
#include <stack>
using namespace std;
// 树的三种遍历的循环实现
// 用到了栈,也可以用前面自己写的数据结构
typedef struct _TreeNode
{
int _data;
struct _TreeNode* _left;
struct _TreeNode* _right;
}TreeNode;
// 先序遍历
void preOrderIterator(TreeNode *root){
if (root)
{
stack<TreeNode*> s;
while(root || !s.empty()){ // 只要root不为空
// 一路压栈
while(root){ // r非空
cout << root->_data << " ";
s.push(root);
root = root->_left; // 将r取为r的左节点
}
// 出栈 - 类似于dfs,在s栈空前一直寻找有右节点的,把右节点压栈输出然后继续寻找这个右节点的左节点
root = s.top();
s.pop();
root = root->_right;
}
}
}
// 中序遍历
void midOrderIterator(TreeNode *root){
if (root)
{
stack<TreeNode*> s;
while(root || !s.empty()){ // 只要root不为空
// 一路压栈
while(root){ // r非空
s.push(root);
root = root->_left; // 将r取为r的左节点
}
// 出栈 - 类似于dfs,在s栈空前一直寻找有右节点的,把右节点压栈输出然后继续寻找这个右节点的左节点
root = s.top();
s.pop();
cout << root->_data << " ";
root = root->_right;
}
}
}
// 后序遍历
void postOrderIterator(TreeNode *root){
if (root)
{
stack<TreeNode*> s;
TreeNode* cur; // 当前节点
TreeNode* pre = NULL; // 上一次访问的节点
s.push(root);
while(!s.empty()){
cur = s.top();s.pop(); // 先取出栈顶的节点,得到节点的值
s.push(cur); // 再把节点放回去
// 如果当前节点没有子节点 或者 子节点都已经被访问过了
if ((cur->_left==NULL && cur->_right==NULL) || (pre!=NULL && (pre==cur->_left || pre==cur->_right)))
{
cout << cur->_data << " ";
s.pop();
pre = cur;
}else{
if (cur->_right != NULL) s.push(cur->_right);
if (cur->_left != NULL) s.push(cur->_left);
}
}
}
}
int main(int argc, char const *argv[])
{
TreeNode a, b, c, d, e, f;
// 创建一个指向根节点的指针
TreeNode* root = &a;
a._data = 1;
b._data = 2;
c._data = 3;
d._data = 4;
e._data = 5;
f._data = 6;
a._left = &b;
a._right = &c;
b._left = &d;
b._right = &e;
c._left = NULL;
c._right = &f;
d._left = d._right = NULL;
e._left = e._right = NULL;
f._left = f._right = NULL;
preOrderIterator(root);
cout << endl;
midOrderIterator(root);
cout << endl;
postOrderIterator(root);
cout << endl;
return 0;
}
输出:
1 2 4 5 3 6
4 2 5 1 3 6
4 5 2 6 3 1