银行家算法典型案例-C语言实现

文 | Promise Sun


银行家算法典型案例:

1.题目要求:

(1)模拟一个银行家算法: 设置数据结构 设计安全性算法
(2) 初始化时让系统拥有一定的资源
(3) 用键盘输入的方式申请资源
(4)如果预分配后,系统处于安全状态,则修改系统的资源分配情况
(5)如果预分配后,系统处于不安全状态,则提示不能满足请求

假定系统中有五个进程{P0、P1、P2、P3、P4}和三种类型资源{A、B、C},每一种资源的数量分别为10、5、7。各进程的最大需求、T时刻资源分配情况如下所示:

银行家算法1.png

2.开发环境

1)开发工具:Visual Studio Community 2022
2)开发系统:Windows 11

3.运行结果:

(注:参数可自行设置,示例仅供参考)

银行家算法示例1.png

银行家算法示例2.png
银行家算法示例3.png
银行家算法示例4.png

4.完整代码:

#include<stdio.h>
#include<stdlib.h>

#define False 0
#define True 1

/********主要数据结构********/
char NAME[100] = { 0 };//资源的名称
int Max[100][100] = { 0 };//最大需求矩阵
int Allocation[100][100] = { 0 };//系统已分配矩阵
int Need[100][100] = { 0 };//还需要资源矩阵
int Available[100] = { 0 };//可用资源矩阵
int Request[100] = { 0 };//请求资源向量
int Work[100] = { 0 };//存放系统可提供资源量
int Finish[100] = { 0 }; //标记系统是否有足够的资源分配给各个进程
int Security[100] = { 0 };//存放安全序列

int M = 100;//进程的最大数
int N = 100;//资源的最大数

/********初始化数据:输入进程数量、资源种类、各种资源可利用数量、
各进程对资源最大需求量、各进程的资源已分配数量等。********/
void init()
{
    /* m为进程个数,即矩阵行数,n为资源种类,即矩阵列数。*/
    int i, j, m, n;
    int number, flag;
    char name;//输入资源名称
    int temp[100] = { 0 };//统计已经分配的资源
    //输入系统资源数目及各资源初试个数
    printf("系统可用资源种类为:");
    scanf_s("%d", &n);
    N = n;
    for (i = 0; i < n; i++)
    {
        printf("资源%d的名称:",i);
        //fflush(stdin);  //清空输入流缓冲区的字符,注意必须引入#include<stdlib.h>头文件
        scanf_s("%s", &name,2);
        printf("  资源 %c 的初始个数为:", name);
        NAME[i] = name;

        scanf_s("%d", &number);
        Available[i] = number;
    }

    //输入进程数及各进程的最大需求矩阵
    printf("\n请输入进程的数量:");
    scanf_s("%d", &m);
    M = m;
    printf("请输入各进程的最大需求矩阵的值[Max]:\n");
    do {
        flag = False;
        for (i = 0; i < M; i++)
            for (j = 0; j < N; j++)
            {
                scanf_s("%d", &Max[i][j]);
                if (Max[i][j] > Available[j])
                    flag = True;
            }
        if (flag)
            printf("资源最大需求量大于系统中资源最大量,请重新输入!\n");
    } while (flag);


    //输入各进程已经分配的资源量,并求得还需要的资源量
    do {
        flag = False;
        printf("请输入各进程已经分配的资源量[Allocation]:\n");
        for (i = 0; i < M; i++)
        {
            for (j = 0; j < N; j++)
            {
                scanf_s("%d", &Allocation[i][j]);
                if (Allocation[i][j] > Max[i][j])
                    flag = True;
                Need[i][j] = Max[i][j] - Allocation[i][j];
                temp[j] += Allocation[i][j];//统计已经分配给进程的资源数目
            }
        }
        if (flag)
            printf("分配的资源大于最大量,请重新输入!\n");
    } while (flag);

    //求得系统中可利用的资源量
    for (j = 0; j < N; j++)
        Available[j] = Available[j] - temp[j];
}

/********显示资源分配矩阵********/
void showdata()
{
    int i, j;
    printf("*************************************************************\n");
    printf("系统目前可用的资源[Available]:\n");
    for (i = 0; i < N; i++)
        printf("%c  ", NAME[i]);
    printf("\n");
    for (j = 0; j < N; j++)
        printf("%d  ", Available[j]);
    printf("\n");
    printf("系统当前的资源分配情况如下:\n");
    printf("            Max      Allocation    Need\n");
    printf("进程名     ");
    //输出与进程名同行的资源名,Max、Allocation、Need下分别对应
    for (j = 0; j < 3; j++) {
        for (i = 0; i < N; i++)
            printf("%c  ", NAME[i]);
        printf("     ");
    }
    printf("\n");
    //输出每个进程的Max、Allocation、Need
    for (i = 0; i < M; i++) {
        printf(" P%d        ", i);
        for (j = 0; j < N; j++)
            printf("%d  ", Max[i][j]);
        printf("     ");
        for (j = 0; j < N; j++)
            printf("%d  ", Allocation[i][j]);
        printf("     ");
        for (j = 0; j < N; j++)
            printf("%d  ", Need[i][j]);
        printf("\n");
    }
}

