【C++基础复习02】双向链表实现动态分区分配算法

这是根据操作系统作业写的一个算法,用于模拟实现内存空间的动态分区分配,写的还是比较简单的。使用C++,创建双向链表来模拟动态分区,也当做是对C++链表的复习了。
首先来看具体动态分区结点的定义以及双向链表中方法的定义,具体需要用到的功能都如下所示:

#include
#include
using namespace std;
const int minsize=5; //允许的最小碎片空间大小为5 
struct node   //动态分区结点 
{  
    int space;  //空间大小 
    int address;  //分区首地址 
    bool status;  //状态号 
    node* prev;  
    node* next;  
}; 

class doublelink //双向链表类来存储
{
public:
doublelink(int sp[],int ad[],int i,bool st[]); //构造函数
void FF(doublelink* ptr,int size);//FF算法 首次适应算法
void BF(doublelink* ptr,int size);//BF算法 最佳适应算法
void WF(doublelink* ptr,int size);//WF算法 最坏适应算法
void display(doublelink* ptr); //显示
int getlength(doublelink* ptr); //获得链表长度
void bubble(doublelink* ptr); //将链表从小到大排序
void rebubble(doublelink* ptr);//将链表从大到小排序
void addressbubble(doublelink* ptr); //将链表按照首地址从小到大排序
void deletespace(doublelink* ptr,int i);//回收内存空间
private:
int length; //记录链表长度
node* root; //头结点
node* tail; //尾结点
};

接下来是关于函数的实现,具体的用法以及思路都写在注释中了:

