其实说是无序数组,其实也是使用队列按照输入的顺序插入,和输出。
数据如下:
S E A R C H E X A M P L E
结果如下:
* S 0
* H 5
* X 7
* R 3
* C 4
* L 11
* A 8
* M 9
* P 10
* E 12
代码如下:
public class ArrayST<Key, Value> {
private static final int INIT_SIZE = 8;
private Value[] vals; // 符号表的值
private Key[] keys; // 符号表的索引键
private int n = 0; // 符号表元素的数量
// 初始化该符号表
public ArrayST() {
keys = (Key[]) new Object[INIT_SIZE];
vals = (Value[]) new Object[INIT_SIZE];
}
// 根据 n 的大小返回符号表的大小
public int size() {
return n;
}
// 判断符号表是否为空,根据 size() 是否为0
public boolean isEmpty() {
return size() == 0;
}
// 根据参数调整符号表的大小,先定义好新数组的长度,然后将原数组的值赋值给对应新数组的位置,最后将新数组的数组名赋值给原数组。
private void resize(int capacity) {
Key[] tempk = (Key[]) new Object[capacity];
Value[] tempv = (Value[]) new Object[capacity];
for (int i = 0; i < n; i++)
tempk[i] = keys[i];
for (int i = 0; i < n; i++)
tempv[i] = vals[i];
keys = tempk;
vals = tempv;
}
// 往符号表里面插入数据
public void put(Key key, Value val) {
// 删除重复的键
delete(key);
// 如果数组空间有限,则扩大两倍数组的长度
if (n >= vals.length) resize(2*n);
// 将数据加入数组
vals[n] = val;
keys[n] = key;
n++;
}
// 循环遍历数组的长度,若找到则返回对应的 val ,否则返回 null
public Value get(Key key) {
for (int i = 0; i < n; i++)
if (keys[i].equals(key)) return vals[i];
return null;
}
// 遍历 keys 数组的
public Iterable<Key> keys() {
Queue<Key> queue = new LinkedList<Key>();
for (int i = 0; i < n; i++)
queue.add(keys[i]);
return queue;
}
// 将 key 和 value 删除
public void delete(Key key) {
for (int i = 0; i < n; i++) {
if (key.equals(keys[i])) {
keys[i] = keys[n-1];
vals[i] = vals[n-1];
keys[n-1] = null;
vals[n-1] = null;
n--;
if (n > 0 && n == keys.length/4) resize(keys.length/2);
return;
}
}
}
public static void main(String[] args) {
ArrayST<String, Integer> st = new ArrayST<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));
}
}
最后在命令行中编译出现 「使用了未经检查或不安全的操作」,只需在类前面加上 @SuppressWarnings("unchecked") 即可。