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

順序查找(無序鏈表)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添加一個可以初始化並將符號表排序的構造函數也是有意義的。

可是,二分查找也適合不少應用。咱們須要在構造龐大的符號表的同時可以任意插入(刪除)鍵值對,同時也可以完成查找操做。

相關文章
相關標籤/搜索