数据结构--散列表 Hash Table
生活随笔
收集整理的這篇文章主要介紹了
数据结构--散列表 Hash Table
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
文章目錄
- 1.線性探測(cè) 哈希表代碼
- 2.拉鏈法 哈希表代碼
- 1. 散列表用的是數(shù)組支持按照下標(biāo)隨機(jī)訪問(wèn)數(shù)據(jù)的特性,所以散列表其實(shí)就是數(shù)組的一種擴(kuò)展,由數(shù)組演化而來(lái)。可以說(shuō),如果沒(méi)有數(shù)組,就沒(méi)有散列表。
- 2. 散列函數(shù),設(shè)計(jì)的基本要求
第3條是很難完全滿(mǎn)足的,不滿(mǎn)足稱(chēng)之,散列沖突。
- 3. 散列沖突 解決方法:
a.線性探測(cè)
線性探測(cè)法,當(dāng)空閑位置越來(lái)越少時(shí),幾乎要遍歷整個(gè)散列表,接近O(n)復(fù)雜度
b. 二次探測(cè):每次的步長(zhǎng)是 1, 2, 4, 8, 16,…
c. 雙重散列:使用多個(gè)散列函數(shù),先用第一個(gè),如果位置被占,再用第二個(gè)散列函數(shù)。。。直到找到空閑位置
不管哪種方法,空閑位置不多了,沖突概率會(huì)大大提高,盡量保證有一定比例的空閑(用裝載因子表示,因子越大,空位越少,沖突越多,散列表性能下降)
- 4. 如何設(shè)計(jì)散列函數(shù)
a. 散列函數(shù)的設(shè)計(jì)不能太復(fù)雜。過(guò)于復(fù)雜的散列函數(shù),勢(shì)必會(huì)消耗很多計(jì)算時(shí)間,也就間接的影響到散列表的性能。
b. 散列函數(shù)生成的值要盡可能隨機(jī)并且均勻分布,這樣才能避免或者最小化散列沖突,即便出現(xiàn)沖突,散列到每個(gè)槽里的數(shù)據(jù)也會(huì)比較平均,不會(huì)出現(xiàn)某個(gè)槽內(nèi)數(shù)據(jù)特別多的情況。
c. 裝載因子超過(guò)閾值,自動(dòng)擴(kuò)容,避免累積到最后一次性搬移數(shù)據(jù),分批多次搬移,O(1)復(fù)雜度
d. 數(shù)據(jù)量比較小,裝載因子小的時(shí)候,適合采用開(kāi)放尋址法
e. 基于鏈表的散列沖突處理方法比較適合存儲(chǔ)大對(duì)象、大數(shù)據(jù)量的散列表,而且,比起開(kāi)放尋址法,它更加靈活,支持更多的優(yōu)化策略,比如用紅黑樹(shù)代替鏈表。
1.線性探測(cè) 哈希表代碼
hashtable1.h
/*** @description: 哈希表,開(kāi)放尋址--線性探測(cè)法* @author: michael ming* @date: 2019/5/6 10:26* @modified by: */ #ifndef SEARCH_HASHTABLE1_H #define SEARCH_HASHTABLE1_H #include <iostream> enum KindOfItem {Empty, Active, Deleted}; template <class DataType> struct HashItem {DataType data;KindOfItem info;HashItem<DataType>(KindOfItem i = Empty):info(i){}HashItem<DataType>(const DataType &d, KindOfItem i = Empty):data(d), info(i){}int operator== (HashItem<DataType> &a){return data == a.data;}int operator!= (HashItem<DataType> &a){return data != a.data;} }; template <class DataType> class hashtable1 { private:HashItem<DataType> *ht; //散列表數(shù)組int TableSize; //散列表長(zhǎng)度int currentSize; //當(dāng)前表項(xiàng)個(gè)數(shù)int deletedSize; //刪除標(biāo)記的元素個(gè)數(shù) public:hashtable1<DataType>(int m){TableSize = m;ht = new HashItem<DataType> [TableSize];currentSize = 0;deletedSize = 0;}~hashtable1<DataType>(){delete [] ht;}int hash(const DataType &newData) const{return newData%TableSize; //留余數(shù)法}int find(const DataType &x) const;int find_de(const DataType &x) const; //當(dāng)有deleted標(biāo)記的元素時(shí),插入函數(shù)調(diào)用此查找int insert(const DataType &x);int delete_elem(const DataType &x);void print() const{for(int i = 0; i < TableSize; ++i){std::cout << ht[i].data << " " << ht[i].info << "->";}std::cout << std::endl;}int isInTable(const DataType &x){int i = find(x);return i >= 0 ? i : -1;}DataType getValue(int i) const{return ht[i].data;} }; #endif //SEARCH_HASHTABLE1_Hhashtable1.cpp
/*** @description: 哈希表,開(kāi)放尋址--線性探測(cè)法* @author: michael ming* @date: 2019/5/6 10:26* @modified by: */ #include "hashtable1.h" template <class DataType> int hashtable1<DataType>::find(const DataType &x) const {int i = hash(x);int j = i;while(ht[j].info == Deleted || (ht[j].info == Active && ht[j].data != x)) //說(shuō)明存在沖突{j = (j+1)%TableSize; //用解決沖突的方法繼續(xù)查找(開(kāi)放定址法)if(j == i)return -TableSize; //遍歷整個(gè)散列表,未找到}if(ht[j].info == Active)return j; //找到,返回正值elsereturn -j; //沒(méi)找到,返回負(fù)值 } template <class DataType> int hashtable1<DataType>::find_de(const DataType &x) const //當(dāng)有deleted標(biāo)記的元素時(shí),插入函數(shù)調(diào)用此查找 {int i = hash(x);int j = i;while(ht[j].info == Active) //說(shuō)明存在沖突{j = (j+1)%TableSize; //用解決沖突的方法繼續(xù)查找(開(kāi)放定址法)if(j == i)return -TableSize; //遍歷整個(gè)散列表,沒(méi)有空位}return j; //返回標(biāo)記為Empty或者Deleted的位置 } template <class DataType> int hashtable1<DataType>::insert(const DataType &x) {int i = find(x);if(i > 0)return 0; //元素x已存在else if(i != -TableSize && !deletedSize) //元素x不存在,且散列表未滿(mǎn)(且沒(méi)有deleted標(biāo)記){ht[-i].data = x; //元素賦值ht[-i].info = Active; //占用了,標(biāo)記一下currentSize++;return 1;}else if(i != -TableSize && deletedSize) //元素x不存在,且散列表未滿(mǎn)(且有deleted標(biāo)記){int j = find_de(x);if(j >= 0){if(ht[j].info == Deleted)deletedSize--;ht[j].data = x; //元素賦值ht[j].info = Active; //占用了,標(biāo)記一下(刪除標(biāo)記改成占用標(biāo)記 )currentSize++;return 1;}elsereturn 0;}else return 0; } template <class DataType> int hashtable1<DataType>::delete_elem(const DataType &x) {int i = find(x);if(i >= 0){ht[i].info = Deleted; //找到了要?jiǎng)h除的,標(biāo)記刪除currentSize--;deletedSize++;return 1;}else return 0; }hashtable1_test.cpp 測(cè)試程序
/*** @description: * @author: michael ming* @date: 2019/5/6 10:42* @modified by: */ #include "hashtable1.cpp" #include <iostream> int main() {hashtable1<int> ht1(10);ht1.print();for(int i = 15; i < 18; ++i){ht1.insert(i);ht1.print();}for(int i = 25; i < 29; ++i){ht1.insert(i);ht1.print();}for(int i = 27; i < 29; ++i){ht1.delete_elem(i);ht1.print();}for(int i = 100; i < 103; ++i){ht1.insert(i);ht1.print();}for(int i = 200; i < 203; ++i){ht1.insert(i);ht1.print();}if(ht1.isInTable(109) >= 0)std::cout << ht1.getValue(ht1.isInTable(109));return 0; }測(cè)試結(jié)果:(data,標(biāo)記位)標(biāo)記 empty = 0,active = 1, deleted = 2
2.拉鏈法 哈希表代碼
linkedHash.h
/*** @description: 拉鏈法散列表* @author: michael ming* @date: 2019/5/6 17:56* @modified by: */#ifndef SEARCH_LINKEDHASH_H #define SEARCH_LINKEDHASH_H #include <iostream> template <class DataType> struct linkedNode //鏈表節(jié)點(diǎn) {DataType data;linkedNode *next;linkedNode():next(NULL){}linkedNode(const DataType &d):next(NULL), data(d){} }; template <class DataType> class linkedList //鏈表 { public:linkedNode<DataType> *head;linkedList(){head = new linkedNode<DataType>(); //表頭哨兵}~linkedList(){delete head;} }; template <class DataType> class linkedHash { private:linkedList<DataType> *htList; //散列表鏈表數(shù)組int bucket; //散列表桶個(gè)數(shù) public:linkedHash<DataType>(int m):bucket(m){htList = new linkedList<DataType> [bucket] ();}~linkedHash<DataType>(){for(int i = 0; i < bucket; ++i){linkedNode<DataType> *p = htList[i].head->next, *q = p;while(q != NULL){p = q;q = q->next;delete p;}}delete [] htList;}int hash(const DataType &newData) const{return newData%bucket; //留余數(shù)法}linkedNode<DataType>* find(const DataType &x) const{int i = hash(x);linkedNode<DataType> *p = htList[i].head->next, *q = htList[i].head;while(p && p->data != x){q = p;p = p->next;}return q; //返回找到元素的前一個(gè)節(jié)點(diǎn),或者沒(méi)有找到,返回最后一個(gè)元素}linkedNode<DataType>* insert(const DataType &x){int i = hash(x);linkedNode<DataType> *p = htList[i].head, *q = p;while(q != NULL){p = q;q = q->next;}p->next = new linkedNode<DataType>(x);return p->next;}void delete_elem(const DataType &x){linkedNode<DataType> *q = find(x), *p;if(q->next){p = q->next;q->next = q->next->next;delete p;}}void print() const{for(int i = 0; i < bucket; ++i){std::cout << i << "[ ]";linkedNode<DataType> *p = htList[i].head->next;while(p){std::cout << p->data << "->";p = p->next;}std::cout << std::endl;}std::cout << "----------------------" << std::endl;} }; #endif //SEARCH_LINKEDHASH_HlinkedHash_test.cpp 測(cè)試程序
/*** @description: 拉鏈法散列表 測(cè)試* @author: michael ming* @date: 2019/5/6 17:57* @modified by: */ #include "linkedHash.h" int main() {linkedHash<int> ht2(10);for(int i = 15; i < 37; ++i){ht2.insert(i);ht2.print();}ht2.delete_elem(15);ht2.print();ht2.delete_elem(18);ht2.print();ht2.delete_elem(28);ht2.print();ht2.insert(88);ht2.print();ht2.delete_elem(100);ht2.print();return 0; }測(cè)試結(jié)果:
總結(jié)
以上是生活随笔為你收集整理的数据结构--散列表 Hash Table的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 怎样从php转向java_Github标
- 下一篇: 朴素贝叶斯算法--过滤垃圾短信