js數據結構之樹(tree)

典型的:HTML 就是一個樹結構

(一)二叉樹

特點:

1. 每一個父結點都有兩個子結點

2. 左側子節點存儲比父結點小的值,右側子節點存儲比父結點大的值

操作:增刪改查

代碼:

// 定義Node節點
    class Node {
      constructor (value) {
        this.value = value,
        this.left = null,
        this.right = null
      }
    }

    class Tree {
      constructor () {
        this.root = null // 首先定義根節點 爲null
      }

      // 尋找插入節點
      insertNode (node, CurrentNode){
        if (node.value > CurrentNode.value) {
          if (CurrentNode.right) {
            this.insertNode(node, CurrentNode.right) // 遞歸 繼續向下尋找
          } else {
            CurrentNode.right = node
          }
        } else if (node.value < CurrentNode.value) {
          if (CurrentNode.left) {
            this.insertNode(node, CurrentNode.left) // 遞歸 繼續向下尋找
          } else {
            CurrentNode.left = node
          }
        }
      }
      // 插入
      insert (value) {
        var node = new Node(value)
        if (this.root) {
          this.insertNode(node, this.root)
          // 因爲要遞歸 所以 單獨封裝方法
        } else {
          this.root  = node // 沒有根節點 設置爲根節點
        }
      }

      // 遍歷節點
      traverse (callback) {
        this.traver(this.root, callback)
      }

      traver(node, callback) {
        if (node === null) {
          return
        }
        this.traver(node.left, callback)
        callback(node.value) // 中序遍歷 後序遍歷 前序遍歷等等高改變這行代碼位置
        this.traver(node.right, callback)
      }

      // 刪除節點
      remove () {

      }

      // 二叉樹最小值 找到最左節點
      getMin () {
        // 空樹返回null
        if (this.root === null) {
          return null
        }
        var current = this.root
        while(current.left) {
          current = current.left
        }
        return current.value
      }

      // 獲取二叉樹搜索樹最大值 最右節點
      getMax () {
        // 空樹返回null
        if (this.root === null) {
          return null
        }
        var current = this.root
        while(current.right) {
          current = current.right
        }
        return current.value
      }

      // 獲取樹
      getTree () {
        return this.root
      }
    }
    var tree = new Tree()
    tree.insert(12)
    tree.insert(13)
    tree.insert(4)
    tree.insert(13)
    console.log(tree.getTree())
    tree.traverse((value) => {
      console.log('VALUE', value)
    })
    console.log(tree.getMin())
    console.log(tree.getMax())

還有刪除一個結點,情況複雜 單獨貼

移除一個結點 三種情況:

1. 該結點沒有子節點 直接移除就可以

2. 該結點有一個子結點,將子結點替換爲該結點

3. 該結點有兩個子結點,這種情況最特殊 需要重新計算(最好的方案,一句話總結:替換爲右側子樹的最小子結點

一個結點,它左側的樹的所有值都比它小,它右側的所有值都比他大,比它小才能往左側走,比它大才能往右側去

// 刪除結點 先查找 再刪除
      removeNode (node, value) {
        if (node === null) { return null }
        if (value < node.value) { // 左側找
          node.left = this.removeNode(node.left, value)
          return node
        } else if (value > node.value) { // 右側找
          node.right = this.removeNode(node.right, value)
          return node
        } else { // 值相等 找到 node 就是當前結點
          if (node.left === null && node.right === null) {  // 葉結點 沒有子結點 直接刪除 反向構建 一層層 return
            node = null
            return node
          }
          if (node.left === null && node.right) {
            node = node.right
            return node // 右結點替換
          }
          if (node.right === null && node.left) {
            node = node.left
            return node // 左結點替換
          }
          if (node.right && node.left) { // 左右結點都存在
            var minNode = this.findMinRight(node.right)
            node.value = minNode.value
            node.right = this.removeNode(node.right, node.value) // 從替換元素查找 刪除value的元素
            return node
          }
        }
      }

      // 查找傳入結點的最小子結點
      findMinRight (node) {
        if (node === null) {
          return null
        }
        while (node.left) {
          node = node.left
        }
        return node
      }
      // 刪除節點 重新構建樹
      remove (value) {
        this.root = this.removeNode(this.root, value)
      }

慢慢研究 一環套一環。。。頭禿

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