一、实验目的
分区管理是应用较广泛的一种存储管理技术。本实验要求用一种结构化高级语言构造分区描述器,编制动态分区分配算法和回收算法模拟程序,并讨论不同分配算法的特点。
二、实验内容和要求
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; }