有序词典

6.4  有序词典方法

s[mi].getKey=kye ,此时该条目命中,上若只需找到解决网络访问log 之列的因应用的这类的问题是: 插入的操作平凡,查找,上年拆户操作却极少,另外一些问题却正好相反。频繁的查询,删除操作却极少进行,另外一些问题则正好要求平凡的

就查找而言,散列表的平均性能不错,然后在最坏的情况下比如散列函数选择,可能几乎所偶的条目都会相互冲突玉石对散列表的查找回话为单一的,实际上,只要有(n)的条目的冲突,散列表的查找就需要n 的时间

 在对系统响应的素素的极高的场合,(比如各种奥的可实时处理的算法活服务凶)撒,san'lie'bisanliebi,在奥和散列表这种情况下为了更好的使用的无需散列表,转而为新的数据结构。

6.4.1 铨叙关系的与有序查找表

2,3,4,5,6,7, 有序查找表的结构

6.4.2 二分查找

尽管有血查找表的更新效率不高,但由于可讲姜茶好修奥提高中的O(long) .我们采用通常的习惯,通过条目的第来她们支架的铨叙就关心即:

key(a)<=key(b) 当且晋档rank(a) <=rank(b) 形象的说也就说: “小(大)的条目在前后”

在针对的所有条目的按照序列排列的,股可以采用住户的卓效的反问的思想来实现查找,一般是候选条目的即接lo<hi,则取剧中的是mi=(lo+hi)/2 ,然后将条目s[mi] 的管家的自己的 f与关键码key  做比较哦。

观察结果论: 2: 在对有序茶渣表的二分查找工程中,每次需要深入的所有的作伴区间的,继续查找哦的而且不 会接受命中,而且被忽略v的有伴的bubu汗mu'bmub,目标关键码。

6.4.3  有序词典的ADT方法

从ADT方法,有序词典的方法可以看成是无需词典的扩充你,也就是说,只需要早的在无需字典中基础上再增加操作。

first       : 若 词典非空,则返沪的其中关键码最小的数目,否则返回Nulls

                  输入: 无     输出:  条目对象

 last : 若 词典非空,则返回其中关键码最大的条目,否则返回的Null

     输入: 无  输出: 条目对象

successsors(key):  返回有关键码的不小于key的条目的非 降序的组成 的铁带起的

                              输入: 一个关键码 

                             输出 : 条目迭代期

presessesors(key): 返沪有一个关键啊不大于key 的条目一飞圣墟组成的迭代的

                              输入: 一个关键码

                             输出: 条目迭代期

/*
 * 基于有序查找表实现的有序词典
 */

package dsa;

