Repository: TheAlgorithms/Java
Pull request #5748 (2024-10-13 03:24:03)

Add disk scheduling algorithms.
I added five disk scheduling algorithms and test classes to the disk scheduling folder, and they adopted different strategies when simulating disk read and write requests. They are SSF, SCAN, CSCAN, LOOK and CLOOK algorithms.
SSF (shortest seek first) algorithm is a disk scheduling strategy, and its core idea is to always select the request closest to the current head position for processing. This method can effectively reduce the moving distance of the magnetic head, thus reducing the average seek time. Although SSF can significantly improve disk performance, it may lead to some requests far away from the current head position not being served for a long time, which is the so-called "hunger" problem. In order to alleviate this problem, other strategies or rules are sometimes combined in practical application to ensure that all requests can get reasonable responses.

SCAN algorithm is another disk scheduling technology, which divides the disk into multiple areas, and the head scans continuously from one end to the other until it reaches the edge of the disk and reverses the direction to continue scanning. When the head moves, it will serve all requests encountered on the way. SCAN algorithm avoids the hunger problem that SSF may cause, because it ensures that the requests in each area will eventually be processed. However, because the head has to scan the whole disk range back and forth, it needs to complete a complete round trip even if there is no pending request, which may lead to unnecessary head movement and increased waiting time.

CSCAN (Circular SCAN) algorithm is a variant of SCAN. Different from the traditional Scan, in CSCAN, once the head reaches one end of the disk, it will not scan in reverse immediately, but quickly return to the beginning end of the disk to start a new round of scanning. This method reduces the idle time of the magnetic head in the no-request interval and improves the efficiency. CSCAN also solves the problem of hunger, and it can provide more uniform service distribution than SCAN, because scanning is restarted from one end of the disk every time, instead of turning back halfway.

The LOOK algorithm is similar to SCAN, but there is a key difference: the LOOK algorithm only moves the head in the direction where there is a request for service. If the head reaches one end of the disk and there are no more requests in that direction, the head will immediately turn and jump directly to the nearest request at the other end, instead of continuing to SCAN the blank area like Scan. This optimization reduces unnecessary head movement, and makes LOOK algorithm more efficient than SCAN, especially in the case of uneven distribution of requests.

CLOOK algorithm combines the characteristics of CSCAN and LOOK. The magnetic head only moves in the direction where there is a request, and when it reaches one end of the disk, it will quickly jump back to the other end to continue processing the remaining requests. This not only retains the advantage of LOOK algorithm to reduce useless movement, but also inherits the cyclic characteristics of CSCAN's request processing order, which makes the overall disk access more balanced and can also avoid hunger. CLOOK is suitable for those application scenarios that require high response speed and fairness.

