資料結構:符號表
阿新 • • 發佈:2020-12-29
1 符號表簡介
- 符號表最主要的目的是將一個鍵和一個值聯絡起來,其儲存的資料元素是由一個鍵和一個值共同組成的鍵值對資料;
- 我們可以根據鍵來查詢對應的值;
- 符號表中的鍵具有唯一性;
符號表的使用場景
應用 | 查詢目的 | 鍵 | 值 |
---|---|---|---|
字典 | 找出單詞的釋義 | 單詞 | 釋義 |
圖書索引 | 找出某個術語相關的頁碼 | 術語 | 一串頁碼 |
網路搜尋 | 找出某個關鍵字對應的網頁 | 關鍵字 | 網頁名稱 |
2 符號表API設計
結點類
類名 | Node<Key, Value> |
---|---|
構造方法 | Node(Key key, Value value, Node next):建立Node物件 |
成員變數 | 1.public Key key:儲存鍵 3.public Node next:儲存下一個結點 |
符號表
類名 | SymbolTable<Key, Value> |
---|---|
構造方法 | SymbolTable():建立SymbolTable物件 |
成員方法 | 1.public Value get(Key key):根據鍵key,找對應的值 2.public void put(Key key,Value val):向符號表中插入一個鍵值對 3.public void delete(Key key):刪除鍵為key的鍵值對 4.public int size():獲取符號表的大小 |
成員變數 | 1.private Node head:記錄首結點 |
3 符號表程式碼實現
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() {
this.head = new Node(null,null,null);
this.N=0;
}
//獲取符號表中鍵值對的個數
public int size(){
return N;
}
//往符號表中插入鍵值對
public void put(Key key,Value value){
//符號表中已經存在了鍵為key的鍵值對,那麼只需要找到該結點,替換值為value即可
Node n = head;
while(n.next!=null){
//變換n
n = n.next;
//判斷n結點儲存的鍵是否為key,如果是,則替換n結點的值
if (n.key.equals(key)){
n.value = value;
return;
}
}
//如果符號表中不存在鍵為key的鍵值對,只需要建立新的結點,儲存要插入的鍵值對,把新結點插入到連結串列的頭部:head.next=新結點即可
Node newNode = new Node(key, value, null);
Node oldFirst = head.next;
newNode.next = oldFirst;
head.next = newNode;
//元素個數+1
N++;
}
//刪除符號表中鍵為key的鍵值對
public void delete(Key key){
//找到鍵為key的結點,把該結點從連結串列中刪除
Node n = head;
while(n.next!=null){
//判斷n結點的下一個結點的鍵是否為key,如果是,就刪除該結點
if (n.next.key.equals(key)){
n.next = n.next.next;
N--;
return;
}
n = n.next;
}
}
//從符號表中獲取key對應的值
public Value get(Key key){
//找到鍵為key的結點
Node n = head;
while(n.next!=null){
//變換n
n = n.next;
if (n.key.equals(key)){
return n.value;
}
}
return null;
}
}
public class Test {
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());
}
}
3
老三
3
2
4 有序符號表
- 前面實現的符號表,我們稱之為無序符號表,因為在插入的時候,並沒有考慮鍵值對的順序;
- 然而在實際生活中,有時候我們需要根據鍵的大小進行排序,插入資料時要考慮順序,即有序符號表;
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() {
this.head = new Node(null,null,null);
this.N=0;
}
//獲取符號表中鍵值對的個數
public int size(){
return N;
}
//往符號表中插入鍵值對
public void put(Key key,Value value){
//定義兩個Node變數,分別記錄當前結點和當前結點的上一個結點
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不一樣,說明要插入的key小於curr的key,把新的結點插入到curr之前,且元素個數+1
pre.next = new Node(key, value, curr);
N++;
}
//刪除符號表中鍵為key的鍵值對
public void delete(Key key){
//找到鍵為key的結點,把該結點從連結串列中刪除
Node n = head;
while(n.next!=null){
//判斷n結點的下一個結點的鍵是否為key,如果是,就刪除該結點
if (n.next.key.equals(key)){
n.next = n.next.next;
N--;
return;
}
n = n.next;
}
}
//從符號表中獲取key對應的值
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;
}
}