0% found this document useful (0 votes)
5 views15 pages

2015 Conc

Uploaded by

Rudi Theunissen
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views15 pages

2015 Conc

Uploaded by

Rudi Theunissen
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 15

O(log n)

O(1)

3⇥

(0 until 1000000).toPar.map(x => x + 1)

sum

def sum(xs: List[Int]) = def sum(xs: Conc[Int]) =


xs match { xs match {
case head :: tail => case ls <> rs =>
head + sum(tail) sum(ls) + sum(rs)
case Nil => 0 } case Single(x) => x }
sum xs
head tail
head tail
sum xs ls rs
xs
sum

O(log n)
O(log n)
O(1)

3⇥

Conc
List
Nil :: Conc
Empty Single
<>
Conc
level
level 0 Empty Single 1
<> size Conc
abstract class Conc[+T] { case class Single[T](x: T)
def level: Int extends Leaf[T] {
def size: Int def level = 0
def left: Conc[T] def size = 1
def right: Conc[T] }
def normalized = this }
case class <>[T](
abstract class Leaf[T] left: Conc[T], right: Conc[T]
extends Conc[T] { ) extends Conc[T] {
def left = error() val level =
def right = error() } 1 + max(left.level,
right.level)
case object Empty val size =
extends Leaf[Nothing] { left.size + right.size
def level = 0 }
def size = 0 }

size level
<>
Conc
normalized
normalized

Empty
<> Empty
<>

(0 until n).foldLeft(Empty: Conc[Int]) {


(tree, x) => new <>(tree, new Single(x))
}

level 1

<>
S(level) = 2level
n = S(level) level = log2 n
<> level
|lef t.level right.level| = 1 level

S(level) = S(level 1) + S(level 2), S(0) = 1

p p
1 1 + 5 level 1 1 5 level
S(level) = p ( ) p ( )
5 2 5 2
p
level = log 1+p5 n + log 1+p5 5
2 2

O(log n)

O(log n)

def apply(xs: Conc[T], i: Int) = xs match {


case Single(x) => x
case left <> right =>
if (i < left.size) apply(left, i)
else apply(right, i - left.size) }
def update(xs: Conc[T], i: Int, y: T) =
xs match {
case Single(x) => Single(y)
case left <> right if i < left.size =>
new <>(update(left, i, y), right)
case left <> right =>
val ni = i - left.size
new <>(left, update(right, ni, y)) }
update
i y

O(log n) insert
<>
xs <> ys
new <>(xs, ys)
<>

<>

concat

level
1
level 1

concat
Single
xs ys
level level xs
ys
<>
level
xs ys xs
ys xs
def <>[T](xs: Conc[T], ys: Conc[T]) = {
if (xs == Empty) ys
else if (ys == Empty) xs
else concat(xs.normalized, ys.normalized) }
def concat[T](xs: Conc[T], ys: Conc[T]) = {
val diff = ys.level - xs.level
if (abs(diff) <= 1) new <>(xs, ys)
else if (diff < -1) {
if (xs.left.level >= xs.right.level) {
val nr = concat(xs.right, ys)
new <>(xs.left, nr)
} else {
val nrr = concat(xs.right.right, ys)
if (nrr.level == xs.level - 3) {
val nr = new <>(xs.right.left, nrr)
new <>(xs.left, nr)
} else {
val nl = new <>(xs.left, xs.right.left)
new <>(nl, nrr)
} }
} else {
if (ys.right.level >= ys.left.level) {
val nl = concat(xs, ys.left)
new <>(nl, ys.right)
} else {
val nll = concat(xs, ys.left.left)
if (nll.level == ys.level - 3) {
val nl = new <>(nll, ys.left.right)
new <>(nl, ys.right)
} else {
val nr = new <>(ys.left.right, ys.right)
new <>(nll, nr)
} } } }

xs.left.level >= xs.right.level


xs xs.right <> ys
1
level xs.left xs.right <> ys 1

xs.left.level < xs.right.level


xs.right.right ys
xs.level - 2 xs.level - 3
nrr xs.level - 3
xs.level - 1 nrr.level xs.level - 3
xs.right.left xs.level - 2
nrr xs.right.left
xs.left xs.right.left
1

h1 h2 h |h max(h1 , h2 )|  1

h1 h2 O(|h1 h2 |)
O(1)
concat
concat concat
1 2 3 concat
1
concat O(|xslevel yslevel |) t
u

insert

