1. 程式人生 > 其它 >【資料結構】查詢

【資料結構】查詢

技術標籤:資料結構演算法

本文根據嚴敏俊的資料結構進行的學習與歸納,歡迎進行不足指出和錯誤指正。

    查詢是在一堆資料元素裡尋找滿足某種條件的資料。在此我們為了方便查詢可以將同一種類型的資料放在一起構成查詢表。

查詢表我們可以分為靜態查詢表(線性查詢,折半查詢)和動態查詢表(二叉排序樹,平衡二叉樹,雜湊查詢),靜態查詢就像一本字典,在編寫完成之後就不能再次修改,只能在其中查詢。動態查詢是在你查詢的過程中依然能夠增減資料的元素。
在資料中某個資料項的值我們稱作是關鍵字,關鍵字可以標識一個數據的值,可以認為它是排序中的排序碼(一個關鍵字可以標識多個數據,與資料不一一對應)。

評判查詢演算法的好壞我們就需要用平均查詢長度

來判定,平均查詢長度小我們就認為這個查詢的演算法好,反之亦然。平均查詢長度就是查詢到每一個數據的次數的和除以總的資料數目(每個數查詢到的概率相同)。

靜態查詢表:
線性查詢(順序查詢):
平均查詢長度:(n+1)/2
線性查詢主要用線上性的資料結構中進行查詢。
線性查詢就是,如果我們需要查詢x,我們就從表頭的元素開始按順序與x對比,如果有相同的說明查詢成功,返回查詢成功處的位置,如果沒有相同的則查詢失敗。

折半查詢:
平均查詢長度:log2(n+1)-1。
折半查詢需要要求資料是有序排列的。
折半查詢,如果需要查詢x,將序列從中間分成兩段,與中間值對比,判斷是在前一半還是後一半,進行將所在的那一半分成兩段,重複步驟,直到找出x,返回查詢失敗。

動態查詢:
二叉排序樹(二叉查詢樹):
查詢的次數=樹的高度O(log2n)。
二叉排序樹的儲存形式為一顆二叉樹,在這個二叉樹中需要左子樹節點的值<根節點的值<右子樹節點的值。

查詢:首先對比更節點的值,如果需要更小的,往左子樹去查詢,需要更大的就前往右子樹查詢,到數底還未查詢到就返回查詢失敗。

插入:如果是空樹,新插入的結點成為樹根。若不是,就為新結點找到一個父節點(所找的父節點的要求是,如果比父節點小(大),就要比父節點的左(右)子樹結點值大(小)成為父節點的左(右)子樹結點值,原本的值向下移)(即,如果是先序遍歷二叉樹,所輸出的數值就是遞增排序)。

刪除:在二叉排序樹的刪除中,我們首先需要做的是找到所需要刪除的結點,若所刪除的結點沒有沒有子節點釋放結點所佔有的空間,若刪除的結點只有一個子節點就讓這個結點頂替被刪除的結點,若刪除的結點有兩個子節點,選擇左子樹中最右的結點,或者右子樹中最左的結點頂替被刪除的結點(因為已經是最右(左)的結點,只會有一個左(右)的子樹,頂替被刪除的子樹後,自身的子樹頂替它的位置)。

平衡二叉樹(AVL樹):
平衡二叉樹的左右子樹都是AVL樹,並且左右子樹的深度之差的絕對值不超過1,因此產生一個新的名詞就是:平衡因子,平衡因子=左子樹的深度-右子樹的深度(|平衡因子|<=1)。

構造:初始時為空樹,不斷插入結點,調整平衡。不平衡的調整需要從區域性著手開始調節,是一個從區域性到全域性的調整。

插入:每插入一個節點,樹根的平衡因子就會+(-)1,所以我們只需要消除不平衡就好。
如何消除不平衡:我們可以用四個模板來套用:
LL型:就是左孩子過多導致樹根為2,這種情況我們需要右旋,將原本的樹根的左孩子轉變為樹根,樹根變為其右孩子,原本左孩子的右孩子變為樹根的左孩子。
RR型:與LL型相反,是右孩子過多導致的不平衡,處理方法為對其左旋,方式與右旋相反。
LR型:樹根左子樹上的右子樹過多,處理方法為先左旋後右旋,左旋時區域左旋,也就是樹根的左子樹和左子樹的右子樹左旋,然後樹根和剛換上來的左子樹右旋。
RL型:與LR型正好相反,處理方法為先右旋後左旋,也是區域性右旋整體左旋。

雜湊查詢(雜湊查詢,雜湊查詢):
為了減少比較次數而存在的演算法,一種最少可以只比較一次就可以找到目標的查詢方法。
雜湊查詢是設定一個函式,將要被查詢的關鍵字經過函式處理儲存,查詢時根據將查詢資料的關鍵字過一遍函式,帶著處理過的值直接在表中查詢,省略不必要的多次關鍵字比較。

衝突:當關鍵字過一遍函式後的值相同的關鍵字我們稱為同義詞,我們可以使用線性探測再雜湊(把同義詞放在後一個有空餘的位置上),二次探測再雜湊,偽隨機探測再雜湊,這種同義詞就需要我們查詢兩遍,三遍甚至更多次。或者,我們也可以將同一地址的資料存放在連結串列之中。

函式的設計:函式設計的主要思想就是儘量減少衝突(讓關鍵字均勻的分佈到整個地址空間)。儘量設計的比較簡單,能很快計算出結果的函式最佳。所設計函式的定義域一般大於等於全部關鍵字的集合,而值域小於等於所有地址的集合。
線性函式法:a*key+b。
餘數法:key%p(p要小於等於地址數,而且接近地址數則分佈的更均勻,最好為質數,避免2)
數值抽取法:將關鍵字的某幾位取出來作為地址(只適用於提前知道關鍵字每一位數值分佈的情況,換一個關鍵字集合就要重新選)。
平方取中法:將關鍵字的提前幾位取出來,做平方,然後再從平方里抽取幾位作為地址(詞典中適用的比較多)。
摺疊法:將關鍵字拆成位數相等的幾段疊加,把疊加結果作為地址(移位疊加:最後一位對齊疊加,邊界疊加:各部分來回對摺,然後對齊相加)。
旋轉法:將關鍵字中的數字旋轉位置(12345678->78123456),一般和別的方法一起結合使用。
偽隨機數法:利用偽隨機數生成地址。