数据结构:树的存储结构

news2024/9/27 15:17:27

学习树之前,我们已经了解了二叉树的顺序存储和链式存储,哪么我们如何来存储普通型的树结构的数据?如下图1:

在这里插入图片描述

如图1所示,这是一颗普通的树,我们要如何来存储呢?通常,存储这种树结构的数据的方法有3中:

  1. 双亲表示法。
  2. 孩子表示法。
  3. 孩子兄弟表示法。

双亲表示法

双亲表示法采用顺序表(也就是数组)存储普通树,核心思想:顺序存储各个节点的同时,给各个节点附加一个记录其父节点位置的变量。

注意:根结点没有父节点,因此根结点记录父节点位置的变量一般为-1。

例如,采用双亲表示法存储图1中的普通树,其存储状态如图2所示:

在这里插入图片描述

图2存储普通树转化为代码为:

#define MAX_SIZE 100//定义树中结点最大数量
typedef struct node{
    char data;//树中结点的数据
    int parent;//结点的父节点再数组中的位置下标
};

typedef struct {
    node arr[MAX_SIZE];//存放树中所有结点
    int n;//节点数
}Tree;

因此,存储图1中普通树的实现代码为:

#include "iostream"

using namespace std;
#define MAX_SIZE 100//定义树中结点最大数量
typedef struct node{
    char data;//树中结点的数据
    int parent;//结点的父节点再数组中的位置下标
};

typedef struct {
    node arr[MAX_SIZE];//存放树中所有结点
    int n;//节点数
}Tree;

Tree Init(Tree tree){
    cout << "请输入结点个数:" << endl;
    cin >> tree.n;
    cout << "请输入结点的值其双亲位于数组中的位置下标:" << endl;
    for(int i = 0; i < tree.n; i++){
        cin >> tree.arr[i].data >> tree.arr[i].parent;
    }
    return tree;
}

void FindParent(Tree tree){
    char a;
    bool IsFind = false;
    cout << "请输入要查询的节点值:" << endl;
    cin >> a;
    for(int i = 0; i < tree.n; i++){
        if(tree.arr[i].data == a){
            IsFind = true;
            cout << a << "的父节点为" << tree.arr[tree.arr[i].parent].data << ",存储位置下标为" << tree.arr[i].parent << endl;
            break;
        }
    }
}
int main(){
    Tree tree;
    for(int i = 0; i < MAX_SIZE; i++){
        tree.arr[i].parent = -1;
        tree.arr[i].data = ' ';
    }
    tree = Init(tree);
    FindParent(tree);
    return 0;
}

程序运行实例:

请输入结点个数:
10
请输入结点的值其双亲位于数组中的位置下标:
R -1
A 0
B 0
C 0
D 1
E 1
F 3
G 6
H 6
K 6
请输入要查询的节点值:
C
C的父节点为R,存储位置下标为0

孩子表示法

孩子表示法是采用“顺序表+链表”的组合结构,其存储过程是:从树的根结点开始,使用顺序表依次存储树中各个节点,需要注意的是,与双亲表示法不同,孩子表示法会给各个节点配备一个链表,用于存储各个节点的孩子节点位于顺序表中的位置。

如果孩子没有叶子节点,则该节点的链表为空链表。

例如,使用孩子表示法存储图3a中的树,则最终存储状况如图3b所示:

在这里插入图片描述

代码实现如下:

#include "iostream"

using namespace std;
#define MAX_SIZE 100//定义树中结点最大数量
typedef struct node{
    int child;//链表中每个结点存储的是数据再数组中存储的位置下标
    struct node *next;
};
typedef struct {
    char data;//结点的数据
    node * FirstChild;//孩子链表的头节点
}box;
typedef struct {
    box arr[MAX_SIZE];//存放树中所有结点
    int n, r;//节点数和树根的位置
}Tree;

