【数据结构】树与二叉树(廿四):树搜索指定数据域的结点(算法FindTarget)
文章目录
- 5.3.1 树的存储结构
- 5. 左儿子右兄弟链接结构
- 5.3.2 获取结点的算法
- 1. 获取大儿子、大兄弟结点
- 2. 搜索给定结点的父亲
- 3. 搜索指定数据域的结点
- a. 算法FindTarget
- b. 算法解析
- c. 代码实现
- a. 使用指向指针的指针
- b. 直接返回找到的节点
- 4. 代码整合
5.3.1 树的存储结构
5. 左儿子右兄弟链接结构
【数据结构】树与二叉树(十九):树的存储结构——左儿子右兄弟链接结构(树、森林与二叉树的转化)
左儿子右兄弟链接结构通过使用每个节点的三个域(FirstChild、Data、NextBrother)来构建一棵树,同时使得树具有二叉树的性质。具体来说,每个节点包含以下信息:
- FirstChild: 存放指向该节点的大儿子(最左边的子节点)的指针。这个指针使得我们可以迅速找到一个节点的第一个子节点。
- Data: 存放节点的数据。
- NextBrother: 存放指向该节点的大兄弟(同一层中右边的兄弟节点)的指针。这个指针使得我们可以在同一层中迅速找到节点的下一个兄弟节点。
通过这样的结构,整棵树可以用左儿子右兄弟链接结构表示成一棵二叉树。这种表示方式有时候被用于一些特殊的树结构,例如二叉树、二叉树的森林等。这种结构的优点之一是它更紧凑地表示树,而不需要额外的指针来表示兄弟关系。

A/|\B C D/ \E F
A
|
B -- C -- D|E -- F
即:
A/ B \C/ \ E D\F

5.3.2 获取结点的算法
1. 获取大儿子、大兄弟结点
【数据结构】树与二叉树(二十):树获取大儿子、大兄弟结点的算法(GFC、GNB)
2. 搜索给定结点的父亲
【数据结构】树与二叉树(廿四):树搜索给定结点的父亲(算法FindFather)
3. 搜索指定数据域的结点
a. 算法FindTarget

