WIP(example/yolo
This commit is contained in:
parent
5f8e5a51a4
commit
565be523db
|
@ -1,8 +1,10 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -28,7 +30,11 @@ type Node struct {
|
|||
|
||||
// NewTree creates a tree with a specified comparator
|
||||
func NewTree(c Comparator) *Tree {
|
||||
return &Tree{Comparator: c}
|
||||
return &Tree{
|
||||
Root: nil,
|
||||
Comparator: c,
|
||||
size: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// Put inserts a node to tree
|
||||
|
@ -38,13 +44,12 @@ func (t *Tree) Put(k interface{}, v interface{}) (err error) {
|
|||
if t.Root == nil {
|
||||
t.Comparator = t.Comparator.Init()
|
||||
t.Root = &Node{Key: k, Value: v, color: red}
|
||||
err = nil
|
||||
insertedNode = t.Root
|
||||
} else {
|
||||
node := t.Root
|
||||
|
||||
var loop bool = true
|
||||
for loop {
|
||||
|
||||
switch t.Comparator.Compare(k, node.Key) {
|
||||
case 0:
|
||||
node.Key = k
|
||||
|
@ -168,6 +173,225 @@ func (t *Tree) Values() (retVal []interface{}) {
|
|||
return vals
|
||||
}
|
||||
|
||||
// Left returns the left-most (min) node or nil if tree is empty.
|
||||
func (t *Tree) Left() *Node {
|
||||
var parent *Node
|
||||
current := t.Root
|
||||
for current != nil {
|
||||
parent = current
|
||||
current = current.Left
|
||||
}
|
||||
return parent
|
||||
}
|
||||
|
||||
// Right returns the right-most (max) node or nil if tree is empty.
|
||||
func (t *Tree) Right() *Node {
|
||||
var parent *Node
|
||||
current := t.Root
|
||||
for current != nil {
|
||||
parent = current
|
||||
current = current.Right
|
||||
}
|
||||
return parent
|
||||
}
|
||||
|
||||
// Floor finds floor node of the input key.
|
||||
//
|
||||
// NOTE: `floor node` is defined as the largest node that is smaller or equal
|
||||
// to given node. There may be no floor node if the tree is empty or all nodes
|
||||
// in the tree are larger than the given node.
|
||||
func (t *Tree) Floor(k interface{}) (retVal *Node, found bool) {
|
||||
found = false
|
||||
root := t.Root
|
||||
|
||||
for root != nil {
|
||||
switch t.Comparator.Compare(k, root.Key) {
|
||||
case 0:
|
||||
return root, true
|
||||
case -1:
|
||||
root = root.Left
|
||||
case 1:
|
||||
retVal, found = root, true
|
||||
root = root.Right
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return retVal, found
|
||||
}
|
||||
|
||||
// Ceil returns the ceiling node of the input node.
|
||||
//
|
||||
// Ceiling node is defined as the smallest node that is larger or
|
||||
// equal to the given node. There may not have a ceiling node if
|
||||
// tree is empty or all other nodes in the tree are smaller than
|
||||
// the given node.
|
||||
func (t *Tree) Ceil(k interface{}) (retVal *Node, found bool) {
|
||||
found = false
|
||||
root := t.Root
|
||||
|
||||
for root != nil {
|
||||
switch t.Comparator.Compare(k, root.Key) {
|
||||
case 0:
|
||||
return root, true
|
||||
case -1:
|
||||
retVal, found = root, true
|
||||
root = root.Left
|
||||
case 1:
|
||||
root = root.Right
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return retVal, found
|
||||
}
|
||||
|
||||
// Clear deletes all nodes
|
||||
func (t *Tree) Clear() {
|
||||
t.Root = nil
|
||||
t.size = 0
|
||||
}
|
||||
|
||||
// String returns a string representation of the tree.
|
||||
func (t *Tree) String() (retVal string) {
|
||||
str := "BinaryTree\n"
|
||||
|
||||
if !t.IsEmpty() {
|
||||
output(t.Root, "", true, &str)
|
||||
}
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
// Node methods:
|
||||
//==============
|
||||
|
||||
func (n *Node) String() (retVal string) {
|
||||
return fmt.Sprintf("%v", n.Key)
|
||||
}
|
||||
|
||||
func output(n *Node, prefix string, isTail bool, str *string) {
|
||||
if n.Right != nil {
|
||||
newPrefix := prefix
|
||||
if isTail {
|
||||
newPrefix += "│ "
|
||||
} else {
|
||||
newPrefix += " "
|
||||
}
|
||||
output(n.Right, newPrefix, false, str)
|
||||
}
|
||||
*str += prefix
|
||||
if isTail {
|
||||
*str += "└── "
|
||||
} else {
|
||||
*str += "┌── "
|
||||
}
|
||||
*str += n.String() + "\n"
|
||||
if n.Left != nil {
|
||||
newPrefix := prefix
|
||||
if isTail {
|
||||
newPrefix += " "
|
||||
} else {
|
||||
newPrefix += "│ "
|
||||
}
|
||||
output(n.Left, newPrefix, true, str)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Tree) lookup(k interface{}) (retVal *Node) {
|
||||
root := t.Root
|
||||
|
||||
for root != nil {
|
||||
switch t.Comparator.Compare(k, root.Key) {
|
||||
case 0:
|
||||
return root
|
||||
case -1:
|
||||
root = root.Left
|
||||
case 1:
|
||||
root = root.Right
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *Node) grandparent() (retVal *Node) {
|
||||
if n != nil && n.Parent != nil {
|
||||
return n.Parent.Parent
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *Node) uncle() (retVal *Node) {
|
||||
if n == nil || n.Parent == nil || n.Parent.Parent == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return n.Parent.sibling()
|
||||
}
|
||||
|
||||
func (n *Node) sibling() (retVal *Node) {
|
||||
if n == nil || n.Parent == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if n == n.Parent.Left {
|
||||
return n.Parent.Right
|
||||
}
|
||||
|
||||
return n.Parent.Left
|
||||
}
|
||||
|
||||
func (t *Tree) rotateLeft(n *Node) {
|
||||
right := n.Right
|
||||
t.replaceNode(n, right)
|
||||
|
||||
n.Right = right.Left
|
||||
|
||||
if right.Left != nil {
|
||||
right.Left.Parent = n
|
||||
}
|
||||
|
||||
right.Left = n
|
||||
n.Parent = right
|
||||
}
|
||||
|
||||
func (t *Tree) rotateRight(n *Node) {
|
||||
left := n.Left
|
||||
t.replaceNode(n, left)
|
||||
n.Left = left.Right
|
||||
|
||||
if left.Right != nil {
|
||||
left.Right.Parent = n
|
||||
}
|
||||
|
||||
left.Right = n
|
||||
n.Parent = left
|
||||
}
|
||||
|
||||
func (t *Tree) replaceNode(old, new *Node) {
|
||||
if old.Parent == nil {
|
||||
t.Root = new
|
||||
} else {
|
||||
if old == old.Parent.Left {
|
||||
old.Parent.Left = new
|
||||
} else {
|
||||
old.Parent.Right = new
|
||||
}
|
||||
}
|
||||
|
||||
if new != nil {
|
||||
new.Parent = old.Parent
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Tree) insertCase1(node *Node) {
|
||||
if node.Parent == nil {
|
||||
node.color = black
|
||||
|
@ -176,51 +400,196 @@ func (t *Tree) insertCase1(node *Node) {
|
|||
}
|
||||
}
|
||||
|
||||
func (tree *Tree) insertCase2(node *Node) {
|
||||
if nodeColor(node.Parent) == black {
|
||||
func (t *Tree) insertCase2(n *Node) {
|
||||
if nodeColor(n.Parent) == black {
|
||||
return
|
||||
}
|
||||
tree.insertCase3(node)
|
||||
t.insertCase3(n)
|
||||
}
|
||||
|
||||
func (tree *Tree) insertCase3(node *Node) {
|
||||
uncle := node.uncle()
|
||||
func (t *Tree) insertCase3(n *Node) {
|
||||
uncle := n.uncle()
|
||||
if nodeColor(uncle) == red {
|
||||
node.Parent.color = black
|
||||
n.Parent.color = black
|
||||
uncle.color = black
|
||||
node.grandparent().color = red
|
||||
tree.insertCase1(node.grandparent())
|
||||
n.grandparent().color = red
|
||||
t.insertCase1(n.grandparent())
|
||||
} else {
|
||||
tree.insertCase4(node)
|
||||
t.insertCase4(n)
|
||||
}
|
||||
}
|
||||
|
||||
func (tree *Tree) insertCase4(node *Node) {
|
||||
grandparent := node.grandparent()
|
||||
if node == node.Parent.Right && node.Parent == grandparent.Left {
|
||||
tree.rotateLeft(node.Parent)
|
||||
node = node.Left
|
||||
} else if node == node.Parent.Left && node.Parent == grandparent.Right {
|
||||
tree.rotateRight(node.Parent)
|
||||
node = node.Right
|
||||
func (t *Tree) insertCase4(n *Node) {
|
||||
grandparent := n.grandparent()
|
||||
if n == n.Parent.Right && n.Parent == grandparent.Left {
|
||||
t.rotateLeft(n.Parent)
|
||||
n = n.Left
|
||||
} else if n == n.Parent.Left && n.Parent == grandparent.Right {
|
||||
t.rotateRight(n.Parent)
|
||||
n = n.Right
|
||||
}
|
||||
tree.insertCase5(node)
|
||||
t.insertCase5(n)
|
||||
}
|
||||
|
||||
func (tree *Tree) insertCase5(node *Node) {
|
||||
node.Parent.color = black
|
||||
grandparent := node.grandparent()
|
||||
func (t *Tree) insertCase5(n *Node) {
|
||||
n.Parent.color = black
|
||||
grandparent := n.grandparent()
|
||||
grandparent.color = red
|
||||
if node == node.Parent.Left && node.Parent == grandparent.Left {
|
||||
tree.rotateRight(grandparent)
|
||||
} else if node == node.Parent.Right && node.Parent == grandparent.Right {
|
||||
tree.rotateLeft(grandparent)
|
||||
if n == n.Parent.Left && n.Parent == grandparent.Left {
|
||||
t.rotateRight(grandparent)
|
||||
} else if n == n.Parent.Right && n.Parent == grandparent.Right {
|
||||
t.rotateLeft(grandparent)
|
||||
}
|
||||
}
|
||||
|
||||
func nodeColor(node *Node) bool {
|
||||
if node == nil {
|
||||
func (n *Node) maximumNode() (retVal *Node) {
|
||||
if n == nil {
|
||||
return nil
|
||||
}
|
||||
for n.Right != nil {
|
||||
n = n.Right
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (t *Tree) deleteCase1(n *Node) {
|
||||
if n.Parent == nil {
|
||||
return
|
||||
}
|
||||
t.deleteCase2(n)
|
||||
}
|
||||
|
||||
func (t *Tree) deleteCase2(n *Node) {
|
||||
sibling := n.sibling()
|
||||
if nodeColor(sibling) == red {
|
||||
n.Parent.color = red
|
||||
sibling.color = black
|
||||
if n == n.Parent.Left {
|
||||
t.rotateLeft(n.Parent)
|
||||
} else {
|
||||
t.rotateRight(n.Parent)
|
||||
}
|
||||
}
|
||||
t.deleteCase3(n)
|
||||
}
|
||||
|
||||
func (t *Tree) deleteCase3(n *Node) {
|
||||
sibling := n.sibling()
|
||||
if nodeColor(n.Parent) == black &&
|
||||
nodeColor(sibling) == black &&
|
||||
nodeColor(sibling.Left) == black &&
|
||||
nodeColor(sibling.Right) == black {
|
||||
sibling.color = red
|
||||
t.deleteCase1(n.Parent)
|
||||
} else {
|
||||
t.deleteCase4(n)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Tree) deleteCase4(n *Node) {
|
||||
sibling := n.sibling()
|
||||
if nodeColor(n.Parent) == red &&
|
||||
nodeColor(sibling) == black &&
|
||||
nodeColor(sibling.Left) == black &&
|
||||
nodeColor(sibling.Right) == black {
|
||||
sibling.color = red
|
||||
n.Parent.color = black
|
||||
} else {
|
||||
t.deleteCase5(n)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Tree) deleteCase5(n *Node) {
|
||||
sibling := n.sibling()
|
||||
if n == n.Parent.Left &&
|
||||
nodeColor(sibling) == black &&
|
||||
nodeColor(sibling.Left) == red &&
|
||||
nodeColor(sibling.Right) == black {
|
||||
sibling.color = red
|
||||
sibling.Left.color = black
|
||||
t.rotateRight(sibling)
|
||||
} else if n == n.Parent.Right &&
|
||||
nodeColor(sibling) == black &&
|
||||
nodeColor(sibling.Right) == red &&
|
||||
nodeColor(sibling.Left) == black {
|
||||
sibling.color = red
|
||||
sibling.Right.color = black
|
||||
t.rotateLeft(sibling)
|
||||
}
|
||||
t.deleteCase6(n)
|
||||
}
|
||||
|
||||
func (t *Tree) deleteCase6(n *Node) {
|
||||
sibling := n.sibling()
|
||||
sibling.color = nodeColor(n.Parent)
|
||||
n.Parent.color = black
|
||||
if n == n.Parent.Left && nodeColor(sibling.Right) == red {
|
||||
sibling.Right.color = black
|
||||
t.rotateLeft(n.Parent)
|
||||
} else if nodeColor(sibling.Left) == red {
|
||||
sibling.Left.color = black
|
||||
t.rotateRight(n.Parent)
|
||||
}
|
||||
}
|
||||
|
||||
func nodeColor(n *Node) bool {
|
||||
if n == nil {
|
||||
return black
|
||||
}
|
||||
return node.color
|
||||
return n.color
|
||||
}
|
||||
|
||||
// ToJSON outputs the JSON representation of the tree.
|
||||
func (t *Tree) ToJSON() ([]byte, error) {
|
||||
elements := make(map[string]interface{})
|
||||
it := t.Iterator()
|
||||
for it.Next() {
|
||||
elements[toString(it.Key())] = it.Value()
|
||||
}
|
||||
return json.Marshal(&elements)
|
||||
}
|
||||
|
||||
// FromJSON populates the tree from the input JSON representation.
|
||||
func (t *Tree) FromJSON(data []byte) error {
|
||||
elements := make(map[string]interface{})
|
||||
err := json.Unmarshal(data, &elements)
|
||||
if err == nil {
|
||||
t.Clear()
|
||||
for key, value := range elements {
|
||||
t.Put(key, value)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// ToString converts a value to string.
|
||||
func toString(value interface{}) string {
|
||||
switch value := value.(type) {
|
||||
case string:
|
||||
return value
|
||||
case int8:
|
||||
return strconv.FormatInt(int64(value), 10)
|
||||
case int16:
|
||||
return strconv.FormatInt(int64(value), 10)
|
||||
case int32:
|
||||
return strconv.FormatInt(int64(value), 10)
|
||||
case int64:
|
||||
return strconv.FormatInt(int64(value), 10)
|
||||
case uint8:
|
||||
return strconv.FormatUint(uint64(value), 10)
|
||||
case uint16:
|
||||
return strconv.FormatUint(uint64(value), 10)
|
||||
case uint32:
|
||||
return strconv.FormatUint(uint64(value), 10)
|
||||
case uint64:
|
||||
return strconv.FormatUint(uint64(value), 10)
|
||||
case float32:
|
||||
return strconv.FormatFloat(float64(value), 'g', -1, 64)
|
||||
case float64:
|
||||
return strconv.FormatFloat(float64(value), 'g', -1, 64)
|
||||
case bool:
|
||||
return strconv.FormatBool(value)
|
||||
default:
|
||||
return fmt.Sprintf("%+v", value)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ func (c Comparator) Compare(a, b interface{}) (retVal int) {
|
|||
case "float64":
|
||||
return compareFloat64(a.(float64), b.(float64))
|
||||
default:
|
||||
log.Fatalf("Unsupported a type() or b type().\n", reflect.TypeOf(a).Kind(), reflect.TypeOf(b).Kind())
|
||||
log.Fatalf("Unsupported a type(%v) or b type(%v).\n", reflect.TypeOf(a).Kind(), reflect.TypeOf(b).Kind())
|
||||
}
|
||||
|
||||
return retVal
|
||||
|
|
|
@ -2,5 +2,5 @@ package main
|
|||
|
||||
type block struct {
|
||||
blockType string
|
||||
parameters
|
||||
// parameters
|
||||
}
|
||||
|
|
151
example/yolo/iterator.go
Normal file
151
example/yolo/iterator.go
Normal file
|
@ -0,0 +1,151 @@
|
|||
package main
|
||||
|
||||
// Iterator holding the iterator's state
|
||||
type Iterator struct {
|
||||
tree *Tree
|
||||
node *Node
|
||||
position position
|
||||
}
|
||||
|
||||
type position byte
|
||||
|
||||
const (
|
||||
begin, between, end position = 0, 1, 2
|
||||
)
|
||||
|
||||
// Iterator returns a stateful iterator whose elements are key/value pairs.
|
||||
func (tree *Tree) Iterator() Iterator {
|
||||
return Iterator{tree: tree, node: nil, position: begin}
|
||||
}
|
||||
|
||||
// IteratorAt returns a stateful iterator whose elements are key/value pairs that is initialised at a particular node.
|
||||
func (tree *Tree) IteratorAt(node *Node) Iterator {
|
||||
return Iterator{tree: tree, node: node, position: between}
|
||||
}
|
||||
|
||||
// Next moves the iterator to the next element and returns true if there was a next element in the container.
|
||||
// If Next() returns true, then next element's key and value can be retrieved by Key() and Value().
|
||||
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
|
||||
// Modifies the state of the iterator.
|
||||
func (iterator *Iterator) Next() bool {
|
||||
if iterator.position == end {
|
||||
goto end
|
||||
}
|
||||
if iterator.position == begin {
|
||||
left := iterator.tree.Left()
|
||||
if left == nil {
|
||||
goto end
|
||||
}
|
||||
iterator.node = left
|
||||
goto between
|
||||
}
|
||||
if iterator.node.Right != nil {
|
||||
iterator.node = iterator.node.Right
|
||||
for iterator.node.Left != nil {
|
||||
iterator.node = iterator.node.Left
|
||||
}
|
||||
goto between
|
||||
}
|
||||
if iterator.node.Parent != nil {
|
||||
node := iterator.node
|
||||
for iterator.node.Parent != nil {
|
||||
iterator.node = iterator.node.Parent
|
||||
if iterator.tree.Comparator.Compare(node.Key, iterator.node.Key) <= 0 {
|
||||
goto between
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
iterator.node = nil
|
||||
iterator.position = end
|
||||
return false
|
||||
|
||||
between:
|
||||
iterator.position = between
|
||||
return true
|
||||
}
|
||||
|
||||
// Prev moves the iterator to the previous element and returns true if there was a previous element in the container.
|
||||
// If Prev() returns true, then previous element's key and value can be retrieved by Key() and Value().
|
||||
// Modifies the state of the iterator.
|
||||
func (iterator *Iterator) Prev() bool {
|
||||
if iterator.position == begin {
|
||||
goto begin
|
||||
}
|
||||
if iterator.position == end {
|
||||
right := iterator.tree.Right()
|
||||
if right == nil {
|
||||
goto begin
|
||||
}
|
||||
iterator.node = right
|
||||
goto between
|
||||
}
|
||||
if iterator.node.Left != nil {
|
||||
iterator.node = iterator.node.Left
|
||||
for iterator.node.Right != nil {
|
||||
iterator.node = iterator.node.Right
|
||||
}
|
||||
goto between
|
||||
}
|
||||
if iterator.node.Parent != nil {
|
||||
node := iterator.node
|
||||
for iterator.node.Parent != nil {
|
||||
iterator.node = iterator.node.Parent
|
||||
if iterator.tree.Comparator.Compare(node.Key, iterator.node.Key) >= 0 {
|
||||
goto between
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
begin:
|
||||
iterator.node = nil
|
||||
iterator.position = begin
|
||||
return false
|
||||
|
||||
between:
|
||||
iterator.position = between
|
||||
return true
|
||||
}
|
||||
|
||||
// Value returns the current element's value.
|
||||
// Does not modify the state of the iterator.
|
||||
func (iterator *Iterator) Value() interface{} {
|
||||
return iterator.node.Value
|
||||
}
|
||||
|
||||
// Key returns the current element's key.
|
||||
// Does not modify the state of the iterator.
|
||||
func (iterator *Iterator) Key() interface{} {
|
||||
return iterator.node.Key
|
||||
}
|
||||
|
||||
// Begin resets the iterator to its initial state (one-before-first)
|
||||
// Call Next() to fetch the first element if any.
|
||||
func (iterator *Iterator) Begin() {
|
||||
iterator.node = nil
|
||||
iterator.position = begin
|
||||
}
|
||||
|
||||
// End moves the iterator past the last element (one-past-the-end).
|
||||
// Call Prev() to fetch the last element if any.
|
||||
func (iterator *Iterator) End() {
|
||||
iterator.node = nil
|
||||
iterator.position = end
|
||||
}
|
||||
|
||||
// First moves the iterator to the first element and returns true if there was a first element in the container.
|
||||
// If First() returns true, then first element's key and value can be retrieved by Key() and Value().
|
||||
// Modifies the state of the iterator
|
||||
func (iterator *Iterator) First() bool {
|
||||
iterator.Begin()
|
||||
return iterator.Next()
|
||||
}
|
||||
|
||||
// Last moves the iterator to the last element and returns true if there was a last element in the container.
|
||||
// If Last() returns true, then last element's key and value can be retrieved by Key() and Value().
|
||||
// Modifies the state of the iterator.
|
||||
func (iterator *Iterator) Last() bool {
|
||||
iterator.End()
|
||||
return iterator.Prev()
|
||||
}
|
24
example/yolo/main.go
Normal file
24
example/yolo/main.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
c := Comparator{}
|
||||
tree := NewTree(c)
|
||||
|
||||
tree.MustPut("key1", "Val1")
|
||||
tree.MustPut("key2", "Val2")
|
||||
tree.MustPut("key3", "Val3")
|
||||
tree.MustPut("key4", "Val4")
|
||||
tree.MustPut("key5", "Val5")
|
||||
tree.MustPut("key6", "Val6")
|
||||
tree.MustPut("key7", "Val7")
|
||||
tree.MustPut("key8", "Val8")
|
||||
|
||||
fmt.Println(tree.String())
|
||||
|
||||
fmt.Println(tree.Ceil("key7"))
|
||||
}
|
Loading…
Reference in New Issue
Block a user