树: 是一种递归定义的数据结构。树( Tree )是树结构的简称,它是一种重要的非线性数据结构。树或者是一个空树,即不含有任何的结点(元素),或者是一个非空树,即至少含有一个结点。
根: 在一棵非空树中,它有且仅有一个节点。
子树: 在一棵非空树中,除根外其余所有结点分属于 m 个( m ≥ 0 )不相交的集合。每个集合又构成一棵树,称为根结点的 子树。
树的递归定义:
树 (Tree) 是 n(n≥0) 个结点的有限集 T , T 为空时称为空树,否则它满足如下两个条件:
(1) 有且仅有一个特定的称为根 (Root) 的结点;
(2) 其余的结点可分为 m(m≥0) 个互不相交的子集 Tl , T2 , … , Tm ,其中每个子集本身又是一棵树,并称其为根的子树 (Subree) 。
注意:树的递归定义刻画了树的固有特性:一棵非空树是由若干棵子树构成的,而子树又可由若干棵更小的子树构成。
树的表示: 树形图表示是树结构的主要表示方法。其他还有广义表、集合图、凹入图三种表示形式。
线性结构和树型结构之间的区别:
线性结构
|
树型结构
|
第一个数据元素(无前驱)
最后一个数据元素(无后继)
其它数据元素
(一个前驱、一个后继)
|
根结点(无前驱)
多个叶子结点(无后继)
其它数据元素
(一个前驱、多个后继)
|
结点 (node) :表示树中的元素,包括数据项及若干指向其子树的分支。
结点的度 (degree) :树中的一个结点拥有的子树数称为该结点的度 (Degree) 。
叶子 (leaf) :度为 0 的结点。
孩子 (child) :结点子树的根称为该结点的孩子。
双亲 (parents) :孩子结点的上层结点叫该结点的。
兄弟 (sibling) :同一双亲的孩子。
树的度 :一棵树中最大的结点度数。
结点的层次 (level) :从根结点算起,根为第一层,它的孩子为第二层……。
深度 (depth) :树中结点的最大层次数。
有序树: 子树的位置自左向右有次序关系的称为有序树,顺序决定了大小,孩子的次序不能改变。
无序树: 子树的位置自左向右无次序关系的称为无序树。
森林 (Forest) 是 m(m≥0) 棵互不相交的树的集合。树和森林的概念相近。删去一棵树的根,就得到一个森林;反之,加上一个结点作树根,森林就变为一棵树。
路径 :若树中存在一个结点序列 k1 , k2 , … , ki ,使得 ki 是 ki+1 的双亲 (1≤i<j) ,则称该结点序列是从 k1 到 kj 的一条路径 (Path) 或道路。
路径的长度: 指路径所经过的边 ( 即连接两个结点的线段 ) 的数目,等于 j-1 。
祖先: 若树中结点 k 到 ks 存在一条路径,则称 k 是 ks 的 祖先 (Ancestor) , ks 是 k 的 子孙 (Descendant) 。结点 k 的祖先和子孙不包含结点 k 本身。
结点的层数: (Level) 从根起算:根的层数为 1 ,其余结点的层数等于其双亲结点的层数加 1 。双亲在同一层的结点互为堂兄弟。树中结点的最大层数称为树的高度 (Height) 或深度 (Depth) 。很多文献中将树根的层数定义为 0 。
树形结构的逻辑特征:
树形结构的逻辑特征可用树中结点之间的父子关系来描述:
( 1 ) 树中任一结点都可以有零个或多个直接后继 ( 即孩子 ) 结点,但至多只能有一个直接前趋 ( 即双亲 ) 结点。
( 2 ) 树中只有根结点无前趋,它是开始结点;叶结点无后继,它们是终端结点。
( 3 ) 祖先与子孙的关系是对父子关系的延拓,它定义了树中结点之间的纵向次序。
( 4 ) 有序树中,同一组兄弟结点从左到右有长幼之分。
对这一关系加以延拓,规定若 k1 和 k2 是兄弟,且 k1 在 k2 的左边,则 k1 的任一子孙都在 k2 的任一子孙的左边,那么就定义了树中结点之间的横向次序。
二叉树 :指数的度为 2 的有序树。是最简单的一种树结构,在计算机领域有着广泛的应用。
二叉树的递归定义: 二叉树或者是一棵 空树 ,或者是一棵由一个 根结 点和两棵互不相交的分别称根的 左子树 和 右子树 所组成的 非空树 ,左子树和右子树又同样都是一棵二叉树。
二叉树中,每个结点的左子树的根结点被称为该结点的 左孩子 ( left child ) , 右子树的根结点被称为 右孩子 ( left child )。
满二叉树: 深度为 K 且含有 2K -1 个结点的二叉树,当树中的每一层都满时成为漫二叉树。
完全二叉树: 在一棵二叉树中,除最后一层外,若其余层都是满的,并且最后一层或者是满的,或者在最右边缺少连续若干个结点,则称此树为完全二叉树。
二叉树的抽象数据类型:
ADT BinaryTree is
Data:
// 数据存储结构定义,可采用顺序结构或链接结构
Operation :
void InitBTree(BTreeType& BT); // 初始化
void CreateBTree (BTreeType& BT,char* a);
// 根据广义表创建二叉树
bool BTreeEmpty (BTreeType& BT); // 判断是否为空树
void TraverseBTree (BTreeType& BT); // 遍历
int BTreeDepth (BTreeType& BT); // 求深度
void PrintBTree (BTreeType& BT); // 输出
void CleanBTree (BTreeType& BT); // 清空树中的结点
end BinaryTree
二叉树的存储结构:
1 、顺序存储结构
#define MAX_TREE_SIZE 100 // 二叉数的最大结点数
Typedef {
ElemType SqBiTree[MAX_TREE_SIZE ];//0 号单元存储根结点
}
SqBiTree bt;
2 、链接存储结构
二叉链表 采用独立结点,通常采用的方法是:在每个结点中设置三个域:值域、左指针域和右指针域,其结点结构如 图 5-1 所示:
图 5-1
结点类型描述如下:
Struct BTreeNode
{ ElemType data;
BTreeNode * left;
BTreeNode * right;
};
二叉树的遍历: 二叉树的遍历是二叉树中最重要的运算,顺着某一条搜索路径循序访问二叉树中的结点。使得每个结点均被访问一次,而且仅被访问一次。这样一个过程称之为“遍历”,其中 “ 访问 ” 的含义可以很广,如输出结点的信息 。
|