1. 程式人生 > >《 常見演算法與資料結構》符號表ST(1)——基本介紹

《 常見演算法與資料結構》符號表ST(1)——基本介紹

符號表(Symbol Table)

本系列文章主要介紹常用的演算法和資料結構的知識,記錄的是《Algorithms I/II》課程的內容,採用的是“演算法(第4版)”這本紅寶書作為學習教材的,語言是java。這本書的名氣我不用多說吧?豆瓣評分9.4,我自己也認為是極好的學習演算法的書籍。

通過這系列文章,可以加深對資料結構和基本演算法的理解(個人認為比學校講的清晰多了),並加深對java的理解。

1 符號表介紹和API

1.1 符號表介紹

符號表(Symbol Table)是一個非常常見的資料結構,在現實生活中應用很多。它是一個“鍵”—“值”對應的結構。在符號表中,儲存的是鍵值對。通過輸入鍵,查詢對應的值。

這個基礎的資料結構,在現實生活中使用的特別多,比如字典。

這裡寫圖片描述

1.2 符號表API

其實符號表的操作,也無非就是增刪改查之類的

函式名 功能
ST() 建立一個符號表物件
void Put(Key key, Value val) 往集合中插入一條鍵值對記錄,如果value為空,不新增
Value Get(Key key) 根據key查詢value,如果沒找到返回null
void Delete(Key key) 刪除鍵為key的記錄
boolean Contains(Key key) 判斷集合中是否存在鍵為key的記錄
boolean IsEmpty() 判斷查詢表是否為空
int Size() 返回集合中鍵值對的個數
Iterable Keys() 返回集合中所有的鍵

Ps.有一些約定要提前說一下
- 值不為null
- 如果key不存在,get()返回為null
- put()會覆蓋舊值

通過這幾個約定,我們可以把contain和delete函式簡單實現。

public boolean contains(Key key)
{  return get(key) != null;  }

public void delete(Key key)
{  put(key, null
); }

2 鍵和值的約定

2.1 值(value)

在java中如果我們想要實現一個符號表,我們希望它是支援所有泛型的。

2.2 鍵(Key)

對於鍵的,我們希望:

  • Key是可比較的,即是Comparable的,並且使用compareTo()函式
  • Key是泛型的
  • 能用equals()判斷相等,能用hashCode()獲取鍵(這兩個函式都是java的內建函式)
  • 對於Key最好是使用不可變的型別(Integer,Double, String之類的)

3 相等性測試

如果我們提到了equals() 函式,就不得不提提java的相等性測試,Java要求equals()滿足:

  • 自反性: x.equals(x) is true
  • 對稱性: x.equals(y) iff y.equals(x)
  • 傳遞性: if x.equals(y) and y.equals(z), then x.equals(z)
  • 不為null: x.equals(null) is false

一般來說,我們做判斷使用的( x == y ) 這個式子並不做型別檢查。所以,我們在實現equals()的時候,要特別注意,它看起來很簡單,但是想實現完美比較麻煩。

比如一個日期的class,你可能會這樣實現equals()

public class Date implements Comparable<Date>
{
   private final int month;
   private final int day;
   private final int year;
   ...
   public boolean equals(Date that)
   {
      if (this.day   != that.day  ) return false;
      if (this.month != that.month) return false;
      if (this.year  != that.year ) return false;
      return true;
   }
}

但是你如果這樣實現會更好:

  • final欄位,不然可能會違反對稱性(繼承)
  • 最好用Object,(不過這個專家們目前還在激烈爭論中)
  • 加入自反性,不為null的判斷,並且驗證型別一致性。
  • 關於比較一個類中的不同變數:
    • 如果比較的是一個原始型別,用==
    • 如果比較的是一個物件,用equals()
    • 如果比較的是一個數組,對Arrays.equals(a, b),而不是a.equals(b)
public final class Date implements Comparable<Date>
{
   private final int month;
   private final int day;
   private final int year;
   ...
   public boolean equals(Object y)
   {
      if (y == this) return true;
      if (y == null) return false;
      if (y.getClass() != this.getClass())
         return false;
      Date that = (Date) y;
      if (this.day   != that.day  ) return false;
      if (this.month != that.month) return false;
      if (this.year  != that.year ) return false;
      return true;
   }
}