【数据结构】树与二叉树(十八):树的存储结构——Father链接结构、儿子链表链接结构

文章目录

  • 5.1 树的基本概念
    • 5.1.1 树的定义
    • 5.1.2 森林的定义
    • 5.1.3 树的术语
  • 5.2 二叉树
  • 5.3 树
    • 5.3.1 树的存储结构
      • 1. 理论基础
      • 2. 典型实例
    • 5.3.2 Father链接结构
      • a. 定义树节点结构
      • b. 创建新节点
      • c. 主函数
      • d. 代码整合
    • 5.3.3 儿子链表链接结构
      • a. 定义树节点结构
      • b. 创建新节点
      • c. 添加子节点作为第一个子节点
      • d. 遍历树打印节点数据
      • e. 主函数
      • f. 代码整合

5.1 树的基本概念

5.1.1 树的定义

  • 一棵树是结点的有限集合T:
    • 若T非空,则:
      • 有一个特别标出的结点,称作该树的,记为root(T);
      • 其余结点分成若干个不相交的非空集合T1, T2, …, Tm (m>0),其中T1, T2, …, Tm又都是树,称作root(T)的子树
    • T 空时为空树,记作root(T)=NULL。

5.1.2 森林的定义

  一个森林是0棵或多棵不相交(非空)树的集合,通常是一个有序的集合。换句话说,森林由多个树组成,这些树之间没有交集,且可以按照一定的次序排列。在森林中,每棵树都是独立的,具有根节点和子树,树与树之间没有直接的连接关系。
  森林是树的扩展概念,它是由多个树组成的集合。在计算机科学中,森林也被广泛应用于数据结构和算法设计中,特别是在图论和网络分析等领域。
在这里插入图片描述

5.1.3 树的术语

  • 父亲(parent)、儿子(child)、兄弟(sibling)、后裔(descendant)、祖先(ancestor)
  • 度(degree)、叶子节点(leaf node)、分支节点(internal node)
  • 结点的层数
  • 路径、路径长度、结点的深度、树的深度

参照前文:【数据结构】树与二叉树(一):树(森林)的基本概念:父亲、儿子、兄弟、后裔、祖先、度、叶子结点、分支结点、结点的层数、路径、路径长度、结点的深度、树的深度

5.2 二叉树

5.3 树

5.3.1 树的存储结构

1. 理论基础

  1. Father链接结构:

    • 在这种结构中,每个节点除了存储数据外,还包含一个指向其父节点的指针。
    • 这种结构使得查找父节点很容易,但对于查找子节点则较为困难,因为需要遍历整个树。
    • 在二叉树中,每个节点最多有一个父节点,但在一般的树中,节点可以有多个父节点。
  2. 儿子链表链接结构:

    • 在这种结构中,每个节点包含一个指向其第一个子节点的指针,以及一个指向其下一个兄弟节点的指针。
    • 这种结构使得查找子节点很容易,但查找父节点较为困难,可能需要遍历兄弟节点链表直到找到相应的父节点。
  3. 左儿子右兄弟链接结构:

    • 也称为孩子兄弟表示法,每个节点包含一个指向其第一个子节点的指针,以及一个指向其下一个兄弟节点的指针。
    • 在这种结构中,树的每一层被表示为一个单链表,子节点通过左链连接,兄弟节点通过右链连接。
    • 这种结构既方便查找父节点,又方便查找子节点和兄弟节点,被广泛用于一般的树的表示。

  选择合适的树的存储结构通常取决于具体应用的需求。 Father链接结构适合于查找父节点的操作频繁,而儿子链表链接结构和左儿子右兄弟链接结构适用于频繁查找子节点的情况。

2. 典型实例