doublelink::doublelink(int sp[],int ad[],int i,bool st[])
//构造函数的实现
 {
    root=new node;  //头结点中无数据 
    tail=new node;  //尾结点中无数据 
    root->prev=NULL;  //头结点前驱为NULL 
    tail->next=NULL;  //尾结点后继为NULL 
    root->status=1;   //将头尾结点均设置为永久占用状态,方便之后的排序用 
    tail->status=1;
    node *q;
    q=root;
    length=i;         //length记录链表的长度(不包括头和尾) 
    for(int j=0;jspace=sp[j];
        p->address=ad[j];
        p->status=st[j];
        q->next=p;
        p->prev=q;
        q=q->next;
     }
     q->next=tail;          //记得将最后一个动态分区的后继结点指向尾结点 
 }


 int doublelink::getlength(doublelink *ptr)   //获得链表的长度 
 {
    return ptr->length;
  } 



  void doublelink::deletespace(doublelink* ptr,int e) //释放内存空间 
  {
       node *cur=root->next; //利用cur结点来遍历整个空间 
       int target=-1;   //初始化释放内存空间的大小为-1 
       for(int i=0;ilength;i++,cur=cur->next) //遍历寻找需要释放的结点 
       {
         if(cur->space==e)
         {
         target=e;        //如果找到,直接跳出循环,该节点就是Cur 
         break;
         }      
       }
       if(target==-1)        //遍历完没有发现需要删除的结点,则输出后直接返回 
       {
       cout<<"没有发现需要删除的内存空间"<if(cur->prev->status!=0&&cur->next->status!=0) //该节点的前驱和后继结点均被占用 
       {
        cur->status=0;     //直接释放空间即可 
        cout<<"已经释放内存空间为"<"的分区,没有进行合并"<else if(cur->prev->status!=0&&cur->next->status==0)//该结点的后继结点为空 
       {
        cur->status=0;
        cur->space=cur->space+cur->next->space; //将后继结点合并到当前结点 
        cur->next=cur->next->next;
        cur->next->prev=cur;
        length--;  //记得将动态分区数减1 
        cout<<"已经释放内存空间为"<"的分区,且与下一个相邻空闲分区合并"<else if(cur->prev->status==0&&cur->next->status!=0)//该节点的前驱结点为空闲 
       {
        cur->prev->space=cur->space+cur->prev->space; //将前驱结点与当前结点合并 
        cur->prev->next=cur->next;
        cur->next->prev=cur->prev;
        delete cur;
        length--;
        cout<<"已经释放内存空间为"<"的分区,且与上一个相邻空闲分区合并"<else if(cur->prev->status==0&&cur->next->status==0) //该节点的前驱和后继结点都为空闲 
       {
        node *p=cur->prev;
        node *q=cur->next;
        p->space=p->space+cur->space+q->space;  //将该节点以及其后继合并到其前驱结点 
        p->next=q->next;
        q->next->prev=p;
        delete cur,q;
        length=length-2; //注意3个分区合并成1个,所以要减去2 
        cout<<"已经释放内存空间为"<"的分区,且与上下两个相邻空闲分区合并"<next;
    for(int i=0;ilength;i++)   //根据长度遍历整个动态分区 
    {   
        cout<<"--------------------------------------------------------"<"第"<1<<"个分区大小为:"<space<"分区的首地址为:"<address<if(cur->status==0)
         cout<<"分区状态为空闲,未分配"<else
          cout<<"分区已被分配"<next;

     }
 }

 void doublelink::FF(doublelink *ptr,int size) //FF算法 
 {
    node *cur=root->next;
    for(;cur!=tail;cur=cur->next)//遍历所有空间 
    {
        if(size<=cur->space&&cur->status==0)//首次找到适应的就插入 
        {
            cur->status=1;
            if(cur->space-size>minsize) //剩余空间大于最小碎片要求,进行分区 
            {   node *p=new node; //p为插入新的动态分区,成为当前结点的后继结点 
                node *q=new node; //q为当前结点的后继结点 
                q=cur->next;
                p->space=cur->space-size;
                p->address=cur->address+size;
                p->status=0;
                q->prev=p;           //开始重新设置指针指向 
                p->next=q;
                cur->next=p;
                p->prev=cur;
                 length++;  //多了一个分区,长度+1 
                 cur->space=size;  //当前分区大小为正好需要内存空间的大小 

             }
             cout<<"已成功为进程分配内存空间"<"无法为进程分配内存空间,内存空间不足"<BF(doublelink *ptr,int size) //BF算法 最佳适应算法 
    {    
    bubble(ptr); //只要将内存空间从小到大排序后再进行一次FF算法即可完成 
    FF(ptr,size);
    bubble(ptr);
    }

void doublelink::WF(doublelink *ptr,int size)//WF算法  最坏适应算法 
 {
    rebubble(ptr);//只要将内存空间从大到小排序后再进行一次FF算法即可完成
    FF(ptr,size);
    rebubble(ptr);
 } 

 void doublelink::rebubble(doublelink *ptr) //用冒泡排序算法将内存空间从大到小排序 
 {
    int temp1,temp2;   //用于交换内存空间大小 
    bool temp3;          //用于交换分区占用情况 
     for(int i=0;i1;i++){ //冒泡排序,外循环共进行n-1次 
         node *cur=new node;
            cur=root->next; 
         for(int j=0;j1-i;j++,cur=cur->next){  //内循环一一比较 
         node *p=new node;
         p=cur->next;
         if(cur->spacespace)  //如果小于则进行交换 
         {
             temp1=cur->space;
             temp2=cur->address;
             temp3=cur->status;
             cur->space=p->space;
             cur->address=p->address;
             cur->status=p->status;
             p->space=temp1;
             p->address=temp2;
             p->status=temp3;            
         }
        }
 }
 //cout<<"已成功进行从大到小排序"<0;i1;i++){
         node *cur=new node;
        cur=root->next;
         for(int j=0;j1-i;j++,cur=cur->next){
         node *p=new node;
         p=cur->next;
         if(cur->space>p->space)
         {
             temp1=cur->space;
             temp2=cur->address;
             temp3=cur->status;
             cur->space=p->space;
             cur->address=p->address;
             cur->status=p->status;
             p->space=temp1;
             p->address=temp2;
             p->status=temp3;            
         }
        }
 }
 //cout<<"已成功进行从小到大排序"<0;i1;i++){
         node *cur=new node;
        cur=root->next;
         for(int j=0;j1-i;j++,cur=cur->next){
         node *p=new node;
         p=cur->next;
         if(cur->address>p->address)
         {
             temp1=cur->space;
             temp2=cur->address;
             temp3=cur->status;
             cur->space=p->space;
             cur->address=p->address;
             cur->status=p->status;
             p->space=temp1;
             p->address=temp2;
             p->status=temp3;            
         }
        }
 }
 cout<<"已成功将首地址进行从小到大排序"<

其中几个排序算法都写的比较冗余了,所以代码片长度看上去就比较长。最后是主函数部分:

 int main()
 {
    int space[]={30,40,50,40,20};
    int address[]={0,30,70,120,140};
    bool st[]={1,1,0,0,1};
    int i=1;  //控制输入内存空间大小 
    int n;  //控制功能选择 
    doublelink *ptr=new doublelink(space,address,5,st); //创建内存空间 
    while (1)
    {
        cout<<"1.利用FF算法插入一个进程"<cout<<"2.利用BF算法插入一个进程"<cout<<"3.利用WF算法插入一个进程"<cout<<"4.显示内存空间"<cout<<"5.按照首地址顺序排序"<cout<<"6.释放一个内存空间"<cout<<"7.退出"<cin>>n;
        if(n==7)
        break; 
        switch(n)
        {
            case 1:
                cout<<"请输入要插入的进程所占空间大小:"<cin>>i;
                ptr->FF(ptr,i);
                break;
                    case 2:
                        cout<<"请输入要插入的进程所占空间大小:"<cin>>i;
                    ptr->BF(ptr,i);
                        break;
                        case 3:                           
                            cout<<"请输入要插入的进程所占空间大小:"<cin>>i;
                            ptr->WF(ptr,i);
                            break;
                        case 4:
                            ptr->display(ptr); //调用显示功能 
                            break;
                        case 5:
                             ptr->addressbubble(ptr);
                             break;
                        case 6:
                            cout<<"请输入要释放的进程所占空间大小:"<cin>>i;
                            ptr->addressbubble(ptr);  //每次都需要排序后再进行删除 
                            ptr->deletespace(ptr,i);
                            break; 
                    default:break;
        }
    }
 return 0;
 }

我创建了5个内存空间用于初始化测试,分别为30,40,50,40,20大小的内存空间,第一个,第二个,最后一个内存空间被占用。我们运行一下程序来看一下:
【C++基础复习02】双向链表实现动态分区分配算法_第1张图片
这是直接显示了内存空间的分配情况,现在我们来用BF(最佳适应算法)插入一个进程试试:
插入进程的大小为20
【C++基础复习02】双向链表实现动态分区分配算法_第2张图片

再来删除一个20的试试:
【C++基础复习02】双向链表实现动态分区分配算法_第3张图片

你可能感兴趣的:(c++)