存储管理动态分区分配及回收算法

一、实验目的

分区管理是应用较广泛的一种存储管理技术。本实验要求用一种结构化高级语言构造分区描述器,编制动态分区分配算法和回收算法模拟程序,并讨论不同分配算法的特点。

二、实验内容和要求

1、编写:First Fit Algorithm

2、编写:Best Fit Algorithm

3、编写:空闲区回收算法

#include <iostream>
#include <iomanip>
using namespace std;

#define MAX_SIZE 32767

//*******************************变量定义********************************
//定义分区描述器
typedef struct node
{
    int id;                    //分区编号    
    int adr;                //分区首地址   
    int size;                //分区大小   
    struct node* prior;        //指向前一个分区的指针
    struct node* next;        //指向下一个分区的指针
};
node* headFree = NULL;        //空闲区链表首指针
node* headDtb = NULL;            //分配区链表首指针
node* tailDtb = NULL;         //分配区链表尾指针

node* back = NULL;            //指向释放区 node 结构的指针

int Free = 0;                    //用户申请存储区的大小(由用户键入)
int backFirstAdr = 0;            //释放区首地址(由用户键入)
int backSize = 0;                //释放区大小(由用户键入)

node INIT;

//*******************************函数定义********************************
//初始化设置函数
void init()
{
    INIT.adr = 0;
    INIT.size = 32767;
    INIT.next = NULL;
    INIT.prior = NULL;

    //空闲区队列首指针指向当前最大的空闲片
    headFree = &INIT;
    headFree->next = NULL;
    headFree->prior = NULL;

    headDtb = NULL;     //分配区链表首指针
    tailDtb = NULL;        //分配区链表尾指针
}

//分配算法的参数输入函数
int input_Assignment()
{
    int a;
    cout << "请输入申请区的大小:";
    cin >> a;
    return a;
}

//回收算法的参数输入函数
void input_Acceptment(int& firstAdr, int& size)
{
    cout << "请输入释放区的首地址:";
    cin >> firstAdr;
    cout << "请输入释放区的大小:";
    cin >> size;
}
//检查释放块合法性函数
void check(node* head, int a, int b)
{
    node* head2 = head;//将头指针留个备份,以备后用
    while (head)
    {
        if (head->adr == a && head->size == b)
        {
            back = head;//head指针指向需要释放的节点
            cout << "该释放块合法,正在释放........" << endl;
            break;
        }
        else
        {
            head = head->next;
        }

        if (!head)
        {
            cout << "该释放块不合法,请重新输入!" << endl;
            input_Acceptment(backFirstAdr, backSize);
            a = backFirstAdr;
            b = backSize;

            head = head2;
        }
    }
}

//结果打印函数
void print(node* head)
{
    cout << setw(8) << "首址" << setw(8) << "终址" << setw(8) << "大小" << endl;
    while (head)
    {
        cout << setw(8) << head->adr << setw(8) << head->adr + head->size - 1 << setw(8) << head->size << endl;
        head = head->next;
    }
}

//分配链表尾插入节点函数
void inserttailDtb(node* head)
{
    //将该空闲块加入分配链表尾
    if (!tailDtb)
    {
        tailDtb = head;
        headDtb = head;
    }
    else
    {
        head->prior = tailDtb;
        tailDtb->next = head;
        head->next = NULL;
        tailDtb = head;   //尾指针后移
    }
}

//双向链表的删除函数
void deleteFromDuLinkList(node*& Head, node* head)
{//双向链表的删除(头、中间、尾),Head为需要删除的链表的头指针,head为需要删除的节点
    node* head2 = head;
    node* p;//需要操作的块的前一个
    node* n;//需要操作的块的后一个

    if (!head2->prior && head2->next)//head为头,但head不是唯一一个
    {
        head->next->prior = NULL;
        Head = head->next;//头结点指向下一个
    }

    if (head2->prior && !head2->next)//head为尾,但head不是唯一一个
    {
        head->prior->next = NULL;
    }

    if (!head2->prior && !head2->next)//head为唯一一个节点
    {
        Head = NULL;
    }

    if (head2->prior && head2->next)//head为中间节点
    {
        p = head->prior;
        n = head->next;
        p->next = n;
        n->prior = p;
    }
}

