【C 数据结构】普通树

文章目录

  • 【 1. 树的双亲表示法 】
  • 【 2. 树的孩子表示法 】
  • 【 3. 树的孩子兄弟表示法 】

  • 前面学了二叉树的存储结构,本节学习如何存储具有普通树结构的数据。例如下图所示为普通树存储结构。
    在这里插入图片描述

  • 通常,存储具有普通树结构数据的方法有 3 种:

    • 双亲表示法;
    • 孩子表示法;
    • 孩子兄弟表示法;

【 1. 树的双亲表示法 】

  • 双亲表示法 采用 顺序表(也就是数组)存储普通树。其实现的核心思想是: 顺序存储各个节点的同时,给各节点附加一个记录其父节点位置的变量。而根节点没有父节点(父节点又称为双亲节点),因此 根节点记录父节点位置的变量通常置为 -1
  • 双亲表示法适用于查找某个节点的父节点
  • 例如,采用双亲表示法存储上图中普通树,其存储状态如下图 所示:
    在这里插入图片描述
  • 存储普通树的过程转化为 C 语言代码为:
#define MAX_SIZE 100	//宏定义树中结点的最大数量
typedef char ElemType;	//宏定义树结构中数据类型
typedef struct Snode
{TElemType data;		//树中结点的数据类型int parent;			//结点的父结点在数组中的位置下标
}PTNode;typedef struct
{PTNode tnode[MAX_SIZE];	//存放树中所有结点int n;					//根的位置下标和结点数
}PTree;
  • 存储上面普通树的 C 实现为:
#define _CRT_SECURE_NO_WARNINGS 1
#define MAX_SIZE 20
#include<stdio.h>
#include<stdlib.h>
typedef char ElemType;//宏定义树结构中数据类型
typedef struct Snode  //结点结构
{ElemType data;int parent;
}PNode;
typedef struct  //树结构
{PNode tnode[MAX_SIZE];int n;                 //结点个数
}PTree;PTree InitPNode(PTree tree)
{int i, j;char ch;printf("请输出节点个数:\n");scanf("%d", &(tree.n));printf("请输入结点的值其双亲位于数组中的位置下标:\n");for (i = 0; i < tree.n; i++){getchar();scanf("%c %d", &ch, &j);tree.tnode[i].data = ch;tree.tnode[i].parent = j;}return tree;
}
void FindParent(PTree tree)
{char a;int isfind = 0;printf("请输入要查询的结点值:\n");getchar();scanf("%c", &a);for (int i = 0; i < tree.n; i++) {if (tree.tnode[i].data == a) {isfind = 1;int ad = tree.tnode[i].parent;printf("%c的父节点为 %c,存储位置下标为 %d", a, tree.tnode[ad].data, ad);break;}}if (isfind == 0) {printf("树中无此节点");}
}int main()
{PTree tree;for (int i = 0; i < MAX_SIZE; i++) {tree.tnode[i].data = ' ';tree.tnode[i].parent = 0;}tree = InitPNode(tree);FindParent(tree);return 0;
}

在这里插入图片描述

【 2. 树的孩子表示法 】

  • 孩子表示法 存储普通树采用的是 顺序表+链表 的组合结构,存储过程是:从树的根节点开始,使用顺序表依次存储树中各个节点,需要注意的是,与双亲表示法不同,孩子表示法会给各个节点配备一个链表,用于存储各节点的孩子节点位于顺序表中的位置。如果节点没有孩子节点(叶子节点),则该节点的链表为空链表。
  • 使用孩子表示法存储的树结构,正好和双亲表示法相反, 适用于查找某结点的孩子结点,不适用于查找其父结点。
    在这里插入图片描述
  • C实现
