Tree is an abstract model of hierarchical data.
Two fork tree
A node in a binary tree can only have two byte points at most: one is the left child node, the other is the right child node.
Binary Search Tree
Binary search tree (BST) is a kind of binary tree, but it only allows you to store values smaller than the parent node in the left node and larger or equal than the parent node in the right node.
Binary search tree code implementation:
function BinarySearchTree(){ var Node = function(key){ this.key = key; this.left = null; this.right = null; } var root = null; // Insert a key into the tree this.insert = function(key){ var newNode = new Node(key); if(root === null){ root = newNode; }else{ insertNode(root, newNode); } }; var insertNode = function(node, newNode){ if(newNode.key < node.key){ if(node.left === null){ node.left = newNode; }else{ insertNode(node.left, newNode); } }else{ if(node.right === null){ node.right = newNode; }else{ insertNode(node.right, newNode); } } } function printNode(value){ console.log(value); } // Sequential traversal // Intermediate traversal is to access all nodes in order from small to large. One application of mid-order traversal is to sort trees this.inOrderTraverse = function(callback){ inOrderTraverseNode(root, callback); } var inOrderTraverseNode = function(node , callback){ if(node !== null){ //Recursive Termination Conditions inOrderTraverseNode(node.left, callback); callback(node.key); inOrderTraverseNode(node.right, callback); } } // Preorder traversal // Sequential traversal is to access each node in the order that it takes precedence over the descendant nodes. One application of sequential traversal is to print a structured document this.preOrderTraverse = function(callback){ preOrderTraverseNode(root, callback); } var preOrderTraverseNode = function(node, callback){ if(node !== null){ callback(node.key); preOrderTraverseNode(node.left, callback); preOrderTraverseNode(node.right, callback); } } // Post order traversal // Later traversal is to access the descendant node of the node first, and then the node itself. An application of post-order traversal is to calculate the size of space occupied by all files in a directory and its subdirectories. this.postOrderTraverse = function(callback){ postOrderTraverseNode(root, callback); } var postOrderTraverseNode = function(node, callback){ if(node !== null){ postOrderTraverseNode(node.left, callback); postOrderTraverseNode(node.right, callback); callback(node.key); } } // Search for minimum and maximum // Search for Minimum Value this.min = function(){ return minNode(root); } var minNode = function(node){ if(node){ while(node && node.left !== null){ node = node.left; } console.log(node.key); return node.key } return null; } // Search for maximum this.max = function(){ return maxNode(root); } var maxNode = function(node){ if(node){ while(node && node.right !== null){ node = node.right; } console.log(node.key) return node.key; } return null; } // Search for a specific value this.search = function(key){ return searchNode(root, key); } var searchNode = function(node, key){ if(node === null){ console.log('Node does not exist!!!'); return false; } if(key < node.key){ return searchNode(node.left, key); }else if(key > node.key){ return searchNode(node.right, key); }else{ console.log('Node existence!!!'); return true; } }; // Remove a node this.remove = function(key){ // Set the pointer of the parent node of the node to null root = removeNode(root, key); } var removeNode = function(node, key){ if(node === null){ return null; } if(key < node.key){ node.left = removeNode(node.left, key); return node; } else if(key > node.key){ node.right = removeNode(node.right, key); return node; }else{ //Key equals node.key // The first case - a leaf node if(node.left === null && node.right === null){ node = null; return node; } // The second case - - a node with only one child node if(node.left === null){ node = node.right; return node; }else if(node.right === null){ node = node.left; return node; } // The third case - a node with two sub-nodes var findMinNode = function(node){ while(node && node.left !== null){ node = node.left; } return node; } var aux = findMinNode(node.right); node.key = aux.key; node.right = removeNode(node.right, aux.key); return node; } } }
Test:
function printNode(value){ console.log(value); } var tree = new BinarySearchTree() tree.insert(11) tree.insert(7) tree.insert(15) tree.insert(5) tree.insert(3) tree.insert(9) tree.insert(8) tree.insert(10) tree.insert(13) tree.insert(12) tree.insert(14) tree.insert(20) tree.insert(18) tree.insert(25) tree.insert(6) tree.inOrderTraverse(printNode); //3 5 6 7 8 9 10 11 12 13 14 15 18 20 25 tree.preOrderTraverse(printNode); //11 7 5 3 6 9 8 10 15 13 12 14 20 18 25 tree.postOrderTraverse(printNode); //3 6 5 8 10 9 7 12 14 13 18 25 20 15 11 tree.min(); //3 tree.max(); //25 tree.search(9); //Node existence tree.remove(25); tree.postOrderTraverse(printNode); //3 6 5 8 10 9 7 12 14 13 18 20 15 11
balanced binary tree
Balanced Binary Tree (AVL): The height difference between the left and right subtrees of any node is at most 1.
AVL tree is a self-balancing tree. When nodes are added or removed, the AVL tree tries to self-balance. The maximum difference between the height of the left subtree and the right subtree of any node is 1. When adding or removing nodes, the AVL tree will try to convert to a full tree as much as possible.