(C語言)Map數組的實現(數據結構)(鏈表)(指針)

源代碼:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 鍵值對節點
typedef struct Node {char* key;int value;struct Node* next;
} Node;// Map結構
typedef struct {Node* buckets[100];  // 固定大小的哈希桶(簡化版)int size;            // 元素數量
} Map;// 簡單哈希函數(字符串轉索引)
int hash(const char* key) {int hash = 0;while (*key) {hash += (*key++);}return hash % 100;  // 對應buckets大小
}// 初始化Map
void initMap(Map* map) {memset(map->buckets, 0, sizeof(map->buckets));map->size = 0;
}// 插入或更新鍵值對
void put(Map* map, const char* key, int value) {if (!key) return;int index = hash(key);Node* curr = map->buckets[index];// 查找是否已存在鍵while (curr) {if (strcmp(curr->key, key) == 0) {curr->value = value;  // 更新值return;}curr = curr->next;}// 不存在則創建新節點(頭插法)Node* newNode = (Node*)malloc(sizeof(Node));if (!newNode) return;newNode->key = strdup(key);if (!newNode->key) {free(newNode);return;}newNode->value = value;newNode->next = map->buckets[index];map->buckets[index] = newNode;map->size++;
}// 根據鍵獲取值
int get(Map* map, const char* key, int* result) {if (!key || !result) return 0;int index = hash(key);Node* curr = map->buckets[index];while (curr) {if (strcmp(curr->key, key) == 0) {*result = curr->value;return 1;  // 找到}curr = curr->next;}return 0;  // 未找到
}// 刪除鍵值對
int removeKey(Map* map, const char* key) {if (!key) return 0;int index = hash(key);Node* curr = map->buckets[index];Node* prev = NULL;while (curr) {if (strcmp(curr->key, key) == 0) {if (prev) {prev->next = curr->next;} else {map->buckets[index] = curr->next;}free(curr->key);free(curr);map->size--;return 1;}prev = curr;curr = curr->next;}return 0;
}// 獲取元素數量
int size(Map* map) {return map->size;
}// 清空Map
void clear(Map* map) {for (int i = 0; i < 100; i++) {Node* curr = map->buckets[i];while (curr) {Node* next = curr->next;free(curr->key);free(curr);curr = next;}map->buckets[i] = NULL;}map->size = 0;
}// 測試函數
int main() {Map map;initMap(&map);// 插入數據put(&map, "apple", 10);put(&map, "banana", 5);put(&map, "orange", 8);// 獲取數據int val;if (get(&map, "banana", &val)) {printf("banana: %d\n", val);  // 輸出:banana: 5}// 更新數據put(&map, "banana", 15);get(&map, "banana", &val);printf("updated banana: %d\n", val);  // 輸出:updated banana: 15// 刪除數據removeKey(&map, "orange");printf("size after remove: %d\n", size(&map));  // 輸出:size after remove: 2// 清空Mapclear(&map);printf("final size: %d\n", size(&map));  // 輸出:final size: 0return 0;
}

代碼詳解:?

這個代碼實現了一個簡單的?哈希表(Hash Map)?數據結構,用于存儲鍵值對(key-value pairs)。下面將詳細解釋代碼的每一部分及其功能:


1. 數據結構設計

節點結構?Node
typedef struct Node {char* key;          // 字符串鍵int value;          // 整數值struct Node* next;  // 指向下一個節點的指針(處理哈希沖突)
} Node;
  • 作用:存儲鍵值對的基本單元

  • 關鍵點

    • key?使用?strdup?動態分配內存存儲字符串

    • next?指針用于解決哈希沖突(鏈地址法)

哈希表結構?Map
typedef struct {Node* buckets[100];  // 哈希桶數組(固定大小100)int size;            // 當前存儲的元素數量
} Map;
  • 作用:管理整個哈希表

  • 關鍵點

    • buckets?是長度為 100 的指針數組,每個桶對應一個鏈表

    • size?記錄當前存儲的鍵值對數量


2. 核心功能實現

哈希函數?hash()
int hash(const char* key) {int hash = 0;while (*key) {hash += (*key++);  // 簡單累加ASCII值}return hash % 100;     // 映射到0-99的桶索引
}
  • 作用:將任意字符串鍵映射到固定范圍的索引

  • 特點

    • 簡單但容易產生沖突(如?"ab"?和?"ba"?哈希值相同)

    • 使用取模運算確保結果在桶數組范圍內

初始化函數?initMap()
void initMap(Map* map) {memset(map->buckets, 0, sizeof(map->buckets));map->size = 0;
}
  • 作用:初始化哈希表狀態

  • 關鍵操作

    • 將所有桶指針設為?NULL

    • 元素計數器?size?歸零

插入/更新函數?put()
void put(Map* map, const char* key, int value) {// 1. 計算哈希索引int index = hash(key);// 2. 檢查鍵是否已存在(更新值)Node* curr = map->buckets[index];while (curr) {if (strcmp(curr->key, key) == 0) {curr->value = value;return;}curr = curr->next;}// 3. 創建新節點(頭插法)Node* newNode = malloc(sizeof(Node));newNode->key = strdup(key);  // 復制鍵字符串newNode->value = value;newNode->next = map->buckets[index];map->buckets[index] = newNode;map->size++;
}
  • 特點

    • 鍵存在時更新值

    • 鍵不存在時使用頭插法添加新節點

    • 使用?strdup?深拷貝鍵字符串

查找函數?get()
int get(Map* map, const char* key, int* result) {int index = hash(key);Node* curr = map->buckets[index];while (curr) {if (strcmp(curr->key, key) == 0) {*result = curr->value;  // 通過指針返回結果return 1;  // 成功找到}curr = curr->next;}return 0;  // 未找到
}
  • 特點

    • 返回查找狀態(1成功/0失敗)

    • 通過指針參數?result?返回查找到的值

刪除函數?removeKey()
int removeKey(Map* map, const char* key) {int index = hash(key);Node* curr = map->buckets[index];Node* prev = NULL;while (curr) {if (strcmp(curr->key, key) == 0) {// 從鏈表中刪除節點if (prev) prev->next = curr->next;else map->buckets[index] = curr->next;// 釋放內存free(curr->key);free(curr);map->size--;return 1;  // 刪除成功}prev = curr;curr = curr->next;}return 0;  // 鍵不存在
}
  • 關鍵操作

    • 處理鏈表中間/頭部節點的刪除

    • 釋放鍵字符串和節點本身的內存

輔助函數
int size(Map* map) { return map->size; }  // 返回元素數量void clear(Map* map) {                   // 清空整個哈希表for (int i = 0; i < 100; i++) {Node* curr = map->buckets[i];while (curr) {Node* next = curr->next;free(curr->key);free(curr);curr = next;}map->buckets[i] = NULL;}map->size = 0;
}

3. 測試邏輯(main函數)

int main() {Map map;initMap(&map);  // 初始化// 插入測試put(&map, "apple", 10);put(&map, "banana", 5);put(&map, "orange", 8);// 查找測試int val;get(&map, "banana", &val);  // 輸出: banana: 5// 更新測試put(&map, "banana", 15);    // 更新值get(&map, "banana", &val);  // 輸出: updated banana: 15// 刪除測試removeKey(&map, "orange");printf("size after remove: %d\n", size(&map));  // 輸出: 2// 清空測試clear(&map);printf("final size: %d\n", size(&map));  // 輸出: 0return 0;
}

4. 代碼功能總結

  1. 核心數據結構

    • 實現了一個基于鏈地址法的哈希表

    • 支持字符串鍵(key)和整數值(value)的存儲

  2. 支持操作

    • put(): 插入/更新鍵值對

    • get(): 查找鍵對應的值

    • removeKey(): 刪除指定鍵

    • size(): 獲取元素數量

    • clear(): 清空整個哈希表

  3. 沖突解決

    • 使用鏈表解決哈希沖突(鏈地址法)

    • 每個桶是一個鏈表頭節點

  4. 內存管理

    • 動態分配節點內存

    • 使用?strdup?復制鍵字符串

    • 刪除/清空時釋放所有內存


5. 局限性及改進建議

  1. 固定桶大小

    • 桶數組固定為100,可能導致沖突率高

    • 改進:實現動態擴容(如負載因子>0.75時擴容)

  2. 簡單哈希函數

    • 當前哈希函數易產生沖突

    • 改進:使用更復雜的哈希算法(如djb2)

  3. 鍵類型限制

    • 僅支持字符串鍵

    • 改進:使用泛型支持多種鍵類型

  4. 線程安全

    • 非線程安全

    • 改進:添加互斥鎖實現線程安全

  5. 錯誤處理

    • 未處理內存分配失敗情況

    • 改進:添加NULL指針檢查


6. 實際應用場景

  1. 配置存儲:存儲程序配置參數(鍵值對)

  2. 緩存系統:實現簡單的內存緩存

  3. 詞頻統計:統計文本中單詞出現次數

  4. 符號表:編譯器中的變量管理

  5. 路由表:網絡設備中的IP路由查找

注:該代碼是本人自己所寫,可能不夠好,不夠簡便,歡迎大家指出我的不足之處。如果遇見看不懂的地方,可以在評論區打出來,進行討論,或者聯系我。上述內容全是我自己理解的,如果你有別的想法,或者認為我的理解不對,歡迎指出!!!如果可以,可以點一個免費的贊支持一下嗎?謝謝各位彥祖亦菲!!!!!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/84433.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/84433.shtml
英文地址,請注明出處:http://en.pswp.cn/web/84433.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Logback示例解析

<configuration><!-- 環境變量 --><springProperty scope"context" name"app.name" source"spring.application.name" defaultValue"application"/><!-- 日志存放路徑 --><property name"log.path&qu…

elementui響應式數據類型變更情況

背景。vue2。data中定義的響應數據類型是[]數組。應用在el-select中&#xff08;非multiple情況&#xff09;。當發生響應數據有變更渲染視圖時&#xff0c;發現定義的數組轉換成了字符串。 本身不是問題。但因為疏忽引發了watch監聽formData數據時產生了產生了多次監聽事件。…

人機融合智能 | 人智交互語境下的設計新模態

本章旨在探討技術與設計領域在人智交互語境下的關系及其影響,討論通過傳統設計對人智交互的優化方法。通過回顧大數據和發展趨勢,以 AI技術作為重要的技術推力,我們認為 AI技術將會在未來成為設計領域不可缺少的重要環節,并能夠幫助設計師更加高效、準確地開展設計工作。本章著…

C++設計模式分類(GOF-23種設計模式)

文章目錄 GOF-23 設計模式分類一、從目的分類1. 創建型&#xff08;Creational&#xff09;模式2. 結構型&#xff08;Structural&#xff09;模式3. 行為型&#xff08;Behavioral&#xff09;模式 二、從范圍分類1. 類模式&#xff08;Class Pattern&#xff09;2. 對象模式&…

AbMole| LY294002(M1925)

LY294002是一種廣譜的PI3K抑制劑&#xff0c;對PI3Kα/δ/β的IC50分別為0.5 μM/0.57 μM/0.97 μM。LY294002 也可以抑制 CK2 的活性&#xff0c;IC50 為 98 nM。LY294002 還是一種競爭性 DNA-PK 抑制劑&#xff0c;可逆結合 DNA-PK 的激酶結構域&#xff0c;IC50 為 1.4 μM…

第1章,[標簽 Win32] :第一個 WIn32 程序,MessageBox 函數

專欄導航 上一篇&#xff1a;第1章&#xff0c;[標簽 Win32] &#xff1a;第一個 WIn32 程序&#xff0c;程序入口 回到目錄 下一篇&#xff1a;無 本節前言 本節的學習&#xff0c;需要前兩節的內容作為先修知識。如果還沒有去看本專欄的前兩節&#xff0c;請你先去學習它…

求助帖:學Java開發方向還是網絡安全方向前景好

最近網絡安全被一個培訓機構吹得天花亂墜&#xff0c;雖然他家既有網安又有java和UI&#xff0c;我也是學軟件工程的&#xff08;山西某211&#xff0c;此機構是每年和我們學校合作的校企公司&#xff09;&#xff0c;但那里的老師仍然大力推薦我學網絡安全&#xff08;滲透、代…

OpenCV 圖像仿射變換之旋轉

一、知識點 1、void warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags INTER_LINEAR, int borderMode BORDER_CONSTANT, …

HCIP-數據通信基礎

前言&#xff1a;本博客僅作記錄學習使用&#xff0c;部分圖片出自網絡&#xff0c;如有侵犯您的權益&#xff0c;請聯系刪除 本篇筆記是根據B站上的視頻教程整理而成&#xff0c;感謝UP主的精彩講解&#xff01;如果需要了解更多細節&#xff0c;可以參考以下視頻&#xff1a;…

C語言基本數據類型與變量詳解

# C語言基本數據類型與變量詳解 ## 數據類型概述 在C語言中&#xff0c;數據類型決定了變量在內存中的存儲方式和大小&#xff0c;以及可以對其執行的操作。合理選擇數據類型能夠提高程序的效率和準確性&#xff0c;避免內存浪費和數據溢出等問題。 C語言的基本數據類型主要包括…

Babylon.js學習之路《十、高級幾何體:自定義模型與復雜形狀生成》

文章目錄 1. 引言&#xff1a;高級幾何體的應用場景2. 參數化建模&#xff1a;Babylon.MeshBuilder2.1 擴展幾何體類型2.2 自定義多邊形&#xff08;ExtrudePolygon&#xff09; 3. 頂點級建模&#xff1a;自定義VertexData3.1 手動定義頂點數據3.2 動態生成地形&#xff08;高…

【趙渝強老師】Kubernetes的安全框架

Kubernetes集群的安全框架主要由以下認證、鑒權和準入控制三個階段組成。這三個階段的關系如下圖所示。 視頻講解如下 【趙渝強老師】Kubernetes的安全框架 認證&#xff08;Authentication&#xff09; 當客戶端與Kubernetes集群建立HTTP通信時&#xff0c;首先HTTP請求會進…

CDN與靜態資源優化

CDN與靜態資源優化 在現代Web系統和AI應用中&#xff0c;隨著用戶訪問量的不斷攀升&#xff0c;靜態資源&#xff08;如HTML、CSS、JavaScript、圖片、音視頻、模型文件等&#xff09;帶來的負載日益沉重。尤其在大模型推理、前端渲染、廣告投放等場景中&#xff0c;靜態資源的…

如何填寫“appium inspector”內容?

1. 確認已經開啟appium的服務&#xff0c;運行appium 參考內容&#xff1a;{"appium:platformName": "Android", # 系統名稱"appium:platformVersion": "9", # 安卓版本&#xff0c;看設備"appium:deviceName": "3d…

mysql server層做了什么

服務器處理客戶端請求 服務器程序在處理來自客戶端的查詢請求時&#xff0c;大致需要分為3部分&#xff1a;連接管理、解析與優化、存儲引擎。 連接管理 每當有一個客戶端進程連接到服務器進程時&#xff0c;服務器進程都會創建一個線程專門處理與這個客戶端的交互&#xff…

APISIX 簡介:云原生 API 網關的架構與實踐

文章目錄 引言&#xff1a;APISIX 概述基于Nginx構建的原因基于etcd構建的原因 架構圖示架構分層解析管理層&#xff1a;人機交互與配置入口控制層&#xff1a;配置管理與集群協調數據面&#xff1a;請求處理與流量轉發說明&#xff1a;關于OpenRestry 引言&#xff1a;APISIX …

【AI作畫】第3章 LORA加載器

目錄 LORA加載器 管道信息 ?編輯 ?編輯 ?編輯 lora模型的串接 作品集 LORA加載器 前面我們已經分析過節點目錄了&#xff0c;現在我們來看一下LORA加載器。我們進行圖片渲染&#xff0c;一般都需要LORA模型的。 首先&#xff0c;我們“鼠標右鍵——添加節點——…

Xilinx XC7A12T?1CPG238I Artix?7 FPGA

XC7A12T?1CPG238I 以其獨特的性能與封裝組合&#xff0c;成為諸多工程師的首選方案。下面&#xff0c;我們從多個維度對這款芯片做深入剖析。 一、產品定位與封裝特點 XC7A12T?1CPG238I 屬于賽靈思&#xff08;Xilinx&#xff09;28?nm Artix?7 系列中的入門級型號&#x…

如何利用 Java 爬蟲獲得微店商品詳情:實戰指南

在電商領域&#xff0c;微店作為眾多商家的線上銷售渠道之一&#xff0c;其商品詳情數據對于市場分析、競品研究和商業決策具有重要價值。Java 爬蟲技術可以幫助我們高效地獲取這些數據。本文將詳細介紹如何使用 Java 編寫爬蟲&#xff0c;獲取微店商品詳情。 一、準備工作 &…

【Bug】MAUI自定義彈窗在IOS有異常背景

文章目錄 問題問題代碼原因解決處理Bug的具體步驟 問題 自定義彈窗有異常背景 問題代碼 <mct:Popup xmlns"http://schemas.microsoft.com/dotnet/2021/maui"xmlns:x"http://schemas.microsoft.com/winfx/2009/xaml"xmlns:converters"clr-names…