Scala 索引集合(已排序的索引序列)上的二进制搜索

Scala 索引集合(已排序的索引序列)上的二进制搜索,scala,indexing,binary-search,Scala,Indexing,Binary Search,我有一个索引的集合(它必须被索引),属于某种类型的A: var coll: IndexedSeq[A] 我希望根据一些排序[A]对coll进行排序,但我经常在其中添加/删除项目。这样做的明显机制如下: def binarySearch[A : Ordering](a: IndexedSeq[A], elem: A): Int def add(a: A) { val idx = binarySearch(coll, a) coll = (coll take idx) :+ a +: (c

我有一个索引的集合(它必须被索引),属于某种类型的
A

var coll: IndexedSeq[A]
我希望根据一些排序[A]对
coll
进行排序,但我经常在其中添加/删除项目。这样做的明显机制如下:

def binarySearch[A : Ordering](a: IndexedSeq[A], elem: A): Int
def add(a: A) {
  val idx = binarySearch(coll, a)
  coll = (coll take idx) :+ a +: (coll drop idx)
}

但是标准库中既没有
binarySearch
(奇怪,因为有
scala.util.Sorting.quickSort
),也没有可以找到索引和排序的数据类型(我想这是一个低效的结构)。

我认为
TreeSet
上的
slice
相当有效(您可以将其用于一个元素范围),但您是对的——奇怪的是,没有索引排序的数据结构。而且它足够有效;如果跟踪子级的数量,大多数排序树都可以这样使用。我认为这只是一个遗漏

如果使用仅允许引用相等的标记对重复元素进行包装,则始终可以使用重复元素集,并且可以确保重复元素的顺序:

class Tag[A](val value: A)(implicit ord: Ordering[A]) extends Ordered[Tag[A]] {
  def compare(ta: Tag[A]) = {
    val c = ord.compare(value,ta.value)
    if (c != 0) c
    else if (this eq ta) 0
    else System.identityHashCode(this) compare System.identityHashCode(ta)
  }
  override def toString = value.toString+"'"
  override def hashCode = value.hashCode
  override def equals(a: Any) = a.asInstanceOf[AnyRef] eq this
}

scala> collection.immutable.TreeSet[Tag[Int]]() ++ List(1,2,3,2,1).map(i => new Tag(i))
res1: scala.collection.immutable.TreeSet[Tag[Int]] = TreeSet(1', 1', 2', 2', 3')

scala> res1.slice(2,3).head
res2: Tag[Int] = 2'
但是,对于一个相对简单的任务来说,这确实会增加很多开销。

def getPerson(userList:ArrayList[Person],Person:Person):Integer={
def getPerson(userList: ArrayList[Person], person: Person): Integer = {
var low = 0;
var high = userList.size - 1

while (low <= high) {
  var mid = low + (high - low) / 2
  var midValue = userList.get(mid)
  if (person.firstName < midValue.firstName) {
    high = mid - 1;
  } else if (person.firstName > midValue.firstName) {
    low = mid + 1;
  } else {
    return mid
  }
}
return -1
var-low=0; var high=userList.size-1 while(低中值。firstName){ 低=中+1; }否则{ 中途返回 } } 返回-1
}

$$SearchImpl

在排序序列中的间隔内搜索特定元素。如果序列是IndexedSeq,则使用二进制搜索。否则,使用线性搜索


树具有O(logn)元素访问权限。我认为
IndexedSeq
意味着O(1)访问权限。此外,基于
Ordered
,不可能存在O(1)(用于插入)排序集合,因为按成对比较排序至少是O(nlogn)。@ziggystar-
IndexedSeq
不保证是O(1)访问。看看
List
!@RexKerr
List
不是
IndexedSeq
IndexedSeq
确实应该具有“恒定时间或接近恒定时间的元素访问和长度计算”(scaladoc 2.9.1)。有趣的是-我猜这里基于索引的访问不会是O(1)-这可能有问题,因为这是
TableModel
@oxbow的支持数据结构。您可以拥有O(1)读访问权限,但不能拥有O(1)写访问权限。您在OP中的示例演示了这一点。您是否可以为询问者添加解释和解释,这也将帮助您获得更多选票