Skip to content
Snippets Groups Projects
Commit a94c85f3 authored by Ali Sinan Köksal's avatar Ali Sinan Köksal
Browse files

Some properties for red-black tree deletion (inconclusive for removeMax method).

parent 53bf1ea3
No related branches found
No related tags found
No related merge requests found
...@@ -14,10 +14,16 @@ object RedBlackTree { ...@@ -14,10 +14,16 @@ object RedBlackTree {
case class Node(color: Color, left: Tree, value: Int, right: Tree) extends Tree case class Node(color: Color, left: Tree, value: Int, right: Tree) extends Tree
def hasRedBlackNodes(t: Tree) : Boolean = t match { def hasRedBlackNodes(t: Tree) : Boolean = t match {
case Empty() => true case Empty() => true
case Node(Black(),l,_,r) => hasRedBlackNodes(l) && hasRedBlackNodes(r) case Node(Black(),l,_,r) => hasRedBlackNodes(l) && hasRedBlackNodes(r)
case Node(Red(),l,_,r) => hasRedBlackNodes(l) && hasRedBlackNodes(r) case Node(Red(),l,_,r) => hasRedBlackNodes(l) && hasRedBlackNodes(r)
case _ => false case _ => false
}
def hasRedBlackDesc(t: Tree) : Boolean = t match {
case Node(_,l,_,r) => hasRedBlackNodes(l) && hasRedBlackNodes(r)
case Empty() => true
case DoubleBlackEmpty() => true
} }
def content(t: Tree) : Set[Int] = t match { def content(t: Tree) : Set[Int] = t match {
...@@ -39,6 +45,11 @@ object RedBlackTree { ...@@ -39,6 +45,11 @@ object RedBlackTree {
case _ => false case _ => false
} }
def isNode(t: Tree) : Boolean = t match {
case Node(_,_,_,_) => true
case _ => false
}
def redNodesHaveBlackChildren(t: Tree) : Boolean = { def redNodesHaveBlackChildren(t: Tree) : Boolean = {
require(hasRedBlackNodes(t)) require(hasRedBlackNodes(t))
t match { t match {
...@@ -152,72 +163,93 @@ object RedBlackTree { ...@@ -152,72 +163,93 @@ object RedBlackTree {
} ensuring (res => content(res) == content(Node(c,a,x,b)) /*&& redDescHaveBlackChildren(res)*/) } ensuring (res => content(res) == content(Node(c,a,x,b)) /*&& redDescHaveBlackChildren(res)*/)
/* Deletion */ /* Deletion */
def incColor(c: Color) : Color = c match { def incColor(c: Color) : Color = {
// Could add precondition for not incrementing BB */ require(c != DoubleBlack())
case Black() => DoubleBlack() c match {
case Red() => Black() case Black() => DoubleBlack()
case NegativeBlack() => Red() case Red() => Black()
case DoubleBlack() => throw new Exception("Incrementing double black color") case NegativeBlack() => Red()
} // case DoubleBlack() => throw new Exception("Incrementing double black color")
}
} ensuring(_ != NegativeBlack())
def incColor(t: Tree) : Tree = t match { def incColor(t: Tree) : Tree = {
case Node(c, l, k, r) => Node(incColor(c), l, k, r) require(!isDoubleBlack(t))
case Empty() => DoubleBlackEmpty() t match {
case _ => throw new Exception("Incrementing double black leaf") case Node(c, l, k, r) => Node(incColor(c), l, k, r)
} case Empty() => DoubleBlackEmpty()
// case _ => throw new Exception("Incrementing double black leaf")
}
} ensuring(!isNegativeBlack(_))
def decColor(c: Color) : Color = c match { def decColor(c: Color) : Color = {
case DoubleBlack() => Black() require(c != NegativeBlack())
case Black() => Red() c match {
case Red() => NegativeBlack() case DoubleBlack() => Black()
case NegativeBlack() => throw new Exception("Decrementing negative black color") case Black() => Red()
} case Red() => NegativeBlack()
// case NegativeBlack() => throw new Exception("Decrementing negative black color")
}
} ensuring(_ != DoubleBlack())
def decColor(t: Tree) : Tree = t match { def decColor(t: Tree) : Tree = {
case Node(c, l, k, r) => Node(decColor(c), l, k, r) require(!isNegativeBlack(t) && t != Empty())
case DoubleBlackEmpty() => Empty() t match {
case _ => throw new Exception("Decrementing black leaf") case Node(c, l, k, r) => Node(decColor(c), l, k, r)
} case DoubleBlackEmpty() => Empty()
// case _ => throw new Exception("Decrementing black leaf")
}
} ensuring(!isDoubleBlack(_))
def del(node: Tree, key: Int) : Tree = { def del(node: Tree, key: Int) : Tree = {
require(redNodesHaveBlackChildren(node) && hasRedBlackNodes(node))
node match { node match {
case Node(c, l, k, r) => case Node(c, l, k, r) =>
if (key < k) bubble(c, del(l, key), k, r) if (key < k) bubble(c, del(l, key), k, r)
else if (key == k) remove(node) else if (key == k) remove(node)
else bubble(c, l, k, del(r, key)) else bubble(c, l, k, del(r, key))
case _ => node case _ => node
} }
} } ensuring(res => redNodesHaveBlackChildren(res) && hasRedBlackNodes(res))
def max(t: Tree) : Int = t match { def max(t: Tree) : Int = {
case Node(c, l, k, r @ Node(cr, lr, kr, rr)) => max(r) require(isNode(t))
case Node(c, l, k, r) => k t match {
case _ => throw new Exception("Searching for max in a leaf") case Node(c, l, k, r @ Node(cr, lr, kr, rr)) => max(r)
case Node(c, l, k, r) => k
// case _ => throw new Exception("Searching for max in a leaf")
}
} }
// note: there are unnecessary cases in Racket code file // note: there are unnecessary cases in Racket code file
def remove(node: Tree) : Tree = node match { def remove(node: Tree) : Tree = {
// Leaves are easy to kill: require(redNodesHaveBlackChildren(node) && hasRedBlackNodes(node))
case Node(Red(), Empty(), k, Empty()) => Empty() node match {
case Node(Black(), Empty(), k, Empty()) => DoubleBlackEmpty() // Leaves are easy to kill:
case Node(Red(), Empty(), k, Empty()) => Empty()
// Killing a node with one child: case Node(Black(), Empty(), k, Empty()) => DoubleBlackEmpty()
case Node(Black(), Node(Red(), l, k, r), _, Empty()) => Node(Black(), l, k, r)
case Node(Black(), Empty(), _, Node(Red(), l, k, r)) => Node(Black(), l, k, r)
// Killing a node with two sub-trees:
case Node(c, l @ Node(_, _, _, _), _, r @ Node(_, _, _, _)) =>
val maxV = max(l)
val newL = removeMax(l)
bubble(c, newL, maxV, r)
case _ => throw new Exception("Removing an unexpected tree")
}
def removeMax(node: Tree) : Tree = node match { // Killing a node with one child:
case Node(_, l, _, Empty()) => remove(node) case Node(Black(), Node(Red(), l, k, r), _, Empty()) => Node(Black(), l, k, r)
case Node(c, l, k, r) => bubble(c, l, k, removeMax(r)) case Node(Black(), Empty(), _, Node(Red(), l, k, r)) => Node(Black(), l, k, r)
case _ => throw new Exception("Removing max from a leaf")
} // Killing a node with two sub-trees:
case Node(c, l @ Node(_, _, _, _), _, r @ Node(_, _, _, _)) =>
val maxV = max(l)
val newL = removeMax(l)
bubble(c, newL, maxV, r)
case _ => throw new Exception("Removing an unexpected tree")
}
} ensuring(res => hasRedBlackDesc(res))
def removeMax(node: Tree) : Tree = {
require(redNodesHaveBlackChildren(node) && isNode(node) && hasRedBlackNodes(node))
node match {
case Node(_, l, _, Empty()) => remove(node)
case Node(c, l, k, r) => bubble(c, l, k, removeMax(r))
// case _ => throw new Exception("Removing max from a leaf")
}
} ensuring(res => redNodesHaveBlackChildren(res))
def isDoubleBlack(t: Tree) : Boolean = t match { def isDoubleBlack(t: Tree) : Boolean = t match {
case DoubleBlackEmpty() => true case DoubleBlackEmpty() => true
...@@ -225,6 +257,11 @@ object RedBlackTree { ...@@ -225,6 +257,11 @@ object RedBlackTree {
case _ => false case _ => false
} }
def isNegativeBlack(t: Tree) : Boolean = t match {
case Node(NegativeBlack(), _, _, _) => true
case _ => false
}
def bubble(c: Color, l: Tree, k: Int, r: Tree) : Tree = { def bubble(c: Color, l: Tree, k: Int, r: Tree) : Tree = {
if (isDoubleBlack(l) || isDoubleBlack(r)) { if (isDoubleBlack(l) || isDoubleBlack(r)) {
balance(incColor(c), decColor(l), k, decColor(r)) balance(incColor(c), decColor(l), k, decColor(r))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment