操作系统实验:首次适应算法、最佳适应算法、最坏适应算法

1、首次适应算法

概念:首次适应算法从空闲分区表的第一个表目起查找该表,把最先能够满足要求的空闲区分配给作业,这种方法目的在于减少查找时间。

实验要求:已知作业名、作业大小、作业提交时间、内存容量、碎片大小,要求使用分区大小不等的内存分区方法和首次适应分配算法给每次到来的作业分配内存。输出内存分区情况和分配情况。

#include <iostream>
using namespace std;

#define FREE 0
#define  BUSY 1
#define  MAX_length 300
const double debri = 20; //设置碎片大小
// FREE代表空闲  BUSY代表已分配 

typedef struct free_area //首先定义空闲区分表结构
{
int flag;
int size;
int number;
int begin_address;
 }Elemtype;
 
typedef struct Free_Node
{
	Elemtype date;
	struct Free_Node *prior;
	struct Free_Node *next;
}Free_Node,*pNod;
 
pNod headNode;
pNod initNode;
int m_allocation();//作业分配
int free(int number);//作业回收
bool ff(int number,int size);//首次适应算法
void show();//查看分配
void init();//初始化

int main()
{
	int tag=0;
	int number;
	init();
	while(tag!=4)
	{
		cout<<"请选择操作: 1-申请作业,2-作业回收,3-显示作业状况,4-退出"<<endl;
		cin>>tag;
		switch(tag)
			{
		    case 1:
				m_allocation();
				    break;
			case 2:
				cout<<"请输入需要回收的number号:"<<endl;
				cin>>number;
				free(number);
					break;
			case 3:
				show();
				break;
			default:
				return 0;
		    }
	}
	return 0;
}

void init()
{
	headNode=new Free_Node;
	initNode = new Free_Node;
	headNode->prior=NULL;
	headNode->next=initNode;
	initNode->prior=headNode;
	initNode->next=NULL;
	initNode->date.begin_address=0;
	initNode->date.flag=FREE;
	initNode->date.number= 0;
	initNode->date.size=MAX_length;
}
 
//实现作业分配
int m_allocation()
{
	int number,size1;
	cout<<"请输入作业号:";
	cin>>number;
	cout<<"请输入所需作业大小:";
	cin>>size1;

	if(ff(number,size1))
	{		
		cout<<"分配成功!"<<endl;
	}
	else cout<<"分配失败!"<<endl;
	return 1;
}
 
bool ff(int number,int size)//首次适应算法
{
	 pNod temp= new Free_Node;
	 Free_Node *p=headNode->next;  //从首节点开始
	 temp->date.number=number;
	 temp->date.size=size;
	 temp->date.flag=BUSY;
	while(p)
	{
		if (p->date.flag==FREE &&  p->date.size == size )//请求大小刚好满足
		{
			p->date.flag=BUSY;
			p->date.number=number;
			return true;
		}
		if (p->date.flag==FREE && p->date.size>size)//说明还有其他的空闲区间
		{
			temp->next=p;
			temp->prior=p->prior;
			temp->date.begin_address=p->date.begin_address;
			p->prior->next=temp;
			p->prior=temp;
			p->date.begin_address=temp->date.begin_address+temp->date.size;//空闲分区开始地址+此次分配的空间
			p->date.size-=size;      //分配空闲作业
		    return true;
		}
		p=p->next;
	}
	return false;
}

