使用DFS(深度優先搜索)遍歷求出所有的安全序列。
數據結構
先上頭文件說明,實現此算法用到的數據結構和命名。
#ifndef _DATA_STRUCTURE
#define _DATA_STRUCTURE
// 表示資源個數
#define M (4)
// 表示進程個數
#define N (4)
// 當前狀態還剩多少可用的資源
struct AvailableD;
// 每個進程對每個資源的最大需求量
struct MaxD;
// 當前分配個每個進程的資源數目
struct AllocationD;
// 每個進程還需要多少資源數目(最大需求 - 當前分配)
struct NeedD;
// 當前狀態每個進程請求的資源數量
struct RequestD;
// 存放安全序列的數據結構(名字叫 Queue 實際上是棧的實現【FILO先進後出】)
struct QueueD;
// 表明每個進程是否在安全序列中
struct StatusD;
typedef struct AvailableD *Available;
typedef struct MaxD *Max;
typedef struct AllocationD *Allocation;
typedef struct NeedD *Need;
typedef struct RequestD *Request;
typedef struct QueueD *Queue;
typedef struct StatusD *Status;
Available create_available();
Allocation create_allocation();
Max create_max();
Need create_need();
Queue create_queue();
int queue_full(Queue queue);
int queue_empty(Queue queue);
void queue_add(Queue queue, int data);
int queue_get(Queue queue);
void queue_display(Queue queue);
Status create_status();
void display_need(Need need);
/* 更新 need 數組 */
void update_need(Need need, Allocation allocation, Max max);
/* 將 allocation 矩陣的 第 row 行的值加(減)到 available 裏 */
void update_available(Allocation allocation, int row, Available available, int is_add);
/* 檢查 available 是否滿足 need 的第 row 行的需求 */
void check_available(Allocation allocation, Need need, Available available, int row, Queue queue, Status status);
#endif
算法步驟
首先檢查當前剩餘的資源數目是否滿足某個進程的需求量,也就是說判斷 Available 向量中每一個資源數目是否大於等於 Need 矩陣中某一個進程的需求量;
如果對於進程 row ,對每個資源數目的需求量小於當前可用的系統資源;首先檢查當前進程是否已經在安全序列中,若存在就判斷下一個進程;
若當前進程 row 還沒有處在安全序列,就開始深度優先搜索:將當前進程 row 已經分配到的系統資源數目加到當前可用的資源數目中,即 Allocation 矩陣中第 row 行的所有數目加到 Available 向量中;然後將當前進程 row 添加到安全序列中(此安全序列是一個棧);遞歸調用搜索的函數,向下一個進程開始搜索;
在搜索的過程中需要判斷所有的進程是否已經添加到安全序列中,即查看安全序列(棧)的大小是否等於當前系統的進程數目;若達到了就將安全序列輸出並且開始回溯;此判斷應該放在深度優先搜索函數的前面,用來作爲遞歸出口;
然後將最近加入到安全序列中的進程從安全隊列中刪除,即從棧中彈出一個元素,記爲 row;然後修改此進程row未加在安全序列中的狀態;將此進程row收回的資源數目歸還,即從 Available 向量中減去 Allocation 矩陣中第 row 行的數目;然後向下一個進程搜索。
核心代碼
/**
* allocation: Allocation 每個進程已經分配的資源數目的矩陣
* need: Need 每個進程還需的資源數目的矩陣
* available: Available 剩餘資源數的矩陣
* row: 表示從哪個進程開始向下掃描
* queue: 已加入安全序列的進程(棧性質)
* status: 表示每個進程是否已經存在於安全序列
* */
void check_available(Allocation allocation, Need need, Available available, int row, Queue queue, Status status)
{
int temp = row;
int i;
int flag = 1;
// 遞歸出口
if (queue->length == 4)
{
printf("Safe sequence: ");
queue_display(queue);
return;
}
do
{
for (i = 0; i < M; i++)
{
if (available->vector[i] < need->matrix[row][i])
{
flag = 0;
break;
}
}
if (flag)
{
if (status->vector[row] == 1)
{
row = (row + 1) % N;
continue;
}
// 深搜準備
update_available(allocation, row, available, 1);
queue_add(queue, row);
status->vector[row] = 1;
check_available(allocation, need, available, (row + 1) % N, queue, status);
// 回溯 恢復剛纔的狀態
status->vector[row] = 0;
queue_get(queue);
update_available(allocation, row, available, 0);
//temp = row;
row = (row + 1) % N;
}
else
{
row = (row + 1) % N;
flag = 1;
}
} while (temp != row);
}
所有代碼
#include <stdio.h>
#include <stdlib.h>
#include "datastructure.h"
// 長度爲 m 的一維數組
// 表示還有多少可用資源
struct AvailableD
{
int m;
int *vector;
};
// 長度爲 m*n 的矩陣
// 表示各進程對資源的最大需求數
struct MaxD
{
int m;
int n;
int **matrix;
};
// 長度爲 m*n 的矩陣
// 表示已經給各進程分配了多少資源
struct AllocationD
{
int m;
int n;
int **matrix;
};
// 長度爲 m*n 的矩陣
// 表示各進程最多還需要多少資源
struct NeedD
{
int m;
int n;
int **matrix;
};
// 長度爲 m 的一維數組
// 表示進程此次申請的各種資源
struct RequestD
{
int m;
int *vector;
};
// 長度爲 n 的一維數組
// 具有棧的性質的安全序列
struct QueueD
{
int n;
int *vector;
int length;
int front;
};
// 長度爲 n 的一維數組
// 表示某個進程是否已經在安全序列的標誌
struct StatusD
{
int *vector;
};
// 創建 Allocation 矩陣,數據手動輸入
Allocation create_allocation()
{
int i, j;
Allocation allocation = (Allocation)malloc(sizeof(struct AllocationD));
allocation->m = M;
allocation->n = N;
allocation->matrix = (int **)malloc(sizeof(int *) * N);
for (i = 0; i < M; i++)
{
allocation->matrix[i] = (int *)malloc(sizeof(int) * M);
}
for (i = 0; i < N; i++)
{
for (j = 0; j < M; j++)
{
scanf("%d", &(allocation->matrix[i][j]));
}
}
return allocation;
}
// 創建 Max 矩陣,數據手動輸入
Max create_max()
{
int i, j;
Max max = (Max)malloc(sizeof(struct MaxD));
max->m = M;
max->n = N;
max->matrix = (int **)malloc(sizeof(int *) * N);
for (i = 0; i < M; i++)
{
max->matrix[i] = (int *)malloc(sizeof(int) * M);
}
for (i = 0; i < N; i++)
{
for (j = 0; j < M; j++)
{
scanf("%d", &(max->matrix[i][j]));
}
}
return max;
}
// 創建 Need 矩陣,數據手動輸入
Need create_need()
{
int i, j;
Need need = (Need)malloc(sizeof(struct NeedD));
need->m = M;
need->n = N;
need->matrix = (int **)malloc(sizeof(int *) * N);
for (i = 0; i < M; i++)
{
need->matrix[i] = (int *)malloc(sizeof(int) * M);
}
return need;
}
// 根據 Allocation 和 Max 矩陣計算 Need 矩陣
void update_need(Need need, Allocation allocation, Max max)
{
int i, j;
for (i = 0; i < N; i++)
{
for (j = 0; j < M; j++)
{
need->matrix[i][j] = max->matrix[i][j] - allocation->matrix[i][j];
}
}
}
// 創建 Available 一維數組,數據手動輸入
Available create_available()
{
int i;
Available available = (Available)malloc(sizeof(struct AvailableD));
available->m = M;
available->vector = (int *)malloc(sizeof(int) * M);
for (i = 0; i < M; i++)
{
scanf("%d", &(available->vector[i]));
}
return available;
}
// 將 Allocation 矩陣的第 row 行的資源數目加(減)到 Available 數組中
// is_add: 爲 1 時加;反之爲減
void update_available(Allocation allocation, int row, Available available, int is_add)
{
int i = 0;
for (i = 0; i < N; i++)
{
if (is_add)
{
available->vector[i] += allocation->matrix[row][i];
}
else
{
available->vector[i] -= allocation->matrix[row][i];
}
}
}
// 創建一個安全“隊列”(棧實現)
Queue create_queue()
{
int i;
Queue queue = (Queue)malloc(sizeof(struct QueueD));
queue->n = N;
queue->vector = (int *)malloc(sizeof(int) * N);
queue->length = 0;
queue->front = -1;
return queue;
}
// 判斷是否爲滿
int queue_full(Queue queue)
{
return queue->length == queue->n;
}
// 判斷是否爲空
int queue_empty(Queue queue)
{
return queue->length == 0;
}
// 向安全“隊列”(棧)中添加一個數據項
void queue_add(Queue queue, int data)
{
if (queue_full(queue))
{
printf("Queue has been fulled!\n");
return;
}
queue->front++;
queue->vector[queue->front] = data;
queue->length++;
}
// 從安全“隊列”(棧)獲得(彈出)一個數據項(棧頂)
int queue_get(Queue queue)
{
int result;
if (queue_empty(queue))
{
printf("Queue is empty!\n");
return -1;
}
result = queue->vector[queue->front];
queue->front--;
queue->length--;
return result;
}
// 創建狀態數組
Status create_status()
{
int i;
Status status = (Status)malloc(sizeof(struct StatusD));
status->vector = (int *)malloc(sizeof(int) * N);
for (i = 0; i < N; i++)
{
status->vector[i] = 0;
}
return status;
}
// 打印輸出安全“隊列”(棧)中的所有數據項
void queue_display(Queue queue)
{
int i;
for (i = 0; i < queue->length; i++)
{
printf("P%d\t", queue->vector[i]);
}
printf("\n");
}
// 輸出 Need 矩陣
void display_need(Need need)
{
int i, j;
for (i = 0; i < N; i++)
{
for (j = 0; j < M; j++)
{
printf("%d ", need->matrix[i][j]);
}
printf("\n");
}
}
/**
* allocation: Allocation 每個進程已經分配的資源數目的矩陣
* need: Need 每個進程還需的資源數目的矩陣
* available: Available 剩餘資源數的矩陣
* row: 表示從哪個進程開始向下掃描
* queue: 已加入安全序列的進程(棧性質)
* status: 表示每個進程是否已經存在於安全序列
* */
void check_available(Allocation allocation, Need need, Available available, int row, Queue queue, Status status)
{
int temp = row;
int i;
int flag = 1;
if (queue->length == 4)
{
printf("Safe sequence: ");
queue_display(queue);
return;
}
do
{
for (i = 0; i < M; i++)
{
if (available->vector[i] < need->matrix[row][i])
{
flag = 0;
break;
}
}
if (flag)
{
if (status->vector[row] == 1)
{
row = (row + 1) % N;
continue;
}
// 深搜準備
update_available(allocation, row, available, 1);
queue_add(queue, row);
status->vector[row] = 1;
check_available(allocation, need, available, (row + 1) % N, queue, status);
// 回溯 恢復剛纔的狀態
status->vector[row] = 0;
queue_get(queue);
update_available(allocation, row, available, 0);
//temp = row;
row = (row + 1) % N;
}
else
{
row = (row + 1) % N;
flag = 1;
}
} while (temp != row);
}
int main()
{
// 數據的聲明、創建
Available available;
Allocation allocation;
Max max;
Need need = create_need();
Queue queue = create_queue();
Status status = create_status();
// 手動輸入數據
printf("Input available: \n");
available = create_available();
printf("Input allocation: \n");
allocation = create_allocation();
printf("Input Max: \n");
max = create_max();
// 計算 Need 矩陣
update_need(need, allocation, max);
printf("Need: \n");
display_need(need);
// 深度優先搜索 開始遍歷所有安全序列
printf("\nAll the safa sequence:\n\n");
check_available(allocation, need, available, 0, queue, status);
printf("\n");
system("pause");
return 0;
}