Javascript數據結構與算法學習(六)—— 樹

樹結構

樹是一種重要的非線性數據結構,直觀地看,它是數據元素(在樹中稱爲結點)按分支關係組織起來的結構,很象自然界中的樹那樣。

  • HTML結構就是典型的樹結構
    在這裏插入圖片描述

二叉搜索樹

  • 特點:
    • 節點最多只能有兩個子節點,一個左子節點,一個右子節點,左右子節點的順序不能顛倒。
    • 在左側存儲比父節點小的值
    • 在右側存儲比父節點大的值
  • 實現:
    • 樹(Tree)有:根節點,內部的Node類,查找,刪除,插入,遍歷
      在這裏插入圖片描述
  • 插入節點
function Tree(){
 	var Node = function(val){
        this.value = val
        this.left = null
        this.right = null
    }

    var root = null
    //  插入節點
    /**
     * 1、樹爲空樹:root = value
     * 2、樹不是空的:對比節點
     */
    var insertNode = function(node,newNode){
        if(newNode.value>node.value){
            if(node.right===null){
                node.right = newNode
            }else{
                insertNode(node.right,newNode)
            }
        }else if(newNode.value<node.value){
            if(node.left===null){
                node.left = newNode
            }else{
                insertNode(node.left,newNode)
            }
        }
    }
    this.insert = function(value){
        var node = new Node(value)
        if(root===null){
            root = node
        }else{
            insertNode(root,node)
        }
    }
}

  • 遍歷樹
    在這裏插入圖片描述

 // 遍歷節點
  // 藉助遞歸
    function traverse(node, callback){
        if(node===null) return;
        traverse(node.left,callback)
        traverse(node.right,callback)
        callback(node.value)
    }
    this.traverse = function(callback){
        traverse(root,callback)
    }
  • 獲取最小值
    在這裏插入圖片描述
  • 移除節點

移除節點有很多種情況:

  1. 移除有2個子節點的?——選哪個子節點來代替被刪除的節點
  2. 移除末位節點(葉節點)
  3. 移除只有1個子節點
    在這裏插入圖片描述
    在這裏插入圖片描述
/**
 * 根節點 root
 * 插入 insert
 * 查找 search
 * 遍歷 traverse
 * 刪除 remove
 * 內部的Node類
 * 
 */
function Tree(){
    var Node = function (value){
        this.value = value
        this.left = null
        this.right = null
    }
    var root = null
    // 插入
    function insert(node,newNode){
        if(node.value<newNode.value){
            if(node.right===null){
                node.right = newNode
            }else{
                insert(node.right,newNode)
            }
        }else{
            if(node.left===null){
                node.left = newNode
            }else{
                insert(node.left,newNode)
            }
        }
    }
    this.insert = function(value){
        var node = new Node(value)
        if(!root){
            root = node
        }else{
            insert(root,node)
        }
    }
    // 搜索
    var searchNode = function(node,value){
        if(node===null) return null
        if(value<node.value) return searchNode(node.left,value)
        else if(value>node.value) return  searchNode(node.right,value)
        else return node
    }
    this.search = function(val){
        searchNode(root,value)
    }
    // 遍歷
    function traverse (node,callback){
        if(!node) return;
        //  callback(node.value) //前序遍歷 —— 訪問根節點的操作發生在遍歷其左右子樹之前。
        traverse(node.left,callback)
        // callback(node.value) //中序遍歷 —— 訪問根節點的操作發生在遍歷其左右子樹之間。
        traverse(node.right,callback)
        callback(node.value) //後序遍歷 —— 訪問根節點的操作發生在遍歷其左右子樹之後
    }
    this.traverse = function(callback){
        traverse(root,callback)
    }
    // 最小值
    this.min = function(node){
        if(node===null) return null;
        while(node&&node.left!==null){
            node = node.left
        }
        return node
    }
    // 最大值
    this.max = function(node){
        if(node===null) return null
        while(node&&node.right!==null){
            node = node.right
        }
        return node
    }
    // 刪除——重新構建樹
    function findMinNode(node){
        if(node === null) return null
        while(node && node.left!== null){
            node = node.left
        }
        return node
    }
    let removeNode = function (node, key) {
        if (node === null) return null;
        
        // 查找
        if (key < node.value) {
            node.left = removeNode(node.left, key);
            return node;
        }else if (key > node.value) {
            node.right = removeNode(node.right, key);
            return node;
        }else {
            // 找到節點後,刪除
            // 第一種情況:一個葉子節點(沒有子節點)
            if (node.left === null && node.right === null) {
                node = null;
                return null;
            }
            // 第二種情況:只包含一個子節點
            if (node.left === null) {
                node = node.right;
                return node;
            }
            else if (node.right === null) {
                node = node.left;
                return node;
            }
    
            // 第三種情況:有兩個子節點
            let aux = findMinNode(node);
            node.value = aux.key;
            node.right = removeNode(node.right, aux.value);
            return node;
        }
    };
    this.remove = function(key){
        root = removeNode(root,key)
    }
    this.getTree = function(){
        return root
    }
}
var t = new Tree

t.insert(8)
t.insert(2)
t.insert(3)
t.insert(9)

// t.remove(2)
// console.log(t.getTree())
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章