Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Go #45

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions Go/alkhawarizms/datastructure/linkedlist/slist.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package linkedlist

import (
"fmt"
"strings"
)

type Node struct {
Value int
Next *Node
}

type LinkedList struct {
head *Node
}

func (l *LinkedList) Prepend(val int) *Node {
if l == nil {
*l = LinkedList{}
}

if l.head == nil {
l.head = &Node{Value: val}
} else {

phead := l.head
l.head = &Node{Value: val, Next: phead}
}
return l.head
}

//O(n) to reach out to tail (can be optimized by memorizing tail as a node in LinkedList (same as head))
func (l *LinkedList) Append(val int) *Node {
if l == nil {
*l = LinkedList{}
}

if l.head == nil {
l.head = &Node{Value: val}
return l.head
}

curr := l.head
for curr.Next != nil {
curr = curr.Next
}
curr.Next = &Node{Value: val}
return l.head
}

//O(n)
func (l *LinkedList) Lookup(val int) bool {
curr := l.head
for curr != nil {
if curr.Value == val {
return true
}
}
return false
}

func (l *LinkedList) traverseToIndex(index int) *Node {
//we added a pre here to simplify calculations
//insert at specified zero-based index
//1 - 2 -3 - 4
curr := &Node{Next: l.head}
for curr.Next != nil && index > 0 {
curr = curr.Next
index--
}
return curr
}
func (l *Node) String() string {
c := l
builder := strings.Builder{}
for c != nil {
builder.WriteString(fmt.Sprintf("%d", c.Value))
c = c.Next
}
return builder.String()
}

//we loop until we reach the index before we need to put the value at
//we insert the new item
func (l *LinkedList) Insert(index, val int) *Node {

target := l.traverseToIndex(index)
temp := target.Next
target.Next = &Node{Value: val}
target.Next.Next = temp

//only in case it was prepend (at index 0) make sure you update head of linkedList
if index == 0 {
l.head = target.Next
}

return l.head
}

func (l *LinkedList) RemoveAt(index int) bool {
preHead := &Node{Next: l.head}
prev := preHead
curr := l.head

for curr.Next != nil && index > 0 {
prev = curr
curr = curr.Next
index--
}

if index > 0 {
return false
}

prev.Next = curr.Next
l.head = preHead.Next
return true

//1->2->3

}
54 changes: 54 additions & 0 deletions Go/alkhawarizms/datastructure/linkedlist/slist_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package linkedlist

import (
"github.com/stretchr/testify/assert"
"testing"
)

var l = &LinkedList{
head: &Node{Value: 10,
Next: &Node{
Value: 20,
Next: &Node{
Value: 30,
},
}},
}

func TestNode_String(t *testing.T) {

assert.Equal(t, "102030", l.head.String())
}

func Test_traverseToIndex(t *testing.T) {
//0 - 1 - 2
//10 - 20 - 30
assert.Equal(t, "0102030", l.traverseToIndex(0).String())
assert.Equal(t, "102030", l.traverseToIndex(1).String())
assert.Equal(t, "2030", l.traverseToIndex(2).String())
assert.Equal(t, "30", l.traverseToIndex(3).String())
assert.Equal(t, "30", l.traverseToIndex(4).String())
}

func TestLinkedList_Insert(t *testing.T) {
assert.Equal(t, "10152030", l.Insert(1, 15).String())
assert.Equal(t, "1015203040", l.Insert(4, 40).String())
assert.Equal(t, "51015203040", l.Insert(0, 5).String())
}

func TestLinkedList_Prepend(t *testing.T) {
assert.Equal(t, "5102030", l.Prepend(5).String())
assert.Equal(t, "15102030", l.Prepend(1).String())
}

func TestLinkedList_Append(t *testing.T) {
assert.Equal(t, "10203040", l.Append(40).String())
assert.Equal(t, "1020304050", l.Append(50).String())
}

func TestLinkedList_RemoveAt(t *testing.T) {
assert.True(t, l.RemoveAt(0))
assert.Equal(t, "2030", l.head.String())
assert.True(t, l.RemoveAt(1))
assert.Equal(t, "20", l.head.String())
}
192 changes: 190 additions & 2 deletions Go/alkhawarizms/datastructure/trees/bst/bst.go
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
package bst

import "github.com/pkg/errors"
import (
"fmt"
"github.com/golang-collections/collections/queue"
"github.com/golang-collections/collections/stack"
"github.com/pkg/errors"
"strings"
)

