数据结构:二叉搜索树
Liber 2017-03-21 20:50

sorted-array-to-bst:

/*
#### 问题:
将一个从小到大排列好的数组转换成二叉搜索树。

#### 思路:
由于是从小到大排列好的数组,通过观察发现,每次取数组中间的元素(平衡时向右取),可以得到一个根节点,以及左右两颗子树。
然后分别对子树做同样的操作,并将子树的根节点按二叉搜索树的要求,作为前面根节点的左右节点。
不断对左右子树进行递归操作,最终可以得到一颗二叉搜索树。
*/

class ArrObject {
  constructor(arr) {
    this.arr = arr

    let middleIndex = this.arr.length % 2 === 0 ? this.arr.length / 2 : parseInt(this.arr.length / 2, 10)
    this.middle = arr[middleIndex]

    this.leftArr = this.arr.slice(0, middleIndex)
    this.rightArr = this.arr.slice(middleIndex + 1)
  }
}

class Node {
  constructor(arrObject) {
    this.data = arrObject.middle

    if (arrObject.leftArr.length > 0) {
      this.left = new Node(new ArrObject(arrObject.leftArr))
    }

    if (arrObject.rightArr.length > 0) {
      this.right = new Node(new ArrObject(arrObject.rightArr))
    }  
  }
}

class Tree {
  constructor(arr) {
    this.root = new Node(new ArrObject(arr))

    this.outs = []
  }

  print(curLevelNodes) {
    if (!curLevelNodes) {
      curLevelNodes = [this.root]
      this.outs.push(this.root.data + ' ')
      this.outs.push('| ')
    }

    let nextLevelNodes = []
    for (let i = 0; i < curLevelNodes.length; i++) {
      let curNode = curLevelNodes[i]

      if (curNode.left) {
        this.outs.push(curNode.left.data + ' ')
        nextLevelNodes.push(curNode.left)
      } else {
        this.outs.push('[] ')
      }

      if (curNode.right) {
        this.outs.push(curNode.right.data + ' ')
        nextLevelNodes.push(curNode.right)
      } else {
        this.outs.push('[] ')
      }
    }

    if (nextLevelNodes.length > 0) {
      this.outs.push('| ')
      this.print(nextLevelNodes)
    } else {
      console.log(this.outs.slice(0, this.outs.lastIndexOf('| ')).join(''))
    }
  }
}

var arr = [10, 15, 20, 30, 40, 50, 80, 90, 100, 200, 260]
var tree = new Tree(arr)
tree.print()

var arr = [10, 15, 20, 30, 40, 50, 80, 90, 100, 200]
var tree = new Tree(arr)
tree.print()


sorted-array-to-avl:

/*
#### 问题:
将一个从小到大排列好的数组转换成二叉搜索树。

#### 思路:
- 先让数组按降序排列
- 因此,在往二叉树中添加结点的过程中,新的结点只会添加在最左边
- 通过观察发现,在失衡发生的时候,永远只需要左左旋转
- 还可以简化一些判断条件:高度的计算,失衡的计算。
*/

let addNode = (root, node) => {
  if (!root) {
    return node
  }
  root.left = addNode(root.left, node)

  if (root.left.height - (root.right ? root.right.height : -1) === 2) {
    root = singleRotateLeft(root)
  }
  
  root.height = root.left.height + 1

  return root
}

let singleRotateLeft = (root) => {
  let node = root.left
  root.left = node.right
  node.right = root

  root.height = (root.left ? root.left.height : -1) + 1
  node.height = (node.left ? node.left.height : -1) + 1

  return node
}

class Node {
  constructor(options) {
    this.data = options.data
    this.left = options.left || null
    this.right = options.right || null

    this.height = 0
  }
}

class Tree {
  constructor(list) {
    this.list = list.reverse()

    this.root = new Node({ data: this.list[0] })
    this.buildTree()

    this.outs = []
  }

  buildTree() {
    for (let i = 1; i < this.list.length; i++) {
      let node = new Node({ data: this.list[i] })
      this.add(node)
    }
  }

  add(node) {
    this.root = addNode(this.root, node)
  }

  print(curLevelNodes) {
    if (!curLevelNodes) {
      curLevelNodes = [this.root]
      this.outs.push(this.root.data + ' ')
      this.outs.push('| ')
    }

    let nextLevelNodes = []
    for (let i = 0; i < curLevelNodes.length; i++) {
      let curNode = curLevelNodes[i]

      if (curNode.left) {
        this.outs.push(curNode.left.data + ' ')
        nextLevelNodes.push(curNode.left)
      } else {
        this.outs.push('[] ')
      }

      if (curNode.right) {
        this.outs.push(curNode.right.data + ' ')
        nextLevelNodes.push(curNode.right)
      } else {
        this.outs.push('[] ')
      }
    }

    if (nextLevelNodes.length > 0) {
      this.outs.push('| ')
      this.print(nextLevelNodes)
    } else {
      console.log(this.outs.slice(0, this.outs.lastIndexOf('| ')).join(''));
    }
  }
}

var list = [10, 15, 20, 30, 40, 50, 80, 90, 100, 200, 260]
var tree = new Tree(list)
tree.print()

var list = [1, 3, 5, 7, 100, 1000, 1001]
var tree = new Tree(list)
tree.print()

var list = [-100, -1.1, 0, 666, 2333333]
var tree = new Tree(list)
tree.print()