二叉查找树BST----java实现

转:http://blog.csdn.net/sheepmu/article/details/38407221

二叉查找树BST----Java实现

1.二叉查找树简介

二叉查找树又名二叉搜索树和二叉排序树。性质如下:

 

在二叉查找树中:
(01) 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(02) 任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(03) 任意节点的左、右子树也分别为二叉查找树。
(04) 没有键值相等的节点(no duplicate nodes)。

2.二叉查找树节点类

[java]  view plain  copy
  1. class TreeNode  
  2. {  
  3.     int value;  
  4.     TreeNode parent;  
  5.     TreeNode left;  
  6.     TreeNode right;  
  7.     public TreeNode(int value, TreeNode parent, TreeNode left, TreeNode right) {  
  8.         this.value = value;  
  9.         this.parent = parent;  
  10.         this.left = left;  
  11.         this.right = right;  
  12.     }      
  13. }  

3.遍历

   二叉查找树的遍历同二叉树的遍历,递归与非递归方法详见二叉树的递归遍历和非递归遍历(附详细例子)

4.最大和最小值

a.BST中的最小值即最左的孩子。

[java]  view plain  copy
  1. //求BST的最小值  
  2.     public TreeNode  getMin(TreeNode root)  
  3.     {  
  4.         if(root==null)  
  5.             return null;  
  6.         while(root.left!=null)  
  7.             root=root.left;    
  8.         return root;  
  9.     }  

b.BST中的最大值即最右的孩子。

[java]  view plain  copy
  1. //求BST的最大值  
  2.         public TreeNode  getMax(TreeNode root)  
  3.         {  
  4.             if(root==null)  
  5.                 return null;  
  6.             while(root.right!=null)  
  7.                 root=root.right;  
  8.             return root;  
  9.         }  

5.前驱和后继节点


ps:图片来于网络

a.BST中某节点前驱节点==小于该节点的所有节点中的最大值

前驱容易情形:5寻前驱 4

前驱复杂情形:11寻前驱 10

[java]  view plain  copy
  1. //查找BST中某节点的前驱节点.即查找数据值小于该结点的最大结点。  
  2.         public TreeNode preNode(TreeNode x)  
  3.         {  
  4.             if(x==null)  
  5.                 return null;  
  6.             // 如果x存在左孩子,则"x的前驱结点"为 "以其左孩子为根的子树的最大结点"。  
  7.             if(x.left!=null)  
  8.                 return getMax(x.left);  
  9.             // 如果x没有左孩子。则x有以下两种可能:  
  10.             // (01) x是"一个右孩子",则"x的前驱结点"为 "它的父结点"。  
  11.             // (02) x是"一个左孩子",则 前驱节点为x的某一个祖先节点的父节点,而且该祖先节点是作为其父节点的右儿子  
  12.             TreeNode p=x.parent;  
  13.             while(p!=null&&p.left==x)  
  14.             {  
  15.                 x=p;//父节点置为新的x  
  16.                 p=p.parent;  //父节点的父节点置为新的父节点  
  17.             }  
  18.            return p;       
  19.         }  
b.BST中某节点后继节点==大于该节点的所有节点中的最小值

后继容易情形:5寻后继 6

复杂情形:9寻后继 10

 

[java]  view plain  copy
  1. //查找BST中某节点的后继节点.即查找数据值大于该结点的最小结点。  
  2.         public TreeNode postNode(TreeNode x)  
  3.         {  
  4.             if(x==null)  
  5.                 return null;  
  6.             // 如果x存在右孩子,则"x的后继结点"为 "以其右孩子为根的子树的最小结点"。  
  7.             if(x.left!=null)  
  8.                 return getMin(x.right);  
  9.             // 如果x没有右孩子。则x有以下两种可能:  
  10.             //  (01) x是"一个左孩子",则"x的后继结点"为 "它的父结点"。  
  11.             // (02) x是"一个右孩子",则 前驱节点为x的某一个祖先节点的父节点,而且该祖先节点是作为其父节点的左儿子  
  12.             TreeNode p=x.parent;  
  13.             while(p!=null&&p.right==x)  
  14.             {  
  15.                 x=p;//父节点置为新的x  
  16.                 p=p.parent;  //父节点的父节点置为新的父节点  
  17.             }  
  18.            return p;       
  19.         }  

6.查找

查找值为val的节点,如果小于根节点在左子树查找,反之在右子树查找