insert
def insert[T](xs: Conc[T], i: Int, y: T) =
xs match {
case Single(x) =>
if (i == 0) new <>(Single(y), xs)
else new <>(xs, Single(y))
case left <> right if i < left.size =>
insert(left, i, y) <> right
case left <> right =>
left <> insert(right, i - left.size, y) }

O(1)
O(log n)
O(log n) split insert
O(log n)
Single

def <>[T](xs: Conc[T], x: T) = xs <> Single(x)

O(log n)
O(1)
append
O(log n)

O(log n)
Append
<> Append
left right
Append
right Append Append
Append Empty Append
Append Append
Nil

<> Append
case class Append[T](left: Conc[T], right: Conc[T])
extends Conc[T] {
val level = 1 + left.level.max(right.level)
val size = left.size + right.size
override def normalized = wrap(left, right)
}
def wrap[T](xs: Conc[T], ys: Conc[T]) =
xs match {
case Append(ws, zs) => wrap(ws, zs <> ys)
case xs => xs <> ys
}
normalized

normalized Append wrap


Append

concat normalized
O(log n) normalized O(log n)

concat O(log n)

Append

def append[T](xs: Conc[T], ys: Single[T]) = new Append(xs, ys)


+ =

⇧ )

append
normalized n
normalized O(n log n)
append append
concat
append
level

level <>

n O(n)
1 O(1)
O(log n)
n Single O(n)
level
O(1)
Append a
Append b a.right.level < b.right.level
Append
2level

Append
append O(1)

level

O(log n)
O(log n)

O(log n) y z
t⇤ xyzs⇤
x O(log n)
O(log n)
O(log n)
def append[T](xs: Conc[T], ys: Leaf[T]) =
xs match {
case Empty => ys
case xs: Leaf[T] => new <>(xs, ys)
case _ <> _ => new Append(xs, ys)
case xs: Append[T] => append(xs, ys) }
private def append[T](xs: Append[T], ys: Conc[T]) =
if (xs.right.level > ys.level) new Append(xs, ys)
else {
val zs = new <>(xs.right, ys)
xs.left match {
case ws @ Append(_, _) =>
append(ws, zs)
case ws =>
if (ws.level <= xs.level) ws <> zs
else new Append(ws, zs) } }

append Leaf Single

foreach

Leaf Chunk

+=

case class Chunk[T](xs: Array[T], size: Int, k: Int)


extends Leaf[T] { def level = 0 }

Chunk xs size
k Chunk insert
Chunk
Chunk size k remove
Chunk

append

O(1)
O(log n)

O(1)
class ConcBuffer[T](val k: Int) {
private var conc: Conc[T] = Empty
private var ch: Array[T] = new Array(k)
private var lastSize: Int = 0
def +=(elem: T) {
if (lastSize >= k) expand()
ch(lastSize) = elem
lastSize += 1 }
private def expand() {
conc = append(conc, new Chunk(ch, lastSize, k))
ch = new Array(k)
lastSize = 0 } }

O(1)

ConcBuffer

Chunk
O(1)

Chunk
k Conc
expand
ConcBuffer ArrayList
vector

O(n) ArrayBuffer
ArrayList vector

O(1)

2
foreach
foreach

Chunk
k = 128 2⇥
k 128

2⇥

4⇥

104

log

Vector

Chunk

Chunk

50%
Single Chunk
6 6
ms

ms
4 4

2 2

0 0
0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 0.2 0.4 0.6 0.8 1 1.2 1.4 1.6
·105 ·106
30
8
ms

ms
20 6

4
10

0
0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 0.2 0.4 0.6 0.8 1 1.2 1.4 1.6
·105 ·106

10
ms

ms

101

0 100

0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 0.2 0.4 0.6 0.8 1 1.2 1.4 1.6
·105 ·106

101 8,000
ms

kB

100 6,000

1
10 4,000

2
10
2,000
3
10
0
0 0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 0 0.2 0.4 0.6 0.8 1 1.2 1.4 1.6
·105 ·106
20
15
ms

ms

15
10
10

5
5

0 0
0 0.5 1 1.5 2 2.5 3 0 0.5 1 1.5 2 2.5 3
·106 ·106

foreach Chunk foreach Chunk append Chunk


append Chunk prepend Chunk
map
map

x => x + 1

map

2 3⇥

ArrayList vector
O(1)
O(1)
O(1)

O(n)
O(n)
O(log n)

O(log n)

O(log n)
n1
O(log n2 )
O(1)

3 4⇥
20 50%

3⇥
View publication stats

You might also like