2023年 8月21日 符號表及其基本實現

2022-09-12 15:24:24 字數 3524 閱讀 7391

在開始介紹查詢演算法之前,我們需要定義乙個名為符號表(symbol table)的抽象資料結構,該資料結構類似我們再c#中使用的dictionary,他是對具有鍵值對元素的一種抽象,每乙個元素都有乙個key和value,我們可以往裡面新增key,value鍵值對,也可以根據key來查詢value。在現實的生活中,我們經常會遇到各種需要根據key來查詢value的情況,比如dns根據網域名稱查詢ip位址,圖書館根據索引號查詢圖書等等:

為了實現這一功能,我們定義乙個抽象資料結構,然後選用合適的資料結構來實現:

public class st

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()

返回集合中鍵值對的個數

iterablekeys()

返回集合中所有的鍵

查詢表的實現關鍵在於資料結構的選擇,最簡單的一種實現是使用無序鍊錶來實現,每乙個節點記錄key值,value值以及指向下乙個記錄的物件。

如圖,當我們往煉表中插入元素的時候,從表頭開始查詢,如果找到,則更新value,否則,在表頭插入新的節點元素。

實現起來也很簡單:

public class sequentsearchsymboltable: symboltableswhere tkey : icomparable, iequatable

public tvalue value

public node next

public node(tkey key, tvalue value, node next)

}public override tvalue get(tkey key)

temp = temp.next;

}return result;

}public override void put(tkey key, tvalue value)

temp = temp.next;

}first = new node(key, value, first);

length++;

}....

}

分析:從圖或者**中分析可知,插入的時候先要查詢,如果存在則更新value,查詢的時候需要從煉表頭進行查詢,所以插入和查詢的平均時間複雜度均為o(n)。那麼有沒有效率更好的方法呢,下面就介紹二分查詢。

和採用無序鍊錶實現不同,二分查詢的思想是在內部維護乙個按照key排好序的二維陣列,每一次查詢的時候,跟中間元素進行比較,如果該元素小,則繼續左半部分遞迴查詢,否則繼續右半部分遞迴查詢。整個實現**如下:

class binarysearchsymboltable: symboltableswhere tkey : icomparable, iequatable

public binarysearchsymboltable() : this(init_capacity)

/// /// 根據key查詢value。

/// 首先查詢key在keys中所處的位置,如果在length範圍內,且存在該位置的值等於key,則返回值

/// 否則,不存在

///

///

///

public override tvalue get(tkey key)

/// /// 向符號表中插入key,value鍵值對。

/// 如果存在相等的key,則直接更新value,否則將該key,value插入到合適的位置

/// 1.首先將該位置往後的元素都往後移以為

/// 2.然後再講該元素放到為i的位置上

///

///

///

public override void put(tkey key, tvalue value)

//如果長度相等,則擴容

if (length == keys.length) resize(2 * keys.length);

for (int j = length; j > i; j--)

keys[i] = key;

values[i] = value;

length++;

}/// /// 返回key在陣列中的位置

///

///

///

private int rank(tkey key)

return lo;

}。。。

}

這裡面重點是rank方法,我們可以看到首先獲取mid位置,然後將當前元素和mid位置元素比較,然後更新lo或者hi的位置用mid來替換,如果找到相等的,則直接返回mid,否則返回該元素在集合中應該插入的合適位置。上面是使用迭代的方式來實現的,也可以改寫為遞迴:

private int rank(tkey key, int lo, int hi)

二分查詢的示意圖如下:

分析:

使用有序的二維陣列來實現查詢表可以看出,採用二分查詢只需要最多lgn+1次的比較即可找到對應元素,所以查詢效率比較高。

但是對於插入元素來說,每一次插入不存在的元素,需要將該元素放到指定的位置,然後,將他後面的元素依次後移,所以平均時間複雜度o(n),對於插入來說效率仍然比較低。

可以看到,使用有序陣列的二分查詢法提高了符號表的查詢速度,但是插入效率仍舊沒有得到提高,而且在要維護陣列有序,還需要進行排序操作。這兩種實現方式簡單直觀,但是無法同時達到較高查詢和插入效率。那麼有沒有一種資料結構既能夠在查詢的時候有較高的效率,在插入的時候也有較好的效率呢,本文只是乙個引子,後面的系列文章將會介紹二叉查詢樹,平衡查詢樹以及雜湊表。

希望本文對您了解查詢表的基本概念以及兩種基本實現有所幫助

原文出處: 寒江獨釣   歡迎分享原創到伯樂頭條

2023年8月4日總結

今天的題目真是 啊,王隊出題果然不一樣。不說了,上題 1 rhl的揹包 bag.pas c cpp 問題描述 cj中學組織學生出去春遊,作為學神的rhl自然不會放過這一大好時機,他有n種物品,第i件物品有c i 個,每個體積為v i 價值為w i rhl現在有乙個體積為v的揹包,他想讓他帶的東西價值...

2023年12月8日日誌

這一天沒有做任何有意義的工作,完全停滯。一整天都在為乙個設計人員裝系統,這讓我很沮喪。如果讓我待在自己的電腦旁邊,我會很有成績的做好一大部分工作。可是我今天除了給他安裝作業系統以外,就只是坐著,漫無目的的刷手機,看各種帖子。這種兩種生活展現出來的絕不是自我約束的問題,而是資源錯配。乙個人,放在乙個錯...

2023年6月8日 宋詞學習

青玉案 凌波不過橫塘路 賀鑄 凌波不過橫塘路,但目送,芳塵去。錦瑟華年誰與度。月喬花園,瑣窗朱戶,只有春知處。飛雲冉冉蘅皋暮,彩筆新題斷腸句。試問閒情都幾許?一川菸草,滿城風絮,梅子黃時雨。鷓鴣天 暗淡輕黃體性柔 李清照 暗淡輕黃體性柔,情疏跡遠只留香。何須淺碧深紅色,自是花中第一流。梅定妒,菊應羞...