[java]  view plain  copy
  1. //查找值为val的节点  --递归版--  
  2.         public TreeNode searchRec(TreeNode root ,int val)  
  3.         {  
  4.             if(root==null)  
  5.                 return root;  
  6.             if(val<root.value)  
  7.                 return searchRec(root.left,val);  
  8.             else if(val>root.value)  
  9.                 return searchRec(root.right,val);  
  10.             else  
  11.                 return root;  
  12.         }  
  13.         //查找值为val的节点  --非 递归版--  
  14.         public TreeNode search(TreeNode root ,int val)  
  15.         {  
  16.             if(root==null)  
  17.                 return root;  
  18.             while(root!=null)  
  19.             {  
  20.                 if(val<root.value)  
  21.                     root=root.left;  
  22.                 else if(val>root.value)  
  23.                     root=root.right;  
  24.                 else  
  25.                     return root;  
  26.             }  
  27.             return root;  
  28.         }          

7.插入

a.若当前的二叉查找树为空,则插入的元素为根节点 

b.若插入的元素值小于根节点值,则将元素插入到左子树中

c.若插入的元素值不小于根节点值,则将元素插入到右子树中。首先找到插入的位置,要么向左,要么向右,直到找到空结点,即为插入位置,如果找到了相同值的结点,插入失败。 

[java]  view plain  copy
  1. //BST插入节点  --递归版--  
  2.         public TreeNode insertRec(TreeNode root,TreeNode x)  
  3.         {  
  4.             if(root==null)  
  5.                 root=x;  
  6.             else if(x.value<root.value)  
  7.                 root.left=insertRec(root.left,  x);  
  8.             else if(x.value>root.value)  
  9.                 root.right=insertRec(root.right,  x);  
  10.             return root;  
  11.         }  
  12.         //BST插入节点  --非 递归版--  
  13.         public TreeNode insert(TreeNode root,TreeNode x)  
  14.         {  
  15.             if(root==null)  
  16.                 root=x;  
  17.             TreeNode p=null;//需要记录父节点  
  18.             while(root!=null)//定位插入的位置  
  19.             {  
  20.                 p=root;//记录父节点  
  21.                 if(x.value<root.value)  
  22.                     root=root.left;  
  23.                 else  
  24.                     root=root.right;  
  25.             }  
  26.             x.parent=p;//定位到合适的页节点的空白处后,根据和父节点的大小比较插入合适的位置  
  27.             if(x.value<p.value)   
  28.                 p.left=x;  
  29.             else if(x.value>p.value)  
  30.                 p.right=x;  
  31.             return root;  
  32.         }  

8.删除

二叉查找树的删除,分三种情况进行处理:
1.p为叶子节点,直接删除该节点,再修改其父节点的指针(注意分是根节点和不是根节点),如图a。
2.p为单支节点(即只有左子树或右子树)。让p的子树与p的父亲节点相连,删除p即可;(注意分是根节点和不是根节点);如图b。
3.有两个孩子的情况,当前结点与左子树中最大的元素交换,然后删除当前结点。左子树最大的元素一定是叶子结点,交换后,当前结点即为叶子结点,删除参考没有孩子的情况。另一种方法是,当前结点与右子树中最小的元素交换,然后删除当前结点。如图c。


ps:图片来于网络


