记录一下二叉树的先序、中序、后序非递归遍历算法
因为递归算法很简单,所以不再罗列
节点的结构体定义为:
typedef struct BTNode{
int val;
struct BTNode* left;
struct BTNode* right;
}BTNode;
访问节点的函数:
void visit(BTNode* p){
printf("%d\n", p->val);
}
1.先序非递归
void pre_order(BTNode* root){
if(root == NULL)
return;
BTNode* stack[MAX_SIZE];
int top = -1;
BTNode* ptr = root;
while(ptr != NULL || top > -1){
while(ptr != NULL){
visit(ptr);
stack[++top] = ptr;
ptr = ptr->left;
}
if(top > -1){
ptr = stack[top--];
ptr = ptr->right;
}
}
}
2.中序非递归算法
void in_order(BTNode* root){
if(root == NULL)
return;
BTNode* stack[MAX_SIZE];
int top = -1;
BTNode* ptr = root;
while(ptr != NULL || top > -1){
while(ptr != NULL){
stack[++top] = ptr;
ptr = ptr->left;
}
if(top > -1){
ptr = stack[top--];
visit(ptr);
ptr = ptr->right;
}
}
}
后序非递归算法相对前两种复杂一点,关键是想办法保存父节点并确定何时该访问父节点(即左右子树都访问完后才能访问),所以可以设置一个前驱指针pre,永远指向当前节点cur的父节点,并由pre->right == cur这个条件来确定访问父节点的时机
3.后序非递归算法
void post_order(BTNode* root){
if(root == NULL)
return;
BTNode* stack[MAX_SIZE];
int top = -1;
BTNode* cur = root;
BTNode* pre = NULL; //当cur为根节点时,其父节点为NULL
while(cur != NULL || top > -1){
while(cur != NULL){
stack[++top] = cur;
pre = cur;
cur = cur->left;
}
while(pre != NULL && pre->right == cur){//表示此时pre的左右子树已遍历结束
visit(pre);
cur = pre;
top--;
if(top > -1)
pre = stack[top];
else
pre = NULL; //栈空,此时遍历完二叉树,pre置为NULL
}
if(pre != NULL)
cur = pre->right; //表示此时cur是pre左孩子,要将其变为pre的右孩子
else
cur = NULL;
}
}
这就是三种非递归遍历算法,其中先序和中序非递归算法较为常见。后序非递归网上有很多种方法,但此种方法是从先序和中序的算法思路受启发变形而来,更容易理解。以上代码均已经通过测试。