int free(int number)//主存回收
{
	Free_Node *p=headNode->next;
	while(p)
	{
		if (p->date.number==number)//找到要回收的number区域
		{
			p->date.flag=FREE;
			p->date.number=FREE;
			//判断P与前后区域关系

			//1、回收分区r上临一个空闲分区,此时应该合并为一个连续的空闲区,其始址为r上相邻的分区的首地址,而大小为两者大小之和
			if (p->prior->date.flag==FREE&&p->next->date.flag!=FREE)   
			{
				p->prior->date.size+=p->date.size;
				p->prior->next=p->next;  //将要回收分区的前后两个分区链接起来
				p->next->prior=p->prior;
			}
			//2、回收分区r与下相邻空闲分区,合并后仍然为空闲区,该空闲区的始址为回收分区r的地址。大小为两者之和
			else if (p->prior->date.flag!=FREE&&p->next->date.flag==FREE)
			{
				p->date.size+=p->next->date.size;   //合并前后两个分区
				if(p->next->next)      //下一个分区不是最后一个分区
				{
					p->next->next->prior=p;
				    p->next = p->next->next;
				}
				else 
					p->next=p->next->next;
			}
			//3、回收部分r与上下空闲区相邻,此时将这三个区域合并,始址为r上相邻区域的地址,大小为三个分区大小之和
			else if(p->prior->date.flag==FREE&&p->next->date.flag==FREE)
			{
				p->prior->date.size+=p->date.size+p->next->date.size;
				if(p->next->next) //如果最后一个节点不是最后一个节点
				{
				p->next->next->prior=p->prior;
				p->prior->next=p->next->next;
				}
				else p->prior->next=p->next->next;
			}
			//4、当回收部分r上下区域都为非空闲区域,此时建立一个新的空闲分区,并且加入到空闲区队列中去
			else if(p->prior->date.flag!=FREE && p->next->date.flag!=FREE)
			{
				//只用把结点的number和flag改成free就行了
			}
			break;
		}
		p=p->next;
	}
	cout<<"回收成功!"<<endl;
	return 1;
}

void show()
{
	cout<< endl;
	cout<<"作业分配情况"<<endl;
	int i = 1;
	Free_Node *p=headNode->next;
	cout<<"分区号"  << "  作业号" << "\t起始地址"  << "    作业大小"  << "   分区状态" << endl;
	while(p)
	{
		cout << i++ << "\t " << p->date.number << '\t' << p->date.begin_address << "\t\t" << p->date.size << '\t';
		if (p->date.flag==FREE)
			cout<<"空闲"<<endl;
		else
			 cout<<"已分配"<<endl;
		p=p->next;
	}
}

2、最佳适应算法

概念:最佳适应算法是指从全部空闲区中找出能满足作业要求大小最小的空闲分区的一种计算方法,这种方法能使碎片尽量小。

#include <iostream>
#include <stdlib.h>
using namespace std;
 
#define FREE 0
#define  BUSY 1
#define  MAX_length 300
 
typedef struct freeArea
{
	int flag;
	int size;
	int ID;
	int address;
}Elemtype;
 
typedef struct Free_Node
{
	Elemtype date;
	struct Free_Node *front;
	struct Free_Node *next;
}Free_Node,*FNodeList;
 
FNodeList block_first;
FNodeList block_last;
int alloc(int tag);//内存分配
int free(int ID);//内存回收
int best_fit(int ID,int size);//最佳适应算法
void show();//查看分配
void init();//初始化
void menu();

//初始化 
void init()
{
	block_first=new Free_Node;
	block_last = new Free_Node;
	block_first->front=NULL;
	block_first->next=block_last;
	block_last->front=block_first;
	block_last->next=NULL;
	block_last->date.address=0;
	block_last->date.flag=FREE;
	block_last->date.ID=FREE;
	block_last->date.size=MAX_length;
}
 
//实现内存分配
int alloc(int tag)
{
	int ID,size1;
	cout<<"请输入作业号:";
	cin>>ID;
	cout<<"请输入所需内存大小:";
	cin>>size1;
	if (ID<=0 || size1<=0)
	{
		cout<<"ERROR,请输入正确的ID和请求大小"<<endl;
		return 0;
	}
	
	if (tag==1)//采用最佳适应算法
	{
		if (best_fit(ID,size1))
		{
			cout<<"分配成功!"<<endl;
		}
		else cout<<"分配失败!"<<endl;
		return 1;
	}
	
}
 
int best_fit(int ID,int size)//最佳适应算法
{
	int surplus;//记录可用内存与需求内存的差值
	FNodeList temp=(FNodeList)malloc(sizeof(Free_Node));
	Free_Node *p=block_first->next;
	temp->date.ID=ID;
	temp->date.size=size;
	temp->date.flag=BUSY;
	Free_Node *q=NULL;//记录最佳位置
	while(p)//遍历链表,找到第一个可用的空闲区间将他给q
	{
		if (p->date.flag==FREE&&p->date.size>=size)
		{
			q=p;
			surplus=p->date.size-size;
			break;
		}
		p=p->next;
	}
	while(p)//继续遍历,找到更加合适的位置
	{
		if (p->date.flag==FREE&&p->date.size==size)
		{
			p->date.flag=BUSY;
			p->date.ID=ID;
			return 1;
			break;
		}
		if (p->date.flag==FREE&&p->date.size>size)
		{
			if (surplus>p->date.size-size)
			{
				surplus=p->date.size-size;
				q=p;
			}
 
		}
		p=p->next;
	}
	if (q==NULL)//如果没有找到位置
	{
		return 0;
	}
	else//找到了最佳位置
	{
		temp->next=q;
		temp->front=q->front;
		temp->date.address=q->date.address;
		q->front->next=temp;
		q->front=temp;
		q->date.size=surplus;
		q->date.address+=size;
		return 1;
	}
}
 
