數據結構-散列表查找(哈希表)

一,散列表查找定義

? ?散列技術是在記錄的存儲位置和它的關鍵字之間建立一個確定的對應關系f,使得每個關鍵字key對應一個存儲位置f(key)。查找時,根據這個確定的對應關系找到給定值key的映射f(key),若查找集中存在這個記錄,則必定在f(key)的位置。

這里我們把這種對應關系f稱為散列函數,又稱為哈希(Hash)函數。

采用散列技術將記錄存儲在一塊連續的存儲空間中,這塊連續存儲空間稱為散列表或哈希表(Hash table)。

那么關鍵字對應的記錄存儲位置稱為散列地址。

二、核心組成部分

  1. 哈希函數(Hash Function)

    • 作用:將任意大小的鍵(Key)轉換為固定范圍的整數(通常作為數組索引)。

    • 設計要求

      • 確定性:同一鍵的哈希值必須相同。

      • 均勻性:鍵的哈希值應盡可能均勻分布,減少沖突。

      • 高效性:計算速度快。

    • 常見哈希函數

      • 取模運算:hash(key) = key % size(需注意size通常為質數)。

      • 乘法哈希:利用浮點數運算和取模。

      • 加密哈希(如MD5、SHA-1):用于分布式系統或安全性場景。

  2. 沖突解決(Collision Resolution)

    • 沖突原因:不同鍵可能生成相同的哈希值。

    • 解決方法

      • 開放尋址法(Open Addressing)

        • 當沖突發生時,按某種規則尋找下一個可用位置。

        • 探測方式

          • 線性探測:依次檢查下一個位置(index = (hash(key) + i) % size)。

          • 二次探測:按平方跳躍(index = (hash(key) + i2) % size)。

          • 雙重哈希:使用第二個哈希函數計算步長(index = (hash1(key) + i * hash2(key)) % size)。

        • 缺點:易產生聚集效應,刪除操作需標記為“已刪除”。

      • 鏈地址法(Separate Chaining)

        • 每個桶(Bucket)存儲一個鏈表(或樹),沖突元素追加到鏈表中。

        • 優化:鏈表長度過長時轉換為紅黑樹(如Java 8的HashMap)。

        • 優點:實現簡單,適合頻繁插入/刪除的場景。

三、哈希表操作

  1. 插入(Insert)

    • 計算鍵的哈希值,找到對應位置。

    • 若位置為空,直接插入;若沖突,按沖突解決策略處理。

  2. 查找(Search)

    • 計算哈希值定位桶,遍歷鏈表(鏈地址法)或探測后續位置(開放尋址法),直到找到鍵或確認不存在。

  3. 刪除(Delete)

    • 類似查找操作,找到元素后標記刪除(開放尋址法需特殊標記)或從鏈表中移除。

四,散列函數的構造方法

1.直接定址法

核心思想為:直接使用鍵的值作為哈希表的存儲位置,無需復雜的哈希計算,因此可以完全避免沖突。

1.1 直接定址法的定義

  • 基本思想
    當鍵的取值范圍較小且連續時(例如鍵是整數,范圍在?[0, N-1]),可以直接使用鍵本身作為數組的索引。此時,哈希函數為:

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?hash(key)=key

    即直接將鍵映射到數組的對應位置。

  • 適用條件
    鍵的取值必須滿足以下兩個條件:

    1. 范圍有限:鍵的取值范圍不能過大,否則需要極大數組,浪費內存。

    2. 連續分布:鍵的取值是連續的(或接近連續),避免數組中出現大量未使用的空洞。

1.2 工作原理

  1. 初始化:創建一個大小為?𝑁N?的數組(𝑁N?為鍵的最大值加1)。

  2. 插入操作:將鍵?𝑘k?對應的值存儲在數組的第?𝑘k?個位置。

    array[key] = value
  3. 查找操作:直接訪問數組的第?𝑘k?個位置獲取值。

    value = array[key]
  4. 刪除操作:將數組的第?𝑘k?個位置標記為空或賦予特定值(如?None)。

1.3 適用場景

  1. 鍵為小范圍整數

    • 如學號、員工編號、IP地址的最后8位(0-255)等。

  2. 內存充足且追求極致性能

    • 如實時系統中的關鍵數據查詢。

  3. 無沖突要求的場景

    • 如某些硬件設計或嵌入式系統,需嚴格避免哈希沖突。

1.4 示例代碼

#include <stdio.h>
#include <stdlib.h>typedef struct {int max_key;int* table;
} DirectAddressTable;DirectAddressTable* createTable(int max_key) {DirectAddressTable* da_table = (DirectAddressTable*)malloc(sizeof(DirectAddressTable));if (!da_table) return NULL;da_table->max_key = max_key;da_table->table = (int*)malloc(sizeof(int) * (max_key + 1));if (!da_table->table) {free(da_table);return NULL;}for (int i = 0; i <= max_key; i++) {da_table->table[i] = -1;}return da_table;
}void insert(DirectAddressTable* da_table, int key, int value) {if (key < 0 || key > da_table->max_key) {printf("Error: Key %d out of range [0, %d]\n", key, da_table->max_key);return;}da_table->table[key] = value;
}int search(DirectAddressTable* da_table, int key) {if (key < 0 || key > da_table->max_key) {printf("Error: Key %d out of range [0, %d]\n", key, da_table->max_key);return -1;}return da_table->table[key];
}// 修改函數名為 deleteKey
void deleteKey(DirectAddressTable* da_table, int key) {if (key < 0 || key > da_table->max_key) {printf("Error: Key %d out of range [0, %d]\n", key, da_table->max_key);return;}da_table->table[key] = -1;
}void destroyTable(DirectAddressTable* da_table) {if (da_table) {free(da_table->table);free(da_table);}
}int main() {DirectAddressTable* table = createTable(999);if (!table) {printf("Failed to create table!\n");return 1;}insert(table, 123, 100);insert(table, 456, 200);insert(table, 999, 300);insert(table, 1000, 400); // 觸發越界錯誤printf("Key 123: %d\n", search(table, 123)); // 100printf("Key 456: %d\n", search(table, 456)); // 200deleteKey(table, 456); // 修改為 deleteKeyprintf("After delete Key 456: %d\n", search(table, 456)); // -1destroyTable(table);return 0;
}

?

2.開放定址法

? 所謂的開放定址法就是一旦發生了沖突,就去尋找下一個空的散列地址,只要散列表組足夠大,空的散列表地址總能找到,并將記錄存入

2.1 核心思想

  1. 基本規則

    • 當插入或查找時,若目標位置已被占用(發生沖突),則按預定的探測序列依次檢查后續位置,直到找到空槽或目標鍵。

    • 所有操作(插入、查找、刪除)必須遵循相同的探測規則。

  2. 關鍵特點

    • 內存緊湊:所有數據存儲在數組中,無額外指針開銷。

    • 探測序列設計:探測方式直接影響性能,需避免聚集(Clustering)現象。

    • 刪除需標記:直接刪除元素會導致探測鏈斷裂,需用特殊標記(如TOMBSTONE)占位。

2.2 探測方法

探測序列的設計是開放定址法的核心。以下是三種常見探測方式:

1. 線性探測(Linear Probing)
  • 規則
    若位置?hash(key)?沖突,則依次檢查?(hash(key) + i) % sizei=1,2,3...)。

  • 示例

    • 插入鍵?k1(哈希到位置 3),沖突后存入位置 4。

    • 插入鍵?k2(哈希到位置 3),沖突后存入位置 5。

  • 優點

    • 實現簡單,緩存友好(連續內存訪問)。

  • 缺點

    • 易產生聚集(Clustering):連續沖突形成長鏈,降低效率。

2. 二次探測(Quadratic Probing)
  • 規則
    沖突后檢查?(hash(key) + c1*i + c2*i2) % sizei=1,2,3...,通常取?c1=1,?c2=1)。

  • 示例

    • 插入鍵?k1(哈希到位置 3),沖突后依次檢查位置 4(3+1)、6(3+1+12)、...

  • 優點

    • 減少聚集現象,分布更均勻。

  • 缺點

    • 探測序列可能無法覆蓋所有槽位(需哈希表大小為質數且負載因子≤0.5)。

