嵌入式 数据结构学习 (六) 树、哈希表与内核链表

一、树(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)的使用

相关推荐
王德博客31 分钟前
【从基础到实战】STL string 学习笔记(上)
c++·笔记·学习
赴33540 分钟前
逻辑回归 银行贷款资格判断案列优化 交叉验证,调整阈值,下采样与过采样方法
算法·机器学习·逻辑回归·下采样·交叉验证·过采样·阈值
2501_924878731 小时前
无人机光伏巡检缺陷检出率↑32%:陌讯多模态融合算法实战解析
开发语言·人工智能·算法·视觉检测·无人机
沉睡的无敌雄狮1 小时前
无人机光伏巡检漏检率↓78%!陌讯多模态融合算法实战解析
人工智能·算法·计算机视觉·目标跟踪
Always_away1 小时前
26考研|数学分析:重积分
笔记·学习·考研·数学
♪张三儿℡1 小时前
Oracle优化学习十六
数据库·学习·oracle
Alaso_shuang1 小时前
verilog的学习
学习·fpga开发·数字逻辑·数字电路
magicwt1 小时前
《从零构建大模型》读书笔记
算法
大胖猫L1 小时前
深搜与广搜在 TypeScript 类型递归中的应用
前端·算法
2202_756749692 小时前
02 基于sklearn的机械学习-KNN算法、模型选择与调优(交叉验证、朴素贝叶斯算法、拉普拉斯平滑)、决策树(信息增益、基尼指数)、随机森林
python·算法·决策树·随机森林·机器学习·sklearn