int free(int ID)//主存回收
{
	Free_Node *p=block_first->next;
	while(p)
	{
		if (p->date.ID==ID)//找到要回收的ID区域
		{
			p->date.flag=FREE;
			p->date.ID=FREE;
			//判断P与前后区域关系
			if (p->front->date.flag==FREE&&p->next->date.flag!=FREE)
			{
				p->front->date.size+=p->date.size;
				p->front->next=p->next;
				p->next->front=p->front;
			}
			if (p->front->date.flag!=FREE&&p->next->date.flag==FREE)
			{
				p->date.size+=p->next->date.size;
				if(p->next->next)
				{
					p->next->next->front=p;
				p->next = p->next->next;
				}
				else p->next=p->next->next;
			}
			if(p->front->date.flag==FREE&&p->next->date.flag==FREE)
			{
				p->front->date.size+=p->date.size+p->next->date.size;
				if(p->next->next)
				{
				p->next->next->front=p->front;
				p->front->next=p->next->next;
				}
				else p->front->next=p->next->next;
			}
			if(p->front->date.flag!=FREE&&p->next->date.flag!=FREE)
			{//
				
			}
			break;
		}
		p=p->next;
	}
	cout<<"回收成功!"<<endl;
	return 1;
}



void show()
{
	cout<< endl;
	cout<<"作业分配情况"<<endl;
	int i = 1;
	Free_Node *p=block_first->next;
	cout<<"分区号"  << "  作业号" << "\t起始地址"  << "    作业大小"  << "   分区状态" << endl;
	
	while(p)
	{
		cout << i++ << "\t " << p->date.ID << '\t' << p->date.address << "\t\t" << p->date.size << '\t';
		if (p->date.flag==FREE)
			cout<<"空闲"<<endl;
		else
			cout<<"已分配"<<endl;
		p=p->next;
	}
	
}

void menu()//菜单
{
	int tag=0;
	int ID;
	init();
	cout<<"分区模拟:"<<endl;
	while(tag!=4)
	{
		cout<<"请输入要进行的操作:"<<endl;
		cout<<"1-申请作业,2-作业回收,3-显示作业状况,4-退出"<<endl;
			cin>>tag;
		switch(tag)
			{
			case 1:
				alloc(tag);
				break;
			case 2:
				cout<<"请输入需要回收的ID号:"<<endl;
				cin>>ID;
				free(ID);
				break;
			case 3:
				show();
				break;
		    }
	}
 
}
int main()
{
	menu();
}

3、最坏适应算法

概念:空闲分区链必须按照容量递减的次序进行排序;若不满足容量递减的次序,则重新进行排序。每次选符合条件的最大的空闲区进行分配。

#include <iostream>
#include <stdlib.h>
using namespace std;
 
#define FREE 0
#define  BUSY 1
#define  MAX_length 300
 
typedef struct freeArea
{
	int flag;
	int size;
	int ID;
	int address;
}Elemtype;
 
typedef struct Free_Node
{
	Elemtype date;
	struct Free_Node *front;
	struct Free_Node *next;
}Free_Node,*FNodeList;
 
FNodeList block_first;
FNodeList block_last;
int alloc(int tag);//内存分配
int free(int ID);//内存回收
int worst_fit(int ID,int size);//最坏适应算法 
void show();//查看分配
void init();//初始化
void menu();

//初始化 
void init()
{
	block_first=new Free_Node;
	block_last = new Free_Node;
	block_first->front=NULL;
	block_first->next=block_last;
	block_last->front=block_first;
	block_last->next=NULL;
	block_last->date.address=0;
	block_last->date.flag=FREE;
	block_last->date.ID=FREE;
	block_last->date.size=MAX_length;
}
 
