[Algorithms]查找之符号表SybolTable

符号表API

 1.使用 泛型
 2.键不能为空
 3.get方法是否返回空来测试给定的键是否存在于符号表中
 4.关于删除 :延时删除---》将键对应的值置为空
  即使删除---》立即从表中删除指定的键如put(key,null)
 5.迭代:所有实现必须包含 iterator方法来返回一个迭代器
 6. 所有对象都继承了equals()方法,自定义的键需要重写equals()方法
 
package Chapter3_1.SymbolTable;

/*符号表API
 * 1.使用泛型
 * 2.键不能为空
 * 3.get方法是否返回空来测试给定的键是否存在于符号表中
 * 4.关于删除 :延时删除---》将键对应的值置为空
 * 即使删除---》立即从表中删除指定的键如put(key,null)
 * 5.迭代:所有实现必须包含iterator方法来返回一个迭代器
 * 6.所有对象都继承了equals()方法,自定义的键需要重写equals()方法
 * */

public interface ST<Key,Value> {
	public void put(Key key,Value value);
	public Value get(Key key);
	public void delete(Key key);
	public boolean contains(Key key);
	public boolean isEmpty();
	public int size();
	Iterable<Key> keys();//包含迭代器以方便用例遍历所有的键
}

基本实现

/*符号表的简单实现:测试时,用例的输出中键的顺序是不确定的*/

package Chapter3_1.SymbolTable;

import com.sun.corba.se.impl.oa.poa.ActiveObjectMap.Key;

import jdk.internal.org.objectweb.asm.tree.analysis.Value;

public class SybolTable implements ST<Key, Value> {

	@Override
	public void put(Key key, Value value) {
		
		//防御性代码
		if (value == null) {
			delete(key);
			return;
		}

	}

	@Override
	public Value get(Key key) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void delete(Key key) {
		put(key, null);
	}

	@Override
	public boolean contains(Key key) {
		return get(key) != null;
	}

	@Override
	public boolean isEmpty() {
		return size() == 0;
	}

	@Override
	public int size() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public Iterable<Key> keys() {
		// TODO Auto-generated method stub
		return null;
	}

}

有序符号表

/*有序符号表:测试用例的时候会将键按顺序打印出来,是一种索引用例*/

package Chapter3_1.SymbolTable;

/*Ordered symbol tables.
 * 有序符号表*/

public interface ST_puls<Key,Value> {
	public void put(Key key,Value value);
	public Value get(Key key);
	public void delete(Key key);
	public boolean contains(Key key);
	public boolean isEmpty();
	public int size();
	public Key min();
	public Key max();
	public Key floor(Key key);//小于等于key的最大值
	public Key ceiling(Key key);//大于等于key的最小值
	public int rank(Key key);//小于key键的数量
	public Key select(int k);//排名为k的键
	public void deleteMin();
	public void deleteMax();
	public int size(Key lo,Key hi);//lo..hi之间键的数量
	public Iterable<Key> keys(Key lo,Key hi);//lo..hi之间的所有键(已排序)
	Iterable<Key> keys();//包含迭代器以方便用例遍历所有的键,所有键的集合,已排序
}

基本实现

package Chapter3_1.SymbolTable;

import com.sun.corba.se.impl.oa.poa.ActiveObjectMap.Key;

import jdk.internal.org.objectweb.asm.tree.analysis.Value;

public class SybolTable_puls<Key extends Comparable<Key>, Value> {

	public void put(Key key, Value value) {

		// 防御性代码
		if (value == null) {
			delete(key);
			return;
		}

	}

	public Value get(Key key) {
		// TODO Auto-generated method stub
		return null;
	}

	public void delete(Key key) {
		put(key, null);
	}

	public boolean contains(Key key) {
		return get(key) != null;
	}

	public boolean isEmpty() {
		return size() == 0;
	}

	public int size() {
		// TODO Auto-generated method stub
		return 0;
	}

	public Iterable<Key> keys() {
		return null;
	}

	public Key min() {
		return null;
	}

	public Key max() {
		return null;
	}

	public Key floor(Key key) {
		return null;
	}

	public Key ceiling(Key key) {
		return null;
	}

	public int rank(Key key) {
		return 0;
	}

	public Key select(int k) {
		return null;
	}

	public void deleteMin() {
		delete(min());
	}

	public void deleteMax() {
		delete(max());

	}

