Setting an index of a binary tree in go - algorithm

Im trying to teach myself data structures & algos and I am trying to figure out the best way to add an index to a binary tree
Im guessing the best way to do this is to modify an in orderTraversal operation but im not exactly sure how I would implement this and chain that on after every insert and delete function.
type BinarySearchNode struct {
Left *BinarySearchNode
Right *BinarySearchNode
Parent *BinarySearchNode
Data int
Index int
}
func (BSN *BinarySearchNode) Insert(value int){
if BSN.Data > value {
if BSN.Left == nil{
BSN.Left = &BinarySearchNode{Data:value, Parent:BSN}
return
}
BSN.Left.Insert(value)
return
}
if BSN.Right == nil{
BSN.Right = &BinarySearchNode{Data:value, Parent: BSN}
return
}
BSN.Right.Insert(value)
}
func (BSN *BinarySearchNode) setIndex(node *BinarySearchNode, count int)(int){
if node == nil{
return count
}
if node.Right == nil && node.Left == nil{
node.Index = count
}
node.setIndex(node.Left, count+1)
node.setIndex(node.Right, count+1)
return count
}

I have a piece of code for the implementation of binary tree in golang. It may help you.
package main
import (
"fmt"
"math"
)
// A single Node in a binary tree
type Node struct {
// Value contained by the node
Value int
// Left subnode of the node
Left *Node
// Right subnode of the node
Right *Node
}
type BinaryTree struct {
Root *Node
}
// inserting the element in the binary tree
func (tree *BinaryTree) Insert(value int) {
if tree.Root == nil {
node := new(Node)
node.Value = value
tree.Root = node
return
}
current := tree.Root
for {
if value < current.Value {
if current.Left == nil {
node := new(Node)
node.Value = value
current.Left = node
return
} else {
current = current.Left
}
} else {
if current.Right == nil {
node := new(Node)
node.Value = value
current.Right = node
return
} else {
current = current.Right
}
}
}
}
// current left right
func (tree *BinaryTree) RecursivePreOrder(root *Node) {
if root == nil {
return
}
fmt.Println(root.Value)
tree.RecursivePreOrder(root.Left)
tree.RecursivePreOrder(root.Right)
}
func (tree *BinaryTree) IterativePreOrder(root *Node) {
stack := []*Node{}
for {
for root != nil {
fmt.Println(root.Value)
stack = append([]*Node{root}, stack...)
root = root.Left
}
if len(stack) == 0 {
break
}
root = stack[0]
stack = stack[1:]
root = root.Right
}
}
func (tree *BinaryTree) RecursiveInOrder(root *Node) {
if root == nil {
return
}
tree.RecursiveInOrder(root.Left)
fmt.Println(root.Value)
tree.RecursiveInOrder(root.Right)
}
func (tree *BinaryTree) IterativeInOrder(root *Node) {
var stack []*Node
for {
for root != nil {
stack = append([]*Node{root}, stack...)
root = root.Left
}
if len(stack) == 0 {
break
}
root = stack[0]
stack = stack[1:]
fmt.Println(root.Value)
root = root.Right
}
}
func (tree *BinaryTree) RecursivePostOrder(root *Node) {
if root == nil {
return
}
tree.RecursivePostOrder(root.Left)
tree.RecursivePostOrder(root.Right)
fmt.Println(root.Value)
}
func (tree *BinaryTree) IterativePostOrder(root *Node) {
stack := []*Node{}
var previous *Node = nil
for {
for root != nil {
stack = append([]*Node{root}, stack...)
root = root.Left
}
for root == nil && len(stack) != 0 {
root = stack[0]
if root.Right == nil || root.Right == previous {
fmt.Println(root.Value)
stack = stack[1:]
previous = root
root = nil
} else {
root = root.Right
}
}
if len(stack) == 0 {
break
}
}
}
func (tree *BinaryTree) LevelOrder(root *Node) {
// a queue for performing level order traversal of breadth first traversal
queue := []*Node{}
if root != nil {
queue = append(queue, root)
}
for len(queue) > 0 {
root = queue[0]
queue = queue[1:]
fmt.Println(root.Value)
if root.Left != nil {
queue = append(queue, root.Left)
}
if root.Right != nil {
queue = append(queue, root.Right)
}
}
}
func (tree *BinaryTree) Size(root *Node) int {
if root == nil {
return 0
}
sum := tree.Size(root.Left) + 1 + tree.Size(root.Right)
return sum
}
func (tree *BinaryTree) ElementAt(root *Node, index int) *Node {
if index > tree.Size(root)-1 {
fmt.Println("Index doesnot exist")
return nil
}
leftSize := tree.Size(root.Left)
if index == leftSize {
return root
} else if index < leftSize {
return tree.ElementAt(root.Left, index)
} else {
return tree.ElementAt(root.Right, index-leftSize-1)
}
}
func (tree *BinaryTree) Height(root *Node) int {
if root == nil {
return -1
}
return int(math.Max(float64(tree.Height(root.Left)), float64(tree.Height(root.Right)))) + 1
}
// starting point of the program
func main() {
tree := new(BinaryTree)
tree.Insert(44)
tree.Insert(55)
tree.Insert(33)
fmt.Println(tree.Height(tree.Root))
}

