二叉树的遍历分为前序遍历、中序遍历和后序遍历三种,其遍历顺序分别为根-左-右,左-根-右和左-右-根。
二叉树的数据结果如下:
struct TreeNode
{
TreeNode *left;
TreeNode *right;
int val;
};
对于递归遍历,三种遍历顺序有一定的相似性,所以比较简单:
//前序遍历
void preorder(TreeNode *root, vector<int> &path)
{
if(root != NULL)
{
path.push_back(root->val);
preorder(root->left, path);
preorder(root->right, path);
}
}
//中序遍历
void Inorder(TreeNode *root, vector<int> &path)
{
if(root != NULL)
{
Inorder(root->left, path);
path.push_back(root->val);
Inorder(root->right, path);
}
}
//后续遍历
void postorder(TreeNode *root, vector<int> &path)
{
if(root != NULL)
{
postorder(root->left, path);
postorder(root->right, path);
path.push_back(root->val);
}
}
对于非递归遍历,只能借助栈来完成,就稍微有点复杂了。
//非递归前序遍历
void preorderTraversal(TreeNode *root, vector<int> &path)
{
stack<TreeNode *> s;
TreeNode *p = root;
while(p||!s.empty())
{
while(p)//顺序遍历根节点,直到二叉树左子树为空
{
path.push_back(p->val);
s.push(p);
p=p->left;
}
if(!s.empty())
{
p=s.top();//获得栈顶节点,从而开始遍历右子树
s.pop();
p=p->right;
}
}
}
//非递归中序遍历
void inorderTraversal(TreeNode *root, vector<int> &path)
{
stack<TreeNode *> s;
TreeNode *p = root;
while(p||!s.empty())
{
while(p)
{
s.push(p);
p=p->left;
}
if(!s.empty())
{
p=s.top();//获得栈顶结点
path.push_back(p->val);
s.pop();
p=p->right;
}
}
}
对于非递归后续遍历,其思路如下:
对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,此时该结点出现在栈顶,但是此时不能将其出栈并访问,因此其右孩子还未被访问。所以接下来按照相同的规则对其右子树进行相同的处理,当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。这样就保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现在栈顶,只有在第二次出现在栈顶时,才能访问它。因此需要多设置一个变量标识该结点是否是第一次出现在栈顶。
//非递归后续遍历
struct TempNode
{
TreeNode *btnode;
bool isFirst;
};
void postorderTraversal(TreeNode *root, vector<int> &path)
{
stack<TempNode *> s;
TreeNode *p = root;
TempNode *temp;
while(p != NULL || !s.empty())
{
while(p != NULL) //沿左子树一直往下搜索,直至出现没有左子树的结点
{
TempNode *tempNode = new TempNode;
tempNode->btnode = p;
tempNode->isFirst = true;
s.push(tempNode);
p = p->left;
}
if(!s.empty())
{
temp = s.top();
s.pop();
if(temp->isFirst == true) //表示是第一次出现在栈顶
{
temp->isFirst = false;
s.push(temp);
p = temp->btnode->right;
}
else //第二次出现在栈顶
{
path.push_back(temp->btnode->val);
p = NULL;
}
}
}
}