//前插法插入函数
void insertToDuLinkList(node* Head, node* head)
{//(前插法)双向链表正常插入(头、中间、尾),Head指向链表第i个位置,head指向需要插入的节点,在第i个位置之前插入
    node* p;//Head的前一个
    //在头结点前插入(包括只有一个节点)
    if (!Head->prior)
    {
        Head->prior = head;
        head->next = Head;
        head->prior = NULL;
        headFree = head;
    }
    else
    {
        p = Head->prior;
        p->next = head;
        head->next = Head;
        Head->prior = head;
        head->prior = p;
    }
}

//首地址递增插入函数
void insertToDuLinkList1(node* Head, node* head)
{//向双向链表中按照块首地址的递增顺序插入一个节点,Head为链表头指针,head指向需要插入的节点
    while (Head)
    {
        if (Head->adr > head->adr)
        {
            insertToDuLinkList(Head, head);
            break;
        }
        else
        {
            if (!Head->next)//如果都比head->adr小,则插到尾部
            {
                Head->next = head;
                head->prior = Head;
                head->next = NULL;
                break;
            }
            Head = Head->next;
        }
    }
}

//块大小递增插入函数
void insertToDuLinkList2(node* Head, node* head)
{//向双向链表中按照块大小的递增顺序插入一个节点,Head为链表头指针,head指向需要插入的节点
    while (Head)
    {
        if (Head->size > head->size)
        {
            insertToDuLinkList(Head, head);
            break;
        }
        else
        {
            if (!Head->next)//如果都比head->size小,则插到尾部
            {
                Head->next = head;
                head->prior = Head;
                head->next = NULL;
                break;
            }
            Head = Head->next;
        }
    }
}

//检查链表拼接节点函数
void beforeAcceptmentCheck(node* head, node*& before, node*& after)
{//回收前检查是否前后需要拼接,若需要,返回需要拼接节点的指针,before为需要拼接的前节点,after为需要拼接的后节点
    while (head)
    {
        if ((head->adr + head->size) == back->adr)
        {
            before = head;
        }
        if ((back->adr + back->size) == head->adr)
        {
            after = head;
        }

        head = head->next;
    }
}

//最先适应法分配函数
int FirstFitAlgorithm_Assignment(node* head)
{
    //前提是空闲链表已经按照起始地址递增顺序排列好
    //head指向当前空闲链表表头
    //分配完成的块,直接插入分配链末尾

    while (head)
    {
        if (head->size >= Free)
        {
            if (head->size == Free)
            {//从空闲链中移去该空闲块

                //从空闲链中移去该空闲块
                deleteFromDuLinkList(headFree, head);

                //将该空闲块加入分配链表尾
                inserttailDtb(head);

                //返回分配区首地址
                return head->adr;
                break;
            }
            else
            { //从当前空闲块中截取所需大小,重新连接空闲链

                node* remain = new node();    //为剩余存储区分配空间

                remain->adr = head->adr + Free;
                remain->size = head->size - Free;
                remain->next = NULL;
                remain->prior = NULL;

                if (!head->prior && !head->next)//如果原空闲链表中只有一个节点
                {
                    headFree = remain;//头结点指向剩余空闲节点
                }
                else
                {
                    //从双向链表中删除原节点
                    deleteFromDuLinkList(headFree, head);

                    //向双向链表中插入剩余空闲节点
                    insertToDuLinkList1(headFree, remain);
                }

                //修改即将分配的存储空间大小
                head->size = Free;
                //将该空闲块加入分配链表尾
                inserttailDtb(head);

                return head->adr;
                break;
            }
        }
        else
        {
            if (!head->next)//已经查找到最后一个,仍然没有查找到
            {
                cout << "无可用存储空间,无法分配!" << endl;
                return 40000;
                break;
            }
            head = head->next;
        }
    }
}

