146. LRU缓存机制(C语言)

参考自: https://github.com/Stand1210/c-LRU-/blob/master/LRU/lru_cache_impl.c   感谢博主,代码非常干净漂亮,学到很多。

 

typedef struct cacheEntryS {
	int key;   /* 数据的key */
	int value;  /* 数据的data */

	struct cacheEntryS* hashListPrev;   /* 缓存哈希表指针, 指向哈希链表的前一个元素 */
	struct cacheEntryS* hashListNext;   /* 缓存哈希表指针, 指向哈希链表的后一个元素 */

	struct cacheEntryS* lruListPrev;    /* 缓存双向链表指针, 指向链表的前一个元素 */
	struct cacheEntryS* lruListNext;    /* 缓存双向链表指针, 指向链表后一个元素 */
}cacheEntryS;
typedef struct LRUCache{
    int lruListSize;   /*缓存的双向链表节点个数*/
	int cacheCapacity;  /*缓存的容量*/
	cacheEntryS** hashMap;  /*缓存的哈希表*/

	cacheEntryS* lruListHead;   /*缓存的双向链表表头*/
	cacheEntryS* lruListTail;   /*缓存的双向链表表尾*/
} LRUCache;

static unsigned int hashKey(LRUCache* cache, int key)
{
	unsigned int a = 63689;
	unsigned int hash = 31;
	unsigned int i = 0;	
	hash = hash * a + key;

	return hash % (cache->cacheCapacity);
}
LRUCache* lRUCacheCreate(int capacity) {
	LRUCache* obj = malloc(sizeof(*obj));
	if (obj == NULL)return NULL;
	memset(obj, 0, sizeof(LRUCache*));
	obj->cacheCapacity = capacity;
	obj->hashMap = malloc(sizeof(cacheEntryS*)*capacity);
	if (obj->hashMap == NULL) {
		free(obj);
		return NULL;
	}
    obj->lruListSize = 0;
    obj->lruListHead = obj->lruListTail = NULL;
	memset(obj->hashMap, 0, sizeof(cacheEntryS*) * capacity);
	return obj;
}

static cacheEntryS* newCacheEntry(int key, int value) {
	cacheEntryS* en = malloc(sizeof(*en));
	if (en == NULL) { perror("malloc"); return NULL; }
	memset(en, 0, sizeof(*en));
	en->key = key;
	en->value = value;
    en->lruListNext = NULL;
    en->lruListPrev = NULL;
	en->hashListNext = NULL;
	en->hashListPrev = NULL;
	return en;
}
static cacheEntryS* getValueFromHashMap(LRUCache* cache, int key) {
	cacheEntryS* en = cache->hashMap[hashKey(cache, key)];
	while (en) {
		if (en->key == key)break;
		en = en->hashListNext;
	}
	return en;
}
static void insertentryToHashMap(LRUCache* cache, cacheEntryS* entry) {
	cacheEntryS* en = cache->hashMap[hashKey(cache, entry->key)];
	if (en != NULL) {
		entry->hashListNext = en;
		en->hashListPrev = entry;
	}
	cache->hashMap[hashKey(cache, entry->key)] = entry;
}
static void removeEntryFromHashMap(LRUCache* cache, cacheEntryS* entry)
{
	int key = entry->key;
	cacheEntryS *en = cache->hashMap[hashKey(cache, key)];
	if (en == NULL||cache==NULL||entry==NULL)return;
	while (en) {
		if (en->key == key) {
			if (en->hashListPrev)en->hashListPrev->hashListNext = en->hashListNext;
			else cache->hashMap[hashKey(cache, key)] = en->hashListNext;
			if (en->hashListNext) {
				en->hashListNext->hashListPrev = en->hashListPrev;
			}
			return;
		}
		en = en->hashListNext;
	}
}

/*list operation*/
static void removeFromList(LRUCache* cache, cacheEntryS* entry) {
	if (cache->lruListSize == 0) {
		return;
	}
	if (entry == cache->lruListHead && entry == cache->lruListTail) {
		cache->lruListHead = cache->lruListTail = NULL;
	}
	else if (entry == cache->lruListHead) {
		cache->lruListHead = entry->lruListNext;
		cache->lruListHead->lruListPrev = NULL;
	}
	else if (entry == cache->lruListTail) {
		cache->lruListTail=entry->lruListPrev;
		cache->lruListTail->lruListNext = NULL;
	}
	else {
		entry->lruListPrev->lruListNext = entry->lruListNext;
		entry->lruListNext->lruListPrev = entry->lruListPrev;
	}
	cache->lruListSize--;
}
static cacheEntryS* insertToListHead(LRUCache* obj, cacheEntryS* entry) {
    LRUCache*cache=obj;
	++cache->lruListSize;
	cacheEntryS* removedEntry = NULL;
	if (cache->lruListSize >cache->cacheCapacity) {
		removedEntry = cache->lruListTail;
		removeFromList(cache, cache->lruListTail);
	}
	if (cache->lruListHead == NULL&&cache->lruListTail==NULL) {
		cache->lruListHead =cache->lruListTail= entry;
	}
	else {
		entry->lruListNext=cache->lruListHead;
		entry->lruListPrev = NULL;
		cache->lruListHead->lruListPrev = entry;
		cache->lruListHead = entry;
	}
	return removedEntry;
}
static void freeList(LRUCache* cache) {
	if (cache->lruListSize == 0)return;
	cacheEntryS* p = cache->lruListHead;
	while (p) {
		cacheEntryS* temp = p->lruListNext;
		free(p);
		p = temp;
	}
	cache->lruListSize = 0;
}
static void updateLRUList(LRUCache* cache, cacheEntryS* entry)
{
	/*将节点从链表中摘抄*/
	removeFromList(cache, entry);
	/*将节点插入链表表头*/
	insertToListHead(cache, entry);
}

int lRUCacheGet(LRUCache* obj, int key) {
	LRUCache* cache = obj;
	cacheEntryS* entry = getValueFromHashMap(cache, key);
	if (entry == NULL)return -1;
	else {
		updateLRUList(cache, entry);
		return entry->value;
	}
}

void lRUCachePut(LRUCache* obj, int key, int value) {
	LRUCache* cache = obj;
	cacheEntryS*entry= newCacheEntry(key, value);
	cacheEntryS* en = getValueFromHashMap(cache, key);
	if (en != NULL) {
		en->value = value;
		updateLRUList(cache, en);
	}else{
	cacheEntryS* removedentry=insertToListHead(cache, entry);
	if (removedentry!=NULL) { 
		removeEntryFromHashMap(cache, removedentry); 
		free(removedentry);
	}
	insertentryToHashMap(cache, entry);
	}
	return;
}

void lRUCacheFree(LRUCache* obj) {
	LRUCache* cache = obj;
	if (cache == NULL)return 0;
	if (cache->hashMap)free(cache->hashMap);
	freeList(cache);
	free(cache);

}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值