1. 程式人生 > >實驗六 磁碟排程演算法

實驗六 磁碟排程演算法

一、  需求分析

說明程式設計的任務和目的,明確規定下述內容:

加深對磁碟排程演算法的理解,進一步掌握先來先服務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,

int curentPostion)

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
    }
}