二叉查找樹--查找、刪除、插入(Java實現)


文章,未經博主允許不得轉載。

目錄(?)        下篇:平衡二叉樹

               http://blog.csdn.net/kiritor/article/details/8892648

        二叉查找樹

                 二叉查找樹(Binary Search Tree),或者是一顆空樹,或者是具有下列性質的二叉樹:

                       1、若它的左子樹不空,則其左子樹上的所有結點的值均小於它根結點的值;

                       2、若它的右子樹不空,則其右子樹上的所有結點的值均大於它根結點的值;

                       3、它的左、右子樹也分別爲二叉查找樹。

                                                  

                 二叉查找樹是基於二叉樹的,其結點數據結構定義爲如下:

[java] view plain copy
  1. /**結點數據結構*/  
  2. static class BinaryNode<T>  
  3. {  
  4.     T data;  
  5.     BinaryNode<T> left;  
  6.     BinaryNode<T> right;  
  7.     public BinaryNode(T data) {  
  8.         this(data,null,null);  
  9.     }  
  10.     public BinaryNode( T data, BinaryNode<T> left, BinaryNode<T> right) {  
  11.         this.data =data;  
  12.         this.left = left;  
  13.         this.right =right;  
  14.     }  
  15.     public BinaryNode()  
  16.     {  
  17.         data =null;  
  18.         this.left = left;  
  19.         this.right =right;  
  20.     }  
  21. }  

                 現在明白了什麼是二叉查找樹,那麼二叉查找書的基本操作又是如何來實現的呢?                

          查找操作

                       在二叉查找樹中查找x的過程如下:

                             1、若二叉樹是空樹,則查找失敗。

                             2、若x等於根結點的數據,則查找成功,否則。

                             3、若x小於根結點的數據,則遞歸查找其左子樹,否則。

                             4、遞歸查找其右子樹。

                     根據上述的步驟,寫出其查找操作的代碼: 

[java] view plain copy
  1. /**查找指定的元素,默認從 
  2.     * 根結點出開始查詢*/  
  3.    public boolean contains(T t)  
  4.    {  
  5.       return contains(t, rootTree);  
  6.          
  7.    }  
  8.  /**從某個結點出開始查找元素*/  
  9.    public boolean contains(T t, BinaryNode<T> node)  
  10.    {  
  11.       if(node==null)  
  12.         return false;//結點爲空,查找失敗  
  13.       int result = t.compareTo(node.data);  
  14.        if(result>0)  
  15.           return contains(t,node.right);//遞歸查詢右子樹  
  16.       else if(result<0)  
  17.           return contains(t, node.left);//遞歸查詢左子樹    
  18.       else  
  19.           return true;  
  20.    }  
  21.     /** 
  22.        這裏我提供一個對二叉樹最大值 
  23.        最小值的搜索*/  
  24.    
  25.   
  26.  /**找到二叉查找樹中的最小值*/  
  27.    public T findMin()  
  28.    {  
  29.       if(isEmpty())  
  30.       {  
  31.           System.out.println("二叉樹爲空");  
  32.           return null;  
  33.       }else  
  34.        return findMin(rootTree).data;  
  35.          
  36.    }  
  37.    /**找到二叉查找樹中的最大值*/  
  38.    public T findMax()  
  39.    {  
  40.        if(isEmpty())  
  41.           {  
  42.               System.out.println("二叉樹爲空");  
  43.               return null;  
  44.           }else  
  45.            return findMax(rootTree).data;  
  46.    }  
  47.   
  48. /**查詢出最小元素所在的結點*/  
  49.    public BinaryNode<T> findMin(BinaryNode<T> node)  
  50.    {  
  51.        if(node==null)  
  52.            return null;  
  53.        else if(node.left==null)  
  54.            return node;  
  55.        return findMin(node.left);//遞歸查找  
  56.    }  
  57.    /**查詢出最大元素所在的結點*/  
  58.    public BinaryNode<T> findMax(BinaryNode<T> node)  
  59.    {  
  60.        if(node!=null)  
  61.        {  
  62.            while(node.right!=null)  
  63.                node=node.right;  
  64.        }  
  65.        return node;         
  66.    }  

           插入操作

                     二叉樹查找樹b插入操作x的過程如下:

                        1、若b是空樹,則直接將插入的結點作爲根結點插入。

                        2、x等於b的根結點的數據的值,則直接返回,否則。

                        3、若x小於b的根結點的數據的值,則將x要插入的結點的位置改變爲b的左子樹,否則。

                        4、將x要出入的結點的位置改變爲b的右子樹。

               代碼實現如下:

[java] view plain copy
  1. /**插入元素*/  
  2.    public void insert(T t)  
  3.    {  
  4.        rootTree = insert(t, rootTree);  
  5.    }  
  6. /**在某個位置開始判斷插入元素*/  
  7.    public BinaryNode<T> insert(T t,BinaryNode<T> node)  
  8.    {  
  9.        if(node==null)  
  10.        {  
  11.            //新構造一個二叉查找樹  
  12.            return new BinaryNode<T>(t, nullnull);  
  13.        }  
  14.        int result = t.compareTo(node.data);  
  15.        if(result<0)  
  16.           node.left= insert(t,node.left);  
  17.        else if(result>0)  
  18.           node.right= insert(t,node.right);  
  19.        else  
  20.            ;//doNothing  
  21.        return node;  
  22.    }  

          刪除操作

                         對於二叉查找樹的刪除操作(這裏根據值刪除,而非結點)分三種情況:

                   不過在此之前,我們應該確保根據給定的值找到了要刪除的結點,如若沒找到該結點

                   不會執行刪除操作!

                      下面三種情況假設已經找到了要刪除的結點。

                        1、如果結點爲葉子結點(沒有左、右子樹),此時刪除該結點不會玻化樹的結構

                             直接刪除即可,並修改其父結點指向它的引用爲null.如下圖:

                

                       2、如果其結點只包含左子樹,或者右子樹的話,此時直接刪除該結點,並將其左子樹

                              或者右子樹設置爲其父結點的左子樹或者右子樹即可,此操作不會破壞樹結構。
                 
                           

                       3、 當結點的左右子樹都不空的時候,一般的刪除策略是用其右子樹的最小數據

                            (容易找到)代替要刪除的結點數據並遞歸刪除該結點(此時爲null),因爲

                              右子樹的最小結點不可能有左孩子,所以第二次刪除較爲容易。

                               z的左子樹和右子樹均不空。找到z的後繼y,因爲y一定沒有左子樹,所以可以刪除y,

                              並讓y的父親節點成爲y的右子樹的父親節點,並用y的值代替z的值.如圖:

                    

                  刪除操作源碼:

[java] view plain copy
  1. /**刪除元素*/  
  2.    public void remove(T t)  
  3.    {  
  4.        rootTree = remove(t,rootTree);  
  5.    } /**在某個位置開始判斷刪除某個結點*/  
  6.    public BinaryNode<T> remove(T t,BinaryNode<T> node)  
  7.    {  
  8.        if(node == null)  
  9.            return node;//沒有找到,doNothing  
  10.        int result = t.compareTo(node.data);  
  11.        if(result>0)  
  12.            node.right = remove(t,node.right);  
  13.        else if(result<0)  
  14.            node.left = remove(t,node.left);  
  15.        else if(node.left!=null&&node.right!=null)  
  16.        {  
  17.            node.data = findMin(node.right).data;  
  18.            node.right = remove(node.data,node.right);  
  19.        }  
  20.        else  
  21.            node = (node.left!=null)?node.left:node.right;  
  22.        return node;  
  23.              
  24.    }  

             完整源碼

