| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456 |
- // Copyright 2010 Petar Maymounkov. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- // A Left-Leaning Red-Black (LLRB) implementation of 2-3 balanced binary search trees,
- // based on the following work:
- //
- // http://www.cs.princeton.edu/~rs/talks/LLRB/08Penn.pdf
- // http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf
- // http://www.cs.princeton.edu/~rs/talks/LLRB/Java/RedBlackBST.java
- //
- // 2-3 trees (and the run-time equivalent 2-3-4 trees) are the de facto standard BST
- // algoritms found in implementations of Python, Java, and other libraries. The LLRB
- // implementation of 2-3 trees is a recent improvement on the traditional implementation,
- // observed and documented by Robert Sedgewick.
- //
- package llrb
- // Tree is a Left-Leaning Red-Black (LLRB) implementation of 2-3 trees
- type LLRB struct {
- count int
- root *Node
- }
- type Node struct {
- Item
- Left, Right *Node // Pointers to left and right child nodes
- Black bool // If set, the color of the link (incoming from the parent) is black
- // In the LLRB, new nodes are always red, hence the zero-value for node
- }
- type Item interface {
- Less(than Item) bool
- }
- //
- func less(x, y Item) bool {
- if x == pinf {
- return false
- }
- if x == ninf {
- return true
- }
- return x.Less(y)
- }
- // Inf returns an Item that is "bigger than" any other item, if sign is positive.
- // Otherwise it returns an Item that is "smaller than" any other item.
- func Inf(sign int) Item {
- if sign == 0 {
- panic("sign")
- }
- if sign > 0 {
- return pinf
- }
- return ninf
- }
- var (
- ninf = nInf{}
- pinf = pInf{}
- )
- type nInf struct{}
- func (nInf) Less(Item) bool {
- return true
- }
- type pInf struct{}
- func (pInf) Less(Item) bool {
- return false
- }
- // New() allocates a new tree
- func New() *LLRB {
- return &LLRB{}
- }
- // SetRoot sets the root node of the tree.
- // It is intended to be used by functions that deserialize the tree.
- func (t *LLRB) SetRoot(r *Node) {
- t.root = r
- }
- // Root returns the root node of the tree.
- // It is intended to be used by functions that serialize the tree.
- func (t *LLRB) Root() *Node {
- return t.root
- }
- // Len returns the number of nodes in the tree.
- func (t *LLRB) Len() int { return t.count }
- // Has returns true if the tree contains an element whose order is the same as that of key.
- func (t *LLRB) Has(key Item) bool {
- return t.Get(key) != nil
- }
- // Get retrieves an element from the tree whose order is the same as that of key.
- func (t *LLRB) Get(key Item) Item {
- h := t.root
- for h != nil {
- switch {
- case less(key, h.Item):
- h = h.Left
- case less(h.Item, key):
- h = h.Right
- default:
- return h.Item
- }
- }
- return nil
- }
- // Min returns the minimum element in the tree.
- func (t *LLRB) Min() Item {
- h := t.root
- if h == nil {
- return nil
- }
- for h.Left != nil {
- h = h.Left
- }
- return h.Item
- }
- // Max returns the maximum element in the tree.
- func (t *LLRB) Max() Item {
- h := t.root
- if h == nil {
- return nil
- }
- for h.Right != nil {
- h = h.Right
- }
- return h.Item
- }
- func (t *LLRB) ReplaceOrInsertBulk(items ...Item) {
- for _, i := range items {
- t.ReplaceOrInsert(i)
- }
- }
- func (t *LLRB) InsertNoReplaceBulk(items ...Item) {
- for _, i := range items {
- t.InsertNoReplace(i)
- }
- }
- // ReplaceOrInsert inserts item into the tree. If an existing
- // element has the same order, it is removed from the tree and returned.
- func (t *LLRB) ReplaceOrInsert(item Item) Item {
- if item == nil {
- panic("inserting nil item")
- }
- var replaced Item
- t.root, replaced = t.replaceOrInsert(t.root, item)
- t.root.Black = true
- if replaced == nil {
- t.count++
- }
- return replaced
- }
- func (t *LLRB) replaceOrInsert(h *Node, item Item) (*Node, Item) {
- if h == nil {
- return newNode(item), nil
- }
- h = walkDownRot23(h)
- var replaced Item
- if less(item, h.Item) { // BUG
- h.Left, replaced = t.replaceOrInsert(h.Left, item)
- } else if less(h.Item, item) {
- h.Right, replaced = t.replaceOrInsert(h.Right, item)
- } else {
- replaced, h.Item = h.Item, item
- }
- h = walkUpRot23(h)
- return h, replaced
- }
- // InsertNoReplace inserts item into the tree. If an existing
- // element has the same order, both elements remain in the tree.
- func (t *LLRB) InsertNoReplace(item Item) {
- if item == nil {
- panic("inserting nil item")
- }
- t.root = t.insertNoReplace(t.root, item)
- t.root.Black = true
- t.count++
- }
- func (t *LLRB) insertNoReplace(h *Node, item Item) *Node {
- if h == nil {
- return newNode(item)
- }
- h = walkDownRot23(h)
- if less(item, h.Item) {
- h.Left = t.insertNoReplace(h.Left, item)
- } else {
- h.Right = t.insertNoReplace(h.Right, item)
- }
- return walkUpRot23(h)
- }
- // Rotation driver routines for 2-3 algorithm
- func walkDownRot23(h *Node) *Node { return h }
- func walkUpRot23(h *Node) *Node {
- if isRed(h.Right) && !isRed(h.Left) {
- h = rotateLeft(h)
- }
- if isRed(h.Left) && isRed(h.Left.Left) {
- h = rotateRight(h)
- }
- if isRed(h.Left) && isRed(h.Right) {
- flip(h)
- }
- return h
- }
- // Rotation driver routines for 2-3-4 algorithm
- func walkDownRot234(h *Node) *Node {
- if isRed(h.Left) && isRed(h.Right) {
- flip(h)
- }
- return h
- }
- func walkUpRot234(h *Node) *Node {
- if isRed(h.Right) && !isRed(h.Left) {
- h = rotateLeft(h)
- }
- if isRed(h.Left) && isRed(h.Left.Left) {
- h = rotateRight(h)
- }
- return h
- }
- // DeleteMin deletes the minimum element in the tree and returns the
- // deleted item or nil otherwise.
- func (t *LLRB) DeleteMin() Item {
- var deleted Item
- t.root, deleted = deleteMin(t.root)
- if t.root != nil {
- t.root.Black = true
- }
- if deleted != nil {
- t.count--
- }
- return deleted
- }
- // deleteMin code for LLRB 2-3 trees
- func deleteMin(h *Node) (*Node, Item) {
- if h == nil {
- return nil, nil
- }
- if h.Left == nil {
- return nil, h.Item
- }
- if !isRed(h.Left) && !isRed(h.Left.Left) {
- h = moveRedLeft(h)
- }
- var deleted Item
- h.Left, deleted = deleteMin(h.Left)
- return fixUp(h), deleted
- }
- // DeleteMax deletes the maximum element in the tree and returns
- // the deleted item or nil otherwise
- func (t *LLRB) DeleteMax() Item {
- var deleted Item
- t.root, deleted = deleteMax(t.root)
- if t.root != nil {
- t.root.Black = true
- }
- if deleted != nil {
- t.count--
- }
- return deleted
- }
- func deleteMax(h *Node) (*Node, Item) {
- if h == nil {
- return nil, nil
- }
- if isRed(h.Left) {
- h = rotateRight(h)
- }
- if h.Right == nil {
- return nil, h.Item
- }
- if !isRed(h.Right) && !isRed(h.Right.Left) {
- h = moveRedRight(h)
- }
- var deleted Item
- h.Right, deleted = deleteMax(h.Right)
- return fixUp(h), deleted
- }
- // Delete deletes an item from the tree whose key equals key.
- // The deleted item is return, otherwise nil is returned.
- func (t *LLRB) Delete(key Item) Item {
- var deleted Item
- t.root, deleted = t.delete(t.root, key)
- if t.root != nil {
- t.root.Black = true
- }
- if deleted != nil {
- t.count--
- }
- return deleted
- }
- func (t *LLRB) delete(h *Node, item Item) (*Node, Item) {
- var deleted Item
- if h == nil {
- return nil, nil
- }
- if less(item, h.Item) {
- if h.Left == nil { // item not present. Nothing to delete
- return h, nil
- }
- if !isRed(h.Left) && !isRed(h.Left.Left) {
- h = moveRedLeft(h)
- }
- h.Left, deleted = t.delete(h.Left, item)
- } else {
- if isRed(h.Left) {
- h = rotateRight(h)
- }
- // If @item equals @h.Item and no right children at @h
- if !less(h.Item, item) && h.Right == nil {
- return nil, h.Item
- }
- // PETAR: Added 'h.Right != nil' below
- if h.Right != nil && !isRed(h.Right) && !isRed(h.Right.Left) {
- h = moveRedRight(h)
- }
- // If @item equals @h.Item, and (from above) 'h.Right != nil'
- if !less(h.Item, item) {
- var subDeleted Item
- h.Right, subDeleted = deleteMin(h.Right)
- if subDeleted == nil {
- panic("logic")
- }
- deleted, h.Item = h.Item, subDeleted
- } else { // Else, @item is bigger than @h.Item
- h.Right, deleted = t.delete(h.Right, item)
- }
- }
- return fixUp(h), deleted
- }
- // Internal node manipulation routines
- func newNode(item Item) *Node { return &Node{Item: item} }
- func isRed(h *Node) bool {
- if h == nil {
- return false
- }
- return !h.Black
- }
- func rotateLeft(h *Node) *Node {
- x := h.Right
- if x.Black {
- panic("rotating a black link")
- }
- h.Right = x.Left
- x.Left = h
- x.Black = h.Black
- h.Black = false
- return x
- }
- func rotateRight(h *Node) *Node {
- x := h.Left
- if x.Black {
- panic("rotating a black link")
- }
- h.Left = x.Right
- x.Right = h
- x.Black = h.Black
- h.Black = false
- return x
- }
- // REQUIRE: Left and Right children must be present
- func flip(h *Node) {
- h.Black = !h.Black
- h.Left.Black = !h.Left.Black
- h.Right.Black = !h.Right.Black
- }
- // REQUIRE: Left and Right children must be present
- func moveRedLeft(h *Node) *Node {
- flip(h)
- if isRed(h.Right.Left) {
- h.Right = rotateRight(h.Right)
- h = rotateLeft(h)
- flip(h)
- }
- return h
- }
- // REQUIRE: Left and Right children must be present
- func moveRedRight(h *Node) *Node {
- flip(h)
- if isRed(h.Left.Left) {
- h = rotateRight(h)
- flip(h)
- }
- return h
- }
- func fixUp(h *Node) *Node {
- if isRed(h.Right) {
- h = rotateLeft(h)
- }
- if isRed(h.Left) && isRed(h.Left.Left) {
- h = rotateRight(h)
- }
- if isRed(h.Left) && isRed(h.Right) {
- flip(h)
- }
- return h
- }
|