//Number of nodes in each level 2^Level_Index
//# of nodes => 2^h - 1 where h is the hight = how many levels in tree
//log(nodes) = height (steps to find items)
//Balance BST using AVL or RedBlack Trees
//Perfect Binary Tree (all nodes have 2 children)
//Full Binary Tree (every node has 0 or 2 childs)
type BSTNode struct {
value int
rank int
left *BSTNode
right *BSTNode
}
Expand All @@ -16,6 +27,36 @@ type bsTree struct {
func NewBSTree() *bsTree {
return &bsTree{}
}
func (b *bsTree) Lookup(value int) bool {
//queu := queue.New()
stack := stack.New()

if b == nil {
return false
}

stack.Push(b.root)
for stack.Len() > 0 {
item := stack.Pop().(*BSTNode)
//exhausted - no more items
if item == nil {
return false
}

//we found it
if item.value == value {
return true
} else { //less than current item go left
if value < item.value {
stack.Push(item.left)
} else { //go right
stack.Push(item.right)
}
}
}

return false
}

func (b *bsTree) Insert(value int) error {
if b.root == nil {
Expand All @@ -26,6 +67,57 @@ func (b *bsTree) Insert(value int) error {
return b.root.Insert(value)
}

func (b *bsTree) DepthFirstTraverse() string {
str := strings.Builder{}
stack := stack.New()
if b.root != nil {
stack.Push(b.root)
}

for stack.Len() != 0 {
node := stack.Pop().(*BSTNode)

str.WriteString(fmt.Sprintf("%d", node.value))

if node.right != nil {
stack.Push(node.right)
}

if node.left != nil {
stack.Push(node.left)
}

}
return str.String()

}

//level by level traversal
func (b *bsTree) BreadthFirstTraverse() string {
str := strings.Builder{}
queue := queue.New()
if b.root != nil {
queue.Enqueue(b.root)
}

for queue.Len() != 0 {
node := queue.Dequeue().(*BSTNode)

str.WriteString(fmt.Sprintf("%d", node.value))

if node.left != nil {
queue.Enqueue(node.left)
}

if node.right != nil {
queue.Enqueue(node.right)
}

}
return str.String()

}

func (b *BSTNode) Insert(value int) error {
if b == nil {
return errors.New("node nil")
Expand All @@ -47,3 +139,99 @@ func (b *BSTNode) Insert(value int) error {

return nil
}

func (b *bsTree) Remove(value int) bool {
//find element first and keep track of its parent
//do one of three operations:
//1 node doesn't have right node
//2 node has right child (right child doesn't have left child)
//3 node has right child (right child has left child)
current := b.root
var parent *BSTNode = nil
for current != nil {
//not found
if value < current.value {
parent = current
current = current.left
} else if value > current.value {
parent = current
current = current.right
} else { //found

if current.right == nil {
//current is the root itself
if parent == nil {
b.root = current.left
} else if current.value < parent.value { //in the left
parent.left = current.left
} else {
parent.right = current.left
}
} else if current.right != nil && current.right.left == nil { //there's right but no right's left child
if parent == nil {
tmp := b.root.left //preserve left child
b.root = current.right
b.root.left = tmp //return left child
//current.right.left = current.left //whatever in the left side
// 4
// 3 5
//remove 4 =>
// 5
// 3
} else if current.value < parent.value { //in the left
// 6
// 4
// 3 5
//remove 4

parent.left = current.right
parent.left.left = current.left

} else {

// 2
// 1 4
// 3 5

parent.right = current.right
parent.right.left = current.left
}
} else {
//go one step right and then all way down to the left (gives us the smallest number in this case)
smallestParent := current.right
smallest := current.right.left
//while we have left childs, we continue moving on
for smallest.left != nil {
smallestParent = smallest
smallest = smallest.left
}

// 2
// 1 4
// 3 5
//remove 2

//take care of right part of the smallest since we know that it doesn't have any left childs so we only care about right
//put it under smallestParent
smallestParent.left = smallest.right
//then we move smallest to the main node
smallest.left = current.left
smallest.right = current.right

//adjust parent to make sure we have parent pointing to the new node (smallest)
if parent == nil {
b.root = smallest
} else if current.value < parent.value {
parent.left = smallest
} else {
parent.right = smallest
}

}

return true
}
}

return false
}
Loading