树的存储结构难点:无法直接用数组表示树的逻辑结构
但是却可以设计结构体数组对结点间的关系进行表述
如下图:(用一个表格描述图中的树)
那么问题来了:
1. 树结构需要添加和删除结点,数组存储是否足够灵活?
答:树经常需要动态的插入和删除结点,数组存储肯定不够灵活。
2. 每个结点的子节点可以有多个,如何存储?
答:看下面
树的存储结构:
1. 利用链表组织树中的各个结点
2. 链表中的前后关系不代表结点间的逻辑关系
3. 结点的逻辑关系由child数据域描述
4. child数据域保存其他结点的存储地址
树结点结构体:
typedef struct _tag_GTreeNode GTreeNode;
struct _tag_GTreeNode
{
GTreeData* data;//用于保存数据
GTreeNode* parent;//指向双亲的指针
LinkList* child;//链表用于存储多个孩子的地址,
};
链表结点结构体:
typedef struct _tag_TLNode TLNode;
struct _tag_TLNode
{
LinkListNode header;
GTreeNode* node;//一个指向树结点的指针
} ;
链表的结构体定义:
typedef void LinkList;
typedef struct _tag_LinkListNode LinkListNode;
struct _tag_LinkListNode
{
LinkListNode* next;//链表指针域
};
typedef struct _tag_LinkList
{
LinkListNode header;//链表头
int length;//链表长度
} TLinkList;
要维护每一个结点和双亲之间的连接,对于每一个新加进来的树节点都必须将它的parent指针指向它的双亲结点
下图中红色箭头标识部分。
图示:
链表表示形式图示:(蓝色的线)
通过蓝色线的图示部分是可以访问树中的每一个结点
那么怎么表示图中的绿色线表示的部分呢?
详细架构图:
先看最下边的是一个组织链表,组织链表里面的每个元素都有一个指针指向一个树结点
第0个元素的指针指向了根节点A,第1个元素的指针指向了结点B,第2个元素的指针
指向了结点C......
结点之间的关系如何真实的表现?
看蓝色的箭头,A的child链表有三个元素,每个元素保存的是A结点的孩子的地址(也就是指向BCD的指针)
通用树结构实现的一种模型!是不是很神奇!反正第一个想出这样的人真的好牛逼啊!
最后总结:1. 上面的树结构是一种通用树的数据结构
2. 利用链表组织树结点能够便利的存取结点,但是链表的维护具有一定的复杂性
3. 树结构的非线性特性和递归定义的特性是树结构难度较大的根本原因