二叉树遍历1

二叉树遍历01

0x00 二叉树的递归遍历

void preordertraversal(list* p){
	if(p){
		printf("%d",p->data);
		preordertraversal(p->left);
		preordertraversal(p->right);
	}
}
void inordertraversal(list* p){
	if(p){
		preordertraversal(p->left);
		printf("%d",p->data);
		preordertraversal(p->right);
	}
}
void postordertraversal(list* p){
	if(p){
		preordertraversal(p->left);
		preordertraversal(p->right);
		printf("%d",p->data);
	}
}

0x01 非递归遍历(堆栈实现)

递归实现既是使用系统的·函数堆栈实现,只要清楚访问到底是在左子树进堆栈前还是后,就可以自己构堆栈实现。

先序遍历

void preordertraversal(node* head){
	stack* s=createstack(1000);
	node p=head;
	while(p||s->top!=-1){
		while(p){
			printf("(%d)",p->data);
			push(s,p);
			p=p->left;
		}
		p=pop(s);
		p=p->right;
	}
	return ;
}

中序遍历

相对于先序遍历只是简单的改变了访问的顺序,在左子树出堆栈返回时才访问本身,这和递归遍历是一致的!

void inordertraversal(node* head){
	stack* s=createstack(1000);
	node p=head;
	while(p||s->top!=-1){
		while(p){
			push(s,p);
			p=p->left;
		}
		p=pop(s);
		printf("(%d)",p->data);
		p=p->right;
	}
	return ;
}

后序遍历

后续遍历比较麻烦一点,1 什么时候该访问节点,按照递归版本,先访问左节点,当左节点没有时,访问右节点,右节点如果有,指针就指向右节点,又循环这个过程,如果没有,那么久该出栈一个节点,也就是最近的父节点A,访问他。 但是如果循环继续,发现,又会重复的访问这个A的左右节点,所以我们给每个节点加一个flag初始为0,在入栈的时候判断下,如果为0就允许入栈,并改成1,这样左节点就不会重复访问。同样,访问右节点时也判断下,没有右节点或者右节点被访问过都表示该出栈父节点了。

void postordertraversal(node* head){
	stack* s=createstack(1000);
	node p=head;
	while(p||s->top!=-1){
		while(p){
			if(!p->flag){
				p->flag=1;
				push(s,p);
				p=p->left;
			}else{
				break;
			}	
		}
		if(s->top!=-1){
			p=s->data[s->top];
		}	
		p=p->right;
        if(!p||p->flag){
			if(s->top!=-1){
			p=pop(s);
			printf("(%d) ",p->data);	
			}else{
				break;
			}
			
		}
	}
	return;
} 

以上代码均测试通过