java符号表_[Java]-符号表,二分查找

package cn.ywrby.Searches;

//二分查找,基于有序数组

import edu.princeton.cs.algs4.Queue;

import edu.princeton.cs.algs4.StdIn;

import edu.princeton.cs.algs4.StdOut;

import java.util.NoSuchElementException;

public class BinarySearchST,Value> {

private static final int INIT_CAPACITY=2; //定义数组的初始大小

private Key[] keys; //键数组

private Value[] vals; //值数组

private int n=0 ; //数组大小

//无参构造函数

public BinarySearchST(){

this(INIT_CAPACITY); //利用固定初始大小调用含餐构造函数

}

//含参构造函数

public BinarySearchST(int capacity){

keys=(Key[]) new Comparable[capacity];

vals=(Value[])new Object[capacity];

}

//动态调整数组大小

private void resize(int capacity){

assert capacity>=n:"不可以动态将数组调大"; //判断传入容量大小,不可以将容量调大。只通过put增加数组大小

//assert [boolean 表达式] : [错误表达式 (日志)] 返回一个报错

Key[] tempKey=(Key[]) new Comparable[capacity];

Value[] tempValue=(Value[]) new Object[capacity];

for(int i=0;i

tempKey[i]=keys[i];

tempValue[i]=vals[i];

}

vals=tempValue;

keys=tempKey;

}

public int size(){return n;}

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

//判断键是否存在

public boolean contains(Key key) {

//如果键为null即报错,警告键不可能为null

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

return get(key) != null;

}

public Value get(Key key){

if (key == null) throw new IllegalArgumentException("argument to get() is null"); //防止搜索null键

if(isEmpty()) return null; //防止搜索空数组

int i=rank(key); //获取对应键的索引值

if(i

return null; //未找到

}

/*

*查找目标键的值

* 如果存在,返回的对应键的索引值

*如果不存在,返回表中小于它的键的数量(即新键的位置)

* */

public int rank(Key key){

if(key==null) throw new IllegalArgumentException("argument to rank() is null"); //避免索引null值

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; //while循环结束条件是lo>hi此时lo的值即为小于key的键的数量

}

//插入元素

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

vals[i]=val;

return;

}

//如果键不存在

//判断是否需要动态调整数组大小

if(n==keys.length){

resize(keys.length*2);

}

//将值按键序放入

for(int j=n;j>i;j--){

keys[j]=keys[j-1];

vals[j]=vals[j-1];

}

keys[i]=key;

vals[i]=val;

n++;

assert check();

}

//删除对应键的元素

public void delete(Key key){

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

if (isEmpty()) return;

int i=rank(key);

//不存在对应键

if(i==n || keys[i].compareTo(key)!=0 ) return;

//存在对应键

for(int j=i;j

keys[j]=keys[j+1];

vals[j]=vals[j+1];

}

n--;

keys[n]=null;

vals[n]=null;

//删减后动态调整数组大小

if (n > 0 && n == keys.length/4) resize(keys.length/2);

assert check();

}

//删除最小元素

public void deleteMin() {

if (isEmpty()) throw new NoSuchElementException("Symbol table underflow error");

delete(min());

}

//删除最大元素

public void deleteMax() {

if (isEmpty()) throw new NoSuchElementException("Symbol table underflow error");

delete(max());

}

//返回数组最小值

public Key min() {

if (isEmpty()) throw new NoSuchElementException("called min() with empty symbol table");

return keys[0];

}

//返回数组最大值

public Key max() {

if (isEmpty()) throw new NoSuchElementException("called max() with empty symbol table");

return keys[n-1];

}

//返回数组第k个键

public Key select(int k) {

if (k < 0 || k >= size()) {

throw new IllegalArgumentException("called select() with invalid argument: " + k);

}

return keys[k];

}

//向下取整,找出小于等于该键的最大键

public Key floor(Key key) {

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

int i = rank(key);

if (i < n && key.compareTo(keys[i]) == 0) return keys[i];

if (i == 0) return null;

else return keys[i-1];

}

//向上取整,找出大于等于该键的最小键

public Key ceiling(Key key) {

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

int i = rank(key);

if (i == n) return null;

else return keys[i];

}

//返回表中所有键的集合(已排序)

public Iterable keys() {

return keys(min(), max());

}

//返回表中从lo至hi的所有键的集合

public Iterable 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 queue = new Queue();

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;

}

//检查数组是否符合规定条件

private boolean check() {

return isSorted() && rankCheck();

}

//检查是否已经排序

private boolean isSorted() {

for (int i = 1; i < size(); i++)

if (keys[i].compareTo(keys[i-1]) < 0) return false;

return true;

}

//检查是否出现重复的键

private boolean rankCheck() {

for (int i = 0; i < size(); i++)

if (i != rank(select(i))) return false;

for (int i = 0; i < size(); i++)

if (keys[i].compareTo(select(rank(keys[i]))) != 0) return false;

return true;

}

public static void main(String[] args) {

BinarySearchST st = new BinarySearchST();

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

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值