-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRamQueue.scala
More file actions
103 lines (85 loc) · 3.08 KB
/
RamQueue.scala
File metadata and controls
103 lines (85 loc) · 3.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*
Copyright © 2013 RainWarrior
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package asmstuff
import collection.{ Iterable, IterableLike }
import collection.mutable.{ ArrayBuffer, Builder }
import collection.generic.{ GenericOrderedCompanion, GenericOrderedTraversableTemplate, Shrinkable }
import math.Ordering
import annotation.tailrec
import scalaz._
import Scalaz._
class RamQueue[A](implicit val ord: Ordering[A]) extends Iterable[A]
with IterableLike[A, RamQueue[A]]
with Builder[A, RamQueue[A]]
with GenericOrderedTraversableTemplate[A, RamQueue]
with Shrinkable[A] {
implicit val or = Order.fromScalaOrdering(ord)
// data(map(a)) == a
private[this] val data = ArrayBuffer.empty[A]
private[this] var map = Map.empty[A, Int]
private def swap(i: Int, j: Int): Unit = if(i != j) {
val t = data(i)
data(i) = data(j)
data(j) = t
map += data(i) -> i
map += data(j) -> j
}
@tailrec private def pushUp(pos: Int): Unit = if(pos > 0) {
val ppos = (pos - 1) / 2
if(data(ppos) > data(pos)) {
swap(ppos, pos)
pushUp(ppos)
}
}
@tailrec private def pushDown(pos: Int): Unit = if(pos * 2 + 1 < data.length) {
if(data(pos) > data(pos * 2 + 1) &&
(pos * 2 + 2 >= data.length || data(pos * 2 + 1) <= data(pos * 2 + 2))) { // left is min
swap(pos, pos * 2 + 1)
pushDown(pos * 2 + 1)
} else if(pos * 2 + 2 < data.length && data(pos) > data(pos * 2 + 2)) {
swap(pos, pos * 2 + 2)
pushDown(pos * 2 + 2)
}
}
//override def seq = data
override def iterator = data.iterator
protected[this] override def newBuilder = new RamQueue[A]
override def orderedCompanion: GenericOrderedCompanion[RamQueue] = RamQueue
override def +=(a: A): this.type = {
data += a
map += a -> (data.length - 1)
pushUp(data.length - 1)
this
}
override def -=(a: A): this.type = {
map.get(a) map { pos =>
swap(pos, data.length - 1)
data.trimEnd(1)
map -= a
if(pos < data.length) {
if(a < data(pos)) pushDown(pos)
else if(a > data(pos)) pushUp(pos)
}
}
this
}
override def clear(): Unit = {
data.clear()
map = Map.empty
}
override def result = this
}
object RamQueue extends GenericOrderedCompanion[RamQueue] {
override def newBuilder[A](implicit ord: Ordering[A]) = new RamQueue[A]
}