Related

Golang pointer receiver not updating as expected

I am implementing node deletion in binary search tree. I have implemented a method which look good (at algorithm standpoint). But do not work. After spending hours trying to understand why, I would love to get some help from you.
BST definition
type Node struct {
Data int
Left *Node
Right *Node
}
Helper methods (they have been tested and works)
// New returns a pointer to a mew node (like the new construct in Go)
func New(data int) *Node {
return &Node{Data: data}
}
// Find checks whether some data exist in the bst and returns the corresponding node
func (bst *Node) Find(data int) *Node {
if bst == nil {
return bst
}
if bst.Data == data {
return bst
}
if data < bst.Data {
return bst.Left.Find(data)
}
return bst.Right.Find(data)
}
// Min returns the smallest element in a bst
func (bst *Node) Min() *Node {
if bst == nil {
return nil
}
current := bst
for current.Left != nil {
current = current.Left
}
return current
}
The non working method
// Delete removes a key from the binary tree
func (bst *Node) Delete(data int) *Node {
if bst == nil {
return bst
}
current := bst
toDelete := current.Find(data)
if toDelete == nil {
return current
}
if toDelete.Right == nil && toDelete.Left != nil {
toDelete = toDelete.Left
return current
}
if toDelete.Right != nil && toDelete.Left == nil {
toDelete = toDelete.Right
return current
}
inOrderSuccessor := toDelete.Right.Min()
toDelete = inOrderSuccessor
return current
}
Test
func main() {
root := bst.New(8)
root.Left = bst.New(3)
root.Right = bst.New(10)
root.Left.Left = bst.New(1)
root.Left.Right = bst.New(6)
fmt.Println(root.InOrder())
root = root.Delete(3)
fmt.Println(root.InOrder())
}
output
1->3->6->8->10->
1->3->6->8->10->
There is something wrong in the Delete method but I could not understand why.
This code can be run in the playground here https://go.dev/play/p/oJZMOCp2BXL
I assume that you think that
toDelete = toDelete.Left
overwrites data that is stored where toDelete points to.
But this operation will just assign a new pointer to toDeletevariable. To overwrite data that is stored in memory you need to dereference the pointer:
*toDelete = *toDelete.Left
You can look at this example https://go.dev/play/p/M62hd3lpHXk and see the difference in a simpler case.

How to find a binary tree depth using breadth-first algorithm in Golang

