Scala Program to Implement Jump Search

Scala Program to Implement Jump Search

Jump Search is a searching algorithm designed to improve efficiency when working with sorted arrays. Unlike Linear Search, which checks each element one by one, Jump Search skips ahead by fixed steps, called jumps, and then performs a smaller search within a block where the target may lie. This approach reduces the number of comparisons, making it faster than Linear Search, especially for large datasets.

Pluralsight Logo
Accelerate your tech career
with hands-on learning.
Whether you're a tech newbie or a total pro,
get the skills and confidence to land your next move.
Start 10-Day Free Trial

Jump Search is particularly useful when the dataset is sorted and accessing elements has a uniform cost. It is often used in applications like searching records in a database or looking up values in ordered lists. Learning Jump Search in Scala helps beginners understand how algorithmic optimizations like block-wise search can save time and improve program efficiency. It also introduces the concept of combining jumps with smaller linear searches for better performance.

Program 1: Basic Iterative Jump Search

This program demonstrates the classic Jump Search using a fixed step size to find an integer in a sorted array.

object JumpSearchIterative {

  def jumpSearch(arr: Array[Int], target: Int): Int = {

    val n = arr.length
    val step = Math.sqrt(n).toInt
    var prev = 0
    var curr = 0

    while (curr < n && arr(curr) < target) {
      prev = curr
      curr += step
    }

    for (i <- prev until Math.min(curr, n)) {
      if (arr(i) == target) return i
    }

    -1

  }

  def main(args: Array[String]): Unit = {

    val data = Array(1, 3, 5, 7, 9, 11, 13)
    val target = 7
    val index = jumpSearch(data, target)

    if (index != -1) println(s"Element $target found at index $index")
    else println(s"Element $target not found")

  }

}

This iterative approach uses a step size equal to the square root of the array length, which is the optimal step for Jump Search. Beginners can understand that the algorithm “jumps” forward and then searches linearly within the block to locate the target.

Program 2: Jump Search with Custom Step Size

This program allows defining a custom step size instead of using the square root of the array length.

object JumpSearchCustomStep {

  def jumpSearch(arr: Array[Int], target: Int, step: Int): Int = {

    var prev = 0
    var curr = 0
    val n = arr.length

    while (curr < n && arr(curr) < target) {
      prev = curr
      curr += step
    }

    for (i <- prev until Math.min(curr, n)) {
      if (arr(i) == target) return i
    }

    -1

  }

  def main(args: Array[String]): Unit = {

    val data = Array(2, 4, 6, 8, 10, 12, 14)
    val target = 10
    val step = 3
    val index = jumpSearch(data, target, step)

    if (index != -1) println(s"Element $target found at index $index")
    else println(s"Element $target not found")

  }

}

By changing the step size, beginners can experiment with how jump size affects the efficiency of the algorithm. A larger step reduces jumps but increases the size of the linear search block, while a smaller step does the opposite.

Program 3: Recursive Jump Search

Jump Search can also be implemented recursively, which helps understand how the search block is reduced step by step.

object JumpSearchRecursive {

  def jumpSearch(arr: Array[Int], target: Int, prev: Int = 0, step: Int = -1): Int = {

    val n = arr.length
    val s = if (step == -1) Math.sqrt(n).toInt else step
    val curr = Math.min(prev + s, n)

    if (prev >= n || arr(prev) > target) return -1

    if (arr(curr - 1) >= target) {

      for (i <- prev until curr) {
        if (arr(i) == target) return i
      }

      -1

    } else {
      jumpSearch(arr, target, curr, s)
    }

  }

  def main(args: Array[String]): Unit = {

    val data = Array(1, 2, 4, 5, 7, 9)
    val target = 5
    val index = jumpSearch(data, target)

    if (index != -1) println(s"Element $target found at index $index")
    else println(s"Element $target not found")

  }

}

The recursive approach divides the array into blocks and calls itself on the next block until it finds the target. This teaches beginners how recursion can simplify block-based searching logic.

