二叉查找树(Binary Search Tree)

二叉查找树Binary Search Tree),或者是一棵空树,或者是具有下列性质的二叉树

  1. 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
  2. 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
  3. 它的左、右子树也分别为二叉排序树。

二叉查找树的表示:
class Node { int data; Node leftChild = null; Node rightChild = null; }

二叉查找树的常用方法:
1. 查找(lookup)
/* Given a binary tree, return true if a node with the target data is found in the tree. Recurs down the tree, chooses the left or right branch by comparing the target to each node. */ static boolean lookup(Node rootNode, int target) { // 1. Base case == empty tree // in that case, the target is not found so return false if (rootNode == null) return false; else if (target == rootNode.data) return true; else if (target < rootNode.data) return(lookup(rootNode.leftChild, target)); else return(lookup(rootNode.rightChild, target)); }
2. 最大(max)
/* return the node with maximum key value. It should be last right child of the tree, or the root if the root does not have any child */ public Node maxNode(Node rootNode) { while (rootNode.righttChild != null) { rootNode = rootNode.rightChild; } return rootNode; }
3. 最小 (min)
/* return the node with minimum key value. It should be last left child of the tree, or the root if the root does not have any child */ public Node minNode(Node rootNode) { while (rootNode.leftChild != null) { rootNode = rootNode.leftChild; } return rootNode; }
4. 插入(insert)
public static Node insert(Node root, int data) { // 1. If the tree is empty, the new node is the root if (root == null) { return new Node(data); } else { // 2. Otherwise, recur down the tree if (data <= root.data) root.leftChild = insert(root.leftChild, data); else root.rightChild = insert(root.rightChild, data); } return root; }

5. in-order tree walk
public void inorder(Node rootNode) { if (rootNode != null) { inorder(rootNode.leftChild); print(nodeNode.data); inorder(rootNode.rightChild); } }
6. successor
一个node的successor可以通过in-order walk看出来,因为in-order walk实际上是把二叉查找树做了一个排序。 predecesor 刚好和successor 相反。

Search consists of two cases.
1) If node x has a non-empty right subtree, then x’s successor is the minimum in the right subtree of x.
2) If node x has an empty right subtree, then as long as we move to the left up the tree (move up through right children), we are visiting smaller keys.x’s successor y is the node that x is the predecessor of (x is the maximum in y’s left subtree).In other words, x’s successor y, is the lowest ancestor of x whose left child is also an ancestor of x.
public Node Successor(Node node) { if (node.rightChild != null) { return minNode(node.rightChild); } Node parentNode = node.parent; while (parentNode != null && node == parentNode.rightChild) { node = parentNode; parentNode = parentNode.parent; } return parentNode; }
7. 删除 (delete)

删除一个node x 需要考虑下面几种情况:
case 1:if x has no children, then remove x;
case 2:if x has one child, thenmake p[x] point to child;
case 3:if x has two children (subtrees) ,then swap x with its successor,perform case 0 or case 1 to delete it.

伪代码:

delete(x) if x.left = NIL and x.right = NIL //case 1 if x.parent.left = x x.parent.left = NIL else x.parent.right = NIL else if x.left = NIL //case 2a connect x.parent to x.right else if x.right = NIL //case 2b connect x.parent to x.left else //case 3 y = successor(x) connect y.parent to y.right replace x with y

8. 求节点的个数(size)
/* Compute the number of nodes in a tree. */ int size(Node rootNode) { if (node == NULL) { return(0); } else { return(size(rootNode.leftChild) + 1 + size(rootNode.rightChild)); } }
9. 把一个二叉树转成它的“镜像”(mirror)
private void mirror(Node rootNode) { if (rootNode != null) { // do the sub-trees mirror(rootNode.leftChild); mirror(rootNode.rightChild); // swap the left/right pointers Node temp = rootNode.leftChild; rootNode.rightChild = rootNode.rightChild; rootNode.rightChild = temp; } }

10. check balanced (isBalanced)
To check a binary tree is balanced or not, we can simply convert this question into comparing the maximum depth and minimum depth of the BT, if the diffrence betweenthe maximum depth and minimum depth is larger than 1, the tree is not balanced, otherwise, it is balanced.

int maxDepth(Node rootNode) { if (rootNode == null) { return 0; } return 1 + max(maxDepth(rootNode.leftChild), maxDepth(rootNode.rightChild)); } int minDepth(Node rootNode) { if (rootNode == null) { return 0; } return 1 + min(minDepth(rootNode.leftChild), minDepth(rootNode.rightChild)); } bool isBalanced(Node rootNode) { return maxDepth(rootNode) - minDepth(rootNode) <= 1; }
11. First common ancestor
查找两个node的最早的公共祖先,分三种情况:
1. 如果两个node在root的两边,那么最早的公共祖先就是root。
2. 如果两个node在root的左边,那么把root.leftChild作为root,再递归。
3.如果两个node在root的右边,那么把root.rightChild作为root,再递归。
/* * get the first common ancestor of node p and node q */ public static Node commonAncestor(Node rootNode, Node p, Node q) { if (covers(rootNode.leftChild, p) && covers(rootNode.leftChild, q)) return commonAncestor(rootNode.leftChild, p, q); if (covers(rootNode.rightChild, p) && covers(rootNode.rightChild, q)) return commonAncestor(rootNode.rightChild, p, q); return rootNode; } /* * check whether the node n is in the tree */ private static boolean covers(Node rootNode, Node n) { if(rootNode == null) return false; if(rootNode == n) return true; return covers(rootNode.leftChild, n) || covers(rootNode.rightChild, n); }

如果这个Binary Tree 是 BST的话,可以利用左子树的值小于根节点的值,右子树的值大于根节点的值进行判断两个节点(p, q)的位置,这样更简单。

public Node LCA(Node root, Node p, Node q) { if (root != null || p != null || q != null ) return NULL; if (minValue(root) > p.data || maxValue(root) < q.data) return NULL; //to avoid the case that p.data = q.data = root.data if (minValue(root) == p.data && maxValue(root) == q.data) return NULL; if (max(p.data, q.data) < root.data) return LCA(root.left, p, q); else if (min(p.data, q.data) > root.data) return LCA(root.right, p, q); else return root; }

这个算法的复杂度是O(h)。

12. ISBST()
Given a plain binary tree, examine the tree to determine if itmeets the requirement to be a binary search tree. To be a binary search tree, for every node, all of the nodes in itsleft tree must be <= the node, and all of the nodes in its right subtree must be > the node.
private boolean isBST(Node node) { if (node==null) return(true); if (node.left!=null && maxValue(node.left) > node.data) return(false); if (node.right!=null && minValue(node.right) <= node.data) return(false); // check that the subtrees themselves are ok return( isBST(node.left) && isBST(node.right) ); }
However, the approach given above is very expensive (O(n*h)), because the maxValue(Node node) function will be called n times, and the complexity of the maxValue(Node node) is h (the height of the tree).

Because of the properity of BST, we can simply pass down the minvalue and maxvalue after narrowing the range of the minvalue and maxvalue, and the complexity of this algorithm is O(n). The code below shows the algorithm.
bool isBSTHelper(Node p, int low, int high) { if (p == null) return true; if (low < p.data && p.data < high) return isBSTHelper(p.leftChild, low, p.data) && isBSTHelper(p.rightChild, p.data, high); else return false; } bool isBST(Node root) { return isBSTHelper(root, INT_MIN, INT_MAX); }


参考: http://cslibrary.stanford.edu/110/BinaryTrees.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值