查找(一):二分查找和二叉查找树

二分查找

二分查找的原理很简单:
在一个有序数组中(本文讨论的是升序,降序同理) java

从数组中间的元素开始,若是A[mid]大于被查找元素key,那么就在A[0]到A[mid-1]中查找,反之在A[mid++]到A[A.lenth - 1]中查找。 node

从这看来,递归的意味又很浓啊,固然也能够用非递归的方式,效率更高,意味二分查找比较简单,就直接上代码了: 数组

定义一个查找抽象基类:ide

 

public abstract class SearchBase {
    public Integer[] a = {0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8};
    
    //public Character[] a = {'a' ,'b' ,'c' ,'d' ,'e' ,'f' ,'g' ,'h' ,'i'};
    
    public abstract <T> Integer search(Comparable<T> key);
}

 

二分查找代码:this

public class BinarySearch extends SearchBase {

    /* (non-Javadoc)
     * @see Search.SearchBase#search(java.lang.Comparable)
     */
    @SuppressWarnings("unchecked")
    @Override
    public <T> Integer search(Comparable<T> key) {
        // TODO Auto-generated method stub
        Integer low = 0;
        Integer high = a.length - 1;
        Integer mid = (low + high)/2;
        
        while(low <= high) {
            if(key.compareTo((T) a[mid]) == 0) {
                return mid;
            } else if(key.compareTo((T) a[mid]) > 0) {
                low = ++mid;
            } else if(key.compareTo((T) a[mid]) < 0) {
                high = --mid;
            }
            mid = (low + high)/2;
        }
        
        return -1;
    }
    
    @SuppressWarnings("unchecked")
    public <T> Integer searchRecursion(Comparable<T> key,Integer low,Integer high) {
        if(low > high)
            return -1;
        Integer mid = (low + high)/2;
        if(key.compareTo((T) a[mid]) > 0)
            return searchRecursion(key,++mid,high);
        else if(key.compareTo((T) a[mid]) < 0)
            return searchRecursion(key,low,--mid);
        else
            return mid;
    }
    
    public static void main(String[] args) {
        BinarySearch binarySearch = new BinarySearch();
        System.out.println(binarySearch.searchRecursion(0,0,binarySearch.a.length-1));
    }
    
}

 

 

对于查找来讲,又两个指标比较重要,一个是插入新元素的效率,一个是查找的效率: spa

二分查找平均插入效率:O(N/2) code

二分查找平均查找效率:O(lgN) blog

二叉查找树

二叉查找树简单的说,就是一个二叉树: 排序

构建过程: 递归

左子树全部节点小于根节点,右子树全部节点大于等于根节点(能够反过来,本身定义)

 

查找过程:

    中序遍历,若是查找到就返回。

 

其实二叉查找树也能够用来排序,和堆排序很像

 

在构建二叉查找树时,构建出来的树的形状是很是重要的,直接影响到查找的效率,以下图:

 

如最左边的图,最好的状况是一个彻底二叉树,这样查找效率最高。

如最右边的图,最坏的状况会退化成一个链表,这样查找效率最低。

 

直接上代码实现:

public class BinarySearchTree extends SearchBase {
    
    class Node<T> {
        
        public Node(Comparable<T> value,Node<T> leftChile,Node<T> rightChild) {
            this.value = value;
            this.leftChild = leftChile;
            this.rightChild = rightChild;
        }
        
        Comparable<T> value = null;
        Node<T> leftChild = null;
        Node<T> rightChild = null;
    }

    @Override
    public <T> Integer search(Comparable<T> key) {
        // TODO Auto-generated method stub
        return null;
    }
    
    @SuppressWarnings("unchecked")
    public <T> T search(Comparable<T> key,Node<T> root) {
        // TODO Auto-generated method stub
        Node<T> node = root;
        while(node != null) {
            if(key.compareTo((T) node.value) < 0) {
                node = node.leftChild;
            } else if(key.compareTo((T) node.value) > 0){
                node = node.rightChild;
            } else {
                break;
            }
        }
        
        if(node == null)
            return null;
        else 
            return (T) node.value;
    }

    //向树中添加元素
    @SuppressWarnings("unchecked")
    public <T> Node<T> addTree(Comparable<T> value,Node<T> node) {
        if(node == null)
            return new Node<T>(value,null,null);
        
        if(node.value.compareTo((T)value) > 0)
            node.leftChild = addTree(value, node.leftChild);
        else 
            node.rightChild = addTree(value, node.rightChild);
        
        return node;
    }
    
    
    //遍历树,输出有序序列
    public <T> void traverseTree(Node<T> node) {
        if(node == null)
            return;
        
        traverseTree(node.leftChild);
        System.out.print(node.value);
        traverseTree(node.rightChild);
    }
    
    public static void main(String[] args) {
        BinarySearchTree binarySearchTree = new BinarySearchTree();
        Integer[] b = {1,4,2,6,7,0,3};
        
        BinarySearchTree.Node<Integer> root = binarySearchTree.new Node<Integer>(b[0],null,null);
        for(int i=1;i<b.length;i++) {
            root = binarySearchTree.addTree(b[i],root);
        }
        
        binarySearchTree.traverseTree(root);
        System.out.println();
        
        Integer result = binarySearchTree.search(1,root);
        System.out.println("result: " + result);
    }
}

 

二叉查找树平均插入效率:1.39LgN

二叉查找树平均查找效率:1.39LgN

相关文章
相关标签/搜索