【C++基础复习02】双向链表实现动态分区分配算法
2018-01-05 10:38
417 查看
这是根据操作系统作业写的一个算法,用于模拟实现内存空间的动态分区分配,写的还是比较简单的。使用C++,创建双向链表来模拟动态分区,也当做是对C++链表的复习了。
首先来看具体动态分区结点的定义以及双向链表中方法的定义,具体需要用到的功能都如下所示:
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; //尾结点
};
接下来是关于函数的实现,具体的用法以及思路都写在注释中了:
其中几个排序算法都写的比较冗余了,所以代码片长度看上去就比较长。最后是主函数部分:
我创建了5个内存空间用于初始化测试,分别为30,40,50,40,20大小的内存空间,第一个,第二个,最后一个内存空间被占用。我们运行一下程序来看一下:
这是直接显示了内存空间的分配情况,现在我们来用BF(最佳适应算法)插入一个进程试试:
插入进程的大小为20
再来删除一个20的试试:
首先来看具体动态分区结点的定义以及双向链表中方法的定义,具体需要用到的功能都如下所示:
#include<iostream> #include<cstring> 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;j<i;j++) //利用数组构造结点 { node *p=new node; p->space=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;i<ptr->length;i++,cur=cur->next) //遍历寻找需要释放的结点 { if(cur->space==e) { target=e; //如果找到,直接跳出循环,该节点就是Cur break; } } if(target==-1) //遍历完没有发现需要删除的结点,则输出后直接返回 { cout<<"没有发现需要删除的内存空间"<<endl; return ; } if(cur->prev->status!=0&&cur->next->status!=0) //该节点的前驱和后继结点均被占用 { cur->status=0; //直接释放空间即可 cout<<"已经释放内存空间为"<<target<<"的分区,没有进行合并"<<endl; } 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<<"已经释放内存空间为"<<target<<"的分区,且与下一个相邻空闲分区合并"<<endl; } 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<<"已经释放内存空间为"<<target<<"的分区,且与上一个相邻空闲分区合并"<<endl; } 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<<"已经释放内存空间为"<<target<<"的分区,且与上下两个相邻空闲分区合并"<<endl; } } void doublelink::display(doublelink *ptr) //显示动态分区的安排情况 { node *cur=root->next; for(int i=0;i<ptr->length;i++) //根据长度遍历整个动态分区 { cout<<"--------------------------------------------------------"<<endl; cout<<"第"<<i+1<<"个分区大小为:"<<cur->space<<endl; cout<<"分区的首地址为:"<<cur->address<<endl; if(cur->status==0) cout<<"分区状态为空闲,未分配"<<endl; else cout<<"分区已被分配"<<endl; cout<<endl; cur=cur->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<<"已成功为进程分配内存空间"<<endl; return; //分配成功直接返回 } } cout<<"无法为进程分配内存空间,内存空间不足"<<endl; //遍历到最后都没有成功分配,则说明内存空间不足,分配失败 } void doublelink::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;i<length-1;i++){ //冒泡排序,外循环共进行n-1次 node *cur=new node; cur=root->next; for(int j=0;j<length-1-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<<"已成功进行从大到小排序"<<endl; } void doublelink::bubble(doublelink *ptr) //用冒泡排序算法将内存空间从小到大排序 ,就改了一个小于符号,和上述排序同理 { int temp1,temp2; bool temp3; for(int i=0;i<length-1;i++){ node *cur=new node; cur=root->next; for(int j=0;j<length-1-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<<"已成功进行从小到大排序"<<endl; } void doublelink::addressbubble(doublelink *ptr) { //首地址排序 ,也是冒泡排序,即排序依据是首地址 int temp1,temp2; bool temp3; for(int i=0;i<length-1;i++){ node *cur=new node; cur=root->next; for(int j=0;j<length-1-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<<"已成功将首地址进行从小到大排序"<<endl; }
其中几个排序算法都写的比较冗余了,所以代码片长度看上去就比较长。最后是主函数部分:
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算法插入一个进程"<<endl; cout<<"2.利用BF算法插入一个进程"<<endl; cout<<"3.利用WF算法插入一个进程"<<endl; cout<<"4.显示内存空间"<<endl; cout<<"5.按照首地址顺序排序"<<endl; cout<<"6.释放一个内存空间"<<endl; cout<<"7.退出"<<endl; cin>>n; if(n==7) break; switch(n) { case 1: cout<<"请输入要插入的进程所占空间大小:"<<endl; cin>>i; ptr->FF(ptr,i); break; case 2: cout<<"请输入要插入的进程所占空间大小:"<<endl; cin>>i; ptr->BF(ptr,i); break; case 3: cout<<"请输入要插入的进程所占空间大小:"<<endl; cin>>i; ptr->WF(ptr,i); break; case 4: ptr->display(ptr); //调用显示功能 break; case 5: ptr->addressbubble(ptr); break; case 6: cout<<"请输入要释放的进程所占空间大小:"<<endl; cin>>i; ptr->addressbubble(ptr); //每次都需要排序后再进行删除 ptr->deletespace(ptr,i); break; default:break; } } return 0; }
我创建了5个内存空间用于初始化测试,分别为30,40,50,40,20大小的内存空间,第一个,第二个,最后一个内存空间被占用。我们运行一下程序来看一下:
这是直接显示了内存空间的分配情况,现在我们来用BF(最佳适应算法)插入一个进程试试:
插入进程的大小为20
再来删除一个20的试试:
相关文章推荐
- 双向链表基础操作C++实现
- 双向链表基础操作C++实现
- c++复习基础要点02 虚函数与模板 与static inline是否共存
- 算法与数据结构基础1:C++实现动态数组
- c++复习基础要点02 虚函数与模板 与static inline是否共存
- 双向链表基础操作C++实现
- c\c++复习基础要点05---assert断言及其自定义实现
- 双向链表基础操作C++实现
- c++ 模板类实现 动态顺序表 基础操作
- 双向链表基础操作C++实现
- 双向链表基础操作C++实现
- 双向链表基础操作C++实现
- 双向链表基础操作C++实现
- 双向链表基础操作C++实现
- 双向链表基础操作C++实现
- 双向链表基础操作C++实现
- 双向链表基础操作C++实现
- 双向链表基础操作C++实现
- 双向链表基础操作C++实现
- 双向链表基础操作C++实现