一、.树的概念
1、树的定义
树是一种常见的非线性的数据结构。
树的定义如下: 树是n(n>=0)个结点的有限集,n=0时称为空树。在任意一棵非空树中:
⑴有且仅有一个结点没有前驱(父亲结点),该结点称为树的根;
⑵n>1时,其余结点可分成m(m>0)个互不相交的有限集,其中每个集合本身又是一棵树,并且称为根的子树。
2、结点的分类
结点一般分成三类
⑴根结点:
没有父亲的结点。在树中有且仅有一个根结点。
⑵分支结点(非终端结点):
除根结点外,有孩子的结点称为分支结点。a,b,c,x,t,d,i。分支结点亦是其子树的根;
⑶叶结点(终端结点):
没有孩子的结点称为树叶。w,h,e,f,s,m,o,n,j,u为叶结点。
根结点到每一个分支结点或叶结点的路径是唯一的。从根r到结点i的唯一路径为rcti。
3、有关度的定义
⑴结点的度:一个结点的子树的数目称为该结点的度。
⑵树的度:所有结点的度的最大值称为该树的度(宽度)。
4、结点间的关系
结点的子树的根称为该结点的孩子(child)。
该结点称为孩子的双亲(parent)。
同一个双亲的孩子之间称为兄弟(sibling)。
结点的祖先是指从根到该结点所经分支上的所有结点。
以某结点为根的子树中的任一结点都称为该结点的子孙。
5、树的深度(高度)
树是分层次的。结点所在的层次是从根算起的。根结点在第一层,根的儿子在第二层,其余各层依次类推。
在树中,父结点在同一层的所有结点构成兄弟关系。 树中最大的层次称为树的深度,亦称高度。
6、森林
所谓森林,是指若干棵互不相交的树的集合。
如图去掉根结点r,其原来的三棵子树Ta,Tb,Tc的集合{Ta,Tb,Tc}就为森林,这三棵子树的具体形态如图(c)。
7、有序树和无序树
按照树中同层结点是否保持有序性,可将树分为有序树和无序树。
如果树中同层结点从左而右排列,其次序不容互换,这样的树称为有序树;如果同层结点的次序任意,这样的树称为无序树。
树的表示方法
1、树的表示方法 树的表示方法一般有两种:
⑴自然界的树形表示法:用结点和边表示树,例如上图采用的就是自然界的树形表示法。
⑵括号表示法:
先将根结点放入一对圆括号中,然后把它的子树按由左而右的顺序放入括号中,而对子树也采用同样方法处理:同层子树与它的根结点用圆括号括起来,
同层子树之间用逗号隔开,最后用闭括号括起来。例如图可写成如下形式 (r(a(w,x(d(h),e)),b(f),c(s,t(i(m,o,n),j),u)))
树的存储结构
1 双亲表示法: 一组连续空间存储树的结点,同时在每个结点中附设一个指示器指示其双亲结点在链表中的位置。
2 孩子表示法: 把每个结点的孩子结点排列起来,以单链表作存储结构。则n个结点就有n个孩子链表,如果是叶子结点,则此单链表为空,
n个头指针又组成一个线性表,采用顺序存储结构,存放到一个一维数组中。
3 孩子兄弟(二叉树)表示法
每个结点中有三个域:数据域,孩子指针,兄弟指针。
二叉树
二叉树(Binary Tree)
是n(n>=0)个结点的有限集合,该集合或者为空集(空二叉树),
或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树的二叉树组成。
由上述定义可以看出
⑴树的每一个结点可以有任意多棵子树,而二叉树中每个结点的最多有2棵子树;
⑵树的子树可以不分次序(除有序树外);而二叉树的子树有左右之分。
前面引入的有关树的一些基本术语对二叉树仍然适用。下图列出二叉树的五种基本形态:
2、二叉树的两个特殊形态
⑴满二叉树 在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有的叶子都在同一层上,这样的二叉树称为满二叉树。
特点:叶子只能出现在最下一层
非叶子结点的度一定是2
在同样深度的二叉树中,满二叉树的结点个数最多,叶子树最多。
(2)完全二叉树 对一棵具有n个结点的二叉树按层序编号,如果编号为i(1<=i<=n)的结点与同样深度的满二叉树中编号为i的结点在二叉树中的位置完全相同,
则这棵二叉树称为完全二叉树。
完全二叉树的特点:
1.叶子结点只能出现在最下两层
2.最下层的叶子一定集中在左部连续位置
3.倒数第二层,若有叶子结点,一定都在右部连续位置
4.如果结点的度为1,则该结点只有左孩子
5.同样结点数的二叉树,完全二叉树的深度最小
3、二叉树的主要性质
性质1:在二叉树的第i(≥1)层上,最多有2i-1个结点
性质2:在深度为k(k≥1)的二叉树中最多有2k-1个结点。
性质3:对于一棵非空二叉树,如果叶子结点数为n0,度为2的结点数为n2,则n0=n2+1
性质4:具有n个结点的完全二叉树的深度为
性质5: 如果对一棵有n个结点的完全二叉树的结点按层序编号(从第1层到第 层,每层从左到右),则对任一结点i(1<=i<=n),有:
(1)如果i=1,则结点i无双亲,是二叉树的根;如果i>1,则其双亲是结点。
(2)如果2i<=n,则序号为i的结点的左孩子结点的序号是2i;如果2i>n,则序号为i的结点无左孩子(该i结点为叶子结点)。
(3)如果2i+1>n,则结点i无右孩子;否则,其右孩子是结点2i+1。
二叉树的遍历
假如以L、D、R分别表示遍历左子树、遍历根结点和 遍历右子树,遍历整个二叉树则有DLR、LDR、LRD、 DRL、RDL、RLD六种遍历方案。
若规定先左后右,则只有前三种情况,分别规定为: DLR——先(根)序遍历, LDR——中(根)序遍历, LRD——后(根)序遍历。
1、先序遍历二叉树的操作定义为:
若二叉树为空,则空操作;否则
(1)访问根结点;
(2)先序遍历左子树;
(3)先序遍历右子树。
2、中序遍历二叉树的操作定义为:
若二叉树为空,则空操作;否则
(1)中序遍历左子树;
(2)访问根结点;
(3)中序遍历右子树。
3、后序遍历二叉树的操作定义为:
若二叉树为空,则空操作;否则
(1)后序遍历左子树;
(2)后序遍历右子树;
(3)访问根结点。
二叉树的遍历过程
前序遍历算法
//前序遍历算法 preorder(bitree t) { if(t) { printf("%3c",t->data); preorder(t->lchild); preorder(t->rchild); } }
中序遍历算法
//中序遍历算法 inorder(bitree t) { if(t) { inorder(t->lchild); printf("%3c",t->data); inorder(t->rchild); } }
后序遍历算法
//后序遍历算法 postorder(bitree t) { if(t) { postorder(t->lchild); postorder(t->rchild); printf("%3c",t->data); } }
二叉树的建立