树的存储结构

news2024/11/22 14:52:56

双亲存储结构

● 做法

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

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

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

● 定义存储结构

        

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站课程 .

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/5215.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

对象的比较(上)PriorityQueue中的底层源码解析

作者&#xff1a;~小明学编程 文章专栏&#xff1a;Java数据结构 格言&#xff1a;目之所及皆为回忆&#xff0c;心之所想皆为过往 目录 问题引入 offer() 扩容 构造方法 grow() siftUp() siftUpComparable&#xff08;&#xff09; 问题引入 问题是这样的&#xff0c…

LeetCode ——160. 相交链表,142. 环形链表 II

✅<1>主页&#xff1a;C语言的前男友 &#x1f4c3;<2>知识讲解&#xff1a;LeetCode经典链表笔试题目 &#x1f525;<3>创作者&#xff1a;C语言的前男友 ☂️<4>开发环境&#xff1a;Visual Studio 2022 &#x1f3e1;<5>系统环境&#xff1a;…

机器学习笔记 十八:基于3种方法的随机森林模型分析房屋参数重要性

这里写自定义目录标题1. 探索性数据分析1.1 数据集分割&#xff08;训练集、测试集&#xff09;1.2 模型拟合2. 特征重要性比较2.1 Gini Importance2.2 Permutation Importance2.3 Boruta3. 特征比较3.1 Gini Importance3.2 Permutation Importance3.3 Boruta4. 模型比较将机器…

算法设计与分析复习(一)

判断题&#xff1a; 如果一个NP完全问题能在多项式时间内得到解决&#xff0c;那么NP中的每一个问题都能在多项式时间内求解。&#xff08;T&#xff09;可以用如下方法来证明某结论X成立&#xff1a;先假设X不成立&#xff0c;在此假设基础上推出X成立&#xff0c;则可以证明…

8、Bean的循环依赖问题

8.2 singleton下的set注入产生的循环依赖(解决) A对象中有B属性。B对象中有A属性。这就是循环依赖。我依赖你&#xff0c;你也依赖我。 比如&#xff1a;丈夫类Husband&#xff0c;妻子类Wife。Husband中有Wife的引用。Wife中有Husband的引用。 Husband Data public class …

覆盖变量漏洞

变量覆盖&#xff1a; \> $a 1; $b 2; $a 3; echo $a; > 输出3 .代码从上而下执行&#xff0c;$a被多次定义 常见变量覆盖导致漏洞的函数 \> 经常导致变量覆盖漏洞场景有&#xff1a; $$使用不当 EXTRACT()函数使用不当 PARSE_STR()函数使用不当IMPORT_REQUEST_…

c语言指针(深入了解指针)

前沿&#xff1a; 有人曾说过不会指针等于没有学习c语言&#xff0c;而我也是非常认同这个观点的&#xff0c;要想学习好c语言&#xff0c;指针是比不可缺少的&#xff0c;如果指针学不会c语言也就没办法学好&#xff0c;而向如此越重要的东西越比较难学&#xff0c;但难学并不…

Qt基础之四:Qt信号与槽机制原理及优缺点

信号和插槽用于对象之间的通信。信号和槽机制是Qt的核心特性&#xff0c;可能也是与其他框架提供的特性最大不同的部分。Qt的元对象系统使信号和槽成为可能。 一.简介 在GUI编程中&#xff0c;当我们改变一个控件&#xff0c;通常希望其他控件被通知到。更一般的&#xff0c;…

【优化覆盖】基于matlab果蝇算法求解无线传感器覆盖优化问题【含Matlab源码 2215期】

一、⛄果蝇算法 果蝇优化算法(Fruit Fly Optimization Algorithm, FOA) 是台湾学者潘文超经过研究发现, 并于2011年提出的一种新型智能优化算法, 它具有很好的全局优化性能, 能够解决很多的优化求解问题.果蝇有着优于其它生物的感官知觉, 特别是视觉与嗅觉, 依靠灵敏的嗅觉, 果…

Linux服务器被入侵后的排查思路(应急响应思路)

目录Linux-暴力破解、替换ps命令并留存后门事件复现一、事件背景二、应急响应过程排查crontab后门排查是否有命令被替换响应过程回顾三、事件还原查看后门排查安全日志Linux-暴力破解、替换ps命令并留存后门事件复现 一、事件背景 服务器疑似被入侵&#xff0c;与恶意IP进行通信…

手眼标定笔记

文章目录基本介绍&#xff1a;坐标系变换运算规则&#xff1a;关系运算说明&#xff1a;坐标系运算规则一&#xff1a;坐标系运算规则二&#xff1a;齐次坐标系&#xff1a;齐次坐标系下的坐标变换&#xff1a;眼在手外&#xff1a;眼在手内&#xff1a;解方程&#xff1a;- Ta…

Spring学习第4篇:Spring 的依赖注入

大家家好&#xff0c;我是一名网络怪咖&#xff0c;北漂五年。相信大家和我一样&#xff0c;都有一个大厂梦&#xff0c;作为一名资深Java选手&#xff0c;深知Spring重要性&#xff0c;现在普遍都使用SpringBoot来开发&#xff0c;面试的时候SpringBoot原理也是经常会问到&…

数据结构 | 单链表

… &#x1f333;&#x1f332;&#x1f331;本文已收录至&#xff1a;数据结构 | C语言 更多知识尽在此专栏中!文章目录&#x1f333;前言&#x1f333;正文&#x1f332;链表打印与销毁&#x1fab4;打印&#x1fab4;销毁&#x1f332;尾部插入与删除&#x1fab4;节点申请&…

javaweb JAVA JSP销售系统购物系统jsp购物系统购物商城系统源码(jsp电子商务系统)网上在线销售

JSP销售系统购物系统jsp购物系统购物商城系统源码&#xff08;jsp电子商务系统&#xff09;网上在线销售

Linux基础 - 虚拟化介绍(KVM)

‍‍&#x1f3e1;博客主页&#xff1a; Passerby_Wang的博客_CSDN博客-系统运维,云计算,Linux基础领域博主 &#x1f310;所属专栏&#xff1a;『Linux基础』 &#x1f30c;上期文章&#xff1a; Linux基础 - 服务管理&#xff08;systemd&#xff09; &#x1f4f0;如觉得博…

爬取医药卫生知识服务系统的药品数据——超详细流程

爬取医药卫生知识服务系统的药品数据——超详细流程 文章目录爬取医药卫生知识服务系统的药品数据——超详细流程前言一、寻找药品数据二、爬取药品ID1.资源获取2.数据提取3.资源保存4.主函数5.总体代码三、爬取药品信息1.加载资源ID2.获取数据3.数据提取4.保存信息5.主函数6.总…

SpringBoot-属性绑定和bean属性校验

目录 属性绑定 自定义类属性绑定 第三方bean属性匹配 规则:松散绑定&#xff08;宽松绑定&#xff09; Bean属性校验 属性绑定 属性绑定&#xff1a;我们可以使用配置文件对类的属性进行赋值绑定。 自定义类属性绑定 我们自定义一个类&#xff0c;在此使用yml文件进行类…

【滤波器】基于matlab实现微波带低通高通带通滤波器设计

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

python科研做图系列之雷达图

文章目录参考资料matplotlib库画的复现一个 pyecharts的雷达图尝试在上面的基础上&#xff0c;把pyecharts 导出存为一般的png图尝试在上面的基础上&#xff0c;把pyecharts 导出存为一般的矢量图用pygal画雷达图参考资料 参考知乎 CSDN给出了一些参数 matplotbib库雷达图官网 …

Python实现九九乘法表的几种方式,入门必备案例~超级简单~

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 们在学习Python的过程中需要不断的积累和练习&#xff0c;这样才能够走的更远&#xff0c; 今天一起来学习怎么用Python写九九乘法表~ 第一种方法&#xff1a;for-for 代码&#xff1a; for i in range(1, 10):for j in…