This commit is contained in:
krahets
2023-07-26 08:59:03 +08:00
parent fd34c845bc
commit 974fea7de4
48 changed files with 299 additions and 299 deletions
@@ -3480,8 +3480,8 @@
<p>如下代码给出了数组表示下的二叉树的简单实现,包括以下操作:</p>
<ul>
<li>给定某节点,获取它的值、左(右)子节点、父节点</li>
<li>获取前序遍历、中序遍历、后序遍历、层序遍历序列</li>
<li>给定某节点,获取它的值、左(右)子节点、父节点</li>
<li>获取前序遍历、中序遍历、后序遍历、层序遍历序列</li>
</ul>
<div class="tabbed-set tabbed-alternate" data-tabs="2:11"><input checked="checked" id="__tabbed_2_1" name="__tabbed_2" type="radio" /><input id="__tabbed_2_2" name="__tabbed_2" type="radio" /><input id="__tabbed_2_3" name="__tabbed_2" type="radio" /><input id="__tabbed_2_4" name="__tabbed_2" type="radio" /><input id="__tabbed_2_5" name="__tabbed_2" type="radio" /><input id="__tabbed_2_6" name="__tabbed_2" type="radio" /><input id="__tabbed_2_7" name="__tabbed_2" type="radio" /><input id="__tabbed_2_8" name="__tabbed_2" type="radio" /><input id="__tabbed_2_9" name="__tabbed_2" type="radio" /><input id="__tabbed_2_10" name="__tabbed_2" type="radio" /><input id="__tabbed_2_11" name="__tabbed_2" type="radio" /><div class="tabbed-labels"><label for="__tabbed_2_1">Java</label><label for="__tabbed_2_2">C++</label><label for="__tabbed_2_3">Python</label><label for="__tabbed_2_4">Go</label><label for="__tabbed_2_5">JavaScript</label><label for="__tabbed_2_6">TypeScript</label><label for="__tabbed_2_7">C</label><label for="__tabbed_2_8">C#</label><label for="__tabbed_2_9">Swift</label><label for="__tabbed_2_10">Zig</label><label for="__tabbed_2_11">Dart</label></div>
<div class="tabbed-content">
@@ -3957,15 +3957,15 @@
<h2 id="733">7.3.3. &nbsp; 优势与局限性<a class="headerlink" href="#733" title="Permanent link">&para;</a></h2>
<p>二叉树的数组表示的优点包括:</p>
<ul>
<li>数组存储在连续的内存空间中,对缓存友好,访问与遍历速度较快</li>
<li>不需要存储指针,比较节省空间</li>
<li>允许随机访问节点</li>
<li>数组存储在连续的内存空间中,对缓存友好,访问与遍历速度较快</li>
<li>不需要存储指针,比较节省空间</li>
<li>允许随机访问节点</li>
</ul>
<p>然而,数组表示也具有一些局限性:</p>
<ul>
<li>数组存储需要连续内存空间,因此不适合存储数据量过大的树</li>
<li>增删节点需要通过数组插入与删除操作实现,效率较低</li>
<li>当二叉树中存在大量 <span class="arithmatex">\(\text{None}\)</span> 时,数组中包含的节点数据比重较低,空间利用率较低</li>
<li>数组存储需要连续内存空间,因此不适合存储数据量过大的树</li>
<li>增删节点需要通过数组插入与删除操作实现,效率较低</li>
<li>当二叉树中存在大量 <span class="arithmatex">\(\text{None}\)</span> 时,数组中包含的节点数据比重较低,空间利用率较低</li>
</ul>
+2 -2
View File
@@ -5615,8 +5615,8 @@
<p>AVL 树的节点查找操作与二叉搜索树一致,在此不再赘述。</p>
<h2 id="754-avl">7.5.4. &nbsp; AVL 树典型应用<a class="headerlink" href="#754-avl" title="Permanent link">&para;</a></h2>
<ul>
<li>组织和存储大型数据,适用于高频查找、低频增删的场景</li>
<li>用于构建数据库中的索引系统</li>
<li>组织和存储大型数据,适用于高频查找、低频增删的场景</li>
<li>用于构建数据库中的索引系统</li>
</ul>
<div class="admonition question">
<p class="admonition-title">为什么红黑树比 AVL 树更受欢迎?</p>
+9 -9
View File
@@ -3458,8 +3458,8 @@
<h1 id="74">7.4. &nbsp; 二叉搜索树<a class="headerlink" href="#74" title="Permanent link">&para;</a></h1>
<p>「二叉搜索树 Binary Search Tree」满足以下条件:</p>
<ol>
<li>对于根节点,左子树中所有节点的值 <span class="arithmatex">\(&lt;\)</span> 根节点的值 <span class="arithmatex">\(&lt;\)</span> 右子树中所有节点的值</li>
<li>任意节点的左、右子树也是二叉搜索树,即同样满足条件 <code>1.</code> </li>
<li>对于根节点,左子树中所有节点的值 <span class="arithmatex">\(&lt;\)</span> 根节点的值 <span class="arithmatex">\(&lt;\)</span> 右子树中所有节点的值</li>
<li>任意节点的左、右子树也是二叉搜索树,即同样满足条件 <code>1.</code> </li>
</ol>
<p><img alt="二叉搜索树" src="../binary_search_tree.assets/binary_search_tree.png" /></p>
<p align="center"> Fig. 二叉搜索树 </p>
@@ -3468,9 +3468,9 @@
<h3 id="_1">查找节点<a class="headerlink" href="#_1" title="Permanent link">&para;</a></h3>
<p>给定目标节点值 <code>num</code> ,可以根据二叉搜索树的性质来查找。我们声明一个节点 <code>cur</code> ,从二叉树的根节点 <code>root</code> 出发,循环比较节点值 <code>cur.val</code><code>num</code> 之间的大小关系</p>
<ul>
<li><code>cur.val &lt; num</code> ,说明目标节点在 <code>cur</code> 的右子树中,因此执行 <code>cur = cur.right</code> </li>
<li><code>cur.val &gt; num</code> ,说明目标节点在 <code>cur</code> 的左子树中,因此执行 <code>cur = cur.left</code> </li>
<li><code>cur.val = num</code> ,说明找到目标节点,跳出循环并返回该节点</li>
<li><code>cur.val &lt; num</code> ,说明目标节点在 <code>cur</code> 的右子树中,因此执行 <code>cur = cur.right</code> </li>
<li><code>cur.val &gt; num</code> ,说明目标节点在 <code>cur</code> 的左子树中,因此执行 <code>cur = cur.left</code> </li>
<li><code>cur.val = num</code> ,说明找到目标节点,跳出循环并返回该节点</li>
</ul>
<div class="tabbed-set tabbed-alternate" data-tabs="1:4"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><input id="__tabbed_1_3" name="__tabbed_1" type="radio" /><input id="__tabbed_1_4" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">&lt;1&gt;</label><label for="__tabbed_1_2">&lt;2&gt;</label><label for="__tabbed_1_3">&lt;3&gt;</label><label for="__tabbed_1_4">&lt;4&gt;</label></div>
<div class="tabbed-content">
@@ -3708,8 +3708,8 @@
<h3 id="_2">插入节点<a class="headerlink" href="#_2" title="Permanent link">&para;</a></h3>
<p>给定一个待插入元素 <code>num</code> ,为了保持二叉搜索树“左子树 &lt; 根节点 &lt; 右子树”的性质,插入操作分为两步:</p>
<ol>
<li><strong>查找插入位置</strong>:与查找操作相似,从根节点出发,根据当前节点值和 <code>num</code> 的大小关系循环向下搜索,直到越过叶节点(遍历至 <span class="arithmatex">\(\text{None}\)</span> )时跳出循环</li>
<li><strong>在该位置插入节点</strong>:初始化节点 <code>num</code> ,将该节点置于 <span class="arithmatex">\(\text{None}\)</span> 的位置</li>
<li><strong>查找插入位置</strong>:与查找操作相似,从根节点出发,根据当前节点值和 <code>num</code> 的大小关系循环向下搜索,直到越过叶节点(遍历至 <span class="arithmatex">\(\text{None}\)</span> )时跳出循环</li>
<li><strong>在该位置插入节点</strong>:初始化节点 <code>num</code> ,将该节点置于 <span class="arithmatex">\(\text{None}\)</span> 的位置</li>
</ol>
<p>二叉搜索树不允许存在重复节点,否则将违反其定义。因此,若待插入节点在树中已存在,则不执行插入,直接返回。</p>
<p><img alt="在二叉搜索树中插入节点" src="../binary_search_tree.assets/bst_insert.png" /></p>
@@ -4041,8 +4041,8 @@
<p>当待删除节点的度为 <span class="arithmatex">\(2\)</span> 时,我们无法直接删除它,而需要使用一个节点替换该节点。由于要保持二叉搜索树“左 <span class="arithmatex">\(&lt;\)</span><span class="arithmatex">\(&lt;\)</span> 右”的性质,因此这个节点可以是右子树的最小节点或左子树的最大节点。假设我们选择右子树的最小节点(或者称为中序遍历的下个节点),则删除操作为:</p>
<ol>
<li>找到待删除节点在“中序遍历序列”中的下一个节点,记为 <code>tmp</code> </li>
<li><code>tmp</code> 的值覆盖待删除节点的值,并在树中递归删除节点 <code>tmp</code> </li>
<li>找到待删除节点在“中序遍历序列”中的下一个节点,记为 <code>tmp</code> </li>
<li><code>tmp</code> 的值覆盖待删除节点的值,并在树中递归删除节点 <code>tmp</code> </li>
</ol>
<div class="tabbed-set tabbed-alternate" data-tabs="4:4"><input checked="checked" id="__tabbed_4_1" name="__tabbed_4" type="radio" /><input id="__tabbed_4_2" name="__tabbed_4" type="radio" /><input id="__tabbed_4_3" name="__tabbed_4" type="radio" /><input id="__tabbed_4_4" name="__tabbed_4" type="radio" /><div class="tabbed-labels"><label for="__tabbed_4_1">&lt;1&gt;</label><label for="__tabbed_4_2">&lt;2&gt;</label><label for="__tabbed_4_3">&lt;3&gt;</label><label for="__tabbed_4_4">&lt;4&gt;</label></div>
<div class="tabbed-content">
+10 -10
View File
@@ -3614,14 +3614,14 @@
<h2 id="711">7.1.1. &nbsp; 二叉树常见术语<a class="headerlink" href="#711" title="Permanent link">&para;</a></h2>
<p>二叉树涉及的术语较多,建议尽量理解并记住。</p>
<ul>
<li>「根节点 Root Node」:位于二叉树顶层的节点,没有父节点</li>
<li>「叶节点 Leaf Node」:没有子节点的节点,其两个指针均指向 <span class="arithmatex">\(\text{None}\)</span> </li>
<li>节点的「层 Level」:从顶至底递增,根节点所在层为 1 </li>
<li>节点的「度 Degree」:节点的子节点的数量。在二叉树中,度的范围是 0, 1, 2 </li>
<li>「边 Edge」:连接两个节点的线段,即节点指针</li>
<li>二叉树的「高度」:从根节点到最远叶节点所经过的边的数量</li>
<li>节点的「深度 Depth」 :从根节点到该节点所经过的边的数量</li>
<li>节点的「高度 Height」:从最远叶节点到该节点所经过的边的数量</li>
<li>「根节点 Root Node」:位于二叉树顶层的节点,没有父节点</li>
<li>「叶节点 Leaf Node」:没有子节点的节点,其两个指针均指向 <span class="arithmatex">\(\text{None}\)</span> </li>
<li>节点的「层 Level」:从顶至底递增,根节点所在层为 1 </li>
<li>节点的「度 Degree」:节点的子节点的数量。在二叉树中,度的范围是 0, 1, 2 </li>
<li>「边 Edge」:连接两个节点的线段,即节点指针</li>
<li>二叉树的「高度」:从根节点到最远叶节点所经过的边的数量</li>
<li>节点的「深度 Depth」 :从根节点到该节点所经过的边的数量</li>
<li>节点的「高度 Height」:从最远叶节点到该节点所经过的边的数量</li>
</ul>
<p><img alt="二叉树的常用术语" src="../binary_tree.assets/binary_tree_terminology.png" /></p>
<p align="center"> Fig. 二叉树的常用术语 </p>
@@ -3930,8 +3930,8 @@
<h2 id="714">7.1.4. &nbsp; 二叉树的退化<a class="headerlink" href="#714" title="Permanent link">&para;</a></h2>
<p>当二叉树的每层节点都被填满时,达到「完美二叉树」;而当所有节点都偏向一侧时,二叉树退化为「链表」。</p>
<ul>
<li>完美二叉树是理想情况,可以充分发挥二叉树“分治”的优势</li>
<li>链表则是另一个极端,各项操作都变为线性操作,时间复杂度退化至 <span class="arithmatex">\(O(n)\)</span> </li>
<li>完美二叉树是理想情况,可以充分发挥二叉树“分治”的优势</li>
<li>链表则是另一个极端,各项操作都变为线性操作,时间复杂度退化至 <span class="arithmatex">\(O(n)\)</span> </li>
</ul>
<p><img alt="二叉树的最佳与最差结构" src="../binary_tree.assets/binary_tree_best_worst_cases.png" /></p>
<p align="center"> Fig. 二叉树的最佳与最差结构 </p>