一、树(Tree)结构详解

1. 树的基本概念

树的核心特性
  • 非线性结构:数据元素之间存在一对多的层次关系

  • 递归定义:树的子树仍然是树

  • 专业术语

    • 度(Degree):结点拥有的子树数

    • 叶子结点:度为0的结点

    • 层次(Level):根为第1层,依次递增

    • 深度/高度:树中结点的最大层次

树的存储结构

c

/* 树结点的链式存储结构 */
typedef struct _tree_node_ {DATATYPE data;struct _tree_node_ *left;  // 左子树指针struct _tree_node_ *right; // 右子树指针
} TreeNode;

2. 二叉树专题

二叉树特殊形态
  1. 斜树:所有结点只有左子树或只有右子树

  2. 满二叉树

    • 所有分支结点都有左右子树

    • 所有叶子在同一层

  3. 完全二叉树

    • 结点位置与同深度满二叉树对应

    • 叶子结点集中在左部连续位置

二叉树性质(重要公式)
  1. 第i层最多有2^(i-1)个结点

  2. 深度为k的二叉树最多有2^k -1个结点

  3. 叶子结点数n0 = 度为2的结点数n2 + 1

  4. 具有n个结点的完全二叉树深度为⌊log₂n⌋+1

3. 二叉树遍历实现

(1) 先序遍历

c

void PreOrderTraverse(TreeNode *root) {if (NULL == root) return;printf("%c", root->data);      // 访问根结点PreOrderTraverse(root->left);  // 遍历左子树PreOrderTraverse(root->right); // 遍历右子树
}
(2) 中序遍历

c

void InOrderTraverse(TreeNode *root) {if (NULL == root) return;InOrderTraverse(root->left);   // 遍历左子树printf("%c", root->data);      // 访问根结点InOrderTraverse(root->right);  // 遍历右子树
}
(3) 后序遍历

c

void PostOrderTraverse(TreeNode *root) {if (NULL == root) return;PostOrderTraverse(root->left);  // 遍历左子树PostOrderTraverse(root->right); // 遍历右子树printf("%c", root->data);       // 访问根结点
}

4. 二叉树创建与销毁

静态创建示例

c

char data[] = "abd#f###c#eg###"; // '#'表示空结点
int ind = 0;void CreateTree(TreeNode **root) {char c = data[ind++];if ('#' == c) {*root = NULL;return;}*root = malloc(sizeof(TreeNode));(*root)->data = c;CreateTree(&(*root)->left);   // 递归创建左子树CreateTree(&(*root)->right);  // 递归创建右子树
}
内存释放

c

void DestroyTree(TreeNode *root) {if (NULL == root) return;DestroyTree(root->left);   // 释放左子树DestroyTree(root->right);  // 释放右子树free(root);                // 释放当前结点
}

二、哈希表(Hash Table)实现

1. 哈希表核心概念

关键技术点
  • 哈希函数:将关键字映射到存储位置

  • 冲突解决

    • 开放定址法:线性探测、二次探测

    • 链地址法:数组+链表结构

常用哈希函数

c

/* 除留余数法 */
int HSFun(HSTable* hs, DATATYPE* data) {return *data % hs->tlen;  // 取模运算得到索引
}

2. 哈希表完整实现

结构定义

c

typedef struct {DATATYPE* head;  // 存储数组int tlen;        // 表长度
} HSTable;
创建与初始化

c

