Skip to content

Instantly share code, notes, and snippets.

@Dionid
Created July 6, 2020 16:06
Show Gist options
  • Save Dionid/d63e642c3d61c5bd2fadd76a63329e10 to your computer and use it in GitHub Desktop.
Save Dionid/d63e642c3d61c5bd2fadd76a63329e10 to your computer and use it in GitHub Desktop.
Poorly done Binary tree isBalanced check (this is bad, i know, it is for future me to improve) + tests
interface TNode {
value: number
left?: TNode
right?: TNode
}
export interface Tree {
root: TNode
}
interface CheckingNode {
node: TNode
leftIsChecked: boolean
rightIsChecked: boolean
isLeftNode: boolean
isRightNode: boolean
isRootNode: boolean
}
class TreeIsNotBalanced extends Error {}
export class BinaryTreeNodeChecker {
private static checkPrevNodes(prevNodes: CheckingNode[], val: number): boolean {
return prevNodes.every((prevNode) => {
const prevNodeVal = prevNode.node.value
return (
(prevNode.isRightNode && prevNodeVal > val) || // if prev node is on right side than current value must be bigger
(prevNode.isLeftNode && prevNodeVal < val) || // if prev node is on left side than current value must be smaller
(prevNode.isRootNode && prevNode.leftIsChecked && prevNodeVal < val) || // if prev node is root and we are on right branch than current value must be bigger
(prevNode.isRootNode && !prevNode.leftIsChecked && prevNodeVal > val) // if prev node is root and we are on left branch than current value must be smaller
)
})
}
private static nodeIsBalanced(
currentNode: CheckingNode,
prevNodes: CheckingNode[],
): boolean {
if (currentNode.node.left && !currentNode.leftIsChecked) {
// . If left node exist and hasn't been checked
const leftVal = currentNode.node.left.value
// . Check current node value more than left node value and previous nodes are in order
if (currentNode.node.value > leftVal && this.checkPrevNodes(prevNodes, leftVal)) {
// . Push current node to nodeList and continue with left node value
prevNodes.push(currentNode)
return this.nodeIsBalanced(
{
node: currentNode.node.left,
leftIsChecked: false,
rightIsChecked: false,
isLeftNode: true,
isRightNode: false,
isRootNode: false,
},
prevNodes,
)
} else {
throw new TreeIsNotBalanced()
}
} else if (currentNode.node.right && !currentNode.rightIsChecked) {
// . If right node exist and hasn't been checked
const rightVal = currentNode.node.right.value
// . Check current node value less than right node value and previous nodes are in order
if (currentNode.node.value < rightVal && this.checkPrevNodes(prevNodes, rightVal)) {
// . Push current node to nodeList and continue with right node value
prevNodes.push(currentNode)
return this.nodeIsBalanced(
{
node: currentNode.node.right,
leftIsChecked: false,
rightIsChecked: false,
isRightNode: true,
isLeftNode: false,
isRootNode: false,
},
prevNodes,
)
} else {
throw new TreeIsNotBalanced()
}
} else {
if (currentNode.leftIsChecked && currentNode.rightIsChecked && currentNode.isRootNode) {
// . If left and right nodes were checked and this is Root node, than return true
return true
}
const prevNode = prevNodes.pop()
if (prevNode) {
if (prevNode.leftIsChecked) {
// . If prevNode left branch was checked, than we were on right node, so we set prevNode right branch checked
return this.nodeIsBalanced({ ...prevNode, rightIsChecked: true }, prevNodes)
} else {
// . If prevNode left branch wasn't checked, we set it checked
return this.nodeIsBalanced({ ...prevNode, leftIsChecked: true }, prevNodes)
}
} else {
// . Critical error, because this can't happen
throw new Error("prev node must exist")
}
}
}
public static isBalanced(tree: Tree): boolean {
return this.nodeIsBalanced(
{
node: tree.root,
leftIsChecked: false,
rightIsChecked: false,
isLeftNode: false,
isRightNode: false,
isRootNode: true,
},
[],
)
}
}
describe("binary tree checking is balanced", function () {
it("should return true", function () {
const tree: Tree = {
root: {
value: 45,
left: {
value: 34,
left: {
value: 17,
},
right: {
value: 38,
left: {
value: 36,
left: {
value: 35,
},
right: {
value: 37,
},
},
right: {
value: 42,
},
},
},
right: {
value: 60,
left: {
value: 50,
},
right: {
value: 65,
},
},
},
}
const res = BinaryTreeNodeChecker.isBalanced(tree)
expect(res).toBeTruthy()
})
it("should throw error", function () {
const tree: Tree = {
root: {
value: 45,
left: {
value: 34,
left: {
value: 17,
},
right: {
value: 38,
left: {
value: 36,
left: {
value: 35,
},
right: {
value: 37,
},
},
right: {
value: 42,
},
},
},
right: {
value: 60,
left: {
value: 40, // error
},
right: {
value: 65,
},
},
},
}
expect(() => BinaryTreeNodeChecker.isBalanced(tree)).toThrowError()
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment