編程實驗篇--線性探測哈希表

線性探測哈希表性能測試實驗報告

1. 實驗目的

  • 編程實現線性探測哈希表。
  • 編程測試線性探測哈希表。
  • 了解線性探測哈希表的性能特征,并運行程序進行驗證。

2. 實驗背景與理論基礎

哈希表是一種高效的數據結構,用于實現符號表(Symbol Table),支持快速的插入、查找和刪除操作。當不同的鍵哈希到同一個地址時,會發生沖突。線性探測(Linear Probing)是一種常見的開放尋址(Open Addressing)沖突解決策略,它通過探測當前位置的下一個連續槽位來尋找空閑位置。

線性探測的性能分析主要關注查找操作所需的平均探測次數。根據教材,當沖突通過線性探測解決時,哈希表大小為 M M M 且包含 N = α M N = \alpha M N=αM 個鍵時,其平均探測次數有以下理論近似值(Property 14.3):

  • 查找失敗 (misses) 的平均探測次數:
    1 2 ( 1 + 1 ( 1 ? α ) 2 ) \frac{1}{2}\left(1 + \frac{1}{(1-\alpha)^2}\right) 21?(1+(1?α)21?)

其中, α = N / M \alpha = N/M α=N/M 是哈希表的負載因子。

此外,查找失敗的平均成本也可以通過分析哈希表中形成的聚簇(clusters)來計算:
查找失敗的平均成本 = 1 + N 2 M + ∑ i k t i 2 2 M \text{查找失敗的平均成本} = 1+\frac{N}{2M}+\frac{\sum_i^kt_i^2}{2M} 查找失敗的平均成本=1+2MN?+2Mik?ti2??
其中, t i t_i ti? 是插入過程中形成的第 i i i 個聚簇的長度,總共有 k k k 個聚簇。

本次實驗將重點關注查找失敗的平均成本

根據實驗設計,我們將 N / 2 N/2 N/2 個隨機整數插入到大小為 N N N 的哈希表中,因此負載因子 α = ( N / 2 ) / N = 0.5 \alpha = (N/2) / N = 0.5 α=(N/2)/N=0.5。代入查找失敗的理論公式,可計算出在此負載因子下的理論平均成本:
理論平均成本 = 1 2 ( 1 + 1 ( 1 ? 0.5 ) 2 ) = 2.5 \text{理論平均成本} = \frac{1}{2}\left(1 + \frac{1}{(1-0.5)^2}\right)= 2.5 理論平均成本=21?(1+(1?0.5)21?)=2.5
因此,對于本次實驗中的所有測試用例,理論上的查找失敗平均成本應為 2.5 次探測。

3. 實驗設計與實現

實驗任務: 編寫程序實現 Exercise 14.28,即插入 N / 2 N/2 N/2 個隨機整數到大小為 N N N 的哈希表中,并計算查找失敗的平均成本。

Exercise1428

程序實現

  1. 哈希表結構: 使用數組 st 作為哈希表,存儲 Item 指針。Item 包含 KeyValue
  2. 初始化 (STinit): 根據傳入的最大元素數量 max,將哈希表大小 M 設置為 2 * max。由于實驗要求插入 N / 2 N/2 N/2 個元素到大小為 N N N 的表,所以 M 在這里對應練習題中的 N N N
  3. 哈希函數 (hash): 采用簡單的整數哈希函數 (11 * x) % M
  4. 插入 (STinsert): 采用線性探測解決沖突。如果初始哈希位置被占用,則向右(索引遞增)探測直到找到空槽位。
  5. 簇分析 (analyze_clusters):
    • 遍歷哈希表,識別所有形成的聚簇。一個聚簇被定義為連續的被占用槽位序列。
    • 計算每個聚簇的長度 t i t_i ti?
    • 累加所有聚簇長度的平方和 ∑ t i 2 \sum t_i^2 ti2?
    • 根據公式 1 + N 2 M + ∑ i k t i 2 2 M 1+\frac{N}{2M}+\frac{\sum_i^kt_i^2}{2M} 1+2MN?+2Mik?ti2?? 計算出基于簇長度的查找失敗平均成本(即實驗值 average_cost)。
    • 同時,根據負載因子 α = N / M \alpha = N/M α=N/M 和 Property 14.3 的公式計算理論平均成本(theory_cost)。
    • 打印實驗值和理論值以便對比。
  6. 測試用例: 設計了四組測試,分別對應 N = 10 3 , 10 4 , 10 5 , 10 6 N=10^{3}, 10^{4}, 10^{5}, 10^{6} N=103,104,105,106。在每個測試中,向表中插入 N / 2 N/2 N/2 個隨機整數。
    • test_insert_1000(): M=1000, 插入 500 個隨機數。
    • test_insert_10000(): M=10000, 插入 5000 個隨機數。
    • test_insert_100000(): M=100000, 插入 50000 個隨機數。
    • test_insert_1000000(): M=1000000, 插入 500000 個隨機數。
  7. 隨機數生成: 使用 srand(time(NULL)) 進行隨機數播種,以確保每次程序運行生成不同的隨機序列。