HSTable* CreateHsTable(int len) {HSTable* hs = malloc(sizeof(HSTable));hs->head = malloc(sizeof(DATATYPE) * len);for (int i = 0; i < len; i++) {hs->head[i] = -1;  // -1表示空位置}hs->tlen = len;return hs;
}
插入操作(线性探测法)

c

int HSInsert(HSTable* hs, DATATYPE* data) {int ind = HSFun(hs, data);while (hs->head[ind] != -1) {  // 处理冲突ind = (ind + 1) % hs->tlen;  // 线性探测}hs->head[ind] = *data;return 0;
}
查找实现

c

int HsSearch(HSTable* hs, DATATYPE* data) {int ind = HSFun(hs, data);int old_ind = ind;while (hs->head[ind] != *data) {ind = (ind + 1) % hs->tlen;if (old_ind == ind) return -1;  // 未找到}return ind;  // 返回找到的索引
}

三、Linux内核链表解析

1. 内核链表特点

与传统链表的区别
  • 嵌入设计:list_head结构体嵌入到宿主数据结构中

  • 双向循环:首尾相连形成环状结构

  • 高复用性:与具体数据类型解耦

核心结构定义

c

struct list_head {struct list_head *next, *prev;
};

2. 内核链表操作示例

链表初始化

c

struct my_data {int value;struct list_head list;  // 嵌入链表结点
};INIT_LIST_HEAD(&my_list);  // 初始化链表头
添加结点

c

list_add(&new_node->list, &head);       // 头插法
list_add_tail(&new_node->list, &head);  // 尾插法
遍历链表

c

struct my_data *pos;
list_for_each_entry(pos, &my_list, list) {printk("Value: %d\n", pos->value);
}
删除结点

c

list_del(&node->list);  // 从链表中移除
kfree(node);            // 释放内存

四、嵌入式开发应用建议

  1. 树结构适用场景

    • 配置文件解析(XML/JSON)

    • 设备树(Device Tree)管理

    • 路由算法实现

  2. 哈希表优化技巧

    • 选择质数作为表长度减少冲突

    • 动态扩容机制设计

    • 嵌入式环境下可考虑静态内存分配

  3. 内核链表最佳实践

    • 多线程环境配合spinlock使用

    • 使用container_of宏获取宿主结构

    • 注意内存屏障(Memory Barrier)的使用

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

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

相关文章

封装WebSocket

一个基于原生 WebSocket 的封装库&#xff0c;实现了自动重连、心跳检测等功能&#xff0c;用于在前端应用中稳定地与后端 WebSocket 服务通信。下面从设计思路、关键功能等方面进行详细分析&#xff1a;设计思路 这个封装库采用单例模式设计&#xff0c;全局维护一个 WebSocke…

SLICEGPT: COMPRESS LARGE LANGUAGE MODELSBY DELETING ROWS AND COLUMNS

发表&#xff1a;ICLR24 机构&#xff1a;ETH Zurich 连接&#xff1a;https://arxiv.org/pdf/2401.15024 ABSTRACT 大型语言模型&#xff08;Large Language Models, LLMs&#xff09;已成为自然语言处理的基石&#xff0c;但其使用伴随着在计算和内存资源方面的高昂代价。…

Python 【技术面试题和HR面试题】➕ 循环结构、控制语句及综合应用问答

1.技术面试题 &#xff08;1&#xff09;详细描述单调栈的工作原理和应用场景 答&#xff1a; 原理 维护栈内元素单调递增 / 递减&#xff0c;新元素入栈前&#xff0c;弹出破坏单调性的栈顶&#xff0c;保持单调。 应用场景 排队比身高&#xff0c;搭积木找最大的空地 &#x…

100G系列光模块产品与应用场景介绍

在当今数字化时代&#xff0c;网络流量呈爆炸式增长&#xff0c;对数据传输速度和带宽的要求也越来越高。100G 光模块作为高速数据传输的关键组件&#xff0c;因其卓越的高速传输能力&#xff0c;已成为数据中心、云计算、企业网络以及 5G 通信网络等领域的重要组成部分。接下来…

运筹说 第140期 | 从直觉到算法:这些奠基人如何塑造了启发式方法的科学根基?

运筹说建构知识体系&#xff0c;解析学习要点运 筹 优 化 领 域 教 学 媒 体视频课程已上线&#xff01;&#xff01;!欢迎大家关注同名抖音和哔哩哔哩账号&#xff01;在人工智能与优化科学的浩瀚星空中&#xff0c;启发式算法如同一把钥匙&#xff0c;为人类打开了处…

Flutter编译安卓应用时遇到的compileDebugJavaWithJavac和compileDebugKotlin版本不匹配的问题

记一次flutter应用&#xff0c;编译安卓时&#xff0c;报的一个compileDebugJavaWithJavac和compileDebugKotlin版本本匹配的问题。 最终定位的原因是项目一来了audioplayers组件。 audioplayers组件有依赖了audioplayers_android&#xff0c; 它使用1.8编译的。 版本过低。后来…

linux-权限管理

linux-权限管理一、权限的基本类型二、权限的表示方式1. 字符形式&#xff08;rwx&#xff09;2. 数字形式三、权限管理常用命令1. chmod2. chown3. chgrp四、隐藏权限1. lsattr2. chattr五、权限掩码六、特别权限位1. suid2. sgid3. Sticky Bit七、权限委托1. 授权用户2. 授权…

从FCOS3D到PGD:看深度估计如何快速搭建你的3D检测项目

【导读】 还记得那个曾经在单目3D目标检测领域掀起热潮的 FCOS3D 吗&#xff1f;在后续更新中他们又推出了全新升级版——PGD&#xff08;Probabilistic and Geometric Depth&#xff09;最有意思的是&#xff0c;这次他们彻底换了路线&#xff1a;从原先的“直接回归深度”&a…

Apache Cloudberry 向量化实践(三)重塑表达式构建路径:Gandiva 优化实战

在向量化执行系统中&#xff0c;表达式构建是不可或缺的基础环节。无论是 SQL 中的投影、筛选&#xff0c;还是分区、聚合、排序&#xff0c;最终都需转化为底层执行引擎能识别和执行的表达式树。而在 Apache Cloudberry 向量化执行框架中&#xff0c;这一过程由 Gandiva 表达式…

Windows删除文件或者拔出U盘显示正在使用/占用解决办法

1、复制文件地址2、打开任务管理器&#xff0c;选择左侧【性能】3、打开资源监视器4、选择资源监视器中的CPU5、粘贴你复制的占用文件地址6、除了explore.exe以外&#xff0c;其他的关联的句柄都选中&#xff0c;然后右键结束

自由学习记录(68)

&#x1f9e0; blender为什么不用 M 或 T&#xff1f; 键位含义为什么没选MMove&#xff1f;其实被用作「Move to Collection」等功能不符合历史定义&#xff0c;而且功能太多了TTransform&#xff1f; 但 transform 是一个总称&#xff08;含移动、旋转、缩放&#xff09;T 被…

ReactNative【实战系列教程】我的小红书 8 -- 我(含左侧弹窗菜单,右下角图标等)

最终效果点左上角菜单按钮&#xff0c;弹出左侧菜单后代码实现app/(tabs)/mine.tsx import icon_add from "/assets/icons/icon_add.png"; import mine_bg from "/assets/images/mine_bg.png"; import Heart from "/components/Heart"; import a…

C++性能优化实战:从理论到落地的五大核心策略

在当今这个对计算效率要求极高的时代&#xff0c;C作为系统级编程语言的王者&#xff0c;其性能优化能力依然是无可替代的核心竞争力。本文将分享我在大型分布式系统开发中积累的C性能优化实战经验&#xff0c;这些经验帮助我们将关键组件的吞吐量提升了300%&#xff0c;延迟降…

字节 Seed 团队联合清华大学智能产业研究院开源 MemAgent: 基于多轮对话强化学习记忆代理的长文本大语言模型重构

&#x1f525; 最新动态!!! [2025/07] 我们提供了快速启动脚本&#xff0c;让使用MemAgent变得超级简单&#xff0c;详情请见下方"快速入门"部分。[2025/06] 我们发布了RL-MemAgent-14B和RL-MemAgent-7B模型&#xff0c;在350万token上下文任务中实现了近乎无损的性…

【unitrix】 4.20 类型级二进制数减法实现解析(sub.rs)

一、源码 这段代码实现了一个用于统计二进制补码整数位数的系统&#xff0c;支持多种自定义数值类型&#xff08;Z0、P1、N1、B0、B1&#xff09;。 use core::mem::size_of; use crate::number::{Z0, P1, N1, B0, B1, Var};/// 统计二进制位数的 trait pub trait BitLength {f…

手把手教你安全删除Anaconda虚拟环境(避坑指南)

文章目录一、删除前必看清单&#xff08;超级重要&#xff09;二、三种删除方法对比&#xff08;建议收藏&#xff09;方法1&#xff1a;官方推荐命令&#xff08;最安全&#xff09;方法2&#xff1a;暴力删除大法&#xff08;快速但需谨慎&#xff09;方法3&#xff1a;核弹级…

Effective Modern C++ 条款7:区分使用 `()` 和 `{}` 创建对象

在 C11 及以后的版本中&#xff0c;初始化对象的方式变得更加灵活&#xff0c;但也带来了选择上的困惑。() 和 {} 是两种常见的初始化语法&#xff0c;它们在语义、行为和适用场景上有显著差异。本文将通过具体示例&#xff0c;深入解析这两种初始化方式的区别&#xff0c;并探…

Java基础-String常用的方法

String常用的三种构造方法 public static void main(String[] args) {//1.使用常量字符串构造String s1 "1.Hello world";System.out.println(s1);//2.使用new关键字构造String s2 new String("2.Hello world");System.out.println(s2);//3。使用字符数组…

数学建模:多目标规划:ε约束法、 理想点法

一、ε约束法定义ε约束法通过将部分目标函数转化为约束条件&#xff0c;保留一个主要目标进行优化。1、选择一个主要目标 fk​(x) 进行优化。2、其他目标 fi​(x) 转化为约束 fi​(x)≤εi​&#xff0c;其中 εi​ 是决策者设定的容许阈值。​​原理​​​​目标选择​​&…

linux kernel struct regmap_config结构详解

在 Linux 内核中&#xff0c;struct regmap_config 是 ​Regmap 子系统的核心配置结构体&#xff0c;用于定义如何与底层硬件寄存器进行交互。Regmap&#xff08;Register Map&#xff09;子系统通过抽象不同总线&#xff08;如 I2C、SPI、MMIO 等&#xff09;的寄存器访问细节…