算法——顺序查找和二分查找

顺序查找(无序链表)java

符号表中使用的数据结构的一个简单选择就是链表,每一个结点存储一个键值对。get()方法和put()方法的实现即为遍历链表。代码实现以下:算法

public class SequentialSearchST<Key,Value>{
	private Node first;//链表首节点
	private class Node{
		 //链表结点的定义
		Key key;
		Value val;
		Node next;
		public Node(Key key,Value val,Node next) {
			this.key=key;
			this.val=val;
			this.next=next;
		}
	}
	public Value get(Key key) {
		  //查找给定的键,返回键的值
		for(Node x=first;x!=null;x=x.next) {
			if(key.equals(x.key)) {
				return x.val;//命中
			}
		}
		return null; //未命中
	}
	public void put(Key key,Value val) {
		for(Node x=first;x!=null;x=x.next) {
			if(key.equals(x.key)) {
				x.val=val;return; //命中,更新
			}
		}
		first=new Node(key,val,first); //将put进的结点设置为first结点,并指向原first结点
	}
}

性能分析数组

在表中查找一个不存在的键时,咱们会将表中每一个键和给定的键比较(N)。由于不容许出现重复的键,每次插入操做以前咱们都须要这样查找一遍。数据结构

                推论: 向一个空表中插入N个不一样的键须要~N²/2次比较。函数

链表的实现以及顺序查找是很是低效的,没法知足Frequency-Counter处理庞大输入问题的需求。比较的总次数和查找次数与插入次数的乘积成正比。性能

 

二分查找(有序数组)this

它使用的数据结构是一对平行的数组,一个存储键一个存储值。算法先保证数组中的Comparable类型的键有序,而后再使用数组的索引来高效的实现get()和其余操做。code

这份实现的核心是rank()方法,它返回表中小于给定键的键的数量。对于get()方法,只要给定的键存在于表中,rank()方法就可以精确地告诉咱们在哪里能找到它(若是找不到,那它确定不在表中了)。排序

对于put()方法,只要给定的键存在于表中,rank()方法就可以精确地告诉咱们到哪里去更新他的值,以及当键不在表中时将键存储到标的何处。咱们将全部更大的键向后移动一格来腾出位置。索引

实现代码以下:

public class BinarySearchST<Key extends Comparable<Key>,Value>{
	private Key[] keys;
	private Value[] vals;
	private int N;//存储当前字符表的大小
	public BinarySearchST(int capacity) {
		keys=(Key[])new Comparable[capacity];
		vals=(Value[])new Object[capacity];
	}
	public int size() {
		return N;
	}
	public Value get(Key key) {
		if(isEmpty())return null;
		int i=rank(key);
		if(i<N&&keys[i].compareTo(key)==0)return vals[i];
		else return null;
	}
	public int rank(Key key) {
		int lo=0,hi=N-1;
		while(lo<=hi) {
			int mid=lo+(hi-lo)/2;
			int cmp=key.compareTo(keys[mid]);
			if(cmp<0)hi=mid-1;
			else if(cmp>0)lo=mid+1;
			else return mid;
		}
		return lo;
	}
}

性能分析:在N个键的有序数组中进行二分超找最多须要(lgN+1)次比较(不管是否成功)。

二分查找减小了比较的次数但没法减小运行所需的时间,由于它没法改变如下事实:在键是随机排列的状况下,构造一个基于有序数组的符号表所须要的访问数组的次数是数组长度的平方级别。

通常状况下二分查找都比顺序查找快得多,它也是众多实际应用程序的最佳选择,对于一个静态表(不容许插入)来讲,将其在初始化时就排序是值得的。即便查找前全部的键值对已知,为BinarySearchST添加一个可以初始化并将符号表排序的构造函数也是有意义的。

可是,二分查找也适合不少应用。咱们须要在构造庞大的符号表的同时可以任意插入(删除)键值对,同时也可以完成查找操做。

相关文章
相关标签/搜索