Program 4: Jump Search for Floating-Point Numbers

Jump Search can handle sorted arrays of floating-point numbers as well.

object JumpSearchFloat {

  def almostEqual(a: Double, b: Double, precision: Double = 1e-9): Boolean =
    (a - b).abs < precision

  def jumpSearch(arr: Array[Double], target: Double): Int = {

    val n = arr.length
    val step = Math.sqrt(n).toInt
    var prev = 0
    var curr = 0

    while (curr < n && arr(curr) < target) {
      prev = curr
      curr += step
    }

    for (i <- prev until Math.min(curr + 1, n)) {
      if (almostEqual(arr(i), target)) return i
    }

    -1

  }

  def main(args: Array[String]): Unit = {

    val data = Array(1.1, 2.2, 3.3, 4.4, 5.5)
    val target = 3.3
    val index = jumpSearch(data, target)

    if (index != -1) println(s"Element $target found at index $index")
    else println(s"Element $target not found")

  }

}

This demonstrates that Jump Search is not limited to integers. Beginners can see that as long as the array is sorted, the algorithm works efficiently with decimal values.

Program 5: Jump Search with Multiple Occurrences

This program finds all occurrences of a target value in a sorted array with duplicates.

object JumpSearchMultiple {

  def jumpSearchAll(arr: Array[Int], target: Int): Array[Int] = {

    val n = arr.length
    val step = Math.sqrt(n).toInt
    var prev = 0
    var curr = 0

    // Jump in steps to find a block that may contain the target
    while (curr < n && arr(curr) < target) {
      prev = curr
      curr += step
    }

    curr = Math.min(curr, n - 1)

    // Linear scan from prev to curr to find one occurrence
    var foundIndex = -1
    var i = prev
    var found = false

    while (i <= curr && !found) {

      if (arr(i) == target) {
        foundIndex = i
        found = true
      }

      i += 1

    }

    if (foundIndex == -1) return Array()

    // Scan left and right from foundIndex to collect all indices
    val indices = scala.collection.mutable.ArrayBuffer[Int]()

    i = foundIndex
    while (i >= 0 && arr(i) == target) { indices += i; i -= 1 }

    i = foundIndex + 1
    while (i < n && arr(i) == target) { indices += i; i += 1 }

    indices.sorted.toArray

  }

  def main(args: Array[String]): Unit = {

    val data = Array(2, 4, 4, 4, 6, 8)
    val target = 4
    val indices = jumpSearchAll(data, target)

    if (indices.nonEmpty) println(s"Element $target found at indices: ${indices.mkString(", ")}")
    else println(s"Element $target not found")

  }

}

By collecting all matching indices, this program teaches beginners how to handle duplicates while still benefiting from Jump Search’s efficiency.

Frequently Asked Questions (FAQ)

This section answers common questions beginners may have when learning Jump Search in Scala.

Q1: What is Jump Search?
Jump Search is an algorithm that searches a sorted array by jumping ahead in fixed steps and then searching within a block linearly.

Q2: When is Jump Search faster than Linear Search?
It is faster for large, sorted arrays because it reduces the number of comparisons.

Q3: How do I choose the step size?
The optimal step size is usually the square root of the array length. Beginners can experiment with different sizes for learning.

Q4: Can Jump Search handle floating-point numbers?
Yes, as long as the array is sorted and step calculation is applied properly.

Q5: Can Jump Search find multiple occurrences?
Yes, by searching within the block and collecting all indices of the target value.

Conclusion

Jump Search is an efficient searching algorithm for sorted arrays, especially large datasets, by combining block jumps with linear searches. By exploring multiple implementations in Scala—including iterative, recursive, floating-point, custom step sizes, and multiple occurrences—beginners can learn how to optimize search operations and understand block-wise algorithmic thinking. Practicing these programs helps build confidence in algorithm design and prepares learners for more advanced search techniques.

Scroll to Top