zstu 校赛 最佳淘汰算法 (优先队列)

106 篇文章 0 订阅
4 篇文章 0 订阅


4272: 最佳淘汰算法

Time Limit: 12 Sec  Memory Limit: 128 MB
Submit: 396  Solved: 58

Description

Lyf在做操作系统作业的时候,遇到了一题要他实现下Opt算法(全称页面置换最佳淘汰算法)。可是Lyf发现最近好忙啊,于是他想请他的学弟,学妹们帮他来完成。
作业里的内容是这样的:

提出最佳页面淘汰算法。是操作系统存储管理中的一种全局页面替换策略当要调入一页而必须淘汰旧页时,应该淘汰以后不再访问的页,或距现在最长时间后要访问的页面。它所产生的缺页数最少,然而,却需要预测程序的页面引用串,这是无法预知的,不可能对程序的运行过程做出精确的断言。但是我们在这里会告诉你一个已经存在的一个页面序列,请输出最终在内存中存在的页面即可。

Input

有多组数据(组数<=21)。

每组数据输入形如:

n m

a1 a2 a3 a4 .... an

其中n(n,m<=500000)表示已知页面序列的长度。

ai(0<=ai<=100000)表示页面类型,为整数。

m为在内存中保存的页面类型数量。

Output

输出形如:

b1 b2 b3 .... bk

具体要求请仔细阅读样例和Hint。

Sample Input

21 37 0 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 13 22 1 34 31 0 0 1

Sample Output

7 0 13 11 0

解题思路:

用优先队列去维护距离下一个同类型页面最远的编号,再用一个大小为m的数组去存页面内容就好了。当m数组没有填满的时候,就直接填进去就好了,当m数组填满了后,我们就根据情况替代里面的元素。但是需要注意一个trick,出现一个数组里已经存在的编号的的页面的时候,不可以直接continue,虽然不能进入内存,但需要更新下这个编号下一次出现的位置,如果不更新就会出错,直接塞进优先队列里就好了。

另外这个题还加深了我对优先队列的认识,因为踩了个大坑,我之前是用这种代码去写的优先队列的<重载函数:

 bool operator <(const p &a)const
    {
        if(ww[a.x]!=ww[x])return ww[a.x]>x;
        else return a.x>x;
    }

然后果断gg,我生成了一些数据,发现中间有些地方,队列里第一个元素的ww值反而小于第二个元素的ww值,非常奇怪。后来才发现,是因为我在中间过程中修改过ww数组的值,而由于这时候可能没有重新插入元素,所以优先队列没有调整,所以直到下一次修改优先队列之前优先队列肯定就是不优先的了,所以会发生错误。

所以说,以后写代码不要写这种奇奇怪怪的风格的代码,容易踩到莫名的坑。这里要注意的就是

优先队列千万别用外部元素来写重载函数

优先队列千万别用外部元素来写重载函数

优先队列千万别用外部元素来写重载函数


代码:

#include <bits/stdc++.h>
#define ps push_back
using namespace std;
const int maxn=5e5+5;
const int inf=5e5+5;
int n, m;
int h[500000+6];
int pos[500000+5];
struct p
{
    int w;
    int y;
    int x;
    bool operator <(const p &a)const
    {
        if(a.w!=w)return a.w>w;
        else return a.x>x;
    }
    
};
int b[maxn];
int ans[maxn];
int book[500000+5];
int po[maxn];
int num[500000+5];
bool cmp(p a, p b)
{
    return a.y<b.y;
}
int main()
{
//    freopen("C:\\Users\\johsnow\\Desktop\\in.txt", "r", stdin);
//    freopen("C:\\Users\\johsnow\\Desktop\\out2.txt", "w", stdout);
    int i, j;
    p node;
 
//    scanf("%d%d", &n, &m);
    while(~scanf("%d%d", &n, &m))
    {
        memset(book, 0, sizeof book);
        memset(ans, 0, sizeof ans);
        priority_queue <p>a;
        int ma=0;
        for(i=0; i<n; i++)
        {
 
            scanf("%d", &b[i]);
            ma=b[i]>ma?b[i]:ma;
        }
        for(i=0; i<=ma; i++)pos[i]=inf;
        for(i=n-1; i>=0; i--)
        {
            h[i]=pos[b[i]];
            pos[b[i]]=i;
        }
    int top=1, tmp;
    for(i=0; i<n; i++)
    {
        node.x=b[i];
        node.y=i;
        node.w=h[i];
        if(top<=m)
        {
        if(book[b[i]]==0)
        {
      //      printf("%d\n", b[i]);
            ans[top]=b[i];
            book[b[i]]=top;
      //      printf("%d %d\n", b[i], book[b[i]]);
            top++;
        }
        a.push(node);
        }
        else break;
    }
    j=i;
    if(top<=m)
    {
        for(i=1; i<top; i++)printf(i==top-1?"%d\n":"%d ", ans[i]);    
        continue;
    }
    
         for(i=j; i<n; i++)
         {
            node.x=b[i];
            node.w=h[i];
            if(book[b[i]]==0)
            {
                tmp=book[a.top().x];
                book[a.top().x]=0;
                ans[tmp]=b[i];
       //         printf("%d %d\n", b[i], tmp);
                book[b[i]]=tmp;
                a.pop();   
            }
            a.push(node);
        }
    for(i=1; i<top; i++)printf(i==top-1?"%d\n":"%d ", ans[i]);
    }
 
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
页面置换算法课设 private void FIFO_button1_Click(object sender, EventArgs e) { if (page.Length == 0 || strsize.Length == 0) MessageBox.Show("输入得页面序列或物理块数不能为空", "提示", MessageBoxButtons.OK); else { //初始化数据,并访问第一个页面 int i, j, u, losecount, changecount = 0; for (i = 0; i < size; i++) { X[i].Num = -1; X[i].Timer = 0; } X[0].Num = page[0]; X[0].Timer = 1; FIFO_label.Text = "FIFO\n" + (X[0].Num - 48).ToString() + "\n"; losecount = 1; //循环,按照页面序列,选择淘汰的页面并进行置换 for (i = 1; i < page.Length; i++) { u = 0;//进程的内存中是否存在要访问的页面的标记 //若内存中存在要访问的页面,则设置u=1,并退出循环 for (j = 0; j < size; j++) { if (X[j].Num == page[i]) { u = 1; break; } } //若内存中不存在要访问的页面,且内存中无空闲的空间则进行下列置换 if (u != 1 && X[size - 1].Num != -1) { j = GetMaxTime();//选择呆的时间最长的页面进行置换 X[j].Num = page[i]; X[j].Timer = 0; changecount++; losecount++; } //若内存中不存在要访问的页面,且内存中有空闲的空间则进行下列置换 if (u != 1 && X[size - 1].Num == -1) { for (j = 0; j < size; j++) { if (X[j].Num == -1) { X[j].Num = page[i]; losecount++; break; } } } //对内存中不为空的页面的时间加1 for (j = 0; j < size; j++) { if (X[j].Num != -1) X[j].Timer++; } //输出数据 for (j = 0; j < size; j++) { if (X[j].Num != -1) FIFO_label.Text += (X[j].Num - 48).ToString(); else FIFO_label.Text += " "; } FIFO_label.Text += "\n"; } FIFOlosepage = (float)losecount / (float)(page.Length);//缺页率 FIFO_label.Text += "访问次数是:" + page.Length + "\n页面置换次数:" + changecount + "\n缺页中断次数:" + losecount + "\n缺页率是:" + FIFOlosepage; } } (3)LRU置换算法 private void LRU_button1_Click(object sender, EventArgs e) { if (page.Length == 0 || strsize.Length == 0) MessageBox.Show("输入得页面序列或物理块数不能为空", "提示", MessageBoxButtons.OK); else { //初始化数据,并访问第一个页面,并输出访问结果 int i, j, u, losecount, changecount = 0; for (i = 0; i < size; i++) { X[i].Num = -1; X[i].Timer = 0; } X[0].Num = page[0]; X[0].Timer = 1; losecount = 1; LRU_label.Text = "LRU\n" + (X[0].Num - 48).ToString() + "\n"; //循环,按照页面序列依次访问页面,并输出访问结果 for (i = 1; i < page.Length; i++) { u = 0; //如果内存中存在要访问的页面,则置Timer为0,u为1 for (j = 0; j < size; j++) {
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值