	public int size(Key lo, Key hi) {
		if (lo.compareTo(lo) < 0) {
			return 0;
		} else if (contains(hi)) {
			return rank(hi) - rank(lo) + 1;
		} else {
			return rank(hi) - rank(lo);
		}
	}

	public Iterable<Key> keys(Key lo, Key hi) {
		return keys(min(), max());
	}

}

顺序查找(基于无序链表)

效率非常低效,无法满足处理庞大输入问题的需求,比较的总次数和查找次数与插入次数的乘积成正比
package Chapter3_1.SymbolTable;

public class SequentialSearchST<Key, Value> {

	/*
	 * 顺序查找 基于无序链表
	 * 随机命中(查找表中的每个键)---》~N/2
	 * 效率非常低效,无法满足处理庞大输入问题的需求,比较的总次数和查找次数与插入次数的乘积成正比
	 */

	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);
		}
	}
}

二分查找(基于有序数组)

package Chapter3_1.SymbolTable;

import edu.princeton.cs.algs4.Queue;
import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut;

/*二分查找(基于有序数组)
 * 该段符号表的实现用两个数组来保存键和值
 * */

public class BinarySearchST<Key extends Comparable<Key>, Value> {

	private static final int INIT_CAPACITY = 2;
	private Key[] keys;
	private Value[] vals;
	private int N;

	public BinarySearchST() {
		this(INIT_CAPACITY);
	}

	@SuppressWarnings("unchecked")
	public BinarySearchST(int capacity) {
		keys = (Key[]) new Comparable[capacity];
		vals = (Value[]) new Object[capacity];
	}

	private void resize(int capacity) {
		assert capacity >= N;
		Key[] tempk = (Key[]) new Comparable[capacity];
		Value[] tempv = (Value[]) new Object[capacity];
		for (int i = 0; i < N; i++) {
			tempk[i] = keys[i];
			tempv[i] = vals[i];
		}
		vals = tempv;
		keys = tempk;
	}

	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) {// 二分查找运用开始

		/*
		 * 首先将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;
	}

	public void put(Key key, Value val) {
		/* 此方法会在插入新元素前将所有较大的键向后移动一格 */

		if (key == null)
			throw new IllegalArgumentException("first argument to put() is null");

		if (val == null) {
			delete(key);
			return;
		}

		int i = rank(key);
		if (i < N && keys[i].compareTo(key) == 0) {
			vals[i] = val;
			return;
		}

		if (N == keys.length)
			resize(2 * keys.length);
		for (int j = N; j > i; j--) {
			// 注意j>i的条件,代表是较大的键需要排在前面,循环其他键向后移动
			keys[j] = keys[j - 1];
			vals[j] = vals[j - 1];
		}
		keys[i] = key;
		vals[i] = val;
		N++;
	}

	public void delete(Key key) {
		put(key, null);
	}

	public Key min() {
		return keys[0];

	}

	public Key max() {
		return keys[N - 1];
	}

	public Key select(int k) {
		return keys[k];
	}

	public Key ceiling(Key key) {
		int i = rank(key);
		return keys[i];
	}

	public Key floor(Key key) {
		int i = rank(key);
		return keys[i];
	}

	public boolean contains(Key key) {
		return get(key) != null;
	}

	public Iterable<Key> keys(Key lo, Key hi) {
		if (lo == null)
			throw new IllegalArgumentException("first argument to keys() is null");
		if (hi == null)
			throw new IllegalArgumentException("second argument to keys() is null");

		Queue<Key> queue = new Queue<Key>();
		if (lo.compareTo(hi) > 0)
			return queue;
		for (int i = rank(lo); i < rank(hi); i++)
			queue.enqueue(keys[i]);
		if (contains(hi))
			queue.enqueue(keys[rank(hi)]);
		return queue;
	}

	public boolean isEmpty() {
		return size() == 0;
	}

	public Iterable<Key> keys() {
		Queue<Key> q = new Queue<Key>();
		for (int i = 0; i < keys.length; i++) {
			q.enqueue(keys[i]);
		}
		return q;
	}

	public static void main(String[] args) {
		BinarySearchST<String, Integer> st = new BinarySearchST<String, Integer>();
		for (int i = 0; !StdIn.isEmpty(); i++) {
			String key = StdIn.readString();
			st.put(key, i);
		}
		for (String s : st.keys())
			StdOut.println(s + " " + st.get(s));
	}

}

猜你喜欢

转载自blog.csdn.net/qq_38277033/article/details/81010076