参考自:http://blog.csdn.net/fansongy/article/details/6798278/
遍历即将树的所有结点访问且仅访问一次。按照根节点位置的不同分为前序遍历,中序遍历,后序遍历。
前序遍历:根节点->左子树->右子树
中序遍历:左子树->根节点->右子树
后序遍历:左子树->右子树->根节点
例如:求下面树的三种遍历
前序遍历:abdefgc
中序遍历:debgfac
后序遍历:edgfbca
void preorder(bintree t){ if(t){ printf("%c ",t->data); preorder(t->lchild); preorder(t->rchild); } }
非递归的实现
因为当遍历过根节点之后还要回来,所以必须将其存起来。考虑到后进先出的特点,选用栈存储。数量确定,以顺序栈存储。
#define SIZE 100 typedef struct seqstack{ bintree data[SIZE]; int tag[SIZE]; //为后续遍历准备的 int top; //top为数组的下标 }seqstack; void push(seqstack *s,bintree t){ if(s->top == SIZE){ printf("the stack is full\n"); }else{ s->top++; s->data[s->top]=t; } } bintree pop(seqstack *s){ if(s->top == -1){ return NULL; }else{ s->top--; return s->data[s->top+1]; } }
1、前序遍历
2、中序遍历void preorder_dev(bintree t){ seqstack s; s.top = -1; //因为top在这里表示了数组中的位置,所以空为-1 if(!t){ printf("the tree is empty\n"); }else{ while(t || s.stop != -1){ while(t){ //只要结点不为空就应该入栈保存,与其左右结点无关 printf("%c ",t->data); push(&s,t); t= t->lchild; } t=pop(&s); t=t->rchild; } } }
void midorder(bintree t){ seqstack s; s.top = -1; if(!t){ printf("the tree is empty!\n"); }else{ while(t ||s.top != -1){ while(t){ push(&s,t); t= t->lchild; } t=pop(&s); printf("%c ",t->data); t=t->rchild; } } }
3、后序遍历
因为后序遍历最后还要要访问根结点一次,所以要访问根结点两次。采取夹标志位的方法解决这个问题。
这段代码非常纠结,对自己有信心的朋友可以尝试独立写一下。反正我是写了很长时间。逻辑不难,我画了一张逻辑图:
void postorder_dev(bintree t){ seqstack s; s.top = -1; if(!t){ printf("the tree is empty!\n"); }else{ while(t || s.top != -1){ //栈空了的同时t也为空。 while(t){ push(&s,t); s.tag[s.top] = 0; //设置访问标记,0为第一次访问,1为第二次访问 t= t->lchild; } if(s.tag[s.top] == 0){ //第一次访问时,转向同层右结点 t= s.data[s.top]; //左走到底时t是为空的,必须有这步! s.tag[s.top]=1; t=t->rchild; }else { while (s.tag[s.top] == 1){ //找到栈中下一个第一次访问的结点,退出循环时并没有pop所以为其左子结点 t = pop(&s); printf("%c ",t->data); } t = NULL; //必须将t置空。跳过向左走,直接向右走 } } } }
4、层次遍历:即每一层从左向右输出
元素需要储存有先进先出的特性,所以选用队列存储。
#define MAX 1000 typedef struct seqqueue{ bintree data[MAX]; int front; int rear; }seqqueue; void enter(seqqueue *q,bintree t){ if(q->rear == MAX){ printf("the queue is full!\n"); }else{ q->data[q->rear] = t; q->rear++; } } bintree del(seqqueue *q){ if(q->front == q->rear){ return NULL; }else{ q->front++; return q->data[q->front-1]; } }