操作系统实验之动态分区分配算法

一、实验内容

设计程序模拟四种动态分区分配算法:首次适应算法、循环首次适应算法、最佳适应算法和最坏适应算法的工作过程。假设内存中空闲分区个数为n,空闲分区大小分别为P1, … ,Pn,在动态分区分配过程中需要分配的进程个数为m(m≤n),它们需要的分区大小分别为S1, … ,Sm,分别利用四种动态分区分配算法将m个进程放入n个空闲分区,给出进程在空闲分区中的分配情况。

二、C++代码

#include<iostream>
#include<string>
#include<list>
using namespace std;
#define MaxNum 100

typedef struct Node{//每个分区用一个结点表示
    int index;//表示该分区是第几分区,例如:第1分区、第2分区
    list<string> process;//用来存放进程名
    struct Node *next;//指向下一个分区
    struct Node *before;//指向前一个分区
    int orilen;//原始的分区大小
    int length;//现在的分区大小
}Node,*NodeLink;

int index[MaxNum];
int pnum,snum;
string name[MaxNum];
int length[MaxNum];


void print(int pnum,int snum,string name[],int index[],NodeLink space){
    //打印输出
    Node *p = space,*q;
    int count = 0;
    for(int i=0;i<pnum;i++){
        cout<<name[i]<<"在分区"<<index[i]<<endl;
    }
    do{
        cout<<"第"<<p->index<<"分区有进程:";
        list<string>::iterator itor;
        itor = p->process.begin();
	    while(itor!=p->process.end()){
            cout<< *itor++;//输出作业名
        } 
        q = p;
        p = p->next;
        ++count;
        free(q);
        cout<<endl;
    } while (p != space && count != snum);
    cout<<endl;
    cout<<"-------------------------"<<endl;
}

NodeLink sort(NodeLink begin){
    //对空闲分区进行从小到大的排序
    Node *temp = begin->next,*p,*q,*node;
    //将链表置空
    node = begin;
    begin->next = begin;
    begin->before = begin;
    bool tag;
    while(temp!=node){
        //保存原链表中temp的下一个节点
        tag = true;
        q = temp->next;
        //找到temp插入的位置
        for(p = begin;(p != begin || tag)&& p->length < temp->length ; p=p->next) {
            tag = false;
        }
        //将temp插入到p之前
        temp->next = p;
        temp->before = p->before;
        p->before->next = temp;
        p->before = temp; 
        if (p == begin && p->length > temp->length){
            begin = temp;
        }
        //将temp指向要插入的下一个节点
        temp = q;
    }
    begin->before->next = begin;
    return begin;
}

void FF(int pnum,int snum,string name[],int length[],Node *space){
    //首次适应算法
    Node *flag;//用来标志
    for (int i = 0; i < pnum; i++){
        flag = space;//从第一个分区开始查找
        do{
            if(length[i] <= flag->length){//分区内存是否够分配作业
               flag->length -= length[i];//分区大小减去作业大小
               index[i] = flag->index;//保存作业在位置
               flag->process.push_back(name[i]);//保存进程名
               break;
            }else{
                flag = flag->next;//下一个分区
            }
        } while (flag != space);//是否查找过所有的分区,避免出现死循环的情况
    }
    cout<<"首次适应算法"<<endl;
    print(pnum,snum,name,index,space);//打印输出结果
}

void NF(int pnum,int snum,string name[],int length[],Node *space){
    //循环适应算法
    Node *flag = space,*end;//flag指向每一轮开始分配的分区,用于遍历分区,end用于保存flag开始的位置
    bool tag;//用于区分以下两种情况
    for (int i = 0; i < pnum; i++){
        //flag == end有两种情况,
        //一种是查找的第一个分区就能够分配作业
        //另一种是查找过所有的分区了,而都不足以分配作业的情况
        tag = true;
        end = flag;//保存flag开始的位置
        while (length[i] > flag->length){//查找分区内存够分配作业
            flag = flag->next;
            if (end == flag){//判断是否已经查找过所有的分区了,若是的话则退出,避免陷入死循环
                tag = false;
                break;
            }
        }
        if (tag || flag != end){//找到可分配的分区
            flag->length -= length[i];//分区大小减去作业大小
            index[i] = flag->index;//保存作业在位置
            flag->process.push_back(name[i]);//保存进程名
            flag = flag ->next;//指向下一个分区
        }
    }
    cout<<"循环适应算法"<<endl;
    print(pnum,snum,name,index,space);
}

