嵌入式 數據結構學習 (六) 樹、哈希表與內核鏈表

一、樹(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;的寄存器訪問細節…