有序符号表(数组实现,JAVA,算法(四),二分法)
来源:互联网 发布:ubuntu安装到虚拟机 编辑:程序博客网 时间:2024/06/06 00:12
数组实现的有序符号表介绍:
两个平行数组,相同的下标分别是键和值,由于查入和删除需要调整数组大小,所以和无序链表一样,这两个操作仍然是线性的。但是符号表最为频繁的操作应该是查询的,查询操作可以使用二分法实现,达到了logN的复杂度。二分法的实现需要排好序的键,所以有了泛型的存在,需要实现Comparable接口。rank函数用二分法查找键,在很多函数里面我们都会使用这个函数以达到快速查找的能力。由于有序符号表的实现可以基于多种数据结构,但是它们的操作都是符号表常见操作,故在这里抽象出一个SymbolTable类,包装好以后的符号表使用的函数声明原型。
Comparable:为了使任意类型可比较,JAVA包装好的Integer,Double..这些类都实现了这个接口。当前类的函数接受一个Comparable类型的参数,只要实现了这个接口的类都可以作为参数传递,这就是接口回调,类似于上转型对象。
有序符号表基类:
package com.lizi.datastructure.symboltable;//有序符号表基类public abstract class SymbolTable<Key extends Comparable<Key>,Value> { //将键值对存入表中(若值为空则将建key从表中删除) public abstract void put(Key key,Value value); //获取键Key对应的值(若键key不存在返回空) public abstract Value get(Key key); //从表中删去键key(及其对应的值) public abstract Value delete(Key key); //表中是否存在该键 public boolean contains(Key key){ return get(key)!=null; } //表是否为空 public boolean isEmpty(){ return size()==0; } //表中的键值对数量 public abstract int size(); //最小的键 public abstract Key min(); //最大的键 public abstract Key max(); //小于等于Key的最大键 public abstract Key floor(Key key); //大于等于Key的最小键 public abstract Key ceiling(Key key); //小于key的键的数量 public abstract int rank(Key key); //删除最小的键 public void deleteMin(){ delete(min()); } //删除最大的键 public void deleteMax(){ delete(max()); } //返回下标为index的键 public abstract Key select(int index); //[low....high]之间键的数量,包括相等元素 public int size(Key low,Key high){ if (high.compareTo(low)<0) return 0; else if (contains(high)) return rank(high)-rank(low)+1; else return rank(high)-rank(low); } //[low....high]之间键的集合,已经排序 public abstract Iterable<Key> keys(Key low,Key high); //表中所有键的集合,已经排序 public Iterable<Key> keys(){ return keys(min(),max()); }}
以下是数组实现的符号表:
package com.lizi.datastructure.symboltable;import java.util.ArrayList;import java.util.List;//二分搜索,基于排序数组public class BinarySearchST<Key extends Comparable<Key>,Value> extends SymbolTable<Key, Value> { private Key[] keys; private Value[] values; private int size=0; @SuppressWarnings("unchecked") public BinarySearchST(int capacity) { keys=(Key[]) new Comparable[capacity]; values=(Value[]) new Object[capacity];//java不允许泛型数组,只能创建Object再强制转换类型 this.size=0; } @Override public void put(Key key, Value value) { if(value==null) {delete(key); return;} //如果键存在,则修改键值 int pos=rank(key); if (pos<size&&keys[pos].compareTo(key)==0) { values[pos]=value; return; } //键值不存在,判断数组是否越界并将数组扩容 if(size==keys.length) resize(2*keys.length); for (int i =size; i>pos; i--) { keys[i]=keys[i-1]; values[i]=values[i-1]; } keys[pos]=key; values[pos]=value; size++; } @Override public Value get(Key key) { if(isEmpty()) return null; int pos=rank(key); if (pos<size&&keys[pos].compareTo(key)==0) return values[pos]; else return null; } @Override public Value delete(Key key) { int pos=rank(key); //没找到则返回空 if (pos<size&&keys[pos].compareTo(key)!=0) { return null; } Value value = values[pos]; if(size<keys.length/2) resize(keys.length/2); for (int i = pos; i < size - 1; i++) { keys[i] = keys[i + 1]; values[i] = values[i + 1]; } size--; return value; } @Override public int size() { return size; } @Override public Key min() { return keys[0]; } @Override public Key max() { return keys[size-1]; } @Override public Key floor(Key key) { int pos=rank(key); if (pos<size&&keys[pos].compareTo(key)==0) { return keys[pos]; } return keys[pos-1]; } @Override public Key ceiling(Key key) { int pos=rank(key); return keys[pos]; } //非递归的二分查找 @Override public int rank(Key key) { int low=0; int high=size-1; while (low<=high) { int middle=low+(high-low)/2; int cmp=key.compareTo(keys[middle]); if (cmp<0) high=middle-1; else if(cmp>0) low=middle+1; else return middle; } return low; } //递归的二分查找 public int rank(Key key,int low,int high) { if(low>high) return low; int pos=rank(key); int cmp=key.compareTo(keys[pos]); if (cmp>0) return rank(key, pos+1, high); else if(cmp<0) return rank(key,low,pos-1); else return pos; } @Override public Key select(int index) { return keys[index]; } @Override public Iterable<Key> keys(Key low, Key high) { List<Key> keys=new ArrayList<Key>(size); for (int i = 0; i <size; i++) { keys.add(this.keys[i]); } return keys; } //该函数仅仅将容量扩大,但是有效元素数量并未改变,所以大小还是size @SuppressWarnings("unchecked") public void resize(int capacity) { Key[] newKeys=(Key[]) new Comparable[capacity]; Value[] newValues=(Value[]) new Object[capacity]; for (int i = 0; i < size; i++) { newKeys[i]=keys[i]; newValues[i]=values[i]; } keys=newKeys; values=newValues; }}
阅读全文
0 0
- 有序符号表(数组实现,JAVA,算法(四),二分法)
- 有序符号表(二叉树实现,JAVA,算法(四))
- 有序数组实现符号表
- 无序符号表(链表实现,JAVA,算法(四))
- java数组实现二分法查找算法
- 【数据结构与算法】有序数组二分法查找
- 数据结构实现之有序符号表BinarySearchST(使用有序数组的二分查找)
- java二分法实现在有序的数组中定位某数在数组中的位置
- (二)有序数组的二分法查找
- 二分法查找有序数组
- 有序数组搜索二分法
- 有序数组和二分法
- 二分法查找有序数组
- 二分法查找有序数组
- 有序数组和二分法
- java实现有序数组
- Java算法:二分法算法实现
- 算法学习记录七(C++)--->二分法找有序旋转数组最小值
- 破解webstorm方法
- 批处理实现简单“批量文件合并”
- 数据库事务隔离级别
- mysql(二) 数据类型
- 5.8哈夫曼树及其应用
- 有序符号表(数组实现,JAVA,算法(四),二分法)
- [LeetCode]206. Reverse Linked List
- 花花的聚会【NOIP2017提高A组模拟8.10】
- 微信公众号开发
- C语言数组
- 解决tomcat运行闪退问题
- 指针与数组
- noip2002普及组-产生数
- <job_demo><Qt>仪表上微机界面