目录
前言
这篇文章介绍数据结构中的树和二叉树
。
树型结构是一类重要的非线性数据结构。其中以树和二叉树最为常用,直观看来,树是以分支关系定义的层次结构。
1.树的概念和术语
1.数的概念
树是零个或者多个结点的有限集合。结点为0的树称为空树,结点大于零的树称为非空树。
非空树有以下特点:1.有且仅有一个根结点(root) 2.当结点树大于1的时候,由很多个子树。
图1.树的示意图
2.树的术语
1.结点的度(Degree)
结点拥有的子树数称为结点的度。
在图1中A的度为3,C的度为1,F的度为0。
2.叶子或者终端节点
度为0的结点称为叶子(Leaf)或者终端结点。
如图1中的结点K、L、F、G、M、I、J都是树的叶子。
3.非终端结点或分支结点
度不为0的结点称为非终端结点或者分支结点。
4.树的度
树内各结点的度的最大值。
如图1中树的度为3.
5.结点的孩子
结点的子树的根称为结点的孩子。
6.结点的双亲
结点叫做结点的子树的双亲。
7.兄弟
拥有同一双亲的结点称为兄弟(Sibling)。
8.结点的层次
跟为第一层,根的孩子为第二层,依次类推
9.树的深度
树中结点的最大层次称为树的深度(depth)。
10.森林
m棵树互不相交的树的集合称为森林,其中m>=0。
2.二叉树
1.定义
二叉树是一种树型结构,它的特点是每个节点至多只有两颗子树,并且二叉树的子树有左右之分,其次序不能任意颠倒。
图2.二叉树的五种状态
二叉树有图2所示的五种状态。、
其中a为空二叉树,b为仅有根结点的二叉树,
c为仅有左子树的二叉树,
d为左右子树均非空的二叉树,
e为仅有右子树的二叉树。
2.二叉树的性质
1.二叉树的第一个性质
2.二叉树的第二个性质
3.二叉树的第三个性质
4.二叉树的第四个性质
3.二叉树的存储结构
1.二叉树链表存储表示
我们使用一组地址连续的存储单元依次自上而下、自左至右存储完全二叉树上的节点元素。使用0表示不存在该节点。
// - - - - - - 二叉树的顺序存储表示 - - - - - -
#define MAXTREESIZE 100 //二叉树的最大节点数
typedef char TElemType;
typedef TElemType SqBiTree[MAXTREESIZE]; // 0号元素存储根节点
2.二叉树的链式存储表示
链式二叉树的三要素:根节点、左子树、右子树。
我们使用data表示二叉树数据域,leftChild和rightChild表示二叉树的左右节点。在下面的定义中,我们使用两个结点结构所得二叉树的存储结构称为二叉链表。
// 二叉树节点的数据类型
typedef char TElementType;
// 二叉树结点的定义
typedef struct BiTNode {
TElementType data;
struct BiTNode * leftChild, * rightChild;
} BiTNode, * BiTree;
当然我们还可以使用三个节点来表示二叉树的存储结构,在上述定义的基础上,我们增加一个父结点指针指向结点的双亲,这种二叉树结构称为三叉链表。定义如下:
// 二叉树节点的数据类型
typedef char TElementType;
// 二叉树结点的定义
typedef struct BiTNode {
TElementType data;
struct BiTNode * leftChild, * rightChild,*parent;
} BiTNode, * BiTree;
3.遍历二叉树和线索二叉树
1.遍历二叉树
1.先序遍历二叉树
若二叉树为空,则空操作;否则
- 访问根节点
- 先序遍历左子树
- 先序遍历右子树
2.中序遍历二叉树
若二叉树为空,则空操作;否则
- 中序遍历左子树
- 访问根节点
- 中序遍历右子树
3.后序遍历二叉树
若二叉树为空,则空操作;否则
- 后序遍历左子树
- 后序遍历右子树
- 访问根节点
2.线索二叉树
在上述遍历二叉树的过程中,我们无法得到节点的直接前驱和直接后继结点。
4.树和森林
1.树的存储结构
1.双亲表示法
每个结点附设一个指示器指示其双亲结点在链表中的位置。
// - - - - - - 树的双亲表示法 - - - - - -
#define MAX_TREE_SIZE 100 //二叉树的最大节点数
typedef char TElemType;
typedef int Status;
typedef struct PTNode{
TElemType data;
int parent;// 双亲位置域
}PTNode;
typedef struct{//树结构
PTNode nodes[MAX_TREE_SIZE];
int r,n;//
}PTree;
2.孩子表示法
// - - - - - - 树的孩子链表存储表示 - - - - - -
#define MAX_TREE_SIZE 100
typedef char TElemType;
typedef struct CTNode{
int child;
struct CTNode *next;
}* ChildPtr;
typedef struct{//树结构
TElemType data;
ChildPtr firstChild;//孩子链表头指针
}CTBox;
typedef struct{//树结构
CTBox nodes[MAX_TREE_SIZE];
ChildPtr n,r;//节点数和根的位置
}CTree;
3.孩子兄弟表示法
// - - - - - - 树的二叉链表存储表示 - - - - - -
typedef char ElemType;
typedef struct CSNode{//树结构
ElemType data;
struct CSNode *firstchild,*nextsibling;
}CSNode,*CSTree;
2.森林与二叉树的转换
森林和二叉树之间可以进行转换
3.树和森林的遍历
1.树的遍历
图3.树的示意图
1.先跟(次序)遍历树
先访问数的根节点,然后依次先跟遍历根的每颗子树。
以上述的图结构为例,先根遍历树之后的先根序列为:
A B C D E
2.后跟(次序)遍历树
先依次后跟遍历每颗子树,然后访问根结点。
以上述的图结构为例,先根遍历树之后的先根序列为:
B D C E A
2.森林的遍历
图4.森林示意图
1.先序遍历森林
若森林非空,按照以下顺序 遍历森林:
- 访问森林中的第一棵树的根结点
- 先序遍历第一棵树中根结点的子树森林
- 先序遍历除去第一棵树之后剩余的树构成的森林
以图4为例,遍历结果为:
A B C D E F G H I J
2.中序遍历森林
若森林非空,按照以下顺序 遍历森林:
- 中序遍历森林中第一棵树中根结点的子树森林
- 访问森林中的第一棵树的根结点
- 中序遍历除去第一棵树之后剩余的树构成的森林
以图4为例,遍历结果为:
B C D A F E G H J I G