今儿来把二叉树的stack based的非递归遍历收个尾
非对归就非递归,干嘛还扯stack based的,很洋气么?
好吧,其实我只是想提前透露一下下一篇博文的内容
一种不用递归,不用栈的二叉树遍历方法(时间和空间复杂度只要O(n)和O(1)哦亲)
And now
Let‘s get down to business
__________________________我是分割线_______________________________________
要用栈实现二叉树的后序遍历,难点在于从栈里退出一个节点的时候不知道这个节点是否已经访问过了
要解决这个问题,我们需要在栈里边多保存一个flag,这个flag用于标记该节点是否已经被访问过了
实际上,对于单个节点分析,这个过程可以被这样概括:
节点入栈,对应的flag标志复位
开始访问节点的左子树
节点的左子树访问结束,节点出栈
此时,节点的flag标志是复位状态
证明此节点的左子树已经被访问过了,但是右子树还有待访问
因此,我们让节点再次入栈,并置对应的flag标志位
接着开始访问节点的右子树
该节点的右子树访问完毕,节点出栈
节点的flag标志是置位状态,代表左右子树均被访问过了
访问节点本身
OK,思路讲解结束,下边看代码
我知道这很痛苦,兄弟,可是大神Linus说过:just read the f**king source code
typedef struct _node
{
char data;
struct _node *l;
struct _node *r;
}node;
typedef struct _record
{
node *data;
int flag;
}record;
typedef struct _stack
{
record *data;
int offset;
}stack;
int push(stack *s, node *d, int flag)
{
record *r = &s->data[s->offset++];
r->data = d;
r->flag = flag;
}
record pop(stack *s)
{
return s->data[--s->offset];
}
int empth(stack *s)
{
return 0 == s->offset;
}
void depth_last_no_rec(node *root)
{
stack *s = malloc(sizeof(stack));
s->data = malloc(1024 * sizeof(record));
s->offset = 0;
record c;
while(root){
push(s, root, 0);
root = root->l;
}
while(!empth(s)){
c = pop(s);
root = c.data;
if(c.flag){
printf("%c ",root->data);
}
else{
push(s, root, 1);
root = root->r;
while(root){
push(s, root, 0);
root = root->l;
}
}
}
}
需要源代码的朋友,请猛击此处