【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…

学习java第五十三天

Spring器中的bean可以分为5个范围&#xff1a; singleton&#xff1a;这种bean范围是默认的&#xff0c;这种范围确保不管接受多少请求&#xff0c;每个容器中只有一个bean的实例&#xff0c;单例模式&#xff1b; prototype&#xff1a;为每一个bean提供一个实例&#xff1b…

Ubuntu 系统使用 root 用户登录

Ubuntu 系统在安装过程中默认不设置 root 帐户和密码。如有需要&#xff0c;可在设置中开启允许 root 用户登录。具体操作步骤如下&#xff1a; 1.使用 ubuntu 帐户登录服务器 2.执行以下命令&#xff0c;设置 root 密码 sudo passwd root 3.输入 root 的密码&#xff0c;按…

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

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

C++生产者消费者问题实例

C生产者消费者问题实例 全局变量声明生产者生产函数消费者消费函数生产者线程入口消费者线程入口主函数 全局变量声明 #include <iostream> #include <condition_variable> #include <mutex> #include <thread>static const int repository_size 10;/…

android 内部序列化对象

在Android中&#xff0c;内部序列化对象通常指的是将对象的状态转换为字节流&#xff0c;以便可以将对象保存到文件、通过网络发送&#xff0c;或者在应用的不同部分之间传递。在Java中&#xff0c;序列化是通过实现java.io.Serializable接口来完成的。Android继承了Java的序列…

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;他们学习到的…

leetcode_29.两数相除

29. 两数相除 题目描述&#xff1a;给你两个整数&#xff0c;被除数 dividend 和除数 divisor。将两数相除&#xff0c;要求 不使用 乘法、除法和取余运算。 整数除法应该向零截断&#xff0c;也就是截去&#xff08;truncate&#xff09;其小数部分。例如&#xff0c;8.345 将…

[Swift]单元测试

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

window驱动开发-内核线程

在内核开发中&#xff0c;不可避免需要用到多线程技术&#xff0c;毕竟驱动是针对所有进程&#xff0c;而非某个特定进程&#xff0c;故驱动自然也是多线程的。在设计目标中&#xff0c;已经明确了驱动例程设计中&#xff0c;需要考虑的问题之一就是"重入"的概念&…

重生之我是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;示例如下…

int和byte数组相互转换详解

转换之前我们需要了解各种进制之间的关系&#xff0c;不太了解的可以先看下计算机组成原理和体系 这篇文章 byte byte是字节的意思&#xff0c;一个字节等于8位&#xff0c;范围是 0000 0000 ~ 1111 1111(十六进制&#xff1a;0x0~0xff),总共包含256个数。 有符号的byte表示的…

java 和 php 的AES 128位 256位 加解密 【java解密php的AES加密方案】

项目需要 需要java可以解密 php加密的 字符串 &#xff0c; 使用的方法是 AES128位加解密 坑一踩完 &#xff0c;还是直接上代码 package com.xxx.init.utils;import com.xxx.init.utils.BaseDataUtil; import com.xxx.init.exception.xxxRuntimeException; import com.xxx.i…