数据结构之---树(三)---四种树的遍历

来源:互联网 发布:网络印刷平台20强 编辑:程序博客网 时间:2024/06/04 11:39

树的遍历常见的有先序,中序,后序,层序遍历,它们各有用处。这里以二叉树为例。

给出树的结构为:

typedef struct node *ptrnode;typedef struct node *tree;struct node{int element;ptrnode lchild;ptrnode rchild;};

先序遍历常常用于打印文件输出等,特别是文件系统中,因为它可以利用节点深度信息,有层次的打印出一个文件系统的结构出来。

void preorder_travel(tree T){if(T!=NULL){visit(T);preoder_travel(T->lchild);preoder_travel(T->rchild);}}
而中序遍历在二叉查找树中可以很方便的解决关键字排序输出的问题,注意到的是利用二叉查找树可以将一个输入序列,在时间复杂度为O(NlogN)上建立成为一棵二叉查找树,然后打印输出将花费O(N)。

/*中序遍历,在二叉查找树中,这种遍历能够很容易解决关键字排序输出的问题*/void midorder_travel(tree T){if(T!=NULL){midorder_travel(T->lchild);visit(T);midorder_travel(T->rchild);}}
后序遍历则常常用于计算数值中,比如我们想计算树的高度,其一个普适的算法描述为:

void lastorder_travel(tree T){if(T!=NULL){lastoeder_travel(T->lchild);lastorder_travel(T->rchild);visit(T);}}
如果我们用于计算一棵树的高度,则有:

/*计算高度*/int height(tree T){if(T==NULL)return -1;elsereturn 1+max(height(T->lchild),height(T->rchild));}
注意到在这些算法中我们都要小心的处理空的情况,这种小心在递归中尤其重要。

最后便是层序遍历了,与前三种遍历不同的是,它并不能利用前面那种递归思想了,因为递归中栈的使用必然会使得这种同一层的打印输出变得不可能。一个显而易见的思路是使用队列,第一次的时候将首节点入列,然后我们利用一个循环,当队列不为空时,我们就出队进行操作,并把这个出队元素的所有孩子都入队。根据队列FIFO的特性,便能够实现层序遍历了。

*层序遍历*//*与前三种不同,栈已经不适合了,应该采用队列,当然就不是递归了*/void level_travel(tree T,queue Q){Q.Enqueue(T);while(!is_empty(Q)){ptrnode temp;temp=Q.Dequeue();visit(temp);if(temp->lchild!=NULL)Q.Enqueue(temp->lchild);if(temp->rchild!=NULL)Q.Enqueue(temp->rchild);}}
注意到前面几个操作的时间复杂度都是O(N),因为我们对每个节点都进行了一次访问,而每次访问的操作时间都是常数时间,所以时间复杂度便是O(N)了。这个需要特别注意,很多时候我们一提到二叉树便会不假思索的哦O(logN),这是不正确的,具体问题具体分析,不要一概而论。给自己提个醒。







0 0