public class SortedDictionary_ExtArray implements SortedDictionary {
	Vector	S;//有序查找表
	Comparator C;//比较器

//默认构造方法
	public SortedDictionary_ExtArray()
	{	this(new ComparatorDefault()); }

//构造方法
	public SortedDictionary_ExtArray(Comparator comp)
	{	S = new Vector_ExtArray();	C = comp; }

/**************************** 辅助方法 ****************************/
//二分查找
//返回值可能是命中元素的秩,也可能是key可以插入的秩
//具体如何,需要进一步检查
//不变性:若将key按照返回的秩插入有序向量,向量依然有序
	private static int binSearch(Vector s, Comparator c, Object key, int lo, int hi) {
		if (lo > hi) return lo;//递归基,查找失败
		
		int mi = (lo + hi)>>1;//取中值
		Entry e = (Entry)s.getAtRank(mi);//居中的条目
		int flag = c.compare(key, e.getKey());//比较关键码
		if (flag < 0)				return binSearch(s, c, key, lo, mi-1);//转向左半区间
		else if (flag > 0)	return binSearch(s, c, key, mi+1, hi);//转向右半区间
		else								return mi;//命中
	}

/**************************** 无序词典ADT方法 ****************************/
//查询词典结构当前的规模
	public int getSize()
	{	return S.getSize(); }

//判断词典结构是否为空
	public boolean isEmpty()
	{ return S.isEmpty(); }

//若词典中存在以key为关键码的条目,则返回其中的一个条目;否则,返回null
	public Entry find(Object key) {
		int k = binSearch(S, C, key, 0, S.getSize()-1);//查找关键码为key的条目
		if (0 > k || k >= S.getSize() || (0 != C.compare(key, ((Entry)S.getAtRank(k)).getKey())))
			return null;//若这样的条目不存在,则返回失败标志
		return (Entry) S.getAtRank(k);
	}

//返回由关键码为key的条目组成的迭代器
	public Iterator findAll(Object key) {
		List L = new List_DLNode();//创建一个链表L

		int k = binSearch(S, C, key, 0, S.getSize()-1);//查找关键码为key的条目
		if (0 > k || k >= S.getSize() || (0 != C.compare(key, ((Entry)S.getAtRank(k)).getKey())))
			return new IteratorElement(L);//若这样的条目不存在,则返回空迭代器

		L.insertFirst(S.getAtRank(k));//将e插入L中
		
		int lo = k;//从S[k-1]开始
		while (0 <= --lo) {//不断向前搜索
			if (0 != C.compare(key, ((Entry)S.getAtRank(lo)).getKey()))	break;//直到第一个不命中的条目
			L.insertFirst(S.getAtRank(lo));//将命中的条目插入L中
		}
		
		int hi = k;//从S[k+1]开始
		while (++hi < S.getSize()) {//不断向后搜索
			if (0 != C.compare(key, ((Entry)S.getAtRank(hi)).getKey()))	break;//直到第一个不命中的条目
			L.insertLast(S.getAtRank(hi));//将命中的条目插入L中
		}

		return new IteratorElement(L);//由L创建迭代器,返回之
	}

//插入条目(key, value),并返回该条目
	public Entry insert(Object key, Object value) {
		Entry e = new EntryDefault(key, value);//创建新条目

	//若词典为空,则直接插入新元素
		if (S.isEmpty())	return (Entry) S.insertAtRank(0, e);

	//通过二分查找,确定可插入位置
	//请读者自己检查:即便key在S中为最小或最大,都可以正常插入
		return (Entry) S.insertAtRank(binSearch(S, C, key, 0, S.getSize()-1), e);
	}

//若词典中存在以key为关键码的条目,则将摘除其中的一个并返回;否则,返回null
	public Entry remove(Object key) {
		int k = binSearch(S, C, key, 0, S.getSize()-1);//查找关键码为key的条目
		if (0 > k || k >= S.getSize() || (0 != C.compare(key, ((Entry)S.getAtRank(k)).getKey())))
			return null;//若这样的条目不存在,则返回失败标志
		return (Entry) S.removeAtRank(k);
	}

//返回词典中所有条目的一个迭代器
	public Iterator entries() {
		List L = new List_DLNode();
		for (int i=0; i<S.getSize(); i++)
			L.insertLast(S.getAtRank(i));
		return new IteratorElement(L);//直接利用List接口的方法生成元素迭代器
	}

/**************************** 有序词典ADT方法 ****************************/
//若词典非空,则返回其中关键码最小的条目;否则,返回null
	public Entry first()
	{	return (S.isEmpty()) ? null : (Entry) S.getAtRank(0); }

//若词典非空,则返回其中关键码最大的条目;否则,返回null
	public Entry last()
	{	return (S.isEmpty()) ? null : (Entry) S.getAtRank(S.getSize()-1); }

//返回由关键码不小于key的条目依非降序组成的迭代器
	public Iterator successors(Object key) {
		List L = new List_DLNode();//创建一个链表L

		int k = binSearch(S, C, key, 0, S.getSize()-1);//查找关键码为key的条目
		if (0 > k || k >= S.getSize() || (0 != C.compare(key, ((Entry)S.getAtRank(k)).getKey())))
			return new IteratorElement(L);//若这样的条目不存在,则返回空迭代器

		while (0 <= --k)//从S[k-1]开始向前搜索,直至符合要求的、秩最小的元素
			if (0 != C.compare(key, ((Entry)S.getAtRank(k)).getKey()))	break;
		while (S.getSize() > ++k)//将后继的所有元素依次
			L.insertLast(S.getAtRank(k));//插入L中

		return new IteratorElement(L);//由L创建迭代器,返回之
	}

//返回由关键码不大于key的条目依非升序组成的迭代器
	public Iterator predecessors(Object key) {
		List L = new List_DLNode();//创建一个链表L

		int k = binSearch(S, C, key, 0, S.getSize()-1);//查找关键码为key的条目
		if (0 > k || k >= S.getSize() || (0 != C.compare(key, ((Entry)S.getAtRank(k)).getKey())))
			return new IteratorElement(L);//若这样的条目不存在,则返回空迭代器

		while (S.getSize() > ++k)//从S[k-1]开始向后搜索,直至符合要求的、秩最大的元素
			if (0 != C.compare(key, ((Entry)S.getAtRank(k)).getKey()))	break;
		while (0 <= --k)//将前驱的所有元素依次
			L.insertLast(S.getAtRank(k));//插入L中

		return new IteratorElement(L);//由L创建迭代器,返回之
	}
}

猜你喜欢

转载自blog.csdn.net/xiamaocheng/article/details/85728055