Tree Init(Tree tree){
    cout << "请输入结点个数:";
    cin >> tree.n;
    for(int i = 0; i < tree.n; i++){
        cout << "输入第" << i + 1 << "个节点的值:" ;
        cin >> tree.arr[i].data;
        tree.arr[i].FirstChild = new node;
        tree.arr[i].FirstChild->next = NULL;
        cout << "输入结点" << tree.arr[i].data << "的孩子结点的数量:";
        int num = 0;
        cin >> num;
        if(num != 0){
            node *p = tree.arr[i].FirstChild;
            for(int j = 0; j < num; j++){
                node *ptr = new node;
                ptr->next = NULL;
                cout << "输入第" << j + 1 << "个孩子节点在顺序表中的位置: ";
                cin >> ptr->child;
                p->next = ptr;
                p = p->next;
            }
        }
    }
    return tree;
}

void FindKids(Tree tree, char ch){
    bool IsFind = false;
    for(int i = 0; i < tree.n; i++){
        if(tree.arr[i].data == ch){
            node *p = tree.arr[i].FirstChild->next;
            while(p){
                IsFind = true;
                cout << tree.arr[p->child].data;
                p = p->next;
            }
            break;
        }
    }
}
int main(){
    Tree tree;
    tree.r = 0;//默认根结点的下标为0
    for(int i = 0; i < MAX_SIZE; i++){
        tree.arr[i].FirstChild = NULL;
    }
    tree = Init(tree);
    FindKids(tree, 'F');//找出结点F的所有孩子结点
    return 0;
}

程序运行结果如下:

请输入结点个数:10
输入第1个节点的值:R
输入结点R的孩子结点的数量:3
输入第1个孩子节点在顺序表中的位置: 1
输入第2个孩子节点在顺序表中的位置: 2
输入第3个孩子节点在顺序表中的位置: 3
输入第2个节点的值:A
输入结点A的孩子结点的数量:2
输入第1个孩子节点在顺序表中的位置: 4
输入第2个孩子节点在顺序表中的位置: 5
输入第3个节点的值:B
输入结点B的孩子结点的数量:0
输入第4个节点的值:C
输入结点C的孩子结点的数量:1
输入第1个孩子节点在顺序表中的位置: 6
输入第5个节点的值:D
输入结点D的孩子结点的数量:0
输入第6个节点的值:E
输入结点E的孩子结点的数量:0
输入第7个节点的值:F
输入结点F的孩子结点的数量:3
输入第1个孩子节点在顺序表中的位置: 7
输入第2个孩子节点在顺序表中的位置: 8
输入第3个孩子节点在顺序表中的位置: 9
输入第8个节点的值:G
输入结点G的孩子结点的数量:0
输入第9个节点的值:H
输入结点H的孩子结点的数量:0
输入第10个节点的值:K
输入结点K的孩子结点的数量:0
找出节点 F 的所有孩子节点:GHK

使用孩子表示法存储的树结构,正好和双亲表示法相反,适用于 查找某个节点的孩子结点,不适用于查找父节点。

其实,我们也可以将双亲表示法和孩子表示法相互结合,就可以得到如图4所示:

在这里插入图片描述

使用图4结果存储普通树,技能快速找到指定节点的父节点,也能快速找到指定结点的孩子结点。

孩子兄弟表示法

孩子兄弟表示法:采用的是链式存储结构,其思想是,从树的根结点开始,依次用链表存储各个节点的孩子结点和兄弟节点。

所以,该链表中的结点包括3个部分,如图5所示:

  1. 结点的值。
  2. 指向孩子结点的指针。
  3. 指向兄弟结点的指针。

在这里插入图片描述

代码表示如下:

typedef struct node{
    char data;
    struct node *ForstChild, *NextSibling;
};

还是以图1为例,使用孩子兄弟表示法进行存储的结果如图所示:

在这里插入图片描述

由图我们可以发现,孩子兄弟表示法是用二叉树的左子树存储树的孩子结点,用右子树来存储兄弟结点

