众做周知,逻辑结构分为:线性结构、树形结构、图形结构、集合四种。前面说的List(线性表)都是线性结构,一个前驱一个后继,树有一个前驱多个后继,就像下面这样的。
树的应用很广了,比如省市县的关系就是树结构;计算机系统中文件系统就是树结构;国家、公司的组织结构都是输结构。
树的几个概念
- 结点的度:树中一个结点几个子节点的个数。
- 树的度:树中结点最大度数。
- 分支结点:有儿子的结点(即度大于0)。
- 叶子结点:没儿子的结点(即度等于0)。
- 树的高度(深度):这棵树一共有几代人(就是族谱中的几代人)。
- n叉树:树的度为n就叫n叉树,比如二叉树表示树的度为2,即结点最多生俩孩子,三叉树就是结点最多生三个孩子。
- 路径:树中两个结点之间的路径是由这两个结点之间所经过的结点序列组成的。
- 路径长度:路径上所经过边的个数。
- 满n叉树:比如满二叉树,树的所有结点都有俩孩子;满3叉树,每个结点都有三孩子。
- 完全n叉树:比如完全二叉树,从上到下从左到右生孩子,不能跳。
树的几个性质
- 结点数=所有结点的度+1
- 度为m的第i层上最多有pow(m,i-1)个结点
- 高度为h的m叉树至多有1+m+pow(m,2)+...+pow(m,h-1)个结点(可以用等比数列求和公式化简)
- 具有n个结点的m叉树最小高度
树的存储结构
双亲表示法
以双亲作为索引的关键词的一种存储方式,每个结点只有一个双亲,所以选择顺序存储占主要,以一组连续空间存储树的结点,同时在每个结点中,附设一个指示其双亲结点位置的指针域,这种方式经常用在数据库存储中。
/*树的双亲表示法结点结构定义*/
#define MAX_TREE_SIZE 100
typedef int TElemType;
typedef struct PTNode //结点结构
{
TElemType data; //结点数据
int parent; //双亲位置
}PTNode;
typedef struct //树结构
{
PTNode nodes[MAX_TREE_SIZE]; //结点数组
int r, n; //r是根位置,n是结点数
}PTree;
孩子表示法
主要关注孩子结点,将每个孩子结点用链表的形式连接出来,类似于HashMap的结构。
/*树的孩子表示法结点结构定义*/
#define MAX_TREE_SIZE 100
typedef int TElemType;
typedef struct CTNode //孩子结点
{
int child;
struct CTNode* next;
}*ChildPtr;
typedef struct //表头结构
{
TElemType data;
ChildPtr firstChild; //这里只是一个头指针,指向第一个结点
}CTBox;
typedef struct //树结构
{
CTBox nodes[MAX_TREE_SIZE]; //结点数组
int r, n; //r是根位置,n是结点数
}CTree;
孩子兄弟表示法
这种方法又叫二叉树表示法,用二叉链表作为树的存储结构。任意一棵树,他的结点的第一个孩子如果存在就是唯一结点,他的右兄弟存在,也是唯一的。设置两个指针,分别指向该节点的第一个孩子和该节点的右兄弟。
typedef int TElemType;
typedef struct CSNode
{
TElemType data;
struct CSNode* firstchild, *rightsib;
}CSNode,*CSTree;