您的位置:首页 > 其它

树的基本结构,以及利用链表实现树的各项操作(创建、添加/删除/打印树节点、销毁等等)

2018-01-26 20:04 1096 查看
树:

n个结点的有限集合,n = 0时称为空树。在非空树中,有且仅有一个根结点(root),根的子树互不相交。

单个树节点的度:其所拥有的子结点的数目。

树的度:其内所有子结点的度的最大值。

内部结点:除了根结点之外的分支结构。

叶结点:度为0的结点。

结点间的关系:

孩子(儿子):一个结点的直接后继称为该结点的孩子结点。该结点称为孩子结点的双亲结点。

子孙(孙子):一个结点的孩子的孩子。给结点称为子孙的祖先。

兄弟:同一个双亲的孩子结点之前互称兄弟。

堂兄弟: 双亲在同一层的结点互为堂兄弟。

结点的层次:

根结点:第一层。

根结点的孩子:第二层。

依次往下延伸

树的深度:树中结点的最大层次称为树的深度。

树的实例代码

树的头文件

#ifndef __TREE_H__
#define __TREE_H__

#include "error.h"

struct _treeNode;//为下面孩子结点类型直接用树结点指针做声明

//孩子结点链表的类型(存放孩子地址的结构体)
typedef struct _childNode
{
struct _treeNode *childNode;//指向孩子
struct _childNode *next;//指向下一个存放孩子结点地址的结构体
}ChildNode;

//树节点类型
typedef char TreeData;
typedef struct _treeNode
{
TreeData data;//具体数据
struct _treeNode *parent;//指向父亲
struct _treeNode *next;  //指向下个树节点(PS:树内的所有结点都是用链表连起来)
struct _childNode *childList;//指向孩子链表的头结点
int degree;//结点的度
}TreeNode;

//树
typedef struct _tree
{
struct _treeNode *head;//指向树链表的头结点(头结点指向树中的结点)
int len;//树的结点个数
}Tree;

//定义一个函数指针类型
typedef void (*TreePrint)(TreeNode* node);

Tree* Create_Tree();

//添加树节点
int Insert_Tree(Tree*tree, TreeData data, int pos);
/*
pos代表要插入结点父亲结点的位置
约定:
1 新插入的结点插入在当前父亲结点所有孩子的右边
2 根结点的位置是 0
*/

//打印树节点
void Display(Tree*tree, TreePrint pFunc);

//删除树节点
int Delete(Tree*tree, int pos, TreeData *x);

//获取树节点数据
int Tree_Get(Tree*tree, int pos, TreeData *x);

//清空树节点
int Tree_Clear(Tree*tree);

//销毁树
void Tree_Destory(Tree*tree);

//获取树的根结点地址
TreeNode* Tree_Root(Tree* tree);

//树结点总数
int Tree_Count(Tree* tree);

//树高
int Tree_Height(Tree* tree);

//树的度(最大的度)
int Tree_Degree(Tree* tree);

#endif// __TREE_H__

编程实现对树的操作

#include "tree.h"
#include <stdlib.h>

Tree* Create_Tree()
{
//创建树
Tree* tree = (Tree*)malloc(sizeof(Tree)/sizeof(char));
if (NULL == tree)
{
errno = MALLOC_ERROR;
return NULL;
}

//给树节点链表创建头结点(不在树内)
tree->head = (TreeNode*)malloc(sizeof(TreeNode)/sizeof(char));
if (NULL == tree->head)
{
errno = MALLOC_ERRO
4000
R;
free(tree);//防止内存泄漏,头结点创建失败不能使用树需要释放之前创建的树
return NULL;
}
//tree->head为树的头结点指针,指向类型为树节点的类型
tree->head->parent = NULL;//无需使用头结点内的parent,置空
tree->head->childList = NULL;//无需使用头结点内的childList,置空
tree->head->next = NULL;//表示树内没有结点

tree->len = 0;//空树情况下,树节点为0
//printf("ok");
return tree;
}

//添加树节点
int Insert_Tree(Tree*tree, TreeData data, int pos)
{
if (NULL == tree || pos < 0 || pos > tree->len)
{
errno = ERROR;
return FALSE;
}

if (pos != 0 && tree->len == pos)
{
errno = ERROR;
return FALSE;
}
//一 创建新的树节点(结点内有5要素)
TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode)/sizeof(char));
if (NULL == node)
{
errno = MALLOC_ERROR;
return FALSE;
}
//1)新添结点的数据
node->data = data;
//2)新结点内next的指向
node->next = NULL;//新结点放末尾;