4. 實驗結果

程序運行后,得到以下輸出:

Table(M=1000):the average cost of unsuccessful search in that table is 1.558000, theory cost: 2.500000
Table(M=10000):the average cost of unsuccessful search in that table is 2.488200, theory cost: 2.500000
Table(M=100000):the average cost of unsuccessful search in that table is 2.481630, theory cost: 2.500000
Table(M=1000000):the average cost of unsuccessful search in that table is 2.503940, theory cost: 2.500000

5. 結果分析

這些結果清晰地展示了線性探測哈希表在不同規模下,查找失敗平均成本的實驗值與理論值之間的關系。

  1. M=1000 (表大小為 1000,插入 500 個元素):

    • 實驗平均成本為 1.558000,而理論平均成本為 2.500000。
    • 分析: 在這種較小規模的哈希表中,實驗結果與理論值存在較明顯的偏差。這是因為理論平均值是基于大量隨機插入的統計結果,而單次運行(尤其在數據量較小的情況下)可能因隨機數的具體序列偶然地形成了比平均情況更少或更短的簇,從而導致實際觀察到的探測次數低于理論預測。這反映了小樣本量下的統計波動性。
  2. M=10000 (表大小為 10000,插入 5000 個元素):

    • 實驗平均成本為 2.488200,理論平均成本為 2.500000。
    • 分析: 實驗結果與理論值已非常接近。這表明隨著哈希表規模的增大(以及插入元素數量的增加),線性探測在隨機插入下的實際行為開始向其統計平均值收斂。隨機性帶來的局部波動效應被更大量的數據所平均。
  3. M=100000 (表大小為 100000,插入 50000 個元素):

    • 實驗平均成本為 2.481630,理論平均成本為 2.500000。
    • 分析: 實驗結果繼續保持與理論值的高度吻合,進一步證實了這種收斂性。
  4. M=1000000 (表大小為 1000000,插入 500000 個元素):

    • 實驗平均成本為 2.503940,理論平均成本為 2.500000。
    • 分析: 實驗結果與理論值幾乎完全一致,僅存在微小的正常波動。這完美地展示了當數據量足夠大時,線性探測在半滿情況下的性能是如何精確符合理論模型的。

6. 結論

該程序 Exercise1428 的運行結果有力地驗證了以下幾點:

  • 理論公式的有效性: 教材中關于線性探測查找失敗平均成本的理論公式 (Property 14.3) 在實踐中是準確的預測器。通過實驗結果與理論值的對比,可以清晰地看到二者的高度吻合,尤其是在大規模數據量下。
  • 規模效應: 隨著哈希表規模的增大,線性探測在隨機插入條件下的實際性能會越來越接近其理論平均值。小規模表的結果可能因隨機性而有較大波動,但隨著 N N N 的增長,這種波動逐漸減小。
  • 線性探測的特性: 即使在負載因子為 0.5 0.5 0.5(即哈希表半滿)這種相對較低的情況下,查找失敗的平均成本也不是理想的 1 1 1 次探測,而是大約 2.5 2.5 2.5 次。這反映了線性探測固有的“初級聚簇”(primary clustering)問題:即使表不滿,連續的占用槽位也會導致查找路徑變長,從而產生額外的探測成本。這也解釋了為什么在線性探測中,通常建議將負載因子保持在更低的水平(例如,遠小于 0.5),以避免性能隨著表接近滿而急劇下降。

