使用C++簡單實現LRU緩存

使用C++簡單實現LRU緩存


  昨天碰巧複習到了LRU緩存機制,也就是最近最少使用,在好奇心的驅動下我想到了用C++簡單的實現一下,本來原理也挺簡單的,寫出來並不難,但由於對C++的基礎把握不勞,結果排查了好長時間的bug。現在總結一下,希望能幫到別的小可愛。

首先是malloc:

  可能是C語言寫習慣的,導致在C++進行內存分配的時候我也習慣用malloc,C和C++混用很可能就會出bug!
  在給struct LRUCache{};初始化時,由於指針會指向一塊內存,指針本身也是要佔用內存的,但指針指向的地方還沒有分配內存呢,所以就需要又malloc 。我就是少malloc,結果程序老是運行不下去。。。

接着是map:

  我在struct LRUCache{};放了一個map<int, ListNode*> mp; mp用來存索引key和映射ListNode的指針.
  如果是用malloc初始化struct LRUCache{};那麼又需要給map初始化,因爲malloc只是申請一塊內存,不會初始化map對應的內存。使用new 除了malloc內存,還會調用默認的構造初始化函數 ,所以最好還是用new比較省事。

malloc和new的區別:

(1)malloc與free是C++/C語言的標準庫函數,new/delete是C++的運算符。
(2)new操作符從自由存儲區(free store)上爲對象動態分配內存空間,而malloc函數從堆上動態分配內存。
(3)使用new操作符申請內存分配時無須指定內存塊的大小,編譯器會根據類型信息自行計算,而malloc則需要顯式地指出所需內存的尺寸。

  下面是代碼,用了get(key)獲取數據,put(key, value)存放數據。代碼還沒有完善,只是簡單的實現,後面有時間會進行修改。(其實可以把struct LRUCache{};換成一個類,這樣比較好。。。)
代碼如下:

#include<iostream>
#include<stdlib.h> 
#include<map>
using namespace std;
struct ListNode{
	int key;
	int value;
	ListNode *pre,*next;//指針 
	ListNode (int key1,int value1){
		key=key1;
		value=value1;
		pre=NULL;
		next=NULL;
	}
};
struct LRUCache{
	int Captacity;
	map<int,ListNode*> m;
	ListNode *head,*tail;//指針 
	LRUCache(int captacity){
		Captacity= captacity;
		head=new ListNode(0,0); 
    	tail=new ListNode(0,0); 
	}
}*cache;
LRUCache *Constructor(int capacity){//初始化 
    LRUCache *cache=new LRUCache(capacity); 
	cache->head->next=cache->tail;
	cache->tail->pre=cache->head;
	return cache;
}
void removeNode(ListNode *node){    //移除 
	node->pre->next=node->next;
	node->next->pre=node->pre;
}
void addNode(ListNode *node){//添加元素到表頭 
	node->next=cache->head->next;
	node->pre=cache->head;
	cache->head->next->pre=node;
	cache->head->next=node;
} 
void moveToHead(ListNode *node) {//移動到表頭 
	removeNode(node); 
	addNode(node);
}
void popTail(){ //刪除表尾 
	ListNode *res = cache->tail->pre;
	removeNode(res);
}
int get(int key){
	map<int,ListNode*>::iterator it=cache->m.find(key);
	if(it==cache->m.end()){//如果不存在 
		return -1;
	}
	ListNode *node = it->second;
	moveToHead(node);
	return node->value; 
}
void put(int key,int value){
	map<int,ListNode*>::iterator it=cache->m.find(key);
	if(it==cache->m.end()){//如果不存在 
		ListNode * NewNode = new ListNode(key,value);
		if(cache->m.size()==cache->Captacity){//如果滿了 
			cache->m.erase(cache->tail->pre->key);//從map表中刪除最後一個 
			cache->m[key]= NewNode;//從map表中加上新的 
			popTail();//刪除 cache最後一個 
			addNode(NewNode);//把新的移到最前面 
		}else{
			cache->m[key]= NewNode;
			addNode(NewNode);
		}
	} else{//如果存在 
		it->second->value=value;//更新值 
		moveToHead(it->second);
	}
}
int main(){
	cache=Constructor(3);
	put(1,1);
	put(2,2);
	put(3,3);
	//順序:3,2,1 
	cout<<get(1)<<endl;//1
	// 順序:1,3,2 
	put(4,4);
	// 順序:4,1,3 
	cout<<get(2)<<endl;//-1
	put(5,5);
	// 順序:5,4,1
	cout<<get(3)<<endl;//-1
	cout<<get(4)<<endl;//4
	cout<<get(5)<<endl;//5
	return 0;
} 

  如果哪裏寫得不夠好或者是大家有不同看法的歡迎評論!我會看情況進行更改。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章