在这里插入图片描述

  1. Father链接结构:
    • A节点:父指针为null(A为根节点)
    • B节点:父指针指向A
    • C节点:父指针指向A
    • D节点:父指针指向A
    • E节点:父指针指向C
    • F节点:父指针指向C
  2. 儿子链表链接结构:
    • A节点:子节点链表为B、C、D
    • B节点:子节点链表为null
    • C节点:子节点链表为E、F
    • D节点:子节点链表为null
    • E节点:子节点链表为null
    • F节点:子节点链表为null
  3. 左儿子右兄弟链接结构:
    • A节点:左儿子为B,右兄弟为null
    • B节点:左儿子为null,右兄弟为C
    • C节点:左儿子为E,右兄弟为D
    • D节点:左儿子为null,右兄弟为null
    • E节点:左儿子为null,右兄弟为F
    • F节点:左儿子为null,右兄弟为null

5.3.2 Father链接结构

a. 定义树节点结构

typedef struct TreeNode {
    char data;              // 节点数据
    struct TreeNode* parent; // 指向父节点的指针
} TreeNode;

b. 创建新节点

TreeNode* createNode(char data) {
    TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));
    if (newNode == NULL) {
        fprintf(stderr, "Memory allocation failed\n");
        exit(EXIT_FAILURE);
    }
    newNode->data = data;
    newNode->parent = NULL;
    return newNode;
}

c. 主函数

int main() {
    // 创建节点
    TreeNode* nodeA = createNode('A');
    TreeNode* nodeB = createNode('B');
    TreeNode* nodeC = createNode('C');
    TreeNode* nodeD = createNode('D');
    TreeNode* nodeE = createNode('E');
    TreeNode* nodeF = createNode('F');

    // 构建树结构,设置父指针
    nodeB->parent = nodeA;
    nodeC->parent = nodeA;
    nodeD->parent = nodeA;
    nodeE->parent = nodeC;
    nodeF->parent = nodeC;

    // 打印每个节点及其父节点
    printf("Node %c, Parent: %c\n", nodeA->data, (nodeA->parent ? nodeA->parent->data : 'N'));
    printf("Node %c, Parent: %c\n", nodeB->data, (nodeB->parent ? nodeB->parent->data : 'N'));
    printf("Node %c, Parent: %c\n", nodeC->data, (nodeC->parent ? nodeC->parent->data : 'N'));
    printf("Node %c, Parent: %c\n", nodeD->data, (nodeD->parent ? nodeD->parent->data : 'N'));
    printf("Node %c, Parent: %c\n", nodeE->data, (nodeE->parent ? nodeE->parent->data : 'N'));
    printf("Node %c, Parent: %c\n", nodeF->data, (nodeF->parent ? nodeF->parent->data : 'N'));

    // 释放内存
    free(nodeA);
    free(nodeB);
    free(nodeC);
    free(nodeD);
    free(nodeE);
    free(nodeF);

    return 0;
}

d. 代码整合

#include <stdio.h>
#include <stdlib.h>

// 定义树节点结构
typedef struct TreeNode {
    char data;              // 节点数据
    struct TreeNode* parent; // 指向父节点的指针
} TreeNode;

// 创建新节点的函数
TreeNode* createNode(char data) {
    TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));
    if (newNode == NULL) {
        fprintf(stderr, "Memory allocation failed\n");
        exit(EXIT_FAILURE);
    }
    newNode->data = data;
    newNode->parent = NULL;
    return newNode;
}

int main() {
    // 创建节点
    TreeNode* nodeA = createNode('A');
    TreeNode* nodeB = createNode('B');
    TreeNode* nodeC = createNode('C');
    TreeNode* nodeD = createNode('D');
    TreeNode* nodeE = createNode('E');
    TreeNode* nodeF = createNode('F');

    // 构建树结构,设置父指针
    nodeB->parent = nodeA;
    nodeC->parent = nodeA;
    nodeD->parent = nodeA;
    nodeE->parent = nodeC;
    nodeF->parent = nodeC;

    // 打印每个节点及其父节点
    printf("Node %c, Parent: %c\n", nodeA->data, (nodeA->parent ? nodeA->parent->data : 'N'));
    printf("Node %c, Parent: %c\n", nodeB->data, (nodeB->parent ? nodeB->parent->data : 'N'));
    printf("Node %c, Parent: %c\n", nodeC->data, (nodeC->parent ? nodeC->parent->data : 'N'));
    printf("Node %c, Parent: %c\n", nodeD->data, (nodeD->parent ? nodeD->parent->data : 'N'));
    printf("Node %c, Parent: %c\n", nodeE->data, (nodeE->parent ? nodeE->parent->data : 'N'));
    printf("Node %c, Parent: %c\n", nodeF->data, (nodeF->parent ? nodeF->parent->data : 'N'));

    // 释放内存
    free(nodeA);
    free(nodeB);
    free(nodeC);
    free(nodeD);
    free(nodeE);
    free(nodeF);

    return 0;
}

