雜湊表(閉雜湊 拉鍊法 雜湊桶)

2021-07-27 04:44:47 字數 4416 閱讀 8597

雜湊表,也稱雜湊表,是一種通過key值來直接訪問在記憶體中的儲存的資料結構。它通過乙個關鍵值的函式(被稱為雜湊函式)將所需的資料對映到表中的位置來訪問資料。

關於雜湊表,主要為以下幾個方面:

一、雜湊表的幾種方法

1、直接定址法:取關鍵字key的某個線性函式為雜湊位址,如hash(key) = key  或 hash(key) = a*key+b;a,b為常數

4、摺疊法:把關鍵碼自左到右分為位數相等的幾部分,每一部分的位數應與雜湊表位址位數相同,只有最後一部分的位數可以短一些。把這些部分的資料疊加起來,就可以得到具有關鍵碼的記錄的雜湊位址。分為移位法和分界法。

6、數學分析法:設有n個d位數,每一位可能有r種不同的符號。這r種不同的符號在各位上出現的頻率不一定相同,可能在某些位上分布均勻些,每種符號出現的機會均等;在某些位上分布不均勻,只有某幾種符號經常出現。可根據雜湊表的大小,選取其中各種符號分布均勻的若干位作為雜湊位址。

在這裡,我們建雜湊表的方法用除留取餘法為例。

儘管有這麼多種方法,但是不同的key值可能會對映到同一雜湊位址上。這樣就會造成雜湊衝突/雜湊碰撞。

那麼遇到雜湊衝突我們該如何處理呢?

二、處理雜湊衝突的閉雜湊方法

1、線性探測:當不同的key值通過雜湊函式對映到同一雜湊位址上時,檢測當前位址的下乙個位址是否可以插入,如果可以的話,就存在當前位置的下乙個位址,否則,繼續向下乙個位址尋找,位址++。

2、二次探測:是針對線性探測的乙個改進,線性探測後插入的key值太集中,這樣造成key值通過雜湊函式後還是無法正確的對映到位址上,太集中也會造成查詢、刪除時的效率低下。因此,通過二次探測的方法,取當前位址加上i^2,可以取到的新的位址就會稍微分散開。

如:此時的雜湊表長度為10:

看到以上的例子之後,我們只是存入int型的資料時,計算餘數尋找位址是比較容易的。如果我們存入的是字典值(string型別),那麼我們就要通過string型別來轉化成數值來計算位址。這裡用到了bkdr雜湊演算法(字串雜湊演算法)。

同時,經研究表明,通過素數表作為雜湊表的長度可以降低雜湊衝突。

三、閉雜湊實現**

主要實現如下:

#pragma once

#include#includeusing namespace std;

#include#includeenum status

;templatestruct hashtablenode

};templatestruct __hashfunc

};template<>

struct __hashfunc

return hash;

} size_t operator()(const string& str) };

template>

class hashtable

~hashtable()

{} size_t hashfunc(const k& key)

void swap(hashtable& ht)

void _checkcapacity()

}this->swap(ht);

} }pairinsert(const k& key,const v& value)}*/

//二次探測

size_t i = 0;

size_t first = index;

while(_tables[index]._status == exist )

++_size;

_tables[index]._key = key;

_tables[index]._value = value;

_tables[index]._status = exist;

return make_pair(&_tables[index],true);

} node* find(const k& key,const v& value)

else

}} return null;

} bool remove(const k& key,const v& value)

return false;

} size_t getprime()

; for(size_t i = 0; i < _primesize; i++)

return 0;

}private:

vector_tables;

size_t _size;

};void hashtest()

}; template<>

struct __hashfunc

return hash;

} size_t operator()(const string& str)

};templateclass hashtable;

templatestruct hashnode

};templatestruct ha****erator

ref operator*()

ptr operator->()

bool operator!=(const self& s) const

self& operator++()

node* next(node* node)

}return null;

}} };

template>

class hashtable

~hashtable()

void clear()

while(cur)

}} iterator begin()

}return iterator((node*)null,this);

} iterator end()

cur = cur->_next;

}return iterator((node*)null,this);*/

} size_t hashfunc(const k& key)

void swap(hashtable& ht)

void _checkcapacity()

}this->swap(tmp);

}} size_t getnextprime()

; for(size_t i = 0; i < _primesize; i++)

return 0;

} public:

pairinsert(pairkv)

cur = cur->_next;

}node* tmp = new node(kv);

tmp->_next = _tables[index];

_tables[index] = tmp;

_size++;

return make_pair(iterator(tmp,this),true);

} node* find(const k& key)

cur = cur->_next;

}return null;

} bool erase(const k& key)

else

delete cur;

cur = null;

_size--;

return true;

}prev = cur;

cur = cur->_next;

}return false;

} private:

vector_tables;

size_t _size;

}; void hashtest()

{ hashtableht;

ht.insert(make_pair(89,0));

ht.insert(make_pair(18,0));

ht.insert(make_pair(49,0));

ht.insert(make_pair(58,0));

ht.insert(make_pair(9,0));

cout<_kv.first it="ht.begin();

while(it != ht.end())

{ cout<

ht1.insert(make_pair(" sort>

ht1.insert(make_pair("left","左邊"));

ht1.insert(make_pair("right","右邊"));

ht1.insert(make_pair("up","上邊"));

cout<_kv.second it1="ht1.begin();

while(it1 != ht1.end())

{ cout<

六、執行結果(編譯執行環境為:vs2013)

雜湊拉鍊法(雜湊桶)

昨天寫了雜湊的開放定址法的部落格,今天我們要說的是拉鍊法,還有乙個名字叫雜湊桶。雜湊桶要做的就是,之前我們用的開放定址法,通過將資料對映到陣列中來實現雜湊。這裡每個陣列的位置只能存放乙個資料,如果衝突的話會繼續往下找找到空的位置然後放進去,但是其實大家都能感覺出來上乙個 很簡單,也很扯,感覺實現起來...

雜湊表(拉鍊法)

開雜湊法又叫鏈位址法 開鏈法 開雜湊法 首先對關鍵碼集合用雜湊函式計算雜湊位址,具有相同位址的關鍵碼歸於同一子集合,每乙個子集合稱為乙個桶,各個 桶中的元素通過乙個單鏈表鏈結起來,各鍊錶的頭結點儲存在雜湊表中。設元素的關鍵碼為37,25,14,36,49,68,57,11,雜湊表為ht 12 表的大...

雜湊錶開雜湊法(拉鍊法)

開雜湊法又叫鏈位址法 開鏈法 設元素的關鍵碼為37,25,14,36,49,68,57,11,雜湊表為ht 12 表的大小為12,雜湊函式為hash x x 11 hash 37 4 hash 25 3 hash 14 3 hash 36 3 hash 49 5 hash 68 2 hash 57 ...