本次實驗成功地編程實現了線性探測哈希表,并通過對比實驗結果與理論預測,加深了對線性探測性能特征及其“初級聚簇”問題的理解。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/82982.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/82982.shtml
英文地址,請注明出處:http://en.pswp.cn/web/82982.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用Python提取PDF元數據的完整指南

PDF文檔中包含著豐富的元數據信息,這些信息對文檔管理和數據分析具有重要意義。本文將詳細介紹如何利用Python高效提取PDF元數據,并對比主流技術方案的優劣。 ## 一、PDF元數據概述 PDF元數據(Metadata)是包含在文檔中的結構化信…

【量化】策略交易類型

通過查找相關資料,這里羅列了一些常見的策略交易類型,如下: 📊 技術分析類策略 均線交叉策略(SMA、EMA)動量策略(Momentum)相對強弱指數策略(RSI)隨機指標策…

【Go語言基礎【17】】切片:一種動態數組

文章目錄 零、概述一、切片基礎1、切片的結構2、切片的創建方式3、切片的操作與擴容 二、切片的拷貝與共享內存三、切片作為函數參數 Go語言的切片(slice)是一種動態數組,提供了靈活、高效的元素序列操作。它基于底層數組實現,通過…

MybatisPlus使用DB靜態工具出現找不到實體類的報錯

報錯:Not Found TableInfoCache. 原因在于沒有創建實體類對應的mapper,并且該mapper還必須繼承baseMapper。 猜測大概的原理應該是DB會去查找實體類對應的mapper,然后通過mapper去查找對應的實體類。

Linux nano命令的基本使用

參考資料 GNU nanoを使いこなすnano基礎 目錄 一. 簡介二. 文件打開2.1 普通方式打開文件2.2 只讀方式打開文件 三. 文件查看3.1 打開文件時,顯示行號3.2 翻頁查看 四. 文件編輯4.1 Ctrl K 復制 和 Ctrl U 粘貼4.2 Alt/Esc U 撤回 五. 文件保存與退出5.1 Ctrl …

LLMs 系列科普文(15)

前面 14 篇文章,就是本系列科普文中想介紹的大部分技術內容。重點講述了訓練這些模型的三個主要階段和范式:預訓練、監督微調和強化學習。 我向你們展示了這些步驟大致對應于我們已用于教導兒童的過程。具體來說,我們將預訓練比作通過閱讀說…

深入理解匯編語言中的順序與分支結構

本文將結合Visual Studio環境配置、順序結構編程和分支結構實現,全面解析匯編語言中的核心編程概念。通過實際案例演示無符號/有符號數處理、分段函數實現和邏輯表達式短路計算等關鍵技術。 一、匯編環境配置回顧(Win32MASM) 在Visual Studi…

Selenium4+Python的web自動化測試框架

一、什么是Selenium? Selenium是一個基于瀏覽器的自動化測試工具,它提供了一種跨平臺、跨瀏覽器的端到端的web自動化解決方案。Selenium主要包括三部分:Selenium IDE、Selenium WebDriver 和Selenium Grid。 Selenium IDE:Firefo…

React 樣式方案與狀態方案初探

React 本身只提供了基礎 UI 層開發范式,其他特性的支持需要借助相關社區方案實現。本文將介紹 React 應用體系中樣式方案與狀態方案的主流選擇,幫助開發者根據項目需求做出合適的選擇。 1. React 樣式方案 1.1. 內聯樣式 (Inline Styles) 通過 style …

PHP中如何定義常量以及常量和變量的主要區別

在PHP編程中,常量和變量是存儲數據的兩種重要方式。常量在定義后值不能改變,而變量的值可以在程序執行過程中發生變化。本文將詳細介紹如何在PHP中定義常量,并深入探討常量和變量的主要區別。 一、PHP中定義常量 1. 使用 define 函數定義常…

奈飛工廠官網,國內Netflix影視在線看|中文網頁電腦版入口