I have a binary tree and I would like to find its maximum depth using a breadth-first approach.
I think I am having a logical error in where to increment the depth.
// You can edit this code!
// Click here and start typing.
package main
import (
"log"
"math"
)
type Queue []*Node
func (q *Queue) Enqueue(n *Node) {
*q = append(*q, n)
}
func (q *Queue) Dequeue() *Node {
node := (*q)[0]
*q = (*q)[1:]
return node
}
func (q *Queue) IsEmpty() bool {
return len(*q) == 0
}
type Node struct {
value *int
left *Node
right *Node
}
func (node *Node) insert(value int) {
if node.value == nil {
node.value = &value
return
}
if *node.value <= value {
if node.left == nil {
node.left = &Node{}
}
node.left.insert(value)
return
}
if node.right == nil {
node.right = &Node{}
}
node.right.insert(value)
}
// HELP NEEDED here
func (node *Node) NumberOfVisibleNodes() int {
var counter int
if node == nil || node.value == nil {
return counter
}
hashtable := map[int]int{}
levelDepth := 0
nodeQueue := Queue{node}
for !nodeQueue.IsEmpty() {
currentNode := nodeQueue.Dequeue()
_, found := hashtable[levelDepth]
if !found {
hashtable[levelDepth] = *currentNode.value
}
if currentNode.left != nil {
nodeQueue.Enqueue(currentNode.left)
hashtable[levelDepth+1] = *currentNode.left.value
}
if currentNode.right != nil {
nodeQueue.Enqueue(currentNode.right)
hashtable[levelDepth+1] = *currentNode.right.value
}
levelDepth++
}
return len(hashtable)
}
func (node *Node) NumberOfVisibleNodesRecursively() int {
if node == nil || node.value == nil {
return 0
}
leftMaxDepth := node.left.NumberOfVisibleNodesRecursively()
rightMaxDepth := node.right.NumberOfVisibleNodesRecursively()
maxDepth := math.Max(float64(leftMaxDepth), float64(rightMaxDepth))
return 1 + int(maxDepth)
}
func main() {
testCases := []struct {
expect string
arguments []int
expected int
}{
{
"expect to return 0 when nodes are empty",
[]int{},
0,
},
{
"expect to get 2",
[]int{3, 5},
2,
},
{
"expect to get 3",
[]int{3, 5, 2, 6, 4, 1},
3,
},
{
"expect to return 4",
[]int{3, 5, 2, 6, 4, 1, -10},
4,
},
}
for _, testCase := range testCases {
var tree Node
for _, value := range testCase.arguments {
tree.insert(value)
}
gotResult := tree.NumberOfVisibleNodes()
if gotResult != testCase.expected {
log.Fatalf("%s but got: %d wanted: %d ", testCase.expect, gotResult, testCase.expected)
}
}
}
I wonder if it's even possible. I know the best approach is to use a depth-first approach but I am curious to learn if the breadth approach is possible!
Running code is here: https://go.dev/play/p/exiI-QqRWIM
[UPDATE]
One approach that seems to work is using a tuple.
type TupleQueue []Tuple
func (tq *TupleQueue) Enqueue(t Tuple) {
*tq = append(*tq, t)
}
func (tq *TupleQueue) Dequeue() Tuple {
tuple := (*tq)[0]
*tq = (*tq)[1:]
return tuple
}
func (tq *TupleQueue) IsEmpty() bool {
return len(*tq) == 0
}
func (node *Node) NumberOfVisibleNodes() int {
if node == nil || node.value == nil {
return 0
}
var depth int
tupleQueue := TupleQueue{{depth, node}}
for !tupleQueue.IsEmpty() {
tuple := tupleQueue.Dequeue()
if tuple.level != depth {
depth++
}
if tuple.node.left != nil {
tupleQueue.Enqueue(Tuple{depth + 1, tuple.node.left})
}
if tuple.node.right != nil {
tupleQueue.Enqueue(Tuple{depth + 1, tuple.node.right})
}
}
return depth + 1
}
I wonder if we can do something similar with hashmaps
You don't need tuple or hashmap to do BFS. Just use queue, I show the code below.
func (node *Node) NumberOfVisibleNodes() int {
if node == nil || node.value == nil {
return 0
}
levelDepth := 0
nodeQueue := Queue{node}
for !nodeQueue.IsEmpty() {
tmpQueue := Queue{}
for !nodeQueue.IsEmpty(){
cNode := nodeQueue.Dequeue()
if cNode.right!= nil{
tmpQueue.Enqueue(cNode.right)
}
if cNode.left!= nil{
tmpQueue.Enqueue(cNode.left)
}
}
nodeQueue = tmpQueue
levelDepth++
}
return levelDepth
}