在这里插入图片描述

注:其他操作……有缘再见

5.3.3 儿子链表链接结构

a. 定义树节点结构

struct TreeNode {
    char data;
    struct TreeNode* child;
    struct TreeNode* sibling;
};

b. 创建新节点

struct TreeNode* createNode(char data) {
    struct TreeNode* newNode = (struct TreeNode*)malloc(sizeof(struct TreeNode));
    newNode->data = data;
    newNode->child = NULL;
    newNode->sibling = NULL;
    return newNode;
}

c. 添加子节点作为第一个子节点

void addChild(struct TreeNode* parent, struct TreeNode* child) {
    child->sibling = parent->child;
    parent->child = child;
}

d. 遍历树打印节点数据


void traverseTree(struct TreeNode* root) {
    if (root != NULL) {
        printf("%c\n", root->data);

        struct TreeNode* child = root->child;
        while (child != NULL) {
            printf("  %c (Child)\n", child->data);
            child = child->sibling;
        }

        // 递归遍历每个子节点
        child = root->child;
        while (child != NULL) {
            traverseTree(child);
            child = child->sibling;
        }
    }
}

e. 主函数

int main() {
    // 创建树节点
    struct TreeNode* A = createNode('A');
    struct TreeNode* B = createNode('B');
    struct TreeNode* C = createNode('C');
    struct TreeNode* D = createNode('D');
    struct TreeNode* E = createNode('E');
    struct TreeNode* F = createNode('F');

    // 构建树结构
    addChild(A, B);
    addChild(A, C);
    addChild(A, D);
    addChild(C, E);
    addChild(C, F);

    // 遍历并打印树节点
    traverseTree(A);

    // 释放内存
    free(A);
    free(B);
    free(C);
    free(D);
    free(E);
    free(F);

    return 0;
}

在这里插入图片描述

f. 代码整合

#include <stdio.h>
#include <stdlib.h>

// 定义树节点结构
struct TreeNode {
    char data;
    struct TreeNode* child;
    struct TreeNode* sibling;
};

// 创建新节点
struct TreeNode* createNode(char data) {
    struct TreeNode* newNode = (struct TreeNode*)malloc(sizeof(struct TreeNode));
    newNode->data = data;
    newNode->child = NULL;
    newNode->sibling = NULL;
    return newNode;
}

// 添加子节点作为第一个子节点
void addChild(struct TreeNode* parent, struct TreeNode* child) {
    child->sibling = parent->child;
    parent->child = child;
}

// 遍历树并打印节点
void traverseTree(struct TreeNode* root) {
    if (root != NULL) {
        printf("%c\n", root->data);

        struct TreeNode* child = root->child;
        while (child != NULL) {
            printf("  %c (Child)\n", child->data);
            child = child->sibling;
        }

        // 递归遍历每个子节点
        child = root->child;
        while (child != NULL) {
            traverseTree(child);
            child = child->sibling;
        }
    }
}

