雜湊表,也稱雜湊表,是一種通過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 ...