一、符号表
符号表最主要的目的就是将一个键和一个值联系起来,符号表能够将存储的数据元素是一个键和一个值共同组成的键值对数据,我们可以根据键来查找对应的值。
符号表中,键具有唯一性。
1.1 符号表API设计
结点类:
下面展示一些 结点类
。
package SymbolTable;
/**
* @author Fantic
* @create 2021-08-14 22:14
*/
public class Node<Key,Value> {
//存储键
public Key key;
//存储值
public Value value;
//存储下一个结点
public Node next;
public Node(Key key, Value value, Node next) {
this.key = key;
this.value = value;
this.next = next;
}
}
符号表:
1.2 符号表实现
下面展示一些 符号表功能实现
。
package SymbolTable;
/**
* @author Fantic
* @create 2021-08-14 22:15
*/
public class SymbleTable<Key,Value> {
public static void main(String[] args) {
//创建符号表对象
SymbleTable<Integer, String> symbleTable = new SymbleTable<>();
//测试put方法
symbleTable.put(1,"乔峰");
symbleTable.put(2,"虚竹");
symbleTable.put(3,"段誉");
symbleTable.put(4,"慕容");
symbleTable.put(5,"王语嫣");
System.out.println("插入完毕后,查看符号表的长度:" + symbleTable.size());
symbleTable.put(2,"鸠摩智");
System.out.println("替换完毕后,查看符号表的长度:" + symbleTable.size());
//测试get方法
String s = symbleTable.get(2);
System.out.println("获取的元素是:" + s);
//测试删除方法
symbleTable.delete(3,"段誉");
symbleTable.delete(4,"段誉");
System.out.println("删除完毕后,查看符号表的长度:" + symbleTable.size());
}
//记录首节点
private Node head;
//记录符号表中键值对的个数
private int Num;
//构造空参构造器,将成员变量进行初始化
public SymbleTable() {
this.head = new Node(null,null,null);
Num = 0;
}
//获取符号表的大小
public int size(){
return Num;
}
//根据键Key,找对应的值
public Value get(Key key){
Node n = head;
while (n.next != null) {
//变换n
n = n.next;
if (n.key.equals(key)){
return (Value) n.value;
}
}
return null;
}
//向符号表中插入一个键值对(即是在符号表头部增加一位)
public void put(Key key,Value value){
Node n = head;
while (n.next != null){
n = n.next;
//判断当前所要插入的键值对的键与原有键相同而对应值相同
if (n.key.equals(key)){
n.value = value;
return;
}
}
//如果符号表中不存在键为key的键值对,只需要创建新的结点,保存要插入的键值对,把新节点插入到链表的头部即可
Node newNode = new Node(key,value,null);
Node oldFirst = head.next;
newNode.next = oldFirst;
head.next = newNode;
//元素个数加1
Num++;
}
//删除键为Key的键值对
public void delete(Key key,Value value) {
//找到键为key的结点,把该结点从链表中删除
Node n = head;
while(n.next != null){
n = n.next;
if (n.key.equals(key)){
n.next = n.next.next;
Num--;
return;
}
}
}
}
1.3 有序符号表
刚才实现的符号表,我们可以称之为无序符号表,因为在插入的时候,并没有考虑键值对的顺序,而在实际生活中,有时候我们需要根据键的大小进行排序,**插入数据时要考虑顺序,**那么接下来我们就实现一下有序符号表。
下面展示一些 有序符号表的实现
。
package SymbolTable;
/**
* @author Fantic
* @create 2021-08-15 19:11
*/
public class OrderSymbolTable<Key extends Comparable<Key>, Value> {
public static void main(String[] args) {
//创建有序符号表对象
//使用DeBug功能运行
OrderSymbolTable<Integer, String> table = new OrderSymbolTable<>();
table.put(1,"张三");
table.put(2,"李四");
table.put(3,"耳语");
table.put(4,"刘宝");
table.put(3,"王宇");
System.out.println(table.size());
}
//记录首节点
private Node head;
//记录符号表中键值对的个数
private int Num;
//构造空参构造器,将成员变量进行初始化
public OrderSymbolTable() {
this.head = new Node(null,null,null);
Num = 0;
}
//获取符号表的大小
public int size(){
return Num;
}
//根据键Key,找对应的值
public Value get(Key key){
Node n = head;
while (n.next != null) {
//变换n
n = n.next;
if (n.key.equals(key)){
return (Value) n.value;
}
}
return null;
}
//向符号表中插入一个键值对(在符号表中任意位置添加)
public void put(Key key,Value value){
//定义两个Node变量,分别记录当前结点和当前结点的上一个结点
Node cur = head.next;
Node pre = head;
//如果与当前结点的键cur不同
while (cur != null && key.compareTo((Key) cur.key) > 0) {
//由于新加的键比现有的键值大,则现有结点向后移一位
pre = cur;
cur = cur.next;
}
Node<Key, Value> newNode = new Node<>(key, value, null);
pre.next = newNode;
//如果当前结点cur的键和要插入的key一样,则替换
if (cur != null && key.compareTo((Key) cur.key) == 0) {
cur.value = value;
return;
}
//元素个数加1
Num++;
}
//删除键为Key的键值对
public void delete(Key key, Value value) {
//找到键为key的结点,把该结点从链表中删除
Node n = head;
while(n.next != null){
n = n.next;
if (n.key.equals(key)){
n.next = n.next.next;
Num--;
return;
}
}
}
}