跟踪每一步流程,C++实现银行家算法

老生常谈的算法,思想很简单,但是实现起来,想跟踪每一步的结果,有点繁琐,详细介绍一下算法的实现过程,也防止自己以后遗忘。编程环境为windows,VC6.0,最古老也是最经典的环境吧。

首先说明几个矩阵,如下所示

#define P 5   //5个任务
#define R 3   //3种资源
int Max[P][R];          //最大需求资源
int Allocation[P][R];    //已分配资源
int Available[R];       //当前可用资源
int Need[P][R];       //任务还需要的资源

其中Max和Allocation是从文件读取,Need是Max-Allocation计算结果,Available是手动输入,初始状态,Max和Allocation的值分别如下:

//max.txt
7 5 3
3 2 2
9 0 2
2 2 2
4 3 3
//allocation.txt
0 1 0
2 0 0
3 0 2
2 1 1
0 0 2

文件读取函数input如下

//从文本中读取数据函数,需要头文件#include <fstream>
void input(FILE* fp, int ptr[P][R])
{
	int i,j;
	for(i=0; i<P; i++)
	{
		for(j=0; j<R; j++)
		{
			fscanf(fp, "%d", &ptr[i][j]);
		}
		fscanf(fp, "\n"); 
	}
	fclose(fp);
}

计算Need矩阵函数

//计算Need矩阵并输出
void computeNeed(int need[P][R], int ptr1[P][R], int ptr2[P][R])
{
	int i,j;
	for(i=0; i<P; i++)
	{
		for(j=0; j<R; j++)
		{
			 need[i][j] = ptr1[i][j] - ptr2[i][j];
		} 
	}
	cout<<"当前"<<P<<"个任务还需要的资源为:"<<endl;
	for(i=0; i<P; i++)
	{
		cout<<"P("<<i<<"):"<<" ";
		for(j=0; j<R; j++)
		{
			 cout<<need[i][j]<<" ";
		} 
		cout<<endl;
	}
}

主函数中对于的调用方式为:

#define maxDataPath  "E:\\VC6.0_test_program\\BankerAlgorithm\\max.txt"     
#define allocationDataPath  "E:\\VC6.0_test_program\\BankerAlgorithm\\allocation.txt"
FILE *fpMax = fopen(maxDataPath, "r");
FILE *fpAllocation = fopen(allocationDataPath, "r");
input(fpMax, Max);
cout<<"当前"<<P<<"个任务需要的最大资源为:"<<endl;
output(fpMax, Max);
input(fpAllocation, Allocation);
cout<<"当前"<<P<<"个任务已分配的资源为:"<<endl;
output(fpAllocation, Allocation);
computeNeed(Need, Max, Allocation);   //计算Need矩阵并输出

安全性检查函数,其中secure[P][R]矩阵用来保存Available和Need的差值,若secure[i][j] < 0,则当前第j类可用资源小于第i个任务第j类需求资源,计数器+1,一次循环下来,当计数器的值仍然为0时(每个循环开始时计数器会清零),才表示第i个任务满足资源分配要求,返回其下标,否则,返回-1。如下所示

//安全性检查,比较Need和Available,如果有任务处于安全状态,则返回其下标,否则返回-1
int securityCheck(int Allocation[P][R], int Need[P][R], int Available[R])
{
	int i,j;
	int secure[P][R];
	int count[P]; 
	for(i=0; i<P; i++)
	{ 
		int c = 0;   //计数器清零
		cout<<"secure["<<i<<"][]的值为:";
		for(j=0; j<R; j++)
		{
	    	secure[i][j] = Available[j] - Need[i][j];
			cout<<secure[i][j]<<" ";
			if(secure[i][j] < 0)
				++c;
		}
		count[i] = c;  //count[i]!=0表示第i个任务不满足资源分配要求
		cout<<"count["<<i<<"]的值是:"<<count[i]<<endl;
	}
	for(i=0; i<P; i++)
	{
		if(count[i] == 0)
		{
			return i;
		}
	}
	return -1;
}
修改矩阵函数set,当存在安全序列时,每执行完一个任务,修改当前可用资源矩阵Available的值,并且将该任务的Need设置为1000(更大的数也可以,只要让它足够大,大到大于Available就可以),表示执行完该任务。
//当存在安全序列时,每执行完一个任务,修改当前可用资源矩阵Available的值,并且将该任务的Need设置为1000
void set(int sequence, int Need[P][R], int Allocation[P][R], int Available[R])
{
	int j;
	cout<<"此时Available为:";
	for(j=0; j<R; j++)
	{
		Available[j] = Available[j] + Allocation[sequence][j];
		Need[sequence][j] = 1000;
		cout<<Available[j]<<" ";
	}
	cout<<endl;
	cout<<endl;
}

主函数对应的调用如下:

int sequence;//sequence是安全序列的任务下标  
for(i=0; i<P; i++)
{
	sequence = securityCheck(Allocation, Need, Available);
	cout<<"sequence的值为"<<sequence<<endl;
	if(sequence != -1)
	{
	   	cout<<"执行任务P("<<sequence<<")"<<endl;
	   	set(sequence, Need, Allocation, Available);
	}
	else
	{
		cout<<"错误,资源不够执行任务!"<<endl;
		break;
	}
}

