1. 程式人生 > >查詢演算法之雜湊查詢

查詢演算法之雜湊查詢

雜湊查詢是通過計算資料元素的儲存地址進行查詢的一種方法。O(1)的查詢,即所謂的秒殺。雜湊查詢的本質是先將資料對映成它的雜湊值。雜湊查詢的核心是構造一個雜湊函式,它將原來直觀、整潔的資料對映為看上去似乎是隨機的一些整數。

雜湊查詢的操作步驟:

1)       用給定的雜湊函式構造雜湊表;

2)       根據選擇的衝突處理方法解決地址衝突;

3)       在雜湊表的基礎上執行雜湊查詢。

建立雜湊表操作步驟:

1)       step1 取資料元素的關鍵字key,計算其雜湊函式值(地址)。若該地址對應的儲存空間還沒有被佔用,則將該元素存入;否則執行step2解決衝突。

2)       step2

根據選擇的衝突處理方法,計算關鍵字key的下一個儲存地址。若下一個儲存地址仍被佔用,則繼續執行step2,直到找到能用的儲存地址為止。

雜湊查詢步驟為:

1)       Step1 對給定k值,計算雜湊地址 Di=Hk);若HST為空,則查詢失敗;若HST=k,則查詢成功;否則,執行step2(處理衝突)。

2)       Step2 重複計算處理衝突的下一個儲存地址 Dk=RDk-1),直到HST[Dk]為空,或HST[Dk]=k為止。若HST[Dk]=K,則查詢成功,否則查詢失敗。

比如說:”5“是一個要儲存的數,然後我丟給雜湊函式,雜湊函式給我返回一個”2",那麼此時的”5“和“2

”就建立一種對應關係,這種關係就是所謂的“雜湊關係”,在實際應用中也就形成了”2“是key,”5“是value

那麼有的朋友就會問如何做雜湊,首先做雜湊必須要遵守兩點原則:

: key儘可能的分散,也就是我丟一個“6”和“5”給你,你都返回一個“2”,那麼這樣的雜湊函數不盡完美。

②:雜湊函式儘可能的簡單,也就是說丟一個“6”給你,你雜湊函式要搞1小時才能給我,這樣也是不好的。

其實常用的做雜湊的手法有“五種”:

第一種:”直接定址法“。

很容易理解,key=Value+C;這個“C"是常量。Value+C其實就是一個簡單的雜湊函式。

第二種:“除法取餘法”。

很容易理解, key=value%C;

解釋同上。

第三種:“數字分析法”。

這種蠻有意思,比如有一組value1=112233value2=112633value3=119033

針對這樣的數我們分析數中間兩個數比較波動,其他數不變。那麼我們取key的值就可以是

key1=22,key2=26,key3=90

第四種:“平方取中法”。此處忽略,見名識意。

第五種:“摺疊法”。

這種蠻有意思,比如value=135790,要求key2位數的雜湊值。那麼我們將value變為13+57+90=160,然後去掉高位“1,此時key=60,哈哈,這就是他們的雜湊關係,這樣做的目的就是key與每一位value都相關,來做到“雜湊地址”儘可能分散的目地。

影響雜湊查詢效率的一個重要因素是雜湊函式本身。當兩個不同的資料元素的雜湊值相同時,就會發生衝突。為減少發生衝突的可能性,雜湊函式應該將資料儘可能分散地對映到雜湊表的每一個表項中。

解決衝突的方法有以下兩種:  

(1)   開放地址法  

如果兩個資料元素的雜湊值相同,則在雜湊表中為後插入的資料元素另外選擇一個表項。當程式查詢雜湊表時,如果沒有在第一個對應的雜湊表項中找到符合查詢要求的資料元素,程式就會繼續往後查詢,直到找到一個符合查詢要求的資料元素,或者遇到一個空的表項。  

(2)   鏈地址法

將雜湊值相同的資料元素存放在一個連結串列中,在查詢雜湊表的過程中,當查詢到這個連結串列時,必須採用線性查詢方法。

實現雜湊函式為“除法取餘法”,解決衝突為“開放地址線性探測法”,程式碼如下:

public class HashSearch {

