版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011815404/article/details/80656655 </div>
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-f57960eb32.css">
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-f57960eb32.css">
<div class="htmledit_views" id="content_views">
<h1><a name="t0"></a>【树的定义】</h1>
树是递归定义的,一颗树是由n(n>0)个元素组成的有限集合,其中:
- 每个元素称为结点(node);
- 至少存在一个结点,它没有前驱(其余的结点都有唯一的一个前驱结点,每个结点可以有0或多个后继结点),这个结点称为根节点(root);
- 除根节点外,其余结点能分成m(m>=0)个互不相交的有限集合T0,T1,T2,……,Tm-1,其中每个子集又是一颗树,这些集合称为这棵树的子树。
【树的基本概念】
- 树是一种非线性的有序数据结构,能很好地描述有分支和层次特性的数据集合。
- 一个结点的子树个数,称为结点的度(degree),树中各节点的度的最大值称为这棵树的度。度为0的结点称为叶结点,度不为0的结点称为分支结点,根以外的分支结点称为内部结点。
- 在图形表示的树型结构中,对两个用线段(树枝)连接的相关联的结点,称上端结点为下端结点的父节点,称下端结点为上端结点的子结点。对同一个父结点的多个子结点互称兄弟结点,对从根结点到某个子结点所经过的所有结点称为这个子结点的祖先,对以某个结点为根的子树中的任一结点都是该结点的子孙。
- 定义一棵树的根结点的层次(level)为0,其它结点的层次等于它的父结点层次加1,则一棵树中所有的结点的层次的最大值称为树的深度(depth)。
- 对于树中任意两个不同的结点,如果从一个结点出发,自上而下沿着树中连着结点的线段能到达另一结点,则称它们之间存在着一条路径。可用路径所经过的结点序列表示路径,其长度等于路径上的结点个数减1。从根节点出发,到树中的其余结点一定存在着一条路径,不同子树上的结点之间不存在路径。
- 森林(forest)是m(m>=0)棵互不相交的树的集合。
- 树形结构中二叉树是最常用的结构,其分支个数确定,又可以为空,具有良好的递归特性,因此常常将一般树转换为二叉树进行处理。
以下图为例:
- 根节点:1,叶结点有:3、5、6、8、9,分支结点有:1、2、4、7,内部结点有:2、4、7,这棵树的度为:3
- 对于根结点1来说,它是2、3、4的父节点,同时2、3、4是结点1的子节点,它们又是兄弟结点。
- 对于结点8来说,1、4、7是它的祖先;对于4来说,7、8、9是它的子孙。
- 根节点的层次为0,结点2、3、4的层次为1,结点5、6、7的层次为2,结点8、9的层次为3,这棵树的深度为3。
- 对于结点1与结点8自己存在的路径,可用1、4、7、8来表示该路径,该路径的长度为3。
【树的存储结构】
1.父亲表示法
使用数组存储,每个结点包括一个数据域和一个指针域(指向其父结点)。
假设树的度为10,树的结点仅存放字符,则这棵树的数据结构定义如下:
-
const
int m=
10;
//树的结点数
-
struct node
-
{
-
char data;
//数据域
-
int parent;
//指针域
-
};
-
node tree[m];
优缺点:利用了树中除根结点外每个结点都有唯一的父结点这个性质,很容易找到树根,但找孩子时需要遍历整个线性表。
2.孩子表示法
树型单链表结构,每个结点包括一个数据域和一个指针域(指向若干子结点)。
假设树的度为10,树的结点仅存放字符,则这棵树的数据结构定义如下:
-
const
int m=
10;
//树的度
-
typedef
struct node;
-
typedef node *tree;
//声明tree是指向node的指针类型
-
struct node
-
{
-
char data;
//数据域
-
tree child[m];
//指针域,指向若干孩子结点
-
};
-
tree t;
缺陷:只能从根(父)结点遍历到子结点,不能从某个子结点返回到它的父结点。
3.父亲孩子表示法
树型双链表结构,每个结点包括一个数据域和二个指针域(一个指向若干子结点,一个指向父结点)。
假设树的度为10,树的结点仅存放字符,则这棵树的数据结构定义如下:
-
const
int m=
10;
//树的度
-
typedef
struct node;
-
typedef node *tree;
//声明tree是指向node的指针类型
-
struct node
-
{
-
char data;
//数据域
-
tree child[m];
//指针域,指向若干孩子结点
-
tree father;
//指针域,指向父亲结点
-
};
-
tree t;
4.孩子兄弟表示法
二叉树型表示法,是一种双链表结构,但每个结点包括一个数据域和二个指针域(一个指向该结点的第一个孩子结点,一个指向该结点的下一个兄弟结点)。
-
typedef
struct node;
-
typedef node *tree;
//声明tree是指向node的指针类型
-
struct node
-
{
-
char data;
//数据域
-
tree firstchild, next;
//指针域,分别指向第一个孩子结点和下一个兄弟结点
-
};
-
tree t;
【树的遍历】
1.先序(根)遍历:先访问根结点,再从左到右按照先序思想遍历各棵子树。(实质上是深度优先遍历)
2.后序(根)遍历:先从左到右遍历各棵子树,再访问根结点。(实质上是深度优先遍历)
3.层次遍历:按层次从小到大逐个访问,同一层次按照从左到右的次序。(实质上是广度优先遍历)
4.叶结点遍历:但将所有数据信息存放在叶结点中,其余结点都是用来表示数据之间的某种分支或层次关系时,从左到右顺序访问叶结点。
以下图为例
先序遍历的结果:125634789
后序遍历的结果:562389741
层次遍历的结果:123456789
叶结点的结果:56389
【例题】
1.树的存储结构:点击这里
2.树的遍历:点击这里