一、什么是二叉搜索树
二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于等于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于等于它的根结点的值; 它的左、右子树也分别为二叉排序树。
二、查询
定义树的结点类为
class Node{ int k; Node left = null; Node right = null; Node p = null; }
查找过程,从树的根节点开始查找,输入树的根节点和需要查找的k值,如果结点存在,返回指向关键字k的结点,否则返回null。
public Node TreeSearch(Node root,int k){ if(root==null||k==root.k) return root; if(k<root.k){ return TreeSearch(root.left,k); }else{ return TreeSearch(root.right,k); } }
三、插入
四、删除插入和删除会引起由二叉搜索树的动态集合的变化。一定要修改数据结果来反映这个变化,但修改要保持二叉树搜索树性质成立。
public void TreeInsert(Node root,Node z){ Node y = null; Node x = root; while(x!=null){ y = x; if(z.k<x.k){ x = x.left; }else{ x = x.right; } } z.p = y; if(y==null){ root = z; }else if(z.k<y.k){ y.left = z; }else{ y.right = z; } }
删除分为三种情况
1、如果z没有孩子结点,那么知识简单地将它删除,并修改它的父结点,用null最为孩子了替换z
2、如果z只有一个孩子,那么将这个孩子提升到树中的z的位置,并修改z的父结点,用z的孩子代替z
3、如果z有两个孩子,那么找z的后继y(一定在z的右子树中)并让其占据树中z的位置,z原来额右子树部分称为y的右子树,并且z的左子树称为y的新的左子树。
为了完成删除操作,我们先来做一下准备工作。
最大关键字元素和最下关键字元素
/** * 获得最小值元素 * @param x * @return */ public Node TreeMiniNum(Node x){ while(x.left!=null){ x = x.left; } return x; } /** * 获得最大值元素 * @param x * @return */ public Node TreeMaxiNum(Node x){ while(x.right!=null){ x = x.right; } return x; }
前驱和后继
一个结点的后继是大于x.key的最小关键词的结点,前驱是小于x.key的最大关键字的结点。
/** * 求后继 * @param x * @return */ public Node TreeSuccessor(Node x){ if(x.right!=null){ return TreeMiniNum(x.right); } Node y = x.p; while(y!=null && x == y.right){ x = y; y = y.p; } return y; }
为了在二叉搜索树内移动子树,定义一个子过程TRANSPLANT,它是用另一颗子树替换一棵子树并成为其双亲的孩子结点。当TRANSPLANT用一颗以v为根的子树来替换一颗以u为根的子树时,结点u的双亲就变为结点v的双亲,并最后v成为u的双亲的相应孩子。
public void Transplant(Node root,Node u,Node v){ if(u.p==null) root = v; else if(u==u.p.left) u.p.left = v; else u.p.right = v; if(v!=null){ v.p = u.p; } }
下面是二叉搜索树删除结点z的删除过程
public void TreeDelete(Node root,Node z){ //第一种情况 if(z.left==null) Transplant(root, z, z.right); else if(z.right == null) Transplant(root, z, z.left); //第二和第三种情况 else { Node y = TreeMiniNum(z.right); if(y.p!=z){//第三种情况 Transplant(root, y, y.right); y.right = z.right; y.right.p = y; } //z的后继恰好为z的有右孩子,第二种情况 Transplant(root, z, y); y.left = z.left; y.left.p = y; } }
在一颗高度为h的二叉搜素树上,实现动态集合操作Insert和Delete的运行时间均为o(h)。
本文为《算法导论》二叉搜索复习笔记