Loading...
(function(){<br />
let canvas = document.createElement('canvas'),<br />
ctx = canvas.getContext('2d'),<br />
w = canvas.width = innerWidth,<br />
h = canvas.height = innerHeight,<br />
particles = [],<br />
properties = {<br />
bgColor : 'rgba(17, 17, 19, 1)',<br />
particleColor : 'rgba(255, 40, 40, 1)',<br />
particleRadius : 3,<br />
particleCount : 60,<br />
particleMaxVelocity : 0.5,<br />
lineLength : 150,<br />
particleLife : 6,<br />
};<br />
<br />
document.querySelector('body').appendChild(canvas);<br />
<br />
window.onresize = function() {<br />
w = canvas.width = innerWidth;<br />
h = canvas.height = innerHeight;<br />
}<br />
<br />
class Particle {<br />
constructor() {<br />
this.x = Math.random()*w;<br />Loading...
This is a short expanded summary of the section about trees in the book Computer Science Guide by William Springer.
A tree is simply a connected graph with no cycles. One vertex is designated as the root, and all other vertices are defined by their relationship to the root.
An example of a tree is the DOM tree.
The following definitions are equivalent for a tree:
A tree has two types of nodes:
Below is an example of a tree with ten vertices and one internal node.

Besides binary trees, trees with four nodes (quadtrees) are also widely used in practice. They are used in game development to organize grids. Each node in such a tree represents one direction (northwest, southeast, and so on).
If needed, this list can be extended with more complex algorithms:
(Example taken from a reference site)
[3, 2, [3, 8], [[8], 3]];
Where:
(Example taken from this website)
1class BinaryTreeNode {2 constructor(value) {3 this.left = null;4 this.right = null;5 this.parent = null;6 this.value = value;7 }89 get height() {10 let leftHeight = this.left ? this.left.height + 1 : 0;11 let rightHeight = this.right ? this.right.height + 1 : 0;12 return Math.max(leftHeight, rightHeight);13 }1415 // When inserting, it is important to update all affected references: left or right for the parent node and parent for the child node. If the parent already had a child, its parent property should be set to null.161718 setLeft(node) {19 if (this.left) {20 this.left.parent = null;21 }22 if (node) {23 this.left = node;24 this.left.parent = this;25 }26 }2728 setRight(node) {29 if (this.right) {30 this.right.parent = null;31 }32 if (node) {33 this.right = node;34 this.right.parent = this;35 }36 }37}38let aNode = new BinaryTreeNode('a');3940let bNode = new BinaryTreeNode('b');41aNode.setLeft(bNode);4243let cNode = new BinaryTreeNode('c');44aNode.setRight(cNode);4546let dNode = new BinaryTreeNode('d');47bNode.setRight(dNode);4849let eNode = new BinaryTreeNode('e');50cNode.setLeft(eNode);5152let fNode = new BinaryTreeNode('f');53cNode.setRight(fNode);
A Binary Search Tree (BST) is a rooted binary tree where each node has at most two children.
It is defined recursively:
This ordering makes searching efficient because half of the tree can be ignored at each step.

Time complexity is proportional to tree height — the length of the longest path from root to leaf.
In the general case, this is Θ(lg n).
The Θ notation means that the execution time is bounded both from above and below; the height of the tree must be at least lg n.
In the worst case (when each node has only one child, which essentially turns the tree into a linked list — an unbalanced binary search tree), the complexity is O(n).
Below is an example of an unbalanced binary tree.

A binary search tree can be implemented as a collection of linked nodes — each node contains a key and pointers to the left and right child nodes, as well as to the parent node.
The examples are taken from this website.
The first added node becomes the root of the tree.
Next, we compare the value of the new element with the value of the parent node. If it is greater, we place the element in the left branch; if it is smaller, we place it in the right branch.
We build the tree in the same way as in the previous example, but this time we add a new method for inserting elements. This method compares values and places the element into the appropriate branch.
1class BinarySearchTreeNode extends BinaryTreeNode {2 constructor(value, comparator) {3 super(value);4 this.comparator = comparator;5 }67 insert(value) {8 if (this.comparator(value, this.value) < 0) {9 if (this.left) return this.left.insert(value);10 let newNode = new BinarySearchTreeNode(value, this.comparator);11 this.setLeft(newNode);1213 return newNode;14 }1516 if (this.comparator(value, this.value) > 0) {17 if (this.right) return this.right.insert(value);18 let newNode = new BinarySearchTreeNode(value, this.comparator);19 this.setRight(newNode);2021 return newNode;22 }23 return this;24 }25}2627class BinarySearchTree {28 constructor(value, comparator) {29 this.root = new BinarySearchTreeNode(value, comparator);30 this.comparator = comparator;31 }3233 insert(value) {34 if (!this.root.value) this.root.value = value;35 else this.root.insert(value);36 }37}3839const comparator = (a, b) => a - b;40/*41If 0 is returned, it means that the numbers are equal;42if a negative number is returned, it means the value is less than the target value;43if a positive number is returned, it means the value is greater than the target value.44*/4546const tree = new BinarySearchTree(14, comparator);47tree.insert(9);48tree.insert(124);49tree.insert(3);50tree.insert(19);51tree.insert(45);52tree.insert(1);53tree.insert(8);54tree.insert(59);
All new values greater than the root go to the left branch, while smaller values go to the right branch. Therefore, the tree in the example above should look like this:

To delete a node d, we need to find it in the tree and then perform the following steps:
d has no children — set the pointer of the parent node that currently references d to null.d has one child — the child takes the place of d.d has two children — find the next node in order (the minimum node in the right subtree of the node being deleted) and replace d with it.1// Add helper methods to the BinarySearchTreeNode class2class BinarySearchTreeNode extends BinaryTreeNode {3 // ...45 // Find the minimum element in the subtree6 findMin() {7 if (!this.left) {8 return this;9 }1011 return this.left.findMin();12 }1314 // Remove the specified element if it is a child of this node.15 removeChild(nodeToRemove) {16 if (this.left && this.left === nodeToRemove) {17 this.left = null;18 return true;19 }2021 if (this.right && this.right === nodeToRemove) {22 this.right = null;23 return true;24 }2526 return false;27 }2829 // Replace a child element with a new one.30 replaceChild(nodeToReplace, replacementNode) {31 if (!nodeToReplace || !replacementNode) {32 return false;33 }3435 if (this.left && this.left === nodeToReplace) {36 this.left = replacementNode;37 return true;38 }3940 if (this.right && this.right === nodeToReplace) {41 this.right = replacementNode;42 return true;43 }4445 return false;46 }47}4849// Add the remove method to the BinarySearchTree class50class BinarySearchTree {51 //...5253 remove(value) {54 const nodeToRemove = this.find(value);5556 if (!nodeToRemove) {57 throw new Error("Item not found");58 }5960 const parent = nodeToRemove.parent;6162 // No children, leaf node63 if (!nodeToRemove.left && !nodeToRemove.right) {64 if (parent) {65 // Remove the pointer to the deleted child from the parent node66 parent.removeChild(nodeToRemove);67 } else {68 // No parent, root node69 nodeToRemove.value = undefined;70 }71 }7273 // Has both left and right children74 else if (nodeToRemove.left && nodeToRemove.right) {75 // Find the minimum value in the right subtree76 // And place it in the position of the deleted node77 const nextBiggerNode = nodeToRemove.right.findMin();7879 if (this.comparator(nextBiggerNode, nodeToRemove.right) === 0) {80 // The right child is also the minimum value in the right subtree,81 // meaning it has no left subtree.82 // We can simply replace the deleted node with its right child.8384 nodeToRemove.value = nodeToRemove.right.value;85 nodeToRemove.setRight(nodeToRemove.right.right);86 } else {87 // Delete the found node (recursion)88 this.remove(nextBiggerNode.value);89 // Update the value of the node being deleted90 nodeToRemove.value = nextBiggerNode.value;91 }92 }9394 // Has only one child (left or right)95 else {96 // Replace the deleted node with its child97 const childNode = nodeToRemove.left || nodeToRemove.right;9899 if (parent) {100 parent.replaceChild(nodeToRemove, childNode);101 } else {102 this.root = childNode;103 }104 }105106 // Remove the reference to the parent107 nodeToRemove.parent = null;108109 return true;110 }111}112
A self-balancing binary search tree is a tree that automatically maintains a small height (compared to the number of required levels), regardless of adding or deleting nodes.
Its height can be greater than the minimum possible height, but it will still be Θ(lg n).