C++數(shù)據(jù)結構哈希表詳解_第1頁
C++數(shù)據(jù)結構哈希表詳解_第2頁
C++數(shù)據(jù)結構哈希表詳解_第3頁
C++數(shù)據(jù)結構哈希表詳解_第4頁
C++數(shù)據(jù)結構哈希表詳解_第5頁
已閱讀5頁,還剩2頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

第C++數(shù)據(jù)結構哈希表詳解目錄實現(xiàn)散列函數(shù)開散列方法閉散列方法(開地址方法)刪除*

實現(xiàn)

哈希表,即散列表,可以快速地存儲和查詢記錄。理想哈希表的存儲和查詢時間都是O(1)。

本《資料》中哈希表分以下幾部分:散列函數(shù)、存儲和查找時的元素定位、存儲、查找。刪除操作因為不常用,所以只給出思想,不給出代碼。

根據(jù)實際情況,可選擇不同的散列方法。

以下代碼假設哈希表不會溢出。

//N表示哈希表長度,是一個素數(shù),M表示額外空間的大小,empty代表“沒有元素”。

constintN=9997,M=10000,empty=-1;

inta[N];

voidinit()//初始化哈希表

memset(a,empty,sizeof(a));//注意,只有empty等于0或-1時才可以這樣做!

memset(bucket,empty,sizeof(bucket));

memset(first,0,sizeof(first));

inlineinth(int);//散列函數(shù)

int*locate(int,bool);//用于存儲和查找的定位函數(shù),并返回對應位置。

//如果用于存儲,則第二個參數(shù)為true,否則為false①。

voidsave(intx)//存儲數(shù)據(jù)

int*p=locate(x,true);

if(p!=NULL)*p=x;

boolisexist(intx)//查找數(shù)據(jù)

int*p=locate(x,false);

return(p!=NULL*p==x);

}

散列函數(shù)

為了達到快速存儲和查找的目的,就必須在記錄的存儲位置和它的關鍵字之間建立一個確定的對應關系h。

這個關系h叫做哈希函數(shù)。

哈希表存取方便但存儲時容易沖突:即不同的關鍵字可以對應同一哈希地址。如何確定哈希函數(shù)和解決沖突是關鍵。以下是幾種常見的哈希函數(shù)的構造方法:

1.取余數(shù)法:h(x)=x%p(pN,且最好是素數(shù))

2.直接定址法:h(x)=x或h(x)=a*x+b

3.數(shù)字分析法:取關鍵字的若干數(shù)位(如中間兩位數(shù))組成哈希地址。

4.平方取中法:關鍵字平方后取中間幾位數(shù)組成哈希地址。

5.折疊法:將關鍵數(shù)字分割成位數(shù)相同的幾部分(最后一部分的位數(shù)可以不同)然后取幾部分的疊加和(舍去進位)作為哈希地址。

6.偽隨機數(shù)法:事先產(chǎn)生一個隨機數(shù)序列r[],然后令h(x)=r[x]。

設計哈希函數(shù)時,要注意

對關鍵碼值的分布并不了解希望選擇的散列函數(shù)在關鍵碼范圍內(nèi)能夠產(chǎn)生一個大致平均的關鍵碼值隨機分布,同時避免明顯的聚集可能性,如對關鍵碼值的高位或低位敏感的散列函數(shù)。

對關鍵碼值的分布有所了解應該使用一個依賴于分布的散列函數(shù),避免把一組相關的關鍵碼值映射到散列表的同一個槽中。

開散列方法

哈希表中難免會發(fā)生沖突。使用開散列方法可以解決這個問題。常用操作方法是拉鏈法,即相同的地址的關鍵字值均鏈入對應的鏈表中。

如果散列函數(shù)很差,就容易形成長長的鏈表,從而影響查找的效率。

下面是用拉鏈法處理沖突時的定位函數(shù):

intsize=-1;

structnode{intv;node*next;}*first[N],mem[M];

#defineNEW(p)p=mem[++size];p-next=NULL

int*locate(intx,boolins=false)

intp=h(x);

if(a[p]==x!ins)returna[p];

//處理沖突

node*q=first[p];

if(ins)

if(q==NULL)

NEW(q);

first[p]=q;

returnq-

while(q-next!=NULL)q=q-next;

node*r;NEW(r);

q-next=r;

returnr-

while(q!=NULL)

if(q-v==x)returnq-

q=q-next;

returnNULL;

}

閉散列方法(開地址方法)

處理沖突的另一種方法是為該關鍵字的記錄找到另一個空的哈希地址。在處理中可能得到一個地址序列g(i)(i=1,2,,k;0g(i)n-1),即在處理沖突時若得到的另一個哈希地址g(1)仍發(fā)生沖突,再

求下一地址g(2),若仍沖突,再求g(3)怎樣得到g(i)呢?

溢出桶法:設一個溢出桶,不管得到的哈希地址如何,一旦發(fā)生沖突,都填入溢出桶。

再哈希法:使用另外一種哈希函數(shù)來定位。

線性探查:g(i)=(h(x)+di)%N,其中h(x)為哈希函數(shù),N為哈希表長,di為增量序列。

1.線性探測再散列:di=1,2,3,,m-1

2.二次探測再散列:

3.偽隨機探測序列:事先產(chǎn)生一個隨機數(shù)序列random[],令di=random[i]。

下面是用溢出桶處理沖突時的定位函數(shù):

intbucket[M],top=-1;//用于閉散列方法(溢出桶)

int*locate(intx,boolins=false)

intp=h(x);

if(a[p]==x!ins)//在查找模式下碰到了所需的元素

returna[p];

elseif(ins)

if(a[p]==empty)//可以插入

returna[p];

else//處理沖突

returnbucket[++top];

else//到溢出桶中尋找元素

for(inti=0;i=top;i++)

if(bucket[i]==x)returnbucket[i];

returnNULL;

}

下面是用線性探查處理沖突的定位函數(shù),當然,它也可以用于再哈希法處理沖突

inlineintg(intp,inti){return(p+i)%N;}//根據(jù)需要來設計

int*locate(intx,boolins=false)

intp=h(x);

intp2,c=0;

if(a[p]==x!ins)

returna[p];

elseif(ins)

p2=g(p,c++);

}while(a[p2]!=empty);

returna[p2];

}else{

p2=g(p,c++);

}while(a[p2]!=xa[p2]!=empty);

if(a[p2]==x)returna[p2];

returnNULL;

}

閉散列方法的優(yōu)點是節(jié)省空間。不過,無論是溢出桶,還是線性探查,都會在尋址過程中浪費時間。線性

探查的探查序列如果太長,就會使一些其他元素被迫散列在其他位置,從而影響了其他元素的查找效率。

刪除*

如果使用開散列方法,那么可以直接刪除元素。然而,使用閉散列方法,是不可以直接刪除元素的。假如

直接刪除,很有可能會影響其他元素的查找。

在這種情況下,有兩種刪除方法:一種是交換法,另一種是標記法。

交換法:在刪除某元素時,不要立刻把它清除。按照線性探查函數(shù)繼續(xù)尋找,直到?jīng)]有數(shù)值為止。將遇到

的最后一個數(shù)值與它交換。當然,交換之前還要進行類似的操作,可謂牽一發(fā)而動全

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論