孩子兄弟表示法可以作为将普通树转化为二叉树的最有效的方法,同时这个方法也被称之为“二叉树表示法”或者”二叉链表表示法

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

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

相关文章

vmware磁盘组使用率100%处理

今天在外办事时&#xff0c;有客户发过来一个截图&#xff0c;问vmware 磁盘组空间使用率100%咋办&#xff1f;如下图&#xff1a; 直接回复&#xff1a; 1、首先删除iso文件等 2、若不存在ISO文件等&#xff0c;找个最不重要的虚拟机直接删除&#xff0c;删除后稍等就会释放…

数据分析-关于指标和指标体系

一、电商指标体系 二、指标体系的作用 三、统计学中基本的分析手段

记一次解决FTPS上传的文件为空的问题

最近公司的vsftpd文件服务由之前的FTP传输改成了FTPS的&#xff0c;虽然代码做了相应的调整&#xff0c;但是始终有个问题&#xff0c;就是在服务器上文件创建成功了&#xff0c;名称也是正确的&#xff0c;可是一看大小确是0&#xff0c;于是查看日志 用项目上传的始终是失败&…

mybatis-config.xml-配置文件详解

文章目录 mybatis-config.xml-配置文件详解说明文档地址:配置文件属性解析properties 属性应用实例 settings 全局参数定义应用实例 typeAliases 别名处理器举例说明 typeHandlers 类型处理器environments 环境environment 属性应用实例 mappers配置 mybatis-config.xml-配置文…

vue除了子组件抛出的额外参数,父组件如何传递额外参数

以下为一个简单的demo,只为记录一下 很多时候如果我们多个地方使用同一函数时,往往就需要进行判断了,但是组件库返回的函数携带的参数没办法让我们做多余的判断 这时就需要传递多余的参数了 方法一 使用箭头函数 <template><div><el-switchv-model"value&…

2023年中秋节国庆节是几月几号开始休假国庆中秋双节放假几天?

2023年中秋节国庆节是几月几号开始休假国庆中秋双节放假几天&#xff1f; 2023年中秋节与国庆节双节相遇一起放假长大8天; 2023年中秋节与国庆节放假时间是从2023年9月29日开始至10月6日共计8天&#xff0c;10月7日、10月8日补班&#xff1b; 2023年中秋节怎么购买月饼省钱又…

Jenkins配置自动化构建的几个问题

在创建构建任务时&#xff0c;填写git远程仓库地址时&#xff0c;出现以下报错 解决此报错先排查一下linux机器上的git版本 git --version 如果git 版本过低&#xff0c;可能会导致拉取失败&#xff0c;此时需要下载更高的git版本。 参考 Git安装 第二个解决办法报错信息中…

Ansible的脚本 --- playbook 剧本

文章目录 一、playbook剧本的组成创建剧本运行playbook二、定义、引用变量三、指定远程主机sudo切换用户四、when条件判断五、迭代Templates 模块tags 模块 一、playbook剧本的组成 playbooks 本身由以下各部分组成 &#xff08;1&#xff09;Tasks&#xff1a;任务&#xff0…

SpringCloudAlibaba之整合openFeign

一.openFeign的入门使用&#xff08;4步&#xff09; 1.引入openFeign的依赖包&#xff0c;记得父项目中要加上SpringCloud依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactI…

VSCode新手快速下载、安装、使用

目录 下载 安装 1、许可协议 2、安装位置 3、开始菜单文件夹 4、附加任务 5、确认安装 6、完成 使用 1、汉化&#xff08;设置中文界面&#xff09; 2、设置 下载 进入VSCode官方页面&#xff0c;选择自己系统对应的下载链接VSCode默认提供的User Installer版本。但…

【解决】el-tree报Cannot read property ‘getCheckedKeys‘ of undefined