//实现内存分配
int alloc(int tag)
{
	int ID,size1;
	cout<<"请输入作业号:";
	cin>>ID;
	cout<<"请输入所需内存大小:";
	cin>>size1;
	if (ID<=0 || size1<=0)
	{
		cout<<"ERROR,请输入正确的ID和请求大小"<<endl;
		return 0;
	}
	
	if (tag==1)//采用最坏适应算法
	{
		if (worst_fit(ID,size1))
		{
			cout<<"分配成功!"<<endl;
		}
		else cout<<"分配失败!"<<endl;
		return 1;
	}
	
}

//最坏适应算法
int worst_fit(int ID, int size) {
    int max_surplus = -1;  // 记录最大的差值
    Free_Node *worst_fit_node = NULL;  // 记录最坏适应位置
    Free_Node *p = block_first->next;

    // 寻找第一个可用空闲区间,并将其作为最坏适应位置
    while (p) {
        if (p->date.flag == FREE && p->date.size >= size) {
            worst_fit_node = p;
            max_surplus = p->date.size - size;
            break;
        }
        p = p->next;
    }

    // 继续遍历链表,寻找更坏适应的位置
    while (p) {
        if (p->date.flag == FREE) {
            int surplus = p->date.size - size;
            if (surplus > max_surplus) {  // 更新最坏适应位置
                worst_fit_node = p;
                max_surplus = surplus;
            }
        }
        p = p->next;
    }

    if (worst_fit_node == NULL) {
        return 0;  // 如果没有找到合适的位置
    } else {
        // 分配内存并更新链表
        FNodeList temp = (FNodeList) malloc(sizeof(Free_Node));
        temp->date.ID = ID;
        temp->date.size = size;
        temp->date.flag = BUSY;

        temp->next = worst_fit_node;
        temp->front = worst_fit_node->front;
        temp->date.address = worst_fit_node->date.address;

        worst_fit_node->front->next = temp;
        worst_fit_node->front = temp;

        worst_fit_node->date.size = max_surplus;
        worst_fit_node->date.address += size;

        return 1;
    }
}

int free(int ID)//主存回收
{
	Free_Node *p=block_first->next;
	while(p)
	{
		if (p->date.ID==ID)//找到要回收的ID区域
		{
			p->date.flag=FREE;
			p->date.ID=FREE;
			//判断P与前后区域关系
			if (p->front->date.flag==FREE&&p->next->date.flag!=FREE)
			{
				p->front->date.size+=p->date.size;
				p->front->next=p->next;
				p->next->front=p->front;
			}
			if (p->front->date.flag!=FREE&&p->next->date.flag==FREE)
			{
				p->date.size+=p->next->date.size;
				if(p->next->next)
				{
					p->next->next->front=p;
				p->next = p->next->next;
				}
				else p->next=p->next->next;
			}
			if(p->front->date.flag==FREE&&p->next->date.flag==FREE)
			{
				p->front->date.size+=p->date.size+p->next->date.size;
				if(p->next->next)
				{
				p->next->next->front=p->front;
				p->front->next=p->next->next;
				}
				else p->front->next=p->next->next;
			}
			if(p->front->date.flag!=FREE&&p->next->date.flag!=FREE)
			{//
				
			}
			break;
		}
		p=p->next;
	}
	cout<<"回收成功!"<<endl;
	return 1;
}


void show()
{
	cout<< endl;
	cout<<"作业分配情况"<<endl;
	int i = 1;
	Free_Node *p=block_first->next;
	cout<<"分区号"  << "  作业号" << "\t起始地址"  << "    作业大小"  << "   分区状态" << endl;
	
	while(p)
	{
		cout << i++ << "\t " << p->date.ID << '\t' << p->date.address << "\t\t" << p->date.size << '\t';
		if (p->date.flag==FREE)
			cout<<"空闲"<<endl;
		else
			cout<<"已分配"<<endl;
		p=p->next;
	}
	
}

void menu()//菜单
{
	int tag=0;
	int ID;
	init();
	cout<<"分区模拟:"<<endl;
	while(tag!=4)
	{
		cout<<"请输入要进行的操作:"<<endl;
		cout<<"1-申请作业,2-作业回收,3-显示作业状况,4-退出"<<endl;
			cin>>tag;
		switch(tag)
			{
			case 1:
				alloc(tag);
				break;
			case 2:
				cout<<"请输入需要回收的ID号:"<<endl;
				cin>>ID;
				free(ID);
				break;
			case 3:
				show();
				break;
		    }
	}
 
}

int main()
{
	menu();
}