//3)创建新结点的孩子结点链表的头结点
node->childList = (ChildNode*)malloc(sizeof(ChildNode)/sizeof(char));
if (NULL == node->childList)
{
errno = MALLOC_ERROR;
free(node);
return FALSE;
}
node->childList->next = NULL;
node->childList->childNode = NULL;//子链表头结点不需要用到孩子

//4)度
node->degree = 0;

//5)/二 找父结点
int i;
TreeNode* parent = tree->head->next;//指向当前树内的第一个结点
for (i = 0; i < pos; i++)
{
parent = parent->next;//parent->next指向紧跟着当前树节点(parent的指向结点)的结点
}
node->parent = parent;//parent存着父结点的地址

//三 父结点的孩子链表中加入一个结点
if (NULL != parent)
{
//新建一个孩子结点
ChildNode* childnode = (ChildNode*)malloc(sizeof(ChildNode)/sizeof(char));
if (NULL == childnode)
{
errno = MALLOC_ERROR;
free(node->childList);//释放子链表头结点
free(node);//释放新建的树节点
return FALSE;
}
childnode->childNode = node;
childnode->next = NULL;//新建子结点放子链表最后

//插入到子链表中
ChildNode* tmp = parent->childList;//子链表的头结点
while (tmp->next)
{
tmp = tmp->next;
}//最后指向原先最后一个子结点
tmp->next = childnode;
parent->degree += 1;//父的度加1
}

//四 新建树节点插到树链表的末尾
TreeNode* tmp = tree->head;
while (tmp->next)
{
tmp = tmp->next;
}

tmp->next = node;
tree->len += 1;

return TRUE;
}

//递归打印结点
void r_display(TreeNode* node, int gap, TreePrint pFunc)//gap为父子结点之间的间距
{
if (NULL == node)
{
errno = MALLOC_ERROR;
return;
}

//打印距离前一个结点的距离
int i;
for (i = 0; i < gap; i++)
{
putchar('-');
}

//printf("%c\n", node->data);

pFunc (node);

ChildNode* child = node->childList->next;//指向子链表的第一个结点

//打印该结点的孩子
while(child)
{
r_display(child->childNode, gap+4, pFunc);
child = child->next;
}
return;
}

//显示
void Display(Tree*tree, TreePrint pFunc)
{
if (NULL == tree)
{
errno = MALLOC_ERROR;
return;
}

r_display(tree->head->next, 0, pFunc);//调用递归打印
}

//递归删除结点
void r_delete(Tree *tree, TreeNode *node)
{
if (NULL == tree || NULL == node)
return;
//一 从树链表里移除这个结点,需找到该结点的前一个结点
TreeNode* tmp = tree->head;
while (tmp->next)
{
if (tmp->next == node)//tmp指向结点的下一个结点是要删的结点
{
tmp->next = node->next;//让tmp指向结点跳过要删结点,指向下下个结点
tree->len --;
break;
}
tmp = tmp->next;
}

//二 将其兄弟链表中(其父亲的子链表)指向他的结点删除
TreeNode* parent = node->parent;//新建指针parent指向要删结点的父亲

if (NULL != parent)//有父情况
{
ChildNode* tmp = parent->childList;//tmp指向兄弟链表的头结点
while (tmp->next)
{
if (tmp->next->childNode == node)//tmp->next->childNode为兄弟链表中指向孩子本身的指针
{
ChildNode* p = tmp->next;//将子链表中指代表要删结点的结点地址给p
tmp->next = p->next;//跳过子链表中指代表要删结点的结点,连接后面的
free(p);
parent->degree--;//父结点的度-1;
break;
}
tmp = tmp->next;
}
}

//三 将要删结点的子节点删了
ChildNode* child = node->childList->next;//要删结点的子链表里的第一个结点
while (child)
{
ChildNode* pchild = child->next;//保存子链表的结点地址
r_delete(tree, child->childNode);
child = pchild;
}

free (node->childList);//释放子链表头结点
free (node);//释放之前开辟要删结点的空间
}

//删结点
int Delete(Tree*tree, int pos, TreeData *x)
{
if (NULL == tree || pos < 0 || pos > tree->len)
{
errno = ERROR;
return FALSE;
}

if (pos != 0 && tree->len == pos)
{
errno = ERROR;
return FALSE;
}

//找结点
int i;
TreeNode* current = tree->head->next;//指向当前树内的第一个结点
for (i = 0; i < pos; i++)
{
current = current->next;//最后current指向要找结点
}
*x = current->data;

r_delete(tree, current);

return TRUE;
}

int Tree_Get(Tree*tree, int pos, TreeData *x)
{
if (NULL == tree || pos < 0 || pos > tree->len)
{
errno = ERROR;
return FALSE;
}

if (pos != 0 && tree->len == pos)
{
errno = ERROR;
return FALSE;
}

//找结点
int i;
TreeNode* current = tree->head->next;//指向当前树内的第一个结点
for (i = 0; i < pos; i++)
{
current = current->next;//最后current指向要找结点
}
*x = current->data;

return TRUE;
}

//清空树节点
int Tree_Clear(Tree*tree)
{
if (NULL == tree)
{
errno = MALLOC_ERROR;
return;
}

TreeData x;
return Delete(tree, 0, &x);//删除根结点就完事了
}

//销毁树
void Tree_Destory(Tree*tree)
{
if (NULL == tree)
{
errno = MALLOC_ERROR;
return;
}

Tree_Clear(tree);//清空树节点
free (tree->head);//释放树的头结点
free (tree);//释放树的结构体空间
}

//获取树的根结点地址
TreeNode* Tree_Root(Tree* tree)
{
if (NULL == tree)
{
errno = MALLOC_ERROR;
return;
}

return tree->head->next;
}

//树结点总数
int Tree_Count(Tree* tree)
{
if (NULL == tree)
{
errno = MALLOC_ERROR;
return;
}

return tree->len;
}

//算树高
int r_height(TreeNode* node)
{
if (NULL == node)
return 0;

int subHeight = 0;
int max = 0;
//如果有子结点
ChildNode* child = node->childList->next;
while (child)
{
subHeight = r_height(child->childNode);
if (subHeight > max)//选取最高的子结点长度
max = subHeight;

child = child->next;
}

return max + 1; //max从0开始需+1
}

//树高
int Tree_Height(Tree* tree)
{
if (NULL == tree)
{
errno = MALLOC_ERROR;
return;
}

int height = r_height(tree->head->next);

return height;
}

//递归算树的度
int r_degree(TreeNode* node)
{
if (NULL == node)
return 0;
int max = node->degree;//先假设根结点的度为最大
int subDegree = 0;
//如果有子结点
ChildNode* child = node->childList->next;
while (child)
{
subDegree = r_height(child->childNode);
if (subDegree > max)//选取度最大的子结点的度
max = subDegree;

child = child->next;
}

return max;
}

//树的度(最大的度)
int Tree_Degree(Tree* tree)
{
if (NULL == tree)
{
errno = MALLOC_ERROR;
return;
}

int degree = r_degree(tree->head->next);

return degree;
}


主函数,实践调试操作

#include <stdio.h>
#include "tree.h"

void printA(TreeNode* node)
{
printf("%c\n", node->data);
}

int main()
{
Tree *tree = Create_Tree();
if (tree == NULL)
{
myError("Create_Tree");
return -1;
}
//printf("ok");
Insert_Tree(tree, 'A', 0);
Insert_Tree(tree, 'B', 0);
Insert_Tree(tree, 'C', 0);
Insert_Tree(tree, 'D', 0);
Insert_Tree(tree, 'E', 1);
Insert_Tree(tree, 'F', 1);
Insert_Tree(tree, 'H', 3);
Insert_Tree(tree, 'I', 3);
Insert_Tree(tree, 'J', 3);
Insert_Tree(tree, 'Z', 0);
Insert_Tree(tree, 'O', 9);
//Insert_Tree(tree, 'U', 8);加上后树高为4
//printf("ok");

Display(tree, printA);
/*
printf ("删除B\n");
TreeData x;
Delete(tree, 1, &x);
Display(tree, printA);
*/

TreeData x;
printf ("height = %d\n", Tree_Height(tree));
printf ("degree = %d\n", Tree_Degree(tree));

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