[问题描述]:如何周游一棵二叉树。
二叉树的周游分为深度优先周游(DFS)和广度优先周游(BFS)。
对于深度优先周游,左中右的排列共有3!=6种,但是先访问右子树后访问左子树不符合人们的习惯,所以就剩下三种:先序(中左右),中序(左中右),后序(左右中)。每种周游都有递归和非递归实现,非递归是利用栈实现的。
后序周游的非递归版本稍微复杂点,因为访问完某个子树之后,还要判断是从哪个子树返回的。如果是左子树,还要访问完右子树,才能访问自己。
广度周游按照层数访问,先访问处于同样深度的节点,然后再访问下一层。广度周游借助队列实现。
#ifndef BITREE
#define BITREE
#include <stack>
#include <queue>
using std::stack;
using std::queue;
struct Node{
char data;
Node *left, *right;
Node(char val = ' ', Node *l = NULL, Node *r = NULL) : data(val), left(l), right(r){}
};
typedef Node* BiTree;
// 先序周游(递归)
void PreOrder(Node* root){
if(root != NULL){
printf("%c", root->data);
PreOrder(root->left);
PreOrder(root->right);
}
}
// 先序周游(非递归)
void PreOrder_NoRecursion(Node* root){
stack<Node*> Stack;
Node *p = root;
while(!Stack.empty() || p){
if(p){
printf("%c", p->data);
Stack.push(p);
p = p->left;
}
else{
p = Stack.top();
Stack.pop();
p = p->right;
}
}
}
// 中序周游(递归)
void InOrder(Node *root){
if(root){
InOrder(root->left);
printf("%c", root->data);
InOrder(root->right);
}
}
// 中序周游(非递归)
void InOrder_NoRecursion(Node *root){
stack<Node*> Stack;
Node *p = root;
while(!Stack.empty() || p){
if(p){
Stack.push(p);
p = p->left;
}
else{
p = Stack.top();
printf("%c", p->data);
Stack.pop();
p = p->right;
}
}
}
// 后续周游(递归)
void PostOrder(Node *root){
if(root){
PostOrder(root->left);
PostOrder(root->right);
printf("%c", root->data);
}
}
// 后续周游(非递归)
void PostOrder_NoRecursive(Node *root){
stack<Node*> Stack;
Node *p = root;
Node *q = NULL;
while(p || !Stack.empty()){
while(p){
Stack.push(p);
p = p->left;
}
p = Stack.top();
if(p->right == NULL || p->right == q){ //从右子树返回
printf("%c", p->data);
Stack.pop();
q = p;
p = NULL;
}
else{
p = p->right; //从左子树返回,访问右子树
}
}
}
// 广度优先周游
void LevelOrder(Node *root){
queue<Node*> Queue;
if(root)
Queue.push(root);
Node *p = NULL;
while(!Queue.empty()){
p = Queue.front();
Queue.pop();
printf("%c", p->data);
if(p->left)
Queue.push(p->left);
if(p->right)
Queue.push(p->right);
}
}
Node* Find(Node *root, char val){
if(!root){
return NULL;
}
else{
if(root->data == val)
return root;
else{
Node *temp = Find(root->left, val);
if(temp == NULL){
temp = Find(root->right, val);
}
return temp;
}
}
}
void DestroyTree(Node *root){
if(root){
DestroyTree(root->left);
DestroyTree(root->right);
delete root;
}
}
#endif