C 语言:用双向链表与哈希表实现高效 LRU 缓存及代码示例
以下是一个使用 C 语言实现的结合双向链表和哈希表的 LRU 缓存示例代码: ```c #include <stdio.h> #include <stdlib.h> // 双向链表节点结构体 typedef struct Node { int key; int value; struct Node *prev; struct Node *next; } Node; // 双向链表结构体 typedef struct DoublyLinkedList { Node *head; Node *tail; } DoublyLinkedList; // 创建新的双向链表节点 Node* createNode(int key, int value) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->key = key; newNode->value = value; newNode->prev = NULL; newNode->next = NULL; return newNode; } // 创建双向链表 DoublyLinkedList* createList() { DoublyLinkedList* list = (DoublyLinkedList*)malloc(sizeof(DoublyLinkedList)); list->head = NULL; list->tail = NULL; return list; } // 将节点添加到双向链表头部 void addToHead(DoublyLinkedList* list, Node* node) { if (list->head == NULL) { list->head = node; list->tail = node; } else { node->next = list->head; list->head->prev = node; list->head = node; } } // 移除双向链表尾部节点 Node* removeTail(DoublyLinkedList* list) { if (list->tail == NULL) { return NULL; } Node* tail = list->tail; if (list->tail->prev!= NULL) { list->tail->prev->next = NULL; list->tail = list->tail->prev; } else { list->head = NULL; list->tail = NULL; } return tail; } // 移动节点到双向链表头部 void moveToHead(DoublyLinkedList* list, Node* node) { if (node == list->head) { return; } if (node == list->tail) { list->tail = node->prev; list->tail->next = NULL; } else { node->prev->next = node->next; node->next->prev = node->prev; } node->next = list->head; node->prev = NULL; list->head->prev = node; list->head = node; } // 哈希表节点结构体 typedef struct HashNode { int key; Node* node; struct HashNode* next; } HashNode; // 哈希表结构体 typedef struct HashTable { HashNode buckets; int capacity; } HashTable; // 创建哈希表 HashTable* createHashTable(int capacity) { HashTable* table = (HashTable*)malloc(sizeof(HashTable)); table->buckets = (HashNode)malloc(capacity * sizeof(HashNode*)); table->capacity = capacity; for (int i = 0; i < capacity; i++) { table->buckets[i] = NULL; } return table; } // 哈希函数 int hashFunction(int key, int capacity) { return key % capacity; } // 在哈希表中查找节点 HashNode* findInHashTable(HashTable* table, int key) { int index = hashFunction(key, table->capacity); HashNode* curr = table->buckets[index]; while (curr!= NULL) { if (curr->key == key) { return curr; } curr = curr->next; } return NULL; } // 在哈希表中插入节点 void insertIntoHashTable(HashTable* table, int key, Node* node) { int index = hashFunction(key, table->capacity); HashNode* newNode = (HashNode*)malloc(sizeof(HashNode)); newNode->key = key; newNode->node = node; newNode->next = table->buckets[index]; table->buckets[index] = newNode; } // LRU 缓存结构体 typedef struct LRUCache { int capacity; DoublyLinkedList* list; HashTable* hashTable; } LRUCache; // 创建 LRU 缓存 LRUCache* createLRUCache(int capacity) { LRUCache* cache = (LRUCache*)malloc(sizeof(LRUCache)); cache->capacity = capacity; cache->list = createList(); cache->hashTable = createHashTable(capacity); return cache; } // 获取缓存中的值 int get(LRUCache* cache, int key) { HashNode* hashNode = findInHashTable(cache->hashTable, key); if (hashNode == NULL) { return -1; } Node* node = hashNode->node; moveToHead(cache->list, node); return node->value; } // 向缓存中添加值 void put(LRUCache* cache, int key, int value) { HashNode* hashNode = findInHashTable(cache->hashTable, key); if (hashNode!= NULL) { Node* node = hashNode->node; node->value = value; moveToHead(cache->list, node); return; } Node* newNode = createNode(key, value); addToHead(cache->list, newNode); insertIntoHashTable(cache->hashTable, key, newNode); if (cache->list->tail!= NULL && cache->list->tail->key!= key) { Node* removedNode = removeTail(cache->list); HashNode* removedHashNode = findInHashTable(cache->hashTable, removedNode->key); if (removedHashNode!= NULL) { int index = hashFunction(removedNode->key, cache->hashTable->capacity); HashNode* curr = cache->hashTable->buckets[index]; if (curr == removedHashNode) { cache->hashTable->buckets[index] = removedHashNode->next; } else { while (curr->next!= removedHashNode) { curr = curr->next; } curr->next = removedHashNode->next; } free(removedHashNode); free(removedNode); } } } // 打印双向链表 void printList(DoublyLinkedList* list) { Node* curr = list->head; while (curr!= NULL) { printf("Key: %d, Value: %d ", curr->key, curr->value); curr = curr->next; } printf("\n"); } // 测试示例 int main() { LRUCache* cache = createLRUCache(2); put(cache, 1, 10); put(cache, 2, 20); printf("Get 1: %d\n", get(cache, 1)); put(cache, 3, 30); printf("Get 2: %d\n", get(cache, 2)); put(cache, 4, 40); printf("Get 1: %d\n", get(cache, 1)); printf("Get 3: %d\n", get(cache, 3)); printf("Get 4: %d\n", get(cache, 4)); return 0; } ``` 这段代码实现了一个简单的 LRU 缓存,使用双向链表维护缓存的访问顺序,使用哈希表加速查找。在 `main` 函数中进行了一些基本的操作和测试。 ######[AI写代码神器 | 1855点数解答 | 2024-11-12 22:46:34]
- C#工程师必知:数组、链表、哈希、队列、栈数据结构优缺点大揭秘! (百度文心 | 561点数解答 | 2023-11-09 17:56:30)280
- Java实现链表反转:迭代与递归双解法详解及开发实战指南(DeepSeek | 1409点数解答 | 2026-03-15 15:09:29)61
- Python 实现球类:精准计算半径、表面积与体积,附输入验证与异常处理!(阿里通义 | 261点数解答 | 2024-11-28 21:19:39)384
- 巴黎奥运:中国女排淘汰赛对决土耳其,朱婷成致胜关键!(字节豆包 | 448点数解答 | 2024-08-06 15:59:48)182
- 代码揭秘:多函数实现页面置换算法及相关操作(字节豆包 | 60点数解答 | 2024-12-13 20:02:21)305
- C语言实现FIFO、Optimal和LRU页面置换算法:代码详解与注意要点(阿里通义 | 858点数解答 | 2024-12-13 20:03:47)337
- Java 实现仿 Windows 资源管理器:文件管理器功能全解析与代码示例(字节豆包 | 623点数解答 | 2025-01-01 14:59:04)271
- 探寻数组中最长摆动子序列长度:思路剖析与代码优化(GPT | 758点数解答 | 2024-12-23 23:18:29)291
- 独家剖析:求解数组最长摆动子序列长度的代码实现与改进建议(GPT | 350点数解答 | 2024-12-23 23:20:54)291
- Three.js 示例代码解析:优化场景渲染与注意要点(字节豆包 | 164点数解答 | 2025-02-27 23:30:20)287
- 51 单片机:定时器 0 实现 8 个 LED 循环点亮,附代码及优化建议(字节豆包 | 1193点数解答 | 2024-12-27 15:10:29)353
- 用 JS 中 for 循环实现 1 到 100 相加并输出结果到页面的完整代码 ( | 240点数解答 | 2024-05-20 22:11:29)501