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


    一、实验目的

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

    二、实验内容和要求

    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;
    }
  • 相关阅读:
    力扣算法题—070爬楼梯
    力扣算法题—069x的平方根
    力扣算法题—068文本左右对齐
    天梯杯 L2-008. 最长对称子串
    CODE[VS] 1294 全排列
    hdu 1829 A Bug's Life(并查集)
    HDU 1213 How Many Tables
    POJ 1182 食物链(经典并查集) (多组输入有时乱加也会错!)
    天梯杯 L2-010. 排座位
    The Suspects POJ1611
  • 原文地址:https://www.cnblogs.com/fengchuiguobanxia/p/16279409.html
Copyright © 2020-2023  润新知