奈飛工廠是一個專注于提供免費Netflix影視資源的在線播放平臺,致力于為國內用戶提供的Netflix熱門影視內容。該平臺的資源與Netflix官網基本同步,涵蓋電影、電視劇、動漫和綜藝等多個領域。奈飛工廠的界面簡潔流暢,資源分類清晰,方…

CMS內容管理系統的設計與實現:架構設計

一、整體架構方案 &#xff08;一&#xff09;架構方案選擇&#xff08;根據項目規模&#xff09; 1. 中小型項目推薦方案&#xff08;團隊<10人&#xff09; #mermaid-svg-cjzaHpptY8pYWnzo {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:1…

嵌入式里的時間魔法:RTC 與 BKP 深度拆解

文章目錄 RTC實時時鐘與BKPUnix時間戳UTC/GMT時間戳轉換時間戳轉換BKP簡介BKP基本結構1. 電池供電模塊&#xff08;VBAT 輸入&#xff09;2. 侵入檢測模塊&#xff08;TAMPER 輸入&#xff09;3. 時鐘輸出模塊&#xff08;RTC 輸出&#xff09;4. 內部寄存器組 RTC簡介RTC時鐘源…

STC8H系列 驅動步進電機

STC8H 驅動步進電機 一、引言二、硬件設計三、軟件設計Step_Motor2.c文件Step_ Motor2.h文件 一、引言 眾所周知STC8H系列有兩個PWM&#xff0c;分別為PWMA和PWMB外設模塊&#xff0c;我全都用上&#xff0c;豈不是就有兩個帶動電機的脈沖信號&#xff1f;&#xff01;哈哈哈哈…

Python高階函數:從入門到精通

目錄 Python高階函數詳解&#xff1a;從概念到高級應用引言&#xff1a;函數式編程的魅力一、高階函數基礎概念1.1 什么是高階函數1.2 Python中的一等函數 二、內置高階函數詳解2.1 map函數&#xff1a;數據轉換利器2.2 filter函數&#xff1a;數據篩選專家2.3 reduce函數&…

騰訊開源視頻生成工具 HunyuanVideo-Avatar,上傳一張圖+一段音頻,就能讓圖中的人物、動物甚至虛擬角色“活”過來,開口說話、唱歌、演相聲!

騰訊混元團隊提出的 HunyuanVideo-Avatar 是一個基于多模態擴散變換器&#xff08;MM-DiT&#xff09;的模型&#xff0c;能夠生成動態、情緒可控和多角色對話視頻。支持僅 10GB VRAM 的單 GPU運行&#xff0c;支持多種下游任務和應用。例如生成會說話的虛擬形象視頻&#xff0…

DeepSeek-R1-0528:開源推理模型的革新與突破

一、 發布日期與背景 2025年5月29日&#xff0c;備受業界關注的DeepSeek推理模型DeepSeek-R1迎來重要更新——DeepSeek-R1-0528模型正式發布。此次更新采取了“靜默發布”策略&#xff0c;未提前預告&#xff0c;而是通過官方渠道&#xff08;官網、App、小程序&#xff09;及…

LeetCode 1723: 完成所有工作的最短時間

給你一個整數數組 jobs &#xff0c;其中 jobs[i] 是完成第 i 項工作要花費的時間。 請你將這些工作分配給 k 位工人。所有工作都應該分配給工人&#xff0c;且每項工作只能分配給一位工人。工人的 工作時間 是完成分配給他們的所有工作花費時間的總和。請你設計一套最佳的工作…

JDK8新特性之Steam流

這里寫目錄標題 一、Stream流概述1.1、傳統寫法1.2、Stream寫法1.3、Stream流操作分類 二、Stream流獲取方式2.1、根據Collection獲取2.2、通過Stream的of方法 三、Stream常用方法介紹3.1、forEach3.2、count3.3、filter3.4、limit3.5、skip3.6、map3.7、sorted3.8、distinct3.…

split方法

在編程中&#xff0c;split 方法通常用于將字符串按照指定的分隔符拆分成多個部分&#xff0c;并返回一個包含拆分結果的列表&#xff08;或數組&#xff09;。不同編程語言中的 split 方法語法略有不同&#xff0c;但核心功能相似。以下是常見語言中的用法&#xff1a; ?1. P…