树:非线性结构(结点间前驱、后继的关系并不具有惟一性),其结点间的关系是前驱惟一,而后继不惟一,即结点之间是一对多的关系。

树的定义:是n(n>=0)个结点的有限集合T。
当n=0时,称为空树;
当n>0时,该集合满足如下条件:
(1)其中必有一个称为根(root)的特定结点,它没有直接前驱,但有零个或多个直接后继。
(2)其余n-1个结点又可以划分成m(m>0)个互不相交的有限集T1,T2,…,Tm,其中Ti又是一颗树,称为根root的子树。每棵子树的根结点有且仅有一个直接前驱root,可有零个或多个直接后继。
因此,树是递归定义的。

树的相关术语:
1、结点:包含一个数据元素及若干指向其他结点的分支信息。
2、结点的度:一个结点的子树个数称为此结点的度。
3、叶子结点:度为0的结点,即无后继的结点,也称为终端结点。
4、分支结点:度不为0的结点,也称为非终端结点。一棵树中除叶结点外的所有结点都是分支结点。
5、结点的层次:从根结点开始定义,根结点的层次为1,根的直接后继的层次是2,依此类推。
6、结点的层次编号:将树中的结点按从上层到下层,同层从左到右的次序排成一个线性序列,依次给它们编以连续的自然数。(一般都是从1开始编号,0也可以。根据人家题中所给。)
7、树的度:树中所有结点的度的最大值。
8、树的高度(深度):树中所有结点的层次的最大值。
9、有序树:在树T中,如果各子树Ti之间是有先后次序的,则称为有序树。其中T1叫做根的第一棵子树,…。
无序树:树中结点的各棵子树之间的次序不重要,可以相互交换位置。
10、森林:m(m>=0)棵互不相交的树的集合。
将一棵非空树的根结点删去,树就变成一个森林;
反之,给森林增加一个统一的根结点,也就是让森林中每一棵树的根结点都变成它的孩子,森林就变成一棵树。
11、同构:给定两棵树T1和T2,如果T1可以通过若干次左右孩子互换就变成T2,则称这两棵树是同构的。
12、我们常常借助人类家族树的术语,以便于直观理解结点间的层次关系。
(1)孩子结点:一个结点的直接后继称为该结点的孩子结点。树中一个结点的子树的根结点称为该结点的孩子结点。
(2)双亲结点:一个结点的直接前驱称为该结点的双亲结点。
(3)兄弟结点:同一双亲结点的孩子结点之间互称兄弟结点。
(4)堂兄弟结点:同一结点层次,不同双亲结点的孩子结点称为堂兄弟结点。
(5)祖先结点:一个结点的祖先结点是指从根结点到该结点的路径上的所有结点。
(6)子孙结点:一个结点的直接后继和间接后继称为该结点的子孙结点。也就是以某结点为根结点的子树中的所有结点。
(7)前辈结点:层号(结点的层次编号)比该结点小的结点,都称为该结点的前辈结点。
(8)后辈结点:层号比该结点大的结点,都称为该结点的后辈结点。

树的图解表示法
(1)倒置树结构(树型表示法),这是最常见的树的图解表示法
(2)集合的文氏图表示法(嵌套集合形式)
(3)广义表形式(嵌套括号表示法):(A(B(E(K,L),F),C(G),D(H(M),I,J)))
(4)凹入表示法(目录结构表示法)

树的存储结构
(1)双亲表示法:data+parent
优点:找一个结点的双亲结点很方便。
缺点:找一个结点的孩子结点很不方便。
定义1

typedef int DataType;
struct TreeNode
{
   DataType data;
   struct TreeNode *Parent;
};

定义2(教材)

typedef int DataType;
#define MAX (10)
typedef struct TreeNode
{
   DataType data;
   int parent;//指示器,指示其双亲结点在数组中的下标位置,根节点的parent=-1。
} TreeNode;
struct Tree
{
   TreeNode tree[MAX];
   int nodenum;//该树的结点个数
};

在这里插入图片描述(2)孩子表示法
优点:找一个结点的孩子结点很方便。
缺点:找一个结点的双亲结点很不方便。
定义1

typedef int DataType;
struct TreeNode
{
   DataType data;
   struct TreeNode *Child1;
   ……
   struct TreeNode *Childn;
};

在这里插入图片描述
这种定义方式需要解决的问题是到底得给多少个指针域?
答:所有结点中指针域最大的那个。显然有些浪费空间。
定义2(教材)

typedef int DataType;
#define MAX (10)
typedef struct ChildNode//单链表
{
   int child;//该孩子结点在数组中的下标位置
   struct ChildNode *next;//指向下一个孩子结点
} ChildNode;
typedef struct DataNode//顺序表中结点的结构定义
{
   DataType data;
   ChildNode *FirstChild;//指向孩子链表的头指针
} DataNode;
struct Tree
{
   Dataode tree[MAX];
   int root;//该树的根节点在数组中的下标位置
   int nodenum;//该树的结点个数
}

在这里插入图片描述
在这里插入图片描述
(3)双亲孩子表示法:双亲表示法+孩子表示法
优点:找一个结点的双亲结点和孩子结点都很方便。
定义如下

typedef int DataType;
struct TreeNode
{
   DataType data;
   struct TreeNode *Parent;
   struct TreeNode *Child1;
   ……
   struct TreeNode *Childn;
};

这种定义方式需要解决的问题是到底得给多少个指针域?
答:所有结点中指针域最大的那个。(因为一个结点的双亲结点只有一个,除了根节点。所以此处需要关心的只是所有结点中孩子最多的那个。)显然有些浪费空间。
(4)孩子兄弟表示法:树中每个结点有两个指针域,分别指向该结点的第一个孩子结点和下一个兄弟(右兄弟)结点。
优点:找一个结点的孩子结点很方便。
缺点:找一个结点的双亲结点很不方便。
定义如下

typedef int DataType;
struct TreeNode
{
   DataType data;
   struct TreeNode *FirstChild;
   struct TreeNode *NextBrother;
};

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值