操作系统最先适应算法(c++双向链表实现)

请添加图片描述
在这里插入图片描述

我参考的这篇文章,点这里

最先适应算法(First Fit)简介

首次适应算法(First Fit):该算法从空闲分区链首开始查找,直至找到一个能满足其大小要求的空闲分区为止。然后再按照作业的大小,从该分区中划出一块内存分配给请求者,余下的空闲分区仍留在空闲分区链中。
特点: 该算法倾向于使用内存中低地址部分的空闲区,在高地址部分的空闲区很少被利用,从而保留了高地址部分的大空闲区。显然为以后到达的大作业分配大的内存空间创造了条件。
缺点:低地址部分不断被划分,留下许多难以利用、很小的空闲区,而每次查找又都从低地址部分开始,会增加查找的开销。

思路:

我理论懂,但是代码不会写我参考的别人的,采用双向链表,开始有两个节点,一个是头结点,不存储任何信息,还有一个主节点,大小为你设置的最大值,后续所有节点都是在这个节点的基础上划分。从这个结点开始,空间大小<你需要的,不满足条件,空间大小>你需要的,只占用了块的一部分,我们只占用块的前半部分,后面的部分还是空闲,空闲块要新生成,位于当前节点和当前节点的下一节点之间,空间大小==你需要的,直接全占用。

回收内存时要注意前后块是否空闲,空闲的话要合并,当前后快都空闲时,我是先合并的后面块,在合并前面块。
在这里插入图片描述

代码:

/*
 * @Author: robot-cmy
 * @Date: 2021-11-22 17:08:50
 * @Last Modified by: robot-cmy
 * @Last Modified time: 2021-11-22 18:01:48
 */
//参考了下方的代码
// https://blog.csdn.net/weixin_39924920/article/details/81054205?ops_request_misc=&request_id=&biz_id=102&utm_term=%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E6%9C%80%E5%85%88%E9%80%82%E5%BA%94%E7%AE%97%E6%B3%95&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-81054205.first_rank_v2_pc_rank_v29&spm=1018.2226.3001.4187

#include <iostream>
using namespace std;

#define MAX_MEMORY 666	//假设最大内存

void init();	//初始化函数,对初始节点初始化
void showInfo();	//显示分配信息
bool firstFit( int id, int memorySize );	//最先适应算法
void allocate();	//内存分配
void recycle();	//内存回收

//链表数据块
struct Area {
    int id;	//作业id
    int size;	//作业大小
    int address;	//作业起始地址
    bool flag;	//=1表示被占用  =0表示未被占用
};

//采用双链表表示法
typedef struct Node {
    Area data;	//节点数段块
    Node *pre;	//前指针
    Node *next;	//后指针

} * LinkList;

//firstPointer时链头  lastPointer实际节点,所有数据分配都是基于这个节点
LinkList firstPointer, lastPointer;

//为两个头结点分配空间并初始化
void init() {
    firstPointer = new Node;
    lastPointer = new Node;
    firstPointer->pre = NULL;	//头结点前指针为空
    firstPointer->next = lastPointer;
    firstPointer->data.size = 0;

    lastPointer->pre = firstPointer;
    lastPointer->next = NULL;
    lastPointer->data.address = 0;	//我们实际操作都基于lastPointer节点,所以设这个起始地址为0
    lastPointer->data.size = MAX_MEMORY;	//同理,size也设为最大
    lastPointer->data.id = 0;
    lastPointer->data.flag = 0;
}

//打印内存分配情况
void showInfo() {
    Node *p = firstPointer->next;	//指针p指向实际的第一个节点
    cout << "------------------------\n";

    //不为空一直遍历
    while( p ) {
        cout << "分区号:";

        if( p->data.id ) {
            cout << p->data.id << endl;
        } else {
            cout << "空闲分区" << endl;
        }

        cout << "分区地址:" << p->data.address << endl;
        cout << "分区大小:" << p->data.size << endl;
        cout << "分区状态:";

        //flag=1表示被占用,=0表示未占用
        if( p->data.flag ) {
            cout << "分区被占用" << endl;
        } else {
            cout << "分区空闲" << endl;
        }

        p = p->next;
        cout << "------------------------\n";
    }
}

//最先适应算法  id为输入的作业编号  memorySize为输入的作业大小
bool firstFit( int id, int memorySize ) {
    Node *p = firstPointer->next;	//指针p指向实际的第一个节点

    while( p ) {
        //当前块未被占用且空间>=需要的空间大小
        if( !p->data.flag && p->data.size >= memorySize ) {
            //当前块刚好等于所需要的大小,直接分配
            if( p->data.size == memorySize ) {
                p->data.id = id;
                p->data.flag = 1;
                return true;
            } else {	//当前块大于需要的,只分当前块的前半部分,后半部分还是空闲
                LinkList temp = new Node;	//后面的空闲块

                temp->data.size = p->data.size - memorySize;	//空闲块大小=原来块大小-需要的
                temp->data.address = p->data.address + memorySize;	//地址=原来块的地址+需要的大小
                temp->data.flag = 0;	//表示未被占用
                temp->data.id = 0;
                temp->pre = p;	//相当于在p和p->next之间插入了一个新空闲块
                temp->next = p->next;

                //原节点此时被完全占用
                p->data.size = memorySize;
                p->data.id = id;
                p->data.flag = 1;
                p->next = temp;
                return true;
            }
        }

        p = p->next;

    }

    return false;	//没有找到可用空闲块
}

//作业内存分配
void allocate() {
    int id, memorySize;
    cout << "输入作业编号和申请内存大小:";
    cin >> id >> memorySize;
    bool sign = firstFit( id, memorySize );

    if( sign ) {
        cout << "分配成功\n";
    } else {
        cout << "内存不足,分配失败\n";
    }
}

//作业内存回收,前面的块空闲要与前面块合并,后面的块空闲要与后面的块合并
void recycle() {
    int id;
    Node *p = firstPointer->next;	//指针p指向实际的第一个节点
    cout << "输入要释放的进程序号:";
    cin >> id;

    while( p ) {
        //找到了内存块
        if( p->data.id == id ) {
            p->data.id = 0;	//id=0表示内存卡未被使用
            p->data.flag = 0; // 1占用  0空闲

            //与前一个块合并时要考虑先合并后面的块,这样才能不出错
            if( !p->pre->data.flag ) {
                //合并后面的块
                if( !p->next->data.flag ) {
                    p->data.size += p->next->data.size;	//当前块大小+后面块大小
                    p->next = p->next->next;	//对应指针改变,前后两个指针都要变
                    p->next->next->pre = p;
                }

                //合并前面块
                p->pre->data.size += p->data.size;
                p->pre->next = p->next;
                p->next->pre = p->pre;
            }

            //合并后面块
            if( !p->next->data.flag ) {
                p->data.size += p->next->data.size;
                p->next = p->next->next;
                p->next->next->pre = p;
            }
        }

        p = p->next;
    }
}

int main() {
    init();//初始化
    int choice;
    cout << "*** 1.分配空间\t2.回收空间\t3.显示内存分配情况\t其余按键均为退出***\n\n" ;


    while( 1 ) {
        cout << "输入选项:";
        cin >> choice;

        switch( choice ) {
        case 1:
            allocate();
            break;

        case 2:
            recycle();
            break;

        case 3:
            showInfo();
            break;

        default:
            return 0;
            break;
        }
    }

    return 0;
}

在这里插入图片描述

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值