codecov-commenter: ## [Codecov](https://app.codecov.io/gh/TheAlgorithms/Java/pull/5748?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms) Report
Attention: Patch coverage is `96.05263%` with `6 lines` in your changes missing coverage. Please review.
> Project coverage is 64.22%. Comparing base [(`4a03f42`)](https://app.codecov.io/gh/TheAlgorithms/Java/commit/4a03f420616a6773e9a5cdc304b1681e96d945bd?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms) to head [(`100f79a`)](https://app.codecov.io/gh/TheAlgorithms/Java/commit/100f79a7eaf3fab5923e1485d085b70760ec7a6e?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms).

| [Files with missing lines](https://app.codecov.io/gh/TheAlgorithms/Java/pull/5748?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms) | Patch % | Lines |
|---|---|---|
| [...eduling/diskscheduling/CircularLookScheduling.java](https://app.codecov.io/gh/TheAlgorithms/Java/pull/5748?src=pr&el=tree&filepath=src%2Fmain%2Fjava%2Fcom%2Fthealgorithms%2Fscheduling%2Fdiskscheduling%2FCircularLookScheduling.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms#diff-c3JjL21haW4vamF2YS9jb20vdGhlYWxnb3JpdGhtcy9zY2hlZHVsaW5nL2Rpc2tzY2hlZHVsaW5nL0NpcmN1bGFyTG9va1NjaGVkdWxpbmcuamF2YQ==) | 90.90% | [0 Missing and 3 partials :warning: ](https://app.codecov.io/gh/TheAlgorithms/Java/pull/5748?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms) |
| [...thms/scheduling/diskscheduling/LookScheduling.java](https://app.codecov.io/gh/TheAlgorithms/Java/pull/5748?src=pr&el=tree&filepath=src%2Fmain%2Fjava%2Fcom%2Fthealgorithms%2Fscheduling%2Fdiskscheduling%2FLookScheduling.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms#diff-c3JjL21haW4vamF2YS9jb20vdGhlYWxnb3JpdGhtcy9zY2hlZHVsaW5nL2Rpc2tzY2hlZHVsaW5nL0xvb2tTY2hlZHVsaW5nLmphdmE=) | 94.44% | [0 Missing and 2 partials :warning: ](https://app.codecov.io/gh/TheAlgorithms/Java/pull/5748?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms) |
| [...eduling/diskscheduling/CircularScanScheduling.java](https://app.codecov.io/gh/TheAlgorithms/Java/pull/5748?src=pr&el=tree&filepath=src%2Fmain%2Fjava%2Fcom%2Fthealgorithms%2Fscheduling%2Fdiskscheduling%2FCircularScanScheduling.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms#diff-c3JjL21haW4vamF2YS9jb20vdGhlYWxnb3JpdGhtcy9zY2hlZHVsaW5nL2Rpc2tzY2hlZHVsaW5nL0NpcmN1bGFyU2NhblNjaGVkdWxpbmcuamF2YQ==) | 96.87% | [0 Missing and 1 partial :warning: ](https://app.codecov.io/gh/TheAlgorithms/Java/pull/5748?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms) |

<details><summary>Additional details and impacted files</summary>


```diff
@@             Coverage Diff              @@
##             master    #5748      +/-   ##
============================================
+ Coverage     63.91%   64.22%   +0.30%     
- Complexity     4167     4219      +52     
============================================
  Files           582      587       +5     
  Lines         16302    16454     +152     
  Branches       3148     3182      +34     
============================================
+ Hits          10419    10567     +148     
+ Misses         5457     5456       -1     
- Partials        426      431       +5     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/TheAlgorithms/Java/pull/5748?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms).


Patch:
diff --git a/src/main/java/com/thealgorithms/scheduling/diskscheduling/CircularLookScheduling.java b/src/main/java/com/thealgorithms/scheduling/diskscheduling/CircularLookScheduling.java
new file mode 100644
index 00000000..2230ecaf
--- /dev/null
+++ b/src/main/java/com/thealgorithms/scheduling/diskscheduling/CircularLookScheduling.java
@@ -0,0 +1,80 @@
+package com.thealgorithms.scheduling.diskscheduling;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Circular Look Scheduling (C-LOOK) is a disk scheduling algorithm similar to
+ * the C-SCAN algorithm but with a key difference. In C-LOOK, the disk arm also
+ * moves in one direction to service requests, but instead of going all the way
+ * to the end of the disk, it only goes as far as the furthest request in the
+ * current direction. After servicing the last request in the current direction,
+ * the arm immediately jumps back to the closest request on the other side without
+ * moving to the disk's extreme ends. This reduces the unnecessary movement of the
+ * disk arm, resulting in better performance compared to C-SCAN, while still
+ * maintaining fair wait times for requests.
+ */
+public class CircularLookScheduling {
+    private int currentPosition;
+    private boolean movingUp;
+    private final int maxCylinder;
+
+    public CircularLookScheduling(int startPosition, boolean movingUp, int maxCylinder) {
+        this.currentPosition = startPosition;
+        this.movingUp = movingUp;
+        this.maxCylinder = maxCylinder;
+    }
+
+    public List<Integer> execute(List<Integer> requests) {
+        List<Integer> result = new ArrayList<>();
+
+        // Filter and sort valid requests in both directions
+        List<Integer> upRequests = new ArrayList<>();
+        List<Integer> downRequests = new ArrayList<>();
+
+        for (int request : requests) {
+            if (request >= 0 && request < maxCylinder) {
+                if (request > currentPosition) {
+                    upRequests.add(request);
+                } else if (request < currentPosition) {
+                    downRequests.add(request);
+                }
+            }
+        }
+
+        Collections.sort(upRequests);
+        Collections.sort(downRequests);
+
+        if (movingUp) {
+            // Process all requests in the upward direction
+            result.addAll(upRequests);
+
+            // Jump to the lowest request and process all requests in the downward direction
+            result.addAll(downRequests);
+        } else {
+            // Process all requests in the downward direction (in reverse order)
+            Collections.reverse(downRequests);
+            result.addAll(downRequests);
+
+            // Jump to the highest request and process all requests in the upward direction (in reverse order)
+            Collections.reverse(upRequests);
+            result.addAll(upRequests);
+        }
+
+        // Update current position to the last processed request
+        if (!result.isEmpty()) {
+            currentPosition = result.get(result.size() - 1);
+        }
+
+        return result;
+    }
+
+    public int getCurrentPosition() {
+        return currentPosition;
+    }
+
+    public boolean isMovingUp() {
+        return movingUp;
+    }
+}
diff --git a/src/main/java/com/thealgorithms/scheduling/diskscheduling/CircularScanScheduling.java b/src/main/java/com/thealgorithms/scheduling/diskscheduling/CircularScanScheduling.java
new file mode 100644
index 00000000..a31c3d99
--- /dev/null
+++ b/src/main/java/com/thealgorithms/scheduling/diskscheduling/CircularScanScheduling.java
@@ -0,0 +1,83 @@
+package com.thealgorithms.scheduling.diskscheduling;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Circular Scan Scheduling (C-SCAN) is a disk scheduling algorithm that
+ * works by moving the disk arm in one direction to service requests until
+ * it reaches the end of the disk. Once it reaches the end, instead of reversing
+ * direction like in the SCAN algorithm, the arm moves back to the starting point
+ * without servicing any requests. This ensures a more uniform wait time for all
+ * requests, especially those near the disk edges. The algorithm then continues in
+ * the same direction, making it effective for balancing service time across all disk sectors.
+ */
+public class CircularScanScheduling {
+    private int currentPosition;
+    private boolean movingUp;
+    private final int diskSize;
+
+    public CircularScanScheduling(int startPosition, boolean movingUp, int diskSize) {
+        this.currentPosition = startPosition;
+        this.movingUp = movingUp;
+        this.diskSize = diskSize;
+    }
+
+    public List<Integer> execute(List<Integer> requests) {
+        if (requests.isEmpty()) {
+            return new ArrayList<>(); // Return empty list if there are no requests
+        }
+
+        List<Integer> sortedRequests = new ArrayList<>(requests);
+        Collections.sort(sortedRequests);
+
+        List<Integer> result = new ArrayList<>();
+
+        if (movingUp) {
+            // Moving up: process requests >= current position
+            for (int request : sortedRequests) {
+                if (request >= currentPosition && request < diskSize) {
+                    result.add(request);
+                }
+            }
+
+            // Jump to the smallest request and continue processing from the start
+            for (int request : sortedRequests) {
+                if (request < currentPosition) {
+                    result.add(request);
+                }
+            }
+        } else {
+            // Moving down: process requests <= current position in reverse order
+            for (int i = sortedRequests.size() - 1; i >= 0; i--) {
+                int request = sortedRequests.get(i);
+                if (request <= currentPosition) {
+                    result.add(request);
+                }
+            }
+
+            // Jump to the largest request and continue processing in reverse order
+            for (int i = sortedRequests.size() - 1; i >= 0; i--) {
+                int request = sortedRequests.get(i);
+                if (request > currentPosition) {
+                    result.add(request);
+                }
+            }
+        }
+
+        // Set final position to the last request processed
+        if (!result.isEmpty()) {
+            currentPosition = result.get(result.size() - 1);
+        }
+        return result;
+    }
+
+    public int getCurrentPosition() {
+        return currentPosition;
+    }
+
+    public boolean isMovingUp() {
+        return movingUp;
+    }
+}
diff --git a/src/main/java/com/thealgorithms/scheduling/diskscheduling/LookScheduling.java b/src/main/java/com/thealgorithms/scheduling/diskscheduling/LookScheduling.java
new file mode 100644
index 00000000..beba69b0
--- /dev/null
+++ b/src/main/java/com/thealgorithms/scheduling/diskscheduling/LookScheduling.java
@@ -0,0 +1,95 @@
+package com.thealgorithms.scheduling.diskscheduling;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * https://en.wikipedia.org/wiki/LOOK_algorithm
+ * Look Scheduling algorithm implementation.
+ * The Look algorithm moves the disk arm to the closest request in the current direction,
+ * and once it processes all requests in that direction, it reverses the direction.
+ */
+public class LookScheduling {
+    private final int maxTrack;
+    private final int currentPosition;
+    private boolean movingUp;
+    private int farthestPosition;
+    public LookScheduling(int startPosition, boolean initialDirection, int maxTrack) {
+        this.currentPosition = startPosition;
+        this.movingUp = initialDirection;
+        this.maxTrack = maxTrack;
+    }
+
+    /**
+     * Executes the Look Scheduling algorithm on the given list of requests.
+     *
+     * @param requests List of disk requests.
+     * @return Order in which requests are processed.
+     */
+    public List<Integer> execute(List<Integer> requests) {
+        List<Integer> result = new ArrayList<>();
+        List<Integer> lower = new ArrayList<>();
+        List<Integer> upper = new ArrayList<>();
+
+        // Split requests into two lists based on their position relative to current position
+        for (int request : requests) {
+            if (request >= 0 && request < maxTrack) {
+                if (request < currentPosition) {
+                    lower.add(request);
+                } else {
+                    upper.add(request);
+                }
+            }
+        }
+
+        // Sort the requests
+        Collections.sort(lower);
+        Collections.sort(upper);
+
+        // Process the requests depending on the initial moving direction
+        if (movingUp) {
+            // Process requests in the upward direction
+            result.addAll(upper);
+            if (!upper.isEmpty()) {
+                farthestPosition = upper.get(upper.size() - 1);
+            }
+
+            // Reverse the direction and process downward
+            movingUp = false;
+            Collections.reverse(lower);
+            result.addAll(lower);
+            if (!lower.isEmpty()) {
+                farthestPosition = Math.max(farthestPosition, lower.get(0));
+            }
+        } else {
+            // Process requests in the downward direction
+            Collections.reverse(lower);
+            result.addAll(lower);
+            if (!lower.isEmpty()) {
+                farthestPosition = lower.get(0);
+            }
+
+            // Reverse the direction and process upward
+            movingUp = true;
+            result.addAll(upper);
+            if (!upper.isEmpty()) {
+                farthestPosition = Math.max(farthestPosition, upper.get(upper.size() - 1));
+            }
+        }
+
+        return result;
+    }
+
+    public int getCurrentPosition() {
+        return currentPosition;
+    }
+
+    public boolean isMovingUp() {
+        return movingUp;
+    }
+
+    public int getFarthestPosition() {
+        return farthestPosition;
+    }
+}
diff --git a/src/main/java/com/thealgorithms/scheduling/diskscheduling/SSFScheduling.java b/src/main/java/com/thealgorithms/scheduling/diskscheduling/SSFScheduling.java
new file mode 100644
index 00000000..30838821
--- /dev/null
+++ b/src/main/java/com/thealgorithms/scheduling/diskscheduling/SSFScheduling.java
@@ -0,0 +1,56 @@
+package com.thealgorithms.scheduling.diskscheduling;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *https://en.wikipedia.org/wiki/Shortest_seek_first
+ * Shortest Seek First (SFF) Scheduling algorithm implementation.
+ * The SFF algorithm selects the next request to be serviced based on the shortest distance
+ * from the current position of the disk arm. It continuously evaluates all pending requests
+ * and chooses the one that requires the least amount of movement to service.
+ *
+ * This approach minimizes the average seek time, making it efficient in terms of response
+ * time for individual requests. However, it may lead to starvation for requests located
+ * further away from the current position of the disk arm.
+ *
+ * The SFF algorithm is particularly effective in systems where quick response time
+ * is crucial, as it ensures that the most accessible requests are prioritized for servicing.
+ */
+public class SSFScheduling {
+    private int currentPosition;
+
+    public SSFScheduling(int currentPosition) {
+        this.currentPosition = currentPosition;
+    }
+
+    public List<Integer> execute(List<Integer> requests) {
+        List<Integer> result = new ArrayList<>(requests);
+        List<Integer> orderedRequests = new ArrayList<>();
+
+        while (!result.isEmpty()) {
+            int closest = findClosest(result);
+            orderedRequests.add(closest);
+            result.remove(Integer.valueOf(closest));
+            currentPosition = closest;
+        }
+        return orderedRequests;
+    }
+
+    private int findClosest(List<Integer> requests) {
+        int minDistance = Integer.MAX_VALUE;
+        int closest = -1;
+        for (int request : requests) {
+            int distance = Math.abs(currentPosition - request);
+            if (distance < minDistance) {
+                minDistance = distance;
+                closest = request;
+            }
+        }
+        return closest;
+    }
+
+    public int getCurrentPosition() {
+        return currentPosition;
+    }
+}
diff --git a/src/main/java/com/thealgorithms/scheduling/diskscheduling/ScanScheduling.java b/src/main/java/com/thealgorithms/scheduling/diskscheduling/ScanScheduling.java
new file mode 100644
index 00000000..2c4fa784
--- /dev/null
+++ b/src/main/java/com/thealgorithms/scheduling/diskscheduling/ScanScheduling.java
@@ -0,0 +1,82 @@
+package com.thealgorithms.scheduling.diskscheduling;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * https://en.wikipedia.org/wiki/Elevator_algorithm
+ * SCAN Scheduling algorithm implementation.
+ * The SCAN algorithm moves the disk arm towards one end of the disk, servicing all requests
+ * along the way until it reaches the end. Once it reaches the end, it reverses direction
+ * and services the requests on its way back.
+ *
+ * This algorithm ensures that all requests are serviced in a fair manner,
+ * while minimizing the seek time for requests located close to the current position
+ * of the disk arm.
+ *
+ * The SCAN algorithm is particularly useful in environments with a large number of
+ * disk requests, as it reduces the overall movement of the disk arm compared to
+ */
+public class ScanScheduling {
+    private int headPosition;
+    private int diskSize;
+    private boolean movingUp;
+
+    public ScanScheduling(int headPosition, boolean movingUp, int diskSize) {
+        this.headPosition = headPosition;
+        this.movingUp = movingUp;
+        this.diskSize = diskSize;
+    }
+
+    public List<Integer> execute(List<Integer> requests) {
+        // If the request list is empty, return an empty result
+        if (requests.isEmpty()) {
+            return new ArrayList<>();
+        }
+
+        List<Integer> result = new ArrayList<>();
+        List<Integer> left = new ArrayList<>();
+        List<Integer> right = new ArrayList<>();
+
+        // Separate requests into those smaller than the current head position and those larger
+        for (int request : requests) {
+            if (request < headPosition) {
+                left.add(request);
+            } else {
+                right.add(request);
+            }
+        }
+
+        // Sort the requests
+        Collections.sort(left);
+        Collections.sort(right);
+
+        // Simulate the disk head movement
+        if (movingUp) {
+            // Head moving upward, process right-side requests first
+            result.addAll(right);
+            // After reaching the end of the disk, reverse direction and process left-side requests
+            result.add(diskSize - 1); // Simulate the head reaching the end of the disk
+            Collections.reverse(left);
+            result.addAll(left);
+        } else {
+            // Head moving downward, process left-side requests first
+            Collections.reverse(left);
+            result.addAll(left);
+            // After reaching the start of the disk, reverse direction and process right-side requests
+            result.add(0); // Simulate the head reaching the start of the disk
+            result.addAll(right);
+        }
+
+        return result;
+    }
+
+    public int getHeadPosition() {
+        return headPosition;
+    }
+
+    public boolean isMovingUp() {
+        return movingUp;
+    }
+}


Test patch:
diff --git a/src/test/java/com/thealgorithms/scheduling/diskscheduling/CircularLookSchedulingTest.java b/src/test/java/com/thealgorithms/scheduling/diskscheduling/CircularLookSchedulingTest.java
new file mode 100644
index 00000000..ae04e725
--- /dev/null
+++ b/src/test/java/com/thealgorithms/scheduling/diskscheduling/CircularLookSchedulingTest.java
@@ -0,0 +1,54 @@
+package com.thealgorithms.scheduling.diskscheduling;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Arrays;
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+public class CircularLookSchedulingTest {
+
+    @Test
+    public void testCircularLookSchedulingMovingUp() {
+        CircularLookScheduling scheduling = new CircularLookScheduling(50, true, 200);
+        List<Integer> requests = Arrays.asList(55, 58, 39, 18, 90, 160, 150);
+        List<Integer> expected = Arrays.asList(55, 58, 90, 150, 160, 18, 39);
+
+        List<Integer> result = scheduling.execute(requests);
+        assertEquals(expected, result);
+    }
+
+    @Test
+    public void testCircularLookSchedulingMovingDown() {
+        CircularLookScheduling scheduling = new CircularLookScheduling(50, false, 200);
+        List<Integer> requests = Arrays.asList(55, 58, 39, 18, 90, 160, 150);
+        List<Integer> expected = Arrays.asList(39, 18, 160, 150, 90, 58, 55);
+
+        List<Integer> result = scheduling.execute(requests);
+        assertEquals(expected, result);
+    }
+
+    @Test
+    public void testCircularLookSchedulingEmptyRequests() {
+        CircularLookScheduling scheduling = new CircularLookScheduling(50, true, 200);
+        List<Integer> requests = Arrays.asList();
+        List<Integer> expected = Arrays.asList();
+
+        List<Integer> result = scheduling.execute(requests);
+        assertEquals(expected, result);
+    }
+
+    @Test
+    public void testCircularLookSchedulingPrintStatus() {
+        CircularLookScheduling scheduling = new CircularLookScheduling(50, true, 200);
+        List<Integer> requests = Arrays.asList(55, 58, 39, 18, 90, 160, 150);
+        List<Integer> result = scheduling.execute(requests);
+
+        // Print the final status
+        System.out.println("Final CircularLookScheduling Position: " + scheduling.getCurrentPosition());
+        System.out.println("CircularLookScheduling Moving Up: " + scheduling.isMovingUp());
+
+        // Print the order of request processing
+        System.out.println("Request Order: " + result);
+    }
+}
diff --git a/src/test/java/com/thealgorithms/scheduling/diskscheduling/CircularScanSchedulingTest.java b/src/test/java/com/thealgorithms/scheduling/diskscheduling/CircularScanSchedulingTest.java
new file mode 100644
index 00000000..06bd53c0
--- /dev/null
+++ b/src/test/java/com/thealgorithms/scheduling/diskscheduling/CircularScanSchedulingTest.java
@@ -0,0 +1,48 @@
+package com.thealgorithms.scheduling.diskscheduling;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Arrays;
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+public class CircularScanSchedulingTest {
+
+    @Test
+    public void testCircularScanSchedulingMovingUp() {
+        CircularScanScheduling circularScan = new CircularScanScheduling(50, true, 200);
+        List<Integer> requests = Arrays.asList(55, 58, 39, 18, 90, 160, 150);
+        List<Integer> expectedOrder = Arrays.asList(55, 58, 90, 150, 160, 18, 39);
+
+        List<Integer> result = circularScan.execute(requests);
+        assertEquals(expectedOrder, result);
+
+        System.out.println("Final CircularScan Position: " + circularScan.getCurrentPosition());
+        System.out.println("CircularScan Moving Up: " + circularScan.isMovingUp());
+        System.out.println("Request Order: " + result);
+    }
+
+    @Test
+    public void testCircularScanSchedulingMovingDown() {
+        CircularScanScheduling circularScan = new CircularScanScheduling(50, false, 200);
+        List<Integer> requests = Arrays.asList(55, 58, 39, 18, 90, 160, 150);
+        List<Integer> expectedOrder = Arrays.asList(39, 18, 160, 150, 90, 58, 55);
+
+        List<Integer> result = circularScan.execute(requests);
+        assertEquals(expectedOrder, result);
+
+        System.out.println("Final CircularScan Position: " + circularScan.getCurrentPosition());
+        System.out.println("CircularScan Moving Down: " + circularScan.isMovingUp());
+        System.out.println("Request Order: " + result);
+    }
+
+    @Test
+    public void testCircularScanSchedulingEmptyRequests() {
+        CircularScanScheduling circularScan = new CircularScanScheduling(50, true, 200);
+        List<Integer> requests = Arrays.asList();
+        List<Integer> expectedOrder = Arrays.asList();
+
+        List<Integer> result = circularScan.execute(requests);
+        assertEquals(expectedOrder, result);
+    }
+}
diff --git a/src/test/java/com/thealgorithms/scheduling/diskscheduling/LookSchedulingTest.java b/src/test/java/com/thealgorithms/scheduling/diskscheduling/LookSchedulingTest.java
new file mode 100644
index 00000000..91acc483
--- /dev/null
+++ b/src/test/java/com/thealgorithms/scheduling/diskscheduling/LookSchedulingTest.java
@@ -0,0 +1,67 @@
+package com.thealgorithms.scheduling.diskscheduling;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Arrays;
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+public class LookSchedulingTest {
+
+    @Test
+    public void testLookSchedulingMovingUp() {
+        LookScheduling lookScheduling = new LookScheduling(50, true, 200);
+        List<Integer> requests = Arrays.asList(55, 58, 39, 18, 90, 160, 150);
+        List<Integer> expected = Arrays.asList(55, 58, 90, 150, 160, 39, 18);
+
+        List<Integer> result = lookScheduling.execute(requests);
+        assertEquals(expected, result);
+    }
+
+    @Test
+    public void testLookSchedulingMovingDown() {
+        LookScheduling lookScheduling = new LookScheduling(50, false, 200);
+        List<Integer> requests = Arrays.asList(55, 58, 39, 18, 90, 160, 150);
+        List<Integer> expected = Arrays.asList(39, 18, 55, 58, 90, 150, 160);
+
+        List<Integer> result = lookScheduling.execute(requests);
+        assertEquals(expected, result);
+    }
+
+    @Test
+    public void testLookSchedulingEmptyRequests() {
+        LookScheduling lookScheduling = new LookScheduling(50, true, 200);
+        List<Integer> requests = Arrays.asList();
+        List<Integer> expected = Arrays.asList();
+
+        List<Integer> result = lookScheduling.execute(requests);
+        assertEquals(expected, result);
+    }
+
+    @Test
+    public void testLookSchedulingCurrentPosition() {
+        LookScheduling lookScheduling = new LookScheduling(50, true, 200);
+
+        // Testing current position remains unchanged after scheduling.
+        assertEquals(50, lookScheduling.getCurrentPosition());
+    }
+
+    @Test
+    public void testLookSchedulingPrintStatus() {
+        LookScheduling lookScheduling = new LookScheduling(50, true, 200);
+
+        List<Integer> requests = Arrays.asList(55, 58, 39, 18, 90, 160, 150);
+
+        List<Integer> result = lookScheduling.execute(requests);
+
+        List<Integer> expectedOrder = Arrays.asList(55, 58, 90, 150, 160, 39, 18);
+        assertEquals(expectedOrder, result);
+
+        System.out.println("Final LookScheduling Position: " + lookScheduling.getCurrentPosition());
+        System.out.println("LookScheduling Moving Up: " + lookScheduling.isMovingUp());
+
+        System.out.println("Farthest Position Reached: " + lookScheduling.getFarthestPosition());
+
+        System.out.println("Request Order: " + result);
+    }
+}
diff --git a/src/test/java/com/thealgorithms/scheduling/diskscheduling/SSFSchedulingTest.java b/src/test/java/com/thealgorithms/scheduling/diskscheduling/SSFSchedulingTest.java
new file mode 100644
index 00000000..0239b011
--- /dev/null
+++ b/src/test/java/com/thealgorithms/scheduling/diskscheduling/SSFSchedulingTest.java
@@ -0,0 +1,55 @@
+package com.thealgorithms.scheduling.diskscheduling;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class SSFSchedulingTest {
+
+    private SSFScheduling scheduler;
+
+    @BeforeEach
+    public void setUp() {
+        scheduler = new SSFScheduling(50);
+    }
+
+    @Test
+    public void testExecuteWithEmptyList() {
+        List<Integer> requests = new ArrayList<>();
+        List<Integer> result = scheduler.execute(requests);
+        assertTrue(result.isEmpty(), "Result should be empty for an empty request list.");
+    }
+
+    @Test
+    public void testExecuteWithSingleRequest() {
+        List<Integer> requests = new ArrayList<>(List.of(100));
+        List<Integer> result = scheduler.execute(requests);
+        assertEquals(List.of(100), result, "The only request should be served first.");
+    }
+
+    @Test
+    public void testExecuteWithMultipleRequests() {
+        List<Integer> requests = new ArrayList<>(List.of(10, 90, 60, 40, 30, 70));
+        List<Integer> result = scheduler.execute(requests);
+        assertEquals(List.of(60, 70, 90, 40, 30, 10), result, "Requests should be served in the shortest seek first order.");
+    }
+
+    @Test
+    public void testExecuteWithSameDistanceRequests() {
+        List<Integer> requests = new ArrayList<>(List.of(45, 55));
+        List<Integer> result = scheduler.execute(requests);
+        assertEquals(List.of(45, 55), result, "When distances are equal, requests should be served in the order they appear in the list.");
+    }
+
+    @Test
+    public void testGetCurrentPositionAfterExecution() {
+        List<Integer> requests = new ArrayList<>(List.of(10, 90, 60, 40, 30, 70));
+        scheduler.execute(requests);
+        int currentPosition = scheduler.getCurrentPosition();
+        assertEquals(10, currentPosition, "Current position should be the last request after execution.");
+    }
+}
diff --git a/src/test/java/com/thealgorithms/scheduling/diskscheduling/ScanSchedulingTest.java b/src/test/java/com/thealgorithms/scheduling/diskscheduling/ScanSchedulingTest.java
new file mode 100644
index 00000000..1dbcd489
--- /dev/null
+++ b/src/test/java/com/thealgorithms/scheduling/diskscheduling/ScanSchedulingTest.java
@@ -0,0 +1,54 @@
+package com.thealgorithms.scheduling.diskscheduling;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Arrays;
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+public class ScanSchedulingTest {
+
+    @Test
+    public void testScanSchedulingMovingUp() {
+        ScanScheduling scanScheduling = new ScanScheduling(50, true, 200);
+        List<Integer> requests = Arrays.asList(55, 58, 39, 18, 90, 160, 150);
+        List<Integer> expected = Arrays.asList(55, 58, 90, 150, 160, 199, 39, 18);
+
+        List<Integer> result = scanScheduling.execute(requests);
+        assertEquals(expected, result);
+    }
+
+    @Test
+    public void testScanSchedulingMovingDown() {
+        ScanScheduling scanScheduling = new ScanScheduling(50, false, 200);
+        List<Integer> requests = Arrays.asList(55, 58, 39, 18, 90, 160, 150);
+        List<Integer> expected = Arrays.asList(39, 18, 0, 55, 58, 90, 150, 160);
+
+        List<Integer> result = scanScheduling.execute(requests);
+        assertEquals(expected, result);
+    }
+
+    @Test
+    public void testScanSchedulingEmptyRequests() {
+        ScanScheduling scanScheduling = new ScanScheduling(50, true, 200);
+        List<Integer> requests = Arrays.asList();
+        List<Integer> expected = Arrays.asList();
+
+        List<Integer> result = scanScheduling.execute(requests);
+        assertEquals(expected, result);
+    }
+
+    @Test
+    public void testScanScheduling() {
+        ScanScheduling scanScheduling = new ScanScheduling(50, true, 200);
+        List<Integer> requests = Arrays.asList(55, 58, 39, 18, 90, 160, 150);
+
+        List<Integer> result = scanScheduling.execute(requests);
+        List<Integer> expectedOrder = Arrays.asList(55, 58, 90, 150, 160, 199, 39, 18);
+        assertEquals(expectedOrder, result);
+
+        System.out.println("Final Head Position: " + scanScheduling.getHeadPosition());
+        System.out.println("Head Moving Up: " + scanScheduling.isMovingUp());
+        System.out.println("Request Order: " + result);
+    }
+}