//最先适应法回收函数
void FirstFitAlgorithm_Acceptment()
{
    //首先将要释放的存储区的(1)首地址和空闲链的每一块的尾地址比较、(2)将要释放的存储区的尾地址和空闲链的每一块的首地址比较
    //if 1\2都不存在,则正常按顺序插入空闲链;if 1有  2无 前拼接;if 1无  2有 后拼接;if 1有 2有 前后拼接
    node* before = NULL;
    node* after = NULL;

    deleteFromDuLinkList(headDtb, back);//从已分配链表中删除将要释放的节点

    beforeAcceptmentCheck(headFree, before, after);//检查是否需要拼接
    if (!before && !after)
    {
        //正常插入
        insertToDuLinkList1(headFree, back);
    }
    if (before && !after)
    {
        //前拼接
        before->size += back->size;
    }
    if (!before && after)
    {
        //后拼接

        //更改释放块的大小
        back->size += after->size;

        //链入空闲链
        if (!after->prior && after->next)//如果after为第一个
        {
            back->next = after->next;
            after->next->prior = back;
            back->prior = NULL;
            headFree = back;
        }
        if (after->prior && !after->next)//如果after为最后一个
        {
            after->prior->next = back;
            back->next = NULL;
            back->prior = after->prior;
        }
        if (!after->prior && !after->next)//如果after为唯一一个
        {
            back->next = NULL;
            back->prior = NULL;
            headFree = back;
        }
        if (after->prior && after->next)//如果after为中间
        {
            after->prior->next = back;
            back->next = after->next;
            after->next->prior = back;
            back->prior = after->prior;
        }
    }
    if (before && after)
    {
        //前后拼接
        before->size = before->size + back->size + after->size;

        //改变before后半部分指针

        if (!after->next)//如果after为最后一个
        {
            before->next = NULL;
        }
        if (after->next)//如果after不是最后一个
        {
            before->next = after->next;
            after->next->prior = before;
        }
    }
}

//最佳适应法分配函数
int BestFitAlgorithm_Assignment(node* head)
{
    //前提是空闲链表已经按照空闲链表块大小递增顺序排列好
    //head指向当前空闲链表表头
    //分配完成的块,直接插入分配链末尾

    while (head)
    {
        if (head->size >= Free)
        {
            if (head->size == Free)
            {//从空闲链中移去该空闲块

                //从空闲链中移去该空闲块
                deleteFromDuLinkList(headFree, head);

                //将该空闲块加入分配链表尾
                inserttailDtb(head);

                //返回分配区首地址
                return head->adr;
                break;
            }
            else
            { //从当前空闲块中截取所需大小,重新连接空闲链

                node* remain = new node();    //为剩余存储区分配空间

                remain->adr = head->adr + Free;
                remain->size = head->size - Free;
                remain->next = NULL;
                remain->prior = NULL;

                if (!head->prior && !head->next)//如果原空闲链表中只有一个节点
                {
                    headFree = remain;//头结点指向剩余空闲节点
                }
                else
                {
                    //从双向链表中删除原节点
                    deleteFromDuLinkList(headFree, head);

                    //向双向链表中插入剩余空闲节点
                    insertToDuLinkList2(headFree, remain);
                }

                //修改即将分配的存储空间大小
                head->size = Free;
                //将该空闲块加入分配链表尾
                inserttailDtb(head);

                return head->adr;
                break;
            }
        }
        else
        {
            if (!head->next)//已经查找到最后一个,仍然没有查找到
            {
                cout << "无可用存储空间,无法分配!" << endl;
                return 40000;
                break;
            }
            head = head->next;
        }
    }
}

//最佳适应法回收函数
void BestFitAlgorithm_Acceptment()
{
    //首先将要释放的存储区的(1)首地址和空闲链的每一块的尾地址比较、(2)将要释放的存储区的尾地址和空闲链的每一块的首地址比较
    //if 1\2都不存在,则正常按顺序插入空闲链;if 1有  2无 前拼接;if 1无  2有 后拼接;if 1有 2有 前后拼接
    node* before = NULL;
    node* after = NULL;

    deleteFromDuLinkList(headDtb, back);//从已分配链表中删除将要释放的节点

    beforeAcceptmentCheck(headFree, before, after);//检查是否需要拼接
    if (!before && !after)
    {
        //正常插入
        insertToDuLinkList2(headFree, back);
    }
    if (before && !after)
    {
        //前拼接
        before->size += back->size;
    }
    if (!before && after)
    {
        //后拼接

        //更改释放块的大小
        back->size += after->size;

        //链入空闲链
        if (!after->prior && after->next)//如果after为第一个
        {
            back->next = after->next;
            after->next->prior = back;
            back->prior = NULL;
            headFree = back;
        }
        if (after->prior && !after->next)//如果after为最后一个
        {
            after->prior->next = back;
            back->next = NULL;
            back->prior = after->prior;
        }
        if (!after->prior && !after->next)//如果after为唯一一个
        {
            back->next = NULL;
            back->prior = NULL;
            headFree = back;
        }
        if (after->prior && after->next)//如果after为中间
        {
            after->prior->next = back;
            back->next = after->next;
            after->next->prior = back;
            back->prior = after->prior;
        }
    }
    if (before && after)
    {
        //前后拼接
        before->size = before->size + back->size + after->size;

        //改变before后半部分指针

        if (!after->next)//如果after为最后一个
        {
            before->next = NULL;
        }
        if (after->next)//如果after不是最后一个
        {
            before->next = after->next;
            after->next->prior = before;
        }
    }
}

