Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix RB #57

Merged
merged 4 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 88 additions & 108 deletions lib/src/main/kotlin/trees/RBSearchTree.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,23 @@ import main.vertexes.RBVertex
* @property root The root vertex of the tree.
*/
class RBSearchTree<K, V> : AbstractBinarySearchTree<K, V, RBVertex<K, V>> {
private val red = RBVertex.Color.RED
private val black = RBVertex.Color.BLACK

/**
* This method removes the vertex with the given key from the tree and returns its associated value,
* maintaining the properties of the red-black tree.
*
* 4 cases we need to look at:
*
* 1) remove red vertex with 0 children -> just remove vetrex
* 1) remove red vertex with 0 children -> just remove vertex
*
* 2) remove red or black vertex with 2 children ->
* find min vertex on the right subtree and swap it's key and value with
* key and value of vertex that we need to remove.
* Now we can work with vertex which has 1 or 0 children
*
* 3) remove black vetrex with 1 child -> child can be only red
* 3) remove black vertex with 1 child -> child can be only red
* so we just swap child's key and value with key and value that we need to remove
* and look at case 1)
*
Expand Down Expand Up @@ -75,7 +78,7 @@ class RBSearchTree<K, V> : AbstractBinarySearchTree<K, V, RBVertex<K, V>> {
private fun needToBalance(vertex: RBVertex<K, V>): Boolean {
when (countChildren(vertex)) {
0 -> {
if (vertex.isRed) {
if (vertex.color == red) {
replaceVertexBy(vertex, null)
return false
}
Expand Down Expand Up @@ -127,79 +130,71 @@ class RBSearchTree<K, V> : AbstractBinarySearchTree<K, V, RBVertex<K, V>> {
*/
private fun balanceAfterRemove(vertex: RBVertex<K, V>?) {
var currentVertex = vertex
while (currentVertex != root && (currentVertex?.isRed == false || currentVertex == null)) {
var brother: RBVertex<K, V>?
if (currentVertex == currentVertex?.parent?.leftSon) {
brother = currentVertex?.parent?.rightSon

if (brother?.isRed == true) {
brother.isRed = false
currentVertex?.parent?.isRed = true
val vertexForRotate = currentVertex?.parent
vertexForRotate?.let { rotateLeft(vertexForRotate) }
brother = currentVertex?.parent?.rightSon
}

if ((brother?.leftSon?.isRed == false || brother?.leftSon == null) &&
(brother?.rightSon?.isRed == false || brother?.rightSon == null)
) {
brother?.isRed = true
currentVertex = currentVertex?.parent
if (vertex == currentVertex?.leftSon) currentVertex?.leftSon = null
} else {
if (brother.rightSon?.isRed == false || brother.rightSon == null) {
brother.leftSon?.isRed = false
brother.isRed = true
rotateRight(brother)
while (currentVertex != root && (currentVertex?.color == black || currentVertex == null)) {
val isBrotherRightSon = (currentVertex == currentVertex?.parent?.leftSon)
var brother: RBVertex<K, V>? = if (isBrotherRightSon) currentVertex?.parent?.rightSon else currentVertex?.parent?.leftSon

if (brother?.color == red) {
brother.color = black
currentVertex?.parent?.color = red
val vertexForRotate = currentVertex?.parent

when (isBrotherRightSon) {
true -> {
vertexForRotate?.let { rotateLeft(vertexForRotate) }
brother = currentVertex?.parent?.rightSon
} else -> {
vertexForRotate?.let { rotateRight(vertexForRotate) }
brother = currentVertex?.parent?.leftSon
}
}
}

if ((brother?.leftSon?.color == black || brother?.leftSon == null) &&
(brother?.rightSon?.color == black || brother?.rightSon == null)
) {
brother?.color = red
currentVertex = currentVertex?.parent

val parentColor = currentVertex?.parent?.isRed
parentColor?.let { brother?.isRed = parentColor }
currentVertex?.parent?.isRed = false
brother?.rightSon?.isRed = false
val vertexForRotate = currentVertex?.parent
vertexForRotate?.let { rotateLeft(vertexForRotate) }
if (currentVertex == vertex) currentVertex?.parent?.leftSon = null
currentVertex = root
when (vertex) {
currentVertex?.leftSon -> currentVertex?.leftSon = null
currentVertex?.rightSon -> currentVertex?.rightSon = null
}
} else {
brother = currentVertex?.parent?.leftSon
if ((isBrotherRightSon) && (brother.rightSon?.color == black || brother.rightSon == null)) {
brother.leftSon?.color = black
brother.color = red
rotateRight(brother)
brother = currentVertex?.parent?.rightSon
}

if (brother?.isRed == true) {
brother.isRed = false
currentVertex?.parent?.isRed = true
val vertexForRotate = currentVertex?.parent
vertexForRotate?.let { rotateRight(vertexForRotate) }
else if ((!isBrotherRightSon) && (brother.leftSon?.color == black || brother.leftSon == null)) {
brother.rightSon?.color = black
brother.color = red
rotateLeft(brother)
brother = currentVertex?.parent?.leftSon
}

if ((brother?.leftSon?.isRed == false || brother?.leftSon == null) &&
(brother?.rightSon?.isRed == false || brother?.rightSon == null)
) {
brother?.isRed = true
currentVertex = currentVertex?.parent
if (vertex == currentVertex?.rightSon) currentVertex?.rightSon = null
} else {
if (brother.leftSon?.isRed == false || brother.leftSon == null) {
brother.rightSon?.isRed = false
brother.isRed = true
rotateLeft(brother)
brother = currentVertex?.parent?.leftSon
val parentColor = currentVertex?.parent?.color
parentColor?.let { brother?.color = parentColor }
currentVertex?.parent?.color = black
val vertexForRotate = currentVertex?.parent

when (isBrotherRightSon) {
true -> {
brother?.rightSon?.color = black
vertexForRotate?.let { rotateLeft(vertexForRotate) }
if (currentVertex == vertex) currentVertex?.parent?.leftSon = null
} else -> {
brother?.leftSon?.color = black
vertexForRotate?.let { rotateRight(vertexForRotate) }
if (currentVertex == vertex) currentVertex?.parent?.rightSon = null
}

val parentColor = currentVertex?.parent?.isRed
parentColor?.let { brother?.isRed = parentColor }
currentVertex?.parent?.isRed = false
brother?.leftSon?.isRed = false
val vertexForRotate = currentVertex?.parent
vertexForRotate?.let { rotateRight(vertexForRotate) }
if (currentVertex == vertex) currentVertex?.parent?.rightSon = null
currentVertex = root
}
currentVertex = root
}
}
currentVertex?.isRed = false
currentVertex?.color = black
}

/**
Expand Down Expand Up @@ -265,7 +260,7 @@ class RBSearchTree<K, V> : AbstractBinarySearchTree<K, V, RBVertex<K, V>> {
}

if (currentVertex == null) {
currentVertex = RBVertex(key, value, null, null, true, parent)
currentVertex = RBVertex(key, value, null, null, red, parent)
if (root == null) {
root = currentVertex
} else if (isLeft) {
Expand Down Expand Up @@ -295,50 +290,34 @@ class RBSearchTree<K, V> : AbstractBinarySearchTree<K, V, RBVertex<K, V>> {
private fun balanceAfterPut(vertex: RBVertex<K, V>) {
var currentVertex = vertex

while (currentVertex.parent?.isRed == true) {
while (currentVertex.parent?.color == red) {
val grandparent = currentVertex.parent?.parent

if (currentVertex.parent == grandparent?.leftSon) {
val uncle = grandparent?.rightSon

if (uncle?.isRed == true) {
currentVertex.parent?.isRed = false
uncle.isRed = false
grandparent.isRed = true
currentVertex = grandparent
} else {
if (currentVertex == currentVertex.parent?.rightSon) {
currentVertex = currentVertex.parent ?: currentVertex
rotateLeft(currentVertex)
}

currentVertex.parent?.isRed = false
currentVertex.parent?.parent?.isRed = true
val vertexForRightRotate = currentVertex.parent?.parent
vertexForRightRotate?.let { rotateRight(vertexForRightRotate) }
}
val isUncleRightSon = (currentVertex.parent == grandparent?.leftSon)
val uncle = if (isUncleRightSon) grandparent?.rightSon else grandparent?.leftSon

if (uncle?.color == red) {
currentVertex.parent?.color = black
uncle.color = black
grandparent?.color = red
currentVertex = grandparent ?: currentVertex
} else {
val uncle = grandparent?.leftSon

if (uncle?.isRed == true) {
currentVertex.parent?.isRed = false
uncle.isRed = false
grandparent.isRed = true
currentVertex = grandparent
} else {
if (currentVertex == currentVertex.parent?.leftSon) {
currentVertex = currentVertex.parent ?: currentVertex
rotateRight(currentVertex)
}
if ((isUncleRightSon) && (currentVertex == currentVertex.parent?.rightSon)) {
currentVertex = currentVertex.parent ?: currentVertex
rotateLeft(currentVertex)
}

currentVertex.parent?.isRed = false
currentVertex.parent?.parent?.isRed = true
val vertexForLeftRotate = currentVertex.parent?.parent
vertexForLeftRotate?.let { rotateLeft(vertexForLeftRotate) }
else if ((!isUncleRightSon) && (currentVertex == currentVertex.parent?.leftSon)) {
currentVertex = currentVertex.parent ?: currentVertex
rotateRight(currentVertex)
}

currentVertex.parent?.color = black
currentVertex.parent?.parent?.color = red
val vertexForRotate = currentVertex.parent?.parent
vertexForRotate?.let { if (isUncleRightSon) rotateRight(vertexForRotate) else rotateLeft(vertexForRotate) }
}
}
root?.isRed = false
root?.color = black
}

/**
Expand Down Expand Up @@ -421,17 +400,18 @@ class RBSearchTree<K, V> : AbstractBinarySearchTree<K, V, RBVertex<K, V>> {
* Constructs a new binary search tree with the specified comparator.
* @param comparator the comparator to use for comparing keys, or null to use natural ordering
*/
constructor(comparator: Comparator<K>? = null) : super(comparator)
constructor(comparator: Comparator<K>? = null) {
this.comparator = comparator
}

/**
* Constructs a new binary search tree and initializes it with the mappings from the specified map.
* @param map the map whose mappings are to be added to this tree
* @param replaceIfExists if true, replaces the value if the key already exists, otherwise ignores it
* @param comparator the comparator to use for comparing keys, or null to use natural ordering
*/
constructor(map: Map<K, V>, replaceIfExists: Boolean = true, comparator: Comparator<K>? = null) : super(
map,
replaceIfExists,
comparator,
)
constructor(map: Map<K, V>, replaceIfExists: Boolean = true, comparator: Comparator<K>? = null) {
this.comparator = comparator
putAll(map, replaceIfExists)
}
}
14 changes: 9 additions & 5 deletions lib/src/main/kotlin/vertexes/RBVertex.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package main.vertexes
* @param V Type of values.
* @property key The key associated with this vertex.
* @property value The value associated with this vertex.
* @property isRed A boolean indicating whether this vertex is red.
* @property color The color of this vertex (red or black).
* @property parent The parent vertex of this vertex.
* @property leftSon The left child vertex of this vertex.
* @property rightSon The right child vertex of this vertex.
Expand All @@ -15,7 +15,11 @@ class RBVertex<K, V>(
override var key: K,
override var value: V,
) : InterfaceBSTVertex<K, V, RBVertex<K, V>> {
var isRed = true
enum class Color {
RED,
BLACK
}
var color: Color = Color.RED
var parent: RBVertex<K, V>? = null
override var leftSon: RBVertex<K, V>? = null
override var rightSon: RBVertex<K, V>? = null
Expand All @@ -26,20 +30,20 @@ class RBVertex<K, V>(
* @param value The value associated with this vertex.
* @param leftSon The left child vertex of this vertex.
* @param rightSon The right child vertex of this vertex.
* @param isRed A boolean indicating whether this vertex is red.
* @param color The color of this vertex (red or black).
* @param parent The parent vertex of this vertex.
*/
constructor(
key: K,
value: V,
leftSon: RBVertex<K, V>?,
rightSon: RBVertex<K, V>?,
isRed: Boolean,
color: Color,
parent: RBVertex<K, V>?,
) : this(key, value) {
this.leftSon = leftSon
this.rightSon = rightSon
this.parent = parent
this.isRed = isRed
this.color = color
}
}
Loading