6.1 树和二叉树
树和二叉树的基本概念、特殊二叉树、二叉树的存储结构
树的定义和基本概念
定义
树(tree)是n(n>0)个结点的有限集T,其中:
有且仅有一个特定的结点,称为树的根(root)
当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1,T2,……Tm,其中每一个集合本身又是一棵树,称为根的子树(subtree)
- 特点:
树中至少有一个结点——根
树中各子树是互不相交的集合
基本术语
结点(node)
指树中的一个数据元素,包括数据项及若干指向其子树的分支。一般用一个字母表示。
结点的度(degree)
结点拥有的子树数
叶子(leaf)
度为0的结点,也叫终端结点。
分枝结点
除叶子结点外的所有结点,也叫非终端结点。
孩子(child)
结点子树的根称为该结点的孩子
双亲(parents)
孩子结点的上层结点叫该结点的~
祖先结点
从根结点到该结点所经过分枝上的所有结点为该结点的祖先,如图6-1c中M的祖先有A,D ,H 。
子孙结点
某一结点的子女及子女的子女都为该结点子孙。
兄弟(sibling)
具有同一个双亲的结点
树的度
一棵树中最大的结点度数
结点的层次(level)
从根结点算起,根为第一层,它的孩子为第二层……
深度(depth)
树中结点的最大层次数
有序树
若一棵树中所有子树从左到右的排序是有顺序的,不能颠倒次序。称该树为有序树。
无序树
若一棵树中所有子树的次序无关紧要,则称为无序树。
森林(forest)
m(m>=0)棵互不相交的树的集合.一棵树可以看成是一个特殊的森林。
ADT
ADT Tree{
数据对象D:D是具有相同特性的数据元素的集合
数据关系R:
若D为空集,则称为空树;
若D仅含一个数据元素,则R为空集,否则R={H},
H是如下二元关系:
在D中存在唯一的称为根的数据元素root,它在关系H下无前驱;
若D-{root}≠Φ,则存在D-{root}的一个划分D1,D2,…Dm(m>0),对任意j≠k (1≤j,k≤m)又Dj∩Dk=Φ,且对任意的i(1≤i≤m),唯一存在数据元素xi∈Di,有<root,xi>∈H;
对应于D-{root}的划分,H - {<root,x1>, … <root , xm> } 有唯一的一个划分H1,H2,…Hm,m>0,对任意j≠k(1≤j,k≤m)有Hj∩Hk=Φ,且对任意i(1≤i≤m),Hi是Di上的二元关系,(Di,{Hi})是一棵符合本定义的树,称为根root的子树。
基本操作:
InitTree( &T ); // 初始化
DestroyTree( &T ); // 销毁
CreateTree( &T, definition);//按definition构造树
ClearTree( &T ); // 清空
TreeEmpty( T ); // 空?
TreeDepth( T ); // 树的深度
Root( T ); // 树根
Value( T, cur_e ); // 求结点cur_e的值
Assign( T, cur_e, value ); // 赋值
Parent( T, cur_e ); // 求cur_e的双亲
LeftChild( T, cur_e ); // 求cur_e的最左孩子
RightSibling( T, cur_e );// 求cur_e的右兄弟
InsertChild( &T, &p, i, c );// 插入c为T中p所指结点的第i棵子树
DeleteChild( &T, &p, i);// 删除T中,p所指结点的第i个子树
TraverseTree( T, visit() ); //遍历
}//ADT Tree
二叉树
定义
二叉树是n(n>=0)个结点的有限集,它或为空树(n=0),或由一个根结点和两棵分别称为左子树和右子树的互不相交的二叉树构成
- 特点
每个结点至多有二棵子树(即不存在度大于2的结点)
二叉树的子树有左、右之分,且其次序不能任意颠倒
二叉树的ADT表示
ADT BinaryTree
{
数据对象D:D是具有相同特性的数据元素的集合;
数据关系R:
若D = Φ,则 R = Φ, 称BinaryTree为空二叉树;
若D ≠ Φ,则 R = { H }, H是如下的二元关系:
(1) 在D中,存在唯一的称为根的数据元素
root, 它在关系H下无前驱;
(2) 若D – {root} ≠ Φ, 则存在
D-{root} = {Dl, Dr}, 且 Dl ∩Dr = Φ;
(3) 若Dl ≠ Φ, 则Dl中存在唯一的元素xl,
<root, xl> ∈ H, 且存在Dl上的关系Hl ∈H;
若Dr ≠ Φ,则Dr中存在唯一的元素xr,<root,xr>∈H,
且存在Dr上的关系Hr ∈H;
H = { <root, xl>,<root, xr>, Hl, Hr};
(4) ( Dl,{ Hl})是一棵符合本定义的二叉树,称为根的左子树;
( Dr, {Hr})是一棵符合本定义的二叉树,称为根的右子树;
基本操作:
InitBiTree( &T ); // 初始化
DestroyBiTree( &T ); // 销毁
CreateBiTree( &T, definition ); // 创建二叉树
ClearBiTree( &T ); // 清空
BiTreeEmpty( T ); // 空?
BiTreeDepth( T ); // 深度
Root( T ); // 根
Value( T, e ); // 求e的值
Assign( T, &e, value ); // 赋值
Parent( T, e ); // 求双亲
LeftChild( T, e ); // 左孩子
RightChild( T, e ); // 右孩子
LeftSibling( T, e) ; // 左兄弟
RightSibling( T, e ); // 右兄弟
InsertChild( T, p, LR, c ); // 插入
DeleteChild( T, p, LR ); // 删除
PreOrderTraverse( T, Visit( )); // 先序遍历
InOrderTraverse( T, Visit( )); // 中序遍历
PostOrderTraverse( T, Visit( )); // 后序遍历
LeverOrderTraverse( T, Visit( )); // 层序遍历
} // ADT BinaryTree
二叉树的性质
- 性质1:在二叉树的第i层上至多有2^(i-1)个结点(i≥1)
- 性质2:深度为k的二叉树至多有2^(k-1)个结点(k≥1)
- 性质3:对任何一棵二叉树T,如果其终端结点数为n0,度为2的结点数为n2,则n0=n2+1
- 性质4:具有n个结点的完全二叉树的深度为floor[ log2 n ] +1
- 性质5:如果对一棵有n个结点的完全二叉树的结点按层序编号,则对任一结点i(1<=i<=n),有:
(1) 如果i=1,则结点i是二叉树的根,无双亲;如果i>1,则其双亲是florr[i/2]
(2) 如果2i>n,则结点i无左孩子;如果2i<=n,则其左孩子是2i
(3) 如果2i+1>n,则结点i无右孩子;如果2i+1<=n,则其右孩子是2i+1
特殊的二叉树
满二叉树
深度为k,其一共有2^(k)-1个节点
(每一层都满了)
完全二叉树
深度为k,有n个结点的二叉树当且仅当其每一个结点都与深度为k的满二叉树中编号从1至n的结点一一对应
(最后一层,从最右节点去掉连续节点后的满二叉树)
二叉树的存储结构
顺序存储结构
更适合存储完全二叉树,一般二叉树会浪费空间
链式存储结构
二叉链表
typedef struct BitNode
{ TElemType data;
struct BitNode *lchild,*rchild;
}BiTNode,*BiTree;
三叉链表
typedef struct node
{ Elemtype data;
struct node *lchild,*rchild,*parent;
};BiTNode, *BiTree;