如何在Scala中的对象列表上执行二进制搜索

时间:2018-09-11 18:29:55

标签: scala big-o binary-search scala-collections

case class Employee (id: Int, name : String, age : Int)

// Added four emplyees emp1, emp2 emp3, emp4 to the list like below::

val emp1 = Employee(101, "name1", 101)
val emp2 = Employee(102, "name2", 102)
val emp3 = Employee(103, "name3", 103)
val emp4 = Employee(104, "name4", 104)

list = scala.List(emp1, emp2, emp3, emp4)

我想使用BINARY SEARCH在列表中按员工的姓名搜索,然后检索该员工对象。

请注意:搜索复杂度应为O(logn),我们不应为此目的使用任何地图。

类似

val emp = list.binarysearch("name2")
println("the returned employee's age: ", emp.age) //should print 102

任何帮助将不胜感激!!

2 个答案:

答案 0 :(得分:3)

Searching提供二进制搜索,但是您需要一个索引序列,而不是线性序列(即List),正如其他人所解释的那样-否则您仍然可以使用search但您会得到线性的O(n)行为,而不是O(Log n)。

您说要搜索名称,因此需要按名称排序,否则结果可能会不一致。您应该研究scala.math.Ordering

因此,如果您可以将列表转换为数组,则可以执行此操作。

case class Employee (id: Int, name : String, age : Int)
val emp1 = Employee(1, "Jane Doe", 45)
val emp2 = Employee(2, "Jon Doe", 54)
val emp3 = Employee(3, "Tera Patrick", 38)
val emp4 = Employee(4, "Jenna Jameson", 36)
// convert to an array
val employees = List(emp1, emp2, emp3, emp4).toArray

// define your ordering
import scala.math.Ordering
implicit object NameOrdering extends Ordering[Employee] {
  def compare(a:Employee, b:Employee) = a.name compare b.name
}

// now sort
import scala.util.Sorting
Sorting.quickSort(employees)(NameOrdering)

然后。

import scala.collection.Searching._

// If the element is found its index is returned
scala> val result = employees.search(emp3)
result: collection.Searching.SearchResult = Found(3)

要检索元素,请对结果使用insertionPoint方法。

scala> employees(result.insertionPoint)
res6: Employee = Employee(3,Tera Patrick,38)

如果找不到该元素,则返回其插入点在排序序列中的索引。

val emp5 = Employee(5, "Aurora Snow", 34)     // not added

scala> employees.search(emp5)
res2: collection.Searching.SearchResult = InsertionPoint(0)

答案 1 :(得分:0)

您永远无法在O(log n)中的scala List()上进行二进制搜索,因为我们无法一次丢弃一半的列表,因此必须遍历直到那。但是,可以使用数组来完成。在Scala中,您可以创建一个隐式类,以在任何Array [String]实例上具有binarySearch()方法

  implicit class StrArrayOps(strArray: Array[String]) {
    @scala.annotation.tailrec
    private def bs(arr: Array[String], s: Int, e: Int, str: String): Option[Int] = {
      if (e<s) {
        None
      } else {
        val m = (s+e)/2
        val mid = arr(m)
        if (mid == str) {
          Some(m)
        } else {
          if (str.compareTo(mid) > 0) {
            bs(arr, m+1, e, str)
          } else {
            bs(arr, 0, m-1, str)
          }
        }
      }
    }

    //returns None if str not found in the strArray
    //returns Some(i) where i is the index of str in the strArray
    def binarySearch(str: String): Option[Int] = bs(strArray, 0, strArray.length-1, str)
  }

您可以按以下方式使用它

scala> val a = Array("name1", "name2", "name3")
a: Array[String] = Array(name1, name2, name3)

scala> a.binarySearch("name2")
res20: Option[Int] = Some(1)

scala> a.binarySearch("name1")
res21: Option[Int] = Some(0)

scala> a.binarySearch("name3")
res22: Option[Int] = Some(2)

scala> a.binarySearch("name34")
res23: Option[Int] = None