1、三、二叉树的定义、性质四、二叉树的顺序存储结构和链式存储结构五、小结作业复习本讲内容并预习下一讲内容课堂情况及课后分析掌握二叉树遍历的三种方法及二叉树的基本操作二叉树的遍历算法中序与后序遍历的非递归算法一、复习二叉树的定义二、遍历二叉树的三种方法三、递归法遍历二叉树四、二叉树的基本操作五、总结理解树与森林的转换,掌握哈夫曼树哈夫曼树树与森林的转换一、导入二、树与森林三、哈夫曼树四、小结习题6前面几章讨论的数据结构都属于线性结构,线性结构的特点是逻辑结构简单,易于进行查找、插入和删除等操作,可用于描述客观世界中具有单一前驱和后继的数据关系。采用非线性结构描述诸如人类社会的族谱、各种社会组织机构以
2、及城市交通、通讯等对应的数据关系会更加明确和便利。所谓非线性结构是指,在该结构中至少存在一个数据元素有两个或两个以上的直接前驱(或直接后继)元素。树形结构就是一种十分重要的非线性结构,本章介绍树形结构的有关概念、存储结构、在各种存储结构上实施的运算与应用。6.1 树的基本概念6.1.1 定义树是n(n0)个结点的有限集合。若n=0,则称为空树;否则,有且仅有一个特定的结点被称为根,当n1时,其余结点被分成m(m0)个互不相交的子集T1,T2,Tm,每个子集又是一棵树。可以看出,树的定义是递归的。图6-1(a)是一棵具有9个结点的树T,即TA,B,C,H,I,结点A为树的根结点,除根结点A之外的
3、其余结点分为两个不相交的集合:T1B,D,E,F,H,I和T2=C,G,T1和T2构成了结点A的两棵子树。例如,子树T1的根结点为B,其余结点又分为三个不相交的集合:T11D,T12E,H,I和T13F。T11、T12和T13构成了子树T1的根结点B的三棵子树。如此可继续向下分为更小的子树,直到每棵子树只有一个根结点为止。从定义和图6-1(a)可以看出,树具有特点:(1)树的根结点没有前驱结点,除根结点之外的所有结点有且只有一个前驱结点。(2)树中所有结点可以有零个或多个后继结点。由此可知,图6-1的(b),(c),(d)都不是树。图6-1 树结构和非树结构示意图结点:数据元素的内容及其指向其
4、子树根的分支统称为结点。结点的度是该结点的子树的个数。树的度是该树中结点的最大度数。树中度为零的结点称为叶结点或终端结点。树中度不为零的结点称为分枝结点或非终端结点。除根结点外的分枝结点统称为内部结点。结点的子树的根称为该结点的孩子;相应地,该结点称为孩子的双亲。如果存在树中的结点序列K1,K2,Kj,使得结点Ki是结点Ki+1(1iLchild);Rchild); 2. 中序遍历递归算法void InOrder(BTree BT) InOrder(BT- Visit(BT); InOrder(BT-3. 后序遍历递归算法void PostOrder(BTree BT)if (BT) Post
5、Order(BT- PostOrder(BT-上述二叉树先序、中序和后序三种遍历算法都是递归算法。然而,并非所有程序设计语言都允许递归;另一方面,递归程序虽然简洁,但可读性一般不好,执行效率也不高。通过对三种遍历方法的实质分析,可得到遍历二叉树的非递归算法,有兴趣的读者可参见有关参考书。6.2.4 二叉树的基本操作1. 输入二叉树的先序序列,构造这棵二叉树为了保证唯一地构造出所希望的二叉树,在键入这棵树的先序序列时,需要在所有空二叉树的位置上填补一个特殊的字符,比如,#。在算法中,需要对每个输入的字符进行判断,如果对应的字符是,则在相应的位置上构造一棵空二叉树;否则,创建一个新结点。整个算法结
6、构以先序遍历递归算法为基础,二叉树中结点之间的指针连接是通过指针参数在递归调用返回时完成的。BTree Pre_Create_BT( ) getch(ch); if (ch=) return NULL; /构造空树 else BT=(BTree)malloc(sizeof(BTLinklist); /构造新结点 BT-data=ch;lchild =Pre_Create_BT( ); /构造左子树rchild =Pre_Create_BT( ); /构造右子树 return BT;2. 计算一棵二叉树的叶子结点数目这个操作可以使用三种遍历顺序中的任何一种,只需将访问操作变成判断该结点是否为叶子
7、结点,如果是叶子结点将累加器加1即可。下面是中序遍历的实现。void Leaf(BTree BT,int *count) if (BT) Leaf(BT-child,&count); /计算左子树的叶子结点个数 if (BT-lchild=NULL&BT-rchild=NULL) (*count)+; Leaf(BT-rchild,& /计算右子树的叶子结点个数3. 交换二叉树的左右子树void change_left_right(BTree BT) change_left_right(BT-lchild); change_left_right(BT-rchild); BT-lchildrch
8、ild;4. 求二叉树的高度使用后序遍历,首先分别求出左右子树的高度,在左右子树较大的高度值加1得出该棵树的高度。int hight(BTree BT)/h1和h2分别是以BT为根的左右子树的高度if (BT=NULL) return 0; else h1=hight(BT- h2=hight(BT-right); return max(h1,h2)+1; 6.3 树 和 森 林6.3.1 树的存储结构 树属非线性结构,其存储方式需反映出树中各结点间的非线性关系。下面介绍三种常用的树的存储结构:双亲表示法,孩子表示法,孩子兄弟表示法。1. 双亲表示法在树中,除根结点没有双亲外,其他每个结点的双
9、亲是唯一确定的。因此,根据树的这一性质,存储树中结点时,可以包含两个信息:结点的值data和该结点的双亲信息parent。借助于每个结点的这两个信息便可唯一地表示任何一棵树。这种表示方法称为双亲表示法。例如:图6-14是图6-1(a)所示树的双亲表示法示意。在C语言中,这种存储形式定义如下:#define MAX_TREE_LINKLIST_SIZE 10typedef struct ChildLinklist int child; /该孩子结点在一维数组中的下标值 struct ChileLinklist *next; /指向下一个孩子结点CLinklist;typedef struct E
10、lemtype info; /结点信息 CLinklist *firstchild; /指向第一个孩子结点的指针TLinklist;typedef struct TLinklist elemMAX_TREE_LINKLIST_SIZE; int n,root; /n为树中当前结点的数目,root为根结点在一维数组中的位置ChildTree;这种存储方法的特点是寻找结点的双亲很容易,但寻找结点的孩子比较困难。2. 孩子表示法孩子表示法描述孩子关系。由于各结点的孩子数可能不同,利用链式存储结构更加合适。孩子表示法如图6-15所示。其主体是一个一维数组,数组的每一个元素有两个域组成,一个域用来存放结点信息,另一个用来存放指针,该指针指向由该结点孩子组成的单链表的首位置。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1