符号表最主要的目的就是将一个键和一个值联系起来,符号表能够将存储的数据元素是一个键和一个值共同组成的 键值对数据,我们可以根据键来查找对应的值。
符号表中,键具有唯一性。 符号表在实际生活中的使用场景是非常广泛的,见下表:
-- API设计:
-- 代码:
public class SymbolTable<Key,Value> {
// 记录首结点
private Node head;
// 记录符号表中元素的个数
private int N;
// 构造方法
public SymbolTable() {
head = new Node(null,null,null);
N = 0;
}
// 获取符号表元素个数
public int size() {
return N;
}
// 往符号表中添加键值对
public void put(Key key,Value value) {
// 查找符号中是否有相同key已经存在
Node n = head;
while (n.next != null) {
// 拿出结点
n = n.next;
if(n.key.equals(key)) {
// 如果当前结点的key等于要插入key,直接将值覆盖
n.value = value;
}
}
// 如果没有与要插入的key相等,构建新结点,新结点的下一个指向为head.next
Node newNode = new Node(key,value,head.next);
head.next = newNode;
// 个数+1
N++;
}
// 删除符号表中键为key的键值对
public void delete(Key key) {
Node n = head;
// 遍历链表
while (n.next != null) {
// 当前结点的下一个结点为要删除的元素
if(n.next.key.equals(key)) {
n.next = n.next.next;
// 个数-1
N--;
return;
}
n = n.next;
}
}
// 从符号表中获取key对应的值
public Value get(Key key) {
Node n = head;
// 遍历链表找到key对应的值
while (n.next != null) {
n = n.next;
if(n.key.equals(key)) {
return n.value;
}
}
return null;
}
// 结点类
class Node {
// 存储键
private Key key;
// 存储值
private Value value;
// 下一个结点
private Node next;
// 构造方法
public Node(Key key, Value value, Node next) {
this.key = key;
this.value = value;
this.next = next;
}
}
}
-- 测试代码:
public class SymbolTableTest {
public static void main(String[] args) throws Exception {
SymbolTable<Integer, String> st = new SymbolTable<>();
st.put(1, "张三");
st.put(3, "李四");
st.put(5, "王五");
System.out.println(st.size());
st.put(1, "老三");
System.out.println(st.get(1));
System.out.println(st.size());
st.delete(1);
System.out.println(st.size());
}
}
-- 运行效果图:
-- 有序符号表:
刚才实现的符号表,我们可以称之为无序符号表,因为在插入的时候,并没有考虑键值对的顺序,而在实际生活 中,有时候我们需要根据键的大小进行排序,插入数据时要考虑顺序,那么接下来我们就实现一下有序符号表。
-- 代码:
/**
* 有序符号表
*/
public class OrderSymbolTable<Key extends Comparable<Key>,Value> {
// 记录首结点
private Node head;
// 记录符号表中元素的个数
private int N;
// 构造方法
public OrderSymbolTable() {
head = new Node(null,null,null);
N = 0;
}
// 获取符号表中元素的个数
public int size() {
return N;
}
// 往符号表中插入键值对
public void put(Key key,Value value) {
// 当前结点
Node curr = head.next;
// 上一个结点
Node pre = head;
// 如果key大于当前结点key,则一直寻找下去
while (curr != null && key.compareTo(curr.key) > 0) {
pre = curr;
curr = curr.next;
}
// 如果当前结点的key和要插入的key一样,则替换
if(curr != null && curr.key.compareTo(key) == 0) {
curr.value = value;
}
// 如果没有找到相同的key,把新结点插入到curr之前
Node newNode = new Node(key,value,curr);
pre.next = newNode;
}
// 删除符号表中键为key的键值对
public void delete(Key key) {
Node n = head;
// 遍历符号表
while (n.next != null) {
if(n.next.key.equals(key)) {
// 当前结点的下一个结点为要删除的结点
n.next = n.next.next;
// 个数-1
N--;
return;
}
n = n.next;
}
}
// 从符号表中获取key对应的值
public Value get(Key key) {
Node n = head;
// 遍历链表找到key对应的值
while (n.next != null) {
n = n.next;
if(n.key.equals(key)) {
return n.value;
}
}
return null;
}
// 结点类
class Node {
// 存储Key
private Key key;
// 存储Value
private Value value;
// 下一个指向
private Node next;
// 构造方法
public Node(Key key, Value value, Node next) {
this.key = key;
this.value = value;
this.next = next;
}
}
}
@ 以上内容属于个人笔记