数据结构--树

树的定义与基本使用

树的定义

我们生活中会了解到许多树,门前的核桃树,松树等,我们这里要讨论另一种在数据结构例定义的树。
树是n个结点的有限集。n=0时称为空树。在任意一颗非空树中:有且仅有一个特定的成为根的结点;当n>1时,其余结点可分为m个互不相交的有限集T1、T2、……、Tm,其中每一个集合本身又是一棵树,并且称为根的子树。
在这里插入图片描述
注:1.n>0时根结点是唯一的,不可能存在多个根节点。
2.m>0时,子树的个数没有限制,但他们一定是互不相交的。如下图反例:
在这里插入图片描述

结点分类

树的结点包含一个数据元素及若干指向其子树的分支。结点拥有的子树称为结点的度。度为0的结点称为叶结点或终端节点;度不为0的结点称为非终端节点或分支结点。除根结点之外,分支结点也称为内部结点。树的度是树内各节点的度的最大值。
在这里插入图片描述

结点间关系

结点的子树的根称为该节点的孩子,相应地,该节点称为孩子的双亲,同一个双亲的孩子之间互称兄弟。结点的祖先是从根到该节点所经分支上的所有节点。

树的存储结构

定义这种东西肯定很好理解,接下来我们看看树的表示。

双亲表示法

在树中,除了根结点,其他结点都是由双亲的,但不一定有孩子。
我们假设以一组连续空间存储树的结点,同时在每个节点中,附设一个指示器指示其双亲结点到链表中的位置。也就是说,每个节点有自己的数据和其双亲的位置。
以下是双亲表示法的结点结构定义代码:

#define MAX_TREE_SIZE 100
typedef int Type; 
typedef struct{  // 结点结构 
 Type data;  //结点数据 
 int parent;  //双亲位置 
}Node;
typedef struct{  //树结构 
 Node nodes[MAX_TREE_SIZE];  //结点数组 
 int r,n;  // 根的位置和结点数 
}; 

通俗易懂。
有了这样的定义,就可以实现双亲表示法了。因为根结点没有双亲,所以要定义根结点的位置域为-1。现在每个结点除了根结点都知道自己的双亲在哪。当然,还可以再继续设置若干个位置域实现其他功能,比如找到自己是否有兄弟以及兄弟的位置等。

孩子表示法

在树中每个结点可能有多课子树,可以考虑用多重链表,即每个结点有多个指针域,其中每个指针指向一颗子树的根结点。
每个结点指针域的个数等于该结点的度,我们专门取一个位置来存储结点指针域的个数。
但是这样做各个结点的链表就是不同的结构,加上维护都节点的度的数值,时间上的损耗就增加了。所以我们还可以再对每个结点的孩子建立一个单一链表体现他们的关系。
把每个结点的孩子结点排列起来,以单链表作存储结构,则n个结点有n个孩子链表,叶节点单链表为空。然后n个头指针又组成一个线性表,采用顺序存储结构,放进一个一维数组中:

在这里插入图片描述
child是数据域,用来存储某个结点在表头数组中的下标。next是指针域,用来存储指向某节点的下一个孩子结点的指针。data是数据域,存储某结点的数据信息。firstchild是头指针域,存储该节点的孩子链表的头指针。
结构定义代码:

#define MAX_TREE_SIZE 100
typedef int Type; 
typedef struct CTNode{ //孩子节点 
 int child;  
 struct CTNode *next;
} *ChildPtr;
typedef struct{  //表头结构 
 Type data; 
 ChildPtr firstchild;
}CTBox;
typedef struct{  //树结构 
 CTBox nodes[MAX_TREE_SIZE];  //结点数组 
 int r,n;  //根的位置和结点数 
}CTree;

这样的结构对于查找起来很方便,只需查找这个结点的孩子单链表即可,遍历只需对头节点的数组循环即可。
以上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值