Browse Source

pkg/adt: document textbook implementation with pseudo-code

Signed-off-by: Gyuho Lee <leegyuho@amazon.com>
Gyuho Lee 6 years ago
parent
commit
3b631e1bb6
1 changed files with 233 additions and 6 deletions
  1. 233 6
      pkg/adt/interval_tree.go

+ 233 - 6
pkg/adt/interval_tree.go

@@ -211,14 +211,54 @@ type IntervalTree interface {
 
 // NewIntervalTree returns a new interval tree.
 func NewIntervalTree() IntervalTree {
-	return &intervalTree{}
+	return &intervalTree{
+		root:  nil,
+		count: 0,
+	}
 }
 
 type intervalTree struct {
 	root  *intervalNode
 	count int
+
+	// TODO: use 'sentinel' as a dummy object to simplify boundary conditions
+	// use the sentinel to treat a nil child of a node x as an ordinary node whose parent is x
+	// use one shared sentinel to represent all nil leaves and the root's parent
 }
 
+// TODO: make this consistent with textbook implementation
+//
+// "Introduction to Algorithms" (Cormen et al, 3rd ed.), chapter 13.4, p324
+//
+//	 0. RB-DELETE(T, z)
+//	 1.
+//	 2. y = z
+//	 3. y-original-color = y.color
+//	 4.
+//	 5. if z.left == T.nil
+//	 6. 	x = z.right
+//	 7. 	RB-TRANSPLANT(T, z, z.right)
+//	 8. else if z.right == T.nil
+//	 9. 	x = z.left
+//	10. 	RB-TRANSPLANT(T, z, z.left)
+//	11. else
+//	12. 	y = TREE-MINIMUM(z.right)
+//	13. 	y-original-color = y.color
+//	14. 	x = y.right
+//	15. 	if y.p == z
+//	16. 		x.p = y
+//	17. 	else
+//	18. 		RB-TRANSPLANT(T, y, y.right)
+//	19. 		y.right = z.right
+//	20. 		y.right.p = y
+//	21. 	RB-TRANSPLANT(T, z, y)
+//	22. 	y.left = z.left
+//	23. 	y.left.p = y
+//	24. 	y.color = z.color
+//	25.
+//	26. if y-original-color == BLACK
+//	27. 	RB-DELETE-FIXUP(T, x)
+
 // Delete removes the node with the given interval from the tree, returning
 // true if a node is in fact removed.
 func (ivt *intervalTree) Delete(ivl Interval) bool {
@@ -263,9 +303,53 @@ func (ivt *intervalTree) Delete(ivl Interval) bool {
 	return true
 }
 
+// "Introduction to Algorithms" (Cormen et al, 3rd ed.), chapter 13.4, p326
+//
+//	 0. RB-DELETE-FIXUP(T, z)
+//	 1.
+//	 2. while x ≠ T.root and x.color == BLACK
+//	 3. 	if x == x.p.left
+//	 4. 		w = x.p.right
+//	 5. 		if w.color == RED
+//	 6. 			w.color = BLACK
+//	 7. 			x.p.color = RED
+//	 8. 			LEFT-ROTATE(T, x, p)
+//	 9. 		if w.left.color == BLACK and w.right.color == BLACK
+//	10. 			w.color = RED
+//	11. 			x = x.p
+//	12. 		else if w.right.color == BLACK
+//	13. 				w.left.color = BLACK
+//	14. 				w.color = RED
+//	15. 				RIGHT-ROTATE(T, w)
+//	16. 				w = w.p.right
+//	17. 			w.color = x.p.color
+//	18. 			x.p.color = BLACK
+//	19. 			LEFT-ROTATE(T, w.p)
+//	20. 			x = T.root
+//	21. 	else
+//	22. 		w = x.p.left
+//	23. 		if w.color == RED
+//	24. 			w.color = BLACK
+//	25. 			x.p.color = RED
+//	26. 			RIGHT-ROTATE(T, x, p)
+//	27. 		if w.right.color == BLACK and w.left.color == BLACK
+//	28. 			w.color = RED
+//	29. 			x = x.p
+//	30. 		else if w.left.color == BLACK
+//	31. 				w.right.color = BLACK
+//	32. 				w.color = RED
+//	33. 				LEFT-ROTATE(T, w)
+//	34. 				w = w.p.left
+//	35. 			w.color = x.p.color
+//	36. 			x.p.color = BLACK
+//	37. 			RIGHT-ROTATE(T, w.p)
+//	38. 			x = T.root
+//	39.
+//	40. x.color = BLACK
+//
 func (ivt *intervalTree) deleteFixup(x *intervalNode) {
 	for x != ivt.root && x.color() == black && x.parent != nil {
-		if x == x.parent.left {
+		if x == x.parent.left { // line 3-20
 			w := x.parent.right
 			if w.color() == red {
 				w.c = black
@@ -292,7 +376,9 @@ func (ivt *intervalTree) deleteFixup(x *intervalNode) {
 				ivt.rotateLeft(x.parent)
 				x = ivt.root
 			}
-		} else {
+
+		} else { // line 22-38
+
 			// same as above but with left and right exchanged
 			w := x.parent.left
 			if w.color() == red {
@@ -322,15 +408,58 @@ func (ivt *intervalTree) deleteFixup(x *intervalNode) {
 			}
 		}
 	}
+
 	if x != nil {
 		x.c = black
 	}
 }
 
+func (ivt *intervalTree) createIntervalNode(ivl Interval, val interface{}) *intervalNode {
+	return &intervalNode{
+		iv:     IntervalValue{ivl, val},
+		max:    ivl.End,
+		c:      red,
+		left:   nil,
+		right:  nil,
+		parent: nil,
+	}
+}
+
+// TODO: make this consistent with textbook implementation
+//
+// "Introduction to Algorithms" (Cormen et al, 3rd ed.), chapter 13.3, p315
+//
+//	 0. RB-INSERT(T, z)
+//	 1.
+//	 2. y = T.nil
+//	 3. x = T.root
+//	 4.
+//	 5. while x ≠ T.nil
+//	 6. 	y = x
+//	 7. 	if z.key < x.key
+//	 8. 		x = x.left
+//	 9. 	else
+//	10. 		x = x.right
+//	11.
+//	12. z.p = y
+//	13.
+//	14. if y == T.nil
+//	15. 	T.root = z
+//	16. else if z.key < y.key
+//	17. 	y.left = z
+//	18. else
+//	19. 	y.right = z
+//	20.
+//	21. z.left = T.nil
+//	22. z.right = T.nil
+//	23. z.color = RED
+//	24.
+//	25. RB-INSERT-FIXUP(T, z)
+
 // Insert adds a node with the given interval into the tree.
 func (ivt *intervalTree) Insert(ivl Interval, val interface{}) {
 	var y *intervalNode
-	z := &intervalNode{iv: IntervalValue{ivl, val}, max: ivl.End, c: red}
+	z := ivt.createIntervalNode(ivl, val)
 	x := ivt.root
 	for x != nil {
 		y = x
@@ -353,13 +482,48 @@ func (ivt *intervalTree) Insert(ivl Interval, val interface{}) {
 		y.updateMax()
 	}
 	z.c = red
+
 	ivt.insertFixup(z)
 	ivt.count++
 }
 
+// "Introduction to Algorithms" (Cormen et al, 3rd ed.), chapter 13.3, p316
+//
+//	 0. RB-INSERT-FIXUP(T, z)
+//	 1.
+//	 2. while z.p.color == RED
+//	 3. 	if z.p == z.p.p.left
+//	 4. 		y = z.p.p.right
+//	 5. 		if y.color == RED
+//	 6. 			z.p.color = BLACK
+//	 7. 			y.color = BLACK
+//	 8. 			z.p.p.color = RED
+//	 9. 			z = z.p.p
+//	10. 		else if z == z.p.right
+//	11. 				z = z.p
+//	12. 				LEFT-ROTATE(T, z)
+//	13. 			z.p.color = BLACK
+//	14. 			z.p.p.color = RED
+//	15. 			RIGHT-ROTATE(T, z.p.p)
+//	16. 	else
+//	17. 		y = z.p.p.left
+//	18. 		if y.color == RED
+//	19. 			z.p.color = BLACK
+//	20. 			y.color = BLACK
+//	21. 			z.p.p.color = RED
+//	22. 			z = z.p.p
+//	23. 		else if z == z.p.right
+//	24. 				z = z.p
+//	25. 				RIGHT-ROTATE(T, z)
+//	26. 			z.p.color = BLACK
+//	27. 			z.p.p.color = RED
+//	28. 			LEFT-ROTATE(T, z.p.p)
+//	29.
+//	30. T.root.color = BLACK
+//
 func (ivt *intervalTree) insertFixup(z *intervalNode) {
 	for z.parent != nil && z.parent.parent != nil && z.parent.color() == red {
-		if z.parent == z.parent.parent.left {
+		if z.parent == z.parent.parent.left { // line 3-15
 			y := z.parent.parent.right
 			if y.color() == red {
 				y.c = black
@@ -375,7 +539,7 @@ func (ivt *intervalTree) insertFixup(z *intervalNode) {
 				z.parent.parent.c = red
 				ivt.rotateRight(z.parent.parent)
 			}
-		} else {
+		} else { // line 16-28
 			// same as then with left/right exchanged
 			y := z.parent.parent.left
 			if y.color() == red {
@@ -394,34 +558,97 @@ func (ivt *intervalTree) insertFixup(z *intervalNode) {
 			}
 		}
 	}
+
+	// line 30
 	ivt.root.c = black
 }
 
 // rotateLeft moves x so it is left of its right child
+//
+// "Introduction to Algorithms" (Cormen et al, 3rd ed.), chapter 13.2, p313
+//
+//	 0. LEFT-ROTATE(T, x)
+//	 1.
+//	 2. y = x.right
+//	 3. x.right = y.left
+//	 4.
+//	 5. if y.left ≠ T.nil
+//	 6. 	y.left.p = x
+//	 7.
+//	 8. y.p = x.p
+//	 9.
+//	10. if x.p == T.nil
+//	11. 	T.root = y
+//	12. else if x == x.p.left
+//	13. 	x.p.left = y
+//	14. else
+//	15. 	x.p.right = y
+//	16.
+//	17. y.left = x
+//	18. x.p = y
+//
 func (ivt *intervalTree) rotateLeft(x *intervalNode) {
+	// line 2-3
 	y := x.right
 	x.right = y.left
+
+	// line 5-6
 	if y.left != nil {
 		y.left.parent = x
 	}
+
 	x.updateMax()
+
+	// line 10-15, 18
 	ivt.replaceParent(x, y)
+
+	// line 17
 	y.left = x
 	y.updateMax()
 }
 
 // rotateRight moves x so it is right of its left child
+//
+//	 0. RIGHT-ROTATE(T, x)
+//	 1.
+//	 2. y = x.left
+//	 3. x.left = y.right
+//	 4.
+//	 5. if y.right ≠ T.nil
+//	 6. 	y.right.p = x
+//	 7.
+//	 8. y.p = x.p
+//	 9.
+//	10. if x.p == T.nil
+//	11. 	T.root = y
+//	12. else if x == x.p.right
+//	13. 	x.p.right = y
+//	14. else
+//	15. 	x.p.left = y
+//	16.
+//	17. y.right = x
+//	18. x.p = y
+//
 func (ivt *intervalTree) rotateRight(x *intervalNode) {
 	if x == nil {
 		return
 	}
+
+	// line 2-3
 	y := x.left
 	x.left = y.right
+
+	// line 5-6
 	if y.right != nil {
 		y.right.parent = x
 	}
+
 	x.updateMax()
+
+	// line 10-15, 18
 	ivt.replaceParent(x, y)
+
+	// line 17
 	y.right = x
 	y.updateMax()
 }