`

二叉排序树

 
阅读更多

今天就聊聊这个”五大经典查找“中的最后一个”二叉排序树“,又叫二叉查找树。

1. 概念


如图就是一棵二叉排序树:


2.实际操作:

    我们都知道,对一个东西进行操作,无非就是增删查改,接下来我们就聊聊其中的基本操作。

    <1> 插入:相信大家对“排序树”的概念都清楚了吧,那么插入的原理就很简单了。
比如说我们插入一个20到这棵树中。

首先:20跟50比,发现20是老小,不得已,得要归结到50的左子树中去比较。
然后:20跟30比,发现20还是老小。
再然后:20跟10比,发现自己是老大,随即插入到10的右子树中。
最后: 效果呈现图如下:



<2>查找:相信懂得了插入,查找就跟容易理解了。

就拿上面一幅图来说,比如我想找到节点10.

首先:10跟50比,发现10是老小,则在50的左子树中找。
然后:10跟30比,发现还是老小,则在30的左子树中找。
再然后:  10跟10比,发现一样,然后就返回找到的信号。
        
<3>删除:删除节点在树中还是比较麻烦的,主要有三种情况。

《1》 删除的是“叶节点20“,这种情况还是比较简单的,删除20不会破坏树的结构。如图:



《2》删除”单孩子节点90“,这个情况相比第一种要麻烦一点点,需要把他的孩子顶上去。


《3》删除“左右孩子都有的节点50”,这个让我在代码编写上纠结了好长时间,问题很直白,我把50删掉了,谁顶上去了问题,是左孩子呢?还是右 孩子呢?还是另有蹊跷?这里我就坦白吧,不知道大家可否知道“二叉树”的中序遍历,现在可以当公式记住吧,就是找到右节点的左子树最左孩子。

比如:首先 找到50的右孩子70。
然后  找到70的最左孩子,发现没有,则返回自己。
最后  原始图和最终图如下。





3.说了这么多,上代码说话。

Java代码  收藏代码
  1. //二叉搜索树   
  2. public   class  BinarySearchTree<T  extends  Comparable<?  super  T>>  
  3. {  
  4.   
  5.    /** 二叉排序树的根 */   
  6.     private  BinaryNode<T> root;  
  7.   
  8.     /**  
  9.      * 构造一棵空树.  
  10.      */   
  11.     public  BinarySearchTree( )  
  12.     {  
  13.         root = null ;  
  14.     }  
  15.   
  16.     /**  
  17.      * 在二叉搜索树中插入数据.  
  18.      * @param x the item to insert.  
  19.      */   
  20.     public   void  insert( T x )  
  21.     {  
  22.         root = insert( x, root );  
  23.     }  
  24.   
  25.     /**  
  26.      * 从二叉搜索中删除数据(节点).  
  27.      * @param x the item to remove.  
  28.      */   
  29.     public   void  remove( T x )  
  30.     {  
  31.         root = remove( x, root );  
  32.     }  
  33.   
  34.     /**  
  35.      * 找最小数据.  
  36.      * @return smallest item or null if empty.  
  37.      */   
  38.     public  T findMin( )  
  39.     {  
  40.         if ( isEmpty( ) )  
  41.             throw   new  UnderflowException( );  
  42.         return  findMin( root ).element;  
  43.     }  
  44.   
  45.     /**  
  46.      * 找最大数据.  
  47.      * @return the largest item of null if empty.  
  48.      */   
  49.     public  T findMax( )  
  50.     {  
  51.         if ( isEmpty( ) )  
  52.             throw   new  UnderflowException( );  
  53.         return  findMax( root ).element;  
  54.     }  
  55.   
  56.     //二叉搜索树中是否包含x   
  57.     public   boolean  contains( T x )  
  58.     {  
  59.         return  contains( x, root );  
  60.     }  
  61.   
  62.      
  63.     public   void  makeEmpty( )  
  64.     {  
  65.         root = null ;  
  66.     }  
  67.   
  68.      
  69.     public   boolean  isEmpty( )  
  70.     {  
  71.         return  root ==  null ;  
  72.     }  
  73.   
  74.    //中序遍历输出二叉搜索树的内容   
  75.     public   void  printTree( )  
  76.     {  
  77.         if ( isEmpty( ) )  
  78.             System.out.println( "Empty tree"  );  
  79.         else   
  80.             printTree( root );  
  81.     }  
  82.   
  83.     //插入   
  84.     private  BinaryNode<T> insert( T x, BinaryNode<T> t )  
  85.     {  
  86.         if ( t ==  null  )  
  87.             return   new  BinaryNode<T>( x,  null null  );  
  88.           
  89.         int  compareResult = x.compareTo( t.element );  
  90.               
  91.         if ( compareResult <  0  )  
  92.             t.left = insert( x, t.left );  
  93.         else   if ( compareResult >  0  )  
  94.             t.right = insert( x, t.right );  
  95.         else   
  96.            ;  // 重复的,什么也不做。当然你也可以将重复的数据加入右边。   
  97.         return  t;  
  98.     }  
  99.   
  100.     //删除   
  101.     private  BinaryNode<T> remove( T x, BinaryNode<T> t )  
  102.     {  
  103.          //先在树中查找x      
  104.         if ( t ==  null  )  
  105.             return  t;    // 没有找到,返回   
  106.           
  107.         int  compareResult = x.compareTo( t.element );  
  108.           // 在左树中找   
  109.         if ( compareResult <  0  )  
  110.             t.left = remove( x, t.left );  
  111.           //在右树中找   
  112.         else   if ( compareResult >  0  )  
  113.             t.right = remove( x, t.right );  
  114.         //在树中找到了节点值为x的节点   
  115.         else   if ( t.left !=  null  && t.right !=  null  )  // 这个节点有两个孩子节点   
  116.         {  
  117.             t.element = findMin( t.right ).element;  
  118.             t.right = remove( t.element, t.right );  
  119.         }  
  120.         else //这个节点只有一个孩子节点或没有孩子节点   
  121.             t = ( t.left != null  ) ? t.left : t.right;  
  122.         return  t;  
  123.     }  
  124.   
  125.    //在二叉搜索树中找最小值节点   
  126.     private  BinaryNode<T> findMin( BinaryNode<T> t )  
  127.     {  
  128.         if ( t ==  null  )  
  129.             return   null ;  
  130.         else   if ( t.left ==  null  )  
  131.             return  t;  
  132.         return  findMin( t.left );  
  133.     }  
  134.   
  135.     //在二叉搜索树中找最大值节点   
  136.     private  BinaryNode<T> findMax( BinaryNode<T> t )  
  137.     {  
  138.         if ( t !=  null  )  
  139.             while ( t.right !=  null  )  
  140.                 t = t.right;  
  141.   
  142.         return  t;  
  143.     }  
  144.   
  145.    //是否包含   
  146.     private   boolean  contains( T x, BinaryNode<T> t )  
  147.     {  
  148.         if ( t ==  null  )  
  149.             return   false ;  
  150.               
  151.         int  compareResult = x.compareTo( t.element );  
  152.               
  153.         if ( compareResult <  0  )  
  154.             return  contains( x, t.left );  
  155.         else   if ( compareResult >  0  )  
  156.             return  contains( x, t.right );  
  157.         else   
  158.             return   true ;     // Match   
  159.     }  
  160.   
  161.    //中序遍历二叉树   
  162.     private   void  printTree( BinaryNode<T> t )  
  163.     {  
  164.         if ( t !=  null  )  
  165.         {  
  166.             printTree( t.left );  
  167.             System.out.print(t.element+"  " );  
  168.             printTree( t.right );  
  169.         }  
  170.          
  171.     }  
  172.   
  173.     // 二叉搜索树节点   
  174.     private   static   class  BinaryNode<T>  
  175.     {  
  176.             // Constructors   
  177.         BinaryNode( T theElement )  
  178.         {  
  179.             this ( theElement,  null null  );  
  180.         }  
  181.   
  182.         BinaryNode( T theElement, BinaryNode<T> lt, BinaryNode<T> rt )  
  183.         {  
  184.             element  = theElement;  
  185.             left     = lt;  
  186.             right    = rt;  
  187.         }  
  188.   
  189.         T element;            // The data in the node   
  190.         BinaryNode<T> left;   // Left child   
  191.         BinaryNode<T> right;  // Right child   
  192.     }  
  193.   
  194.   
  195.         
  196.   
  197.         // 测试   
  198.     public   static   void  main( String [ ] args )  
  199.     {  
  200.          //创建二叉排序树      
  201.         int  list[]={  50 30 70 10 40 90 80 };  
  202.         BinarySearchTree<Integer> bsTree = new  BinarySearchTree<Integer>( );  
  203.          for int  i =  0 ; i<list.length;i++)  
  204.             bsTree.insert( list[i] );  
  205.         
  206.            System.out.println("中序遍历的原始数据:" );    
  207.             //中序遍历      
  208.            bsTree.printTree( );  
  209.            System.out.printf("\n--------------------------------" );    
  210.   
  211.          //查找一个节点      
  212.        System.out.printf("\n10在二叉树中是否包含:"  + bsTree.contains( new  Integer( 10 )));    
  213.      
  214.            System.out.printf("\n---------------------------------" );    
  215.   
  216.         //插入一个节点      
  217.              bsTree.insert(20 );    
  218.      
  219.              System.out.printf("\n20插入到二叉树,中序遍历后:" );    
  220.      
  221.              //中序遍历      
  222.              bsTree.printTree();    
  223.              System.out.printf("\n-----------------------------------\n" );    
  224.   
  225.           System.out.printf("删除叶子节点 20, \n中序遍历后:" );    
  226.      
  227.              //删除一个节点(叶子节点)      
  228.              bsTree.remove(new  Integer( 20 ));    
  229.      
  230.              //再次中序遍历      
  231.              bsTree.printTree();     
  232.              System.out.printf("\n****************************************\n" );    
  233.      
  234.              System.out.printf("删除单孩子节点 90, \n中序遍历后:" );    
  235.      
  236.              //删除单孩子节点      
  237.              bsTree.remove(new  Integer( 90 ));    
  238.      
  239.              //再次中序遍历      
  240.              bsTree.printTree();    
  241.              System.out.printf("\n****************************************\n" );    
  242.   
  243.              System.out.printf("删除根节点 50, \n中序遍历后:" );    
  244.              //删除根节点      
  245.              bsTree.remove(new  Integer( 50 ));    
  246.              bsTree.printTree();        
  247.              
  248.     }  
  249. }  
  250.   
  251. public   class  UnderflowException  extends  RuntimeException{}  


运行结果:

D:\java>java   BinarySearchTree
中序遍历的原始数据:
10  30  40  50  70  80  90
------------------------------------------------
10在二叉树中是否包含:true
--------------------------------------------------
20插入到二叉树,中序遍历后:10  20  30  40  50  70  80  90
-------------------------------------------------
删除叶子节点 20,
中序遍历后:10  30  40  50  70  80  90
*************************************************
删除单孩子节点 90,
中序遍历后:10  30  40  50  70  80
************************************************
删除根节点 50,
中序遍历后:10  30  40  70  80

值的注意的是:二叉排序树同样采用“空间换时间”的做法。

突然发现,二叉排序树的中序遍历同样可以排序数组,呵呵,不错!

PS:  插入操作:O(LogN)。

       删除操作:O(LogN)。

       查找操作:O(LogN)。

分享到:
评论

相关推荐

    二叉排序树_17281183_刘梦婷_leavingtbk_二叉排序树_

    二叉排序树,又称二叉查找树或二叉搜索树,是一种特殊的二叉树数据结构,它具有以下特性:对于树中的每个节点,其左子树中的所有节点的值都小于该节点的值,而右子树中的所有节点的值都大于该节点的值。这种性质使得...

    数据结构课程设计 二叉排序树与平衡二叉排序树

    在数据结构的学习中,二叉排序树(Binary Search Tree,BST)是一种常见的树形数据结构,它具有查找、插入和删除等操作的高效性。在这个课程设计中,我们将重点探讨如何利用二叉链表作为存储结构来实现二叉排序树,...

    Java实现二叉排序树

    二叉排序树(Binary Sort Tree,BST),也称为二叉搜索树,是一种特殊的二叉树数据结构,它的每个节点都包含一个键(key)、一个关联的值、一个指向左子节点的指针和一个指向右子节点的指针。在二叉排序树中,对于...

    二叉排序树插入

    二叉排序树插入算法 二叉排序树插入是指在二叉排序树中插入新的数据元素的过程。二叉排序树是一种特殊的二叉树,它的每个结点的关键字都大于左子树的关键字,小于右子树的关键字。因此,在插入新的数据元素时,需要...

    二叉排序树与文件操作

    【二叉排序树与文件操作】 功能要求: (1)从键盘输入一组学生记录建立二叉排序树; (2)二叉排序树存盘; (3)由文件恢复内存的二叉排序树; (4)中序遍历二叉排序树; (5)求二叉排序树深度; (6)求二叉...

    二叉排序树C++实现

    二叉排序树(Binary Sort Tree,BST),也称为二叉查找树或二叉搜索树,是一种特殊的二叉树数据结构,它的每个节点都包含一个键(key)、一个关联的值、一个指向左子树的引用和一个指向右子树的引用。在二叉排序树中...

    数据结构之二叉排序树的生成

    二叉排序树,又称二叉查找树或二叉搜索树,是一种特殊的数据结构,它具有以下特性:对于树中的任意节点,其左子树中的所有节点的值都小于该节点的值,而右子树中所有节点的值都大于该节点的值。这种特性使得在二叉...

    二叉排序树 c 版本

    【二叉排序树】,全称为Binary Sort Tree,是一种特殊的二叉树,其每个节点的值都大于其左子树中的所有节点值,且小于其右子树中的所有节点值。这种特性使得二叉排序树在查找、插入和删除操作上具有较高的效率。 在...

    实现二叉排序树的各种算法

    二叉排序树(Binary Sort Tree,BST),也称为二叉查找树或二叉搜索树,是一种自平衡的二叉树数据结构,它在处理搜索、插入和删除操作时具有较高的效率。二叉排序树的主要特性是:对于任意节点,其左子树中的所有...

    数据结构二叉排序树及其操作实验报告

    二叉排序树(Binary Sort Tree,BST),也称为二叉查找树或有序二叉树,是一种特殊类型的二叉树,其每个节点的左子树只包含比其小的元素,右子树包含比其大的元素,且整个树保持自平衡。在本实验报告中,我们将深入...

    二叉排序树C++

    二叉排序树(Binary Sort Tree,BST),也称为二叉搜索树或有序二叉树,是一种自平衡的二叉树数据结构。在二叉排序树中,对于任意一个节点,其左子树中的所有节点的值都小于该节点的值,而右子树中的所有节点的值都...

    数据结构二叉排序树的源代码

    根据给定的信息,我们可以分析出该段代码主要实现了二叉排序树的基本操作,包括创建、插入元素、查找元素以及中序遍历等。下面将详细解释这些知识点。 ### 数据结构:二叉排序树 二叉排序树(Binary Search Tree, ...

    二叉排序树增删改查

    二叉排序树(Binary Sort Tree,BST),也称为二叉搜索树,是一种特殊的二叉树数据结构,它具有以下特性: 1. 每个节点包含一个键(key)、一个关联的值、一个指向左子节点的引用和一个指向右子节点的引用。 2. ...

    二叉排序树C实现代码

    二叉排序树C语言的简单实现,包含如下操作: 1.创建二叉排序树; 2.销毁二叉排序树; 3.清空二叉排序树; 4.插入指点结点至二叉排序树; 5.删除二叉排序树指点结点; 5.获取二叉排序树指定结点; 6.获取二叉排序树根...

    二叉排序树实现教师成果管理系统源码

    二叉排序树(Binary Sort Tree,BST),也称为二叉搜索树,是一种特殊的二叉树数据结构,它的每个节点都包含一个键值,且满足以下性质:对于任意节点,其左子树中所有节点的键值均小于该节点的键值;其右子树中所有...

    vc++二叉排序树的程序

    二叉排序树(Binary Search Tree,BST),又称为二叉查找树或有序二叉树,是一种自平衡的二叉树数据结构。它在计算机科学中扮演着重要角色,特别是在数据检索、排序和组织方面。VC++是Microsoft开发的一款集成开发...

Global site tag (gtag.js) - Google Analytics