符号表(Symbol Table)
简介符号表(Symbol Table)是一个非常常见的数据结构,在现实生活中应用很多。它是一个“键”—“值”对应的结构。在符号表中,存储的是键值对。通过输入键,查询对应的值。
4.6.1、符号表的定义
符号表(Symbol Table)是一个非常常见的数据结构,在现实生活中应用很多。它是一个“键”—“值”对应的结构。在符号表中,存储的是键值对。通过输入键,查询对应的值。
这个基础的数据结构,在现实生活中使用的特别多,比如字典。
4.6.2、符号表的API设计
结点类:
| 类名 | Node |
|---|---|
| 构造方法 | Node(Key key,Value value,Node next):创建Node对象 |
| 成员变量 | public Key key:存储键 public Value value:存储值 public Node next:存储下一个结点 |
符号表:
| 类名 | SymbolTable |
|---|---|
| 构造方法 | SymbolTable():创建SymbolTable对象 |
| 成员变量 | private Node head:记录首结点 private int N:记录符号表中键值对的个数 |
| 成员方法 | public Value get(Key key):根据Key找到对应的值 public void put(Key key,Value value):向符号表插入一个键值对 public void delete(Key key):删除键为key的值 public int size():获取符号表大小 |
4.6.3、符号表的设计
实现类:
package cn.test.algorithm.datastruct;
public class SymbolTable<Key, Value> {
private Node head;
private int N;
private class Node {
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;
}
}
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)) {
n.value = value;
return;
}
}
//如果不存在,就需要创建新的结点
Node oldFirst = head.next;//获取第一个结点
Node newNode = new Node(key, value, oldFirst);
head.next = newNode;
N++;
}
public Value delete(Key key) {
//首先需要找到key的结点,然后将结点删除掉
Node n = head;
while (n.next != null) {
n = n.next;
if (n.key.equals(key)) {
N--;
n.next = n.next.next;
return n.value;
}
}
return null;
}
public Value get(Key key) {
//首先需要找到key的结点,然后将结点删除掉
Node n = head;
while (n.next != null) {
n = n.next;
if (n.key.equals(key)) {
return n.value;
}
}
return null;
}
}
测试类
package cn.test.algorithm.test;
import cn.test.algorithm.datastruct.SymbolTable;
public class SymbolTableTest {
public static void main(String[] args) {
SymbolTable<String, String> tables = new SymbolTable<>();
tables.put("zhangsan", "张三");
tables.put("lisi", "李四");
tables.put("wangwu", "王五");
System.out.println("----------------------------------------");
System.out.println("符号表元素个数:" + tables.size());
System.out.println(tables.get("zhangsan"));
System.out.println(tables.get("wangwu"));
System.out.println("----------------------------------------");
System.out.println(tables.delete("lisi"));
System.out.println("符号表元素个数:" + tables.size());
System.out.println("----------------------------------------");
tables.put("wangwu", "新王五");
System.out.println(tables.get("wangwu"));
}
}
测试结果:
----------------------------------------
符号表元素个数:3
张三
王五
----------------------------------------
李四
符号表元素个数:2
----------------------------------------
新王五
4.6.4、有序符号表的设计
上面我们实现的符号表是没有顺序的,那么如果要实现有序的符号表应该如何做呢?
- key必须要能进行比较,所以需要继承Comparable
- 插入的时候需要进行比较
实现类:
package cn.test.algorithm.datastruct;
public class OrderSymbolTable<Key extends Comparable<Key>, Value> {
private Node head;
private int N;
private class Node {
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;
}
}
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;
while (curr != null && key.compareTo(curr.key) > 0) {
//编号当前结点
pre = curr;
curr = curr.next;
}
//如果当前结点curr与要插入的key一样
if (curr != null && key.compareTo(curr.key) == 0) {
curr.value = value;
return;
}
//如果当前结点curr与要插入key不一样,把当前结点插入到curr之前
Node newNode = new Node(key, value, curr);
pre.next = newNode;
N++;
}
public Value delete(Key key) {
//首先需要找到key的结点,然后将结点删除掉
Node n = head;
while (n.next != null) {
n = n.next;
if (n.key.equals(key)) {
N--;
n.next = n.next.next;
return n.value;
}
}
return null;
}
public Value get(Key key) {
//首先需要找到key的结点,然后将结点删除掉
Node n = head;
while (n.next != null) {
n = n.next;
if (n.key.equals(key)) {
return n.value;
}
}
return null;
}
}
测试类:
package cn.test.algorithm.test;
import cn.test.algorithm.datastruct.OrderSymbolTable;
public class OrderSymbolTableTest {
public static void main(String[] args) {
OrderSymbolTable<Integer, String> tables = new OrderSymbolTable<>();
tables.put(1, "张三");
tables.put(2, "李四");
tables.put(5, "王五");
tables.put(3, "赵六");
tables.put(4, "王琦");
}
}
通过断点查看结果。
前一篇博客中已经说过Golang对Gzip的处理,其实这是我的服务器端的处理,那么当我们服务器返回Gzip压缩的字符串后,客户端如何进行解压呢?本文主要记录下JavaScript对Gzip进行压缩和解压处理。
网页扫描二维码库:Html5-Qrcode,官网地址:https://scanapp.org/html5-qrcode-docs/
《是妈妈是女儿》聚焦母女间未曾言明的爱意,以书信对话的形式呈现出各自的内心独白,表达彼此的牵挂。黄绮珊与希林娜依·高用跨越时空、打开心扉、深情对唱的形式,将天下母女爱的寄语化作心灵的倾诉。黄绮珊的每一句话,每一个字都演绎出了妈妈对女儿的爱,而希林依娜·高把女儿对妈妈的爱由不理解到理解再到感恩演绎得淋漓尽致。
默认情况下 pip 使用的是国外的镜像,在下载的时候速度非常慢,本文我们介绍使用国内源对pip进行加速。
快速生成表格
Electron页面跳转、浏览器打开链接和打开新窗口
Docker编译镜像出现:fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/APKINDEX.tar.gz
ERROR: http://dl-cdn.alpinelinux.org/alpine/v3.12/main: temporary error (try again later)
WARNING: Ignoring APKINDEX.2c4ac24e.tar.gz: No such file or directory问题
在Mac电脑中,如何对Git的用户名和密码进行修改呢?起初不懂Mac,所以整了很久,本文将记录如何对这个进行操作,以便后期使用。
在使用Git的过程中,不想每次都输入用户名和密码去拉取代码,所以就需要保存这些信息,那么既然有保存了,就必须有清除功能。