//主菜单
void menu()//菜单及主要过程
{
    int chose; //存放用户选择的算法
    int ch; //ch存放用户的操作
    int flag1 = 1;
    int flag2 = 1;
    while (flag1)
    {
        system("cls");
        cout << "欢迎进入存储管理动态分区分配及回收算法" << endl << endl;
        cout << "****************************************************" << endl;
        cout << "   请选择存储管理动态分区分配及回收算法:      " << endl;
        cout << "              1 - 最先适应算法                 " << endl;
        cout << "              2 - 最佳适应算法                 " << endl;
        cout << "              3 - 退出程序                     " << endl;
        cout << "\n请输入选项:";
        cin >> chose;
        switch (chose)
        {
        case 1:
        {
            while (flag2)
            {
                //system("cls");
                cout << "\n******************最先适应算法**********************" << endl;
                cout << "           请选择待执行操作:                   " << endl;
                cout << "           1 - 分配内存                         " << endl;
                cout << "           2 - 回收内存                        " << endl;
                cout << "           3 - 返回                            " << endl;
                cout << "\n请输入选项:";
                cin >> ch;
                fflush(stdin);//清空输入缓冲区
                switch (ch)
                {
                case 1:
                {
                    cout << "\n****************************************************" << endl;
                    Free = input_Assignment();
                    cout << "分配的首地址为:" << FirstFitAlgorithm_Assignment(headFree) << endl;
                    cout << "\n----------空闲链表----------" << endl;
                    print(headFree);
                    cout << "----------分配链表----------" << endl;
                    print(headDtb);
                }
                break;

                case 2:
                {
                    cout << "\n****************************************************" << endl;
                    input_Acceptment(backFirstAdr, backSize);
                    check(headDtb, backFirstAdr, backSize);
                    FirstFitAlgorithm_Acceptment();
                    cout << "\n----------空闲链表----------" << endl;
                    print(headFree);
                    cout << "----------分配链表----------" << endl;
                    print(headDtb);
                }
                break;

                case 3:
                    flag2 = 0;
                    break;
                }
            }
        }

        case 2:
        {
            while (flag2)
            {
                //system("cls");
                cout << "\n********************最佳适应算法********************" << endl;
                cout << "           请选择待执行操作:                   " << endl;
                cout << "           1 - 分配内存                         " << endl;
                cout << "           2 - 回收内存                        " << endl;
                cout << "           3 - 返回                            " << endl;
                cout << "\n请输入选项:";
                cin >> ch;
                fflush(stdin);//清空输入缓冲区
                switch (ch)
                {
                case 1:
                {
                    cout << "\n****************************************************" << endl;
                    Free = input_Assignment();
                    cout << "分配的首地址为:" << BestFitAlgorithm_Assignment(headFree) << endl;
                    cout << "\n----------空闲链表----------" << endl;
                    print(headFree);
                    cout << "----------分配链表----------" << endl;
                    print(headDtb);
                }
                break;

                case 2:
                {
                    cout << "\n****************************************************" << endl;
                    input_Acceptment(backFirstAdr, backSize);
                    check(headDtb, backFirstAdr, backSize);
                    BestFitAlgorithm_Acceptment();
                    cout << "\n----------空闲链表----------" << endl;
                    print(headFree);
                    cout << "----------分配链表----------" << endl;
                    print(headDtb);
                }
                break;

                case 3:
                    flag2 = 0;
                    break;
                }
            }
        }

        case 3:
            flag1 = 0;
            break;
        }
    }
}

//主函数
int main()
{
    system("color 3f");
    init();
    menu();
    return 0;
}

 

posted @ 2022-05-17 07:51  风吹过半夏  阅读(456)  评论(0编辑  收藏  举报