动态分区-首次适应&最佳适应

编写并调试一个可变式分区分配的存储管理方案。并模拟实现分区的分配和回收过程。

对分区的分配算法可以是下面三种算法之一:
  • 首次适应算法
  • 循环首次适应算法
  • 最佳适应算法

1,在内存分配时,系统优先使用空闲区低端的空间
10240+102380=112640 从地址112460开始分配,由低端向高端增长。
例如:分配给作业1,作业长度20,==》起始地址:112620,长度20,标志1。
每次分配,从起始地址最大的结点开始查找是否有合适区域
2,首次适应算法

// Memory_V1.cpp : 定义控制台应用程序的入口点。

/*
*Name:Memory_V1.cpp
*Author:WangLin
*Created On:2015/11/04
*Function:首次适应算法 可变式分区分配,模拟实现分区的分配和回收过程。 
*/
#include "stdafx.h"
# include<iostream>
using namespace std;

struct  partition //分区结构体:起始地址+分区长度+标志
{
    int addr;
    int length;
    int tag;
    partition* next;
};
partition *empty=new partition; //空闲分区
partition *busy=new partition;//已分配区


//初始化函数
void init()
{
    //空闲分区初始化,empty和busy始终指向首地址最大结点,即低端第一个结点
    empty->addr=10240;
    empty->length=102400;
    empty->tag=1;//1表示可用
    empty->next=NULL;

    //已分配区初始化
    busy->addr=0;
    busy->length=0;
    busy->tag=0;//0表示空闲
    busy->next=NULL;
}

/*
分配主存
*/
void distriMemory()
{
    int pname,plength;
    partition* temp=new partition;
    cout<<"输入作业名(请输入数字):";
    cin>>pname;
    temp->tag=pname;
    cout<<endl;

    cout<<"输入作业所需长度xk:";
    cin>>plength;
    temp->length=plength;

    //为新作业分配主存,在空闲区表中,寻找长度大于等于temp结点长度的结点
    partition* q=new partition;
    partition* p=new partition;
    bool isfind=false;//标志是否找到可分配的区域
    for(q=empty;;p=q,q=q->next)//p是q的前驱
    {
        if((q->tag==1)&&(q->length>=temp->length))
        {
            isfind=true;
            temp->addr=(q->addr+q->length)-temp->length;//在已分配区表中创建分配结点,分配区域
            q->length-=temp->length;    //修改空闲区表长度
            if(q->length==0)//长度为0,区域已经不可以再分配了,从空闲区表删除
            {
                if(q==empty)//删除首结点
                    empty=empty->next;
                else
                    p->next=q->next;
            }
            break;
        }
    }
    if(isfind)
    {
        //修改已分配区表,temp挂到busy队列中
        for(q=busy;;p=q,q=q->next)//找到第1个addr<temp->addr的结点q,temp插在q前面
            if(q->addr<temp->addr)break;
        if(q==busy)
        {
            temp->next=busy;//先连
            busy=temp;//后断
        }
        else
        {
            temp->next=q;//先连
            p->next=temp;//后断
        }
        cout<<"内存已分配!"<<endl;
    }
    else
        cout<<"找不到合适大小的区域,内存分配失败!"<<endl;
}

/*
回收主存:4种情况
*/
void colletMemory()
{
    int pname;
    cout<<"输入要回收分区的作业名:";
    cin>>pname;

    //在已分配区表中,按作业名查找要回收的结点p,何时删除这个结点?
    partition* q=new partition;
    partition* bfp=new partition;//p的前驱
    partition* p=new partition;
    partition* m=new partition;
    for(p=busy;p!=NULL;bfp=p,p=p->next)
    {
        if((p->tag==pname)&&(p->addr!=0)&&(p->length)!=0)
        {

            if(p==busy)
                busy=busy->next;
            else
                bfp->next=p->next;
            p->next=NULL;//从已分配区表中取下p结点
            break;
        }
    }
    if(p!=NULL)
    {
        //==============4种情况修改空闲表========================================
        for(q=empty;;m=q,q=q->next)//寻找地址和p相邻的结点,m->addr>p->addr>q->addr
            if((q->tag==1)&&(q->addr<p->addr))
                break;
        //case1回收区与插入点的前一个空闲分区F1相邻接,此时将两个分区合并() p和m相邻,修改m,删除p
        if(((p->addr+p->length)==m->addr)&&((q->addr+q->length)!=p->addr))
        {
            m->length+=p->length;
            m->addr-=p->length;
            m->tag=1;
            delete(p);
        }

        //case2回收区与插入点的后一个空闲分区F2相邻接,此时将两个分区合并,p和q相邻,修改p,删除q
        else if(((q!=empty)&&(p->addr+p->length)!=m->addr)&&((q->addr+q->length)==p->addr))
        {
            q->length+=p->length;
            q->tag=1;
            delete(p);
        }
        //3)回收区与插入点的前,后两个空闲分区相邻接,此时将三个分区合并,m,p,q相邻,修改m,删除p,q
        else if(((p->addr+p->length)==m->addr)&&((q->addr+q->length)==p->addr))
        {
            m->length+=(p->length+q->length);
            m->addr-=(p->length+q->length);
            m->next=q->next;
            m->tag=1;
            delete(p);
            delete(q);
        }

        //4)回收区既不与F1相邻接,又不与F2相邻接,此时应为回收区单独建立一个新表项,p挂到空闲表区中m和q之间
        else
        {
            p->tag=1;
            if(q==empty)
            {
                if(((q->addr+q->length)==p->addr))
                    q->length+=p->length;
                else
                {
                    p->next=empty;
                    empty=p;
                }
            }
            else
            {
                p->next=q;//先连
                m->next=p;//后断
            }
        }
        //================空闲表区修改完毕-===================
        cout<<"内存已回收!"<<endl;
    }
    else
        cout<<"作业不存在!"<<endl;
}

