Learning JavaScript Data Structure and Algorithms (Chapter 8) (Trees)

1. Binary search tree (two conditions):

(1) There are at most two sub-nodes in the binary tree: one is the left node, the other is the right sub-node.
(2) Only values smaller than the parent node are allowed to be stored in the left node, while values larger (or equal to) are allowed in the right node.

2. Code Architecture:

It mainly includes insert, search, removce, traverse and other functions.

var Tree = function() {
    var Node = function(value) {
        this.value = value;
        this.left = null;  //Left node
        this.right = null; //Right node
    }
    var root = null;    //Root node  
    /*
    Insert node:
    1,The tree is empty.
    2,Trees are not empty - > comparative (less than - > go left; greater than - > go right)
    */ 
    this.insert = function(value) {};
    //Search nodes (search for a specific value)
    this.search = function(value) {};
    //A Method of Finding the Minimum Key of a Tree
    this.min = function() {};
    //A Method of Finding the Maximum Key of a Tree
    this.max = function() {};
    /*
    Remove nodes:
    1,Simplest case: Remove leaf nodes
    2,Remove a node with only one child node
    3,Remove the node with two sub-nodes (replaced by the smallest node in the right subtree)
    */
    this.remove =function(value) {
    };
    //Traversing node
    this.traverse = function(callback) {};
    
    //Display tree
    this.getRoot = function() {};
}

3. Overall detailed code section

var Tree = function() {
    var Node = function(value) {
        this.value = value;
        this.left = null;
        this.right = null;
    }
    var root = null;    //Root node  
    /*
    Insert node:
    1,The tree is empty.
    2,Trees are not empty - > comparative (less than - > go left; greater than - > go right)
    */ 
    this.insert = function(value) {
        var newNode = new Node(value);
        if(root == null) { //Empty tree          
            root = newNode;
        }else{//Trees are not empty.           
            insertNode(root, newNode);
        }
    };
    var insertNode = function(node, newNode) {
        if(newNode.value > node.value) {
            //Go right.
            if(node.right == null) {
                node.right = newNode;
            }else{
                insertNode(node.right, newNode);
            }   
        }else if(newNode.value < node.value) {
            //Go to the left.
            if(node.left == null) {
                node.left = newNode;
            }else{
                insertNode(node.left, newNode);
            }
        }
    };


    //Search nodes (search for a specific value)
    this.search = function(value) {
        return searchNode(root, value);
    };
    var searchNode = function(node, value) {
        if(node === null) {
            return false;
        }
        if(value < node.value) {
            return searchNode(node.left, value);
        }else if(value > node.value) {
            return searchNode(node.right, value);
        }else{
            return true;
        }
    };
   //A Method of Finding the Minimum Key of a Tree
   this.min = function() {
       return minNode(root);
   };
   var minNode = function(node) {
       if(node) {
           while(node && node.left !== null) {
               node = node.left;
           }
           return node.value;
       }
       return null;
   };
   //A Method of Finding the Maximum Key of a Tree
   this.max = function() {
       return maxNode(root);
   };
   var maxNode = function(node) {
       if(node) {
           while(node && node.right !== null) {
               node = node.right;
           }
           return node.value;
       }
       return null;
   };

    /*
    Remove nodes:
    1,Simplest case: Remove leaf nodes
    2,Remove a node with only one child node
    3,Remove the node with two sub-nodes (replaced by the smallest node in the right subtree)
    */
    this.remove =function(value) {
        root = removeNode(root, value);
    };
    var removeNode = function(node,value) {
        if( node == null) return null;
        if(node.value < value) {
            //Continue to look to the right
            node.right = removeNode(node.ritht , value);
            return node;
        }else if(node.value > value) {
            //Search left
            node.left = removeNode(node.left, value);
            return node;
        }else{
            //value == node.value
            //Execute the deletion process
            //Leaf Node Conditions
            if(node.left == null && node.right == null) {
                node = null;
                return node;
            }
            //Only one subnode condition
            if(node.left == null && node.right) {
                node = node.right;
                return node;     
            }else if(node.right == null && node.left){
                node = node.left;
                return node;
            }

            //There are two child nodes (replaced by the smallest node of the right subtree)
            var aux = findMinNode(node.right);   //aux is the smallest child found
            node.value = aux.value;
            node.right = removeNode(node.right, aux.value);
            return node;
        }
    };
    var findMinNode = function(node) {
        if(node == null) return null;
        while(node && node.left) {
            node = node.left
        }
        return node;
    };


    //Traversing node
    this.traverse = function(callback) {
        traverse(root, callback);
    };
    var traverse = function(node, callback) {
        if(node == null) return;
        //(follow-up traversal) left-right middle; (middle-order traversal) left-right; (pre-order traversal) middle-left
        traverse(node.left, callback);
        traverse(node.right, callback);
        callback(node.value);
    };
    
    //Display tree
    this.getRoot = function() {
        return root;
    };
}

4. Code Function Verification Test

var t = new Tree;
var print = function(value) {
    console.log('value -',value)   
};

t.insert(11);
t.insert(8);
t.insert(4);
t.insert(9);
t.insert(3);
t.insert(5);

t.insert(9);
t.insert(12);

t.search(9); //true
t.remove(8);
t.min(); //3
t.max(); //12
t.traverse(print); 

5. Traversal Mode

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.


11 7 5 3 6 9 8 10 15 13 12 14 20 18 25

this.preOrderTraverse = function(callback){
    preOrderTraverseNode(root, callback);
};
preOrderTraverseNode The implementation of the method is as follows:
var preOrderTraverseNode = function (node, callback) {
    if (node !== null) {
        callback(node.key); //{1}
        preOrderTraverseNode(node.left, callback); //{2}
        preOrderTraverseNode(node.right, callback); //{3}
    }
};

Sequential traversal

  • Intermediate traversal is a traversal method of accessing all BST nodes in row order, that is, accessing all nodes in the order of minimum to maximum. One application of mid-order traversal is to sort trees.


3 5 6 7 8 9 10 11 12 13 14 15 18 20 25

this.inOrderTraverse = function(callback){
    inOrderTraverseNode(root, callback); //{1}
};
var inOrderTraverseNode = function (node, callback) {
    if (node !== null) { //{2}
    inOrderTraverseNode(node.left, callback); //{3}
    callback(node.key); //{4}
    inOrderTraverseNode(node.right, callback); //{5}
    }
};

Post order traversal

  • Later traversal is to access the descendant node of the node first, and then the node itself. One application of post-order traversal is to calculate the size of space occupied by all files in a directory and its subdirectories.


3 6 5 8 10 9 7 12 14 13 18 25 20 15 11

this.postOrderTraverse = function(callback){
    postOrderTraverseNode(root, callback);
};
postOrderTraverseNode The implementation of the method is as follows:
var postOrderTraverseNode = function (node, callback) {
    if (node !== null) {
        postOrderTraverseNode(node.left, callback); //{1}
        postOrderTraverseNode(node.right, callback); //{2}
        callback(node.key); //{3}
    }
};

Keywords: Javascript less

Added by Xu Wei Jie on Wed, 09 Oct 2019 23:44:13 +0300