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` 函数中进行了一些基本的操作和测试。 [2024-11-12 22:46:34 | AI写代码神器 | 1855点数解答]
- 作为c#工程师,数组、链表、哈希、队列、栈数据结构特点,各⾃优点和缺点?(561点数解答 | 2023-11-09 17:56:30)164
- import math class ball: """ 实现 def __init__(self, radius) 函数, 他有一个参数radius, 并为对象初始化一个变量self.radius """ """ 实现 def surface_area(self) 函数, 通过self.radius计算球的表面积, 并将这个表面积返回 """ """ 实现 def volume(self) 函数, 通过self.radius计算球的体积, 并将这个体积返回 """ """ 在评测文件中将这样调用这个类 ball = ball(eval(input())) print("球的半径:{:.2f}".format(ball.radius)) print("球的表面积:{:.2f}".format(ball.surface_area())) print("球的体积:{:(261点数解答 | 2024-11-28 21:19:39)177
- 商品展示模块 前端页面:productlist.jsp、productdetail.jsp 后端逻辑:productservlet 处理获取商品列表与详情请求 实现商品分页显示、按类别或关键词搜索功能 前端页面渲染与交互 使用 jsp、el、jstl 渲染商品数据 使用 css 优化页面样式,确保用户界面美观统一 使用 javascript 实现简单的前端交互,如商品图片切换、下拉菜单 搜索与过滤功能 在 productlist.jsp 实现搜索栏,允许用户输入关键词进行搜索 后端根据搜索条件查询数据库,返回符合条件的商品列表 使用 jstl 循环输出商品数据,并实现价格或类别过滤选项(19点数解答 | 2024-12-13 15:00:43)196
- #include<stdio.h> #include<stdlib.h> #include<time.h> int producerand(int remainder); void initprocess(); void chosedisplace(); struct linknode* fifo(struct linknode* head, int randcount); void optimal(struct linknode* head, int randprocess); struct linknode* lru(struct linknode* head, int randprocess); struct linknode* initlink(); void choicestey(); int allotment(struct linknode* head); int checkfifooptimal(struct linknode* head, int checkpage); void recover(struct linknode* head, int randproc(60点数解答 | 2024-12-13 20:02:21)188
- #include<stdio.h> #include<stdlib.h> #include<time.h> int producerand(int remainder); void initprocess(); void chosedisplace(); struct linknode* fifo(struct linknode* head, int randcount); void optimal(struct linknode* head, int randprocess); struct linknode* lru(struct linknode* head, int randprocess); struct linknode* initlink(); void choicestey(); int allotment(struct linknode* head); int checkfifooptimal(struct linknode* head, int checkpage); void recover(struct linknode* head, int randproc(858点数解答 | 2024-12-13 20:03:47)167
- [问题描述]windows 资源管理器(file explorer)是 windows 操作系统中用于管理文件和文件夹的文件管理器,为用户在 windows 操作系统中进行文件和文件夹管理提供了便利和多样的功能。请模拟该软件完成一个自己的文件管理器,具体要求如下:(1) 文件和文件夹操作(60 分):可以创建、复制、粘贴、移动、重命名和删除文件和文件夹。(2) 导航和路径(10 分):允许用户在文件系统中导航,查看文件路径和目录结构,以快速定位文件或文件夹。(3) 搜索(10 分):提供搜索功能,可以按文件名、文件类型、修改日期等进行搜索并定位文件。(4) 文件属性(10 分):允许查看文件的属性,如大小、创建日期、修改日期和文件类型等。(5) 快速访问(10 分):提供快速访问常用文件夹和最近访问的文件功能,方便用户快速打开常用文件或文件夹。(6) 标签页(附加 10 分):允许用户以标签页形式打开多个文件资源管理器窗口,方便在4不同位置之间进行拖放操作或文件整理。[测试数据]参考操作系统中资源管理器。[实现提示]可能用到树、链表、哈希表、栈、队列、图等。,语言方向:Java,系统环(623点数解答 | 2025-01-01 14:59:04)127
- 题目:按照以下步骤在 pycharm 中进行自动化测试脚本编写,并执行脚本。 步骤: (1)从 selenium 中引入 webdriver; (2)使用 selenium 模块的 webdriver 打开谷歌浏览器; (3)在谷歌浏览器中通过 get 方法发送网址eshop测试平台登录页面; (4)增加智能时间等待 5 秒; (5)查看登录页面中的用户名输入框元素,通过 css_selector 属性定位用户名输入框,并输入用户名(用自己注册的用户); (6)查看登录页面中的密码输入框元素,通过 xpath 属性定位密码输入框,并输入密码(用自己注册的用户对应密码) ; (7)查看登录页面中的登录按钮元素,通过 class_name 方法定位登录按钮,使用 click()方法点击登录按钮进入eshop测试平台首页; (8)在eshop测试平台首页通过 link_text 方法对“我的订单”按钮进行定位,使用 click()方法点击“我的订单”(304点数解答 | 2024-11-06 15:38:30)273
- 循环点亮 led 灯: (1) 使用定时器to 的方式 1,实现 8个 led 由上至下间隔 1s 流动,其中每个 led 亮 0.5s,灭0.5s,一直重复。。 (2) 使用定时器 to 的方式 1,实现 8个 led 逐个点亮,间隔 1s,一直重复。。(1193点数解答 | 2024-12-27 15:10:29)175
- 编写 js 代码,使用 for 循环,实现 1 到 100 相加,将结果输出到页面。(240点数解答 | 2024-05-20 22:11:29)240
- 编写 js 代码,使用 while 循环,实现 1 到 100 相加,将结果输出到页面。(47点数解答 | 2024-05-20 22:16:48)224
- 使用 vue.js 实现 matter.js 物理模拟(522点数解答 | 2024-05-29 22:26:06)243
- 使用 winform 开发桌面 布置时 利用 label、textbox、buttoncombobox、等控件完成注册页面,点击注册按钮实现弹框提示注册成功。 要求:(1)注册页面包括姓名,性别,联系方式,家庭住址,联系方式等。 (2)点击注册按钮验证用户输入框,输入框如果有空值提示用户“请重新输入”(3)点击注册按钮如果不为空则提示用户“注册成功” (4)注册页面包含清空按钮,清空按钮实现清空所有用户输入内容 实现步骤 提示:1姓名,性别等文字展示使用label控件 2.使用控件的 text属性获取用户输入的内容 3.使用 clear()方法清除用户输入内容 交付标准 + (1)注册页面包括姓名,性别,联系方式,家庭住址,联系方式等。(20分) (2)点击注册按钮验证用户输入框,输入框如果有空值提示用户“请重新输入”(20分)(3)点击注册按钮如果不为空则提示用户“注册成功”(20分) (4)注册页面包含清空按钮,清空按钮实现清空所有用户输入内容(20分)(5266点数解答 | 2024-06-14 16:04:40)355