Skip to content

Commit

Permalink
Replace Go implementation by a more naive one
Browse files Browse the repository at this point in the history
The previous implementation was relatively hard to read and maintain.
This implementation aims to be better in this regard:

- Rename Node's X,Y to Value and Weight
- Make methods of functions that operate on *Node
- Concentrate complexity in the *Node methods

The implementation is faster as well.
  • Loading branch information
silkeh committed Jun 25, 2018
1 parent 3cafcd9 commit d81b8a0
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 66 deletions.
2 changes: 1 addition & 1 deletion go/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Translated from JavaScript version by: Vlad Frolov (@frol)
## Compile

```
go build -o treap main-raw.go
go build -o treap main.go
```

or
Expand Down
141 changes: 76 additions & 65 deletions go/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,98 +3,110 @@ package main
import (
"fmt"
"math/rand"
"time"
)

type Node struct {
X int
Y int
Left *Node
Right *Node
func init() {
rand.Seed(time.Now().UnixNano())
}

func NewNode(v int) *Node {
y := rand.Int()
return &Node{
X: v,
Y: y,
}
// Tree represents a treap
type Tree struct {
root *Node
}

type Tree struct {
Root *Node
// Insert inserts a value into the treap
func (t *Tree) Insert(v int) {
t.root = t.root.Insert(v)
}

// Erase removes a value from the treap
func (t *Tree) Erase(v int) {
t.root = t.root.Erase(v)
}

// HasValue checks if the treap contains a value
func (t *Tree) HasValue(v int) bool {
splitted := split(t.Root, v)
res := splitted.Equal != nil
t.Root = merge3(splitted.Lower, splitted.Equal, splitted.Greater)
return res
return t.root.HasValue(v)
}

func (t *Tree) Insert(v int) error {
splitted := split(t.Root, v)
if splitted.Equal == nil {
splitted.Equal = NewNode(v)
}
t.Root = merge3(splitted.Lower, splitted.Equal, splitted.Greater)
return nil
// Node represents a node in the treap
type Node struct {
X, Y int
Left, Right *Node
}

func (t *Tree) Erase(v int) error {
splitted := split(t.Root, v)
t.Root = merge(splitted.Lower, splitted.Greater)
return nil
// NewNode creates a new node with a value and a random weight
func NewNode(v int) *Node {
return &Node{
X: v,
Y: rand.Int(),
}
}

type SplitResult struct {
Lower *Node
Equal *Node
Greater *Node
// HasValue checks if the current node, or related nodes, contain a value
func (n *Node) HasValue(v int) bool {
lower, equal, greater := n.split(v)
merge(merge(lower, equal), greater)
return equal != nil
}

func merge(lower, greater *Node) *Node {
if lower == nil {
return greater
// Insert inserts a value in the correct place in or below the current node
func (n *Node) Insert(v int) *Node {
lower, equal, greater := n.split(v)
if equal == nil {
equal = NewNode(v)
}
return merge(merge(lower, equal), greater)
}

if greater == nil {
return lower
}
// Erase deletes a node with a specified value from the tree
func (n *Node) Erase(v int) *Node {
lower, _, greater := n.split(v)

if lower.Y < greater.Y {
right := merge(lower.Right, greater)
lower.Right = right
return lower
}
left := merge(lower, greater.Left)
greater.Left = left
return greater
return merge(lower, greater)
}

func merge3(lower, equal, greater *Node) *Node {
return merge(merge(lower, equal), greater)
// split splits the tree between binary equal and greater node-links
func (n *Node) split(v int) (lower, equal, greater *Node) {
var equalGreater *Node

lower, equalGreater = n.splitBinary(v)
equal, greater = equalGreater.splitBinary(v + 1)

return
}

func splitBinary(original *Node, value int) (*Node, *Node) {
if original == nil {
return nil, nil
// splitbinary splits the tree in twain on a value
func (n *Node) splitBinary(v int) (left, right *Node) {
if n == nil {
return
}

if original.X < value {
splitPair0, splitPair1 := splitBinary(original.Right, value)
original.Right = splitPair0
return original, splitPair1
if n.X < v {
left = n
n.Right, right = n.Right.splitBinary(v)
} else {
right = n
left, n.Left = n.Left.splitBinary(v)
}

splitPair0, splitPair1 := splitBinary(original.Left, value)
original.Left = splitPair1
return splitPair0, original
return
}

func split(original *Node, value int) SplitResult {
lower, equalGreater := splitBinary(original, value)
equal, greater := splitBinary(equalGreater, value+1)
return SplitResult{lower, equal, greater}
// merge two nodes
func merge(left, right *Node) (result *Node) {
if left == nil {
result = right
} else if right == nil {
result = left
} else if left.Y > right.Y {
result, left.Right = left, merge(left.Right, right)
} else {
result, right.Left = right, merge(left, right.Left)
}

return
}

func main() {
Expand All @@ -111,9 +123,8 @@ func main() {
} else if a == 1 {
t.Erase(cur)
} else if a == 2 {
has := t.HasValue(cur)
if has {
res += 1
if t.HasValue(cur) {
res++
}
}
}
Expand Down

0 comments on commit d81b8a0

Please sign in to comment.