1. 程式人生 > 其它 >作業系統課程設計 —— 磁碟排程演算法

作業系統課程設計 —— 磁碟排程演算法

talk is easy, show the code

import java.util.*
import kotlin.math.abs

/**
 * 磁碟排程演算法工廠類, 構造器私有化, 防止外部類例項化
 */
class DiskScheduleFactory private constructor() {

    /**
     * 磁碟排程演算法介面, 不對外開放
     */
    private interface DiskScheduling {
        /**
         * 磁頭移動路徑資料
         * @property moveCount Int
         * @property allDistance Int
         * @property lastPosition Int
         * @constructor
         */
        data class Data(val moveCount: Int, val allDistance: Int, val lastPosition: Int) {
            /**
             * 過載 + 號, 方便合併兩部分資料
             * @param other Data
             * @return Data
             */
            operator fun plus(other: Data) = Data(
                other.moveCount + moveCount,
                other.allDistance + allDistance,
                lastPosition
            )

            /**
             * 將資料以人類能看的方式顯示出來
             * @return String
             */
            override fun toString(): String {
                return "moveCount -> $moveCount allDistance = $allDistance"
            }
        }

        /**
         * 具體演算法實現方法
         * @param visitList IntArray
         * @param currentPosition Int
         * @param upList LinkedList<Int>
         * @param downList LinkedList<Int>
         */
        fun doStuff(visitList: IntArray, currentPosition: Int, upList: LinkedList<Int>, downList: LinkedList<Int>)

        /**
         * 遍歷列表輔助方法
         * @param visitList IntArray
         * @param currentPosition Int
         * @return Data
         */
        fun forEach(visitList: IntArray, currentPosition: Int): Data {
            var head = currentPosition
            var currentDistance: Int
            var allDistance = 0
            var moveCount = 0
            visitList.forEach {
                currentDistance = abs(head - it)
                println("磁頭移動 $head -> $it, 移動距離為 $currentDistance")
                head = it
                allDistance += currentDistance
                moveCount += 1
            }
            return Data(moveCount, allDistance, visitList.last())
        }

        /**
         * 輸出資料
         * @param data Data
         */
        fun outData(data: Data) {
            println("總共移動了 ${data.moveCount} 下, 移動距離為 ${data.allDistance} 平均移動距離為 ${data.allDistance / data.moveCount}")
        }
    }

    /**
     * 演算法實現列舉類, 不對外開放
     */
    private enum class DiskScheduleImpl : DiskScheduling {
        /**
         * 先來先服務演算法
         */
        FirstComeFirstServer {
            override fun doStuff(
                visitList: IntArray,
                currentPosition: Int,
                upList: LinkedList<Int>,
                downList: LinkedList<Int>
            ) {
                outData(forEach(visitList, currentPosition))
            }
        },

        /**
         * 最短尋道時間演算法
         */
        ShortestSeekTimeFirst {
            override fun doStuff(
                visitList: IntArray,
                currentPosition: Int,
                upList: LinkedList<Int>,
                downList: LinkedList<Int>
            ) {
                val allData = forEach(visitList.sortedWith(compareBy {
                    abs(it - currentPosition)
                }).toIntArray(), currentPosition)
                outData(allData)
            }
        },

        /**
         * 電梯演算法 自下往上
         */
        SCAN_UP {
            override fun doStuff(
                visitList: IntArray,
                currentPosition: Int,
                upList: LinkedList<Int>,
                downList: LinkedList<Int>
            ) {
                // 從大到小排序
                downList.reverse()
                // 先往上走
                val upData = forEach(upList.toIntArray(), currentPosition)
                // 再往上走
                val downData = forEach(downList.toIntArray(), upData.lastPosition)
                // 算出總共的
                val allData = downData + upData
                outData(allData)
            }
        },

        /**
         * 電梯演算法 自上往下
         */
        SCAN_DOWN {
            override fun doStuff(
                visitList: IntArray,
                currentPosition: Int,
                upList: LinkedList<Int>,
                downList: LinkedList<Int>
            ) {
                // 從大到小排序
                downList.reverse()
                // 先往下走
                val downData = forEach(downList.toIntArray(), currentPosition)
                // 再往上走
                val upData = forEach(upList.toIntArray(), downData.lastPosition)
                // 算出總共的
                val allData = downData + upData
                outData(allData)
            }
        },

        /**
         * 單項掃描演算法
         */
        C_SCAN {
            override fun doStuff(
                visitList: IntArray,
                currentPosition: Int,
                upList: LinkedList<Int>,
                downList: LinkedList<Int>
            ) {
                // 走到頭後歸零
                downList.push(0)
                // 先往上走
                val upData = forEach(upList.toIntArray(), currentPosition)
                // 再往上走
                val downData = forEach(downList.toIntArray(), upData.lastPosition)
                // 算出總共的
                val allData = downData + upData
                outData(allData)
            }
        }
    }

    /**
     * 伴生物件, 建立例項的方法
     */
    companion object {
        private lateinit var instance: DiskScheduleImpl

        /**
         * 根據演算法名獲取相應的演算法物件
         * @param algorithm String
         * @return DiskScheduleFactory
         */
        fun getInstance(algorithm: String): DiskScheduleFactory {
            runCatching {
                instance = DiskScheduleImpl.valueOf(algorithm)
            }.onFailure {
                throw IllegalArgumentException("演算法不支援!")
            }
            return DiskScheduleFactory()
        }
    }

    /**
     * 代理呼叫演算法
     * @param visitList IntArray
     * @param currentPosition Int
     */
    fun doStuff(visitList: IntArray, currentPosition: Int) {
        // 升序排序
        visitList.sort()
        val downList = LinkedList<Int>()
        val upList = LinkedList<Int>()
        // 分離 上層 與 下層
        visitList.forEach {
            if (it <= currentPosition)
                downList.add(it)
            else
                upList.add(it)
        }
        instance.doStuff(visitList, currentPosition, upList, downList)
    }
}

object Main {

    @JvmStatic
    fun main(args: Array<String>) {
        // 一共 8 條記錄
        val visitDisk = intArrayOf(98, 183, 37, 122, 14, 124, 65, 67)
        DiskScheduleFactory.getInstance("SCAN_DOWN")
            .doStuff(visitDisk, 53)
    }
}