[java] view plain copy
  1. <p></p><pre name="code" class="java">package com.kiritor;  
  2. /** 
  3.  * Java實現二叉查找樹 
  4.  * @author Kiritor 
  5.  * @param <T>*/  
  6. public class BinarySearchTree<T extends Comparable<? super T>> {  
  7.     
  8.  /**結點數據結構*/  
  9.  static class BinaryNode<T>  
  10.     {  
  11.         T data;  
  12.         BinaryNode<T> left;  
  13.         BinaryNode<T> right;  
  14.         public BinaryNode(T data) {  
  15.             this(data,null,null);  
  16.         }  
  17.         public BinaryNode( T data, BinaryNode<T> left, BinaryNode<T> right) {  
  18.             this.data =data;  
  19.             this.left = left;  
  20.             this.right =right;  
  21.         }  
  22.         public BinaryNode()  
  23.         {  
  24.             data =null;  
  25.             this.left = left;  
  26.             this.right =right;  
  27.         }  
  28.     }  
  29.      
  30.    private BinaryNode<T> rootTree;  
  31.    /**構造一顆空的二叉查找樹*/  
  32.    public BinarySearchTree()  
  33.    {  
  34.        rootTree = null;  
  35.    }  
  36.    /**清空二叉查找樹*/  
  37.    public void clear()  
  38.    {  
  39.        rootTree = null;  
  40.    }  
  41.    /**判斷是否爲空*/  
  42.    public boolean isEmpty()  
  43.    {  
  44.        return rootTree == null;  
  45.    }  
  46.    /**查找指定的元素,默認從 
  47.     * 根結點出開始查詢*/  
  48.    public boolean contains(T t)  
  49.    {  
  50.       return contains(t, rootTree);  
  51.          
  52.    }  
  53.    /**找到二叉查找樹中的最小值*/  
  54.    public T findMin()  
  55.    {  
  56.       if(isEmpty())  
  57.       {  
  58.           System.out.println("二叉樹爲空");  
  59.           return null;  
  60.       }else  
  61.        return findMin(rootTree).data;  
  62.          
  63.    }  
  64.    /**找到二叉查找樹中的最大值*/  
  65.    public T findMax()  
  66.    {  
  67.        if(isEmpty())  
  68.           {  
  69.               System.out.println("二叉樹爲空");  
  70.               return null;  
  71.           }else  
  72.            return findMax(rootTree).data;  
  73.    }  
  74.    /**插入元素*/  
  75.    public void insert(T t)  
  76.    {  
  77.        rootTree = insert(t, rootTree);  
  78.    }  
  79.    /**刪除元素*/  
  80.    public void remove(T t)  
  81.    {  
  82.        rootTree = remove(t,rootTree);  
  83.    }  
  84.    /**打印二叉查找樹*/  
  85.    public void printTree()  
  86.    {  
  87.         
  88.    }  
  89.    /**從某個結點出開始查找元素*/  
  90.    public boolean contains(T t, BinaryNode<T> node)  
  91.    {  
  92.       if(node==null)  
  93.         return false;  
  94.       int result = t.compareTo(node.data);  
  95.       if(result>0)  
  96.           return contains(t,node.right);  
  97.       else if(result<0)  
  98.           return contains(t, node.left);  
  99.       else  
  100.           return true;  
  101.    }  
  102.    /**查詢出最小元素所在的結點*/  
  103.    public BinaryNode<T> findMin(BinaryNode<T> node)  
  104.    {  
  105.        if(node==null)  
  106.            return null;  
  107.        else if(node.left==null)  
  108.            return node;  
  109.        return findMin(node.left);//遞歸查找  
  110.    }  
  111.    /**查詢出最大元素所在的結點*/  
  112.    public BinaryNode<T> findMax(BinaryNode<T> node)  
  113.    {  
  114.        if(node!=null)  
  115.        {  
  116.            while(node.right!=null)  
  117.                node=node.right;  
  118.        }  
  119.        return node;      
  120.    }  
  121.    /**在某個位置開始判斷插入元素*/  
  122.    public BinaryNode<T> insert(T t,BinaryNode<T> node)  
  123.    {  
  124.        if(node==null)  
  125.        {  
  126.            //新構造一個二叉查找樹  
  127.            return new BinaryNode<T>(t, nullnull);  
  128.        }  
  129.        int result = t.compareTo(node.data);  
  130.        if(result<0)  
  131.           node.left= insert(t,node.left);  
  132.        else if(result>0)  
  133.           node.right= insert(t,node.right);  
  134.        else  
  135.            ;//doNothing  
  136.        return node;  
  137.    }  
  138.    /**在某個位置開始判斷刪除某個結點*/  
  139.    public BinaryNode<T> remove(T t,BinaryNode<T> node)  
  140.    {  
  141.        if(node == null)  
  142.            return node;//沒有找到,doNothing  
  143.        int result = t.compareTo(node.data);  
  144.        if(result>0)  
  145.            node.right = remove(t,node.right);  
  146.        else if(result<0)  
  147.            node.left = remove(t,node.left);  
  148.        else if(node.left!=null&&node.right!=null)  
  149.        {  
  150.            node.data = findMin(node.right).data;  
  151.            node.right = remove(node.data,node.right);  
  152.        }  
  153.        else  
  154.            node = (node.left!=null)?node.left:node.right;  
  155.        return node;  
  156.              
  157.    }  
  158.    public BinaryNode<Integer> init()  
  159.    {  
  160.        BinaryNode<Integer> node3 = new BinaryNode<Integer>(3);  
  161.        BinaryNode<Integer> node1 = new BinaryNode<Integer>(1);  
  162.        BinaryNode<Integer> node4 = new BinaryNode<Integer>(4,node3,null);  
  163.        BinaryNode<Integer> node2 = new BinaryNode<Integer>(2,node1,node4);  
  164.        BinaryNode<Integer> node8 = new BinaryNode<Integer>(8);  
  165.        BinaryNode<Integer> root = new BinaryNode<Integer>(6,node2,node8);  
  166.        return root;  
  167.    }  
  168.     public void preOrder(BinaryNode node) {  
  169.         if (node != null) {  
  170.             System.out.print(node.data);  
  171.             preOrder(node.left);  
  172.             preOrder(node.right);  
  173.         }  
  174.     }  
  175.       /*簡單測試*/   
  176.       public static void main(String[] args) {  
  177.         BinarySearchTree  searchTree = new BinarySearchTree<>();  
  178.         BinaryNode<Integer> node= searchTree.init();  
  179.         searchTree.rootTree=node;  
  180.         searchTree.preOrder(searchTree.rootTree);  
  181.         searchTree.remove(4);  
  182.         searchTree.preOrder(searchTree.rootTree);  
  183.     }  
  184.      
  185. }      </pre>  
  186. <pre></pre>  
  187. <pre></pre>  
  188. <pre></pre>  
  189. <pre></pre>  
  190. <pre></pre>  
  191. <pre></pre>  
  192.      
發佈了164 篇原創文章 · 獲贊 26 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章