[java]  view plain  copy
  1. //BST删除节点  
  2.         public void delete(TreeNode root,TreeNode x)  
  3.         {  
  4.             if(root==null)  
  5.                 return ;  
  6.             TreeNode p=null;  
  7.             while(root!=null)//定位到需要删除的节点  
  8.             {  
  9.                 if(x.value<root.value)  
  10.                 {  
  11.                     p=root;//记录父节点  
  12.                     root=root.left;  
  13.                 }  
  14.                 else if(x.value>root.value)  
  15.                 {  
  16.                     p=root;//记录父节点  
  17.                     root=root.right;  
  18.                 }  
  19.                 else//找到啦  
  20.                 {  
  21.                     if(root.left==null&&root.right==null)//①待删除的是 叶子节点  
  22.                     {  
  23.                         if(p==null)//待删除的是根节点  
  24.                             root=null;  
  25.                         else  
  26.                         {  
  27.                             if(p.left==root)  
  28.                                 p.left=null;  
  29.                             else if(p.right==root)  
  30.                                 p.right=null;  
  31.                         }  
  32.                     }  
  33.                     else if(root.left!=null&&root.right==null)//② 待删除的节点只有左孩子  
  34.                     {  
  35.                         if(p==null)//待删除的是根节点  
  36.                             root=root.left;  
  37.                         else  
  38.                         {  
  39.                              if(p.left==root)//待删除的本身是一个左孩子  
  40.                                  p.left=root.left;  
  41.                              else if(p.right==root)  
  42.                                  p.right=root.left;  
  43.                         }  
  44.                     }  
  45.                     else if(root.left==null&&root.right!=null)//② 待删除的节点只有右孩子  
  46.                     {  
  47.                         if(p==null)//待删除的是根节点  
  48.                             root=root.right;  
  49.                         else  
  50.                         {  
  51.                              if(p.left==root)//待删除的本身是一个左孩子  
  52.                                  p.left=root.right;  
  53.                              else if(p.right==root)  
  54.                                  p.right=root.right;  
  55.                                
  56.                         }  
  57.                     }  
  58.                     else//③待删除的节点即有左孩子又有右孩子    方法:得到待删除节点右子树的最小值,      
  59.                     {//该最小值与待删除节点进行“ 值 ”交换,删除该最小值位置处的节点  
  60.                         TreeNode rMin=root.right; //求待删除节点的后继节点,即待删除节点的右孩子的最小值(找到的后继节点肯定没有左孩子!!!)  
  61.                         TreeNode rMinP=null;//因为需要删除后继节点位置,所以需要记录父节点  
  62.                         while(rMin!=null)  
  63.                         {  
  64.                             rMinP=rMin;  
  65.                             rMin=rMin.left;  
  66.                         }  
  67.                          int rootVtemp=root.value;//值交换  
  68.                          root.value=rMin.value;  
  69.                          rMin.value=rootVtemp;  
  70.                          //删除rMin位置的节点,此时此位置的值已是待删节点的值  
  71.                          if(rMinP.left==rMin)  
  72.                              rMinP.left=rMin.right;  
  73.                          else if(rMinP.right==rMin)  
  74.                              rMinP.right=rMin.right;  
  75.                     }  
  76.                 }  
  77.                 break;//找到后删了后就跳出while循环  
  78.             }  
  79.                
  80.         }  

9.二叉树查找树常见面试题

a.判断一个数组是不是二叉搜索树的后序遍历

[java]  view plain  copy
  1. package com.sheepmu;  
  2.   
  3. public class Offer24   
  4. {  
  5.     public static void main(String[] args)  
  6.     {  
  7.         int[] a={5,7,6,9,11,10,8};  
  8.         int len=a.length;  
  9.        
  10.         System.out.println(isProOfBST(a,len));  
  11.     }  
  12.     public static boolean isProOfBST(int[] a,int len)   
  13.     {  
  14.         if(a==null||len<=0)  
  15.             return false;  
  16.         int root=a[len-1];//后序遍历的最后一个为根节点  
  17.         int i=0;  
  18.         while(a[i]<root)//找到左树的个数  
  19.             i++;  
  20.         int j=i;//先看右树中是否有非法数字,即比根节点小的数字  
  21.         while(j<len-1)  
  22.         {  
  23.             if(a[j]<root)  
  24.                 return false;  
  25.             j++;  
  26.         }  
  27.         //若左右子树的数字都合法,即左子树都比根的值小,右子树都比根节点大;此时只需递归判断左右子树是否是二叉搜索树的后序遍历  
  28.         //求左右子树的数组,到这儿明显发现用字符串很爽呀直接subString()  
  29.         boolean left=true;  
  30.         if(i>0)//必须要判断是否存在左树  
  31.         {  
  32.             int[] aleft=new int[i];  
  33.             for(int x=0;x<i;x++)   
  34.                 aleft[x]=a[x];  
  35.               left=isProOfBST(aleft,i);  
  36.         }  
  37.         boolean right=true;  
  38.         if(i<len-1)//必须要判断是否存在右树  
  39.         {  
  40.             int[] aright=new int[len-i-1];  
  41. //          for(int y=i;y<len-1;y++)//粗心啊!!!!  
  42. //          {  
  43. //              aright[y]=a[y];  
  44. //          }  
  45.             for(int y=0;y<len-i-1;y++)  
  46.                 aright[y]=a[i+y];  
  47.               right=isProOfBST(aright,len-i-1);  
  48.         }     
  49.         return left&&right;  
  50.     }  
  51. }  
b.将一颗二叉搜索树转为为排序的双向链表
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值