考虑到当前状态会有任务请求资源,故设置了一个请求检查函数,检测任务请求的资源是否合理合法,其中requestSeq是手动输入的请求任务下标,Request[R]也是手动输入的请求资源,如果请求资源既不大于当前该任务的需求资源,也不大于当前可用资源,则说明对该类资源的请求合法,index+1,所以当index==3为真时,表示该任务请求的资源合法,返回请求任务的下标,否则当循环结束时返回-1

//请求检查,检测任务请求的资源是否合理合法
int requestCheck(int requestSeq, int Request[R], int Need[P][R], int Available[R])
{
	int i=0;
	int index = 0;
	while(i<R)
	{
		if(Request[i] <= Need[requestSeq][i])    //判断请求资源是否不大于当前该任务的需求资源
		{
			if(Request[i] <= Available[i])  //判断请求资源是否不大于当前可用资源
			{
				++index;   //index=3表示请求资源合理
				++i;
			}
			else{
				cout<<"请求的第"<<i<<"种资源可用资源不足!"<<endl;
				++i;
				//ntinue;
			}
		}else{
			cout<<"请求的第"<<i<<"种资源超过任务P("<<requestSeq<<")的需求,请重新输入!"<<endl;
			++i;
		}	
	}
	cout<<"index的值为:"<<index<<endl;
	if(index == 3)
	{
		return requestSeq;   //请求资源合法,返回请求任务的下标
	}
	return -1;
}

在请求完资源且检查过请求合法,那么重新分配当前资源,修改Allocation、Need、Available矩阵

//请求资源后,重新分配当前资源,修改Allocation、Need、Available矩阵
void afterReq(int requestSeq, int Request[R], int Allocation[P][R], int Need[P][R], int Available[R])
{
	int i;
	for(i=0; i<R; i++)
	{
		Allocation[requestSeq][i] = Allocation[requestSeq][i] + Request[i];
		Need[requestSeq][i] = Need[requestSeq][i] - Request[i];
		Available[i] = Available[i] - Request[i];
	}
}


完整代码如下:

#include <iostream.h>
#include <stdio.h>
#include <fstream>
#define maxDataPath  "E:\\VC6.0_test_program\\BankerAlgorithm\\max.txt"   //文件路径
#define allocationDataPath  "E:\\VC6.0_test_program\\BankerAlgorithm\\allocation.txt"
//#define availableDataPath  "E:\\C++\\BankerAlgorithm\\available.txt"
#define P 5   //5个任务
#define R 3   //3种资源
//从文本中读取数据函数
void input(FILE* fp, int ptr[P][R])
{
	int i,j;
	for(i=0; i<P; i++)
	{
		for(j=0; j<R; j++)
		{
			fscanf(fp, "%d", &ptr[i][j]);
		}
		fscanf(fp, "\n"); 
	}
	fclose(fp);
}

//输出数据函数
void output(FILE* fp, int ptr[P][R])
{
	int i,j;
	for(i=0; i<P; i++)
	{
		cout<<"P("<<i<<"):"<<" ";
		for(j=0; j<R; j++)
		{
			cout<<ptr[i][j]<<" ";
		}
		cout<<endl; 
	}
}

//计算Need矩阵并输出
void computeNeed(int need[P][R], int ptr1[P][R], int ptr2[P][R])
{
	int i,j;
	for(i=0; i<P; i++)
	{
		for(j=0; j<R; j++)
		{
			 need[i][j] = ptr1[i][j] - ptr2[i][j];
		} 
	}
	cout<<"当前"<<P<<"个任务还需要的资源为:"<<endl;
	for(i=0; i<P; i++)
	{
		cout<<"P("<<i<<"):"<<" ";
		for(j=0; j<R; j++)
		{
			 cout<<need[i][j]<<" ";
		} 
		cout<<endl;
	}
}

//安全性检查,比较Need和Available,如果有任务处于安全状态,则返回其下标,否则返回-1
int securityCheck(int Allocation[P][R], int Need[P][R], int Available[R])
{
	int i,j;
	int secure[P][R];
	int count[P]; 
	for(i=0; i<P; i++)
	{ 
		int c = 0;   //计数器清零
		cout<<"secure["<<i<<"][]的值为:";
		for(j=0; j<R; j++)
		{
	    	secure[i][j] = Available[j] - Need[i][j];
			cout<<secure[i][j]<<" ";
			if(secure[i][j] < 0)
				++c;
		}
		count[i] = c;  //count[i]!=0表示第i个任务不满足资源分配要求
		cout<<"count["<<i<<"]的值是:"<<count[i]<<endl;
	}
	for(i=0; i<P; i++)
	{
		if(count[i] == 0)
		{
			return i;
		}
	}
	return -1;
}

