mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
pkg/adt: document textbook implementation with pseudo-code
Signed-off-by: Gyuho Lee <leegyuho@amazon.com>
This commit is contained in:
parent
456c91b63a
commit
3b631e1bb6
@ -211,14 +211,54 @@ type IntervalTree interface {
|
|||||||
|
|
||||||
// NewIntervalTree returns a new interval tree.
|
// NewIntervalTree returns a new interval tree.
|
||||||
func NewIntervalTree() IntervalTree {
|
func NewIntervalTree() IntervalTree {
|
||||||
return &intervalTree{}
|
return &intervalTree{
|
||||||
|
root: nil,
|
||||||
|
count: 0,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type intervalTree struct {
|
type intervalTree struct {
|
||||||
root *intervalNode
|
root *intervalNode
|
||||||
count int
|
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
|
// Delete removes the node with the given interval from the tree, returning
|
||||||
// true if a node is in fact removed.
|
// true if a node is in fact removed.
|
||||||
func (ivt *intervalTree) Delete(ivl Interval) bool {
|
func (ivt *intervalTree) Delete(ivl Interval) bool {
|
||||||
@ -263,9 +303,53 @@ func (ivt *intervalTree) Delete(ivl Interval) bool {
|
|||||||
return true
|
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) {
|
func (ivt *intervalTree) deleteFixup(x *intervalNode) {
|
||||||
for x != ivt.root && x.color() == black && x.parent != nil {
|
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
|
w := x.parent.right
|
||||||
if w.color() == red {
|
if w.color() == red {
|
||||||
w.c = black
|
w.c = black
|
||||||
@ -292,7 +376,9 @@ func (ivt *intervalTree) deleteFixup(x *intervalNode) {
|
|||||||
ivt.rotateLeft(x.parent)
|
ivt.rotateLeft(x.parent)
|
||||||
x = ivt.root
|
x = ivt.root
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
|
} else { // line 22-38
|
||||||
|
|
||||||
// same as above but with left and right exchanged
|
// same as above but with left and right exchanged
|
||||||
w := x.parent.left
|
w := x.parent.left
|
||||||
if w.color() == red {
|
if w.color() == red {
|
||||||
@ -322,15 +408,58 @@ func (ivt *intervalTree) deleteFixup(x *intervalNode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if x != nil {
|
if x != nil {
|
||||||
x.c = black
|
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.
|
// Insert adds a node with the given interval into the tree.
|
||||||
func (ivt *intervalTree) Insert(ivl Interval, val interface{}) {
|
func (ivt *intervalTree) Insert(ivl Interval, val interface{}) {
|
||||||
var y *intervalNode
|
var y *intervalNode
|
||||||
z := &intervalNode{iv: IntervalValue{ivl, val}, max: ivl.End, c: red}
|
z := ivt.createIntervalNode(ivl, val)
|
||||||
x := ivt.root
|
x := ivt.root
|
||||||
for x != nil {
|
for x != nil {
|
||||||
y = x
|
y = x
|
||||||
@ -353,13 +482,48 @@ func (ivt *intervalTree) Insert(ivl Interval, val interface{}) {
|
|||||||
y.updateMax()
|
y.updateMax()
|
||||||
}
|
}
|
||||||
z.c = red
|
z.c = red
|
||||||
|
|
||||||
ivt.insertFixup(z)
|
ivt.insertFixup(z)
|
||||||
ivt.count++
|
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) {
|
func (ivt *intervalTree) insertFixup(z *intervalNode) {
|
||||||
for z.parent != nil && z.parent.parent != nil && z.parent.color() == red {
|
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
|
y := z.parent.parent.right
|
||||||
if y.color() == red {
|
if y.color() == red {
|
||||||
y.c = black
|
y.c = black
|
||||||
@ -375,7 +539,7 @@ func (ivt *intervalTree) insertFixup(z *intervalNode) {
|
|||||||
z.parent.parent.c = red
|
z.parent.parent.c = red
|
||||||
ivt.rotateRight(z.parent.parent)
|
ivt.rotateRight(z.parent.parent)
|
||||||
}
|
}
|
||||||
} else {
|
} else { // line 16-28
|
||||||
// same as then with left/right exchanged
|
// same as then with left/right exchanged
|
||||||
y := z.parent.parent.left
|
y := z.parent.parent.left
|
||||||
if y.color() == red {
|
if y.color() == red {
|
||||||
@ -394,34 +558,97 @@ func (ivt *intervalTree) insertFixup(z *intervalNode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// line 30
|
||||||
ivt.root.c = black
|
ivt.root.c = black
|
||||||
}
|
}
|
||||||
|
|
||||||
// rotateLeft moves x so it is left of its right child
|
// 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) {
|
func (ivt *intervalTree) rotateLeft(x *intervalNode) {
|
||||||
|
// line 2-3
|
||||||
y := x.right
|
y := x.right
|
||||||
x.right = y.left
|
x.right = y.left
|
||||||
|
|
||||||
|
// line 5-6
|
||||||
if y.left != nil {
|
if y.left != nil {
|
||||||
y.left.parent = x
|
y.left.parent = x
|
||||||
}
|
}
|
||||||
|
|
||||||
x.updateMax()
|
x.updateMax()
|
||||||
|
|
||||||
|
// line 10-15, 18
|
||||||
ivt.replaceParent(x, y)
|
ivt.replaceParent(x, y)
|
||||||
|
|
||||||
|
// line 17
|
||||||
y.left = x
|
y.left = x
|
||||||
y.updateMax()
|
y.updateMax()
|
||||||
}
|
}
|
||||||
|
|
||||||
// rotateRight moves x so it is right of its left child
|
// 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) {
|
func (ivt *intervalTree) rotateRight(x *intervalNode) {
|
||||||
if x == nil {
|
if x == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// line 2-3
|
||||||
y := x.left
|
y := x.left
|
||||||
x.left = y.right
|
x.left = y.right
|
||||||
|
|
||||||
|
// line 5-6
|
||||||
if y.right != nil {
|
if y.right != nil {
|
||||||
y.right.parent = x
|
y.right.parent = x
|
||||||
}
|
}
|
||||||
|
|
||||||
x.updateMax()
|
x.updateMax()
|
||||||
|
|
||||||
|
// line 10-15, 18
|
||||||
ivt.replaceParent(x, y)
|
ivt.replaceParent(x, y)
|
||||||
|
|
||||||
|
// line 17
|
||||||
y.right = x
|
y.right = x
|
||||||
y.updateMax()
|
y.updateMax()
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user