废话不多说,分别给出二叉树的先序、中序和后序遍历的递归和非递归算法。
先序遍历-递归算法:
class Node {
public:
int value;
Node *left;
Node *right;
};
class Visit {
public:
void operator() (Node * node) const {
cout<<" "<<node->value<<" "<<endl;
}
};
void preOrderVisitTree(Node* root, Visit &visit) {
if (!root) {
return ;
}
visit(root);
preOrderVisitTree(root->left,visit);
preOrderVisitTree(root->right,visit);
return ;
}
先序遍历-非递归算法:
思想:用一个辅助栈记录,比较简单这里就不废话了。
No code say what?
void preOrderVisitTreeEx(Node *root, Visit &visit) {
if (!root) {
return ;
}
stack<Node*> S;
Node *current = root;
while (!S.empty()) {
if (current->right) {
S.push(current->left);
}
if (current->left) {
S.push(current->right);
}
visit(current);
current = S.top();
S.pop();
}
return;
}
中序遍历-递归算法:
void inOrderVisitTree(Node* root, Visit &visit) {
if (!root) {
return ;
}
preOrderVisitTree(root->left,visit);
visit(root);
preOrderVisitTree(root->right,visit);
return ;
}
中序遍历-非递归算法:
思想:一直把树的左边界压入栈,当压无可压时,弹出一个节点,然后访问其右子树。再一直压树的左边界…
No code say what?
void inOrderVisitTreeEx(Node *root, Visit & visit) {
if (!root) {
return ;
}
stack<Node*> S;
Node *current = root;
while (!S.empty() && !current) {
if (current->left) {
S.push(current->left);
current = current->left;
continue;
}
current = S.top();
S.pop();
visit(current);
current = current->right;
}
return ;
}
后序遍历-递归算法:
void posOrderVisitTree(Node* root, Visit &visit) {
if (!root) {
return ;
}
preOrderVisitTree(root->left,visit);
preOrderVisitTree(root->right,visit);
visit(root);
return ;
}
后序遍历-非递归法
思想:后序遍历非递归算法稍微复杂点,下面给出了两种方法,这里说几句。
methold1:把后序顺序的节点序导入到一个栈中,然后依次遍历这个栈。有两个栈就很容易搞定这个事,假设最后待遍历的栈为Stack2,另一个栈为Stack1,首先入栈root到stack1,stack1弹出节点A,节点A并压入stack2,把A的左右儿子压入stack1,以此循环一直到stack1空为止。此时以此弹出stack2就可得到树的后序遍历序列。
No code say what?
void posOrderVisitTreeEx(Node* root, Visit &visit) {
if (!root) {
return ;
}
stack<Node*> S1;
stack<Node*> S2;
Node *current = NULL;
S1.push(root);
while (!S1.empty() &¤t) {
current = S1.top();
S1.pop();
S2.push(current);
if (current->left) {
S1.push(current->left);
}
if (current->right) {
S1.push(current->right);
}
}
while (!S2.empty()) {
visit(S2.top());
S2.pop();
}
return ;
}
methold2:
不用两个栈,用一个栈,这个思路比较绕。
1.首先把头节点入栈;
2.然后获得当前栈顶元素(不弹出);
3.判断栈顶元素左子树是否为空,
若不为空,且其左右子树都未访问过,就把此节点左子树头节点入栈;
4.判断栈顶元素右子树是否为空,
若不为空,且其右子树未被访问过,就把此节点的右子树头节点入栈。
No code say what?
void posOrderVisitTreeExt(Node* root, Visit &visit) {
if (!root) {
return ;
}
stack<Node*> S;
Node *h = NULL;
Node *c = NULL;
S.push(root);
while (!S.empty()) {
c = S.top();
if (!c->left && c->left != h && c->right != h) {
S.push(c->left);
} else if (!c->right && c->right != h) {
S.push(c->right);
} else {
visit(h);
h = c;
}
}
return ;
}