數據結構筆記--二叉查找樹概述以及java代碼實現


一些概念:

  二叉查找樹的重要性質:對於樹中的每一個節點X,它的左子樹任一節點的值均小於X,右子樹上任意節點的值均大於X.

  二叉查找樹是java的TreeSet和TreeMap類實現的基礎.

  由於樹的遞歸定義,二叉查找樹的代碼實現也基本上都是使用遞歸的函數,二叉查找樹的平均深度是O(logN).

  因為二叉查找樹要求所有的節點都可以進行排序.所以編寫時代碼時需要一個Comparable泛型接口,當需要對類中的對象進行排序的時候,就需要實現這個泛型接口,里邊定義了一個public int compareTo(Object o)方法,接受一個Object作為參數,java中String,Integer等類都實現了這個接口.

java代碼實現:

  remove方法:在查找樹的代碼實現中,最難得是刪除,因為這涉及到三種情況:

    被刪除節點是樹葉節點(沒有子樹):最簡單,直接刪除,將該節點置為null即可

    被刪除節點有一個子節點(左子樹或右子樹):是該節點的父節點指向該節點的子節點(左或右).見圖1

    被刪除節點有兩個子節點:用其右子樹中的最小值代替該節點上的值,刪除其右子樹上的最小值.見圖2.

  

  1 package com.wang.tree;
  2 
  3 public class BinarySearchTree<T extends Comparable<T>>{
  4 
  5     
  6     private static class Node<T>{
  7         private T data;
  8         private Node<T> left;
  9         private Node<T> right;
 10         
 11         public Node(T data){
 12             this(data,null,null);
 13         }
 14         public Node(T data, Node<T> left, Node<T> right) {
 15             this.data = data;
 16             this.left = left;
 17             this.right = right;
 18         }
 19     }
 20     
 21     //私有變量 根節點root
 22     private Node<T> root;
 23     
 24     //無參構造函數,根節點為null
 25     public BinarySearchTree(){
 26         root=null;
 27     }
 28     
 29     //清空二叉查找樹
 30     public void makeEmpty(){
 31         root=null;
 32     }
 33     //判斷樹是否為空
 34     public boolean isEmpty(){
 35         
 36         return root==null;
 37     }
 38     //查找集合中是否有元素value,有返回true
 39     public boolean contains(T value){
 40         
 41         return contains(value,root);
 42     }
 43     
 44     private boolean contains(T value, Node<T> t) {
 45         
 46         if(t==null){
 47             return false;
 48         }
 49         int result=value.compareTo(t.data);
 50         if(result<0){
 51             return contains(value,t.left);
 52         }else if(result>0){
 53             return contains(value,t.right);
 54         }else{
 55             return true;
 56         }
 57     }
 58 
 59     //查找集合中的最小值
 60     public T findMin(){
 61         
 62         return  findMin(root).data;
 63     }
 64     private Node<T> findMin(Node<T> t) {
 65         if(t==null){
 66             return null;
 67         }else if(t.left==null){
 68             return t;
 69         }
 70         
 71         
 72         return findMin(t.left);
 73     }
 74 
 75     //查找集合中的最大值
 76     public T findMax(){
 77         
 78         return findMax(root).data;
 79     }
 80     
 81     private Node<T> findMax(Node<T> t) {
 82         if(t!=null){
 83             while(t.right!=null){
 84                 t=t.right;
 85             }
 86         }
 87         
 88         return t;
 89     }
 90 
 91     //插入元素
 92     public void insert(T value){
 93         
 94         root =insert(value,root);
 95     }
 96 
 97     private Node<T> insert(T value, Node<T> t) {
 98         if(t==null){
 99             return new Node(value,null,null);
100         }
101         int result=value.compareTo(t.data);
102         if(result<0){
103             t.left=insert(value,t.left);
104         }else if(result>0){
105             t.right=insert(value,t.right);
106         }
107         return t;
108     }
109     //移除元素
110     public void remove(T value){
111         root=remove(value,root);
112         
113         
114     }
115 
116     private Node<T> remove(T value, Node<T> t) {
117         if(t==null){
118             return t;
119         }
120         
121         int result=value.compareTo(t.data);
122         if(result<0){
123             t.left=remove(value,t.left);
124         }else if(result>0){
125             t.right=remove(value,t.right);
126         }else if(t.left!=null&&t.right!=null){//如果被刪除節點有兩個兒子
127             //1.當前節點值被其右子樹的最小值代替
128             t.data=findMin(t.right).data;
129             //將右子樹的最小值刪除
130             t.right=remove(t.data, t.right);
131         }else{
132             //如果被刪除節點是一個葉子 或只有一個兒子
133             t=(t.left!=null)?t.left:t.right;
134         }
135         
136         return t;
137     }
138     
139     //中序遍歷打印
140     public void printTree(){
141         printTree(root);
142     }
143 
144     private void printTree(Node<T> t) {
145         
146         if(t!=null){
147             printTree(t.left);
148             System.out.println(t.data);
149             printTree(t.right);
150         }
151     }
152 }

  測試代碼:

package com.wang.tree;

public class TestBST {

    public static void main(String[] args) {
        
        BinarySearchTree<Integer> bst=new BinarySearchTree<>();
        bst.insert(5);
        bst.insert(7);
        bst.insert(3);
        bst.insert(1);
        bst.insert(9);
        bst.insert(6);
        bst.insert(4);
        System.out.println("最小值:"+bst.findMin());
        System.out.println("最大值:"+bst.findMax());
        System.out.println("查找元素9是否存在:"+bst.contains(9));
        System.out.println("查找元素8是否存在:"+bst.contains(8));
        System.out.println("遍歷二叉樹");
        bst.printTree();
    }
}

打印結果:

最小值:1
最大值:9
查找元素9是否存在:true
查找元素8是否存在:false
遍歷二叉樹
1
3
4
5
6
7
9

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM