银行家算法——输出所有安全序列
银行家算法的具体思路可见我的另一篇文章 点击了解
思路:递归从N个进程里选一个满足条件的进程作为一个安全序列的第一个元素,之后再各自从剩下的进程中选择满足条件的作为第二个元素……
问题:由于确定每一个安全序列、以及确定安全序列的每一个元素的过程中Finish[i]和Work[j]都在变化,所以需要一个撤回操作的步骤(回溯)
和深度优先搜索类似
代码如下
#include<string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define max 10
int PN; //进程数
int RT; //资源数
int Resourse[max];//资源种类
int Available[max];//系统剩余资源
int Work[max]; //工作向量
int Allocation[max][max];//进程已分配资源
int Need[max][max];//进程目前资源需求
int MAX[max][max];//进程最大资源需求
int Request[max];//申请
bool Finish[max];//完成标志
int sum;//安全序列计数
int choice;//选择申请资源
typedef struct
{
int SafeOrder[max];
int top;
}stack;
void push(stack *s, int x)
{
s->SafeOrder[s->top] = x;
s->top++;
}
void pop(stack *s)
{
s->top--;
}
stack Order;
void printOrder()
{
int i;
sum++;
if (sum == 1) printf("当前系统安全!\n");
printf("第%d个安全序列: ", sum);
for (i = 0; i < PN; i++)
{
if (i == 0)
printf("P%d", Order.SafeOrder[i]);
else
printf("->P%d", Order.SafeOrder[i]);
}
printf("\n");
}
void IsSafe(int k)
{
int i, j;
if (k == PN) //找到了一种安全性序列,打印输出
{
printOrder();
return;
}
for (i = 0; i<PN; i++)
{
if (!Finish[i])
{
bool flag = true;
for (j = 0; j<RT; j++)
if (Need[i][j] > Work[j])
flag = false;
if (flag)//暂时放入安全性队列
{
for (j = 0; j < RT; j++)
Work[j] += Allocation[i][j];
Finish[i] = true;
push(&Order, i + 1);//满足要求的进程放进安全序列
IsSafe(k + 1); //搜索下一个
pop(&Order); //回溯,将第i个进程所做的改变恢复,也就是弹出刚刚放进去的进程
for (j = 0; j<RT; j++)
Work[j] -= Allocation[i][j];
Finish[i] = false;
}
}
}
}
void Input(int a, int b, int c[max][max])
{
int i, j;
for (i = 0; i < b; i++)
if (i == 0) printf(" R%d ", i + 1);
else printf("R%d ", i + 1);
printf("\n");
for (i = 0; i < a; i++)
{
printf("P%d ", i + 1);
for (j = 0; j < b; j++)
scanf("%d", &c[i][j]);
}
}
void init()
{
int i, j;
sum = 0;
Order.top = 0;
printf("初始化: 请输入进程个数和资源总类: ");
scanf("%d%d", &PN, &RT);
printf("请输入各类资源数量: \n");
for (i = 0; i < RT; i++)
printf("R%d ", i + 1);
printf("\n");
for (i = 0; i < RT; i++)
scanf("%d", &Resourse[i]);
printf("请输入每个进程对每种资源的最大需求量:\n");
Input(PN, RT, MAX);
printf("请输入各类资源已分配量:\n");
Input(PN, RT, Allocation);
for (i = 0; i < PN; i++)
for (j = 0; j < RT; j++)
Need[i][j] = MAX[i][j] - Allocation[i][j];
for (i = 0; i < RT; i++)
{
int s[max] = { 0 };
for (j = 0; j < PN; j++)
s[i] += Allocation[j][i];
Available[i] = Resourse[i] - s[i];
Work[i] = Available[i];
}
for (j = 0; j < PN; j++)
Finish[i] = false;
}
bool Apply()//进程资源申请
{
int i;
printf("选择申请资源的进程: P");
scanf("%d", &choice);
printf("输入各类资源申请数量\n");
for (i = 0; i < RT; i++)
printf("R%d ", i + 1);
printf("\n");
for (i = 0; i < RT; i++)
scanf("%d", &Request[i]);
for (i = 0; i < RT; i++)
if (Request[i] <= Need[choice - 1][i])
{
if (Request[i] > Available[i])
{
printf("资源不足!"); return false;
}
}
else//申请超出所需
{
printf("申请超出所需!"); return false;
}
return true;
}
bool banker()
{
sum = 0;
Order.top = 0;
int i = choice - 1, j;
for (j = 0; j < RT; j++)//试分配
{
Available[j] -= Request[j];
Allocation[i][j] += Request[j];
Need[i][j] -= Request[j];
Work[j] = Available[j];
}
for (j = 0; j < PN; j++)
Finish[j] = false;
IsSafe(0);
if (sum == 0)
{
for (j = 0; j < RT; j++)
{
Available[j] += Request[j];
Allocation[i][j] -= Request[j];
Need[i][j] += Request[j];
Work[j] = Available[j];
}
return false;
}
return true;
}
void print()
{
int i, j;
printf("\n资源已分配|资源尚需: \n");
for (i = 0; i < RT; i++)
if (i == 0) printf(" R%d ", i + 1);
else printf("R%d ", i + 1);
printf("\n");
for (i = 0; i < PN; i++)
{
printf(" P%d :", i + 1);
for (j = 0; j < RT; j++)
printf("%2d|%-2d ", Allocation[i][j], Need[i][j]);
printf("\n");
}
printf("系统剩余:");
for (i = 0; i < RT; i++)
printf(" %-4d", Available[i]);
printf("\n");
}
void Menu()
{
printf("------------------Banker-----------------------\n");
printf("* 1.初始化数据 *\n");
printf("* 2.检验T0时刻安全性 *\n");
printf("* 3.资源申请 *\n");
printf("* 4.退出 *\n");
printf("------------------------------------------------\n");
}
void main()
{
bool flag1, flag2;
Menu();
Initialization:init();
IsSafe(0);
if (sum == 0)
{
printf("当前系统处于不安全状态,请重新初始化!\n");
goto Initialization;
}
else print();
Application: flag1 = Apply();
if (flag1)
{
flag2 = banker();
if (!flag2)
{
printf("资源申请造成系统处不安全状态!申请失败!请重新申请\n");
goto Application;
}
else
{
printf("申请成功!");
print();
}
}
else
{
printf("申请失败!请重新申请\n");
goto Application;
}
int n;
printf("是否还有进程申请资源? 是请输入1,否请输入0 :");
scanf("%d", &n);
if (n == 1)
goto Application;
}