3. 雙重哈希(Double Hashing)
  • 規則
    使用第二個哈希函數計算步長:

    index=(hash1(𝑘𝑒𝑦)+𝑖×hash2(𝑘𝑒𝑦))?%?sizeindex=(hash1(key)+i×hash2(key))?%?size
    • hash2(key)?不能為0,通常設計為?hash2(key) = R - (key % R)R?為小于表大小的質數)。

  • 示例

    • hash1(k)=3hash2(k)=5,沖突后探測位置 8, 13, 18...

  • 優點

    • 最接近理想均勻分布,沖突率最低。

  • 缺點

    • 計算成本略高,需設計兩個哈希函數。

?2.3 代碼示例

#include <stdio.h>
#include <stdlib.h>#define SIZE 10
#define TOMBSTONE -2typedef struct {int key;int value;
} Entry;typedef struct {Entry* table;int size;int count;  // 有效元素數(不含TOMBSTONE)
} OpenAddressHashTable;OpenAddressHashTable* createHashTable() {OpenAddressHashTable* ht = (OpenAddressHashTable*)malloc(sizeof(OpenAddressHashTable));ht->size = SIZE;ht->count = 0;ht->table = (Entry*)malloc(sizeof(Entry) * SIZE);for (int i = 0; i < SIZE; i++) {ht->table[i].key = -1;  // -1表示空位}return ht;
}int hash1(int key) {return key % SIZE;
}int hash2(int key) {return 7 - (key % 7);  // 7為小于SIZE的質數
}int probe(int key, int i) {return (hash1(key) + i * hash2(key)) % SIZE;
}void insert(OpenAddressHashTable* ht, int key, int value) {if (ht->count >= ht->size * 0.7) {printf("Warning: Load factor exceeds 0.7, consider rehashing.\n");}for (int i = 0; i < ht->size; i++) {int index = probe(key, i);if (ht->table[index].key == -1 || ht->table[index].key == TOMBSTONE) {ht->table[index].key = key;ht->table[index].value = value;ht->count++;return;} else if (ht->table[index].key == key) {ht->table[index].value = value;  // 更新現有鍵return;}}printf("Error: Hash table is full!\n");
}int search(OpenAddressHashTable* ht, int key) {for (int i = 0; i < ht->size; i++) {int index = probe(key, i);if (ht->table[index].key == key) {return ht->table[index].value;} else if (ht->table[index].key == -1) {return -1;  // 未找到}}return -1;
}// 修改函數名為 deleteKey
void deleteKey(OpenAddressHashTable* ht, int key) {for (int i = 0; i < ht->size; i++) {int index = probe(key, i);if (ht->table[index].key == key) {ht->table[index].key = TOMBSTONE;ht->count--;return;} else if (ht->table[index].key == -1) {return;  // 未找到}}
}void destroyHashTable(OpenAddressHashTable* ht) {free(ht->table);free(ht);
}int main() {OpenAddressHashTable* ht = createHashTable();insert(ht, 5, 100);insert(ht, 15, 200);  // 沖突,使用雙重哈希探測printf("Search 5: %d\n", search(ht, 5));   // 100printf("Search 15: %d\n", search(ht, 15)); // 200deleteKey(ht, 5);  // 原 delete(ht, 5)printf("After delete, Search 5: %d\n", search(ht, 5)); // -1destroyHashTable(ht);return 0;
}

3.再散列函數法(Rehashing/雙散列法)

核心思想

當哈希沖突發生時,通過第二個(或更多)哈希函數重新計算存儲位置,直到找到空閑的槽位。屬于開放定址法的一種。

工作流程
  1. 首次哈希:用第一個哈希函數??1(𝑘𝑒𝑦)h1?(key)?計算初始位置。

  2. 沖突處理:若沖突,用第二個哈希函數??2(𝑘𝑒𝑦)h2?(key)?計算偏移量,按公式?(?1+𝑖×?2)%表大小(h1?+i×h2?)%表大小?探測(𝑖i?為嘗試次數)。

  3. 重復探測:直到找到空位或遍歷全表。

示例

假設??1(𝑘)=𝑘%7h1?(k)=k%7,?2(𝑘)=5?(𝑘%5)h2?(k)=5?(k%5),插入鍵 23 和 30:

  • 23 →?23%7=223%7=2(直接插入位置2)

  • 30 →?30%7=230%7=2(沖突),計算偏移??2(30)=5?0=5h2?(30)=5?0=5,新位置?(2+1×5)%7=0(2+1×5)%7=0

優缺點
  • 優點:減少聚集現象,探測序列分布均勻。

  • 缺點:多次計算可能耗時,需合理設計哈希函數避免循環。

應用場景
  • 內存受限環境(無需額外指針)。

  • 預期沖突率較低的場景(如數據庫索引)。

4.鏈地址法(拉鏈法/Separate Chaining)

4.1核心思想

每個哈希桶維護一個鏈表(或樹),沖突元素直接追加到鏈表中。哈希表退化為“鏈表數組”。

4.2 工作流程

  1. 哈希計算:用??(𝑘𝑒𝑦)h(key)?找到桶位置。

  2. 鏈表操作

    • 插入:將新元素插入鏈表頭部或尾部。

    • 查找:遍歷鏈表比對鍵值。

    • 刪除:找到節點后斷開鏈接。

4.3 示例

哈希函數??(𝑘)=𝑘%3h(k)=k%3,插入 3, 6, 9:

  • 桶0:3 → 9(插入到鏈表)

  • 桶1:空

  • 桶2:6

4.4 優化策略

  • 鏈表轉紅黑樹:當鏈表長度超過閾值(如Java HashMap的閾值8),轉為樹結構提升查詢效率。

4.5 優缺點

  • 優點:處理高沖突高效,實現簡單,適合動態數據。

  • 缺點:指針占用額外內存,鏈表過長影響性能。

4.6 應用場景

  • Java HashMap、C++ unordered_map。

  • 頻繁插入刪除的場景。

5.公共溢出區法

5.1 核心思想

將哈希表分為主表和溢出區,沖突元素統一存放到獨立的溢出區域。

5.2 工作流程

  1. 主表插入:通過??(𝑘𝑒𝑦)h(key)?找到主表位置。

  2. 溢出處理:若主表位置已占用,將元素存入溢出區(順序存儲或鏈表結構)。

  3. 查找邏輯:先查主表,未命中則遍歷溢出區。

5.3 示例

主表大小5,溢出區大小3。插入鍵 5, 10, 15(假設??(𝑘)=𝑘%5h(k)=k%5):

  • 主表位置0:5

  • 主表位置0沖突,10和15存入溢出區。

5.4 管理策略

  • 溢出區結構:可采用順序表(簡單但查詢慢)或鏈表(需額外指針)。

  • 合并整理:定期將溢出區數據遷移回主表(需重新哈希)。

5.5 優缺點

  • 優點:實現簡單,主表結構穩定。

  • 缺點:溢出區可能成為性能瓶頸,需合理設計大小。

5.6 應用場景

  • 嵌入式系統等內存布局固定的場景。

  • 沖突較少或數據規模可預估的情況。

五,散列表查找實現

1.散列表查找算法實現

無論采用何種沖突解決方法,查找的核心步驟均為:

  1. 計算哈希值:用哈希函數計算鍵的初始位置。

  2. 定位元素

    • 若當前位置的鍵匹配 → 返回數據。

    • 若位置為空 → 表示不存在該鍵。

    • 若位置被占用但鍵不匹配 → 按沖突策略繼續查找。

  3. 處理沖突:根據沖突解決策略(如開放定址法、鏈地址法)繼續探測。

示例代碼:

#include <stdio.h>
#include <stdlib.h>#define SUCCESS 1
#define UNSUCCESS 0
#define HASHSIZE 12    // 散列表長度
#define NULLKEY -32768 // 空標記
#define OK 1
#define ERROR 0typedef int Status;typedef struct {int *elem;      // 數據存儲基址int count;      // 元素個數
} HashTable;int m = 0;          // 全局表長/* 初始化散列表 */
Status InitHashTable(HashTable *H) {m = HASHSIZE;H->count = m;H->elem = (int *)malloc(m * sizeof(int));for (int i = 0; i < m; i++) {H->elem[i] = NULLKEY;}return OK;
}/* 散列函數(除留余數法) */
int Hash(int key) {return key % m;
}/* 插入關鍵字 */
void InsertHash(HashTable *H, int key) {int addr = Hash(key);// 線性探測解決沖突while (H->elem[addr] != NULLKEY) {addr = (addr + 1) % m;}H->elem[addr] = key;
}/* 查找關鍵字 */
Status SearchHash(HashTable H, int key, int *addr) {*addr = Hash(key);// 記錄初始探測位置int startAddr = *addr;while (H.elem[*addr] != key) {*addr = (*addr + 1) % m;// 遇到空位或回到起點說明不存在if (H.elem[*addr] == NULLKEY || *addr == startAddr) {return UNSUCCESS;}}return SUCCESS;
}int main() {HashTable H;int keys[] = {12, 67, 56, 16, 25, 37, 22, 29, 15, 47, 48, 34};int n = sizeof(keys)/sizeof(keys[0]);// 初始化散列表if (InitHashTable(&H) != OK) {printf("初始化失敗!\n");return 1;}// 插入數據for (int i = 0; i < n; i++) {InsertHash(&H, keys[i]);}// 驗證插入結果printf("散列表內容:");for (int i = 0; i < m; i++) {printf("%d ", H.elem[i]);}printf("\n");// 查找測試int target = 37;int addr;if (SearchHash(H, target, &addr) {printf("找到%d,位置:%d\n", target, addr);} else {printf("未找到%d\n", target);}free(H.elem);return 0;
}

六、優缺點分析

  • 優點

    • 平均時間復雜度O(1),適合高頻查詢場景。

    • 靈活支持動態數據。

  • 缺點

    • 哈希函數設計不當會導致沖突頻繁,性能退化至O(n)。

    • 內存預分配可能浪費空間。

    • 無法保證元素順序(有序哈希表需額外設計)。

七、應用場景

  1. 字典(Dictionary):如Python的dict、C++的unordered_map

  2. 緩存系統:如Redis、Memcached。

  3. 數據庫索引:加速數據檢索。

  4. 唯一性檢查:快速判斷元素是否存在(如布隆過濾器)。

八、優化與變種

  1. 完美哈希(Perfect Hashing):無沖突的哈希函數,適用于靜態數據集。

  2. 一致性哈希(Consistent Hashing):用于分布式系統,減少節點增減時的數據遷移。

  3. 布隆過濾器(Bloom Filter):基于哈希的概率數據結構,用于高效判斷元素是否存在。

九、代碼實現示例(Python)

class HashTable:def __init__(self, size=10):self.size = sizeself.table = [[] for _ in range(size)]  # 鏈地址法def _hash(self, key):return hash(key) % self.size  # 使用內置哈希函數取模def insert(self, key, value):idx = self._hash(key)for item in self.table[idx]:if item[0] == key:item[1] = value  # 更新現有鍵returnself.table[idx].append([key, value])  # 插入新鍵def get(self, key):idx = self._hash(key)for item in self.table[idx]:if item[0] == key:return item[1]raise KeyError(f"Key {key} not found")def delete(self, key):idx = self._hash(key)for i, item in enumerate(self.table[idx]):if item[0] == key:del self.table[idx][i]returnraise KeyError(f"Key {key} not found")

十、總結

哈希表通過巧妙的哈希函數和沖突解決策略,在時間與空間之間實現高效平衡。理解其原理和實現細節,有助于在開發中選擇合適的優化策略(如動態擴容、鏈與樹的轉換),應對不同場景的需求。

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

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

相關文章

Stable Diffusion 簡單了解一下

1. 幫我簡單介紹一下:StableDiffusion ?? Stable Diffusion 是什么? Stable Diffusion 是一個 文本生成圖像(Text-to-Image) 的人工智能模型。你只需要輸入一句話,它就能根據這句話生成一張高質量的圖片。 比如: "一只穿著太空服的貓,在月球上彈吉他"St…

R語言科研編程-標準偏差柱狀圖

生成隨機數據 在R中&#xff0c;可以使用rnorm()生成正態分布的隨機數據&#xff0c;并模擬分組數據。以下代碼生成3組&#xff08;A、B、C&#xff09;隨機數據&#xff0c;每組包含10個樣本&#xff1a; set.seed(123) # 確保可重復性 group_A <- rnorm(10, mean50, sd…

普羅米修斯監控CPU\內存匯聚圖

要找出內存使用率大于80%的主機&#xff0c;你可以使用以下PromQL查詢。這個查詢會計算每個節點的內存使用率&#xff0c;然后篩選出使用率超過80%的節點&#xff1a; (avg by(nodename) ((node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes)* on(instance) group…

飛牛fnNAS手機相冊備份及AI搜圖

目錄 一、相冊安裝應用 二、手機開啟自動備份 三、開始備份 四、照片檢索 五、AI搜圖設置 六、AI搜圖測試 七、照片傳遞 現代的手機,已經成為我們最親密的“伙伴”。自從手機拍照性能提升后,手機已經完全取代了簡單的卡片相機,而且與入門級“單反”相機發起了挑戰。在…

華為高斯數據庫(GaussDB)深度解析:國產分布式數據庫的旗艦之作

高斯數據庫介紹 一、高斯數據庫概述 GaussDB是華為自主研發的新一代分布式關系型數據庫&#xff0c;專為企業核心系統設計。它支持HTAP&#xff08;混合事務與分析處理&#xff09;&#xff0c;兼具強大的事務處理與數據分析能力&#xff0c;是國產數據庫替代的重要選擇。 產…

網頁 CSS美化2(詳解)

這是接著上一篇css基礎的第二篇&#xff1a;主要開始對頁面的布局進行學習 顯示模式&#xff1a; 塊級模式&#xff08;Block&#xff09; 特點 &#xff1a; 元素會獨占一行&#xff0c;在其前后會自動換行&#xff0c;與其他塊級元素在垂直方向上排列。 寬度默認為所在容器…

JSON解析性能優化全攻略:協程調度器選擇與線程池饑餓解決方案

簡介 JSON解析是現代應用開發中的基礎操作,但在使用協程處理時,若調度器選擇不當,會導致性能嚴重下降。特別是當使用Dispatchers.IO處理JSON解析時,可能觸發線程池饑餓,進而引發ANR或系統卡頓。本文將深入剖析這一問題的技術原理,提供全面的性能檢測方法,并給出多種優化…

python打卡第37天

知識點回顧&#xff1a; 過擬合的判斷&#xff1a;測試集和訓練集同步打印指標模型的保存和加載 僅保存權重保存權重和模型保存全部信息checkpoint&#xff0c;還包含訓練狀態 早停策略 作業&#xff1a;對信貸數據集訓練后保存權重&#xff0c;加載權重后繼續訓練50輪&#xf…

【洛谷P9303題解】AC- [CCC 2023 J5] CCC Word Hunt

在CCC單詞搜索游戲中&#xff0c;單詞隱藏在一個字母網格中。目標是確定給定單詞在網格中隱藏的次數。單詞可以以直線或直角的方式排列。以下是詳細的解題思路及代碼實現&#xff1a; 傳送門&#xff1a; https://www.luogu.com.cn/problem/P9303 解題思路 輸入讀取與初始化&…

LangGraph + LLM + stream_mode

文章目錄 LLM 代碼valuesmessagesupdatesmessages updatesmessages updates 2 LLM 代碼 from dataclasses import dataclassfrom langchain.chat_models import init_chat_model from langgraph.graph import StateGraph, STARTfrom langchain_openai import ChatOpenAI # 初…

Pydantic 學習與使用

Pydantic 學習與使用 在 Fastapi 的 Web 開發中的數據驗證通常都是在使用 Pydantic 來進行數據的校驗&#xff0c;本文將對 Pydantic 的使用方法做記錄與學習。 **簡介&#xff1a;**Pydantic 是一個在 Python 中用于數據驗證和解析的第三方庫&#xff0c;它現在是 Python 使…

批量文件重命名工具

分享一個自己使用 python 開發的小軟件&#xff0c;批量文件重命名工具&#xff0c;主要功能有批量中文轉拼音&#xff0c;簡繁體轉換&#xff0c;大小寫轉換&#xff0c;替換文件名&#xff0c;刪除指定字符&#xff0c;批量添加編號&#xff0c;添加前綴/后綴。同時還有文件時…

多語言視角下的 DOM 操作:從 JavaScript 到 Python、Java 與 C#

多語言視角下的 DOM 操作&#xff1a;從 JavaScript 到 Python、Java 與 C# 在 Web 開發中&#xff0c;文檔對象模型&#xff08;DOM&#xff09;是構建動態網頁的核心技術。它將 HTML/XML 文檔解析為樹形結構&#xff0c;允許開發者通過編程方式訪問和修改頁面內容、結構和樣…

【C/C++】紅黑樹學習筆記

文章目錄 紅黑樹1 基本概念1.1 定義1.2 基本特性推理1.3 對比1.4 延伸1.4.1 簡單判別是否是紅黑樹1.4.2 應用 2 插入2.1 插入結點默認紅色2.2 插入結點2.2.1 插入結點是根結點2.2.2 插入結點的叔叔是紅色2.2.3 插入結點的叔叔是黑色場景分析LL型RR型LR型RL型 3 構建4 示例代碼 …

網絡通信的基石:深入理解幀與報文

在這個萬物互聯的時代&#xff0c;我們每天都在享受著網絡帶來的便利——從早晨查看天氣預報&#xff0c;到工作中的視頻會議&#xff0c;再到晚上刷著短視頻放松。然而&#xff0c;在這些看似簡單的網絡交互背后&#xff0c;隱藏著精密而復雜的數據傳輸機制。今天&#xff0c;…

STM32 SPI通信(硬件)

一、SPI外設簡介 STM32內部集成了硬件SPI收發電路&#xff0c;可以由硬件自動執行時鐘生成、數據收發等功能&#xff0c;減輕CPU的負擔 可配置8位/16位數據幀、高位先行/低位先行 時鐘頻率&#xff1a; fPCLK / (2, 4, 8, 16, 32, 64, 128, 256) 支持多主機模型、主或從操作 可…

尚硅谷redis7-11-redis10大類型之總體概述

前提&#xff1a;我們說的數據類型一般是value的數據類型&#xff0c;key的類型都是字符串。 redis字符串【String】 string類型是二進制安全的,意思是redis的string可以包含任何數據,比如jpg圖片或者序列化的對象。 string類型是Redis最基本的數據類型,一個redis中字符串va…

【遞歸、搜索與回溯算法】專題一 遞歸

文章目錄 0.理解遞歸、搜索與回溯1.面試題 08.06.漢諾塔問題1.1 題目1.2 思路1.3 代碼 2. 合并兩個有序鏈表2.1 題目2.2 思路2.3 代碼 3.反轉鏈表3.1 題目3.2 思路3.3 代碼 4.兩兩交換鏈表中的節點4.1 題目4.2 思路4.3 代碼 5. Pow(x, n) - 快速冪5.1 題目5.2 思路5.3 代碼 0.理…

C#實現List導出CSV:深入解析完整方案

C#實現List導出CSV&#xff1a;深入解析完整方案 在數據交互場景中&#xff0c;CSV文件憑借其跨平臺兼容性和簡潔性&#xff0c;成為數據交換的重要載體。本文將基于C#反射機制實現的通用CSV導出方案&#xff0c;結合實際開發中的痛點&#xff0c;從基礎實現、深度優化到生產級…

字符串day7

344 反轉字符串 字符串理論上也是一個數組&#xff0c;因此只需要用雙指針即可 class Solution { public:void reverseString(vector<char>& s) {for(int i0,js.size()-1;i<j;i,j--){swap(s[i],s[j]);}} };541 反轉字符串 自己實現一個反轉從start到end的字符串…