银行家算法(链表)

一.程序模块及流程
(1)本程序中重要模块主要包括以下模块:
1初始化void Init()
2安全性算法int Safety_Algorithm()
3试分配process* Attempt()
4测试void TestBanker()
(2)执行流程:
此银行家算法运用了链表来实现,首先建立进程链表块,每一个节点代表一个进程信息,每个进程的资源信息为数据结构中的数据信息。
1进行进程的初始化,存储当前的进程信息
2将信息打印输出在屏幕上
3调用安全性算法,检测当前系统是否处于安全状态,若处于安全状态,则进行下一步,若不安全则程序结束
4调用试分配函数,进行试分配,若试分配成功,修改相关数据结构,打印当前系统资源情况表,进行下一步,否则,重新接收其他请求向量。
5再次调用安全性算法,检查试分配以后的系统安全性,若安全则打印安全性序列和系统资源情况表,并选择是否继续操作。否则之前的试分配失败,返回试分配之前的数据结构,输出系统资源情况表,接收下一个进程请求。

二.主要函数说明:
void Insret_Tail(process **head, process node);//链表尾插
void Init(process **head, int m); //初始化系统资源
void Print(process *head, int *avail, int m);//打印当前系统资源情况表
void PrintSafety(process *head, int *safety, int work[][M], int m, int n);//打印试分配后安全状态的资源情况表
process* Location(process* head, int pro_num);//进程定位
process* Attempt(process* head, int *request, int *avail, int m);//试分配
process* CurRun(process* head, int*finish, int*work, int m, int n);//找到当前可执行进程(通过安全检查的进程)
void Change(process* p, int* work, int* finish, int record[][M], int m);//修改进程书信息
int Safety_Algorithm(process* head, int *avail, int *safety, int Record[][M], int m, int n);//安全性算法
void Back(process* p, int *request, int *avail, int m);//试分配失败后恢复分配前系统资源
void TestBanker();//测试函数

三.程序设计流程图:
《银行家算法(链表)》

四.测试结果:

《银行家算法(链表)》

《银行家算法(链表)》

《银行家算法(链表)》

《银行家算法(链表)》

《银行家算法(链表)》

《银行家算法(链表)》

五.源代码:

//banker.h
#include<windows.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define M 50 // 系统资源的种类
#define N 50 // 最大进程数
int n = 0;
typedef struct my_process
{
    int num;                    //进程标号 
    int Max[M];                 // 表示某个进程对某类资源的最大需求
    int Allocation[M];          // 表示某个进程已分配到某类资源的个数
    int Need[M];                // 表示某个进程尚需要某类资源的个数
    struct my_process* next;            //指向下一个进程节点
}process;

void Insret_Tail(process **head, process node)    //尾插法建立进程链表
{
    process* p = (process*)malloc(sizeof(process));
    process* last = NULL;
    memcpy(p, &node, sizeof(process));     //动态创建进程结点
    p->next = NULL;
    if (NULL == *head)
    {
        *head = p;
    }
    else      //找表尾
    {
        last = *head;
        while (last->next != NULL)
        {
            last = last->next;
        }
        last->next = p;             //插入链尾
    }

}

void Init(process **head, int m)//初始化系统资源
{
    int n1 = n;
    int i, j = 0;
    for (int z = 0; z < n1; z++)
    {
        process node;
        node.num = j++;
        printf("请输入第 %d个进程信息 :\n", z + 1);
        printf("最大需求矩阵: ");
        for (i = 0; i<m; i++)
        {
            scanf_s("%d", &node.Max[i]);
        }
        printf("分配矩阵: ");
        for (i = 0; i<m; i++)
        {
            scanf_s("%d", &node.Allocation[i]);
        }
        printf("\n");
        for (i = 0; i<m; i++)
        {
            node.Need[i] = node.Max[i] - node.Allocation[i];
        }
        Insret_Tail(head, node);  //插入链尾
    }
}

void Print(process *head, int *avail, int m)//打印初始系统资源
{
    process* p = NULL;
    int count = 0;
    int i, j;
    char ch;
    p = head;
    if (NULL == p)
    {
        printf("当前无进程 !\n");
        return;
    }
    else
    {
        printf("资源分配情况表:\n");
        printf("\n |num| |Max| |Allocation| | Need | |Available| \n");
        printf("\t");
        for (i = 0; i<4; i++)
        {
            ch = 'A';
            for (j = 0; j<m; j++)
            {
                printf("%4c", ch++);
            }
            printf("\t");
        }

        printf("\n");
        while (p != NULL)
        {
            count++;
            printf("%8d", p->num);
            for (j = 0; j<m; j++)
            {
                printf("%4d", p->Max[j]);
            }
            printf("\t");
            for (j = 0; j<m; j++)
            {
                printf("%4d", p->Allocation[j]);
            }
            printf("\t");
            for (j = 0; j<m; j++)
            {
                printf("%4d", p->Need[j]);
            }
            printf("\t");
            if (count == 1)
            {
                for (j = 0; j<m; j++)
                {
                    printf("%4d", avail[j]);
                }
            }
            printf("\n");
            p = p->next;
        }
        printf("\n");
    }
}

