實驗六 磁碟排程演算法
說明程式設計的任務和目的,明確規定下述內容:
加深對磁碟排程演算法的理解,進一步掌握先來先服務FCFS、最短尋道時間優先 SSTF、SCAN和迴圈SCAN演算法的實現方法。
(1) 輸入的形式和輸入值的範圍;
輸入1-4的整數選擇演算法
已在程式中預置好磁碟訪問請求
(2) 輸出的形式;
磁碟排程過程
(3) 程式所能達到的功能;
模擬FCFS、 SSTF、SCAN和迴圈SCAN演算法對磁碟排程的過程
(4) 測試資料,包括正確的輸入及其輸出結果和含有錯誤的輸入及其輸出結果。
二、 概要設計
說明本程式中用到的所有抽象資料型別的定義、主程式的流程以及各程式模組之間的層次(呼叫)關係。
磁軌訪問請求物件
classTrackOrder
{
publicint ArriveID;//到達順序編號
publicint TrackOrderID;//訪問目標磁軌
publicint MoveDistance;//本次訪問移動的距離
publicint TempDistance;//快取距離
}
三、 詳細設計
實現程式模組的具體演算法。
staticList<TrackOrder> FCFS(List<TrackOrder> list)
staticList<TrackOrder> SSTF(List<TrackOrder> list,
staticList<TrackOrder> SCAN(List<TrackOrder> list, int curentPostion,MoveDirection direcion)
staticList<TrackOrder> CSCAN(List<TrackOrder> list, int curentPostion, MoveDirection direcion)
四、 除錯分析
(1) 除錯過程中遇到的問題以及解決方法,設計與實現的回顧討論和分析;
從幾個演算法中抽閒出相同點,最後將問題轉化為排序問題
五、 使用者使用說明
程式的使用說明,列出每一步的操作步驟。
執行程式--選擇演算法--檢視結果
六、 測試結果
列出測試結果,包括輸入和輸出。
七、 附錄
帶註釋的源程式,註釋應清楚具體;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Lab6
{
enum MoveDirection
{
Left,Right
}
class TrackOrder//磁軌訪問請求物件
{
public int ArriveID;//到達順序編號
public int TrackOrderID;//訪問目標磁軌
public int MoveDistance;//本次訪問移動的距離
public int TempDistance;//快取距離
//建構函式
public TrackOrder(int ArriveID, int TrackOrderID, int MoveDistance)
{
this.ArriveID = ArriveID;
this.TrackOrderID = TrackOrderID;
this.MoveDistance = MoveDistance;
TempDistance = -1;
}
}
class Program
{
#region 公共函式
//獲取差的絕對值
static int getAbsoluteValue(int a, int b)
{
return a - b > 0 ? a - b : b - a;
}
//根據方向獲取差值,若b在a的移動方向,則返回正值,若在移動的反方向則返回負值
static int getDifferenceValue(int a, int b,MoveDirection direcion)
{
if (direcion == MoveDirection.Right)
{
return b - a;
}
else
{
return a-b;
}
}
//列印序列[返回平均移動磁軌數]
static double printTrackOrderList(List<TrackOrder> list,string tipStr="序列如下",bool caculateAvg=false)
{
Console.WriteLine(tipStr);
double avgDistance = 0;
double sumDistance = 0;
for (int i = 0; i < list.Count; i++)
{
if (caculateAvg)
{
sumDistance += list[i].MoveDistance;
Console.WriteLine("請求編號:" + list[i].ArriveID + " 訪問目標磁軌:" + list[i].TrackOrderID + " 本次訪問移動的距離:" + list[i].MoveDistance);
}
else
{
Console.WriteLine("請求編號:" + list[i].ArriveID + " 訪問目標磁軌:" + list[i].TrackOrderID );
}
}
avgDistance=sumDistance/list.Count;
return avgDistance;
}
//處理序列
static void dealTrackOrderList(List<TrackOrder> list, int curentPostion)
{
Console.WriteLine("正在處理...");
for (int i = 0; i < list.Count; i++)
{
list[i].MoveDistance = getAbsoluteValue(curentPostion, list[i].TrackOrderID);
curentPostion = list[i].TrackOrderID;
}
}
#endregion
static void Main(string[] args)
{
Console.WriteLine("----------磁碟排程演算法----------- \n");
//磁頭當前位置
int curentPostion=100;
//移動方向(1向內 2向外)
MoveDirection moveDirection = MoveDirection.Right;
//請求序列
List<TrackOrder> TrackOrderList = new List<TrackOrder>();
int[] TrackOrderIDs = new int[] {55,58,39,18,90,160,150,38,184 };
for (int i = 0; i < 9; i++) //按順序新增9條訪問請求
{
TrackOrderList.Add(new TrackOrder(i,TrackOrderIDs[i],-1));
}
printTrackOrderList(TrackOrderList, "磁碟訪問序列如下");
Console.WriteLine("請選擇演算法1-FCFS,2-SSTF,3-SCAN,4-CSCAN");
string choose=Console.ReadLine();
switch (choose)
{
case "1": { TrackOrderList = FCFS(TrackOrderList); } break;//先來的優先
case "2": { TrackOrderList = SSTF(TrackOrderList, curentPostion); } break;//最短尋道時間優先
case "3": { TrackOrderList = SCAN(TrackOrderList, curentPostion, moveDirection); } break;//按方向掃描
case "4": { TrackOrderList = CSCAN(TrackOrderList, curentPostion, moveDirection); } break;//單一方向掃描
default: { Console.WriteLine("輸入錯誤,程式即將終止"); } break;
}
dealTrackOrderList(TrackOrderList,curentPostion);
double avgTime= printTrackOrderList(TrackOrderList, "處理結果如下",true);
Console.WriteLine("平均尋道時間:" + avgTime);
Console.ReadLine();
}
#region 4種演算法
//先來先訪問-按到達先後排序
static List<TrackOrder> FCFS(List<TrackOrder> list)
{
Console.WriteLine("先來的優先[FCFS]");
return list.OrderBy(m => m.ArriveID).ToList();
}
static List<TrackOrder> SSTF(List<TrackOrder> list, int curentPostion)
{
Console.WriteLine("最短尋道時間優先[SSTF]");
List<TrackOrder> result = new List<TrackOrder>();
//複製一份資料
TrackOrder[] temp = new TrackOrder[list.Count];
list.CopyTo(temp, 0);
List<TrackOrder> tempList = temp.ToList();
for (int k = 0; k < list.Count; k++)
{
//計算和當前位置的差值絕對值
for (int i = 0; i < tempList.Count; i++)
{
tempList[i].TempDistance = getAbsoluteValue(curentPostion, tempList[i].TrackOrderID);
}
//按絕對值排序
List<TrackOrder> tt= tempList.OrderBy(m => m.TempDistance).ToList();
//取第一個元素加入結果集
result.Add(tt[0]);
//在快取中刪除加入結果集的節點
tempList.Remove(tt[0]);
//移動磁頭
curentPostion = tt[0].TrackOrderID;
}
return result;
}
static List<TrackOrder> SCAN(List<TrackOrder> list, int curentPostion,MoveDirection direcion)
{
Console.WriteLine("按方向掃描[SCAN]");
List<TrackOrder> result = new List<TrackOrder>();
//複製一份資料
TrackOrder[] temp = new TrackOrder[list.Count];
list.CopyTo(temp, 0);
List<TrackOrder> tempList = temp.ToList();
for (int k = 0; k < list.Count; k++)
{
//計算和當前位置的差值
for (int i = 0; i < tempList.Count; i++)
{
tempList[i].TempDistance = getDifferenceValue(curentPostion, tempList[i].TrackOrderID, direcion);
}
//排序,忽略小於0的元素
List<TrackOrder> tt = tempList.Where(q=>q.TempDistance>0).OrderBy(m => m.TempDistance).ToList();
//如果不存在大於0的元素,變換方向並跳過本次迴圈(回退k)
if (tt.Count==0)
{
Console.WriteLine("正在改變磁頭方向...");
direcion = direcion == MoveDirection.Left ? MoveDirection.Right : MoveDirection.Left;
k--;
continue;
}
else
{
//取第一個元素加入結果集
result.Add(tt[0]);
//在快取中刪除加入結果集的節點
tempList.Remove(tt[0]);
//移動磁頭
curentPostion = tt[0].TrackOrderID;
}
}
return result;
}
static List<TrackOrder> CSCAN(List<TrackOrder> list, int curentPostion, MoveDirection direcion)
{
Console.WriteLine("按單一方向掃描[SCAN]");
List<TrackOrder> result = new List<TrackOrder>();
//複製一份資料
TrackOrder[] temp = new TrackOrder[list.Count];
list.CopyTo(temp, 0);
List<TrackOrder> tempList = temp.ToList();
for (int k = 0; k < list.Count; k++)
{
//計算和當前位置的差值
for (int i = 0; i < tempList.Count; i++)
{
tempList[i].TempDistance = getDifferenceValue(curentPostion, tempList[i].TrackOrderID, direcion);
}
//排序,忽略小於0的元素
List<TrackOrder> tt = tempList.Where(q => q.TempDistance > 0).OrderBy(m => m.TempDistance).ToList();
//如果不存在大於0的元素,將磁頭歸至0位並跳過本次迴圈(回退k)
if (tt.Count == 0)
{
Console.WriteLine("正在將磁頭歸至0位...");
curentPostion = 0;
k--;
continue;
}
else
{
//取第一個元素加入結果集
result.Add(tt[0]);
//在快取中刪除加入結果集的節點
tempList.Remove(tt[0]);
//移動磁頭
curentPostion = tt[0].TrackOrderID;
}
}
return result;
}
#endregion
}
}