Last active
September 16, 2016 22:27
-
-
Save frio80/638a19618494ec29ea4aecad726f1b65 to your computer and use it in GitHub Desktop.
Fun with Binary 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
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Binary Tree Fun</title> | |
<meta charset="UTF-8"> | |
<style> | |
blink, .blink { | |
-webkit-animation: blink 1s step-end infinite; | |
-moz-animation: blink 1s step-end infinite; | |
-o-animation: blink 1s step-end infinite; | |
animation: blink 1s step-end infinite; | |
color: red; | |
font-weight: bold; | |
font-size: 2rem; | |
} | |
@-webkit-keyframes blink { | |
67% { opacity: 0 } | |
} | |
@-moz-keyframes blink { | |
67% { opacity: 0 } | |
} | |
@-o-keyframes blink { | |
67% { opacity: 0 } | |
} | |
@keyframes blink { | |
67% { opacity: 0 } | |
} | |
</style> | |
<script> | |
if (typeof window.customElements === 'undefined') { | |
alert('Y U NO USE GOOD BROWSER?! Try Chrome Canary!'); | |
} | |
class BinaryTree extends HTMLElement { | |
static get observedAttributes() { | |
return ["tree", "nonleafnode"]; | |
} | |
set tree(t) { | |
this.setAttribute('tree', t); | |
} | |
get tree() { | |
return this._tree; | |
} | |
/** | |
* Expose Shadow DOM | |
*/ | |
get DOMTree() { | |
return this.shadowRoot.childNodes[3]; | |
} | |
constructor(/*list, makeNodeForNonLeaf = false*/) { | |
super(); // always call super() first in the ctor. | |
this._tree = null; | |
this.div = document.createElement('div'); | |
this.template = document.querySelector('#binary-tree-template'); | |
} | |
_createNode(val) { | |
var node = this.div.cloneNode(false); | |
node.textContent = val; | |
return node; | |
} | |
_buildDOMTree(root, tree) { | |
var div; | |
if (tree[0] !== null) { | |
div = this._createNode(tree[0]); | |
root.appendChild(div); | |
if (tree[1] !== null) this._buildDOMTree(div, tree[1]); | |
} | |
if (tree[2] !== null) { | |
div = this._createNode(tree[2]); | |
root.appendChild(div); | |
if (tree[3] !== null) this._buildDOMTree(div, tree[3]); | |
} | |
return; | |
} | |
connectedCallback() { | |
this._drawTree(this._tree); | |
} | |
disconnectCallback() {} | |
attributeChangedCallback(name, oldValue, newValue) { | |
switch (name) { | |
case "tree": this._tree = newValue; break; | |
default: break; | |
} | |
} | |
_drawTree(binaryTree) { | |
let root, tree, DOMtree, shadowRoot; | |
shadowRoot = this.attachShadow({mode: 'open'}); | |
[root, tree] = JSON.parse(binaryTree); | |
DOMtree = this._createNode(root); | |
shadowRoot.appendChild(this.template.content.cloneNode(true)); | |
this._buildDOMTree(DOMtree, tree); | |
shadowRoot.appendChild(DOMtree); | |
} | |
} | |
window.customElements.define('binary-tree', BinaryTree); | |
</script> | |
</head> | |
<body> | |
<h1>Binary Tree Fun!</h1> | |
<h3>Pre-Order Traversal with TreeWalker!</h3> | |
<p>A tree is "superbalanced" if the difference between the depths of any two leaf nodes is no greater than one.</p> | |
<template id="binary-tree-template"> | |
<style> | |
* { | |
line-height: 50px; | |
text-align: center; | |
color: white; | |
background-color: lightgrey; | |
} | |
span { | |
display: block; | |
} | |
div { | |
margin-top: 54px; | |
height: 50px; | |
border: 1px solid #333333; | |
border-radius: 26px; | |
min-width: 50px; | |
float: left; | |
} | |
div > div:last-child { | |
float:right; | |
} | |
</style> | |
</template> | |
<binary-tree | |
tree="[100, [50, [10, [4, [1, null, 6, null], 11, null], 60, [50, null, 70, [65, null, 71, null]]], 150, [140, [130, null, 150, null], 160, [159, null, 161, null]]]]"> | |
<!-- | |
Non Super Balanced | |
[100, [50, [10, [4, [1, null, 6, [5, null, 7, null]], 11, null], 60, [50, null, 70, [65, null, 71, null]]], 150, [140, null, 160, null]]] | |
Super Balanced | |
[100, [50, [10, [4, [1, null, 6, null], 11, null], 60, [50, null, 70, [65, null, 71, null]]], 150, [140, [130, null, 150, null], 160, [159, null, 161, null]]]] | |
--> | |
</binary-tree> | |
<script> | |
customElements.whenDefined('binary-tree').then(() => { | |
let treeWalker = document.createTreeWalker( | |
document.getElementsByTagName('binary-tree')[0].DOMTree, | |
NodeFilter.SHOW_ELEMENT | |
); | |
let maxHeight = 0; | |
let minHeight = 0; | |
const isLeaf = (node) => node.children.length === 0; | |
const visitLeaf = (node) => node.style.backgroundColor = '#167F31'; | |
const visitNonLeaf = (node) => node.style.backgroundColor = '#865B45'; | |
const visitNode = (node) => { | |
node.dataset.height = parseInt(node.parentNode.dataset.height) + 1; | |
isLeaf(node) ? visitLeaf(node) : visitNonLeaf(node); | |
return node.dataset.height; | |
}; | |
const runner = (generatorObject) => { | |
if (!generatorObject.next().done) setTimeout(() => runner(generatorObject), 200); | |
}; | |
visitNonLeaf(treeWalker.currentNode); | |
treeWalker.currentNode.dataset.height = 0; | |
/** | |
* Pre Order Traversal | |
* | |
* We visit the nodes, check if it's a leaf and then check the height. | |
* | |
*/ | |
runner(function* preOrderTraversal() { | |
let blink = document.createElement('blink'); | |
while (treeWalker.nextNode()) { | |
let height = parseInt(visitNode(treeWalker.currentNode)); | |
if (isLeaf(treeWalker.currentNode)) | |
if (minHeight === 0) minHeight = height; | |
else if (height > maxHeight) maxHeight = height; | |
else if (height < minHeight) minHeight = height; | |
yield; | |
} | |
blink.textContent = ((maxHeight - minHeight > 1) ? 'Not ' : '') + 'SuperBalanced'; | |
document.body.appendChild(blink); | |
}()); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment