Created
July 6, 2020 16:06
-
-
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
This file contains hidden or 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
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