void PrintSafety(process *head, int *safety, int work[][M], int m, int n)  //打印试分配后的系统资源状态
{
    process* p = NULL;
    int i, j;
    p = head;
    if (NULL == p)
    {
        exit(0);
    }
    else
    {
        printf("\n |Work+| ");
        printf("\n|Process| |Work| |Need| |Allocation| |Allocation| |Finish|\n");
        puts("");
        for (i = 0; i<n; i++)
        {
            p = head;
            while (p != NULL)
            {
                if (p->num == safety[i])
                {
                    printf("%8d", p->num);
                    for (j = 0; j<m; j++)
                    {
                        printf("%4d", work[p->num][j]);
                    }
                    printf("\t");
                    for (j = 0; j<m; j++)
                    {
                        printf("%4d", p->Need[j]);
                    }
                    printf("\t");
                    for (j = 0; j<m; j++)
                    {
                        printf("%4d", p->Allocation[j]);
                    }
                    printf("\t");
                    for (j = 0; j<m; j++)
                    {
                        printf("%4d", work[p->num][j] + p->Allocation[j]);
                    }
                    for (j = 0; j<m - 2; j++)
                    {
                        printf("\ttrue");
                    }
                    break;
                }
                else
                {
                    p = p->next;
                }
            }
            puts("");
        }
    }
}

process* Location(process* head, int pro_num)   //进程定位函数,找到当前请求进程在进程链表中的位置,以便后面对其操作
{
    process *p = NULL;
    p = head;
    if (NULL == p)
    {
        printf("error !\n");            //异常,当前链表为空
        return p;
    }
    else
    {
        while (p != NULL)
        {
            if (p->num == pro_num)
            {
                break;
            }
            else
            {
                p = p->next;
            }
        }
        if (NULL == p)              //无此进程,输入错误
        {
            printf("无此进程 !\n");
            return p;
        }
        else
        {
            return p;
        }
    }
}

process* Attempt(process* head, int *request, int *avail, int m)//试分配
{
    int num, i;
    process* p = NULL;
    printf("请输入进程编号: \n");
    scanf_s("%d", &num);
    p = Location(head, num);
    if (NULL == p)
    {
        printf("无此进程!\n");
        return p;
    }
    printf("请输入该进程的请求向量: \n");
    for (i = 0; i<m; i++)
    {
        scanf_s("%d", &request[i]);
    }
    for (i = 0; i<m; i++)       //请求的合法性检验
    {
        if (request[i] <= p->Need[i])
        {
            continue;
        }
        else
        {
            printf("该请求系统不能满足 !\n");
            return NULL;
        }
    }
    for (i = 0; i<m; i++)
    {
        if (request[i] <= avail[i])
        {
            continue;
        }
        else
        {
            printf("该请求系统不能满足 !\n");
            return NULL;
        }
    }
    for (i = 0; i<m; i++)                     //试分配,修改相关数据结构
    {
        avail[i] = avail[i] - request[i];
        p->Allocation[i] = p->Allocation[i] + request[i];
        p->Need[i] = p->Need[i] - request[i];
    }
    return p;
}

process* CurRun(process* head, int*finish, int*work, int m, int n)//找当前可执行的进程
{
    int i = 0, j = 0, count = 0;
    process* p = NULL;
    while (1)
    {
        if (finish[i] != -1)  //表示该进程未执行安全性检查
        {
            p = Location(head, finish[i]);      //定位该进程
            if (p != NULL)
            {
                for (j = 0; j<m; j++)
                {
                    if (p->Need[j]>work[j])
                    {

                        break;
                    }
                    else
                    {
                        continue;
                    }
                }
                if (j == m)
                {
                    return p;
                }
                else
                {
                    i++;    //当前进程检查没有通过,则进行下一个进程的检查
                }
            }
        }
        else
        {
            i++;   //当前进程已经检查过,则进行下一个进程的检查
        }
        if (i == n)
        {
            return NULL;  //遍历所有进程都未找到,则跳出返回NULL
        }
    }
}

void Change(process* p, int* work, int* finish, int record[][M], int m) //修改相关数据结构
{
    int i;
    for (i = 0; i<m; i++)
    {
        record[p->num][i] = work[i];
        work[i] = work[i] + p->Allocation[i];

    }
    finish[p->num] = -1;   //表示该进程已通过安全性检查
}

