概述: 用於數據查找(搜索)的數據結構
前面的文章系列,我們都是講排序,這次我們來講講另外一個應用場景: 數據搜索。
- 散列表
- 布隆過濾器
- 二叉樹
- 紅黑樹
- B樹
一. 散列表
通過hash函數,將數據均勻的分佈在不同的bucket中,這樣就大大減少了數據檢索的時間。
散列函數:
散列表的性能取決於散列函數,散列函數決定了可以把原始數據集分佈到多少的桶中。
動態散列表:
二. 布隆過濾器
布隆過濾器這個使用場景是比較多的。
原理是使用n個hash函數,然後分別對原始數據進行計算後存儲hash函數計算之後的值。
如果它們有一個說元素不在集合中,那肯定就不在。
但是因爲不同數值的hash值可能一致,所以當布隆過濾器判斷數值在集合中存在的時候,不一定真的就存在,需要通過其它數據結構,再進行判斷。
而且,當數據量越來越大,布隆過濾器的準確率也就越來越低。
三. 二叉樹
3.1 二叉樹
左邊小於父節點的值
右邊大於等於父節點的值
二叉樹的弱點:
基於二叉查找樹的這種特點,在查找某個節點的時候,可以採取類似於二分查找的思想,快速找到某個節點。n 個節點的二叉樹,正常情況下,查找的時間複雜度爲 O(logN)。之所以說是正常情況下,是因爲二叉查找樹有可能出現一種極端的情況,例如:
這種情況雖也滿足二叉樹的條件,但已經近似退化爲一條鏈表,這樣的二叉樹的查找時間複雜度頓時變成了 O(n)。所以必須防止這種情況發生,於是引申出了平衡二叉樹。
3.2 平衡二叉樹
平衡二叉樹是基於二分法的策略提高數據查找速度的二叉樹的數據結構。
平衡二叉樹是採用二分法思維把數據按規則組裝成一個樹形結構的數據,用這個樹形結構的數據減少無關數據的檢索,大大的提升了數據檢索的速度。平衡二叉樹的數據結構組裝過程有以下規則:
2.1) 非葉子節點只能允許最多兩個子節點存在。
2.2 ) 每一個非葉子節點數據分佈規則爲左邊的子節點小當前節點的值,右邊的子節點大於當前節點的值(這裏值是基於自己的算法規則而定的,比如 hash 值)。平衡二叉樹特點:
3.1) 非葉子節點最多擁有兩個子節點。
3.2) 非葉子節點值大於左邊子節點、小於右邊子節點。
3.3)樹的左右兩邊的層級數相差不會大於 1。
3.4)沒有值相等重複的節點。
右邊的二叉樹,如果是平衡二叉樹的話,就會通過旋轉,變化爲左邊的平衡二叉樹。
四. 紅黑樹
雖然平衡樹解決了二叉查找樹退化爲近似鏈表的缺點,能夠把查找時間控制在 O(logn),卻不是最佳的。因爲平衡樹要求每個節點的左子樹和右子樹的高度差至多等於 1,這個要求太嚴,導致每次進行【插入/刪除】節點的時候,幾乎都會破壞平衡樹的第二個規則,進而都需要通過左旋和右旋來進行調整,使之再次成爲一顆符合要求的平衡樹。
五. B樹
節點
樹形
B樹索引的弱點:
六. 實例
http://poj.org/problem?id=2503
package com.suanfa.數據結構;
import java.util.Scanner;
import java.util.Hashtable;
public class POJ2503 {
public static void main(String[] args) {
Scanner in = new Scanner( System.in );
Hashtable<String, String> table = new Hashtable<String, String>();
String input;
String [] array = new String[2];
while (in.hasNext()){
input = in.nextLine();
if (input.length()==0) break;
array = input.split( " " );
table.put( array[1], array[0] );
}
while (in.hasNext()){
input= in.nextLine();
if (table.get( input ) != null) System.out.println(table.get( input ));
else System.out.println("eh");
}
}
}