#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LEN 100
#define CACHE_CAPACITY 3
#define HASH_SIZE 1024
// Node cho doubly linked list và hash table
typedef struct Node {
int key;
char value[MAX_LEN];
int freq;
struct Node *prev, *next;
struct Node *hnext; // next trong hash chain
} Node;
// Hash map đơn giản
Node* hashmap[HASH_SIZE];
// Hàm băm đơn giản
int hash(int key) {
return key % HASH_SIZE;
}
Node* hash_get(int key) {
int idx = hash(key);
Node* cur = hashmap[idx];
while (cur) {
if (cur->key == key) return cur;
cur = cur->hnext;
}
return NULL;
}
void hash_put(Node* node) {
int idx = hash(node->key);
node->hnext = hashmap[idx];
hashmap[idx] = node;
}
void hash_remove(int key) {
int idx = hash(key);
Node *cur = hashmap[idx], *prev = NULL;
while (cur) {
if (cur->key == key) {
if (prev) prev->hnext = cur->hnext;
else hashmap[idx] = cur->hnext;
return;
}
prev = cur;
cur = cur->hnext;
}
}
// ==== LRU ====
Node *lru_head = NULL, *lru_tail = NULL;
int lru_size = 0;
void lru_move_to_front(Node* node) {
if (node == lru_head) return;
if (node->prev) node->prev->next = node->next;
if (node->next) node->next->prev = node->prev;
if (node == lru_tail) lru_tail = node->prev;
node->prev = NULL;
node->next = lru_head;
if (lru_head) lru_head->prev = node;
lru_head = node;
if (!lru_tail) lru_tail = lru_head;
}
void lru_remove_tail() {
if (!lru_tail) return;
Node* temp = lru_tail;
if (lru_tail->prev) lru_tail->prev->next = NULL;
lru_tail = lru_tail->prev;
if (!lru_tail) lru_head = NULL;
hash_remove(temp->key);
lru_size--;
}
void lru_put(int key, const char* value) {
Node* node = hash_get(key);
if (node) {
strncpy(node
->value
, value
, MAX_LEN
); lru_move_to_front(node);
return;
}
if (lru_size == CACHE_CAPACITY) lru_remove_tail();
Node
* new_node
= (Node
*)malloc(sizeof(Node
)); new_node->key = key;
strncpy(new_node
->value
, value
, MAX_LEN
); new_node->prev = new_node->next = new_node->hnext = NULL;
new_node->freq = 1;
new_node->next = lru_head;
if (lru_head) lru_head->prev = new_node;
lru_head = new_node;
if (!lru_tail) lru_tail = lru_head;
hash_put(new_node);
lru_size++;
}
char* lru_get(int key) {
Node* node = hash_get(key);
if (!node) return NULL;
node->freq++;
lru_move_to_front(node);
return node->value;
}
void print_lru_cache() {
Node* cur = lru_head;
while (cur) {
printf("(%d:%s) ", cur
->key
, cur
->value
); cur = cur->next;
}
}
// ==== MRU ====
Node *mru_head = NULL, *mru_tail = NULL;
int mru_size = 0;
void mru_remove_head() {
if (!mru_head) return;
Node* temp = mru_head;
if (mru_head->next) mru_head->next->prev = NULL;
mru_head = mru_head->next;
if (!mru_head) mru_tail = NULL;
hash_remove(temp->key);
mru_size--;
}
void mru_put(int key, const char* value) {
Node* node = hash_get(key);
if (node) {
strncpy(node
->value
, value
, MAX_LEN
); return;
}
if (mru_size == CACHE_CAPACITY) mru_remove_head();
Node
* new_node
= (Node
*)malloc(sizeof(Node
)); new_node->key = key;
strncpy(new_node
->value
, value
, MAX_LEN
); new_node->prev = mru_tail;
new_node->next = NULL;
new_node->hnext = NULL;
new_node->freq = 1;
if (mru_tail) mru_tail->next = new_node;
mru_tail = new_node;
if (!mru_head) mru_head = new_node;
hash_put(new_node);
mru_size++;
}
void print_mru_cache() {
Node* cur = mru_head;
while (cur) {
printf("(%d:%s) ", cur
->key
, cur
->value
); cur = cur->next;
}
}
// ==== MFU ====
Node* mfu_list = NULL;
int mfu_size = 0;
void mfu_remove_most_frequent() {
Node *prev = NULL, *cur = mfu_list, *target = NULL, *target_prev = NULL;
int max_freq = -1;
while (cur) {
if (cur->freq > max_freq) {
max_freq = cur->freq;
target = cur;
target_prev = prev;
}
prev = cur;
cur = cur->next;
}
if (!target) return;
if (target_prev) target_prev->next = target->next;
else mfu_list = target->next;
hash_remove(target->key);
mfu_size--;
}
void mfu_put(int key, const char* value) {
Node* node = hash_get(key);
if (node) {
strncpy(node
->value
, value
, MAX_LEN
); node->freq++;
return;
}
if (mfu_size == CACHE_CAPACITY) mfu_remove_most_frequent();
Node
* new_node
= (Node
*)malloc(sizeof(Node
)); new_node->key = key;
strncpy(new_node
->value
, value
, MAX_LEN
); new_node->prev = new_node->next = NULL;
new_node->hnext = NULL;
new_node->freq = 1;
new_node->next = mfu_list;
mfu_list = new_node;
hash_put(new_node);
mfu_size++;
}
void print_mfu_cache() {
Node* cur = mfu_list;
while (cur) {
printf("(%d:%s|f%d) ", cur
->key
, cur
->value
, cur
->freq
); cur = cur->next;
}
}
int main() {
printf("\n=== Custom Test LRU Cache ===\n"); lru_put(1, "Value 1");
lru_put(2, "Value 2");
lru_put(3, "Value 3");
print_lru_cache(); // Cache: (3:Value 3) (2:Value 2) (1:Value 1)
lru_get(2); // Truy cập key 2 => đưa lên đầu
print_lru_cache(); // Cache: (2:Value 2) (3:Value 3) (1:Value 1)
lru_put(4, "Value 4"); // Thêm key 4 => loại key 1 (cũ nhất)
print_lru_cache(); // Cache: (4:Value 4) (2:Value 2) (3:Value 3)
char* val = lru_get(1); // Truy cập key 1 (đã bị loại bỏ) => NULL
if (val
) printf("Found key 1: %s\n", val
); else printf("Key 1 not found in cache.\n");
}