在实际应用中,二叉树的遍历一般都采用递归形式,简洁、直观。
但在笔试、面试中却很喜欢考察非递归形式的写法,下面将二叉树的非递归遍历实现总结如下:
节点定义:
struct Node{
int val;
Node *left, *right;
};
1)中序遍历
实现I
void InOrderTraverse(Node *root){
stack<Node*> st;
st.push(root);
while(!st.empty()){
while(st.top() != NULL)
st.push(st.top()->left);
st.pop();
if(!st.empty()){
Node *head = st.top();
printf("%d ", head->val);
st.pop();
st.push(head->right);
}
}
printf("\n");
}
实现II:
void InOrderTraverse2(Node *root){
stack<Node*> st;
Node *p = root;
while(p || !st.empty()){
if(p){
st.push(p);
p = p->left;
}
else{
printf("%d ", st.top()->val);
p = st.top()->right;
st.pop();
}
}
printf("\n");
}
两种实现本质是一样的,区别仅在在空指针的判断和存放上。
2)先序遍历
实现I:
void PreOrderTraverse(Node *root){
stack<Node*> st;
Node *p = root;
while(p || !st.empty()){
if(p){
printf("%d ", p->val);
st.push(p);
p = p->left;
}
else{
p = st.top()->right;
st.pop();
}
}
printf("\n");
}
实现II:
void PreOrderTraverse2(Node *root){
stack<Node*> st;
Node *p = root;
while(p || !st.empty()){
if(p == NULL){
p = st.top();
st.pop();
}
printf("%d ", p->val);
if(p->right)
st.push(p->right);
p = p->left;
}
printf("\n");
}
void PostOrderTraverse(Node *root){
stack<Node*> st;
if(root != NULL)
st.push(root);
Node *pre = NULL;
while(!st.empty()){
Node *head = st.top();
if((head->left == NULL && head->right == NULL)
|| (pre != NULL && (pre == head->right || pre == head->left ))){
printf("%d ", head->val);
pre = head;
st.pop();
}
else{
if(head->right != NULL)
st.push(head->right);
if(head->left != NULL)
st.push(head->left);
}
}
printf("\n");
}
后续遍历的实现,参照了了博文“
二叉树的非递归遍历”