	public static void main(String[] args) {
		//“除法取餘法”
        int hashLength = 13;

        int [] array  = { 13, 29, 27, 28, 26, 30, 38 };

        //雜湊表長度
        int[] hash = new int[hashLength];
        //建立hash
        for (int i = 0; i < array.length; i++)
        {
            insertHash(hash, hashLength, array[i]);
        }
        
        int result = searchHash(hash,hashLength, 29);

		if (result != -1)
			System.out.println("已經在陣列中找到,索引位置為:" + result);
		else
			System.out.println("沒有此原始");
	}

	/****
	 * Hash表檢索資料
	 * 
	 * @param hash
	 * @param hashLength
	 * @param key
	 * @return
	 */
	public static int searchHash(int[] hash, int hashLength, int key) {
		// 雜湊函式
		int hashAddress = key % hashLength;

		// 指定hashAdrress對應值存在但不是關鍵值,則用開放定址法解決
		while (hash[hashAddress] != 0 && hash[hashAddress] != key) {
			hashAddress = (++hashAddress) % hashLength;
		}

		// 查詢到了開放單元,表示查詢失敗
		if (hash[hashAddress] == 0)
			return -1;
		return hashAddress;

	}

	/***
	 * 資料插入Hash表
	 * 
	 * @param hash 雜湊表
	 * @param hashLength
	 * @param data
	 */
	public static void insertHash(int[] hash, int hashLength, int data) {
		// 雜湊函式
		int hashAddress = data % hashLength;

		// 如果key存在,則說明已經被別人佔用,此時必須解決衝突
		while (hash[hashAddress] != 0) {
			// 用開放定址法找到
			hashAddress = (++hashAddress) % hashLength;
		}

		// 將data存入字典中
		hash[hashAddress] = data;
	}
}

執行結果:
已經在陣列中找到,索引位置為:3

相關推薦

查詢演算法查詢(近似O(1)的單點查詢方法)

雜湊查詢是通過計算資料元素的儲存地址進行查詢的一種方法。O(1)的查詢,即所謂的秒殺。雜湊查詢的本質是先將資料對映成它的雜湊值。雜湊查詢的核心是構造一個雜湊函式,它將原來直觀、整潔的資料對映為看上去似乎是隨機的一些整數。 雜湊查詢的操作步驟: 1)       用給定的雜

查詢演算法查詢

雜湊查詢是通過計算資料元素的儲存地址進行查詢的一種方法。O(1)的查詢,即所謂的秒殺。雜湊查詢的本質是先將資料對映成它的雜湊值。雜湊查詢的核心是構造一個雜湊函式,它將原來直觀、整潔的資料對映為看上去似乎是隨機的一些整數。 雜湊查詢的操作步驟: 1)       用給定的雜湊

路由路由表查詢演算法概述-/LC-Trie樹/256-way-mtrie樹

引:路由是網際網路的一個核心概念,廣義的講,它使分組交換網的每個節點彼此獨立,通過路由耦合在一起,甚至在電路交換網中,虛電路的建立也依賴路由,路由就是網路中資料通路的指向標。狹義的講,路由專指IP路由,它支撐著整個IP網路。     由於IP是資料報網路,它是

Internet路由路由表查詢演算法概述-/LC-Trie樹/256-way-mtrie樹

                說明:本文沒有原始碼分析的內容,然而我認為能理解本質比能看懂原始碼更有用,因為理解了本質之後,你也許就不用再看原始碼了,你甚至都可以寫原始碼了。這就是Linux核心和Cisco的網站中包含大量文件的原因。引:路由是網際網路的一個核心概念,廣義的講,它使分組交換網的每個節點彼此獨

路由表查詢演算法概述-/LC-Trie樹/256-way-mtrie樹

說明:本文沒有原始碼分析的內容,然而我認為能理解本質比能看懂原始碼更有用,因為理解了本質之後,你也許就不用再看原始碼了,你甚至都可以寫原始碼了。這就是Linux核心和Cisco的網站中包含大量文件的原因。引:路由是網際網路的一個核心概念,廣義的講,它使分組交換網的每個節點彼此獨立,通過路由耦合在一起,甚至在

七大查詢演算法樹表查詢---二叉樹查詢演算法

