BST golang search func - go

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

Related

Setting an index of a binary tree in go

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))
}

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
}

Will a struct be modified when in receiver method it is referred to as pointer?

I am trying to implement a tree in Go.
type BinaryNode struct {
left *BinaryNode
right *BinaryNode
data int
}
type BinaryTree struct {
root *BinaryNode
}
Now to insert elements , I have an insert func,
func (t *BinaryNode) insertNode(d int) {
fmt.Printf("%+v\n", t)
if t == nil {
t = &BinaryNode{
data: d,
left: nil,
right: nil,
}
fmt.Printf("%+v inside insert\n", t)
} else {
if d <= t.data {
t.left.insertNode(d)
} else {
t.right.insertNode(d)
}
}
}
If the pointer is nil, create a new node, if not look for left or right, according to the data.
In my main function , i am trying simple few steps :
func main() {
tree1 := &BinaryTree{
root: nil,
}
tree1.root.insertNode(3)
fmt.Printf("%+v\n", tree1.root)
}
What i expect to see is a tree with root value 3.
but i do not see any. Instead I get:
<nil>
&{left:<nil> right:<nil> data:3} inside insert
<nil>
From what I have understood, if the struct pointer is used for methods, a copy is not made. In that case, the modification should persist.
What have I missed here?
this is i thing a simplest solution you can do, i hope its self explanatory
type Bin struct {
left, right *Bin
value int
}
func New(value int) *Bin {
return &Bin{value: value}
}
func (b *Bin) Insert(value int) {
if value <= b.value {
if b.left == nil {
b.left = New(value)
} else {
b.left.Insert(value)
}
} else {
if b.right == nil {
b.right = New(value)
} else {
b.right.Insert(value)
}
}
}

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)
}
}
}

Stop recursive function when element is found

I am trying to solve an exercise from The go programming language book:
The starting code can be found here: exercise.
What I need to do:
Modify forEachNode so that the pre and post functions return a boolean result indicating whether to continue the traversal. Use it to write a function ElementByID with the following signature that finds the first HTML element with the specified id attribute. The function should stop the traversal as soon as a match is found.
Signature: func ElementByID(doc *html.Node, id string) *html.Node
What I did:
func ElementByID(doc *html.Node, id string) *html.Node {
if doc.Data == id {
fmt.Printf(" %s: %s\n", "found", doc.Data)
return doc
}
return nil
}
func startElement(n *html.Node) bool {
if n.Type == html.ElementNode {
if ElementById(n, "a") != nil {
return true
}
fmt.Printf("%*s<%s>\n", depth*2, "", n.Data)
depth++
}
return false
}
func endElement(n *html.Node) bool {
if n.Type == html.ElementNode {
if ElementById(n, "a") != nil {
return true
}
depth--
fmt.Printf("%*s</%s>\n", depth*2, "", n.Data)
}
return false
}
Is the above right?, or I've missed something? How can I stop the traversal where element is found?
The forEachNode is the same, only the pre and post signature was changed to return a bool.
You can create a closure and "close" found node. Example below.
Modify forEachNode so that the pre and post functions return a boolean result indicating whether to continue the traversal.:
func forEachNode(n *html.Node, pre, post func(n *html.Node) bool) {
if pre != nil && !pre(n) {
return
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
forEachNode(c, pre, post)
}
if post != nil && !post(n) {
return
}
}
Use it to write a function ElementByID with the following signature that finds the first HTML element with the specified id attribute. The function should stop the traversal as soon as a match is found.:
func ElementByID(doc *html.Node, id string) *html.Node {
var found *html.Node
pre := func(n *html.Node) bool {
for _, a := range n.Attr {
if a.Key == "id" && a.Val == id {
found = n // memorize matching node
return false // stop traversing
}
}
return true
}
forEachNode(doc, pre, nil)
return found
}

Resources