-
Notifications
You must be signed in to change notification settings - Fork 96
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Solve the "Test if a binary tree is balanced" problem
commit 719971269104da2c8743540471c53821dc36e005 Author: Peter Mrekaj <mrekucci@gmail.com> Date: Tue Oct 20 21:49:12 2015 -0700 Solve the "Test if a binary tree is balanced" problem commit 3b950cb514552eddedf88402d48ce2e332adf788 Author: Peter Mrekaj <mrekucci@gmail.com> Date: Mon Oct 19 22:17:27 2015 -0700 Simplify test for Walk method commit 3aade4a7593a5cea042d7b549434c57335b1444f Author: Peter Mrekaj <mrekucci@gmail.com> Date: Mon Oct 19 22:12:49 2015 -0700 Implement BTree with walking support commit 054653c91a31b659d6523c6725f89ab61b73079b Author: Peter Mrekaj <mrekucci@gmail.com> Date: Sat Oct 17 18:15:12 2015 -0700 Improve stack tests for more coverage and readability commit 494a4d9186f34638504528373e899b307708ab7e Author: Peter Mrekaj <mrekucci@gmail.com> Date: Sat Oct 17 17:10:42 2015 -0700 Solve the "Implement a queue using stacks" problem
- Loading branch information
Showing
5 changed files
with
264 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// Copyright (c) 2015, Peter Mrekaj. All rights reserved. | ||
// Use of this source code is governed by a MIT-style | ||
// license that can be found in the LICENSE.txt file. | ||
|
||
package btrees | ||
|
||
// state represents the state of the binary tree. | ||
type state struct { | ||
isBalanced bool | ||
height int | ||
} | ||
|
||
// checkState returns the status of the binary tree t. | ||
func checkState(t *BTree) state { | ||
if t == nil { | ||
return state{true, -1} // Base case. | ||
} | ||
|
||
// Postorder walk. | ||
lt := checkState(t.left) | ||
if !lt.isBalanced { | ||
return lt | ||
} | ||
rt := checkState(t.right) | ||
if !rt.isBalanced { | ||
return rt | ||
} | ||
|
||
d := lt.height - rt.height | ||
max := lt.height | ||
if lt.height < rt.height { | ||
max = rt.height | ||
} | ||
return state{d <= 1 && d >= -1, max + 1} | ||
|
||
} | ||
|
||
// IsBalanced returns true if t is a balanced binary tree. | ||
// The time complexity is O(n). The O(h) additional space | ||
// is needed (where h is the height of the tree). | ||
func IsBalanced(t *BTree) bool { return checkState(t).isBalanced } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// Copyright (c) 2015, Peter Mrekaj. All rights reserved. | ||
// Use of this source code is governed by a MIT-style | ||
// license that can be found in the LICENSE.txt file. | ||
|
||
package btrees | ||
|
||
import "testing" | ||
|
||
func TestIsBalance(t *testing.T) { | ||
for _, test := range []struct { | ||
tree *BTree | ||
want bool | ||
}{ | ||
// Balanced Binary Trees. | ||
{&BTree{"TREE_0", nil, nil}, true}, | ||
{&BTree{"TREE_1", &BTree{"A", nil, nil}, nil}, true}, | ||
{&BTree{"TREE_2", | ||
&BTree{"A", | ||
&BTree{"B", nil, nil}, | ||
&BTree{"C", nil, nil}}, | ||
&BTree{"D", nil, nil}}, true}, | ||
|
||
// Not balanced Binary Trees. | ||
{&BTree{"TREE_3", &BTree{"A", &BTree{"B", nil, nil}, nil}, nil}, false}, | ||
{&BTree{"TREE_4", | ||
&BTree{"A", | ||
&BTree{"B", | ||
&BTree{"C", nil, nil}, | ||
&BTree{"D", nil, nil}}, | ||
&BTree{"E", nil, nil}}, | ||
&BTree{"F", nil, nil}}, false}, | ||
{&BTree{"TREE_5", | ||
&BTree{"A", | ||
&BTree{"B", | ||
&BTree{"C", | ||
&BTree{"D", nil, nil}, | ||
&BTree{"E", nil, nil}}, | ||
&BTree{"F", nil, nil}}, | ||
&BTree{"G", nil, nil}}, | ||
&BTree{"H", nil, nil}}, false}, | ||
{&BTree{"TREE_6", | ||
&BTree{"A", nil, nil}, | ||
&BTree{"B", | ||
&BTree{"C", nil, nil}, | ||
&BTree{"D", | ||
&BTree{"E", nil, nil}, | ||
&BTree{"F", nil, nil}}}}, false}, | ||
{&BTree{"TREE_7", | ||
&BTree{"A", nil, nil}, | ||
&BTree{"B", | ||
&BTree{"C", nil, nil}, | ||
&BTree{"D", | ||
&BTree{"E", nil, nil}, | ||
&BTree{"F", | ||
&BTree{"G", nil, nil}, | ||
&BTree{"H", nil, nil}}}}}, false}, | ||
} { | ||
if got := IsBalanced(test.tree); got != test.want { | ||
t.Errorf("IsBalanced(%v) = %t; want %t", test.tree, got, test.want) | ||
} | ||
} | ||
} | ||
|
||
func BenchmarkIsBalanced(b *testing.B) { | ||
tree := &BTree{"A", | ||
&BTree{"B", | ||
&BTree{"C", | ||
&BTree{"D", | ||
&BTree{"E", nil, nil}, | ||
&BTree{"F", nil, nil}}, | ||
&BTree{"G", nil, nil}}, | ||
&BTree{"H", | ||
&BTree{"I", nil, nil}, | ||
&BTree{"J", nil, nil}}}, | ||
&BTree{"K", | ||
&BTree{"L", | ||
&BTree{"M", nil, nil}, | ||
&BTree{"N", nil, nil}}, | ||
&BTree{"O", nil, nil}}} | ||
b.ResetTimer() | ||
for i := 0; i < b.N; i++ { | ||
IsBalanced(tree) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// Copyright (c) 2015, Peter Mrekaj. All rights reserved. | ||
// Use of this source code is governed by a MIT-style | ||
// license that can be found in the LICENSE.txt file. | ||
|
||
package btrees | ||
|
||
// BTree represents a binary tree. | ||
type BTree struct { | ||
Data interface{} | ||
left *BTree | ||
right *BTree | ||
} | ||
|
||
// Height returns the height of the binary tree t. | ||
// The time complexity is O(n). The O(h) additional | ||
// space is needed (where h is the height of the tree). | ||
func Height(t *BTree) int { | ||
hl, hr := -1, -1 | ||
if t != nil { | ||
hl = 1 + Height(t.right) | ||
hr = 1 + Height(t.left) | ||
} | ||
if hl > hr { | ||
return hl | ||
} | ||
return hr | ||
} | ||
|
||
// Walk returns elements of the binary tree t in given traversal order. | ||
func Walk(t *BTree, order func(t *BTree, w *[]interface{})) []interface{} { | ||
var w []interface{} | ||
order(t, &w) | ||
return w | ||
} | ||
|
||
// Preorder visit the root, traverse the left | ||
// subtree, then traverse the right subtree. | ||
// The time complexity is O(n). The O(h) additional | ||
// space is needed (where h is the height of the tree). | ||
func Preorder(t *BTree, w *[]interface{}) { | ||
if t != nil { | ||
*w = append(*w, t.Data) | ||
Preorder(t.left, w) | ||
Preorder(t.right, w) | ||
} | ||
} | ||
|
||
// Inorder traverse the left subtree, visit the | ||
// root, then traverse the right subtree. | ||
// The time complexity is O(n). The O(h) additional | ||
// space is needed (where h is the height of the tree). | ||
func Inorder(t *BTree, w *[]interface{}) { | ||
if t != nil { | ||
Inorder(t.left, w) | ||
*w = append(*w, t.Data) | ||
Inorder(t.right, w) | ||
} | ||
} | ||
|
||
// Postorder traverse the left subtree, traverse the | ||
// right subtree, and then visit the root. | ||
// The time complexity is O(n). The O(h) additional | ||
// space is needed (where h is the height of the tree). | ||
func Postorder(t *BTree, w *[]interface{}) { | ||
if t != nil { | ||
Postorder(t.left, w) | ||
Postorder(t.right, w) | ||
*w = append(*w, t.Data) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// Copyright (c) 2015, Peter Mrekaj. All rights reserved. | ||
// Use of this source code is governed by a MIT-style | ||
// license that can be found in the LICENSE.txt file. | ||
|
||
package btrees | ||
|
||
import ( | ||
"reflect" | ||
"testing" | ||
) | ||
|
||
func TestHeight(t *testing.T) { | ||
for _, test := range []struct { | ||
tree *BTree | ||
want int | ||
}{ | ||
{&BTree{"TREE_0", nil, nil}, 0}, | ||
{&BTree{"TREE_1", &BTree{"A", nil, nil}, nil}, 1}, | ||
{&BTree{"TREE_2", nil, &BTree{"A", nil, nil}}, 1}, | ||
{&BTree{"TREE_3", &BTree{"A", nil, nil}, &BTree{"B", nil, nil}}, 1}, | ||
{&BTree{"TREE_4", &BTree{"A", &BTree{"B", nil, nil}, nil}, nil}, 2}, | ||
} { | ||
if got := Height(test.tree); got != test.want { | ||
t.Errorf("Height(%v) = %d; want %d", test.tree, got, test.want) | ||
} | ||
} | ||
} | ||
|
||
func TestWalk(t *testing.T) { | ||
// A Binary Tree of height 5. | ||
tree := &BTree{"A", | ||
&BTree{"B", | ||
&BTree{"C", | ||
&BTree{"D", nil, nil}, | ||
&BTree{"E", nil, nil}}, | ||
&BTree{"F", | ||
nil, | ||
&BTree{"G", | ||
&BTree{"H", nil, nil}, | ||
nil}}}, | ||
&BTree{"I", | ||
&BTree{"J", | ||
nil, | ||
&BTree{"K", | ||
&BTree{"L", | ||
nil, | ||
&BTree{"M", nil, nil}}, | ||
&BTree{"N", nil, nil}}}, | ||
&BTree{"O", | ||
nil, | ||
&BTree{"P", nil, nil}}}} | ||
|
||
for _, test := range []struct { | ||
fnName string | ||
fn func(t *BTree, w *[]interface{}) | ||
want []interface{} | ||
}{ | ||
{"Preorder", Preorder, []interface{}{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P"}}, | ||
{"Inorder", Inorder, []interface{}{"D", "C", "E", "B", "F", "H", "G", "A", "J", "L", "M", "K", "N", "I", "O", "P"}}, | ||
{"Postorder", Postorder, []interface{}{"D", "E", "C", "H", "G", "F", "B", "M", "L", "N", "K", "J", "P", "O", "I", "A"}}, | ||
} { | ||
if got := Walk(tree, test.fn); !reflect.DeepEqual(got, test.want) { | ||
t.Errorf("tree.Walk %q got %v; want %v", test.fnName, got, test.want) | ||
} | ||
} | ||
} |