/********尝试分配资源********/
int test(int i) //试探性的将资源分配给第i个进程
{
    for (int j = 0; j < N; j++)
    {
        Available[j] = Available[j] - Request[j];
        Allocation[i][j] = Allocation[i][j] + Request[j];
        Need[i][j] = Need[i][j] - Request[j];
    }
    return True;
}

/********试探性分配资源作废********/
int Retest(int i) //与test操作相反
{
    for (int j = 0; j < N; j++)
    {
        Available[j] = Available[j] + Request[j];
        Allocation[i][j] = Allocation[i][j] - Request[j];
        Need[i][j] = Need[i][j] + Request[j];
    }
    return True;
}

/********安全性算法********/
int safe()
{
    int i, j, k = 0, m, apply;
    //初始化work
    for (j = 0; j < N; j++)
        Work[j] = Available[j];
    //初始化Finish
    for (i = 0; i < M; i++)
        Finish[i] = False;
    //求安全序列
    for (i = 0; i < M; i++) {
        apply = 0;
        for (j = 0; j < N; j++) {
            if (Finish[i] == False && Need[i][j] <= Work[j])
            {
                apply++;
                //直到每类资源尚需数都小于系统可利用资源数才可分配
                if (apply == N)
                {
                    for (m = 0; m < N; m++)
                        Work[m] = Work[m] + Allocation[i][m];//更改当前可分配资源
                    Finish[i] = True;
                    Security[k++] = i;
                    i = -1; //保证每次查询均从第一个进程开始
                }
            }
        }
    }

    for (i = 0; i < M; i++) {
        if (Finish[i] == False) {
            printf("系统不安全\n");//不成功系统不安全
            return False;
        }
    }
    printf("系统是安全的!\n");//如果安全,输出成功
    printf("存在一个安全序列:");
    for (i = 0; i < M; i++) {//输出运行进程数组
        printf("P%d", Security[i]);
        if (i < M - 1)
            printf("->");
    }
    printf("\n");
    return True;
}

/********利用银行家算法对申请资源进行试分********/
void bank()
{
    int flag = True;//标志变量,判断能否进入银行家算法的下一步
    int i, j;

    printf("请输入请求分配资源的进程号(0-%d):", M - 1);
    scanf_s("%d", &i);//输入须申请资源的进程号

    printf("请输入进程P%d要申请的资源个数:\n", i);
    for (j = 0; j < N; j++)
    {
        printf("%c:", NAME[j]);
        scanf_s("%d", &Request[j]);//输入需要申请的资源
    }

    //判断银行家算法的前两条件是否成立
    for (j = 0; j < N; j++)
    {
        if (Request[j] > Need[i][j])//判断申请是否大于需求,若大于则出错
        {
            printf("进程P%d申请的资源大于它需要的资源", i);
            printf("分配不合理,不予分配!\n");
            flag = False;
            break;
        }
        else
        {
            if (Request[j] > Available[j])//判断申请是否大于当前可分配资源,若大于则出错
            {
                printf("进程%d申请的资源大于系统现在可利用的资源", i);
                printf("\n");
                printf("系统尚无足够资源,不予分配!\n");
                flag = False;
                break;
            }
        }
    }
    //前两个条件成立,试分配资源,寻找安全序列
    if (flag) {
        test(i); //根据进程需求量,试分配资源
        showdata(); //根据进程需求量,显示试分配后的资源量
        if (!safe()) //寻找安全序列
        {
            Retest(i);
            showdata();
        }
    }
}


//显示版权信息函数 
void versionInfo()
{
    printf( " ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ \n"  );
    printf( " ┃       银行家算法模拟系统        ┃ \n"  );
    printf( " ┠──────────────────────────────────────────────┨ \n"  );
    printf( " ┃   (c)All Right Reserved Promise Sun     ┃ \n"  );
    printf( " ┃   https://blog.csdn.net/sun_promise     ┃ \n"  );
    printf( " ┃     version 100 build 2023        ┃ \n"  );
    printf( " ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ \n"  );
}


int main()//主函数
{
    versionInfo();
    char choice;
    init();//初始化数据
    showdata();//显示各种资源
    //用银行家算法判定系统当前时刻是否安全,不安全就不再继续分配资源
    if (!safe()) exit(0);

    do {
        printf("*************************************************************\n");
        printf("\n");
        printf("\n");
        printf("\t-------------------银行家算法演示------------------\n");
        printf("                     R(r):请求分配   \n");
        printf("                     E(e):退出       \n");
        printf("\t---------------------------------------------------\n");
        printf("请选择:");
        fflush(stdin);  //清空输入流缓冲区的字符,注意必须引入#include<stdlib.h>头文件
        scanf_s("%s", &choice,2);

        switch (choice)
        {
        case 'r':
        case 'R':
            bank(); break;
        case 'e':
        case 'E':
            exit(0);
        default: printf("请正确选择!\n"); break;
        }
    } while (choice);
}

版权声明:本文为博主原创文章,转载请点赞此文并注明出处,谢谢!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容