5.4 遍历
5.4.1 递归式遍历(递归:recursion)
- 先序遍历:VLR
- 中序遍历:LVR
- 后序遍历:LRV
- 先序遍历
0001 template <typename T, typename VST> //元素类型、操作器
0002 void travPre_R ( BinNodePosi<T> x, VST& visit ) { //二叉树先序遍历算法(递归版)
0003 if ( !x ) return;
0004 visit ( x->data );
0005 travPre_R ( x->lc, visit );
0006 travPre_R ( x->rc, visit );
0007 }
- 后序遍历
0001 template <typename T, typename VST> //元素类型、操作器
0002 void travPost_R ( BinNodePosi<T> x, VST& visit ) { //二叉树后序遍历算法(递归版)
0003 if ( !x ) return;
0004 travPost_R ( x->lc, visit );
0005 travPost_R ( x->rc, visit );
0006 visit ( x->data );
0007 }
- 中序遍历
0001 template <typename T, typename VST> //元素类型、操作器
0002 void travIn_R ( BinNodePosi<T> x, VST& visit ) { //二叉树中序遍历算法(递归版)
0003 if ( !x ) return;
0004 travIn_R ( x->lc, visit );
0005 visit ( x->data );
0006 travIn_R ( x->rc, visit );
0007 }
5.4.2 迭代版(迭代:iteration)
5.4.3 层次遍历
在所谓广度优先或层次遍历(level - order traversal)中,确定节点访问次序的原因则可概括为“先上后下、先左后右”
有根性和有序性是层次遍历序列得以明确定义的基础。正因为确定了树根,各节点方可拥有深度这一指标,并进而依此排序;有序性则保证孩子有左、右之别,并依次确定同深度节点之间的次序。
- 算法实现:
0001 template <typename T> template <typename VST> //元素类型、操作器
0002 void BinNode<T>::travLevel ( VST& visit ) { //二叉树层次遍历算法
0003 Queue<BinNodePosi<T>> Q; //辅助队列
0004 Q.enqueue ( this ); //根节点入队
0005 while ( !Q.empty() ) { //在队列再次变空之前,反复迭代
0006 BinNodePosi<T> x = Q.dequeue(); visit ( x->data ); //取出队首节点并访问之
0007 if ( HasLChild ( *x ) ) Q.enqueue ( x->lc ); //左孩子入队
0008 if ( HasRChild ( *x ) ) Q.enqueue ( x->rc ); //右孩子入队
0009 }
0010 }
- 实例:
- 完全二叉树:
在层次遍历算法的每一次迭代中,必有一个节点出队(而且不再入队),故累计恰好迭代n次。
定义:若在对某棵二叉树的层次遍历过程中,前⌊n/2⌋次迭代中都有左孩子入队,且前⌈n/2⌉ - 1次迭代中都有右孩子入队,则称之为完全二叉树(complete binary tree)。
一般性宏观拓扑结构特征:叶节点只能出现在最底部的两层,且最底层叶节点均处于次底层叶节点的左侧。
规律: 1. 高度为h的完全二叉树,规模应该介于2h至2h+1 - 1之间;反之,规模为n的完全二叉树,高度h = ⌊log2n⌋ = O(logn) 。
- 叶节点虽不致少于内部节点,但至多多出一个 。
作用:得益于以上特性,完全二叉树可以借助向量结构,实现紧凑存储和高效访问。
- 满二叉树:
定义:完全二叉树的一种特例,所有叶节点同处于最底层(非底层节点均为内部节点)。每一层的节点数都应达到饱和,称其为满二叉树(full binary tree)。
规律:高度为h的满二叉树由2h+1 - 1个节点组成,其中叶节点恰好比内部节点多出一个。
“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 8 天,点击查看活动详情”