BST golang search func

can you help with search func, it always returns nil and i cannot understand why
func BTreeSearchItem(root *TreeNode, elem string) *TreeNode {
if root == nil {
return nil
}
if root.Data < elem {
return BTreeSearchItem(root.Left, elem)
} else if root.Data > elem {
return BTreeSearchItem(root.Right, elem)
}
return root
}
Tried to do like this, but it returns 4 instead of 7
func BTreeSearchItem(root *TreeNode, elem string) *TreeNode {
if root == nil {
return nil
}
if root.Data < elem {
BTreeSearchItem(root.Left, elem)
} else if root.Data > elem {
BTreeSearchItem(root.Right, elem)
}
return root
}
Complete Code is
package main
import "fmt"
type TreeNode struct {
Left, Right, Parent *TreeNode
Data string
}
func BTreeSearchItem(root *TreeNode, elem string) *TreeNode {
if root == nil {
return nil
}
if root.Data < elem {
BTreeSearchItem(root.Left, elem)
} else if root.Data > elem {
BTreeSearchItem(root.Right, elem)
}
return root
}
func BTreeInsertData(root *TreeNode, data string) *TreeNode {
if root == nil {
return &TreeNode{Data: data}
}
if root.Data == data {
return nil
}
if root.Data > data {
if root.Left == nil {
root.Left = &TreeNode{Data: data}
}
return BTreeInsertData(root.Left, data)
}
if root.Data < data {
if root.Right == nil {
root.Right = &TreeNode{Data: data}
}
return BTreeInsertData(root.Right, data)
}
return root
}
func main() {
root := &TreeNode{Data: "4"}
BTreeInsertData(root, "1")
BTreeInsertData(root, "7")
BTreeInsertData(root, "5")
selected := BTreeSearchItem(root, "7")
fmt.Print("Item selected -> ")
if selected != nil {
fmt.Println(selected.Data)
} else {
fmt.Println("nil")
}
fmt.Print("Parent of selected item -> ")
if selected.Parent != nil {
fmt.Println(selected.Parent.Data)
} else {
fmt.Println("nil")
}
fmt.Print("Left child of selected item -> ")
if selected.Left != nil {
fmt.Println(selected.Left.Data)
} else {
fmt.Println("nil")
}
fmt.Print("Right child of selected item -> ")
if selected.Right != nil {
fmt.Println(selected.Right.Data)
} else {
fmt.Println("nil")
}
}
searched the internet and found a lot by methods, but i need as func. i'm beginner at programming, so it hard to me to understand
PlayGoundLink
My suggestion is check the value of root in main() before calling function BTreeSearchItem. What I suspect is root values is already nil in that stage itself.
okey, https://play.golang.org/p/gQmdYLfAvIY this code works, in BTreeInsertData forgot to add Parant and in BTreeSearchItem I mismatch Right and Left

Removing an item in a Linked List with Go