b. 算法解析
算法FindTarget在以t为根指针的树中搜索数据成员等于target的节点,类似先根遍历,其时间复杂度为O(n) 。
- 首先,将
result指针设置为空。 - 如果
t为空,直接返回。 - 如果
t的数据成员等于target,表示找到了目标节点,将result指针指向t,然后返回。 - 将指针
p指向t的第一个子节点。 - 进入一个循环,只要
p不为空:- 递归调用
FindTarget函数,传入参数p和target,并将结果存储在result中。 - 如果
result不为空,表示已经找到了目标节点,直接返回。 - 将指针
p更新为p的下一个兄弟节点。
- 递归调用
- 如果循环结束仍然没有找到目标节点,那么
result仍然为空。
c. 代码实现
a. 使用指向指针的指针
TreeNode* FindTarget(TreeNode* t, char target) {if (t == NULL) {return NULL;}if (t->data == target) {return t;}TreeNode* p = t->firstChild;while (p != NULL) {struct TreeNode* resultt = FindTarget(p, target);if (resultt != NULL) {return resultt;}p = p->nextBrother;}
}
b. 直接返回找到的节点
void FindTarget(TreeNode* t, char target, TreeNode** result) {*result = NULL;if (t == NULL) {return;}if (t->data == target) {*result = t;return;}TreeNode* p = t->firstChild;while (p != NULL) {FindTarget(p, target, result);if (*result != NULL) {return;}p = p->nextBrother;}
}
两种实现方式在逻辑上是等价的,主要的区别在于结果的返回方式和对指针的处理。
4. 代码整合
#include <stdio.h>
#include <stdlib.h>// 定义树节点
typedef struct TreeNode {char data;struct TreeNode* firstChild;struct TreeNode* nextBrother;
} TreeNode;// 创建树节点
TreeNode* createNode(char data) {TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));if (newNode != NULL) {newNode->data = data;newNode->firstChild = NULL;newNode->nextBrother = NULL;}return newNode;
}// 释放树节点及其子树
void freeTree(TreeNode* root) {if (root != NULL) {freeTree(root->firstChild);freeTree(root->nextBrother);free(root);}
}// 算法GFC:获取大儿子结点
TreeNode* getFirstChild(TreeNode* p) {if (p != NULL && p->firstChild != NULL) {return p->firstChild;}return NULL;
}// 算法GNB:获取下一个兄弟结点
TreeNode* getNextBrother(TreeNode* p) {if (p != NULL && p->nextBrother != NULL) {return p->nextBrother;}return NULL;
}// 队列结构
typedef struct QueueNode {TreeNode* treeNode;struct QueueNode* next;
} QueueNode;typedef struct {QueueNode* front;QueueNode* rear;
} Queue;// 初始化队列
void initQueue(Queue* q) {q->front = NULL;q->rear = NULL;
}// 入队列
void enqueue(Queue* q, TreeNode* treeNode) {QueueNode* newNode = (QueueNode*)malloc(sizeof(QueueNode));newNode->treeNode = treeNode;newNode->next = NULL;if (q->rear == NULL) {q->front = newNode;q->rear = newNode;} else {q->rear->next = newNode;q->rear = newNode;}
}// 出队列
TreeNode* dequeue(Queue* q) {if (q->front == NULL) {return NULL; // 队列为空}TreeNode* treeNode = q->front->treeNode;QueueNode* temp = q->front;q->front = q->front->next;free(temp);if (q->front == NULL) {q->rear = NULL; // 队列为空}return treeNode;
}// 层次遍历的算法
void LevelOrder(TreeNode* root) {if (root == NULL) {return;}Queue queue;initQueue(&queue);enqueue(&queue, root);while (queue.front != NULL) {TreeNode* p = dequeue(&queue);while (p != NULL) {// 访问当前结点printf("%c ", p->data);// 将大儿子结点入队列if (getFirstChild(p) != NULL) {enqueue(&queue, getFirstChild(p));}// 移动到下一个兄弟结点p = getNextBrother(p);}}
}// 算法 FindTarget
void FindTarget(TreeNode* t, char target, TreeNode** result) {*result = NULL;if (t == NULL) {return;}if (t->data == target) {*result = t;return;}TreeNode* p = t->firstChild;while (p != NULL) {FindTarget(p, target, result);if (*result != NULL) {return;}p = p->nextBrother;}
}// TreeNode* FindTarget(TreeNode* t, char target) {
// if (t == NULL) {
// return NULL;
// }
//
// if (t->data == target) {
// return t;
// }
//
// TreeNode* p = t->firstChild;
//
// while (p != NULL) {
// struct TreeNode* resultt = FindTarget(p, target);
//
// if (resultt != NULL) {
// return resultt;
// }
//
// p = p->nextBrother;
// }
// }int main() {// 构建左儿子右兄弟链接结构的树TreeNode* A = createNode('A');TreeNode* B = createNode('B');TreeNode* C = createNode('C');TreeNode* D = createNode('D');TreeNode* E = createNode('E');TreeNode* F = createNode('F');A->firstChild = B;B->nextBrother = C;C->nextBrother = D;C->firstChild = E;E->nextBrother = F;// 要查找的目标值char targetValue = 'C';// 使用算法 FindTarget 查找结点// TreeNode* result = FindTarget(A, targetValue);TreeNode* result = NULL;FindTarget(A, targetValue, &result);// 输出结果if (result != NULL) {printf("Node with data %c found.\n", targetValue);} else {printf("Node with data %c not found.\n", targetValue);}// 层次遍历printf("Level Order: \n");LevelOrder(result);printf("\n");// 释放树节点freeTree(A);return 0;
}

相关文章:
【数据结构】树与二叉树(廿四):树搜索指定数据域的结点(算法FindTarget)
文章目录 5.3.1 树的存储结构5. 左儿子右兄弟链接结构 5.3.2 获取结点的算法1. 获取大儿子、大兄弟结点2. 搜索给定结点的父亲3. 搜索指定数据域的结点a. 算法FindTargetb. 算法解析c. 代码实现a. 使用指向指针的指针b. 直接返回找到的节点 4. 代码整合 5.3.1 树的存储结构 5.…...
vue3怎么提升效率的?为什么vue3比vue2快?效率提升主要在哪些方面?
官方文档中说vue3在 客户端渲染效率比vue2提升了1.3~2倍, SSR渲染效率比vue2提升了2~3倍,那么究竟是怎么提升的呢? 一、静态提升 在 vue3项目中的package.json文件中,可以看到这个 vue/compiler-sfc,它是用来解析(.v…...
C语言文件操作 | 文件分类、文件打开与关闭、文件的读写、文件状态、文件删除与重命名、文件缓冲区
欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学习,人工智能等相关领域的知识和…...
从零开始的c语言日记day37——数组指针练习
一、 取地址数组储存在了*p里,里面储存的是整个数组的地址但本质也是第一个元素的地址解引用后1为4个字节所以就可以打印数组了。但一般不用这种方法 这样更方便一些 打印多维数组 如果不用这样传参,用指针传参怎么做呢? Main里函数的arr表示…...
codeforces 1851F
题目链接 题目大意:给你一个长度为n的数组a, 和一个整数k(2<n<2e5, k<30, a[i]<pow(2,k))。 任选一个x,求(a[i] ^ x) & (a[j] ^ x) 的最大值(1<i,j<n, i!j, x<pow(2,k))。 由于中间有个&,所以我们要求两个数最高…...
js把格式为YYYY-MM-DD HH:mm:ss的时间转换为UTC时间ISO 8601格式
// 要转换的日期字符串 const inputDate 2023-11-25 14:54:01; // 将日期字符串转换为Date对象 const dateObj new Date(inputDate); // 获取时间戳(毫秒) const timestamp dateObj.getTime(); // 转换格式 const outputDate new Date(tim…...
使用 Java 来读取 Excel 文件,检查每一行中的 URL,并将不符合条件的行标记为红色
-- 日、时、分、秒,这是计时的单位,惜时就应该惜日、惜时、惜分、惜秒。 用 Java 来读取 Excel 文件,检查每一行中的 URL,并将不符合条件的行标记为红色。以下是一个简单的示例,使用 Apache POI 进行 Excel 操作&#…...
雷达公式实现(matlab)
雷达公式实现 代码来源:《雷达系统分析与设计(MATLAB版)(第三版)》 function [snr] radar_eq(pt,freq,g,sigma,b,nf,loss,range) % This program implements Eq.(1.63) %% Inputs:% pt——峰值功率,W% freq——雷达中心频率,Hz% g——天线…...
CMake构建一个转换为3d tile的开源代码成功
之前CMake构建一个转换为3d tile的开源代码,生成解决方案之后,从VS2019打开; 总是报一个错误,跟 mocs_compilation_Debug.cpp 这个QT相关文件有关,它生成的obj,总是报模块计算机x64和目标计算机x86冲突&am…...
Java线程通信
线程通信 案例 package com.itheima.d4;public class ThreadTest {public static void main(String[] args) {Desk desk new Desk();//创建3个生产者线程new Thread(() -> {while (true) {desk.put();}}, "厨师1").start();new Thread(() -> {while (true) {…...
计算4人队形的最可能分布
2 2 2 1 2 2 2 2 2 1 2 2 2 2 2 1 2 2 3 3 3 x 3 3 2 2 2 1 2 2 2 2 2 1 2 2 在6*6的平面上2个点随机分布,有3种分布方式,2a1,2a2,2a3,占比为1:5:1. 3 3 …...
如何解决 Java 中的 IllegalArgumentException 异常?
非法参数异常(IllegalArgumentException)的抛出是为了表明一个方法被传递了一个非法参数。该异常扩展了 RuntimeException 类,因此属于在 Java 虚拟机(JVM)运行期间可能抛出的异常。它是一种未检查异常,因此…...
Vue 双向数据绑定
之前通过v-bind来完成的数据绑定,属性值和表达式进行绑定,表达式的值发生变化了属性值也跟着发生变化。 单向数据绑定: <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>首页</titl…...
电脑开机过程中,程序的启动的顺序是怎么样的?
电脑的启动过程涉及多个步骤,程序按照特定的顺序启动。这个过程通常如下: 电源开启: 当你按下电源按钮时,电源供应器(PSU)开始向电脑的各个组件供电。 自检加电(POST): 这是电脑启动过程的第一步。在这个阶段,基本输入输出系统(BIOS)或统一可扩展固件接口(UEFI)执行…...
JSON详细教程
😊JSON详细教程 🚩JSON简介☃️JSON语法规则🔊JSON和JavaScript对象的区别 ☃️JSON数据类型字符串🔊数字🔊布尔值🔊数组🔊对象🔊Null ☃️JSON对象🔊访问JSON对象的值&a…...
DSP介绍及CCS
文章目录 CCS版本编译器CCS使用注意严禁中文 CCS的基本操作新建工程导入现有工程调整字体的大小工程界面恢复标签的使用 仿真盒小虫子进入在线Debug 仿真器芯片TMS320F28355基本介绍特性 DSP中特殊指令dsp指令中的EALLOW EDIS CCS TI官网 版本 CCS版本: CCS8.3.1…...
周期串(Periodic Strings)
做了我两个小时,我真的裂开 之前已经发过一次了,走在回宿舍的路上突然发现有些情况并不适用,赶紧删掉了 题目如下: 如果一个字符串可以由某个长度为k的字符串重复多次得到,则称该串以k为周期。例如:abca…...
C语言——猜凶手
题目: 日本某地发生了一件谋杀案,警察通过排查确定杀人凶手必为4个嫌疑犯的一个。 以下为4个嫌疑犯的供词: A说:不是我。 B说:是C。 C说:是D。 D说:C在胡说 已知3个人说了真话,1个人说的是假话。…...
【TiDB】TiDB离线方式部署
目录 1 下载TiDB离线组件包 2 安装TiUP 3 合并离线包 4 TIDB 软件和硬件环境建议配置 5 TiDB环境与系统配置检查 6 生成集群初始化配置文件模板 7 执行部署命令 1 检查就能存在的潜在风险 2 手动修复风险 3 部署 TiDB 集群 8 查看TIUP管理的集群情况 9 检查部署的…...
android shape绘制半圆
<?xml version"1.0" encoding"utf-8"?><shape xmlns:android"http://schemas.android.com/apk/res/android"android:shape"rectangle"><sizeandroid:width"20dp"android:height"10dp" /><…...
iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
