二分查找
二分查找的原理很简单:
在一个有序数组中(本文讨论的是升序,降序同理)
从数组中间的元素开始,如果A[mid]大于被查找元素key,那么就在A[0]到A[mid-1]中查找,反之在A[mid++]到A[A.lenth - 1]中查找。
从这看来,递归的意味又很浓啊,当然也可以用非递归的方式,效率更高,意味二分查找比较简单,就直接上代码了:
定义一个查找抽象基类:
public abstract classSearchBase {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 Integer search(Comparablekey);
}
二分查找代码:
public class BinarySearch extendsSearchBase {/*(non-Javadoc)
* @see Search.SearchBase#search(java.lang.Comparable)*/@SuppressWarnings("unchecked")
@Overridepublic Integer search(Comparablekey) {//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) {returnmid;
}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 Integer searchRecursion(Comparablekey,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
returnmid;
}public static voidmain(String[] args) {
BinarySearch binarySearch= newBinarySearch();
System.out.println(binarySearch.searchRecursion(0,0,binarySearch.a.length-1));
}
}
对于查找来说,又两个指标比较重要,一个是插入新元素的效率,一个是查找的效率:
二分查找平均插入效率:O(N/2)
二分查找平均查找效率:O(lgN)
二叉查找树
二叉查找树简单的说,就是一个二叉树:
构建过程:
左子树所有节点小于根节点,右子树所有节点大于等于根节点(可以反过来,自己定义)
查找过程:
中序遍历,如果查找到就返回。
其实二叉查找树也可以用来排序,和堆排序很像。
在构建二叉查找树时,构建出来的树的形状是非常重要的,直接影响到查找的效率,如下图:
如最左边的图,最好的情况是一个完全二叉树,这样查找效率最高。
如最右边的图,最坏的情况会退化成一个链表,这样查找效率最低。
直接上代码实现:
public class BinarySearchTree extendsSearchBase {class Node{public Node(Comparable value,Node leftChile,NoderightChild) {this.value =value;this.leftChild =leftChile;this.rightChild =rightChild;
}
Comparable value = null;
Node leftChild = null;
Node rightChild = null;
}
@Overridepublic Integer search(Comparablekey) {//TODO Auto-generated method stub
return null;
}
@SuppressWarnings("unchecked")public T search(Comparable key,Noderoot) {//TODO Auto-generated method stub
Node 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 Node addTree(Comparable value,Nodenode) {if(node == null)return new Node(value,null,null);if(node.value.compareTo((T)value) > 0)
node.leftChild=addTree(value, node.leftChild);elsenode.rightChild=addTree(value, node.rightChild);returnnode;
}//遍历树,输出有序序列
public void traverseTree(Nodenode) {if(node == null)return;
traverseTree(node.leftChild);
System.out.print(node.value);
traverseTree(node.rightChild);
}public static voidmain(String[] args) {
BinarySearchTree binarySearchTree= newBinarySearchTree();
Integer[] b= {1,4,2,6,7,0,3};
BinarySearchTree.Node root = binarySearchTree.new Node(b[0],null,null);for(int i=1;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