- 二叉查找树的定义
二叉查找树是按二叉树结构来组织的,即可按照二叉树的数据结构来构造。即每个节点都包含域left,right和key。
设x是二叉查找树的一个节点。如果y是x的左子树的一个结点,则key[y]<=key[x]。如果y是x的右子树的一个节点,则key[y]>=key[x]。如:
- 二叉查找树的遍历
中序遍历结果是有序,结果为3,4,5,6,7 二叉查找树的查询
1、按key值查询——-二叉查找,在O(h)时间内完成。
2、查找最小节点——-沿左节点向下查找,最小节点为3
3、查找最大节点——-沿右节点向下查找,最大节点为7
4、查找某节点x的后继—-如果该节点x右子树非空,则后继是右子树的最左节点。如果右子树为空,且该节点存在后继,则后继是x的最低祖先节点O(h)。4的后继是5
5、查找某节点的前继—-和后继对称O(h)。6的前驱是5。二叉查找树的插入与删除
1、插入—-简单操作
2、删除—-删除给定节点Z有3种情况。1)、Z没有子女,则直接删除。2)、Z只有一个子女,则通过其子节点与父节点之间建立一条连接来删除Z。3)、Z有2个子女,则先删除Z的后继y(y没有左子树),再用y的内容来替代Z的内容。- 随机构造二叉查找树(只说一下思路,不加证明)
1.插入—-1/N的概率作为根节点,(N-1)/N的概率递归到子节点,重复上述步骤。
2.删除—-由于删除普通做法是:利用被删节点的后继(右子树最小节点)为根,这对左子树不公平。优化方案:以概率的方式来决定谁来做根,一般是大子树做根的概率大,从而拉低大子树的高度,达到平衡。
//二叉查找树
public class BinarySearchTree<T extends Comparable<T>> {
//TreeNode<T> root;
static class TreeNode<T extends Comparable<T>>
{
T val;
TreeNode parent;
TreeNode left;
TreeNode right;
public TreeNode(T val) {
// TODO Auto-generated constructor stub
this.val = val;
}
public TreeNode() {
// TODO Auto-generated constructor stub
}
}
public BinarySearchTree() {
// TODO Auto-generated constructor stub
}
public void insert(T val, TreeNode<T> x)
{
if(x.val == null){x.val = val;return;}
TreeNode<T> node = new TreeNode<T>(val);
TreeNode<T> y = x;
TreeNode<T> temp = null;
while(y != null)
{
temp = y;
if(val.compareTo(y.val)>0)
{
y = y.right;
}else
y = y.left;
}
if(val.compareTo(temp.val) >0)
{
temp.right = node;
}else
{
temp.left = node;
}
node.parent = temp;
}
public TreeNode<T> remove(TreeNode<T> z, TreeNode<T> root)
{
//three situation
TreeNode<T> y = null;
TreeNode<T> x = null;
//找到y
if(z.left == null || z.right == null)
{
y = z;
}else
y = treeSuccessor(z);//最多只有一个子节点
//对y删除,连接。。。。。。
//找到y的非空子节点
if(y.left != null)
x = y.left;
else
x = y.right;
//
if(x != null)
{
x.parent = y.parent;
}
//
if(y.parent == null)//即y是根节点
{
root = x;
}else
if(y.parent.left == y)
y.parent.left = x;
else
y.parent.right = x;
//如果是左右都不为空情况
if(y != z)
{
z.val = y.val;
}
return root;
}
public void treeWalk(TreeNode<T> x){
if(x == null){return;}
treeWalk(x.left);
System.out.println(x.val+" ");
treeWalk(x.right);
}
public T treeSearch(T val, TreeNode<T> x)
{
if(x == null) return null;
if(val.compareTo(x.val)==0) {return val;}
if(val.compareTo(x.val)>0)
return treeSearch(val, x.right);
else
return treeSearch(val, x.left);
}
public TreeNode<T> treeMinmum(TreeNode<T> x)
{
if(x == null) return null;
if(x.left == null) return x;
return treeMaxmum(x.left);
}
public TreeNode<T> treeMaxmum(TreeNode<T> x)
{
if(x == null) return null;
if(x.right == null) return x;
return treeMaxmum(x.right);
}
public TreeNode<T> treeSuccessor(TreeNode<T> x)//crucial
{
if(x == null ) return null;
if(x.right != null)
return treeMinmum(x.right);
else
{
TreeNode<T> y = x.parent;
while(y!=null && y.right == x)
{
x = y;
y = x.parent;
}
return y;
}
}
public TreeNode<T> treePredecessor(TreeNode<T> x)//important
{
if(x == null) return null;
if(x.left != null) return treeMaxmum(x.left);
else
{
TreeNode<T> y = x.parent;
while(y!=null && y.left == x)
{
x = y;
y = x.parent;
}
return y;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
BinarySearchTree<Integer> bst = new BinarySearchTree<>();
TreeNode<Integer> root = new TreeNode<>();
bst.insert(2, root);
bst.insert(3, root);
bst.insert(1, root);
bst.insert(5, root);
bst.insert(4, root);
bst.treeWalk(root);
System.out.println("maxMum:"+bst.treeMaxmum(root).val);
System.out.println("minMun:"+bst.treeMinmum(root).val);;
System.out.println("root:"+root.val);
System.out.println("root successor:"+bst.treeSuccessor(root).val);
System.out.println("root predecessor:"+bst.treePredecessor(root).val);
root = bst.remove(root, root);
System.out.println("remove root:");
bst.treeWalk(root);
}
}