题记
二叉树的递归遍历比较简单,这里就不说了。二叉树非递归的实现要依赖栈,其中,后序遍历的非递归实现稍微复杂些。这里总结下,便于理解。
好了,不多说了,直接上代码,思路都在注释里。
代码部分:
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 30
typedef struct BSTreeNode{
int m_value;
struct BSTreeNode *m_pLeft;
struct BSTreeNode *m_pRight;
}BSTreeNode;
//先得写个简单的int栈
typedef struct stack{
BSTreeNode* data[MAXSIZE];
int top;
}Stack;
//-------- 栈的各种操作--------------------//
int isEmpty(Stack *s){
if(s->top == 0){
return 1;
}else{
return 0;
}
}
int push(Stack *s, BSTreeNode *node){
if(s->top>=MAXSIZE){
printf("error:栈已满\n");
return -1;
}
s->data[s->top++] = node;
return 1;
}
BSTreeNode * pop(Stack *s){
if(s->top == 0){
printf("error:栈内没有元素\n");
return NULL;
}
return s->data[--(s->top)];
}
//------- 树的各种操作 --------------------------//
//生成二叉查找树
BSTreeNode *insert(BSTreeNode *tree,BSTreeNode *n){
if(tree == NULL){
tree = n;
}else if(n->m_value < tree->m_value){
tree->m_pLeft = insert(tree->m_pLeft,n);
}else{
tree->m_pRight = insert(tree->m_pRight,n);
}
return tree;
}
//生成测试的二叉查找树
BSTreeNode * create(){
int data[]={10,6,14,4,8,12,16};
int i;
BSTreeNode * tree=NULL;
for(i=0;i<sizeof(data)/sizeof(int);i++){
BSTreeNode *fresh = (BSTreeNode*)malloc(sizeof(BSTreeNode));
fresh->m_value = data[i];
fresh->m_pLeft = fresh->m_pRight = NULL;
tree = insert(tree,fresh);
}
return tree;
}
void destroy(BSTreeNode *cnode){
if(cnode!=NULL){
destroy(cnode->m_pLeft);
destroy(cnode->m_pRight);
free(cnode);
}
}
//Description:非递归前序遍历
//Algorithm:
//沿着左指针访问沿途经过的根节点,同时将右指针进栈,以便在递归访
//问左子树完成后能得到右子树的根节点的地址,如此重复进行,直到栈空。
void preOrderTree(BSTreeNode *cnode){
Stack s;
s.top=0;
while( cnode || !isEmpty(&s)){
if(cnode){
printf("%d,",cnode->m_value);//输出节点
if(cnode->m_pRight){
push(&s,cnode->m_pRight);//压入右子树节点
}
cnode = cnode->m_pLeft;
}else{
cnode = pop(&s);
}
}
}
//Description:非递归中序遍历
//Algorithm:
//先沿着左指针走到二叉树中最左下的结点,即左指针为空的结点,将沿
//途经过的根节点,指针进栈。当左指针为空时,从栈中取出根节点访问,然后再跳
//到右子树上。
void inOrderTree(BSTreeNode *cnode){
Stack s;
s.top = 0;//初始化栈
while(cnode || !isEmpty(&s)){
while(cnode){//将沿途的的左孩子压栈
push(&s,cnode);
cnode = cnode->m_pLeft;
}
cnode=pop(&s);
//访问该节点
printf("%d,",cnode->m_value);
//访问右子树
cnode = cnode->m_pRight;
}
}
//Description:非递归的后序遍历
//Algorithm:先沿着左指针走到二叉树中最左下的结点,将沿途经过的根节点指针进
//栈,若右子树为空,则弹栈并访问根节点,否则,跳到右子树上
void postOrderTree(BSTreeNode *cnode){
int flag[20]={0};//用于判断该节点的右子树是否已经被访问过了!
Stack s;
s.top=0;
while(cnode || !isEmpty(&s)){
while(cnode){
push(&s,cnode);
flag[s.top-1]=0;//注意在这里赋初值!而不是在一开始!
cnode = cnode->m_pLeft;
}
cnode = pop(&s);
if(cnode->m_pRight && flag[s.top] ==0){
push(&s,cnode);
flag[s.top-1]=1;//标记该节点的右子树已经被访问了
cnode = cnode->m_pRight;
}else{
printf("%d,",cnode->m_value);
cnode = NULL;//这个地方值得注意!让其递归向上。
}
}
}
int main(){
BSTreeNode *tree = create();
preOrderTree(tree);
printf("\n");
inOrderTree(tree);
printf("\n");
postOrderTree(tree);
printf("\n");
destroy(tree);
return 0;
}
感谢 http://www.cnblogs.com/hicjiajia/archive/2010/08/27/1810055.html 和 数据结构课程 为我写这篇文章提供参考。
如果转载请注明 blog.csdn.net/whuslei
(全文完)