//当存在安全序列时,每执行完一个任务,修改当前可用资源矩阵Available的值,并且将该任务的Need设置为1000
void set(int sequence, int Need[P][R], int Allocation[P][R], int Available[R])
{
	int j;
	cout<<"此时Available为:";
	for(j=0; j<R; j++)
	{
		Available[j] = Available[j] + Allocation[sequence][j];
		Need[sequence][j] = 1000;
		cout<<Available[j]<<" ";
	}
	cout<<endl;
	cout<<endl;
}

//请求检查,检测任务请求的资源是否合理合法
int requestCheck(int requestSeq, int Request[R], int Need[P][R], int Available[R])
{
	int i=0;
	int index = 0;
	while(i<R)
	{
		if(Request[i] <= Need[requestSeq][i])    //判断请求资源是否不大于当前该任务的需求资源
		{
			if(Request[i] <= Available[i])  //判断请求资源是否不大于当前可用资源
			{
				++index;   //index=3表示请求资源合理
				++i;
			}
			else{
				cout<<"请求的第"<<i<<"种资源可用资源不足!"<<endl;
				++i;
				//ntinue;
			}
		}else{
			cout<<"请求的第"<<i<<"种资源超过任务P("<<requestSeq<<")的需求,请重新输入!"<<endl;
			++i;
		}	
	}
	cout<<"index的值为:"<<index<<endl;
	if(index == 3)
	{
		return requestSeq;   //请求资源合法,返回请求任务的下标
	}
	return -1;
}
		
//请求资源后,重新分配当前资源,修改Allocation、Need、Available矩阵
void afterReq(int requestSeq, int Request[R], int Allocation[P][R], int Need[P][R], int Available[R])
{
	int i;
	for(i=0; i<R; i++)
	{
		Allocation[requestSeq][i] = Allocation[requestSeq][i] + Request[i];
		Need[requestSeq][i] = Need[requestSeq][i] - Request[i];
		Available[i] = Available[i] - Request[i];
	}
}

void main(){
	int Max[P][R];          //最大需求资源
	int Allocation[P][R];    //已分配资源
	int Available[R];         //当前可用资源
	int Need[P][R];          //任务还需要的资源
	int Request[R];
	int i;
	int sequence,requestSeq;  //sequence是安全序列的任务下标,requestSeq是请求资源的任务下标
	char isRequest;
	bool isLegal = false;
	FILE *fpMax = fopen(maxDataPath, "r");
	FILE *fpAllocation = fopen(allocationDataPath, "r");
	input(fpMax, Max);
	cout<<"当前"<<P<<"个任务需要的最大资源为:"<<endl;
	output(fpMax, Max);
	input(fpAllocation, Allocation);
	cout<<"当前"<<P<<"个任务已分配的资源为:"<<endl;
	output(fpAllocation, Allocation);
    computeNeed(Need, Max, Allocation);   //计算Need矩阵并输出
	cout<<"输入当前可分配资源"<<endl;
	for(i=0; i<R; i++)
	{
		cin>>Available[i];
	}
	cout<<"是否有任务发出资源请求?输入y(yes)或者n(no):";
	cin>>isRequest;
	while(isRequest == 'y')
	{

		cout<<"第几个任务发出的资源请求?输入0到"<<P-1<<":";
		cin>>requestSeq;
		if(requestSeq < 0 || requestSeq >= P)
		{
			cout<<"错误!输入正确的任务编号!"<<endl;
		}
		while(requestSeq >= 0 && requestSeq < P)
		{
	    	cout<<"P("<<requestSeq<<")请求的资源为:";
	    	for(i=0; i<R; i++)
			{
				cin>>Request[i];
			}
			requestSeq = requestCheck(requestSeq, Request, Need, Available);
			if(requestSeq != -1)
			{
				cout<<"请求资源合法"<<endl;
				isLegal = true;
				afterReq(requestSeq, Request, Allocation, Need, Available);
				break;
			}
		}
		if(isLegal) break;
	}
	cout<<"准备计算sequence"<<endl;
	for(i=0; i<P; i++)
	{
		sequence = securityCheck(Allocation, Need, Available);
		cout<<"sequence的值为"<<sequence<<endl;
		if(sequence != -1)
		{
	    	cout<<"执行任务P("<<sequence<<")"<<endl;
	    	set(sequence, Need, Allocation, Available);
		}
		else
		{
			cout<<"错误,资源不够执行任务!"<<endl;
			break;
		}
	}
}



测试结果:

输入Available之前


如果没有任务发出请求,当前存在安全序列P1、P3、P0、P2、P4,并且在每执行完一次任务的时候,实时打印出当前可用资源Available矩阵:


当有任务发出请求时,先输入是哪个任务发出的请求,输入值要经过一次判断在任务下标范围之内,如果请求资源超过其所需的Max资源,则需要重新输入,如下所示


如果请求资源没有超过其所需的Max资源,但大于当前可用资源,仍会指出哪种请求不合法以及不合法原因


如果请求合理合法,但系统分配资源的话,导致安全性检查失败,不存在安全序列,会弹出错误提示:


最后,如果请求合理合法,且存在安全序列,则给出安全序列:


虽然有点繁琐,但并不复杂,跟踪每一步结果,更容易理解算法的思想


















猜你喜欢

转载自blog.csdn.net/hust_cxl/article/details/80528345