I want to remove a Node from a linked list in Go, and I have this struct and these methods:
type Node struct {
Next *Node
Val int
}
func (n *Node) Append(val int) {
end := &Node{Val: val}
here := n
for here.Next != nil {
here = here.Next
}
here.Next = end
}
func Remove(n *Node, val int) *Node {
head := n
for head.Next != nil {
if head.Next.Val == val {
head.Next = head.Next.Next
return head
}
head = head.Next
}
return head
}
func NewNode(val int) *Node {
return &Node{Val: val}
}
I want to remove an item like this:
n := NewNode(1)
n.Append(2)
n.Append(3)
n.Append(4)
n.Append(5)
m := Remove(n, 3)
for m != nil {
fmt.Println(n.Val)
m = m.Next
}
The items that get printed out are 3 and 5, not 1,2,4and5`. I re-implemented this code in Python and got the expected answer. What is going on in Go? I have a feeling it has to do something with pointers.
You lose the head from returning a node you use to traverse. Also you are printing out the wrong object
type Node struct {
Next *Node
Val int
}
func (n *Node) Append(val int) {
end := &Node{Val: val}
here := n
for here.Next != nil {
here = here.Next
}
here.Next = end
}
func Remove(n *Node, val int) *Node {
traverser := n
for traverser.Next != nil {
if traverser.Next.Val == val {
traverser.Next = traverser.Next.Next
return n
}
traverser = traverser.Next
}
return n
}
func NewNode(val int) *Node {
return &Node{Val: val}
}
func main() {
n := NewNode(1)
n.Append(2)
n.Append(3)
n.Append(4)
n.Append(5)
m := Remove(n, 3)
for m != nil {
fmt.Println(m.Val)
m = m.Next
}
}

How to create a binary tree use struct in golang?

I want to create a binary tree and initialize the tree use golang.
And the codes like these:
package Tree
import "fmt"
type TreeNode struct {
Left *TreeNode
Right *TreeNode
Value int
}
func InsertNodeToTree(tree *TreeNode, node *TreeNode)(){
if tree == nil {
tree = node
}
if node.Value > tree.Value {
InsertNodeToTree(tree.Right, node)
}
if node.Value < tree.Value {
InsertNodeToTree(tree.Left, node)
}
}
func InitTree(values ...int) (root *TreeNode) {
rootNode := TreeNode{Value: values[0]}
for _, value := range values {
node := TreeNode{Value:value}
InsertNodeToTree(&rootNode, &node)
}
return &rootNode
}
func main() {
treeNode := InitTree(5, 4, 6, 8, 9, 7, 1, 3, 2)
fmt.Println(treeNode)
}
Why the tree's left and right are nil?
I pass the reference of the tree node, why not work?
In C/C++ programming language, you can use TreeNode *&tree.
But in golang programming language, you can not use *&.
tree is just a copy of the pointer, so you can't point the value to another TreeNode.
I modified your program, and it can run successfully now.
Maybe these codes you need:
package Tree
type TreeNode struct {
Left *TreeNode
Right *TreeNode
Value int
}
var DefaultValue int = -1024
func InsertNodeToTree(tree *TreeNode, node *TreeNode)(){
if tree == nil {
return
}
if tree.Value == DefaultValue {
tree.Value = node.Value
return
}
if node.Value > tree.Value {
if tree.Right == nil {
tree.Right = &TreeNode{Value: DefaultValue}
}
InsertNodeToTree(tree.Right, node)
}
if node.Value < tree.Value {
if tree.Left == nil {
tree.Left = &TreeNode{Value: DefaultValue}
}
InsertNodeToTree(tree.Left, node)
}
}
func InitTree(values ...int) (root *TreeNode) {
rootNode := TreeNode{Value: DefaultValue, Right: nil, Left: nil}
for _, value := range values {
node := TreeNode{Value:value}
InsertNodeToTree(&rootNode, &node)
}
return &rootNode
}
tree is only a copy of the pointer. Assigning to the variable is useless. Instead, you need to assign to an already existing node. For example:
https://play.golang.org/p/Agzby-Yinq
func InsertNodeToTree(tree *TreeNode, node *TreeNode) {
if tree == nil {
panic("cannot insert into nil root")
}
if node.Value > tree.Value {
if tree.Right == nil {
tree.Right = node
} else {
InsertNodeToTree(tree.Right, node)
}
}
if node.Value < tree.Value {
if tree.Left == nil {
tree.Left = node
} else {
InsertNodeToTree(tree.Left, node)
}
}
}

Resources