如果你报错 Cannot read property getCheckedKeys of undefined 或者 Cannot read property getCheckedNodes of undefined 只要在你的在<el-tree>上加个这个&#xff0c;就可以了 ref"tree"

某圆形变电站三维建模模型-glb格式-三维漫游-三维可视化-三维模拟巡检

资源介绍 某个圆形变电站的三维建模模型&#xff0c;glb格式&#xff0c;适用于three.js开发测试&#xff0c;可用来做一些三维室内漫游测试、室内导航测试和三维模拟巡检测试 资源下载地址

联想拯救者笔记本切换独显直连游戏体验翻倍、火力全开“嗨”起来

最早的游戏本是由独显负责图形运算&#xff0c;然后直接向屏幕输出所有画面的。但独显负责所有工作&#xff0c;无时无刻都在耗电&#xff1b;撇开游戏模式下高负载的功耗不谈&#xff0c;即便在省电模式下功耗也比核显高得多。 英伟达发布的Optimus混合输出技术&#xff0c;在…

马哈鱼 v.sqlflow.cn 上线试用

马哈鱼数据血缘工具从2023年8月开始开通国内云版本的服务&#xff0c;相比国外版本&#xff0c;访问速度有很大的提升&#xff0c;访问域名为https://v.sqlflow.cn 2023年8月和9月注册的用户可免费获得价值 3000 元的一年高级帐户&#xff0c;可以使用马哈鱼数据血缘工具全部付…

Caffeine本地缓存技术

说明&#xff1a;Caffeine是本地缓存方案&#xff0c;在所有本地缓存中命中率最佳&#xff0c;参考下图&#xff08;引自http://t.csdn.cn/oiQlH&#xff09;&#xff0c;本文介绍Caffeine在SpringBoot项目中的应用。 使用 例如现在有两个接口&#xff0c;一个查询所有用户&am…

Spring 6【数据校验Validation、JSR 303 和 Hibernate 实现】(十三)-全面详解(学习总结---从入门到深化)

目录 数据校验Validation 2.JSR 303 和 Hibernate 实现 数据校验Validation 1.数据校验介绍 数据校验分为客户端数据校验和服务端数据校验。都是为了保证数据完整性的。 客户端数据校验直接使用客户端脚本校验即可。例如在B/S模型项目中&#xff0c;可以选择使用JavaScript…

Flowable中间事件-中间信号捕获事件

定义 信号中间事件分为 Catching 事件和 Throwing 事件&#xff0c;即信号中间捕获事件&#xff08;Signal Intermediate Catch Event&#xff09;和信号中间抛出事件&#xff08;Signal Intermediate Throwing Event&#xff09;。 当流程执行到信号中间捕获事件时就会中断在…

ESP32(MicroPython) 四足机器人(一)

最近决定研究一下四足机器人&#xff0c;但市面上的产品&#xff0c;要么性价比低&#xff0c;要么性能达不到要求。本人就另外买了零件&#xff0c;安装到之前的一个麦克纳姆轮底盘的底板上。&#xff08;轮子作为装饰&#xff0c;使用铜柱固定&#xff09; 舵机使用MG996R&a…

Stability AI推出Stable Diffusion XL 1.0,文本到图像模型

Stability AI宣布推出Stable Diffusion XL 1.0&#xff0c;这是一个文本到图像的模型&#xff0c;该公司将其描述为迄今为止“最先进的”版本。 Stability AI表示&#xff0c;SDXL 1.0能生成更加鲜明准确的色彩&#xff0c;在对比度、光线和阴影方面做了增强&#xff0c;可生成…

在 Amazon EMR 上构建实时数据湖

前言 当公司业务发展遇到瓶颈时&#xff0c;业务分析师以及决策者们总会希望通过交叉分析大量的业务数据和用户行为数据&#xff0c;以解答“为什么利润会下滑&#xff1f;”“为什么库存周转变慢了&#xff1f;”等问题&#xff0c;最终整点“干货”出来从而促进业务发展。 …