页面置换算法LRU的单链表方式实现

LRU,即最近最少使用算法,是一种常用的页面置换算法。

实现方式有很多,比如数组实现,为每个元素设置时间。或者移动数组中的元素等。移动数组中元素的方式在物理页面数较多时,会移动量很大,效率很低。

也可以使用单链表来实现。

我尝试过采用链表队列来实现,但涉及到非队首数据的删除,有违队列的限制,所以放弃。

于是采用单链表来实现。其中涉及到查找数据。由于单链表删除不太方便,所以查找返回数据的位置,再根据位置进行删除。这样的话需要查找一次,再按位置删除一次,影响效率。

这时应该会有小伙伴想到双向链表,查找并返回数据结点,然后删除,这样就可以直接删除,不需要额外再进行一次查找删除,诶 效率更高了。

java中可以使用hashmap + 双向链表来实现,效率就又高了。hashmap经过散列可以在O(1)时间复杂度找到相关元素。

java中的LinkedHashMap 就是采用hashmap + 双向链表实现的,所以LinkedHashMap天生支持LRU,可以直接使用LinkedHashMap。

下面是我采用单链表方式的实现,实现比较复杂,练练手。


#include <iostream>
#include <stdio.h>

//测试页面走向 7 0 1 2 0 3 0 4 2 7 1
//测试页面走向 0 1 2 3 0 1 4 0 1 2 3 4
//测试页面走向 3 2 1 0 3 2 4 3 2 1 0 4
//测试页面走向 1 2 3 4 1 2 5 1 2 3 4 5
//测试页面走向 1 2 1 3 1 2 4 2 1 3 4 5
//测试页面走向 1 2 3 6 4 7 3 2 1 4 7 5 6 5 2 1

typedef int DataType;

//单链表结点类型
typedef struct node{
    DataType data;
    struct node * next;
}ListNode;

typedef ListNode * LinkList;

//带头结点尾插法建表(创建一个空表)
LinkList createLinkList(){
    LinkList head = (ListNode *)malloc(sizeof(ListNode));
    head->next = NULL;
    return head;
}

//按结点值查找(如果找到,则返回该结点的位置,否则返回0)
int LocateElem(LinkList head,DataType e)
{
    int i=0;
    LinkList p=head->next;
    while(p)
    {
        i++;
        if(p->data==e) /* 找到这样的数据元素 */
                return i;
        p=p->next;
    }

    return 0;
}

//按位置插入
void insertList(LinkList head,int i,DataType x){
    ListNode *p ,*s;
    int j;
    p=head;j=0;
    while (p!=NULL && j<i-1) {
        p=p->next;
        ++j;
    }
    if (p==NULL) {
        printf("error\n");
        return;
    } else {
        s = (ListNode *)malloc(sizeof(ListNode));
        s->data = x;
        s->next = p->next;
        p->next = s;
    }
}

//按位置删除
DataType deleteList(LinkList head,int i){
    ListNode *p,*s;
    DataType x;
    int j;
    p = head;
    j = 0;
    while (p!=NULL && j<i-1) {
        p=p->next;
        ++j;
    }
    if (p==NULL) {
        printf("位置错误\n");
        exit(0);
    } else {
        s = p->next;
        p->next = s->next;
        x = s->data;
        free(s);
        return x;
    }
}

//初始化队列
void initializeList(int list[],int number){
    for (int i = 0; i < number; i ++) {
        list[i] = -1;
    }
}
//展示队列状态
void showList(int list[], int number){
    printf("队列状态:");
    for (int i = 0; i < number; i ++) {
        printf("%2d",list[i]);
    }
    printf("\n");
}

//展示链表状态
void showLinkList(LinkList head){
    ListNode *p = head->next;
    while (p) {
        printf("%2d",p->data);
        p = p->next;
    }
    printf("\n");
}

//展示缺页置换等信息
void informationCount(int missingCount,int replaceCount,int pageNum){
    printf("缺页次数:%d   缺页率:%d/%d\n",missingCount,missingCount,pageNum);
    double result = (double)(pageNum - missingCount)/(double)pageNum;
    printf("置换次数:%d  命中率:%.2f\n",replaceCount,result);
}

//最近最久未使用置换算法
void replacePageByLRU(LinkList head ,int phyNum,int strList[],int pageNum){
    //置换次数
    int replaceCount = 0;
    //缺页次数
    int missingCount = 0;
    //链表中元素的数量
    int phyCount = 0;
    
    for (int i = 0; i < pageNum; i ++) {
        //当页面数超过3个时,首先查找要访问的页面是否在队列中,
        //如果不在队列中,则出队,并将该页面号入队。
        //如果在队列中,删除该结点,并将该结点重新入队。
        if (phyCount < phyNum) {
            int position = LocateElem(head, strList[i]);
            if (!position) {
                //没找到
                insertList(head, phyCount+1, strList[i]);
                missingCount++;
                phyCount++;
            } else {
                //找到了
                deleteList(head, position);
                insertList(head, phyCount, strList[i]);
            }
        } else {
            int l = LocateElem(head, strList[i]);
            if (!l) {
                //没找到,删除头部,插入尾部
                deleteList(head, 1);
                insertList(head, phyNum, strList[i]);
                missingCount++;
                replaceCount++;
            } else {
                //找到了,删除该结点,插入尾部
                deleteList(head, l);
                insertList(head, phyNum, strList[i]);
            }
        }
        //展示当前链表状态
        showLinkList(head);
    }
    informationCount(missingCount, replaceCount, pageNum);
}

int main(int argc, const char * argv[]) {
    
    //物理块的数量
    int phyBlockNum;
    printf("请输入物理块数量:\n");
    scanf("%d",&phyBlockNum);
    
    //页面数量
    int pageNum;
    printf("请输入要访问的页面总数:\n");
    scanf("%d",&pageNum);
    
    //保存页面号引用串
    int pageNumStrList[pageNum];
    printf("请输入要访问的页面号:\n");
    for (int i = 0; i < pageNum; i ++) {
        scanf("%d",&pageNumStrList[i]);
    }
    
    //定义一个链表
    LinkList head = createLinkList();
    
    showList(pageNumStrList, pageNum);
    //lru置换算法
    replacePageByLRU(head, phyBlockNum, pageNumStrList, pageNum);
    
    return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值