mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-13 23:56:07 +00:00
deploy
This commit is contained in:
@@ -3443,7 +3443,7 @@
|
||||
<p>在上两节中,我们了解了哈希表的工作原理和哈希冲突的处理方法。然而无论是开放寻址还是链地址法,<strong>它们只能保证哈希表可以在发生冲突时正常工作,但无法减少哈希冲突的发生</strong>。</p>
|
||||
<p>如果哈希冲突过于频繁,哈希表的性能则会急剧劣化。对于链地址哈希表,理想情况下键值对平均分布在各个桶中,达到最佳查询效率;最差情况下所有键值对都被存储到同一个桶中,时间复杂度退化至 <span class="arithmatex">\(O(n)\)</span> 。</p>
|
||||
<p><img alt="哈希冲突的最佳与最差情况" src="../hash_algorithm.assets/hash_collision_best_worst_condition.png" /></p>
|
||||
<p align="center"> Fig. 哈希冲突的最佳与最差情况 </p>
|
||||
<p align="center"> 图:哈希冲突的最佳与最差情况 </p>
|
||||
|
||||
<p><strong>键值对的分布情况由哈希函数决定</strong>。回忆哈希函数的计算步骤,先计算哈希值,再对数组长度取模:</p>
|
||||
<div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nv">index</span><span class="w"> </span><span class="o">=</span><span class="w"> </span>hash<span class="o">(</span>key<span class="o">)</span><span class="w"> </span>%<span class="w"> </span>capacity
|
||||
@@ -3844,13 +3844,45 @@
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
<div class="highlight"><span class="filename">simple_hash.dart</span><pre><span></span><code><a id="__codelineno-11-1" name="__codelineno-11-1" href="#__codelineno-11-1"></a><span class="p">[</span><span class="n">class</span><span class="p">]{}</span><span class="o">-</span><span class="p">[</span><span class="n">func</span><span class="p">]{</span><span class="n">add_hash</span><span class="p">}</span>
|
||||
<a id="__codelineno-11-2" name="__codelineno-11-2" href="#__codelineno-11-2"></a>
|
||||
<a id="__codelineno-11-3" name="__codelineno-11-3" href="#__codelineno-11-3"></a><span class="p">[</span><span class="n">class</span><span class="p">]{}</span><span class="o">-</span><span class="p">[</span><span class="n">func</span><span class="p">]{</span><span class="n">mul_hash</span><span class="p">}</span>
|
||||
<a id="__codelineno-11-4" name="__codelineno-11-4" href="#__codelineno-11-4"></a>
|
||||
<a id="__codelineno-11-5" name="__codelineno-11-5" href="#__codelineno-11-5"></a><span class="p">[</span><span class="n">class</span><span class="p">]{}</span><span class="o">-</span><span class="p">[</span><span class="n">func</span><span class="p">]{</span><span class="n">xor_hash</span><span class="p">}</span>
|
||||
<a id="__codelineno-11-6" name="__codelineno-11-6" href="#__codelineno-11-6"></a>
|
||||
<a id="__codelineno-11-7" name="__codelineno-11-7" href="#__codelineno-11-7"></a><span class="p">[</span><span class="n">class</span><span class="p">]{}</span><span class="o">-</span><span class="p">[</span><span class="n">func</span><span class="p">]{</span><span class="n">rot_hash</span><span class="p">}</span>
|
||||
<div class="highlight"><span class="filename">simple_hash.dart</span><pre><span></span><code><a id="__codelineno-11-1" name="__codelineno-11-1" href="#__codelineno-11-1"></a><span class="cm">/* 加法哈希 */</span>
|
||||
<a id="__codelineno-11-2" name="__codelineno-11-2" href="#__codelineno-11-2"></a><span class="kt">int</span><span class="w"> </span><span class="n">addHash</span><span class="p">(</span><span class="kt">String</span><span class="w"> </span><span class="n">key</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-11-3" name="__codelineno-11-3" href="#__codelineno-11-3"></a><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">hash</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">0</span><span class="p">;</span>
|
||||
<a id="__codelineno-11-4" name="__codelineno-11-4" href="#__codelineno-11-4"></a><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">MODULUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">1000000007</span><span class="p">;</span>
|
||||
<a id="__codelineno-11-5" name="__codelineno-11-5" href="#__codelineno-11-5"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">key</span><span class="p">.</span><span class="n">length</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-11-6" name="__codelineno-11-6" href="#__codelineno-11-6"></a><span class="w"> </span><span class="n">hash</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">hash</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">key</span><span class="p">.</span><span class="n">codeUnitAt</span><span class="p">(</span><span class="n">i</span><span class="p">))</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="n">MODULUS</span><span class="p">;</span>
|
||||
<a id="__codelineno-11-7" name="__codelineno-11-7" href="#__codelineno-11-7"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-11-8" name="__codelineno-11-8" href="#__codelineno-11-8"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">hash</span><span class="p">;</span>
|
||||
<a id="__codelineno-11-9" name="__codelineno-11-9" href="#__codelineno-11-9"></a><span class="p">}</span>
|
||||
<a id="__codelineno-11-10" name="__codelineno-11-10" href="#__codelineno-11-10"></a>
|
||||
<a id="__codelineno-11-11" name="__codelineno-11-11" href="#__codelineno-11-11"></a><span class="cm">/* 乘法哈希 */</span>
|
||||
<a id="__codelineno-11-12" name="__codelineno-11-12" href="#__codelineno-11-12"></a><span class="kt">int</span><span class="w"> </span><span class="n">mulHash</span><span class="p">(</span><span class="kt">String</span><span class="w"> </span><span class="n">key</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-11-13" name="__codelineno-11-13" href="#__codelineno-11-13"></a><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">hash</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">0</span><span class="p">;</span>
|
||||
<a id="__codelineno-11-14" name="__codelineno-11-14" href="#__codelineno-11-14"></a><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">MODULUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">1000000007</span><span class="p">;</span>
|
||||
<a id="__codelineno-11-15" name="__codelineno-11-15" href="#__codelineno-11-15"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">key</span><span class="p">.</span><span class="n">length</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-11-16" name="__codelineno-11-16" href="#__codelineno-11-16"></a><span class="w"> </span><span class="n">hash</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="m">31</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">hash</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">key</span><span class="p">.</span><span class="n">codeUnitAt</span><span class="p">(</span><span class="n">i</span><span class="p">))</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="n">MODULUS</span><span class="p">;</span>
|
||||
<a id="__codelineno-11-17" name="__codelineno-11-17" href="#__codelineno-11-17"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-11-18" name="__codelineno-11-18" href="#__codelineno-11-18"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">hash</span><span class="p">;</span>
|
||||
<a id="__codelineno-11-19" name="__codelineno-11-19" href="#__codelineno-11-19"></a><span class="p">}</span>
|
||||
<a id="__codelineno-11-20" name="__codelineno-11-20" href="#__codelineno-11-20"></a>
|
||||
<a id="__codelineno-11-21" name="__codelineno-11-21" href="#__codelineno-11-21"></a><span class="cm">/* 异或哈希 */</span>
|
||||
<a id="__codelineno-11-22" name="__codelineno-11-22" href="#__codelineno-11-22"></a><span class="kt">int</span><span class="w"> </span><span class="n">xorHash</span><span class="p">(</span><span class="kt">String</span><span class="w"> </span><span class="n">key</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-11-23" name="__codelineno-11-23" href="#__codelineno-11-23"></a><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">hash</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">0</span><span class="p">;</span>
|
||||
<a id="__codelineno-11-24" name="__codelineno-11-24" href="#__codelineno-11-24"></a><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">MODULUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">1000000007</span><span class="p">;</span>
|
||||
<a id="__codelineno-11-25" name="__codelineno-11-25" href="#__codelineno-11-25"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">key</span><span class="p">.</span><span class="n">length</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-11-26" name="__codelineno-11-26" href="#__codelineno-11-26"></a><span class="w"> </span><span class="n">hash</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="n">key</span><span class="p">.</span><span class="n">codeUnitAt</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
|
||||
<a id="__codelineno-11-27" name="__codelineno-11-27" href="#__codelineno-11-27"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-11-28" name="__codelineno-11-28" href="#__codelineno-11-28"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">hash</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="n">MODULUS</span><span class="p">;</span>
|
||||
<a id="__codelineno-11-29" name="__codelineno-11-29" href="#__codelineno-11-29"></a><span class="p">}</span>
|
||||
<a id="__codelineno-11-30" name="__codelineno-11-30" href="#__codelineno-11-30"></a>
|
||||
<a id="__codelineno-11-31" name="__codelineno-11-31" href="#__codelineno-11-31"></a><span class="cm">/* 旋转哈希 */</span>
|
||||
<a id="__codelineno-11-32" name="__codelineno-11-32" href="#__codelineno-11-32"></a><span class="kt">int</span><span class="w"> </span><span class="n">rotHash</span><span class="p">(</span><span class="kt">String</span><span class="w"> </span><span class="n">key</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-11-33" name="__codelineno-11-33" href="#__codelineno-11-33"></a><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">hash</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">0</span><span class="p">;</span>
|
||||
<a id="__codelineno-11-34" name="__codelineno-11-34" href="#__codelineno-11-34"></a><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">MODULUS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">1000000007</span><span class="p">;</span>
|
||||
<a id="__codelineno-11-35" name="__codelineno-11-35" href="#__codelineno-11-35"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">key</span><span class="p">.</span><span class="n">length</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-11-36" name="__codelineno-11-36" href="#__codelineno-11-36"></a><span class="w"> </span><span class="n">hash</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">((</span><span class="n">hash</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="m">4</span><span class="p">)</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="p">(</span><span class="n">hash</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="m">28</span><span class="p">)</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="n">key</span><span class="p">.</span><span class="n">codeUnitAt</span><span class="p">(</span><span class="n">i</span><span class="p">))</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="n">MODULUS</span><span class="p">;</span>
|
||||
<a id="__codelineno-11-37" name="__codelineno-11-37" href="#__codelineno-11-37"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-11-38" name="__codelineno-11-38" href="#__codelineno-11-38"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">hash</span><span class="p">;</span>
|
||||
<a id="__codelineno-11-39" name="__codelineno-11-39" href="#__codelineno-11-39"></a><span class="p">}</span>
|
||||
</code></pre></div>
|
||||
</div>
|
||||
<div class="tabbed-block">
|
||||
@@ -4013,7 +4045,7 @@
|
||||
<a id="__codelineno-15-7" name="__codelineno-15-7" href="#__codelineno-15-7"></a><span class="c1"># 布尔量 True 的哈希值为 1</span>
|
||||
<a id="__codelineno-15-8" name="__codelineno-15-8" href="#__codelineno-15-8"></a>
|
||||
<a id="__codelineno-15-9" name="__codelineno-15-9" href="#__codelineno-15-9"></a><span class="n">dec</span> <span class="o">=</span> <span class="mf">3.14159</span>
|
||||
<a id="__codelineno-15-10" name="__codelineno-15-10" href="#__codelineno-15-10"></a><span class="n">hash_dec</span> <span class="o">=</span> <span class="nb">hash</span><span class="p">(</span><span class="n">dec</span><span class="p">)</span>
|
||||
<a id="__codelineno-15-10" name="__codelineno-15-10" href="#__codelineno-15-10"></a><span class="n">hash_dec</span> <span class="o">=</span> <span class="nb">hash</span><span class="p">(</span><span class="n">dec</span><span class="p">)</span>
|
||||
<a id="__codelineno-15-11" name="__codelineno-15-11" href="#__codelineno-15-11"></a><span class="c1"># 小数 3.14159 的哈希值为 326484311674566659</span>
|
||||
<a id="__codelineno-15-12" name="__codelineno-15-12" href="#__codelineno-15-12"></a>
|
||||
<a id="__codelineno-15-13" name="__codelineno-15-13" href="#__codelineno-15-13"></a><span class="nb">str</span> <span class="o">=</span> <span class="s2">"Hello 算法"</span>
|
||||
|
||||
@@ -3476,7 +3476,7 @@
|
||||
<h2 id="621">6.2.1. 链式地址<a class="headerlink" href="#621" title="Permanent link">¶</a></h2>
|
||||
<p>在原始哈希表中,每个桶仅能存储一个键值对。「链式地址 Separate Chaining」将单个元素转换为链表,将键值对作为链表节点,将所有发生冲突的键值对都存储在同一链表中。</p>
|
||||
<p><img alt="链式地址哈希表" src="../hash_collision.assets/hash_table_chaining.png" /></p>
|
||||
<p align="center"> Fig. 链式地址哈希表 </p>
|
||||
<p align="center"> 图:链式地址哈希表 </p>
|
||||
|
||||
<p>链式地址下,哈希表的操作方法包括:</p>
|
||||
<ul>
|
||||
@@ -3991,7 +3991,7 @@
|
||||
<a id="__codelineno-4-68" name="__codelineno-4-68" href="#__codelineno-4-68"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">bucket</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-4-69" name="__codelineno-4-69" href="#__codelineno-4-69"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">bucket</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">key</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nx">key</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<a id="__codelineno-4-70" name="__codelineno-4-70" href="#__codelineno-4-70"></a><span class="w"> </span><span class="nx">bucket</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">);</span>
|
||||
<a id="__codelineno-4-71" name="__codelineno-4-71" href="#__codelineno-4-71"></a><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">size</span><span class="o">--</span><span class="p">;</span>
|
||||
<a id="__codelineno-4-71" name="__codelineno-4-71" href="#__codelineno-4-71"></a><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="err">#</span><span class="nx">size</span><span class="o">--</span><span class="p">;</span>
|
||||
<a id="__codelineno-4-72" name="__codelineno-4-72" href="#__codelineno-4-72"></a><span class="w"> </span><span class="k">break</span><span class="p">;</span>
|
||||
<a id="__codelineno-4-73" name="__codelineno-4-73" href="#__codelineno-4-73"></a><span class="w"> </span><span class="p">}</span>
|
||||
<a id="__codelineno-4-74" name="__codelineno-4-74" href="#__codelineno-4-74"></a><span class="w"> </span><span class="p">}</span>
|
||||
@@ -4598,7 +4598,7 @@
|
||||
<li><strong>查找元素</strong>:若发现哈希冲突,则使用相同步长向后线性遍历,直到找到对应元素,返回 <code>value</code> 即可;如果遇到空位,说明目标键值对不在哈希表中,返回 <span class="arithmatex">\(\text{None}\)</span> 。</li>
|
||||
</ul>
|
||||
<p><img alt="线性探测" src="../hash_collision.assets/hash_table_linear_probing.png" /></p>
|
||||
<p align="center"> Fig. 线性探测 </p>
|
||||
<p align="center"> 图:线性探测 </p>
|
||||
|
||||
<p>然而,线性探测存在以下缺陷:</p>
|
||||
<ul>
|
||||
|
||||
@@ -3429,7 +3429,7 @@
|
||||
<p>散列表,又称「哈希表 Hash Table」,其通过建立键 <code>key</code> 与值 <code>value</code> 之间的映射,实现高效的元素查询。具体而言,我们向哈希表输入一个键 <code>key</code> ,则可以在 <span class="arithmatex">\(O(1)\)</span> 时间内获取对应的值 <code>value</code> 。</p>
|
||||
<p>以一个包含 <span class="arithmatex">\(n\)</span> 个学生的数据库为例,每个学生都有“姓名”和“学号”两项数据。假如我们希望实现“输入一个学号,返回对应的姓名”的查询功能,则可以采用哈希表来实现。</p>
|
||||
<p><img alt="哈希表的抽象表示" src="../hash_map.assets/hash_table_lookup.png" /></p>
|
||||
<p align="center"> Fig. 哈希表的抽象表示 </p>
|
||||
<p align="center"> 图:哈希表的抽象表示 </p>
|
||||
|
||||
<p>除哈希表外,我们还可以使用数组或链表实现查询功能。若将学生数据看作数组(链表)元素,则有:</p>
|
||||
<ul>
|
||||
@@ -3853,7 +3853,7 @@
|
||||
<p>随后,我们就可以利用 <code>index</code> 在哈希表中访问对应的桶,从而获取 <code>value</code> 。</p>
|
||||
<p>设数组长度 <code>capacity = 100</code> 、哈希算法 <code>hash(key) = key</code> ,易得哈希函数为 <code>key % 100</code> 。下图以 <code>key</code> 学号和 <code>value</code> 姓名为例,展示了哈希函数的工作原理。</p>
|
||||
<p><img alt="哈希函数工作原理" src="../hash_map.assets/hash_function.png" /></p>
|
||||
<p align="center"> Fig. 哈希函数工作原理 </p>
|
||||
<p align="center"> 图:哈希函数工作原理 </p>
|
||||
|
||||
<p>以下代码实现了一个简单哈希表。其中,我们将 <code>key</code> 和 <code>value</code> 封装成一个类 <code>Pair</code> ,以表示键值对。</p>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="3:12"><input checked="checked" id="__tabbed_3_1" name="__tabbed_3" type="radio" /><input id="__tabbed_3_2" name="__tabbed_3" type="radio" /><input id="__tabbed_3_3" name="__tabbed_3" type="radio" /><input id="__tabbed_3_4" name="__tabbed_3" type="radio" /><input id="__tabbed_3_5" name="__tabbed_3" type="radio" /><input id="__tabbed_3_6" name="__tabbed_3" type="radio" /><input id="__tabbed_3_7" name="__tabbed_3" type="radio" /><input id="__tabbed_3_8" name="__tabbed_3" type="radio" /><input id="__tabbed_3_9" name="__tabbed_3" type="radio" /><input id="__tabbed_3_10" name="__tabbed_3" type="radio" /><input id="__tabbed_3_11" name="__tabbed_3" type="radio" /><input id="__tabbed_3_12" name="__tabbed_3" type="radio" /><div class="tabbed-labels"><label for="__tabbed_3_1">Java</label><label for="__tabbed_3_2">C++</label><label for="__tabbed_3_3">Python</label><label for="__tabbed_3_4">Go</label><label for="__tabbed_3_5">JS</label><label for="__tabbed_3_6">TS</label><label for="__tabbed_3_7">C</label><label for="__tabbed_3_8">C#</label><label for="__tabbed_3_9">Swift</label><label for="__tabbed_3_10">Zig</label><label for="__tabbed_3_11">Dart</label><label for="__tabbed_3_12">Rust</label></div>
|
||||
@@ -4862,11 +4862,11 @@
|
||||
</code></pre></div>
|
||||
<p>如下图所示,两个学号指向了同一个姓名,这显然是不对的。我们将这种多个输入对应同一输出的情况称为「哈希冲突 Hash Collision」。</p>
|
||||
<p><img alt="哈希冲突示例" src="../hash_map.assets/hash_collision.png" /></p>
|
||||
<p align="center"> Fig. 哈希冲突示例 </p>
|
||||
<p align="center"> 图:哈希冲突示例 </p>
|
||||
|
||||
<p>容易想到,哈希表容量 <span class="arithmatex">\(n\)</span> 越大,多个 <code>key</code> 被分配到同一个桶中的概率就越低,冲突就越少。因此,<strong>我们可以通过扩容哈希表来减少哈希冲突</strong>。如下图所示,扩容前键值对 <code>(136, A)</code> 和 <code>(236, D)</code> 发生冲突,扩容后冲突消失。</p>
|
||||
<p><img alt="哈希表扩容" src="../hash_map.assets/hash_table_reshash.png" /></p>
|
||||
<p align="center"> Fig. 哈希表扩容 </p>
|
||||
<p align="center"> 图:哈希表扩容 </p>
|
||||
|
||||
<p>类似于数组扩容,哈希表扩容需将所有键值对从原哈希表迁移至新哈希表,非常耗时。并且由于哈希表容量 <code>capacity</code> 改变,我们需要通过哈希函数来重新计算所有键值对的存储位置,这进一步提高了扩容过程的计算开销。为此,编程语言通常会预留足够大的哈希表容量,防止频繁扩容。</p>
|
||||
<p>「负载因子 Load Factor」是哈希表的一个重要概念,其定义为哈希表的元素数量除以桶数量,用于衡量哈希冲突的严重程度,<strong>也常被作为哈希表扩容的触发条件</strong>。例如在 Java 中,当负载因子超过 <span class="arithmatex">\(0.75\)</span> 时,系统会将哈希表容量扩展为原先的 <span class="arithmatex">\(2\)</span> 倍。</p>
|
||||
|
||||
Reference in New Issue
Block a user