int Safety_Algorithm(process* head, int *avail, int *safety, int Record[][M], int m, int n)//安全性算法
{
    int *work = NULL;
    int *finish = NULL;
    process *p = NULL;
    process *pro = NULL;
    int i, count = 0;
    work = (int*)malloc(m*sizeof(int));     //当前系统可供给进程的各个资源数目
    finish = (int*)malloc(n*sizeof(int));       //标志数组

    p = head;
    for (i = 0; i<m; i++)
    {
        work[i] = avail[i];
    }
    i = 0;
    while (p != NULL)
    {

        finish[i] = p->num;
        p = p->next;
        i++;
    }
    i = 0;
    while (count<n)
    {
        pro = CurRun(head, finish, work, m, n);
        if (pro != NULL)    //Need[i,j]<=work[j],即当前系统可以满足该进程
        {
            Change(pro, work, finish, Record, m);
            count++;
            safety[i] = pro->num;
            i++;
        }
        else
        {
            printf("当前系统处于不安全状态 !\n");
            break;
        }

    }
    if (count == n)
    {
        printf("当前系统处于安全状态,存在一个安全序列 :\n");
        for (i = 0; i<n; i++)
        {
            printf("%d,", safety[i]);     //打印安全序列
        }
        puts("");
    }

    free(finish);
    free(work);
    finish = NULL;
    work = NULL;
    if (count == n)
    {
        return 1;   //找到安全序列则返回1
    }
    else
    {
        return 0;   //未找到安全序列则返回0
    }
}

void Back(process* p, int *request, int *avail, int m)  //若试分配失败,则恢复试分配前的资源状态
{
    int i;
    {
        for (i = 0; i<m; i++)
        {
            p->Allocation[i] -= request[i];
            p->Need[i] += request[i];
            avail[i] += request[i];
        }
    }
}
#include"banker.h"
void TestBanker()
{
    int i, flag = 0, count = 0;
    char ch;
    int mM;
    int *p = NULL;      //进程链头指针数组
    int Available[M] = { 0 };/*其中每一个数组元素表示当前某类资源的可用数目,初始化为系统所提供的资源的最大数目*/
    int Request[M] = { 0 };
    int Record_work[N][M] = { 0 };
    int Safety[N] = { 0 };   //存储安全序列,以便后面排序
    process *head = NULL;
    process *pro = NULL;
    printf("请输入进程个数:");
    scanf_s("%d", &n);
    printf("请输入资源数目:");
    scanf_s("%d", &mM);
    printf("\n请初始化当前可用资源\n");
    for (i = 0; i<mM; i++)
    {
        scanf_s("%d", &Available[i]);
    }
    Init(&head, mM);
    Print(head, Available, mM);
    do
    {
        flag = Safety_Algorithm(head, Available, Safety, Record_work, mM, n);
        if (1 == flag)
        {
            printf("当前系统是安全的,可进行试探分配 !\n");
            do
            {
                pro = Attempt(head, Request, Available, mM);     //通过则试分配
                if (NULL != pro)
                {
                    printf("试分配成功 !\n");
                    Print(head, Available, mM);
                    break;
                }
                else                            // 否则,退到上一级
                {
                    printf("当前请求系统不能满足 ! 请重新输入请求向量(Y/y),或者退出(N/n)\n\n");
                    printf("您是否要继续操作 (Y/N):\n");
                    getchar();
                    scanf_s("%c", &ch);
                    if (ch == 'N' || ch == 'n')
                    {
                        exit(0);
                    }
                }
            } while (ch == 'Y' || ch == 'y');
        }
        else        //未通过安全性算法
        {

            printf("当前系统不安全,不能响应任何进程的请求 !\n");
            return;
        }
        flag = Safety_Algorithm(head, Available, Safety, Record_work, mM, n);
        if (1 == flag)
        {
            printf("分配成功!当前资源分配状态如下表 :\n");
            PrintSafety(head, Safety, Record_work, mM, n);
            printf("您是否还要继续操作 (Y(y)/N(y))\n");
            getchar();
            scanf_s("%c", &ch);
        }
        else
        {
            printf("当前系统处于不安全状态,恢复原来的资源分配状态 ! :\n");
            Back(pro, Request, Available, mM);
            Print(head, Available, mM);
            printf("您是否还要继续操作 (Y(y)/N(y))\n");
            getchar();
            scanf_s("%c", &ch);
        }
    } while (ch == 'Y' || ch == 'y');
}

int main()
{
    TestBanker();
    system("pause");
    return 0;
}
    原文作者:银行家问题
    原文地址: https://blog.csdn.net/yiyi0116/article/details/53914360
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