LRU最近最少未使用算法。在OS虚拟存储器那部分。用到了该算法,根据程序的局部性原理,前人设计出了虚拟存储器,每个进程只被分配几个内存块,当进程的内存块被占完了之后。从硬盘上又重新读取了一个内存块的数据量,此时,哪个内存块的内容被换出去比较合适呢?如果置换算法采取的不好,就会导致缺页率上升。进程频繁的发生缺页中断。OS就会频繁的在内存和外存之间替换页面。影响了进程的执行效率,这种现象又称之为"抖动",LRU置换算法的缺页率相对比较低。
缓存是一种提高数据读取性能的技术,在硬件设计、软件开发中都有着非常广泛的应用,比如常见的 CPU 缓存、数据库缓存、浏览器缓存等等。 硬件中的缓存: CPU缓存,而cpu缓存又可以分为寄存器,一级缓存,二级缓存,三级缓存。 软件中的缓存: 数据库缓存,数据库本身产品就自带缓存。redis也可以作为数据库缓存. 浏览器缓存,就是我们常说的Cookie,本质上就是一个文件。
链表删除、增加操作的时间复杂度
单纯的删除操作,时间复杂度为o(1),但是找到要删除的这个数,要需要一点的时间。常见的删除有两种,一种是删除指定值,一种是删除指定位置。
删除给定指针指向的结点: 这种情况是已经找到了要删除的元素,我们只需要执行删除操作即可. 针对单链表而言: 单链表如果要删除一个结点q.必须要知道这个结点的前驱结点是谁,修改前驱结点的指针指向即可.单链表找某个结点的前驱结点,只能从头开始遍历. 临界值 p->next == q;说明p就是q的前驱结点.所以在单链表中,找这个前驱结点的平均时间复杂度为O(n),然后执行删除操作的时间复杂度为O(1). 根据时间复杂度分析的加法法则: 删除给定指针指向的结点 --> 单链表的总的时间复杂度为O(n).
针对双链表而言: 双链表要删除一个结点q.也必须得知道这个结点的前驱结点和后继结点. 修改前驱结点的后继指针next和后继结点的前驱指针prev即可.而针对双链表而言,找q的前驱结点和q的后继结点的时间复杂度都为O(1).而执行删除操作(修改指针指向)的时间复杂度也为O(1). 根据时间复杂度分析的加法法则: 删除给定指针指向的结点 --> 双链表的总的时间复杂度为O(1).
LRU算法
LRU的算法思路是真的简单,概括下: 使用定长链表来保存所有缓存的值,并且最老的值放在链表最后面 当访问的值在链表中时: 将找到链表中值将其删除,并重新在链表头添加该值(保证链表中 数值的顺序是从新到旧) 当访问的值不在链表中时: 当链表已满:删除链表最后一个值,将要添加的值放在链表头 当链表未满:直接在链表头添加。
typedef int DataType;
//定义
class SNode
{
public:
DataType data;
SNode* next;
};
class SList
{
public:
SList();
SList(int MaxSize);
~SList();
void intsertElemAtBegin(DataType x); //头部插入节点
bool findElem(DataType x); //查找x,存在则返回1,不存在则返回0
void deleteElemAtEnd(); //删除尾节点
bool deleteElem(DataType x); //删除指定节点,如果存在则删除,返回1,如果不存在,则删除失败返回0
bool isEmpty(); // 查看链表是否为空,1表示不为空,0表示为空
bool isFull(); // 查看链表是否满,1表示不满,0表示满
void printAll();
void* findElemOptim(DataType x); //针对此应用的优化,查找,返回指定元素的前一个节点的指针
void deleteElemOptim(void* snode); //针对此应用的优化,删除
private:
int MaxSize; // 链表可以存放最大的数据
int length; // 链表的长度
SNode* head; // 指向头节点
};
/**
* 1)单链表的插入,删除,查找操作;
* 2)链表中存储的是 int 类型
*
* Author:caozx
*/
#include<iostream>
using namespace std;
// 初始化单链表
SList::SList() {
head = new SNode; //申请头节点
head->next = NULL;
this->MaxSize = 10;
this->length = 0;
}
SList::SList(int MaxSize) {
head = new SNode; //申请头节点
head->next = NULL;
this->MaxSize = MaxSize;
this->length = 0;
}
// 销毁单链表,要把开辟的空间都释放,然后再销毁。
SList::~SList() {
SNode* ptr, * temp;
ptr = head;
while (ptr->next != NULL) {
temp = ptr->next;
ptr->next = ptr->next->next;
delete temp;
}
delete head; //删除头节点
this->head = NULL;
this->length = 0;
}
//链表头部插入节点
void SList::intsertElemAtBegin(DataType x) {
SNode* ptr = new SNode;
ptr->data = x;
ptr->next = head->next;
head->next = ptr;
this->length++;
}
//查找x,存在则返回1,不存在则返回0
bool SList::findElem(DataType x)
{
SNode* ptr;
ptr = head;
while (ptr->next != NULL) {
if (ptr->next->data == x) {
return 1;
}
ptr = ptr->next;
}
return 0;
}
// 删除尾结点
void SList::deleteElemAtEnd() {
SNode* ptr, * temp;
ptr = head;
while (ptr->next != NULL && ptr->next->next != NULL) { //倒数第二个节点
ptr = ptr->next;
}
temp = ptr->next;
ptr->next = temp->next;
this->length--;
delete temp;
}
//删除指定节点,
//如果存在则删除,返回1,表示存在且删除成功;
//如果不存在则不删除,返回0,表示不存在该元素,不需要删除,也即删除失败
bool SList::deleteElem(DataType x)
{
SNode* ptr, * temp;
ptr = head;
while (ptr->next != NULL) {
if (ptr->next->data == x) {
temp = ptr->next;
ptr->next = temp->next;
delete temp;
this->length--;
return 1;
}
ptr = ptr->next;
}
return 0;
}
// 查看链表是否为空,1表示不为空,0表示为空
bool SList::isEmpty()
{
if (this->length == 0) { //空
return 0;
}
else {
return 1;
}
}
// 查看链表是否满,1表示不满,0表示满
bool SList::isFull()
{
if (this->length == this->MaxSize) { //满
return 0;
}
else {
return 1;
}
}
// 打印
void SList::printAll()
{
SNode* ptr;
ptr = head;
while (ptr->next != NULL) {
ptr = ptr->next;
cout << ptr->data << " ";
}
cout << endl;
}
//针对此应用的优化,查找,
//若存在则返回指定元素的前一个节点的指针
//若不存在,则返回NULL
void* SList::findElemOptim(DataType x)
{
SNode* ptr;
ptr = head;
while (ptr->next != NULL) {
if (ptr->next->data == x) {
return (void*)ptr;
}
ptr = ptr->next;
}
return NULL;
}
//针对此应用的优化,删除
void SList::deleteElemOptim(void* snode)
{
SNode* ptr, * temp;
ptr = (SNode*)snode;
temp = ptr->next;
ptr->next = temp->next;
this->length--;
delete temp;
}
int main(int argc, char const* argv[])
{
cout << "test " << endl;
SList slist(10); //缓存最大10个。
int num = 0;
while (1)
{
cout << "please enter a number,99999== exit" << endl;
cin >> num;
if (num == 99999)
break;
/* 未优化
if(slist.findElem(num)){ //存在
slist.deleteElem(num); //把原来的位置删除
slist.intsertElemAtBegin(num); //在链表头插入
}
*/
//优化
SNode* prePtr = (SNode*)slist.findElemOptim(num);
if (prePtr != NULL) { //存在
slist.deleteElemOptim(prePtr); //把原来的位置删除
slist.intsertElemAtBegin(num); //在链表头插入
}
else { //不存在
if (slist.isFull()) { //不满
slist.intsertElemAtBegin(num);
}
else { //满
slist.deleteElemAtEnd();
slist.intsertElemAtBegin(num);
}
}
slist.printAll();
}
return 0;
system("pause");
}