File size: 4,702 Bytes
9f135d5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// LRU (Least Recently Used) Cache implementation
// Using hash table and doubly linked list for O(1) operations
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define CACHE_CAPACITY 1000
#define HASH_SIZE 2048
#define NUM_OPERATIONS 100000

typedef struct Node {
    int key;
    int value;
    struct Node *prev;
    struct Node *next;
} Node;

typedef struct {
    Node **hash_table;
    Node *head;
    Node *tail;
    int capacity;
    int size;
} LRUCache;

Node* create_node(int key, int value) {
    Node *node = (Node*)malloc(sizeof(Node));
    node->key = key;
    node->value = value;
    node->prev = NULL;
    node->next = NULL;
    return node;
}

LRUCache* create_cache(int capacity) {
    LRUCache *cache = (LRUCache*)malloc(sizeof(LRUCache));
    cache->hash_table = (Node**)calloc(HASH_SIZE, sizeof(Node*));
    cache->head = create_node(0, 0);  // Dummy head
    cache->tail = create_node(0, 0);  // Dummy tail
    cache->head->next = cache->tail;
    cache->tail->prev = cache->head;
    cache->capacity = capacity;
    cache->size = 0;
    return cache;
}

void move_to_front(LRUCache *cache, Node *node) {
    // Remove from current position
    node->prev->next = node->next;
    node->next->prev = node->prev;
    
    // Insert after head
    node->next = cache->head->next;
    node->prev = cache->head;
    cache->head->next->prev = node;
    cache->head->next = node;
}

int get(LRUCache *cache, int key) {
    int hash = key % HASH_SIZE;
    Node *node = cache->hash_table[hash];
    
    // Search in hash bucket
    while (node) {
        if (node->key == key) {
            move_to_front(cache, node);
            return node->value;
        }
        node = node->next;
    }
    
    return -1;  // Not found
}

void put(LRUCache *cache, int key, int value) {
    int hash = key % HASH_SIZE;
    
    // Check if key exists
    Node *node = cache->hash_table[hash];
    Node *prev = NULL;
    
    while (node) {
        if (node->key == key) {
            node->value = value;
            move_to_front(cache, node);
            return;
        }
        prev = node;
        node = node->next;
    }
    
    // Key doesn't exist - create new node
    Node *new_node = create_node(key, value);
    
    // Add to hash table
    if (!cache->hash_table[hash]) {
        cache->hash_table[hash] = new_node;
    } else {
        prev->next = new_node;
    }
    
    // Add to front of list
    new_node->next = cache->head->next;
    new_node->prev = cache->head;
    cache->head->next->prev = new_node;
    cache->head->next = new_node;
    
    cache->size++;
    
    // Evict if necessary
    if (cache->size > cache->capacity) {
        Node *lru = cache->tail->prev;
        
        // Remove from list
        lru->prev->next = cache->tail;
        cache->tail->prev = lru->prev;
        
        // Remove from hash table
        int lru_hash = lru->key % HASH_SIZE;
        Node *h = cache->hash_table[lru_hash];
        Node *h_prev = NULL;
        
        while (h) {
            if (h->key == lru->key) {
                if (h_prev) {
                    h_prev->next = h->next;
                } else {
                    cache->hash_table[lru_hash] = h->next;
                }
                break;
            }
            h_prev = h;
            h = h->next;
        }
        
        free(lru);
        cache->size--;
    }
}

int main() {
    LRUCache *cache = create_cache(CACHE_CAPACITY);
    
    unsigned int seed = 42;
    
    clock_t start = clock();
    
    int hits = 0, misses = 0;
    
    for (int i = 0; i < NUM_OPERATIONS; i++) {
        seed = seed * 1103515245 + 12345;
        int operation = seed % 100;
        seed = seed * 1103515245 + 12345;
        int key = seed % (CACHE_CAPACITY * 2);
        
        if (operation < 70) {  // 70% puts
            seed = seed * 1103515245 + 12345;
            int value = seed % 10000;
            put(cache, key, value);
        } else {  // 30% gets
            int result = get(cache, key);
            if (result != -1) {
                hits++;
            } else {
                misses++;
            }
        }
    }
    
    clock_t end = clock();
    double time_spent = (double)(end - start) / CLOCKS_PER_SEC;
    
    printf("LRU Cache: capacity=%d, %d operations, %.6f seconds\n",
           CACHE_CAPACITY, NUM_OPERATIONS, time_spent);
    printf("Cache hits: %d, misses: %d, hit rate: %.2f%%\n",
           hits, misses, 100.0 * hits / (hits + misses));
    
    return 0;
}