版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、<p><b> 數(shù) 據(jù) 結(jié) 構(gòu)</b></p><p> 課 程 設(shè) 計(jì) 說(shuō) 明 書</p><p> 2011年12月20日</p><p> 設(shè)計(jì)任務(wù)概述(包括系統(tǒng)總體框圖及功能描述)</p><p><b> 系統(tǒng)總體框圖</b></p><p>
2、<b> 問(wèn)題描述</b></p><p> 散列法中,散列函數(shù)構(gòu)造方法多種多樣,同時(shí)對(duì)于同一散列函數(shù)解決沖突的方法也可以不同。兩者是影響查詢算法性能的關(guān)鍵因素。對(duì)于幾種典型的散列函數(shù)構(gòu)造方法,做實(shí)驗(yàn)觀察,不同的解決沖突方法對(duì)查詢性能的影響。</p><p><b> 概要設(shè)計(jì)</b></p><p> 散列又稱哈
3、希或雜湊。散列法(Hashing)在表項(xiàng)的存儲(chǔ)位置與它的關(guān)鍵碼之間建立一個(gè)確定的對(duì)應(yīng)函數(shù)關(guān)系Hash(),以使每個(gè)關(guān)鍵碼與結(jié)構(gòu)中的唯一存儲(chǔ)位置相對(duì)應(yīng),該關(guān)系可用下式表示:</p><p> Address=Hash(Record.key)</p><p> 相應(yīng)的表稱為哈希表,這種方法的基本思想是:首先在元素的關(guān)鍵字k和元素的存儲(chǔ)位置p之間建立一個(gè)對(duì)應(yīng)關(guān)系H,使得p=H(k),H稱為哈
4、希函數(shù)。創(chuàng)建哈希表時(shí),把關(guān)鍵字為k的元素直接存入地址為H(k)的單元;以后當(dāng)查找關(guān)鍵字為k的元素時(shí),再利用哈希函數(shù)計(jì)算出該元素的存儲(chǔ)位置p=H(k),從而達(dá)到按關(guān)鍵字直接存取元素的目的。 </p><p> 哈希函數(shù)是一個(gè)映象,哈希函數(shù)的設(shè)定靈活,只要使得任何關(guān)鍵字所得的哈希函數(shù)值都落在表長(zhǎng)范圍之內(nèi)即可。 </p><p> 當(dāng)關(guān)鍵字集合很大時(shí),關(guān)鍵字值不同的元素可能會(huì)映
5、象到哈希表的同一地址上,即 k1≠k2,但H(k1)=H(k2),這種現(xiàn)象稱為沖突,此時(shí)稱k1和k2為同義詞。實(shí)際中,沖突是不可避免的,只能通過(guò)改進(jìn)哈希函數(shù)的性能來(lái)減少?zèng)_突。</p><p> 綜上所述,哈希法主要包括以下兩方面的內(nèi)容。</p><p> (1)如何構(gòu)造哈希函數(shù);</p><p> (2) 如何處理沖突。</p><p>
6、; 2. 本設(shè)計(jì)所采用的數(shù)據(jù)結(jié)構(gòu)(如:鏈表、棧、樹(shù)、圖等)</p><p><b> 一、散列函數(shù)</b></p><p> 通常,構(gòu)造散列函數(shù)應(yīng)該注意的幾個(gè)問(wèn)題包括:首先,散列函數(shù)的定義域必須包括需要存儲(chǔ)的全部關(guān)鍵碼,而如果散列表允許有m個(gè)地址,其值域必須在1~m-1之間;其次,散列函數(shù)計(jì)算出來(lái)的地址應(yīng)能均勻分布在整個(gè)地址空間中;再次,散列函數(shù)應(yīng)當(dāng)是盡量簡(jiǎn)單的
7、。</p><p><b> 1.直接定址法</b></p><p> 直接定址法藍(lán)顏元素關(guān)鍵碼的某個(gè)線性函數(shù)值作為該元素的散列地址(散列地址,即元素最終在字典中的存儲(chǔ)位置)。如下面的函數(shù)式:</p><p> Hash(key)=a×key+b</p><p> 式中,a,b為常數(shù)。采用該種方法,當(dāng)向
8、字典中加入某一新元素時(shí)算法自動(dòng)調(diào)用此函數(shù),以確定該元素最終的存儲(chǔ)位置。若某元素關(guān)鍵碼key為1,上式中,a=2,b=3則該元素最終會(huì)存儲(chǔ)在字典第5個(gè)位置中。</p><p> 直接定址法的優(yōu)點(diǎn)是實(shí)現(xiàn)方法簡(jiǎn)單,算法時(shí)間復(fù)雜度較小,而且不會(huì)產(chǎn)生沖突。但是,直接定址法要求散列地址空間的大小與關(guān)鍵碼集合的大小一致,而這種要求是苛刻的,一般很難實(shí)現(xiàn)。例如當(dāng)關(guān)鍵碼的范圍為1~1000000時(shí),元素散列地址的個(gè)數(shù)也要達(dá)到10
9、00000。這么大的散列地址是不合實(shí)際的。</p><p><b> 2.除留余數(shù)法</b></p><p> 設(shè)散列表中允許的地址數(shù)為m,取一個(gè)不大于m,但最接近或等于m的質(zhì)數(shù)k,或選取一個(gè)不含有小于20的質(zhì)因子的合數(shù)作為除數(shù)。利用下面的式子計(jì)算元素的散列地址的方法稱為除留余數(shù)法。</p><p> Hash(key)=key%k,k≤
10、m</p><p> 其中,“%”是整數(shù)除余法取余的運(yùn)算,要求這時(shí)的質(zhì)數(shù)不是接近2的冪。例如,當(dāng)元素的關(guān)鍵碼key為2008,散列地址總數(shù)為50,這時(shí)取k=47,則散列地址為Hash(2008)=2008%47=34,所以運(yùn)算將存儲(chǔ)在字典第47個(gè)位置中。</p><p> 除留余數(shù)法將有效縮減散列地址空間的大小,例如上例散列地址空間中只有50個(gè)有效的散列地址。除留余數(shù)法的缺點(diǎn)是極易發(fā)生
11、沖突,如關(guān)鍵碼為1914的元素經(jīng)過(guò)上述教例函數(shù)計(jì)算后也將獲得散列地址34。此時(shí)出現(xiàn)的兩個(gè)不同元素爭(zhēng)用同一存儲(chǔ)地址的情況就稱為沖突。</p><p><b> 3.平方取中法</b></p><p> 平方取中法是一種常用的實(shí)現(xiàn)散列函數(shù)的方法。</p><p> 平方取中法是一種先放大再集合的構(gòu)造方法,這種構(gòu)造模式先通過(guò)求關(guān)鍵字的平方值擴(kuò)大
12、相近數(shù)的差別,然后根據(jù)表長(zhǎng)度取中間的幾位數(shù)作為散列函數(shù)值,這種取中間數(shù)的方法是一種類隨機(jī)方案,因此也可以認(rèn)為平方取中法是一種產(chǎn)生偽隨機(jī)數(shù)的方法。因?yàn)橐粋€(gè)乘積的中間幾位數(shù)和乘數(shù)的每一位都相關(guān),所以有此產(chǎn)生的散列地址較為均勻。</p><p> 利用平方取中法實(shí)現(xiàn)散列函數(shù)的過(guò)程:首先,利用一定的編碼規(guī)則把元素的關(guān)鍵碼轉(zhuǎn)換成標(biāo)識(shí)符。然后,求出標(biāo)識(shí)符的內(nèi)碼表示并計(jì)算內(nèi)碼的平方值。最后,取內(nèi)碼平方數(shù)的中間x位作為元素最終
13、的散列地址。簡(jiǎn)而言之,即先計(jì)算構(gòu)成關(guān)鍵碼表示符的內(nèi)碼平方,然后按照散列表的大小取中間的若干位作為散列地址。</p><p> 在平方取中法中,地址空間內(nèi)散列地址的數(shù)目一般為2的k次冪,并在計(jì)算出內(nèi)碼平方的平方后,根據(jù)k的大小決定最終散列地址的位數(shù)。例如某個(gè)地址空間中散列地址的個(gè)數(shù)為128,則最終取內(nèi)碼平方中間7位作為元素最終的散列地址。</p><p><b> 4.乘余取整
14、法</b></p><p> 乘余取整法利用下面的式子計(jì)算元素的散列地址。</p><p> Hash(key)=[Z×(a×key%1)]</p><p> 其中,a為一個(gè)常數(shù)且0<a<1,Z為一個(gè)整數(shù)。式a×key%1表示a×key取小數(shù)部分,即a×key%1= a×key
15、-[ a×key] 。例如,當(dāng)元素關(guān)鍵碼為2008, 小數(shù)a為0.6180339,整數(shù)Z為10000,則散列地址計(jì)算為Hash(2008)=[10000×(0.6180339×2008%1)]=120。</p><p> 乘余取整法不但會(huì)縮減散列地址空間的大小,還能極大減小沖突情況的發(fā)生幾率。Knuth對(duì)常數(shù)a的取法做了仔細(xì)的研究,發(fā)現(xiàn)雖然a取任何值都可以,但一般取黃金分割數(shù)0.6
16、180339比較好。</p><p><b> 5.折疊法</b></p><p> 折疊法的工作方式很有趣,此方法把關(guān)鍵嗎從左至右劃分為位數(shù)相等的幾部分,每一部分的位數(shù)與散列地址數(shù)相同。當(dāng)關(guān)鍵碼位數(shù)不能被散列地址位數(shù)整除時(shí),最后一部分可取得短些。</p><p> 折疊法有兩種,即位移法和分界法。 其中,位移法所采取的具體方式是把各部分
17、的最后一位對(duì)齊相加。分界法所采用的具體方式是各部分不折斷,而沿各部分的分界來(lái)回折疊,然后對(duì)齊相加,并將相加的結(jié)果當(dāng)做散列地址。折疊法適用于關(guān)鍵碼位數(shù)很多,且每一位上數(shù)字分布比較均勻的情況。下面通過(guò)實(shí)例演示這兩種方法的工作方式。</p><p> 設(shè)關(guān)鍵碼key=987654321,散列地址為4位。位移法和分界法計(jì)算散列地址的算式如圖所示。</p><p><b> 9876&
18、lt;/b></p><p> 5432 2345</p><p> + 1 + 1</p><p> 15309 12222</p><p> 移位法
19、 分界法</p><p> 由式可見(jiàn),位移法計(jì)算結(jié)果為15309,由于散列地址為4位,所以舍去最高位數(shù)字1,元素最終的散列地址為5309。分界法結(jié)算結(jié)果為12222,同樣舍去最高位數(shù)字1,元素最終的散列地址為2222。</p><p> 二、散列沖突解決方法</p><p> 在構(gòu)造散列函數(shù)的過(guò)程中,不可避免地會(huì)出現(xiàn)沖突的情況。所謂處理沖突,就是在
20、有沖突發(fā)生時(shí),為產(chǎn)生沖突的關(guān)鍵字找到另一個(gè)地址存放該關(guān)鍵字。在解決沖突的過(guò)程中,可能會(huì)得到一系列散列地址hi(i=1,2,…,n),也就是發(fā)生第一沖突時(shí),經(jīng)過(guò)處理后得到第一新地址記作h1,如果h1仍然會(huì)沖突,則處理后得到第二個(gè)地址h2,依此類推,直到hn不產(chǎn)生沖突,將hn作為關(guān)鍵字的儲(chǔ)存地址。</p><p> 處理沖突的方法比較常用的主要有開(kāi)放定址法、再散列法和鏈地址法。</p><p&g
21、t;<b> 開(kāi)放定址法</b></p><p> 開(kāi)放定址法是解決沖突比較常用的方法。開(kāi)放定址法就是利用散列表中的空地址存儲(chǔ)產(chǎn)生沖突的關(guān)鍵字。當(dāng)沖突發(fā)生時(shí),按照下列公式處理沖突:</p><p> hi=(h(key)+di)%m,其中i=1,2,…,m-1</p><p> 其中,h(key)為散列函數(shù),m為散列表長(zhǎng),di為地址增量
22、。地址增量di可以以下三種方法獲得:</p><p> 線性探測(cè)再散列:當(dāng)沖突發(fā)生時(shí),地址增量di依次取1,2,…,m-1自然數(shù)列,即di=1,2,…,m-1。</p><p> 二次探測(cè)再散列:在沖突發(fā)生時(shí),地址增量di依次取自然數(shù)的平方,即di=12,—12,22,—22,…,k2,—k2。</p><p> 偽隨機(jī)數(shù)再散列:在沖突發(fā)生時(shí),地址增量di依次
23、取隨機(jī)數(shù)序列。</p><p> 例如,在長(zhǎng)度為14的散列表中,在將關(guān)鍵字183,123,230,91存放在散列表中的情況如圖所示。</p><p><b> Hash地址</b></p><p> 0 1 2 3 4 5 6 7 8 9 10 11 12 13<
24、;/p><p> 散列表沖突發(fā)生前示意圖</p><p> 當(dāng)要插入關(guān)鍵字149時(shí),有散列函數(shù)h(149)=149%13=6,而單元6已經(jīng)存在關(guān)鍵字,產(chǎn)生沖突,利用線性探測(cè)再散列法解決沖突,即h1=(6+1)%14=7,將149儲(chǔ)存在單元7中,如圖所示。</p><p><b> Hash地址</b></p><p>
25、 0 1 2 3 4 5 6 7 8 9 10 11 12 13</p><p> 插入關(guān)鍵字149后的示意圖</p><p> 當(dāng)要插入關(guān)鍵字227時(shí),由散列函數(shù)h(227)=227%13=6,而單元6已經(jīng)存在關(guān)鍵字,產(chǎn)生沖突,利用線性探測(cè)再散列法解決沖突,即h1=(6+1)%14=7,仍然沖突,繼續(xù)利用線性
26、探測(cè)法,即h2=(6+2)%14=8,單元8空閑,因此將227存儲(chǔ)在單元8中,如圖所示。</p><p><b> Hash地址</b></p><p> 0 1 2 3 4 5 6 7 8 9 10 11 12 13</p><p> 插入關(guān)鍵字227后的示意圖&
27、lt;/p><p> 當(dāng)然,在沖突發(fā)生時(shí),也可以利用二次探測(cè)再散列解決沖突。在圖11.33中,如果要插入關(guān)鍵字227,因?yàn)楫a(chǎn)生沖突,利用二次探測(cè)再散列法解決沖突,即h1=(6+1)%14=7,再次產(chǎn)生沖突時(shí),有h2=(6—1)%14=5,將227儲(chǔ)存在單元5中,如圖所示。</p><p><b> Hash地址</b></p><p> 0
28、 1 2 3 4 5 6 7 8 9 10 11 12 13</p><p> 利用二次探測(cè)再散列解決沖突示意圖</p><p><b> 再散列法</b></p><p> 再散列法就是在沖突發(fā)生時(shí),利用另外一個(gè)散列函數(shù)再次求散列函數(shù)的地址,直到?jīng)_突不再發(fā)生為止,即
29、</p><p> hi=rehash(key),i=1,2…,n</p><p> 其中,rehash表示不同的散列函數(shù)。這種再散列法一般不容易再次發(fā)生沖突,但是需要事先構(gòu)造多個(gè)散列函數(shù),這是一件不太容易的也不現(xiàn)實(shí)的事情。</p><p><b> 鏈地址法</b></p><p> 數(shù)組的特點(diǎn)是:尋址容易,插
30、入和刪除困難;而鏈表的特點(diǎn)是:尋址困難,插入和刪除容易。那么我們能不能綜合兩者的特性,做出一種尋址容易,插入刪除也容易的數(shù)據(jù)結(jié)構(gòu)?答案是肯定的,這就是我們要提起的哈希表,哈希表有多種不同的實(shí)現(xiàn)方法,我接下來(lái)解釋的是最常用的一種方法——鏈地址法,我們可以理解為“鏈表的數(shù)組”,如圖:</p><p> 左邊很明顯是個(gè)數(shù)組,數(shù)組的每個(gè)成員包括一個(gè)指針,指向一個(gè)鏈表的頭,當(dāng)然這個(gè)鏈表可能為空,也可能元素很多。我們根據(jù)元
31、素的一些特征把元素分配到不同的鏈表中去,也是根據(jù)這些特征,找到正確的鏈表,再?gòu)逆湵碇姓页鲞@個(gè)元素。三、 哈希法性能分析</p><p> 由于沖突的存在,哈希法仍需進(jìn)行關(guān)鍵字比較,因此仍需用平均查找長(zhǎng)度來(lái)評(píng)價(jià)哈希法的查找性能。哈希法中影響關(guān)鍵字比較次數(shù)的因素有三個(gè):哈希函數(shù)、處理沖突的方法以及哈希表的裝填因子。哈希表的裝填因子α的定義如下: </p><p><b> ■線
32、性探測(cè)再散列</b></p><p><b> 查找成功時(shí) </b></p><p><b> 查找失敗時(shí) </b></p><p> ■偽隨機(jī)探測(cè)再散列、 二次探測(cè) </p><p><b> 查找成功時(shí) </b></p><p>
33、<b> 查找失敗時(shí) </b></p><p><b> ■鏈址法</b></p><p><b> 查找成功時(shí)</b></p><p><b> 查找失敗時(shí)</b></p><p> 從以上討論可知:哈希表的平均查找長(zhǎng)度是裝填因子α的函數(shù),而與
34、待散列元素?cái)?shù)目n無(wú)關(guān)。因此,無(wú)論元素?cái)?shù)目n有多大,都能通過(guò)調(diào)整α,使哈希表的平均查找長(zhǎng)度較小。 </p><p> 3. 功能模塊詳細(xì)設(shè)計(jì)</p><p> 3.1 詳細(xì)設(shè)計(jì)思想</p><p> (1)程序中結(jié)構(gòu)體的定義</p><p> typedef struct</p><p><b> {
35、</b></p><p><b> int key;</b></p><p><b> int si;</b></p><p> }HashTable1;</p><p> typedef struct node</p><p><b> {&
36、lt;/b></p><p><b> int key;</b></p><p><b> int si;</b></p><p> struct node *next;</p><p><b> }Node;</b></p><p>
37、typedef struct</p><p><b> {</b></p><p> Node *link;</p><p> }HashTable2;</p><p> typedef struct </p><p><b> {</b></p>&
38、lt;p> int * elem[HashSize];</p><p> int count;</p><p><b> int size;</b></p><p> }HashTable3;</p><p><b> (2) 主函數(shù)模塊</b></p><p&g
39、t; void main()</p><p><b> {</b></p><p><b> int data;</b></p><p> HashTable1 hash1[HashSize];</p><p> HashTable2 * hash2[HashSize];</p>
40、;<p> HashTable3 * ha;</p><p> ha=(HashTable3 *)malloc(sizeof(HashTable3));</p><p> for(int i=0;i<HashSize;i++)</p><p> ha->elem[i]=NULL;</p><p> ha-&
41、gt;count=0;</p><p> ha->size=HashSize;</p><p> int a[MaxSize];</p><p><b> while(1)</b></p><p><b> {</b></p><p> printf(&quo
42、t;\n ┏━━━━━━━━━━━━━━━┓ "); </p><p> printf("\n ┃ 歡迎使用本系統(tǒng) ┃ "); </p><p> printf("\n ┏〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓"); </p><p>
43、; printf("\n ┃★ ★ ★ ★ ★ ★散列法的實(shí)驗(yàn)研究★ ★ ★ ★ ★ ★");</p><p> printf("\n ┃ 【1】. 添加數(shù)據(jù)信息 【2】 數(shù)據(jù)的輸出 ┃");</p><p> printf("\n ┃ 【3】. 建立哈希表(線性再散列)
44、 ");</p><p> printf("\n ┃ 【4】. 建立哈希表(二次探測(cè)再散列) ");</p><p> printf("\n ┃ 【5】. 建立哈希表(鏈地址法) ");</p><p> printf("\n
45、 ┃ 【6】. 線性再散列法查找 ┃");</p><p> printf("\n ┃ 【7】. 二次探測(cè)再散列法查找 ┃");</p><p> printf("\n ┃ 【8】. 鏈地址法查找
46、┃");</p><p> printf("\n ┃ 【0】. 退出程序 ┃");</p><p> printf("\n ┗〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓");</p><p> printf("\n")
47、;</p><p> printf("\n");</p><p> printf("請(qǐng)輸入一個(gè)任務(wù)選項(xiàng)>>>");</p><p><b> int x;</b></p><p> scanf("%d",&x);</p&g
48、t;<p><b> switch(x)</b></p><p><b> {</b></p><p><b> case 1:</b></p><p> GetIn (a);break;</p><p><b> case 2:</b&
49、gt;</p><p> GetOut(a);break;</p><p><b> case 3:</b></p><p> CreateHashTable1(hash1,a,num);break;</p><p><b> case 4:</b></p><p>
50、 CreateHash3(ha,a,num);break;</p><p><b> case 5:</b></p><p> CreateHashTable2(hash2,a,num);break;</p><p><b> case 6:</b></p><p> printf(&qu
51、ot;請(qǐng)輸入你查找的數(shù)據(jù):");</p><p> scanf("%d",&data);</p><p> SearchHash1(hash1,data);break;</p><p><b> case 7:</b></p><p> printf("請(qǐng)輸入你查找
52、的數(shù)據(jù):");</p><p> scanf("%d",&data);</p><p> SearchHash3(ha,data);break;</p><p><b> case 8:</b></p><p> printf("請(qǐng)輸入你查找的數(shù)據(jù):");
53、</p><p> scanf("%d",&data);</p><p> SearchHash2(hash2,data,num);break;</p><p> case 0:exit(-1);</p><p><b> }</b></p><p><b
54、> } </b></p><p><b> }</b></p><p><b> 3.2 核心代碼</b></p><p> #include<stdio.h></p><p> #include<stdlib.h></p><
55、p> #define HashSize 53</p><p> #define MaxSize 20</p><p> typedef struct</p><p><b> {</b></p><p><b> int key;</b></p><p>&l
56、t;b> int si;</b></p><p> }HashTable1;</p><p> void CreateHashTable1(HashTable1 *H,int *a,int num)//哈希表線性探測(cè)在散列;</p><p><b> {</b></p><p> int i,
57、d,cnt;</p><p> for(i=0;i<HashSize;i++)</p><p><b> {</b></p><p> H[i].key=0;</p><p> H[i].si=0;</p><p><b> }</b></p>
58、<p> for(i=0;i<num;i++)</p><p><b> {</b></p><p><b> cnt=1;</b></p><p> d=a[i]%HashSize;</p><p> if(H[d].key==0)</p><p>
59、;<b> {</b></p><p> H[d].key=a[i];</p><p> H[d].si=cnt;</p><p><b> }</b></p><p><b> else</b></p><p><b> {<
60、;/b></p><p><b> do</b></p><p><b> {</b></p><p> d=(d+1)%HashSize;</p><p><b> cnt++;</b></p><p> }while(H[d].key
61、!=0);</p><p> H[d].key=a[i];</p><p> H[d].si=cnt;</p><p><b> }</b></p><p><b> }</b></p><p> printf("\n線性再探索哈希表已建成!")
62、;</p><p><b> }</b></p><p> void SearchHash1(HashTable1 *h,int data)</p><p><b> {</b></p><p><b> int d;</b></p><p>
63、 d=data%HashSize;</p><p> if(h[d].key==data)</p><p> printf("數(shù)字%d的探查次數(shù)為:%d\n",h[d].key,h[d].si);</p><p><b> else</b></p><p><b> {</b&
64、gt;</p><p><b> do</b></p><p> d=(d+1)%HashSize;</p><p> while(h[d].key!=data && d<HashSize);</p><p> if(d<HashSize)</p><p>
65、printf("數(shù)字%d的探查次數(shù)為:%d\n",h[d].key,h[d].si);</p><p><b> else</b></p><p> printf("沒(méi)有查找到你所輸入的數(shù)\n");</p><p><b> }</b></p><p>
66、<b> }</b></p><p> typedef struct node</p><p><b> {</b></p><p><b> int key;</b></p><p><b> int si;</b></p>&l
67、t;p> struct node *next;</p><p><b> }Node;</b></p><p> typedef struct</p><p><b> {</b></p><p> Node *link;</p><p> }HashTab
68、le2;</p><p> void CreateHashTable2(HashTable2 *ht[],int *a,int num)//哈希表鏈地址;</p><p><b> {</b></p><p> int i,d,cnt;</p><p> Node *s,*q;</p><p&
69、gt; for(i=0;i<num; i++)</p><p><b> {</b></p><p> ht[i]=(HashTable2 *)malloc(sizeof(HashTable2));</p><p> ht[i]->link=NULL;</p><p><b> }<
70、/b></p><p> for(i=0;i<num;i++)</p><p><b> {</b></p><p><b> cnt=1;</b></p><p> s=(Node *)malloc(sizeof(Node));</p><p> s-
71、>key=a[i];s->next=NULL;</p><p> d=a[i]%num;</p><p> if(ht[d]->link==NULL)</p><p><b> {</b></p><p> ht[d]->link=s;</p><p> s-&g
72、t;si=cnt;</p><p><b> }</b></p><p><b> else</b></p><p><b> {</b></p><p> q=ht[d]->link;</p><p> while(q->next
73、!=NULL)</p><p><b> {</b></p><p> q=q->next;cnt++;</p><p><b> }</b></p><p><b> cnt++;</b></p><p> s->si=cnt;&
74、lt;/p><p> q->next=s;</p><p><b> }</b></p><p><b> }</b></p><p><b> }</b></p><p> void SearchHash2(HashTable2 * h[]
75、,int data,int num)</p><p><b> {</b></p><p><b> int d;</b></p><p><b> Node *q;</b></p><p> d=data%num;</p><p> q=h[
76、d]->link;</p><p> while(q->key!=data && q->next!=NULL)</p><p> q=q->next;</p><p> if(q->next!=NULL)</p><p> printf("數(shù)字%d的查找次數(shù)為:%d\n"
77、;,q->key,q->next);</p><p><b> else</b></p><p> printf("沒(méi)有找到你要查找的那個(gè)數(shù)\n");</p><p><b> }</b></p><p> typedef struct </p>
78、<p><b> {</b></p><p> int * elem[HashSize];</p><p> int count;</p><p><b> int size;</b></p><p> }HashTable3;</p><p> in
79、t Collision(int p,int &c)//二次探測(cè)再散列法解決沖突</p><p><b> {</b></p><p><b> int i,q;</b></p><p><b> i=c/2+1;</b></p><p> while(i<
80、HashSize)</p><p><b> {</b></p><p> if(c%2==0)</p><p><b> {</b></p><p><b> c++;</b></p><p> q=(p+i*i)%HashSize;<
81、/p><p><b> if(q>=0)</b></p><p><b> return q;</b></p><p><b> else</b></p><p><b> i=c/2+1;</b></p><p><
82、;b> }</b></p><p><b> else</b></p><p><b> {</b></p><p> q=(p-i*i)%HashSize;</p><p><b> c++;</b></p><p> i
83、f(q>=0)return q;</p><p> else i=c/2+1;</p><p><b> }</b></p><p><b> }</b></p><p> return (-1);</p><p><b> }</b>&
84、lt;/p><p> void CreateHash3(HashTable3 *h,int *a,int num)//二次探索表</p><p><b> {</b></p><p> int i,p=-1,c,pp;</p><p> for(i=0;i<num;i++)</p><p&g
85、t;<b> {</b></p><p><b> c=0;</b></p><p> p=a[i]%HashSize;</p><p><b> pp=p;</b></p><p> while(h->elem[pp]!=NULL)</p>&l
86、t;p><b> {</b></p><p> pp=Collision(p,c);</p><p><b> if(pp<0)</b></p><p><b> {</b></p><p> printf("第%d個(gè)記錄無(wú)法解決沖突\n&quo
87、t;,i+1);</p><p><b> continue;</b></p><p><b> }</b></p><p><b> }</b></p><p> h->elem[pp]=&(a[a[i]]);</p><p>
88、 h->count++;</p><p> printf("第%d個(gè)記錄沖突次數(shù)為%d\n",i+1,c);</p><p><b> }</b></p><p> printf("\n建表完成!\n此哈希表容量為%d,當(dāng)前表內(nèi)存儲(chǔ)的記錄個(gè)數(shù)%d.\n",HashSize,h->coun
89、t);</p><p><b> }</b></p><p> void SearchHash3(HashTable3 *h,int data)//哈希表二次探索再散列查找</p><p><b> {</b></p><p> int c=0,p,pp;</p><p&
90、gt; p=data%HashSize;</p><p><b> pp=p;</b></p><p> while((h->elem[pp]!=NULL)&&(*(h->elem[pp])!=data))</p><p> pp=Collision(p,c);</p><p> i
91、f((h->elem[pp]!=NULL)&&(*(h->elem[pp])==data))</p><p> printf("\n查找成功!\n查找沖突次數(shù)為%d:",c);</p><p><b> else</b></p><p> printf("\n沒(méi)有查到此數(shù)!\n&q
92、uot;);</p><p><b> }</b></p><p><b> int num;</b></p><p> void GetIn(int *a)</p><p><b> {</b></p><p> printf("輸
93、入添加的個(gè)數(shù):");</p><p> scanf("%d",&num);</p><p> for(int i=0;i<num;i++)</p><p> scanf("%d",&a[i]);</p><p> printf("數(shù)據(jù)已經(jīng)輸入完畢!\n&
94、quot;);</p><p><b> }</b></p><p> void GetOut(int *a)</p><p><b> {</b></p><p> printf("你所輸入的數(shù)據(jù):");</p><p> for(int i=
95、0;i<num;i++)</p><p> printf("%d,",a[i]);</p><p> printf("\n輸出已完畢!");</p><p><b> }</b></p><p> void main()</p><p><
96、;b> {</b></p><p><b> int data;</b></p><p> HashTable1 hash1[HashSize];</p><p> HashTable2 * hash2[HashSize];</p><p> HashTable3 * ha;</p>
97、;<p> ha=(HashTable3 *)malloc(sizeof(HashTable3));</p><p> for(int i=0;i<HashSize;i++)</p><p> ha->elem[i]=NULL;</p><p> ha->count=0;</p><p> ha-&g
98、t;size=HashSize;</p><p> int a[MaxSize];</p><p><b> while(1)</b></p><p><b> {</b></p><p> printf("\n ┏━━━━━━━━━━━━━━━┓ "
99、); </p><p> printf("\n ┃ 歡迎使用本系統(tǒng) ┃ "); </p><p> printf("\n ┏〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓┓"); </p><p> printf("\n ┃★ ★ ★ ★ ★ ★散列法的實(shí)驗(yàn)研
100、究★ ★ ★ ★ ★ ★┃");</p><p> printf("\n ┃ 【1】. 添加數(shù)據(jù)信息 【2】 數(shù)據(jù)的輸出 ┃");</p><p> printf("\n ┃ 【3】. 建立哈希表(線性再散列) ┃");</p><p> print
101、f("\n ┃ 【4】. 建立哈希表(二次探測(cè)再散列) ┃");</p><p> printf("\n ┃ 【5】. 建立哈希表(鏈地址法) ┃");</p><p> printf("\n ┃ 【6】. 線性再散列法查找
102、 ┃");</p><p> printf("\n ┃ 【7】. 二次探測(cè)再散列法查找 ┃");</p><p> printf("\n ┃ 【8】. 鏈地址法查找 ┃");</p><p> print
103、f("\n ┃ 【0】. 退出程序 ┃");</p><p> printf("\n ┗〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓┛");</p><p> printf("\n");</p><p> printf("
104、;\n");</p><p> printf("請(qǐng)輸入一個(gè)任務(wù)選項(xiàng)>>>");</p><p><b> int x;</b></p><p> scanf("%d",&x);</p><p><b> switch(x)<
105、;/b></p><p><b> {</b></p><p><b> case 1:</b></p><p> GetIn (a);break;</p><p><b> case 2:</b></p><p> GetOut(a);
106、break;</p><p><b> case 3:</b></p><p> CreateHashTable1(hash1,a,num);break;</p><p><b> case 4:</b></p><p> CreateHash3(ha,a,num);break;</p
107、><p><b> case 5:</b></p><p> CreateHashTable2(hash2,a,num);break;</p><p><b> case 6:</b></p><p> printf("請(qǐng)輸入你查找的數(shù)據(jù):");</p><
108、;p> scanf("%d",&data);</p><p> SearchHash1(hash1,data);break;</p><p><b> case 7:</b></p><p> printf("請(qǐng)輸入你查找的數(shù)據(jù):");</p><p> s
109、canf("%d",&data);</p><p> SearchHash3(ha,data);break;</p><p><b> case 8:</b></p><p> printf("請(qǐng)輸入你查找的數(shù)據(jù):");</p><p> scanf("%
110、d",&data);</p><p> SearchHash2(hash2,data,num);break;</p><p> case 0:exit(-1);</p><p><b> }</b></p><p><b> } </b></p><p&
111、gt;<b> }</b></p><p> 3.3 程序運(yùn)行結(jié)果(拷屏)</p><p> 利用線性再散列法,二次探查再散列,鏈地址法解決沖突</p><p> 4. 課程設(shè)計(jì)心得、存在問(wèn)題及解決方法</p><p><b> (1) 收獲</b></p><p&g
112、t; 通過(guò)本次課程設(shè)計(jì),使我對(duì)計(jì)算機(jī)語(yǔ)言有了更深一層的了解,也使我對(duì)算法的運(yùn)用有了更多的體會(huì),對(duì)算法和生活的聯(lián)系也有了更多的體會(huì)。更進(jìn)一步了解和熟悉了關(guān)于哈希表的創(chuàng)建和運(yùn)用。現(xiàn)在,計(jì)算機(jī)領(lǐng)域,他只向我展現(xiàn)了冰山一角,以后我會(huì)繼續(xù)探索。好的算法源于我們不斷的思考,思考源于我們對(duì)夢(mèng)想的追尋。</p><p><b> (2) 心得體會(huì)</b></p><p> 在
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫(kù)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 課程設(shè)計(jì)說(shuō)明書
- 課程設(shè)計(jì)說(shuō)明書
- 前門課程設(shè)計(jì)說(shuō)明書
- javaweb課程設(shè)計(jì)說(shuō)明書
- 后蓋課程設(shè)計(jì)說(shuō)明書
- 鍋爐課程設(shè)計(jì)說(shuō)明書
- 空調(diào)課程設(shè)計(jì)說(shuō)明書
- 蝸輪課程設(shè)計(jì)說(shuō)明書
- 采礦課程設(shè)計(jì)說(shuō)明書
- 機(jī)床課程設(shè)計(jì)說(shuō)明書
- caxa課程設(shè)計(jì)說(shuō)明書
- 化工課程設(shè)計(jì)說(shuō)明書
- vb課程設(shè)計(jì)說(shuō)明書
- 課程設(shè)計(jì)說(shuō)明書.doc
- 課程設(shè)計(jì)說(shuō)明書.doc
- 課程設(shè)計(jì)說(shuō)明書.doc
- 課程設(shè)計(jì)說(shuō)明書.doc
- 課程設(shè)計(jì)說(shuō)明書.doc
- 課程設(shè)計(jì)說(shuō)明書.doc
- 課程設(shè)計(jì)說(shuō)明書.doc
評(píng)論
0/150
提交評(píng)論