/*显示主存
(1)显示空闲分区表 empty
(2)显示已分配表busy
*/
void dispMemory()
{
    partition *p=new partition;
    char ch;
    p=empty;//(1)显示空闲分区表 empty
    cout<<endl<<"+++++++++++++"<<endl<<"【输出空闲分区表】"<<endl;
    cout<<"起始地址"<<"     "<<"分区长度"<<"        "<<"标志"<<endl;
    while(p!=NULL)
    {
        cout<<p->addr<<"            ";
        cout<<p->length<<"         ";
        cout<<p->tag<<endl;
        p=p->next;
    }

    p=busy;//(2)输出已分配区表 busy
    cout<<endl<<"+++++++++++++"<<endl<<"【输出已分配区表】"<<endl;
    cout<<"起始地址"<<"     "<<"分区长度"<<"        "<<"标志"<<endl;
    while(p!=NULL)
    {
        cout<<p->addr<<"            ";
        cout<<p->length<<"         ";
        cout<<p->tag<<endl;
        p=p->next;
    }
}
int _tmain(int argc, _TCHAR* argv[])
{
    init();
    bool stop_flag=true;//程序结束标志
    int ch;
    while(stop_flag)
    {
        cout<<endl<<"============================================================="<<endl;
        cout<<"选择功能项<0-退出;1-分配主存;2-回收主存;3-显示主存>"<<endl;
        cout<<"显示功能项<0-3>:";
        cin>>ch;
        switch (ch)
        {
        case 0:cout<<"程序已结束,再见!"<<endl;stop_flag=false;
            break;
        case 1:distriMemory();
            break;
        case 2:colletMemory();
            break;
        case 3:dispMemory();
            break;
        default:cout<<"输入有误,请重新输入"<<endl;
            break;
        }
    }
    return 0;
}



【调试结果】:
这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

3 .最佳适应算法


/*
分配主存
*/
void distriMemory()
{
    int pname,plength;
    partition* temp=new partition;
    cout<<"输入作业名(请输入数字):";
    cin>>pname;
    temp->tag=pname;
    cout<<endl;

    cout<<"输入作业所需长度xk:";
    cin>>plength;
    temp->length=plength;

    //为新作业分配主存,在空闲区表中,寻找长度大于等于temp结点长度的结点
    partition* q=new partition;
    partition* p=new partition;


    //从全部空闲区中找出能满足作业需求的容量最小的空闲区分配之
    q->length=MAXLENGTH;
    partition* s=empty;
    partition* ps=new partition;
    while(s!=NULL)
    {
        if((s->tag==1)&&(s->length>=temp->length))
        {
            if(s->length<q->length)
            {
                p=ps;//p是q的前驱
                q=s;
            }
        }
        ps=s;//ps是s的前驱
        s=s->next;
    }
    if(q->length!=MAXLENGTH)//如果找到可以分配的区域
    {
        temp->addr=(q->addr+q->length)-temp->length;//在已分配区表中创建分配结点,分配区域
        q->length-=temp->length;    //修改空闲区表长度
        if(q->length==0)//长度为0,区域已经不可以再分配了,从空闲区表删除
        {
            if(q==empty)//删除首结点
                empty=empty->next;
            else
                p->next=q->next;
        }

        //修改已分配区表,temp挂到busy队列中
        for(q=busy;;p=q,q=q->next)//找到第1个addr<temp->addr的结点q,temp插在q前面
            if(q->addr<temp->addr)break;
        if(q==busy)
        {
            temp->next=busy;//先连
            busy=temp;//后断
        }
        else
        {
            temp->next=q;//先连
            p->next=temp;//后断
        }
        cout<<"内存已分配!"<<endl;
    }
    else
        cout<<"找不到合适大小的区域,内存分配失败!"<<endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值