A Tree and Node class for Binary Search. Three unique sorts are shown here.
A Pen by HARUN PEHLİVAN on CodePen.
| <div> | |
| <h1>No Sort</h1> | |
| <ul></ul> | |
| </div> | |
| <div> | |
| <h1>By X</h1> | |
| <ul></ul> | |
| </div> | |
| <div> | |
| <h1>By Y</h1> | |
| <ul></ul> | |
| </div> | |
| <div> | |
| <h1>By Prox</h1> | |
| <ul></ul> | |
| </div> |
| console.clear(); | |
| let tmpId = 0; | |
| class BinaryTree { | |
| constructor(title) { | |
| this.title = title; | |
| this.rootNode = null; | |
| this.orderAB = null; | |
| this.orderBA = null; | |
| } | |
| // Setting a node as this tree's rootNode, or passing along to the rootNode | |
| add(node) { | |
| this.rootNode ? this.rootNode.add(node) : (this.rootNode = node); | |
| } | |
| // Recursively traversing through nodes to build an array of ids | |
| save() { | |
| let ascending = this.rootNode ? this.rootNode.traverse([]) : []; | |
| this.ascending = ascending; | |
| this.descending = ascending ? ascending.slice().reverse() : []; | |
| } | |
| // Recursively searching nodes for a value, returns an array of ids. | |
| search(value) { | |
| return this.rootNode ? this.rootNode.search(value) : []; | |
| } | |
| } | |
| class BinaryNode { | |
| // BinaryNode takes the value to sort by, and an identifier to return it's position by | |
| constructor({ value, id }) { | |
| // Ids is always an array (for handling duplicates) | |
| this.ids = [id]; | |
| // Set the value | |
| this.value = value; | |
| if (value === undefined) console.warn(`No value provided for BinaryNode ${id}`); | |
| // Left is the "less than" node | |
| this.left = null; | |
| // Right is the "greater than" node | |
| this.right = null; | |
| } | |
| // Recursive function for finding a value in this node or this node's children | |
| search(value) { | |
| // If value is found here, return this node's ids. | |
| if (this.value === value) { | |
| return this.ids; | |
| // If value is less than here, and we have left, search "less thans". | |
| } else if (value < this.value && this.left) { | |
| return this.left.search(value); | |
| // If value is more than here, and we have right, search "greater thans". | |
| } else if (value > this.value && this.right) { | |
| return this.right.search(value); | |
| } | |
| // Value does not exist | |
| return null; | |
| } | |
| // Recursive function for building an array of ids in a sorted order | |
| traverse(array) { | |
| // If left, visit "less thans" down the chain | |
| if (this.left) array = this.left.traverse(array); | |
| // Add this node's ids | |
| array = array.concat(this.ids); | |
| // If right, visit "greater thans" down the chain | |
| if (this.right) array = this.right.traverse(array); | |
| // Return the array | |
| return array; | |
| } | |
| // Recursive function to set node as this node's left or right position | |
| // or to pass along down left or right chain. | |
| add(node) { | |
| // If less, we defer to or set left | |
| if (node.value < this.value) { | |
| this.left ? this.left.add(node) : (this.left = node); | |
| // If greater, we defer to or set right | |
| } else if (node.value > this.value) { | |
| this.right ? this.right.add(node) : (this.right = node); | |
| // If same value, we add ids to this node | |
| } else { | |
| this.ids = this.ids.concat(node.ids); | |
| } | |
| } | |
| } | |
| // A dummy class containing data we want to be able to search. | |
| class Vector { | |
| constructor({ x, y }) { | |
| this.x = x; | |
| this.y = y; | |
| this.prox = Math.hypot(0.5 - x, 0.5 - y); | |
| this.id = generateId(); | |
| this.info = [ | |
| `#${this.id}`, | |
| `${this.x}x`, | |
| `${this.y}y`, | |
| `${Math.round(this.prox)}p` | |
| ]; | |
| } | |
| } | |
| let indexX = new BinaryTree("Vector X"); | |
| let indexY = new BinaryTree("Vector Y"); | |
| let indexP = new BinaryTree("Vector Proximity"); | |
| let vectors = {}; | |
| for (let i = 0; i < 50; i++) { | |
| let x = Math.round(Math.random() * 1000); | |
| let y = Math.round(Math.random() * 1000); | |
| let vector = new Vector({ x, y }); | |
| vectors[vector.id] = vector; | |
| indexX.add(new BinaryNode({ id: vector.id, value: vector.x })); | |
| indexY.add(new BinaryNode({ id: vector.id, value: vector.y })); | |
| indexP.add(new BinaryNode({ id: vector.id, value: vector.prox })); | |
| } | |
| indexX.save(); | |
| indexY.save(); | |
| indexP.save(); | |
| let $ulS = document.querySelector('div:nth-of-type(1) ul'); | |
| let $ulX = document.querySelector('div:nth-of-type(2) ul'); | |
| let $ulY = document.querySelector('div:nth-of-type(3) ul'); | |
| let $ulP = document.querySelector('div:nth-of-type(4) ul'); | |
| Object.keys(vectors).forEach((id) => { | |
| $ulS.appendChild(li(id, vectors[id].info)); | |
| }); | |
| indexX.ascending.forEach((id) => { | |
| $ulX.appendChild(li(id, vectors[id].info)); | |
| }); | |
| indexY.ascending.forEach((id) => { | |
| $ulY.appendChild(li(id, vectors[id].info)); | |
| }); | |
| indexP.ascending.forEach((id) => { | |
| $ulP.appendChild(li(id, vectors[id].info)); | |
| }); | |
| function li(id, value) { | |
| let $li = document.createElement('li'); | |
| $li.className = `id${id}`; | |
| $li.innerHTML = `<span>${value.join('</span><span>')}</span>`; | |
| $li.addEventListener('mouseenter', () => { handleMouseEnter(id); }); | |
| $li.addEventListener('mouseleave', () => { handleMouseLeave(id); }); | |
| return $li; | |
| } | |
| function handleMouseEnter(id) { | |
| let els = document.body.querySelectorAll(`.id${id}`); | |
| for (let i = 0; i < els.length; i++) els[i].classList.add('active'); | |
| } | |
| function handleMouseLeave(id) { | |
| let els = document.body.querySelectorAll(`.id${id}.active`); | |
| for (let i = 0; i < els.length; i++) els[i].classList.remove('active'); | |
| } | |
| let lis = document.body.querySelectorAll('li'); | |
| Array.from(lis).forEach((li) => { | |
| li.addEventListener('hover', () => { | |
| let classname = li.className; | |
| let els = document.body.querySelectorAll(`li.id${classname}`); | |
| Array.from(els).forEach((el) => { | |
| el.classList.add('active') | |
| }) | |
| }); | |
| }) | |
| function generateId() { | |
| tmpId++; | |
| if (tmpId < 10) return `00${tmpId}`; | |
| if (tmpId < 100) return `0${tmpId}`; | |
| return tmpId.toString(); | |
| } |
| html, body { | |
| height: 100%; | |
| } | |
| h1 { | |
| font-weight: 300; | |
| font-family: 'Helvetica Neue', Helvetica, sans-serif; | |
| color: white; | |
| } | |
| body { | |
| display: flex; | |
| padding: 0 0.5rem; | |
| background: #121212; | |
| div { | |
| flex: 1; | |
| text-align: center; | |
| box-sizing: border-box; | |
| padding: 0 0.5rem; | |
| } | |
| } | |
| ul { | |
| list-style: none; | |
| padding: 0; | |
| font-family: 'Operator Mono SSm', monospace; | |
| font-size: 0.8rem; | |
| } | |
| li { | |
| cursor: pointer; | |
| padding: 0.25rem 0; | |
| display: flex; | |
| justify-content: space-between; | |
| flex-wrap: wrap; | |
| color: #444; | |
| span { | |
| text-align: center; | |
| flex: 1; | |
| } | |
| } | |
| li.active { | |
| color: white; | |
| background: black; | |
| } |
A Tree and Node class for Binary Search. Three unique sorts are shown here.
A Pen by HARUN PEHLİVAN on CodePen.