树的存储结构

双亲存储结构

● 做法

        • 一种顺序存储结构 , 用一组连续空间存储树的所有节点,

        • 同时在每个节点中附设一个伪指针指示其双亲节点的位置

        • 按顺序依次存储 , 逐层逐个节点存储在数组里面

● 定义存储结构

        

typedef struct
{

    //定义数据区
    ElemType data;
    //指向其双亲在数组中的位置
    int parent;

}PTree[MaxSize];

孩子链表存储结构

● 方法

• 存储每个节点的值 , 以及所有孩子的链接

• 按树的度 ( 即树中所有节点度的最大值 ) 设计节点的孩子节点指针域个数

• 从根节点起 , 逐个链接其子节点

● 结构定义 

typedef struct node
{
    //存储数据
    ElemType data;
    //存储其孩子的指针数组
    struct node *sons[MaxSons];
}TsonNode;

// MaxSons 为最多的孩子节点个数

   孩子兄弟链存储结构

● 方法

 ● 孩子兄弟链存储结构是为每个节点设计三个域

        • 一个数据元素域

        • 一个该节点的第一个孩子节点指针域

        • 一个该节点的下一个兄弟节点指针域



因为每个节点可能有多个孩子 , 并且这几个孩子是兄弟 , 所以我们参考广义表的构建 , 把单个节点的孩子们 , 连成一个单链表 ,然后节点的其中一个 指针 *vp 指向 其第一个孩子 , 节点 的另一个指针 *hp  指向同级节点的兄弟

参考链接: http://t.csdn.cn/4yPjZ


注意 : 我们每一层 , 是根据一个节点的孩子进行构成单链表的 

至于 ,如果同一层有两个节点, 并且这两个节点都有子树 , 我们就要对这两个结点的孩子分别设置子单链表

在这里插入图片描述


节点的数据结构定义:

typedef struct tnode
{
    ||节点的值
    ElemType data;
    || 指向兄弟
    struct tnode *hp;
    || 指向孩子节点
    struct tnode *vp;
}TSBNode;

例: 以孩子-兄弟链作为存储结构 , 求树的高度

● 设 f(t)为树t的高度 , 有
        {    0                       , t 为NULL
f(t)= {    1                        , t 没有孩子节点
        {    max {f(p)} + 1    , t 有其他孩子(p为t的孩子)


①当传入的树 ,是空的时候 , 我们没办法算高度 , 就返回 0

②当传入的树 ,只是一个节点的时候, 其没有孩子, 我们只返回 其本身高度 1

③当传入的树 , 其有孩子的时候 , 我们就需要先把其孩子当成树, 递归求出其孩子的高度 , 然后我们再在其孩子的高度基础上 ,加上根节点的高度 1 

下面开始代码实操:

先传入树

int TreeHeigth(TSNode *t)
{

定义指向树节点的指针

TSNode *p;

定义承载最大深度的变量max  和 中间变量 m

int m,max = 0;

对上面三种情况进行判断

如果为空,返回 0

if(t==NULL)
{
	return (0);
}

如果传入的树, 只有一个根节点 ,没有孩子, 我们就返回 1

else if(t->vp == NULL)
{
    return (1);
}

剩下的一种情况 , 就是传入的树根 ,后面有孩子 , 我们就需要先算其孩子的高度

先把指针指向 树根的孩子

p = t -> vp;

然后开始把其第一个孩子当成一个树, 求出其高度 , 然后 我们再把指针指向 孩子的兄弟 ,接着算出高度 , 让几个孩子的高度先存放在 m 中 , 最大的暂存在 max 中 , 当把所有孩子遍历完的时候 (p指向NULL), 我们就可以算出其孩子的最大高度 , 然后我们返回 max+ 1 即可

while(p!=NULL)
{
	m = TreeHeight(p);
	if(max<m)
	{
		max = m;
	}
	p = p->hp;
}
return (max+1);

上面完整代码如下:

int TreeHeight(TSNode *t)	
{
	TSNode *p;
	int m,max =0;
	if(t==NULL)
	{
		return 0;
	}
	else if(t->vp == NULL)
	{
		return (1);
	}
	else
	{
		//求 t 的子树的高度m
		p = t->vp;
		while(p!=NULL)
		{
			m = TreeHeight(p);
			if(max<m)
			{
				max = m;
			}
			//遍历兄弟
			p = p->hp;
		}
		return (max+1);
	}
}

关于实现的讨论

相比二叉树 , 我们这样构建树 , 和广义表类似 ,但没广义表通用 , 没二叉树实用 , 我们这样做 ,是为了后面学习二叉树打基础 , 融汇贯通  , 所以我们这里要理解树的递归思想 ,结合上节我们广义表的构建 ,相信大家会对递归 , 链式存储有更深的理解 . 

下面把主要调试代码奉上:

框架代码:

typedef struct tnode
{
	ElemType data;	//节点的值
	struct tnode *hp;	//指向兄弟
	struct tnode *vp;	//指向孩子节点
}TSBNode;

int TreeHeight(TSNode *t);

void TreeCreate(TSNode *&t);

void TreeDisp(TSNode *t);

int main()
{
	TSNode *tree;
	TreeCreate(tree);
	TreeDisp(tree);
	printf("Height:%d\n",TreeHeight(tree));
	return 0;
}

我们此处只是构建上面的例子的树 ,仅供调试 , 理解:

#include <stdio.h>
#include <malloc.h>

typedef char ElemType;
typedef struct tnode
{
    ElemType data;  //节点的值
    struct tnode *hp;   //指向兄弟
    struct tnode *vp;   //指向孩子节点
} TSBNode;
int TreeHeight(TSBNode *t);
void TreeCreate(TSBNode *&t);
void TreeDisp(TSBNode *t);

int TreeHeight(TSBNode *t)
{
    TSBNode *p;
    int m, max = 0;
    if(t==NULL)
        return(0);
    else if(t->vp==NULL)
        return(1);
    else
    {
        //求t的子树的最大高度max
        p=t->vp;
        while(p!=NULL)
        {
            m=TreeHeight(p);
            if(max<m)
                max=m;
            p=p->hp;
        }
        return(max+1);
    }
}

int main()
{
    TSBNode *tree;
    TreeCreate(tree);
    printf("Height: %d\n", TreeHeight(tree));
    TreeDisp(tree);
    return 0;
}

void TreeCreate(TSBNode *&t)
{
    //本例仅建造说明中特定的树,以支持演示
    TSBNode *a, *b, *c, *d, *e, *f, *g;
    a = (TSBNode *)malloc(sizeof(TSBNode));
    b = (TSBNode *)malloc(sizeof(TSBNode));
    c = (TSBNode *)malloc(sizeof(TSBNode));
    d = (TSBNode *)malloc(sizeof(TSBNode));
    e = (TSBNode *)malloc(sizeof(TSBNode));
    f = (TSBNode *)malloc(sizeof(TSBNode));
    g = (TSBNode *)malloc(sizeof(TSBNode));
    a->data = 'a';
    b->data = 'b';
    c->data = 'c';
    d->data = 'd';
    e->data = 'e';
    f->data = 'f';
    g->data = 'g';
    a->vp = b;
    a->hp = NULL;
    b->vp = d;
    b->hp = c;
    c->vp = NULL;
    c->hp = NULL;
    d->vp = NULL;
    d->hp = e;
    e->vp = g;
    e->hp = f;
    f->vp = NULL;
    f->hp = NULL;
    g->vp = NULL;
    g->hp = NULL;
    t=a;  //a作为根
    return;
}

void TreeDisp(TSBNode *t)
{
    if(t!=NULL)
    {
        printf("node value: %c\n", t->data);
        printf("%c\'s first child --> ", t->data);
        TreeDisp(t->hp);
        printf("%c\'s brother(its father\'s another child) --> ", t->data);
        TreeDisp(t->vp);
    }
    else
    {
        printf("NULL\n");
    }
}

结尾 : 感谢 贺利坚老师 的b站课程 .

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值