void BF(int pnum,int snum,string name[],int length[],Node *space){
    //最佳适应算法
    Node *flag,*temp;//flag用于遍历分区,temp用于重新进行分区的排序标记flag要插入的位置
    bool tag;//用于区分以下两种情况
    space = sort(space);//将分区按照从小到大进行排序
    for (int i = 0; i < pnum; i++){
        //flag == space有两种情况,
        //一种是每一次查找的第一个分区就能够分配作业
        //另一种是查找过所有的分区了,而都不足以分配作业的情况
        tag = true;
        flag = space;//指向最小的分区
        //从最小的分区开始查找大小最适合的空闲分区
        while (length[i] > flag->length){
            flag = flag->next;
            if (flag == space){//判断是否已经查找过所有的分区了,若是的话则退出,避免陷入死循环
                tag = false;
                break;
            }
        }
        if (tag || flag != space){//找到可分配的分区
            flag->length -= length[i];//分区大小减去作业大小
            index[i] = flag->index;//保存作业在位置
            flag->process.push_back(name[i]);//保存进程名
            if (flag == space)continue;//若flag就是第一个分区,则不用再排序
            //开始重新排序,不用sort()方法,因为没必要
            temp = space;//从第一个分区开始往后查找
            while(temp->length <= flag->length){//遍历分区,直到找到合适的位置
                temp = temp->next;
            }
            //将flag指向的分区插入到刚才找到的位置
            flag->before->next = flag->next;
            flag->next->before = flag->before;
            flag->before = temp->before;
            flag->next = temp;
            temp->before->next = flag;
            temp->before = flag;
            //判断temp是否是space,若是的话,说明flag指向的分区现在的大小是所有分区中最小的,要更改space的值
            if (temp == space){
                space = flag;
            }
            
        }
    }
    cout<<"最佳适应算法"<<endl;
    print(pnum,snum,name,index,space);
}

void WF(int pnum,int snum,string name[],int length[],Node *space){
    //最坏适应算法
    Node *end,*p;
    space = sort(space);//将分区按照从小到大进行排序
    for (int i = 0; i < pnum; i++){
        end = space ->before;//end指向最大的分区
        if (end->length > length[i]){//若最大的分区可以分配内存给该作业
            index[i] = end->index;//保存作业在位置
            end->process.push_back(name[i]);//保存进程名
            end->length -= length[i];//分区大小减去作业大小
            for (p = end->before;p != end && p->length >= end->length;p = p->before){
                //遍历分区,直到找到合适的位置
            }
            //判断p是否指向end,若是则说明end指向的分区现在的大小是所有分区中最小的,要更改space的值
            if (p != end){
                //将end指向的分区插入到刚才找到的位置
                end->before->next = end->next;
                end->next->before  =end->before;
                end->before->next = end->next;
                end->next->before = end->before;
                end->before = p;
                end->next = p->next;
                p->next->before = end;
                p->next = end;
            }else{
                space = end;
            }
        }
    }
    cout<<"最坏适应算法"<<endl;
    print(pnum,snum,name,index,space);
}

NodeLink create(int snum,int space[]){
    //构造双向循环链表
    Node *p,*node,*q;
    int i;
    for(i=0;i<snum;i++){
        q = new Node;
        // cin>>q->length;
        q->length = space[i];
        q->index = i + 1;
        q->orilen = q->length;
        if (i == 0){
            q->before = NULL;
            node = q;
            p = q;
        }else{
            p->next = q;
            q->before = p;
            q->next = NULL;
            p = q;
        }
    }
    node->before = q;
    q->next = node;
    return node;
}

int main(int argc, char* argv[])
{
    //int pnum = 3,snum = 4,slen,i;
    int i;
    cout<<"请输入待分配的作业数:";
    cin>>pnum;
    //string name[3] = {"a","b","c"};
    //int length[3] = {8,12,35};
    cout<<"请输入作业名称:";
    for(i=0;i<pnum;i++){
        cin>>name[i];
    }
    cout<<"请输入作业的大小:";
    for(i=0;i<pnum;i++){
        cin>>length[i];
    }
    cout<<"请输入空闲分区的个数:";
    cin>>snum;
    int space[MaxNum];
    //= {64,8,16,32};3
    cout<<"请输入空闲分区的大小:";
    for(i=0;i<snum;i++){
        cin>>space[i];
    }
    Node *node;
    string temp;
    for (i = 0; i < pnum; i++){
        cout<<name[i]<<"  "<<length[i]<<endl;
    }
    cout<<endl;
    while (1){
        cout<<"输入你要执行的操作:"<<endl;
        cout<<"1-FF(首次适应算法),2-NF(循环首次适应算法),3-BF(最佳适应算法),4-WF(最坏适应算法),5-退出:";
        cin>>i;
        if (i == 1){
            node = create(snum,space);
            FF(pnum,snum,name,length,node);
        }else if (i == 2){
            node = create(snum,space);
            NF(pnum,snum,name,length,node);
        }else if (i == 3){
            node = create(snum,space);
            BF(pnum,snum,name,length,node);
        }else if (i == 4){
            node = create(snum,space);
            WF(pnum,snum,name,length,node);
        }else{
            break;
        }

    }
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值