Skip to content

Commit 762f5d8

Browse files
committed
add trees
1 parent 35f1661 commit 762f5d8

File tree

5 files changed

+326
-28
lines changed

5 files changed

+326
-28
lines changed

task4/src/main/kotlin/CoarseGrainedTree.kt

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package org.example
22

3-
import kotlinx.atomicfu.locks.reentrantLock
4-
import kotlinx.atomicfu.locks.withLock
3+
import kotlinx.coroutines.sync.Mutex
4+
import kotlinx.coroutines.sync.withLock
55

6-
class CoarseGrainedTree<K : Comparable<K>, V>: Tree<K, V> {
6+
class CoarseGrainedTree<K : Comparable<K>, V>: Tree<K, V>() {
77
private var root: TreeNode<K, V>? = null
8-
private val lock = reentrantLock()
8+
private val lock = Mutex()
99

10-
override fun insert(key: K, value: V) {
10+
override suspend fun insert(key: K, value: V) {
1111
lock.withLock {
1212
root = insertRec(root, key, value)
1313
}
@@ -27,7 +27,7 @@ class CoarseGrainedTree<K : Comparable<K>, V>: Tree<K, V> {
2727
return node
2828
}
2929

30-
override fun search(key: K): V? {
30+
override suspend fun search(key: K): V? {
3131
lock.withLock {
3232
return searchRec(root, key)
3333
}
@@ -44,7 +44,7 @@ class CoarseGrainedTree<K : Comparable<K>, V>: Tree<K, V> {
4444
}
4545
}
4646

47-
override fun delete(key: K) {
47+
override suspend fun delete(key: K) {
4848
lock.withLock {
4949
root = deleteRec(root, key)
5050
}
@@ -76,17 +76,4 @@ class CoarseGrainedTree<K : Comparable<K>, V>: Tree<K, V> {
7676
}
7777
return current
7878
}
79-
80-
override fun getKeys(): List<K> {
81-
val keys = mutableListOf<K>()
82-
inOrderTraversal(root, keys)
83-
return keys
84-
}
85-
86-
private fun inOrderTraversal(node: TreeNode<K, V>?, keys: MutableList<K>) {
87-
node ?: return
88-
inOrderTraversal(node.left, keys)
89-
keys.add(node.key)
90-
inOrderTraversal(node.right, keys)
91-
}
9279
}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package org.example
2+
3+
import kotlinx.coroutines.sync.Mutex
4+
5+
class FineGrainedTree<K : Comparable<K>, V>: Tree<K, V>() {
6+
private var root: TreeNode<K, V>? = null
7+
private val treeLock = Mutex()
8+
9+
private suspend fun searchAux(key: K): Pair<TreeNode<K, V>?, TreeNode<K, V>?> {
10+
treeLock.lock()
11+
root?.lock()
12+
var parent: TreeNode<K, V>? = null
13+
var current: TreeNode<K, V>? = root
14+
15+
while (current != null && current.key != key) {
16+
val next = if (key < current.key) current.left else current.right
17+
next?.lock()
18+
19+
// Снимаем блокировку с дедушки (или с дерева если деда нет)
20+
parent?.unlock() ?: treeLock.unlock()
21+
parent = current
22+
current = next
23+
}
24+
25+
return current to parent
26+
}
27+
28+
override suspend fun search(key: K): V? {
29+
val (node, parent) = searchAux(key)
30+
val value = node?.value
31+
node?.unlock()
32+
parent?.unlock() ?: treeLock.unlock()
33+
return value
34+
}
35+
36+
override suspend fun insert(key: K, value: V) {
37+
val (node, parent) = searchAux(key)
38+
when {
39+
parent == null -> {
40+
if (root == null) {
41+
root = TreeNode(key, value)
42+
} else {
43+
root!!.value = value
44+
}
45+
}
46+
node == null -> {
47+
val newNode = TreeNode(key, value)
48+
if (key < parent.key) {
49+
parent.left = newNode
50+
} else {
51+
parent.right = newNode
52+
}
53+
}
54+
else -> {
55+
node.value = value
56+
}
57+
}
58+
node?.unlock()
59+
parent?.unlock() ?: treeLock.unlock()
60+
}
61+
62+
override suspend fun delete(key: K) {
63+
val (node, parent) = searchAux(key)
64+
deleteRec(node, parent)
65+
}
66+
67+
private suspend fun deleteRec(node: TreeNode<K, V>?, parent: TreeNode<K, V>?): TreeNode<K, V>? {
68+
when {
69+
node == null -> {
70+
parent?.unlock() ?: treeLock.unlock()
71+
return parent
72+
}
73+
74+
// No children and 1 children case combined
75+
node.left == null || node.right == null -> {
76+
val child = node.left ?: node.right
77+
78+
if (parent == null) {
79+
root = child
80+
} else {
81+
if (node == parent.left) {
82+
parent.left = child
83+
} else {
84+
parent.right = child
85+
}
86+
}
87+
node.unlock()
88+
parent?.unlock() ?: treeLock.unlock()
89+
}
90+
91+
else -> {
92+
node.right?.lock()
93+
node.left?.lock()
94+
val right = node.right!!
95+
val left = node.left!!
96+
// right.lock()
97+
// left.lock()
98+
val (rightmostNode, rightmostNodeParent) = rightmostNode(left)
99+
rightmostNode.right = right
100+
101+
102+
if (parent == null) {
103+
root = left
104+
}
105+
else if (node == parent.left) {
106+
parent.left = left
107+
} else {
108+
parent.right = left
109+
}
110+
111+
rightmostNode.unlock()
112+
rightmostNodeParent?.unlock()
113+
114+
right.unlock()
115+
node.unlock()
116+
parent?.unlock() ?: treeLock.unlock()
117+
}
118+
}
119+
return parent
120+
}
121+
122+
private suspend fun rightmostNode(node: TreeNode<K, V>): Pair<TreeNode<K, V>, TreeNode<K, V>?> {
123+
var current = node
124+
var parent: TreeNode<K, V>? = null
125+
126+
while (current.right != null) {
127+
val next = current.right
128+
next?.lock()
129+
130+
parent?.unlock()
131+
parent = current
132+
current = checkNotNull(next)
133+
}
134+
135+
return current to parent
136+
137+
}
138+
}
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
package org.example
2+
3+
import kotlinx.coroutines.sync.Mutex
4+
5+
class OptimisticTree<K : Comparable<K>, V>: Tree<K, V>() {
6+
private var root: TreeNode<K, V>? = null
7+
private val treeLock = Mutex()
8+
9+
private suspend fun searchAux(key: K): Pair<TreeNode<K, V>?, TreeNode<K, V>?> {
10+
while (true) {
11+
var parent: TreeNode<K, V>? = null
12+
var current: TreeNode<K, V>? = root
13+
14+
while (current != null && current.key != key) {
15+
parent = current
16+
current = if (key < current.key) current.left else current.right
17+
}
18+
19+
parent?.lock()
20+
current?.lock()
21+
22+
// current is
23+
// 1. not found
24+
// 2. root
25+
if (current == null || parent == null) {
26+
return current to parent
27+
}
28+
29+
var validationParent: TreeNode<K, V>? = root
30+
while (parent != validationParent) {
31+
val key = checkNotNull(validationParent?.key)
32+
validationParent = if (key < parent.key) validationParent?.right else validationParent?.left
33+
// if (validationParent == null) {
34+
// // again
35+
// validationParent = root
36+
// }
37+
}
38+
39+
if (current == validationParent.left || current == validationParent.right) {
40+
return current to parent
41+
} else {
42+
// retry
43+
current.unlock()
44+
parent.unlock()
45+
// searchAux(key)
46+
}
47+
}
48+
}
49+
50+
override suspend fun search(key: K): V? {
51+
val (node, parent) = searchAux(key)
52+
val value = node?.value
53+
node?.unlock()
54+
parent?.unlock()
55+
return value
56+
}
57+
58+
override suspend fun insert(key: K, value: V) {
59+
val (node, parent) = searchAux(key)
60+
when {
61+
parent == null -> {
62+
if (root == null) {
63+
root = TreeNode(key, value)
64+
} else {
65+
root!!.value = value
66+
}
67+
}
68+
node == null -> {
69+
val newNode = TreeNode(key, value)
70+
if (key < parent.key) {
71+
parent.left = newNode
72+
} else {
73+
parent.right = newNode
74+
}
75+
}
76+
else -> {
77+
node.value = value
78+
}
79+
}
80+
node?.unlock()
81+
parent?.unlock()
82+
}
83+
84+
85+
override suspend fun delete(key: K) {
86+
val (node, parent) = searchAux(key)
87+
deleteRec(node, parent)
88+
}
89+
90+
private suspend fun deleteRec(node: TreeNode<K, V>?, parent: TreeNode<K, V>?): TreeNode<K, V>? {
91+
when {
92+
node == null -> {
93+
parent?.unlock() ?: treeLock.unlock()
94+
return parent
95+
}
96+
97+
// No children and 1 children case combined
98+
node.left == null || node.right == null -> {
99+
val child = node.left ?: node.right
100+
101+
if (parent == null) {
102+
root = child
103+
} else {
104+
if (node == parent.left) {
105+
parent.left = child
106+
} else {
107+
parent.right = child
108+
}
109+
}
110+
node.unlock()
111+
parent?.unlock() ?: treeLock.unlock()
112+
}
113+
114+
else -> {
115+
node.right?.lock()
116+
node.left?.lock()
117+
val right = node.right!!
118+
val left = node.left!!
119+
// right.lock()
120+
// left.lock()
121+
val (rightmostNode, rightmostNodeParent) = rightmostNode(left)
122+
rightmostNode.right = right
123+
124+
125+
if (parent == null) {
126+
root = left
127+
}
128+
else if (node == parent.left) {
129+
parent.left = left
130+
} else {
131+
parent.right = left
132+
}
133+
134+
rightmostNode.unlock()
135+
rightmostNodeParent?.unlock()
136+
137+
right.unlock()
138+
node.unlock()
139+
parent?.unlock() ?: treeLock.unlock()
140+
}
141+
}
142+
return parent
143+
}
144+
145+
private suspend fun rightmostNode(node: TreeNode<K, V>): Pair<TreeNode<K, V>, TreeNode<K, V>?> {
146+
var current = node
147+
var parent: TreeNode<K, V>? = null
148+
149+
while (current.right != null) {
150+
val next = current.right
151+
next?.lock()
152+
153+
parent?.unlock()
154+
parent = current
155+
current = checkNotNull(next)
156+
}
157+
158+
return current to parent
159+
160+
}
161+
}

task4/src/main/kotlin/Tree.kt

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
11
package org.example
22

3-
interface Tree<K : Comparable<K>, V> {
4-
fun insert(key: K, value: V)
5-
fun search(key: K): V?
6-
fun delete(key: K)
7-
fun getKeys(): List<K>
3+
abstract class Tree<K : Comparable<K>, V> {
4+
private var root: TreeNode<K, V>? = null
5+
6+
abstract suspend fun insert(key: K, value: V)
7+
abstract suspend fun search(key: K): V?
8+
abstract suspend fun delete(key: K)
9+
fun getKeys(): List<K> {
10+
fun inOrderTraversal(node: TreeNode<K, V>?, keys: MutableList<K>) {
11+
node ?: return
12+
inOrderTraversal(node.left, keys)
13+
keys.add(node.key)
14+
inOrderTraversal(node.right, keys)
15+
}
16+
val keys = mutableListOf<K>()
17+
inOrderTraversal(root, keys)
18+
return keys
19+
}
820
}

0 commit comments

Comments
 (0)