二叉樹查詢演算法        二叉查詢樹是先對待查詢的資料進行生成樹,確保樹的左分支的值小於右分支的值,然後在就行和每個節點的父節點比較大小,查詢最適合的範圍。 這個演算法的查詢效率很高,但是如果使用這種查詢方法要首先建立樹。 原理:         二叉查詢樹(Bi

查詢演算法——二叉查詢樹(圖文分析)

1 package Unit3; 2 3 import java.util.Stack; 4 5 import edu.princeton.cs.algs4.Queue; 6 7 public class BST<Key extends Comparab

查詢演算法三分查詢

三、具體實現  const double EPS = 1e-10; double calc(double x) { // f(x) = -(x-3)^2 + 2; return -(x-3.0)*(x-3.0) + 2; } double ternary

資料結構查詢-查詢

目錄 雜湊法(計算式查詢) 雜湊函式的構造方法 處理衝突的方法 雜湊表的查詢過程 雜湊法(計算式查詢) 雜湊法又稱雜湊法、雜湊發、關鍵字地址計演算法,相應的表成為雜湊表、散列表等。 雜湊法的基本思想:首先在元素的關鍵字k和元素的儲存位置p之間建立一個對應

資料結構實驗查詢七:線性

Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 根據給定的一系列整數關鍵字和素數p,用除留餘數法定義hash函式H(K

資料結構實驗查詢五:平方表 (SDUT 3377)

Hash表的平方探測思路:如果當前這個沒存放數值,就放進去,如果當前這個地方Hash [ i ] 已經有數值了,就以平方的間隔左右尋找沒有存放數的空白 Hash [ i ]。  #include <bits/stdc++.h> using namespace std;

資料結構實驗查詢七:線性表 (SDUT 3379)

#include <stdio.h> #include <string.h> #include <stdlib.h> int a[3500]; int Hash[3500]; int main() { int n,p,t; while(~s

SDUT3379資料結構實驗查詢七:線性

最後一個,線性探測hash表,跟上一個平方探測基本類似,觸類旁通型的。 詳情***看註釋*** #include <iostream> #include <cstring> #include <cstdio> using namespace std;

SDUT3377資料結構實驗查詢五:平方

不妨看看註釋吖 因為是刷題的原因,所以註釋沒有那麼的詳細,但是一切盡在註釋中 #include <iostream> #include <cstring> #include <cstdio> using namespace std; int m

查詢演算法及C語言實現

上一節介紹了有關雜湊表及其構造過程的相關知識,本節將介紹如何利用雜湊表實現查詢操作。 在雜湊表中進行查詢的操作同雜湊表的構建過程類似,其具體實現思路為:對於給定的關鍵字 K,將其帶入雜湊函式中,求得與該關鍵字對應的資料的雜湊地址,如果該地址中沒有資料,則證明該查詢表中沒有儲存該資料,查詢失敗:如果雜湊地址中

動態查詢(hash)表

一、介紹   與其他建立在“比較”基礎上的查詢演算法不同,雜湊表是通過雜湊函式將儲存位置與值得關鍵字建立一一對應關係,從而一般一次就能夠得到值。但是有時對於不同關鍵字雜湊後得到的地址會是相同的,稱這種現象為衝突。具有相同雜湊值的關鍵字稱為同義詞。 二、雜

查詢鏈地址法解決衝突(程式碼封裝實現)

鏈地址法的基本思想是:將所有雜湊地址為i 的元素構成一個稱為同義詞鏈的連結串列,並將連結串列的頭指標存在雜湊表的第i個單元中,因而查詢、插入和刪除主要在同義詞鏈中進行。  該雜湊方法首先對關鍵碼集合用某一個雜湊函式計算它們的存放位置。 若設散列表地址空間的所有位置是從

查詢演算法——符號表(引入篇)

符號表的主要目的是用來儲存鍵值對,也就是將一個鍵和一個值關聯起來,它的主要操作為插入和查詢。 這篇只是為下一篇文章作為拋磚引玉,為不熟悉符號表的朋友做了一個大體的介紹,在文章的結尾列出了符號表的基本操作,有一定了解的朋友可以跳的下一篇文章(二叉查詢樹)。 首先我們必須討論幾個基本問題,這在之後的思想中將會

python 查詢

  import random INDEXBOX=7 #雜湊表元素個數 MAXNUM=13 #資料個數 class Node: #宣告連結串列結構 def __init__(self,val): self.val=val

二叉排序樹查詢演算法php實現

        二叉排序樹,又稱為二叉查詢樹。它或者是一棵空樹,或者是具有下列性質的二叉樹。                1.若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值                2.若它的右子樹不空,則右子樹上所有結點的值均小於它