btree: add a way to visualize the tree
This commit is contained in:
		@@ -12,8 +12,8 @@ type data struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Tree is the tree itself
 | 
					// Tree is the tree itself
 | 
				
			||||||
type Tree struct {
 | 
					type Tree struct {
 | 
				
			||||||
	root *node // Pointer to the node root
 | 
						root   *node // Pointer to the node root
 | 
				
			||||||
	t    int   // Minimum degree
 | 
						degree int   // Minimum degree
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type node struct {
 | 
					type node struct {
 | 
				
			||||||
@@ -27,11 +27,11 @@ type node struct {
 | 
				
			|||||||
// Constructors
 | 
					// Constructors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewBtree creates a new btree
 | 
					// NewBtree creates a new btree
 | 
				
			||||||
func NewBtree(t int) *Tree {
 | 
					func NewBtree(degree int) *Tree {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &Tree{
 | 
						return &Tree{
 | 
				
			||||||
		root: nil,
 | 
							root:   nil,
 | 
				
			||||||
		t:    t,
 | 
							degree: degree,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -62,6 +62,15 @@ func (a *data) gt(b *data) bool {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Tree methods
 | 
					// Tree methods
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Visualize the tree
 | 
				
			||||||
 | 
					func (t *Tree) Visualize() {
 | 
				
			||||||
 | 
						if t.root == nil {
 | 
				
			||||||
 | 
							fmt.Println("The tree is empty")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						t.root.visualize("", true)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Traverse the tree
 | 
					// Traverse the tree
 | 
				
			||||||
func (t *Tree) Traverse() {
 | 
					func (t *Tree) Traverse() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -113,8 +122,8 @@ func (t *Tree) Insert(key, value string) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// If the tree is empty
 | 
						// If the tree is empty
 | 
				
			||||||
	if t.root == nil {
 | 
						if t.root == nil {
 | 
				
			||||||
		t.root = newNode(t.t, true)
 | 
							t.root = newNode(t.degree, true)
 | 
				
			||||||
		t.root.keys[0] = k
 | 
							t.root.insertKey(0, k)
 | 
				
			||||||
		t.root.numberOfKeys = 1
 | 
							t.root.numberOfKeys = 1
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -127,7 +136,7 @@ func (t *Tree) Insert(key, value string) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// If the root is full, then the tree grows in height
 | 
						// If the root is full, then the tree grows in height
 | 
				
			||||||
	s := newNode(t.t, false)
 | 
						s := newNode(t.degree, false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Make the old root as a child of the new root
 | 
						// Make the old root as a child of the new root
 | 
				
			||||||
	s.children[0] = t.root
 | 
						s.children[0] = t.root
 | 
				
			||||||
@@ -149,6 +158,37 @@ func (t *Tree) Insert(key, value string) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// node methods
 | 
					// node methods
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// insertKey at i place in the node
 | 
				
			||||||
 | 
					func (n *node) insertKey(i int, k *data) {
 | 
				
			||||||
 | 
						n.keys[i] = k
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (n *node) visualize(prefix string, isEnd bool) {
 | 
				
			||||||
 | 
						fmt.Print(prefix)
 | 
				
			||||||
 | 
						nextPrefix := "    "
 | 
				
			||||||
 | 
						if isEnd {
 | 
				
			||||||
 | 
							fmt.Print("└── ")
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							fmt.Print("├── ")
 | 
				
			||||||
 | 
							nextPrefix = "│   "
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for i := 0; i < n.numberOfKeys-1; i++ {
 | 
				
			||||||
 | 
							fmt.Printf("%s:%s ", n.keys[i].key, n.keys[i].value)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fmt.Printf("%s:%s", n.keys[n.numberOfKeys-1].key, n.keys[n.numberOfKeys-1].value)
 | 
				
			||||||
 | 
						fmt.Printf("\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if n.isLeaf {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 0; i < n.numberOfKeys; i++ {
 | 
				
			||||||
 | 
							n.children[i].visualize(fmt.Sprintf("%s%s", prefix, nextPrefix), false)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						n.children[n.numberOfKeys].visualize(fmt.Sprintf("%s%s", prefix, nextPrefix), true)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// traverse all nodes in a subtree rooted with this node
 | 
					// traverse all nodes in a subtree rooted with this node
 | 
				
			||||||
func (n *node) traverse() {
 | 
					func (n *node) traverse() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -209,7 +249,7 @@ func (n *node) insertNonFull(k *data) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Insert the new key at the found location
 | 
							// Insert the new key at the found location
 | 
				
			||||||
		n.keys[i+1] = k
 | 
							n.insertKey(i+1, k)
 | 
				
			||||||
		n.numberOfKeys++
 | 
							n.numberOfKeys++
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -106,6 +106,9 @@ func ExampleTree_Traverse() {
 | 
				
			|||||||
		tree.Insert(k[0], k[1])
 | 
							tree.Insert(k[0], k[1])
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tree.Visualize()
 | 
				
			||||||
 | 
						fmt.Println("")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tree.Traverse()
 | 
						tree.Traverse()
 | 
				
			||||||
	fmt.Println("")
 | 
						fmt.Println("")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -133,7 +136,14 @@ func ExampleTree_Traverse() {
 | 
				
			|||||||
	tree.Traverse()
 | 
						tree.Traverse()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Output:
 | 
						// Output:
 | 
				
			||||||
	// a:A b:B c:C d:D e:E f:F g:G h:H i:I j:J k:K l:L m:M n:N o:O p:P q:Q
 | 
						// └── c:C f:F i:I l:L
 | 
				
			||||||
 | 
						//     ├── a:A b:B
 | 
				
			||||||
 | 
						//     ├── d:D e:E
 | 
				
			||||||
 | 
						//     ├── g:G h:H
 | 
				
			||||||
 | 
						//     ├── j:J k:K
 | 
				
			||||||
 | 
						//     └── m:M n:N o:O p:P q:Q
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						//  a:A b:B c:C d:D e:E f:F g:G h:H i:I j:J k:K l:L m:M n:N o:O p:P q:Q
 | 
				
			||||||
	//  a:A b:B c:C d:D f:F g:G h:H i:I j:J k:K l:L m:M n:N o:O p:P q:Q
 | 
						//  a:A b:B c:C d:D f:F g:G h:H i:I j:J k:K l:L m:M n:N o:O p:P q:Q
 | 
				
			||||||
	//  a:A b:B c:C d:D f:F g:G h:H i:I k:K l:L m:M n:N o:O p:P q:Q
 | 
						//  a:A b:B c:C d:D f:F g:G h:H i:I k:K l:L m:M n:N o:O p:P q:Q
 | 
				
			||||||
	//  b:B c:C d:D f:F g:G h:H i:I k:K l:L m:M n:N o:O p:P q:Q
 | 
						//  b:B c:C d:D f:F g:G h:H i:I k:K l:L m:M n:N o:O p:P q:Q
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										13
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								main.go
									
									
									
									
									
								
							@@ -11,16 +11,28 @@ func main() {
 | 
				
			|||||||
	// Example program
 | 
						// Example program
 | 
				
			||||||
	t := btree.NewBtree(3)
 | 
						t := btree.NewBtree(3)
 | 
				
			||||||
	t.Insert("animal", "dog")
 | 
						t.Insert("animal", "dog")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s, _ := t.Search("animal")
 | 
				
			||||||
 | 
						fmt.Println(s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	t.Insert("potato", "fries")
 | 
						t.Insert("potato", "fries")
 | 
				
			||||||
	t.Insert("6", "number")
 | 
						t.Insert("6", "number")
 | 
				
			||||||
	t.Insert("12", "number")
 | 
						t.Insert("12", "number")
 | 
				
			||||||
	t.Insert("car", "ferrari")
 | 
						t.Insert("car", "ferrari")
 | 
				
			||||||
	t.Insert("7", "number")
 | 
						t.Insert("7", "number")
 | 
				
			||||||
	t.Insert("plane", "airbus")
 | 
						t.Insert("plane", "airbus")
 | 
				
			||||||
 | 
						t.Insert("animal", "cat")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s, _ = t.Search("animal")
 | 
				
			||||||
 | 
						fmt.Println(s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fmt.Print("Traversal of the constructed tree is")
 | 
						fmt.Print("Traversal of the constructed tree is")
 | 
				
			||||||
	t.Traverse()
 | 
						t.Traverse()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmt.Println("")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Visualize()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if val, err := t.Search("6"); err != nil {
 | 
						if val, err := t.Search("6"); err != nil {
 | 
				
			||||||
		fmt.Print("\nNot Present")
 | 
							fmt.Print("\nNot Present")
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
@@ -32,4 +44,5 @@ func main() {
 | 
				
			|||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		fmt.Printf("\nPresent: value '%s'", val)
 | 
							fmt.Printf("\nPresent: value '%s'", val)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user