http://blog.sina.com.cn/s/blog_6997f0150100y55v.html
图1
上图描述的数据结构就是“树”,其中最上面那个圈圈A称之为根节点(root),其它圈圈称为节点(node),当然root可以认为是node的特例。
树跟之前学习过的线性结构不同,它是一对多的非线性结构,具有二个基本特点:
1、根节点(root)没有前驱节点,除root之外的所有节点有且只有一个前驱节点
2、树中的所有节点都可以有0个或多个后继节点。
所以下面这些歪瓜咧枣,不能算是树:
图2
下是是一些烦人但是很重要的术语:
1、结点(Node):表示树中的数据元素,由数据项和数据元素之间的关系组成。在图1中,共有10个结点。
2、结点的度(Degree of Node):结点所拥有的子树的个数,在图1中,结点A的度为3。
3、树的度(Degree of Tree):树中各结点度的最大值。在图1中,树的度为3。
4、叶子结点(Leaf Node):度为0的结点,也叫终端结点。在图1中,结点E、F、G、H、I、J都是叶子结点。
5、分支结点(Branch Node):度不为0的结点,也叫非终端结点或内部结点。在图1中,结点A、B、C、D是分支结点。
6、孩子(Child):结点子树的根。在图1中,结点B、C、D是结点A的孩子。
7、双亲(Parent):结点的上层结点叫该结点的双亲。在图1中,结点B、C、D的双亲是结点A。
8、祖先(Ancestor):从根到该结点所经分支上的所有结点。在图1中,结点E的祖先是A和B。
9、子孙(Descendant):以某结点为根的子树中的任一结点。在图1中,除A之外的所有结点都是A的子孙。
10、兄弟(Brother):同一双亲的孩子。在图1中,结点B、C、D互为兄弟。
11、结点的层次(Level of Node):从根结点到树中某结点所经路径上的分支数称为该结点的层次。根结点的层次规定为1,其余结点的层次等于其双亲结点的层次加1。
12、堂兄弟(Sibling):同一层的双亲不同的结点。在图1中,G和H互为堂兄弟。
13、树的深度(Depth of Tree):树中结点的最大层次数。在图1中,树的深度为3。
14、无序树(Unordered Tree):树中任意一个结点的各孩子结点之间的次序构成无关紧要的树。通常树指无序树。
15、有序树(Ordered Tree):树中任意一个结点的各孩子结点有严格排列次序的树。二叉树是有序树,因为二叉树中每个孩子结点都确切定义为是该结点的左孩子结点还是右孩子结点。
16、森林(Forest):m(m≥0)棵树的集合。自然界中的树和森林的概念差别很大,但在数据结构中树和森林的概念差别很小。从定义可知,一棵树有根结点和m个子树构成,若把树的根结点删除,则树变成了包含m棵树的森林。当然,根据定义,一棵树也可以称为森林。
二叉树
通俗点讲,就是每个节点最多只能分二叉的树(标准的废话,呵),图示如下:
图3
注:二叉树是有序树,即每个节点下的左右子节点摆放是有顺序的,所以上图中的(a)跟(b)被认为是二棵不同的二叉树!
二叉树有二种经典的特例:完全二叉树(Complete Binary Tree) 与 满二叉树(Full Binary Tree)
图4
如上图,所谓满二叉树就是:每个节点都有二个分支,且所有叶节点都处于同一个层次。(很明显,对于一个深度Degree为K的满二叉树,其节点总数为)
所谓完全二叉树就是:叶结点只可能出现在层次最大的两层上,并且某个结点的"左分支"下"子节点"的最大层次与"右分支"下"子节点"的最大层次相等或大1。(再讲得更通俗点:除最后一层外,其它各层都是满的,且最后一层如果出现未满的情况,叶节点只能在左边,即只能空出右节点的位置)
二叉树的数学特性:
1、 一棵非空二叉树的第 i 层上最多有2^(n-1)个结点(i≥1)。
比如:以上图满二叉树(a)为例,第一层只有节点a,即2的0次方=1,第二层有B,C二个节点,即2的(2-1)次方为2...
2、若规定空树的深度为0,则深度为k的二叉树最多有个结点(k≥0)。
这个其实上面在介绍满二叉树的时候,已经说过深度为k的满二叉树,有个节点,这个就是二叉树的节点数极限了.
比如上图中(a)树的总节点数为15,则深度K = lg(15) + 1 = 3 + 1 = 4
4、对于一棵非空二叉树,如果度为0的结点数目为,度为2的结点数目为,则有
比如上图中(a)树中度为0的节点为H,I,J,K,L,M共6个(即叶节点),其它节点A,B,C,D,E,F,G都是度为2的结节有7个,有 7 = 6 + 1
5、对于具有n个结点的完全二叉树,如果按照从上到下和从左到右的顺序对所有结点从1开始编号,则对于序号为 i 的结点,有:
图5
(1)如果 i>1,则序号为i的结点的双亲结点的序号为i/2(“/”表示整除);如果i=1,则该结点是根结点,无双亲结点。
如上图,随便选一个节点,比如D(序号为4),则D的父节点序号为4/2 = 2,即节点B
(2)如果2i≤n,则该结点的左孩子结点的序号为2i;若2i>n,则该结点无左孩子。
如上图,随便找个节点5(即E点),则2*5<=10,则E节点的左子节点序号为2*5 = 10即J点
(3)如果2i+1≤n,则该结点的右孩子结点的序号为2i+1;若2i+1>n,则该结点无右孩子。
如上图,随便找个节点4(即D点),则2*4 + 1<=10,则D点的右子节点序列为2*4 +1 = 9,即I点
二叉树的存储结构
1、顺序存储
对于完全二叉树,比如图5的这种,可以表示为
由刚才的数学特性5得知,只要知道了一个节点的序号i,就能确定该节点的父节点,以及左右子节点的序号(如果有左右子节点的话),所以这样就可以将非线性的树型结构,变成一一对应的线性结构.
但是非完全二叉树,特性5就不成立了,但我们可以给非完全二叉树添加一些空节点,补成一棵完全二叉树
上图中的^代表空节点(NULL)
这样就能使用顺序存储了,但是缺点很明显:浪费了存储空间。
2、二叉链表存储
把每个节点Node添加三个基本属性 lChild(左子节点),rChild(右子节点),以及data(节点值),如果左子节点或右子节点为空,则用Null表示(图形中用^表示)
如上图,根据是否有头节点引用,可分为"不带头结点的二叉链表"和"带头结点的二叉链表"