<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
雜湊表,即雜湊表,可以快速地儲存和查詢記錄。理想雜湊表的儲存和查詢時間都是 O(1)。
本《資料》中雜湊表分以下幾部分:雜湊函數、儲存和查詢時的元素定位、儲存、查詢。刪除操作因為不常用,所以只給出思想,不給出程式碼。
根據實際情況,可選擇不同的雜湊方法。
以下程式碼假設雜湊表不會溢位。
// N表示雜湊表長度,是一個素數,M表示額外空間的大小,empty代表「沒有元素」。 const int N=9997, M=10000, empty=-1; int a[N]; void init() // 初始化雜湊表 { memset(a,empty,sizeof(a)); // 注意,只有empty等於0或-1時才可以這樣做! memset(bucket,empty,sizeof(bucket)); memset(first,0,sizeof(first)); } inline int h(int); // 雜湊函數 int *locate(int, bool); // 用於儲存和查詢的定位函數,並返回對應位置。 // 如果用於儲存,則第二個引數為true,否則為false①。 void save(int x) // 儲存資料 { int *p = locate(x, true); if (p!=NULL) *p=x; } bool isexist(int x) // 查詢資料 { int *p = locate(x,false); return (p!=NULL && *p==x); }
為了達到快速儲存和查詢的目的,就必須在記錄的儲存位置和它的關鍵字之間建立一個確定的對應關係 h。
這個關係 h 叫做雜湊函數。
雜湊表存取方便但儲存時容易衝突:即不同的關鍵字可以對應同一雜湊地址。如何確定雜湊函數和解決衝突是關鍵。以下是幾種常見的雜湊函數的構造方法:
1. 取餘數法:h(x) = x%p(p≤N,且最好是素數)
2. 直接定址法:h(x)=x 或 h(x)=a*x+b
3. 數位分析法:取關鍵字的若干數位(如中間兩位數)組成雜湊地址。
4. 平方取中法:關鍵字平方後取中間幾位陣列成雜湊地址。
5. 摺疊法:將關鍵數位分割成位數相同的幾部分(最後一部分的位數可以不同)然後取幾部分的疊加和(捨去進位)作為雜湊地址。
6. 偽亂數法:事先產生一個亂數序列 r[],然後令 h(x)=r[x]。
設計雜湊函數時,要注意
對關鍵碼值的分佈並不瞭解——希望選擇的雜湊函數在關鍵碼範圍內能夠產生一個大致平均的關鍵碼值隨機分佈,同時避免明顯的聚集可能性,如對關鍵碼值的高位或低位敏感的雜湊函數。
對關鍵碼值的分佈有所瞭解——應該使用一個依賴於分佈的雜湊函數,避免把一組相關的關鍵碼值對映到雜湊表的同一個槽中。
雜湊表中難免會發生衝突。使用開雜湊方法可以解決這個問題。常用操作方法是“拉鍊法”,即相同的地址的關鍵字值均鏈入對應的連結串列中。
如果雜湊函數很差,就容易形成長長的連結串列,從而影響查詢的效率。
下面是用“拉鍊法”處理衝突時的定位函數:
int size=-1; struct node {int v; node * next;} *first[N], mem[M]; #define NEW(p) p=&mem[++size]; p->next=NULL int * locate(int x, bool ins=false) { int p=h(x); if (a[p]==x && !ins) return &a[p]; // 處理衝突 node *q = first[p]; if (ins) if (q==NULL) { NEW(q); first[p]=q; return &q->v; } else { while (q->next!=NULL) q=q->next; node *r; NEW(r); q->next=r; return &r->v; } else while (q!=NULL) { if (q->v == x) return &q->v; q=q->next; } return NULL; }
處理衝突的另一種方法是為該關鍵字的記錄找到另一個“空”的雜湊地址。在處理中可能得到一個地址序列 g(i)(i=1,2,…,k;0≤g(i)≤n-1),即在處理衝突時若得到的另一個雜湊地址 g(1)仍發生衝突,再
求下一地址 g(2),若仍衝突,再求 g(3)……怎樣得到 g(i)呢?
溢位桶法:設一個溢位桶,不管得到的雜湊地址如何,一旦發生衝突,都填入溢位桶。
再雜湊法:使用另外一種雜湊函數來定位。
線性探查:g(i)=(h(x)+di) % N,其中 h(x)為雜湊函數,N 為雜湊表長,di 為增量序列。
1. 線性探測再雜湊:di=1,2,3,…,m-1
2. 二次探測再雜湊:
3. 偽隨機探測序列:事先產生一個亂數序列 random[],令 di=random[i]。
下面是用溢位桶處理衝突時的定位函數:
int bucket[M], top=-1; // 用於閉雜湊方法(溢位桶) int * locate(int x, bool ins=false) { int p=h(x); if (a[p]==x && !ins) // 在查詢模式下碰到了所需的元素 return &a[p]; else if (ins) { if (a[p]==empty) // 可以插入 return &a[p]; else // 處理衝突 return &bucket[++top]; } else // 到溢位桶中尋找元素 for (int i=0; i<=top; i++) if (bucket[i]==x) return &bucket[i]; return NULL; }
下面是用線性探查處理衝突的定位函數,當然,它也可以用於再雜湊法處理衝突
inline int g(int p, int i) {return (p+i)%N;} // 根據需要來設計 int * locate(int x, bool ins=false) { int p=h(x); int p2, c=0; if (a[p]==x && !ins) return &a[p]; else if (ins) { do { p2 = g(p, c++); } while (a[p2]!=empty); return &a[p2]; } else { do { p2 = g(p, c++); } while (a[p2]!=x && a[p2]!=empty); if (a[p2]==x) return &a[p2]; } return NULL; }
閉雜湊方法的優點是節省空間。不過,無論是溢位桶,還是線性探查,都會在定址過程中浪費時間。線性
探查的探查序列如果太長,就會使一些其他元素被迫雜湊在其他位置,從而影響了其他元素的查詢效率。
如果使用開雜湊方法,那麼可以直接刪除元素。然而,使用閉雜湊方法,是不可以直接刪除元素的。假如
直接刪除,很有可能會影響其他元素的查詢。
在這種情況下,有兩種刪除方法:一種是交換法,另一種是標記法。
交換法:在刪除某元素時,不要立刻把它清除。按照線性探查函數繼續尋找,直到沒有數值為止。將遇到
的最後一個數值與它交換。當然,交換之前還要進行類似的操作,可謂“牽一髮而動全身”。
標記法:開一個標記陣列 flag[]。如果第 i 個元素被刪除了,就將 flag[i]設為 true。
1. 插入元素時,如果所在位置有標記,就把元素放到這裡,並把標記清除。
2. 查詢元素時,如果經過標記,就跳過去繼續查詢。
3. 為了雜湊表的效率,應該定期清理表中的標記(或重新雜湊所有元素)。
到此這篇關於C++資料結構雜湊表詳解的文章就介紹到這了,更多相關C++雜湊表內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45