int main() {
    // 创建树节点
    struct TreeNode* A = createNode('A');
    struct TreeNode* B = createNode('B');
    struct TreeNode* C = createNode('C');
    struct TreeNode* D = createNode('D');
    struct TreeNode* E = createNode('E');
    struct TreeNode* F = createNode('F');

    // 构建树结构
    addChild(A, B);
    addChild(A, C);
    addChild(A, D);
    addChild(C, E);
    addChild(C, F);

    // 遍历并打印树节点
    traverseTree(A);

    // 释放内存
    free(A);
    free(B);
    free(C);
    free(D);
    free(E);
    free(F);

    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

cocos----刚体

刚体&#xff08;Rigidbody&#xff09; 刚体&#xff08;Rigidbody&#xff09;是运动学&#xff08;Kinematic&#xff09;中的一个概念&#xff0c;指在运动中和受力作用后&#xff0c;形状和大小不变&#xff0c;而且内部各点的相对位置不变的物体。在 Unity3D 中&#xff…

2023 OceanBase 年度发布会:砥砺自研,为“关键业务负载”打造一体化数据库

11 月 16 日&#xff0c;2023 OceanBase 年度发布会在京顺利召开。在本次发布会上&#xff0c;OceanBase 对外正式宣布&#xff1a;将持续践行“一体化”新战略&#xff0c;为关键业务负载打造一体化数据库。同时&#xff0c;会上发布一体化数据库的首个长期支持版本 OceanBase…

html在线生成二维码(附源码)

文章目录 1.设计来源1.1 主界面1.2 美化功能 2.效果和源码2.1 动态效果2.2 源代码 源码下载 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/details/134458927 html二维码生成&#xff08;附源码&#xff09;&#xff0c;生成二…

每天一道算法题(四)——移动零(将数组中的零移到最后面)

文章目录 前言1、问题2、示例3、解决方法&#xff08;1&#xff09;方法1&#xff08;2&#xff09;方法2&#xff08;双指针&#xff09; 前言 提示&#xff1a; 1、问题 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的…

如何选择适合企业的ERP管理系统?

如何选择适合企业的ERP管理系统&#xff1f; 企业业务不断发展和扩大&#xff0c;ERP管理系统已成为企业实现信息化管理、提高工作效率、降低成本的重要工具。然而&#xff0c;市场上ERP管理系统种类繁多&#xff0c;如何选择适合自己企业的ERP管理系统成为了企业面临的难题。…

【测试功能篇 01】Jmeter 压测接口最大并发量、吞吐量、TPS

压力测试&#xff0c;我们针对比较关键的接口&#xff0c;可以进行相应的压力测试&#xff0c;主要还是测试看看接口能抗住多少的请求数&#xff0c;TPS稳定在多少&#xff0c;也就是吞吐量多少 安装 Jmeter的安装很简单&#xff0c;官网下载地址 http://jmeter.apache.org/ &…

UE5 - ArchvizExplorer - 数字孪生城市模板 -学习笔记

1、学习资料 https://www.unrealengine.com/marketplace/zh-CN/product/archviz-explorer https://karldetroit.com/archviz-explorer-documentation/ 官网下载的是一个简单版&#xff0c;需要下载扩展&#xff0c;并拷贝到项目录下&#xff0c;才有完整版 https://drive.googl…

AH8691-60V降压至3.3V电源芯片:ESOP8封装解决方案

AH8691-60V降压至3.3V电源芯片&#xff1a;ESOP8封装解决方案 随着电子设备的日益普及&#xff0c;电源管理芯片的重要性也日益凸显。一款高效率、低功耗的电源芯片可以大大提高电子设备的性能和可靠性。今天&#xff0c;我们将介绍一款60V降压至3.3V电源芯片&#xff0c;采用…

websocket详解

一、什么是Websocket WebSocket 是一种在单个 TCP 连接上进行 全双工 通信的协议&#xff0c;它可以让客户端和服务器之间进行实时的双向通信。 WebSocket 使用一个长连接&#xff0c;在客户端和服务器之间保持持久的连接&#xff0c;从而可以实时地发送和接收数据。 在 Web…

工业镜头中远心镜头的特点

远心镜头 在Z轴&#xff08;光轴&#xff09;方向&#xff0c;理论上具有同样成像范围。 消除了透视效应。 消除了渐晕现像。

OpenCV快速入门:像素操作和图像变换

文章目录 前言1. 像素操作1.1 像素统计1.2 两个图像之间的操作1.2.1 图像加法操作1.2.3 图像加权混合 1.3 二值化1.4 LUT&#xff08;查找表&#xff09;1.4.1 查找表原理1.4.2 代码演示 2 图像变换2.1 旋转操作2.1.1 旋转的基本原理2.1.2 代码实现 2.2 缩放操作2.3 平移操作2.…

【字符编码系列一】ASCII编码是什么?

介绍 ASCII 编码于 1967 年第一次发布&#xff0c;最后一次更新是在 1986 年&#xff0c;迄今为止共收录了 128 个字符&#xff0c;包含了基本的拉丁字母&#xff08;英文字母&#xff09;、阿拉伯数字&#xff08;也就是 1234567890&#xff09;、标点符号&#xff08;,.!等&…

直线插补-逐点比较法

直线插补-逐点比较法 逐点比较法四个节拍的工作流程如图所示举例1 逐点比较法 逐点比较法逐点比较法是通过逐点比较刀具与所需插补曲线之间的相对位置&#xff0c;确定刀具的进给方向&#xff0c;进而加工出工件轮廓的插补方法。刀具从加工起点开始&#xff0c;按照“靠近曲线…

TP_Link WR886N 硬改闪存16M内存64M,刷入openwrt

一、换内存&#xff0c;拆闪存&#xff1a; 1、先原机开机试试是否功能正常&#xff1b; 2、拆机&#xff0c;比较难拆&#xff0c;容易坏外壳&#xff1b; 3、找到内存和闪存&#xff0c;用胶带把边上的小元件&#xff0c;电阻都贴好&#xff1b; 4、加助焊油&#xff0c;用风…

人脸识别4G执法记录仪、一体化智能AI布控球在智慧社区、智能网格中的应用

智慧社区守护者&#xff1a;人脸识别与智能监控技术的融合创新 随着城市的飞速发展和科技的不断进步&#xff0c;智慧社区和智能网格的概念已经成为现代城市管理的一个重要趋势。在这一过程中&#xff0c;人脸识别技术、4G执法记录仪以及一体化智能AI布控球等智能监控设备&…

探索计算机视觉技术的应用前景

计算机视觉技术是人工智能领域中一项至关重要的技术&#xff0c;它通过模拟人类视觉系统的工作原理&#xff0c;使计算机能够以一种类似于人类的方式理解和解释图像和视频。这项技术不仅在学术界受到了广泛关注&#xff0c;而且在商业领域也得到了广泛应用。 计算机视觉技术的应…

Libvirt-Qemu-Kvm 操作手记

(持续更新~) 本文主要用于记录在操作libvirt qemu kvm过程中遇到的问题及原因分析。 Hugepage 让qemu使用大页可以减少tdp的size&#xff0c;一定程度上可以提高性能&#xff1b;使用大页可以用memfd或者file backend。 memfd 操作步骤如下&#xff1a; 在系统中reserv…

接口测试系列之 —— 接口安全测试

“开源 Web 应用安全项目”(OWASP)在 2019 年发布了 API 十大安全风险 《OWASP API 安全 Top10》&#xff1a;失效的对象级别授权、失效的用户身份验证、过 度的数据暴露、资源缺乏和速率限制、失效的功能级授权、批量分配、安全配置 错误、注入、资产管理不当、日志和监视不足…

6. hdfs的命令操作

简介 本文主要介绍hdfs通过命令行操作文件 操作文件有几种方式&#xff0c;看个人习惯 hdfs dfs hdfs fs hadoop fs个人习惯使用 hadoop fs 可操作任何对象&#xff0c;命令基本上跟linux命令一样 Usage [hadoophadoop01 ~]$ hadoop fs Usage: hadoop fs [generic option…

hcia学习:

视频学习&#xff1a; 第一部分&#xff1a;基础学习。 19——子网掩码。