This commit is contained in:
krahets
2023-07-24 13:09:54 +08:00
parent 3e2ab6a857
commit 72ae5c4673
17 changed files with 942 additions and 265 deletions

View File

@@ -4495,63 +4495,62 @@
</div>
<div class="tabbed-block">
<div class="highlight"><span class="filename">binary_search_tree.swift</span><pre><span></span><code><a id="__codelineno-30-1" name="__codelineno-30-1" href="#__codelineno-30-1"></a><span class="cm">/* 删除节点 */</span>
<a id="__codelineno-30-2" name="__codelineno-30-2" href="#__codelineno-30-2"></a><span class="p">@</span><span class="n">discardableResult</span>
<a id="__codelineno-30-3" name="__codelineno-30-3" href="#__codelineno-30-3"></a><span class="kd">func</span> <span class="nf">remove</span><span class="p">(</span><span class="n">num</span><span class="p">:</span> <span class="nb">Int</span><span class="p">)</span> <span class="p">{</span>
<a id="__codelineno-30-4" name="__codelineno-30-4" href="#__codelineno-30-4"></a> <span class="c1">// 若树为空,直接提前返回</span>
<a id="__codelineno-30-5" name="__codelineno-30-5" href="#__codelineno-30-5"></a> <span class="k">if</span> <span class="n">root</span> <span class="p">==</span> <span class="kc">nil</span> <span class="p">{</span>
<a id="__codelineno-30-6" name="__codelineno-30-6" href="#__codelineno-30-6"></a> <span class="k">return</span>
<a id="__codelineno-30-7" name="__codelineno-30-7" href="#__codelineno-30-7"></a> <span class="p">}</span>
<a id="__codelineno-30-8" name="__codelineno-30-8" href="#__codelineno-30-8"></a> <span class="kd">var</span> <span class="nv">cur</span> <span class="p">=</span> <span class="n">root</span>
<a id="__codelineno-30-9" name="__codelineno-30-9" href="#__codelineno-30-9"></a> <span class="kd">var</span> <span class="nv">pre</span><span class="p">:</span> <span class="n">TreeNode</span><span class="p">?</span>
<a id="__codelineno-30-10" name="__codelineno-30-10" href="#__codelineno-30-10"></a> <span class="c1">// 循环查找,越过叶节点后跳出</span>
<a id="__codelineno-30-11" name="__codelineno-30-11" href="#__codelineno-30-11"></a> <span class="k">while</span> <span class="n">cur</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
<a id="__codelineno-30-12" name="__codelineno-30-12" href="#__codelineno-30-12"></a> <span class="c1">// 找到待删除节点,跳出循环</span>
<a id="__codelineno-30-13" name="__codelineno-30-13" href="#__codelineno-30-13"></a> <span class="k">if</span> <span class="n">cur</span><span class="p">!.</span><span class="n">val</span> <span class="p">==</span> <span class="n">num</span> <span class="p">{</span>
<a id="__codelineno-30-14" name="__codelineno-30-14" href="#__codelineno-30-14"></a> <span class="k">break</span>
<a id="__codelineno-30-15" name="__codelineno-30-15" href="#__codelineno-30-15"></a> <span class="p">}</span>
<a id="__codelineno-30-16" name="__codelineno-30-16" href="#__codelineno-30-16"></a> <span class="n">pre</span> <span class="p">=</span> <span class="n">cur</span>
<a id="__codelineno-30-17" name="__codelineno-30-17" href="#__codelineno-30-17"></a> <span class="c1">// 待删除节点在 cur 的右子树中</span>
<a id="__codelineno-30-18" name="__codelineno-30-18" href="#__codelineno-30-18"></a> <span class="k">if</span> <span class="n">cur</span><span class="p">!.</span><span class="n">val</span> <span class="o">&lt;</span> <span class="n">num</span> <span class="p">{</span>
<a id="__codelineno-30-19" name="__codelineno-30-19" href="#__codelineno-30-19"></a> <span class="n">cur</span> <span class="p">=</span> <span class="n">cur</span><span class="p">?.</span><span class="kr">right</span>
<a id="__codelineno-30-20" name="__codelineno-30-20" href="#__codelineno-30-20"></a> <span class="p">}</span>
<a id="__codelineno-30-21" name="__codelineno-30-21" href="#__codelineno-30-21"></a> <span class="c1">// 待删除节点在 cur 的左子树中</span>
<a id="__codelineno-30-22" name="__codelineno-30-22" href="#__codelineno-30-22"></a> <span class="k">else</span> <span class="p">{</span>
<a id="__codelineno-30-23" name="__codelineno-30-23" href="#__codelineno-30-23"></a> <span class="n">cur</span> <span class="p">=</span> <span class="n">cur</span><span class="p">?.</span><span class="kr">left</span>
<a id="__codelineno-30-24" name="__codelineno-30-24" href="#__codelineno-30-24"></a> <span class="p">}</span>
<a id="__codelineno-30-25" name="__codelineno-30-25" href="#__codelineno-30-25"></a> <span class="p">}</span>
<a id="__codelineno-30-26" name="__codelineno-30-26" href="#__codelineno-30-26"></a> <span class="c1">// 若无待删除节点,则直接返回</span>
<a id="__codelineno-30-27" name="__codelineno-30-27" href="#__codelineno-30-27"></a> <span class="k">if</span> <span class="n">cur</span> <span class="p">==</span> <span class="kc">nil</span> <span class="p">{</span>
<a id="__codelineno-30-28" name="__codelineno-30-28" href="#__codelineno-30-28"></a> <span class="k">return</span>
<a id="__codelineno-30-29" name="__codelineno-30-29" href="#__codelineno-30-29"></a> <span class="p">}</span>
<a id="__codelineno-30-30" name="__codelineno-30-30" href="#__codelineno-30-30"></a> <span class="c1">// 子节点数量 = 0 or 1</span>
<a id="__codelineno-30-31" name="__codelineno-30-31" href="#__codelineno-30-31"></a> <span class="k">if</span> <span class="n">cur</span><span class="p">?.</span><span class="kr">left</span> <span class="p">==</span> <span class="kc">nil</span> <span class="o">||</span> <span class="n">cur</span><span class="p">?.</span><span class="kr">right</span> <span class="p">==</span> <span class="kc">nil</span> <span class="p">{</span>
<a id="__codelineno-30-32" name="__codelineno-30-32" href="#__codelineno-30-32"></a> <span class="c1">// 当子节点数量 = 0 / 1 时, child = null / 该子节点</span>
<a id="__codelineno-30-33" name="__codelineno-30-33" href="#__codelineno-30-33"></a> <span class="kd">let</span> <span class="nv">child</span> <span class="p">=</span> <span class="n">cur</span><span class="p">?.</span><span class="kr">left</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">?</span> <span class="n">cur</span><span class="p">?.</span><span class="kr">left</span> <span class="p">:</span> <span class="n">cur</span><span class="p">?.</span><span class="kr">right</span>
<a id="__codelineno-30-34" name="__codelineno-30-34" href="#__codelineno-30-34"></a> <span class="c1">// 删除节点 cur</span>
<a id="__codelineno-30-35" name="__codelineno-30-35" href="#__codelineno-30-35"></a> <span class="k">if</span> <span class="n">cur</span> <span class="o">!==</span> <span class="n">root</span> <span class="p">{</span>
<a id="__codelineno-30-36" name="__codelineno-30-36" href="#__codelineno-30-36"></a> <span class="k">if</span> <span class="n">pre</span><span class="p">?.</span><span class="kr">left</span> <span class="p">===</span> <span class="n">cur</span> <span class="p">{</span>
<a id="__codelineno-30-37" name="__codelineno-30-37" href="#__codelineno-30-37"></a> <span class="n">pre</span><span class="p">?.</span><span class="kr">left</span> <span class="p">=</span> <span class="n">child</span>
<a id="__codelineno-30-38" name="__codelineno-30-38" href="#__codelineno-30-38"></a> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<a id="__codelineno-30-39" name="__codelineno-30-39" href="#__codelineno-30-39"></a> <span class="n">pre</span><span class="p">?.</span><span class="kr">right</span> <span class="p">=</span> <span class="n">child</span>
<a id="__codelineno-30-40" name="__codelineno-30-40" href="#__codelineno-30-40"></a> <span class="p">}</span>
<a id="__codelineno-30-41" name="__codelineno-30-41" href="#__codelineno-30-41"></a> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<a id="__codelineno-30-42" name="__codelineno-30-42" href="#__codelineno-30-42"></a> <span class="c1">// 若删除节点为根节点,则重新指定根节点</span>
<a id="__codelineno-30-43" name="__codelineno-30-43" href="#__codelineno-30-43"></a> <span class="n">root</span> <span class="p">=</span> <span class="n">child</span>
<a id="__codelineno-30-44" name="__codelineno-30-44" href="#__codelineno-30-44"></a> <span class="p">}</span>
<a id="__codelineno-30-45" name="__codelineno-30-45" href="#__codelineno-30-45"></a> <span class="p">}</span>
<a id="__codelineno-30-46" name="__codelineno-30-46" href="#__codelineno-30-46"></a> <span class="c1">// 子节点数量 = 2</span>
<a id="__codelineno-30-47" name="__codelineno-30-47" href="#__codelineno-30-47"></a> <span class="k">else</span> <span class="p">{</span>
<a id="__codelineno-30-48" name="__codelineno-30-48" href="#__codelineno-30-48"></a> <span class="c1">// 获取中序遍历中 cur 的下一个节点</span>
<a id="__codelineno-30-49" name="__codelineno-30-49" href="#__codelineno-30-49"></a> <span class="kd">var</span> <span class="nv">tmp</span> <span class="p">=</span> <span class="n">cur</span><span class="p">?.</span><span class="kr">right</span>
<a id="__codelineno-30-50" name="__codelineno-30-50" href="#__codelineno-30-50"></a> <span class="k">while</span> <span class="n">tmp</span><span class="p">?.</span><span class="kr">left</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
<a id="__codelineno-30-51" name="__codelineno-30-51" href="#__codelineno-30-51"></a> <span class="n">tmp</span> <span class="p">=</span> <span class="n">tmp</span><span class="p">?.</span><span class="kr">left</span>
<a id="__codelineno-30-52" name="__codelineno-30-52" href="#__codelineno-30-52"></a> <span class="p">}</span>
<a id="__codelineno-30-53" name="__codelineno-30-53" href="#__codelineno-30-53"></a> <span class="c1">// 递归删除节点 tmp</span>
<a id="__codelineno-30-54" name="__codelineno-30-54" href="#__codelineno-30-54"></a> <span class="n">remove</span><span class="p">(</span><span class="n">num</span><span class="p">:</span> <span class="n">tmp</span><span class="p">!.</span><span class="n">val</span><span class="p">)</span>
<a id="__codelineno-30-55" name="__codelineno-30-55" href="#__codelineno-30-55"></a> <span class="c1">// 用 tmp 覆盖 cur</span>
<a id="__codelineno-30-56" name="__codelineno-30-56" href="#__codelineno-30-56"></a> <span class="n">cur</span><span class="p">?.</span><span class="n">val</span> <span class="p">=</span> <span class="n">tmp</span><span class="p">!.</span><span class="n">val</span>
<a id="__codelineno-30-57" name="__codelineno-30-57" href="#__codelineno-30-57"></a> <span class="p">}</span>
<a id="__codelineno-30-58" name="__codelineno-30-58" href="#__codelineno-30-58"></a><span class="p">}</span>
<a id="__codelineno-30-2" name="__codelineno-30-2" href="#__codelineno-30-2"></a><span class="kd">func</span> <span class="nf">remove</span><span class="p">(</span><span class="n">num</span><span class="p">:</span> <span class="nb">Int</span><span class="p">)</span> <span class="p">{</span>
<a id="__codelineno-30-3" name="__codelineno-30-3" href="#__codelineno-30-3"></a> <span class="c1">// 若树为空,直接提前返回</span>
<a id="__codelineno-30-4" name="__codelineno-30-4" href="#__codelineno-30-4"></a> <span class="k">if</span> <span class="n">root</span> <span class="p">==</span> <span class="kc">nil</span> <span class="p">{</span>
<a id="__codelineno-30-5" name="__codelineno-30-5" href="#__codelineno-30-5"></a> <span class="k">return</span>
<a id="__codelineno-30-6" name="__codelineno-30-6" href="#__codelineno-30-6"></a> <span class="p">}</span>
<a id="__codelineno-30-7" name="__codelineno-30-7" href="#__codelineno-30-7"></a> <span class="kd">var</span> <span class="nv">cur</span> <span class="p">=</span> <span class="n">root</span>
<a id="__codelineno-30-8" name="__codelineno-30-8" href="#__codelineno-30-8"></a> <span class="kd">var</span> <span class="nv">pre</span><span class="p">:</span> <span class="n">TreeNode</span><span class="p">?</span>
<a id="__codelineno-30-9" name="__codelineno-30-9" href="#__codelineno-30-9"></a> <span class="c1">// 循环查找,越过叶节点后跳出</span>
<a id="__codelineno-30-10" name="__codelineno-30-10" href="#__codelineno-30-10"></a> <span class="k">while</span> <span class="n">cur</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
<a id="__codelineno-30-11" name="__codelineno-30-11" href="#__codelineno-30-11"></a> <span class="c1">// 找到待删除节点,跳出循环</span>
<a id="__codelineno-30-12" name="__codelineno-30-12" href="#__codelineno-30-12"></a> <span class="k">if</span> <span class="n">cur</span><span class="p">!.</span><span class="n">val</span> <span class="p">==</span> <span class="n">num</span> <span class="p">{</span>
<a id="__codelineno-30-13" name="__codelineno-30-13" href="#__codelineno-30-13"></a> <span class="k">break</span>
<a id="__codelineno-30-14" name="__codelineno-30-14" href="#__codelineno-30-14"></a> <span class="p">}</span>
<a id="__codelineno-30-15" name="__codelineno-30-15" href="#__codelineno-30-15"></a> <span class="n">pre</span> <span class="p">=</span> <span class="n">cur</span>
<a id="__codelineno-30-16" name="__codelineno-30-16" href="#__codelineno-30-16"></a> <span class="c1">// 待删除节点在 cur 的右子树中</span>
<a id="__codelineno-30-17" name="__codelineno-30-17" href="#__codelineno-30-17"></a> <span class="k">if</span> <span class="n">cur</span><span class="p">!.</span><span class="n">val</span> <span class="o">&lt;</span> <span class="n">num</span> <span class="p">{</span>
<a id="__codelineno-30-18" name="__codelineno-30-18" href="#__codelineno-30-18"></a> <span class="n">cur</span> <span class="p">=</span> <span class="n">cur</span><span class="p">?.</span><span class="kr">right</span>
<a id="__codelineno-30-19" name="__codelineno-30-19" href="#__codelineno-30-19"></a> <span class="p">}</span>
<a id="__codelineno-30-20" name="__codelineno-30-20" href="#__codelineno-30-20"></a> <span class="c1">// 待删除节点在 cur 的左子树中</span>
<a id="__codelineno-30-21" name="__codelineno-30-21" href="#__codelineno-30-21"></a> <span class="k">else</span> <span class="p">{</span>
<a id="__codelineno-30-22" name="__codelineno-30-22" href="#__codelineno-30-22"></a> <span class="n">cur</span> <span class="p">=</span> <span class="n">cur</span><span class="p">?.</span><span class="kr">left</span>
<a id="__codelineno-30-23" name="__codelineno-30-23" href="#__codelineno-30-23"></a> <span class="p">}</span>
<a id="__codelineno-30-24" name="__codelineno-30-24" href="#__codelineno-30-24"></a> <span class="p">}</span>
<a id="__codelineno-30-25" name="__codelineno-30-25" href="#__codelineno-30-25"></a> <span class="c1">// 若无待删除节点,则直接返回</span>
<a id="__codelineno-30-26" name="__codelineno-30-26" href="#__codelineno-30-26"></a> <span class="k">if</span> <span class="n">cur</span> <span class="p">==</span> <span class="kc">nil</span> <span class="p">{</span>
<a id="__codelineno-30-27" name="__codelineno-30-27" href="#__codelineno-30-27"></a> <span class="k">return</span>
<a id="__codelineno-30-28" name="__codelineno-30-28" href="#__codelineno-30-28"></a> <span class="p">}</span>
<a id="__codelineno-30-29" name="__codelineno-30-29" href="#__codelineno-30-29"></a> <span class="c1">// 子节点数量 = 0 or 1</span>
<a id="__codelineno-30-30" name="__codelineno-30-30" href="#__codelineno-30-30"></a> <span class="k">if</span> <span class="n">cur</span><span class="p">?.</span><span class="kr">left</span> <span class="p">==</span> <span class="kc">nil</span> <span class="o">||</span> <span class="n">cur</span><span class="p">?.</span><span class="kr">right</span> <span class="p">==</span> <span class="kc">nil</span> <span class="p">{</span>
<a id="__codelineno-30-31" name="__codelineno-30-31" href="#__codelineno-30-31"></a> <span class="c1">// 当子节点数量 = 0 / 1 时, child = null / 该子节点</span>
<a id="__codelineno-30-32" name="__codelineno-30-32" href="#__codelineno-30-32"></a> <span class="kd">let</span> <span class="nv">child</span> <span class="p">=</span> <span class="n">cur</span><span class="p">?.</span><span class="kr">left</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">?</span> <span class="n">cur</span><span class="p">?.</span><span class="kr">left</span> <span class="p">:</span> <span class="n">cur</span><span class="p">?.</span><span class="kr">right</span>
<a id="__codelineno-30-33" name="__codelineno-30-33" href="#__codelineno-30-33"></a> <span class="c1">// 删除节点 cur</span>
<a id="__codelineno-30-34" name="__codelineno-30-34" href="#__codelineno-30-34"></a> <span class="k">if</span> <span class="n">cur</span> <span class="o">!==</span> <span class="n">root</span> <span class="p">{</span>
<a id="__codelineno-30-35" name="__codelineno-30-35" href="#__codelineno-30-35"></a> <span class="k">if</span> <span class="n">pre</span><span class="p">?.</span><span class="kr">left</span> <span class="p">===</span> <span class="n">cur</span> <span class="p">{</span>
<a id="__codelineno-30-36" name="__codelineno-30-36" href="#__codelineno-30-36"></a> <span class="n">pre</span><span class="p">?.</span><span class="kr">left</span> <span class="p">=</span> <span class="n">child</span>
<a id="__codelineno-30-37" name="__codelineno-30-37" href="#__codelineno-30-37"></a> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<a id="__codelineno-30-38" name="__codelineno-30-38" href="#__codelineno-30-38"></a> <span class="n">pre</span><span class="p">?.</span><span class="kr">right</span> <span class="p">=</span> <span class="n">child</span>
<a id="__codelineno-30-39" name="__codelineno-30-39" href="#__codelineno-30-39"></a> <span class="p">}</span>
<a id="__codelineno-30-40" name="__codelineno-30-40" href="#__codelineno-30-40"></a> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<a id="__codelineno-30-41" name="__codelineno-30-41" href="#__codelineno-30-41"></a> <span class="c1">// 若删除节点为根节点,则重新指定根节点</span>
<a id="__codelineno-30-42" name="__codelineno-30-42" href="#__codelineno-30-42"></a> <span class="n">root</span> <span class="p">=</span> <span class="n">child</span>
<a id="__codelineno-30-43" name="__codelineno-30-43" href="#__codelineno-30-43"></a> <span class="p">}</span>
<a id="__codelineno-30-44" name="__codelineno-30-44" href="#__codelineno-30-44"></a> <span class="p">}</span>
<a id="__codelineno-30-45" name="__codelineno-30-45" href="#__codelineno-30-45"></a> <span class="c1">// 子节点数量 = 2</span>
<a id="__codelineno-30-46" name="__codelineno-30-46" href="#__codelineno-30-46"></a> <span class="k">else</span> <span class="p">{</span>
<a id="__codelineno-30-47" name="__codelineno-30-47" href="#__codelineno-30-47"></a> <span class="c1">// 获取中序遍历中 cur 的下一个节点</span>
<a id="__codelineno-30-48" name="__codelineno-30-48" href="#__codelineno-30-48"></a> <span class="kd">var</span> <span class="nv">tmp</span> <span class="p">=</span> <span class="n">cur</span><span class="p">?.</span><span class="kr">right</span>
<a id="__codelineno-30-49" name="__codelineno-30-49" href="#__codelineno-30-49"></a> <span class="k">while</span> <span class="n">tmp</span><span class="p">?.</span><span class="kr">left</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
<a id="__codelineno-30-50" name="__codelineno-30-50" href="#__codelineno-30-50"></a> <span class="n">tmp</span> <span class="p">=</span> <span class="n">tmp</span><span class="p">?.</span><span class="kr">left</span>
<a id="__codelineno-30-51" name="__codelineno-30-51" href="#__codelineno-30-51"></a> <span class="p">}</span>
<a id="__codelineno-30-52" name="__codelineno-30-52" href="#__codelineno-30-52"></a> <span class="c1">// 递归删除节点 tmp</span>
<a id="__codelineno-30-53" name="__codelineno-30-53" href="#__codelineno-30-53"></a> <span class="n">remove</span><span class="p">(</span><span class="n">num</span><span class="p">:</span> <span class="n">tmp</span><span class="p">!.</span><span class="n">val</span><span class="p">)</span>
<a id="__codelineno-30-54" name="__codelineno-30-54" href="#__codelineno-30-54"></a> <span class="c1">// 用 tmp 覆盖 cur</span>
<a id="__codelineno-30-55" name="__codelineno-30-55" href="#__codelineno-30-55"></a> <span class="n">cur</span><span class="p">?.</span><span class="n">val</span> <span class="p">=</span> <span class="n">tmp</span><span class="p">!.</span><span class="n">val</span>
<a id="__codelineno-30-56" name="__codelineno-30-56" href="#__codelineno-30-56"></a> <span class="p">}</span>
<a id="__codelineno-30-57" name="__codelineno-30-57" href="#__codelineno-30-57"></a><span class="p">}</span>
</code></pre></div>
</div>
<div class="tabbed-block">