#define _CRT_SECURE_NO_WARNINGS 1
#define MAX_SIZE 20
#define TElemType char
#include<stdio.h>
#include<stdlib.h>//孩子表示法
typedef struct CTNode {int child;//链表中每个结点存储的不是数据本身,而是数据在数组中存储的位置下标struct CTNode* next;
}ChildPtr;
typedef struct {TElemType data;//结点的数据类型ChildPtr* firstchild;//孩子链表的头指针
}CTBox;
typedef struct {CTBox nodes[MAX_SIZE];//存储结点的数组int n, r;//结点数量和树根的位置
}CTree;
//孩子表示法存储普通树
CTree initTree(CTree tree) 
{printf("输入节点数量:\n");scanf("%d", &(tree.n));for (int i = 0; i < tree.n; i++) {printf("输入第 %d 个节点的值:\n", i + 1);getchar();scanf("%c", &(tree.nodes[i].data));tree.nodes[i].firstchild = (ChildPtr*)malloc(sizeof(ChildPtr));tree.nodes[i].firstchild->next = NULL;printf("输入节点 %c 的孩子节点数量:\n", tree.nodes[i].data);int Num;scanf("%d", &Num);if (Num != 0) {ChildPtr* p = tree.nodes[i].firstchild;for (int j = 0; j < Num; j++) {ChildPtr* newEle = (ChildPtr*)malloc(sizeof(ChildPtr));newEle->next = NULL;printf("输入第 %d 个孩子节点在顺序表中的位置", j + 1);scanf("%d", &(newEle->child));p->next = newEle;p = p->next;}}}return tree;
}
void findKids(CTree tree, char a) {int hasKids = 0;for (int i = 0; i < tree.n; i++) {if (tree.nodes[i].data == a) {ChildPtr* p = tree.nodes[i].firstchild->next;while (p) {hasKids = 1;printf("%c ", tree.nodes[p->child].data);p = p->next;}break;}}if (hasKids == 0) {printf("此节点为叶子节点");}
}
int main()
{CTree tree;for (int i = 0; i < MAX_SIZE; i++) {tree.nodes[i].firstchild = NULL;}tree = initTree(tree);//默认数根节点位于数组notes[0]处tree.r = 0;printf("找出节点 F 的所有孩子节点:");findKids(tree, 'F');return 0;
}

在这里插入图片描述

  • 将双亲表示法和孩子表示法合二为一,既能快速找到指定节点的父节点,又能快速找到指定节点的孩子节点。存储效果如下图所示:
    在这里插入图片描述

【 3. 树的孩子兄弟表示法 】

  • 树结构中,位于同一层的节点之间互为兄弟节点。例如下图的普通树中,节点 A、B 和 C 互为兄弟节点,而节点 D、E 和 F 也互为兄弟节点。
    在这里插入图片描述
  • 孩子兄弟表示法,采用的是 链式存储结构 。其存储树的实现思想是:从树的根节点开始,依次用链表存储各个节点的孩子节点和兄弟节点。
  • 因此,该链表中的节点应包含以下 3 部分内容(如下图 所示):
    1.节点的值;
    2.指向孩子节点的指针;
    3.指向兄弟节点的指针;
    在这里插入图片描述
  • C 语言代码表示节点结构为:
#define ElemType char
typedef struct CSNode{ElemType data;struct CSNode * firstchild,*nextsibling;
}CSNode,*CSTree;
  • 以上上张图为例,使用孩子兄弟表示法进行存储的结果如图所示:
    在这里插入图片描述
  • 通过孩子兄弟表示法,任意一棵普通树都可以相应转化为一棵二叉树,换句话说, 任意一棵普通树都有唯一的一棵二叉树于其对应 。因此,孩子兄弟表示法通常又被称为 二叉树表示法二叉链表表示法

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

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

相关文章

Linux红帽(RHCE)认证学习笔记-(1)Linux 文件管理

Linux 文件管理 1. Linux下的目录结构 / 是Linux里的根目录 Linux的一级目录 /boot &#xff1a;存放的是系统的启动配置⽂件和内核⽂件/dev &#xff1a;存放的是Linux的设备⽂件/etc&#xff1a;存放的是Linux下的配置文件/home&#xff1a;存放普通用户的家目录/media&am…

NDK 基础(一)—— C 语言知识汇总

本系列文章主要是介绍一些 NDK 开发所需的基础知识&#xff0c;目录如下&#xff1a; NDK 基础&#xff08;一&#xff09;—— C 语言知识汇总 NDK 基础&#xff08;二&#xff09;—— C 语言基础与特性1 NDK 基础&#xff08;三&#xff09;—— C 语言基础与特性2 NDK 基础…

MF(推荐系统的矩阵分解技术)论文笔记

论文概述 推荐系统的矩阵分解技术可以为用户提供更为准确的个性化推荐&#xff0c;对比传统的近邻技术&#xff0c;矩阵分解技术可以纳入更多信息&#xff0c;如隐式反馈、时间效应和置信度 近邻技术&#xff1a;基于用户或物品之间的相似性进行推荐&#xff0c;当用户之间已…

ChatGPT4.0知识问答、DALL-E生成AI图片、Code Copilot辅助编程,打开新世界的大门

目录 1、DALL-E 文字转图片 在线AI修改2、Write For Me3、Code Copilot 目前最强的AI编程大模型4、Diagrams: Show Me5、Instant Website [Multipage] 网站合成神器6、AskYourPDF Research Assistant 无限PDF7、Diagrams & Data: Research, Analyze, Visualize 精读Excel …

【注解和反射】获取类运行时结构

继上一篇博客【注解和反射】类加载器-CSDN博客 目录 七、获取类运行时结构 测试 getFields()和getDeclaredFields() getMethods()和getDeclaredMethods() 七、获取类运行时结构 获取类运行时结构通常指的是在Java等面向对象编程语言中&#xff0c;使用反射&#xff08;Ref…

迁移学习基础知识

简介 使用迁移学习的优势&#xff1a; 1、能够快速的训练出一个理想的结果 2、当数据集较小时也能训练出理想的效果。 注意&#xff1a;在使用别人预训练的参数模型时&#xff0c;要注意别人的预处理方式。 原理&#xff1a; 对于浅层的网络结构&#xff0c;他们学习到的…

[Swift]单元测试

编写单元测试是确保你的代码质量和功能正确性的重要步骤 一、编写单元测试的详细流程 1. 创建一个新的Xcode项目 如果你尚未创建一个项目&#xff0c;首先你需要在Xcode中创建一个新的iOS项目&#xff1a; 打开Xcode&#xff0c;选择“File” > “New” > “Project”…

重生之我是Nginx服务专家

nginx服务访问页面白色 问题描述 访问一个域名服务返回页面空白&#xff0c;非响应404。报错如下图。 排查问题 域名解析正常&#xff0c;网络通讯正常&#xff0c;绕过解析地址访问源站IP地址端口访问正常&#xff0c;nginx无异常报错。 在打开文件时&#xff0c;发现无法…

R可视化:ggplot2绘制双y轴图

介绍 ggplot2绘制双y轴图加载R包 knitr::opts_chunk$set(message = FALSE, warning = FALSE) library(tidyverse) library(readxl)# rm(list = ls()) options(stringsAsFactors = F) options(future.globals.maxSize = 10000 * 1024^2)Importing data 下载Underdetection of c…

IDEA实现Springboot项目自动热部署

每当我们在修改代码时&#xff0c;往往需要重新启动项目&#xff0c;这样不仅浪费时间而且很麻烦&#xff0c;我们可以通过IDEA的热部署来提高效率 1、首先点file >> settings >> Build Excution >> Compire&#xff0c;选择Build project auto matically 2.…

CMakeLists.txt中如何添加编译选项?

