一:树
1.树的表示方式:
(1)图形表示法(分支图表示法)
(2)嵌套集合表示法
(3)广义表表示法
( A ( B ( E ,F( K, L ), ), C ( G ), D ( H , I, J ) )
(4)目录表示法
(5)左孩子-右兄弟表示法
2.树结构与线性结构的比较:
线性结构:第一个结点无前驱,最后一个结点无后继,其他结点有一个前驱和一个后继;
树 结 构:根节点无前驱,多个叶子节点无后继,其他结点只有一个前驱和多个后继。
3.树的存储结构:
(1).顺序存储:
可规定为: 从上至下、从左至右将树的结点依次存入内存
重大缺陷:复原困难(不能唯一复原就没有实用价值)
(2).链式存储:
指针域:一个前驱指针,n个后继指针
存在问题:若规定等长结构体(即每个结构体有n个后继指针),则浪费空间;若规定不等长,则要定义多种结构体,操作起来不方便。
*解决思路:先研究最简单、最有规律的树(二叉树), 然后设法把一般的树转化为简单树(二叉树)。
二.二叉树.
1.性质:
1): 在二叉树的第i层上至多有2的n-1次方个结点(i>=1)
2).深度为k的二叉树至多有2的k次方-1个结点(k>=1)
3).对于任何一棵二叉树,若2度的结点数有n2个,则叶子数(n0)必定为n2+1 (即n0=n2+1)
2.满二叉树:
1)深度为k的节点数为2的k次方-1.
2).满二叉树第k层的结点个数比其1~k-1层所有结点个数之和多一个。
3.完全二叉树:树中的1~n个结点的位置与满二叉树的1~n个节点的位置相同.
1) 叶子结点只可能在层次最大的两层上出现;
2) 对任一结点,若其右分支下的子孙的最大层次 为 L,则其左分支下的子孙的最大层次必为 L 或 L+1。
3)具有n个结点的完全二叉树的高度为└ log2n ┘ + 1(向下取整)
4)具若对含n个结点的完全二叉树从上到下且从左至右进行1至n的编号,则对二叉树中任意一个编号为i的结点:
(1)若i=1,则该结点是二叉树的根,无双亲; 否则,编号为└ i/2 ┘的结点为其双亲结点;
(2)若2i > n,则该结点无左孩子; 否则,编号为2i的结点为其左孩子结点;
(3)若2i+1 > n,则该结点无右孩子结点; 否则,编号为2i+1的结点为其右孩子结点。
4.存储结构:
*顺序存储:
typedef TElemType SqBiTree[MAX_TREE_SIZE];
// 0号单元存储根结点
SqBiTree bt;
1).这种结构只适合满二叉树和完全二叉树
因为这样可以恢复到原来对应的唯一二叉树,比如C的左右孩子依次为第6和第7个,数组也恰好对应
2).当二叉树不再是满二叉树和完全二叉树时,我们只能这样做:把缺少的结点在数组中的位置让它为空
这样一来我们在数组中就会发现会有很多位置空着在,这样就浪费了空间,对于
这样的二叉树(最坏情况):
就会分配2的K次方-1个空间,造成空间的极大浪费!!
*链式存储:
(1)存储结构:
1).二叉链表
typedef struct BiTNode
{
TElemType data; // 结点数据
struct BiTNode *lchild,*rchild; // 左、右孩子指针
}BiTNode, *BiTree;
2).三叉链表:
typedef struct TriTNode {
TElemType data;
struct TriTNode *lchild,*rchild; // 左右孩子指针
struct TriTNode *parent;
} TriTNode, *TriTree;