树的存储结构:
无法直接用数组表示树的逻辑结构;
但可以设计结构体数组对结点间的关系进行表述;
利用链表组织树中的各个结点;
链表中的前后关系不代表结点间的逻辑关系;
结点的逻辑关系由child 数据域描述;
child 数据域保存其他结点的存储地址;
树中每一个结点包含一个指向父结点的指针;
树结点在链表中的位置不代表树的任何逻辑关系;
利用链表组织树结点
能够便利的存取结点
链表的维护具有一定复杂性
树结构的非线性特性和递归定义的特性是树结构实现难度较大的根本原因!!!
#include <stdio.h>
#include <malloc.h>
#include "GTree.h"
#include "LinkList.h"
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;
};
static void recursive_display(GTreeNode* node, GTree_Printf* pFunc, int format, int gap, char div)//递归显示函数,对于外界是隐蔽的,加static,div是分隔符标识
//format表示它的孩子相对于它缩进几个空格;
//函数指针
{
int i = 0;
if( (node != NULL) && (pFunc != NULL) )
{
for(i=0; i<format; i++)
{
printf("%c", div);//打印缩进
}
pFunc(node->data);//打印结点中的值
printf("\n");
for(i=0; i<LinkList_Length(node->child); i++)//打印孩子,遍历孩子链表
{
TLNode* trNode = (TLNode*)LinkList_Get(node->child, i);//get孩子
recursive_display(trNode->node, pFunc, format + gap, gap, div);//递归打印,gap表示间隔打印数
}
}
}
static void recursive_delete(LinkList* list, GTreeNode* node)//递归删除函数
{
if( (list != NULL) && (node != NULL) )
{
GTreeNode* parent = node->parent;
int index = -1;//查找变量index
int i = 0;//循环变量i
for(i=0; i<LinkList_Length(list); i++)//先删除组织链表中的元素
{
TLNode* trNode = (TLNode*)LinkList_Get(list, i);
if( trNode->node == node )
{
LinkList_Delete(list, i);
free(trNode);
index = i;
break;
}
}
if( index >= 0 )
{
if( parent != NULL )//如果有父亲,将该结点其从双亲结点中child链表中删除
{
for(i=0; i<LinkList_Length(parent->child); i++)
{
TLNode* trNode = (TLNode*)LinkList_Get(parent->child, i);
if( trNode->node == node )
{
LinkList_Delete(parent->child, i);
free(trNode);
break;
}
}
}
while( LinkList_Length(node->child) > 0 )将结点自己的孩子链表也删除
{
TLNode* trNode = (TLNode*)LinkList_Get(node->child, 0);
recursive_delete(list, trNode->node);
}
LinkList_Destroy(node->child);
free(node);
}
}
}
static int recursive_height(GTreeNode* node)//欲求树的高度,先求子树的高度
{
int ret = 0;
if( node != NULL )
{
int subHeight = 0;
int i = 0;
for(i=0; i<LinkList_Length(node->child); i++)
{
TLNode* trNode = (TLNode*)LinkList_Get(node->child, i);
subHeight = recursive_height(trNode->node);//子树的高度
if( ret < subHeight )//一边求子树高度,一边返回最大值
{
ret = subHeight;
}
}
ret = ret + 1;
}
return ret;
}
static int recursive_degree(GTreeNode* node)//同求树的高度思维方式一样
{
int ret = -1;
if( node != NULL )
{
int subDegree = 0;
int i = 0;
ret = LinkList_Length(node->child);
for(i=0; i<LinkList_Length(node->child); i++)
{
TLNode* trNode = (TLNode*)LinkList_Get(node->child, i);
subDegree = recursive_degree(trNode->node);
if( ret < subDegree )
{
ret = subDegree;
}
}
}
return ret;
}
GTree* GTree_Create()
{
return LinkList_Create();//返回树结构中组织链表
}
void GTree_Destroy(GTree* tree)
{
GTree_Clear(tree);//释放空间之前clear结点
LinkList_Destroy(tree);//催毁单链表
}
void GTree_Clear(GTree* tree)
{
GTree_Delete(tree, 0);
}
int GTree_Insert(GTree* tree, GTreeData* data, int pPos)//数据data插入树中,pPos表示插入结点的双亲在表中的位置
{
LinkList* list = (LinkList*)tree;//最终的树是一个链表
int ret = (list != NULL) && (data != NULL) && (pPos < LinkList_Length(list));//组织链表不为空,用户插入数据不为空,插入位置小于组织链表的长度
if( ret )
{
TLNode* trNode = (TLNode*)malloc(sizeof(TLNode));//组织链表,listnode
TLNode* cldNode = (TLNode*)malloc(sizeof(TLNode));//child链表,listnode
TLNode* pNode = (TLNode*)LinkList_Get(list, pPos);//待插入结点的双亲结点
GTreeNode* cNode = (GTreeNode*)malloc(sizeof(GTreeNode));//待插入的结点
ret = (trNode != NULL) && (cldNode != NULL) && (cNode != NULL);//合法性检测
if( ret )
{
cNode->data = data;
cNode->parent = NULL;
cNode->child = LinkList_Create();//每个树节点中需要创建一个孩子链表
trNode->node = cNode;
cldNode->node = cNode;
LinkList_Insert(list, (LinkListNode*)trNode, LinkList_Length(list));//插入组织链表中
if( pNode != NULL )//检测插入结点是否为根结点
{
cNode->parent = pNode->node;//如果是给双亲结点赋值
LinkList_Insert(pNode->node->child, (LinkListNode*)cldNode, LinkList_Length(pNode->node->child));//插入孩子结点链表
}
}
else
{
free(trNode);
free(cldNode);
free(cNode);
}
}
return ret;
}
GTreeData* GTree_Delete(GTree* tree, int pos)//删除链表中的结点和双亲中的孩子链表结点
{
TLNode* trNode = (TLNode*)LinkList_Get(tree, pos);//获取删除的数据元素
GTreeData* ret = NULL;
if( trNode != NULL )
{
ret = trNode->node->data;
recursive_delete(tree, trNode->node);//树是递归定义的,删除一个结点,也应该是递归删除的
}
return ret;
}
GTreeData* GTree_Get(GTree* tree, int pos)
{
TLNode* trNode = (TLNode*)LinkList_Get(tree, pos);
GTreeData* ret = NULL;
if( trNode != NULL )
{
ret = trNode->node->data;
}
return ret;
}
GTreeData* GTree_Root(GTree* tree)
{
return GTree_Get(tree, 0);
}
int GTree_Height(GTree* tree)
{
TLNode* trNode = (TLNode*)LinkList_Get(tree, 0);
int ret = 0;
if( trNode != NULL )
{
ret = recursive_height(trNode->node);
}
return ret;
}
int GTree_Count(GTree* tree)
{
return LinkList_Length(tree);
}
int GTree_Degree(GTree* tree)
{
TLNode* trNode = (TLNode*)LinkList_Get(tree, 0);
int ret = -1;
if( trNode != NULL )
{
ret = recursive_degree(trNode->node);
}
return ret;
}
void GTree_Display(GTree* tree, GTree_Printf* pFunc, int gap, char div)//打印一棵树,遍历树中的每一个结点,既然是递归定义,那么必定也是递归遍历
{
TLNode* trNode = (TLNode*)LinkList_Get(tree, 0);//找根结点,组织链表中的第零个元素
if( (trNode != NULL) && (pFunc != NULL) )
{
recursive_display(trNode->node, pFunc, 0, gap, div);
}
}