1. 引子 编译器有多种可供选择&#xff0c;如g、c、clang等&#xff0c;如下以c作为示例。 2. 使用CMAKE_CXX_FLAGS添加编译选项 在Makefile中可能用类似如下的指令来添加编译选项&#xff1a; /usr/bin/c -Wall -Wextra -Wno-sign-compare -Wno-unused-variable -Wno-unuse…

flutter笔记-主要控件及布局

文章目录 1. 富文本实例2. Image2.1 本地图片2.2 网络图片 笔记3. 布局4. 滑动相关view4.1 GridView类似九宫格view4.2 ListView 关于widget的生命周期的相关知识这里就不做介绍&#xff0c;和很多语言类似&#xff1b; 1. 富文本实例 Dart中使用richtext&#xff0c;示例如下…

Vue3+Vite开发的项目进行加密打包

本文主要介绍Vue3+Vite开发的项目如何进行加密打包。 目录 一、vite简介二、混淆工具三、使用方法1. 安装插件:2. 配置插件:3. 运行构建:4. 自定义混淆选项:5. 排除文件:下面是Vue 3+Vite开发的项目进行加密打包的方法。 一、vite简介 Vite 是一个由 Evan You 创造的现代…

XBoot:基于Spring Boot 2.x的一站式前后端分离快速开发平台

XBoot&#xff1a;基于Spring Boot 2.x的一站式前后端分离快速开发平台 摘要 随着信息技术的迅速发展&#xff0c;快速构建高质量、高可靠性的企业级应用成为了迫切需求。XBoot&#xff0c;作为一个基于Spring Boot 2.x的一站式前后端分离快速开发平台&#xff0c;通过整合微信…

针对icon报错

针对上篇文章生成图标链接中图标报错 C# winfrom应用程序添加图标-CSDN博客 问题&#xff1a;参数“picture”必须是可用作Icon的参数 原因&#xff1a;生成的ico图标类型不匹配 解决方法&#xff1a; 更改导出的ico类型

iOS - 多线程-读写安全

文章目录 iOS - 多线程-读写安全1. 多读单写1.1 场景1.2 实现方案1.2.1 pthread_rwlock&#xff1a;读写锁1.2.1.1 示例 1.2.2 dispatch_barrier_async&#xff1a;异步栅栏调用1.2.2.1 示例 iOS - 多线程-读写安全 假设有一个文件&#xff0c;A线程进行读取操作&#xff0c;B…

数智时代的AI人才粮仓模型解读白皮书(2024版)

来源&#xff1a;极客邦科技 自 2023 年上半年起&#xff0c;ChatGPT 等大模型技术蓬勃发展&#xff0c;AI 技术不断突破边界&#xff0c;展现 出惊人的潜力和发展速度。从早期的逻辑推理、专家系统&#xff0c;到如今的深度学习、神经网络&#xff0c; AI 技术显著缩小了科学…

ASP.NET企业投资价值分析系统

摘 要 本文将影响股票投资价值的宏观因素、行业因素、企业内部等诸多因素予以量化分析&#xff0c;对钢铁板块和汽车板块各上市公司进行综合评估&#xff0c;为广大股民的投资方向和资金安全提供了有力的支持。本文还阐述了企业投资价值分析的必要性&#xff0c;说明了企业投…

分类算法——模型评估(八)

1混淆矩阵 在分类任务下&#xff0c;预测结果与正确标记之间存在四种不同的组合&#xff0c;构成混淆矩阵&#xff08;适用于多分类&#xff09; TP True Possitive FN False Negative 2精确率&#xff08;Precision&#xff09;与召回率&#xff08;Recall&#xff09; 精…

mysql-sql-练习题-2

日期topN 日期最值 topN 任意区间topN 每年温度top2建表排名函数万能公式&#xff08;条关&#xff09; 任意区间 各科第1,3,5名排名函数万能公式 日期 本周过生日 -- 本周表示 加减日期 格式化 拼接 select * from student where date_format(s_age,concat(year(curdate()),…