實驗四 動態分割槽分配演算法
一、 需求分析
說明程式設計的任務和目的,明確規定下述內容:
加深對動態分割槽分配演算法的理解,進一步掌握首次適應演算法、迴圈首次適應 演算法、最佳適應演算法和最壞適應演算法的實現方法。
(1) 輸入的形式和輸入值的範圍;
已在程式中預置好記憶體和程序等資訊
(2) 輸出的形式;
按記憶體地址從低到高的順序輸出記憶體狀態和程序的分配結果
(3) 程式所能達到的功能;
模擬首次適應演算法、迴圈首次適應 演算法、最佳適應演算法和最壞適應演算法對記憶體進行分配
(4) 測試資料,包括正確的輸入及其輸出結果和含有錯誤的輸入及其輸出結果。
程序資訊
記憶體資訊(一個 . 代表一個記憶體單元,| 代表 記憶體塊之間的劃分)
二、 概要設計
說明本程式中用到的所有抽象資料型別的定義、主程式的流程以及各程式模組之間的層次(呼叫)關係。
程序物件
classProcess
{
publicstring name;
publicint needSpace;
}
記憶體塊物件
classSpace
{
privatestaticstring usedFlag = "1";
privatestaticstring freeFlag = ".";
publicint id;//空間編號(從小到大排序)
publicint startIndex;//空間開始索引
publicint freeStartIndex;//空閒指標[空間內的相對位置0-空間大小]
publicint freeSize;//空間塊空閒大小
publicList<string> SpaceDetail;//空間詳情
privateList<string>SpaceDetailNote;//【輔助變數】空間詳情描述,便於觀察分配結果
privateint NoteStartIndex;//【輔助變數】空間塊空閒大小
}
記憶體物件
classRAM
{
publicint size;//記憶體大小
publicList<Space> spaceDetail;//記憶體塊詳情
}
三、 詳細設計
實現程式模組的具體演算法。
publicbool
publicbool CycleFirstPartition(List<Process> processList)
publicbool BestPartition(List<Process> processList)
publicbool WorstPartition(List<Process> processList)
四、 除錯分析
(1) 除錯過程中遇到的問題以及解決方法,設計與實現的回顧討論和分析;
完全採用C#用面向物件的方式編寫,程式設計過程十分順利
五、 使用者使用說明
程式的使用說明,列出每一步的操作步驟。
執行程式---檢視結果
六、 測試結果
列出測試結果,包括輸入和輸出。
七、 附錄
帶註釋的源程式,註釋應清楚具體;
using Lab4;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Lab4
{
class Process
{
public string name;
public int needSpace;
public Process(string name, int needSpace)
{
this.name = name;
this.needSpace = needSpace;
}
}
class Space
{
private static string usedFlag = "1";
private static string freeFlag = ".";
public int id;//空間編號(從小到大排序)
public int startIndex;//空間開始索引
public int freeStartIndex;//空閒指標[空間內的相對位置0-空間大小]
public int freeSize;//空間塊空閒大小
public List<string> SpaceDetail;//空間詳情
private List<string> SpaceDetailNote;//【輔助變數】空間詳情描述,便於觀察分配結果
private int NoteStartIndex;//【輔助變數】空間塊空閒大小
public Space(int id, int startIndex, int size)
{
this.id = id;
this.startIndex = startIndex;
freeStartIndex = 0;
freeSize = size;
SpaceDetail = new List<string>(); SpaceDetailNote = new List<string>(); NoteStartIndex = 0;
for (int i = 0; i < size; i++)
{
SpaceDetail.Add(freeFlag); SpaceDetailNote.Add(freeFlag);
}
}
public void useSpace(Process process)
{
for (int i = freeStartIndex; i < freeStartIndex + process.needSpace; i++)
{
SpaceDetail[i] = usedFlag;
}
freeSize -= process.needSpace;
freeStartIndex = SpaceDetail.Count - freeSize - 1;
SpaceDetailNote.RemoveRange(NoteStartIndex, process.needSpace); SpaceDetailNote.Insert(NoteStartIndex, process.name + "[" + process.needSpace + "]"); NoteStartIndex++;
}
public void printSpace()
{
for (int i = 0; i < SpaceDetail.Count; i++)
{
Console.Write(SpaceDetail[i]);
}
}
public void printSpaceNote()
{
for (int i = 0; i < SpaceDetailNote.Count; i++)
{
Console.Write(SpaceDetailNote[i]);
}
}
}
class RAM
{
public int size;//記憶體大小
public List<Space> spaceDetail;//記憶體塊詳情
public RAM(int[] spaceSizeArray)
{
size = 0;
spaceDetail = new List<Space>();
for (int i = 0; i < spaceSizeArray.Length; i++)
{
spaceDetail.Add(new Space(i, size, spaceSizeArray[i]));
size += spaceSizeArray[i];
}
}
public void printRAM(bool printNote = false)
{
//列印前將儲存塊從小到大排序
spaceDetail = spaceDetail.OrderBy(m => m.id).ToList();
Console.WriteLine("當前RAM狀態如下: \n");
foreach (var space in spaceDetail)
{
space.printSpace();
Console.Write("|");
//Console.WriteLine(space.id + "[" + space.startIndex + "," + (space.startIndex + space.SpaceDetail.Count-1) + "]");
}
Console.WriteLine("\n");
if (printNote)
{
foreach (var space in spaceDetail)
{
space.printSpaceNote();
Console.Write("|");
//Console.WriteLine(space.id + "[" + space.startIndex + "," + (space.startIndex + space.SpaceDetail.Count-1) + "]");
}
Console.WriteLine("\n");
}
}
//首次適應演算法
public bool FirstPartition(List<Process> processList)
{
Console.WriteLine("首次適應演算法進行中...");
//預設分配成功次數
int succcefulCount = 0;
//遍歷所有程序
for (int i = 0; i < processList.Count; i++)
{
//遍歷所有空間塊
for (int j = 0; j < spaceDetail.Count; j++)
{
//如果空間充足
if (spaceDetail[j].freeSize >= processList[i].needSpace)
{
//分配空間並轉至處理下一程序
spaceDetail[j].useSpace(processList[i]);
succcefulCount += 1;
break;
}
}
}
return succcefulCount == processList.Count ? true : false;
}
//迴圈首次適應演算法
public bool CycleFirstPartition(List<Process> processList)
{
Console.WriteLine("迴圈首次適應演算法進行中...");
//記錄上次空間塊的位置和1個程序比較空間塊的次數
int spaceIndex = 0, compareCount = 0;
//預設分配成功次數
int succcefulCount = 0;
//遍歷所有程序
for (int i = 0; i < processList.Count; i++)
{
//切換到新程序時重置比較次數
compareCount = 0;
//迴圈遍歷所有空間塊
while (compareCount < spaceDetail.Count)
{
//如果比較了所有空間塊則終止,防止死迴圈!
if (compareCount == spaceDetail.Count)
{
compareCount = spaceDetail.Count;//同時跳出第二層迴圈
break;
}
//取模運算,防止迴圈越界!
if (spaceIndex >= spaceDetail.Count)
{
spaceIndex = spaceIndex % spaceDetail.Count;
}
//如果空間充足
if (spaceDetail[spaceIndex].freeSize >= processList[i].needSpace)
{
//分配空間並轉至處理下一程序
spaceDetail[spaceIndex].useSpace(processList[i]);
succcefulCount++;
spaceIndex++;//移動指標到下一空間
break;
}
spaceIndex++;//移動指標
}
}
return succcefulCount == processList.Count ? true : false;
}
//最佳適應演算法
public bool BestPartition(List<Process> processList)
{
Console.WriteLine("最佳適應演算法進行中...");
//預設分配成功次數
int succcefulCount = 0;
//遍歷所有程序
for (int i = 0; i < processList.Count; i++)
{
//空間塊排序(按剩餘空間從小到大)
spaceDetail = spaceDetail.OrderBy(m => m.freeSize).ToList();
//取出空間訪問順序
List<int> orders = (from t in spaceDetail select t.id).ToList();
//按訪問順序遍歷所有空間塊
for (int j = 0; j < orders.Count; j++)
{
int order = orders[j];
Space space = (from t in spaceDetail where t.id == order select t).FirstOrDefault();
//如果空間充足
if (space.freeSize >= processList[i].needSpace)
{
//分配空間並轉至處理下一程序
spaceDetail[j].useSpace(processList[i]);
succcefulCount += 1;
break;
}
}
}
return succcefulCount == processList.Count ? true : false;
}
//最壞適應演算法
public bool WorstPartition(List<Process> processList)
{
Console.WriteLine("最壞適應演算法進行中...");
//預設分配成功次數
int succcefulCount = 0;
//遍歷所有程序
for (int i = 0; i < processList.Count; i++)
{
//空間塊排序(按剩餘空間從大到小)
spaceDetail = spaceDetail.OrderByDescending(m => m.freeSize).ToList();
//取出空間訪問順序
List<int> orders = (from t in spaceDetail select t.id).ToList();
//按訪問順序遍歷所有空間塊
for (int j = 0; j < orders.Count; j++)
{
int order = orders[j];
Space space = (from t in spaceDetail where t.id == order select t).FirstOrDefault();
//如果空間充足
if (space.freeSize >= processList[i].needSpace)
{
//分配空間並轉至處理下一程序
spaceDetail[j].useSpace(processList[i]);
succcefulCount += 1;
break;
}
}
}
return succcefulCount == processList.Count ? true : false;
}
}
class Tool
{
public static void PrintProcessList(List<Process> processList)
{
Console.WriteLine("----------程序列表如下: \n");
for (int i = 0; i < processList.Count; i++)
{
Console.Write("程序名 " + processList[i].name + " 程序所需空間大小" + processList[i].needSpace+"\n");
}
Console.WriteLine("\n提示: . 表示未使用, 1 表示已被程序佔用 \n");
}
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("----------動態分割槽分配演算法----------- \n");
//初始化程序
List<Process> processList = new List<Process>();
processList.Add(new Process("A", 7));
processList.Add(new Process("B", 18));
processList.Add(new Process("C", 9));
processList.Add(new Process("D", 20));
//初始化記憶體
int[] spaceSizeArray = new int[] { 16, 16, 8, 32, 64, 32 };
//列印資訊
Tool.PrintProcessList(processList);
var r1 = new RAM(spaceSizeArray); r1.printRAM();
if (r1.FirstPartition(processList))
{
r1.printRAM(true);
}
else
{
Console.Write("警告:RAM不足,部分程序未處理!!! \n");
r1.printRAM(true);
}
var r2 = new RAM(spaceSizeArray); r2.CycleFirstPartition(processList); r2.printRAM(true);
var r3 = new RAM(spaceSizeArray); r3.BestPartition(processList); r3.printRAM(true);
var r4 = new RAM(spaceSizeArray); r4.WorstPartition(processList); r4.printRAM(true);
Console.ReadLine();
}
}