树
function BST() { /*初始化根节点为null*/ this.root = null; this.insert = insert; this.inOrder = inOrder; this.preOrder = preOrder; this.postOrder = postOrder; this.getMax = getMax; this.getMin = getMin; this.find = find; } function Node(data, left, right) { this.data = data; this.left = left; this.right = right; this.show = show; } function show() { return this.data; } * 查找正确插入点的算法如下。 * (1) 设根节点为当前节点。 * (2) 如果待插入节点保存的数据小于当前节点, 则设新的当前节点为原节点的左节点; 反之, 执行第 4 步。 * (3) 如果当前节点的左节点为 null, 就将新的节点插入这个位置, 退出循环; 反之, 继续执行下一次循环。 * (4) 设新的当前节点为原节点的右节点。 * (5) 如果当前节点的右节点为 null, 就将新的节点插入这个位置, 退出循环; 反之, 继续执行下一次循环。 * */ function insert(data) { var n = new Node(data, null, null); if (this.root == null) { this.root = n; } else { var current = this.root; var parent; while (true) { parent = current; if (data < current.data) { current = current.left; if (current == null) { parent.left = n; break; } } else { current = current.right; if (current == null) { parent.right = n; break; } } } } } ** * 遍历 * 有三种遍历 BST 的方式: 中序、 先序和后序。 * 中序遍历按照节点上的键值, 以 升序访问 BST 上的所有节点。 * 先序遍历 先访问根节点 , 然后以同样方式访问左子树和右子树。 * 后序遍历先访问叶子节点, 从左子树到右子树, 再到根节点。 * * 三个遍历都接受一个参数,是当前要遍历树或子树的根节点 * * inOrder() 和 preOrder() 方法的唯一区别, 就是 if 语句中代码的顺序。 在 inOrder() * 方法中, show() 函数像三明治一样夹在两个递归调用之间; 在 preOrder() 方法中, show() * 函数放在两个递归调用之前。 * */ function inOrder(node) { if (!(node == null)) { inOrder(node.left); putstr(node.show() + " "); inOrder(node.right); } } function preOrder(node) { if (!(node == null)) { putstr(node.show() + " "); preOrder(node.left); preOrder(node.right); } } function postOrder(node) { if (!(node == null)) { postOrder(node.left); postOrder(node.right); putstr(node.show() + " "); } } /** * 查找: * BST 通常有三种类型的查找: * * 查找最小值: * 沿着 BST 的左子树挨个遍历, 直到遍历到 BST 最左边的节点即为最小值 * * 查找最大值: * 遍历右子树, 直到找到最后一个节点, 该节点上保存的值即为最大值 * * 查找给定值: * 比较该值和当前节点上的值的大小。通过比较,确定如果给定值不在当前节点,该向左遍历还是向右遍历 * 如果找到给定值, 该方法返回保存该值的节点; 如果没找到, 该方法返回 null * */ function getMin() { var current = this.root; while (!(current.left == null)) { current = current.left; } return current.data; } function getMax() { var current = this.root; while (!(current.right == null)) { current = current.right; } return current.data; } function find(data) { var current = this.root; while (current != null) { if (current.data == data) { return current; } else if (data < current.data) { current = current.left; } else { current = current.right; } } return null; } /** * 删除节点, * 使用remove(data) 它会调用removeNode() * 会从根节点开始查起 * */ function remove(data) { root = removeNode(this.root, data); } function removeNode(node, data) { if (node == null) { return null; } if (data == node.data) { // 没有子节点的节点 if (node.left == null && node.right == null) { return null; } // 没有左子节点的节点 if (node.left == null) { return node.right; } // 没有右子节点的节点 if (node.right == null) { return node.left; } // 有两个子节点的节点 var tempNode = getSmallest(node.right); node.data = tempNode.data; node.right = removeNode(node.right, tempNode.data); return node; } else if (data < node.data) { node.left = removeNode(node.left, data); return node; } else { node.right = removeNode(node.right, data); return node; } }
链接:https://blog.csdn.net/haoshidai/article/details/52263191
圣凡无二路,方便有多门。