Tree is the basic knowledge point of data structure. There is a special binary tree in the tree. We will not explain the concept of tree in detail here, but use js to realize a simple binary tree
1. Add node
2. Remove the node
3. Node maximum / minimum
4. Middle order traversal
5. Preorder traversal
6. Post order traversal
7. Find whether the specified node exists
8. Empty tree or not
If you don't want to talk about it, first of all, the basic unit node class of the tree
/** *left:Left tree *right:Right subtree *value:Node value */ export default class BinaryNode { constructor(val) { this.value = val; this.left = null; this.right = null; } }
Next is the binary tree class code
import BinaryNode from './BinaryNode' export default class BinarySearchTree { constructor() { this.root = null; this.values = new Array(); } /** * [insert Insert node] * @param {[type]} val [description] * @return {[type]} [description] */ insert(val) { this.values.push(val); let node = new BinaryNode(val); if (!this.root) { this.root = node; }else { this._insertNode(this.root, node); } } /** * [remove Remove specified value] * @param {[*]} val [Target value] * @return {[type]} [description] */ remove(val) { this.root = this._removeNode(this.root, val); } /** * [search Search] * @param {[*]} val [Retrieved value] * @return {[Boolean]} [Indicates whether it exists] */ search(val) { let values = this.inOrderTraverse(); return values.includes(val); } /** * [min Return minimum] * @return {[type]} [description] */ min() { let values = this.inOrderTraverse(); return values[0]; } /** * [max Return maximum] * @return {[type]} [description] */ max() { let values = this.inOrderTraverse(); return values[values.length - 1]; } /** * [isEmpty Empty binary tree or not] * @return {Boolean} */ isEmpty() { return this.root === null; } /** * [inOrderTraverse Middle order traversal] * @return {[Array]} [description] */ inOrderTraverse() { let result = new Array(); this._inOrderTraverseNode(this.root, function(node) { result.push(node.value); }) return result; } /** * [preOrderTraverse Preorder traversal] * @return {[Array]} [description] */ preOrderTraverse() { let result = new Array(); this._preOrderTraverseNode(this.root, function(node) { result.push(node.value); }) return result; } /** * [postOrderTraverse Backward traversal] * @return {[Array]} [description] */ postOrderTraverse() { let result = new Array(); this._postOrderTraverseNode(this.root, function(node) { result.push(node.value); }) return result; } /** * [_insertNode Insert node at specified node] * @param {[BinaryNode]} node [Target node] * @param {[BinaryNode]} newNode [Nodes to be inserted] */ _insertNode(node, newNode) { if (node.value > newNode.value) { if (node.left) { this._insertNode(node.left, newNode); }else { node.left = newNode; } }else { if (node.right) { this._insertNode(node.right, newNode); }else { node.right = newNode; } } } /** * [_removeNode Remove node recursion] * @param {[BinaryNode]} node [Current node] * @param {[*]} val [Divide node value to move] * @return {[BinaryNode]} [Current node] */ _removeNode(node, val) { if (node === null) { return node; } //Recursively finding the target node if (val < node.value) { this._removeNode(node.left, val); return node; } if (val > node.value) { this._removeNode(node.right, val); return node; } //Target node found if (val === node.value) { //Is a leaf node if (node.left === null && node.right === null) { node = null; return node; } //Only one child node if (node.left === null) { node = node.right; return node; }else if (node.right === null) { node = node.left; return node; } //There are two child nodes let min_node = this._findMinNode(node); node.value = min_node.value; node.right = this._removeNode(node.right, min_node.value); return node; } } /** * [_findMinNode Find the smallest node] * @param {[BinaryNode]} node [Current node] * @return {[BinaryNode]} [Smallest node] */ _findMinNode(node) { while(node && node.left) { node = node.left; } return node; } /** * [_inOrderTraverseNode Middle order traversal recursion] * @param {[BinaryNode]} node [Current node] * @param {Function} callback [Callback function] * @return {[type]} [description] */ _inOrderTraverseNode(node, callback) { if (node) { this._inOrderTraverseNode(node.left, callback); callback(node); this._inOrderTraverseNode(node.right, callback); } } /** * [_preOrderTraverseNode Traversal recursion] * @param {[BinaryNode]} node [Current node] * @param {Function} callback [Callback function] * @return {[type]} [description] */ _preOrderTraverseNode(node, callback) { if (node) { callback(node); this._preOrderTraverseNode(node.left, callback); this._preOrderTraverseNode(node.right, callback); } } /** * [_postOrderTraverseNode Backward traversal recursion] * @param {[BinaryNode]} node [Current node] * @param {Function} callback [Callback function] * @return {[type]} [description] */ _postOrderTraverseNode(node, callback) { if (node) { this._postOrderTraverseNode(node.left, callback); this._postOrderTraverseNode(node.right, callback); callback(node); } } }
The function of each function is in the annotation. Here, a lot of recursion is used for tree traversal. Recursion is relatively simple and easy to understand. Here, finding the maximum and minimum value is lazy. Instead of recursive search, we directly get the maximum and minimum value in the middle order traversal. Note that here is the value, not the node of the tree. In fact, the code to find the minimum node is also written as a private function , it's just not used to find the maximum and minimum value
Of course, it's just a simple binary tree, and it can also be upgraded to AVL tree, etc., which will not be covered here