This commit is contained in:
krahets
2023-02-26 18:18:03 +08:00
parent 281b756ddf
commit e82934bc32
34 changed files with 150 additions and 229 deletions

View File

@@ -1626,9 +1626,7 @@
<li>同理,对剩余 <span class="arithmatex">\(n - 1\)</span> 个元素执行「冒泡」,可将第二大元素交换至正确位置,因而待排序元素只剩 <span class="arithmatex">\(n - 2\)</span> 个。</li>
<li>以此类推…… <strong>循环 <span class="arithmatex">\(n - 1\)</span> 轮「冒泡」,即可完成整个数组的排序</strong></li>
</ol>
<p><img alt="bubble_sort_overview" src="../bubble_sort.assets/bubble_sort_overview.png" /></p>
<p align="center"> Fig. 冒泡排序流程 </p>
<p><img alt="冒泡排序流程" src="../bubble_sort.assets/bubble_sort_overview.png" /></p>
<div class="tabbed-set tabbed-alternate" data-tabs="2:10"><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" /><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></div>
<div class="tabbed-content">
<div class="tabbed-block">

View File

@@ -1589,18 +1589,14 @@
<p>「插入排序 Insertion Sort」是一种基于 <strong>数组插入操作</strong> 的排序算法。</p>
<p>「插入操作」原理:选定某个待排序元素为基准数 <code>base</code>,将 <code>base</code> 与其左侧已排序区间元素依次对比大小,并插入到正确位置。</p>
<p>回忆数组插入操作,我们需要将从目标索引到 <code>base</code> 之间的所有元素向右移动一位,然后再将 <code>base</code> 赋值给目标索引。</p>
<p><img alt="insertion_operation" src="../insertion_sort.assets/insertion_operation.png" /></p>
<p align="center"> Fig. 插入操作 </p>
<p><img alt="单次插入操作" src="../insertion_sort.assets/insertion_operation.png" /></p>
<h2 id="1131">11.3.1. &nbsp; 算法流程<a class="headerlink" href="#1131" title="Permanent link">&para;</a></h2>
<ol>
<li>第 1 轮先选取数组的 <strong>第 2 个元素</strong><code>base</code> ,执行「插入操作」后,<strong>数组前 2 个元素已完成排序</strong></li>
<li>第 2 轮选取 <strong>第 3 个元素</strong><code>base</code> ,执行「插入操作」后,<strong>数组前 3 个元素已完成排序</strong></li>
<li>以此类推……最后一轮选取 <strong>数组尾元素</strong><code>base</code> ,执行「插入操作」后,<strong>所有元素已完成排序</strong></li>
</ol>
<p><img alt="insertion_sort_overview" src="../insertion_sort.assets/insertion_sort_overview.png" /></p>
<p align="center"> Fig. 插入排序流程 </p>
<p><img alt="插入排序流程" src="../insertion_sort.assets/insertion_sort_overview.png" /></p>
<div class="tabbed-set tabbed-alternate" data-tabs="1:10"><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" /><input id="__tabbed_1_5" name="__tabbed_1" type="radio" /><input id="__tabbed_1_6" name="__tabbed_1" type="radio" /><input id="__tabbed_1_7" name="__tabbed_1" type="radio" /><input id="__tabbed_1_8" name="__tabbed_1" type="radio" /><input id="__tabbed_1_9" name="__tabbed_1" type="radio" /><input id="__tabbed_1_10" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">Java</label><label for="__tabbed_1_2">C++</label><label for="__tabbed_1_3">Python</label><label for="__tabbed_1_4">Go</label><label for="__tabbed_1_5">JavaScript</label><label for="__tabbed_1_6">TypeScript</label><label for="__tabbed_1_7">C</label><label for="__tabbed_1_8">C#</label><label for="__tabbed_1_9">Swift</label><label for="__tabbed_1_10">Zig</label></div>
<div class="tabbed-content">
<div class="tabbed-block">

View File

@@ -1645,9 +1645,7 @@
<li>待排序的列表的 <strong>元素类型</strong> 可以是整数、浮点数、字符、或字符串;</li>
<li>排序算法可以根据需要设定 <strong>判断规则</strong>,例如数字大小、字符 ASCII 码顺序、自定义规则;</li>
</ul>
<p><img alt="sorting_examples" src="../intro_to_sort.assets/sorting_examples.png" /></p>
<p align="center"> Fig. 排序中的不同元素类型和判断规则 </p>
<p><img alt="排序中不同的元素类型和判断规则" src="../intro_to_sort.assets/sorting_examples.png" /></p>
<h2 id="1111">11.1.1. &nbsp; 评价维度<a class="headerlink" href="#1111" title="Permanent link">&para;</a></h2>
<p>排序算法主要可根据 <strong>稳定性 、就地性 、自适应性 、比较类</strong> 来分类。</p>
<h3 id="_1">稳定性<a class="headerlink" href="#_1" title="Permanent link">&para;</a></h3>

View File

@@ -1591,9 +1591,7 @@
<li><strong>划分阶段</strong>:通过递归不断 <strong>将数组从中点位置划分开</strong>,将长数组的排序问题转化为短数组的排序问题;</li>
<li><strong>合并阶段</strong>:划分到子数组长度为 1 时,开始向上合并,不断将 <strong>左、右两个短排序数组</strong> 合并为 <strong>一个长排序数组</strong>,直至合并至原数组时完成排序;</li>
</ol>
<p><img alt="merge_sort_overview" src="../merge_sort.assets/merge_sort_overview.png" /></p>
<p align="center"> Fig. 归并排序两阶段:划分与合并 </p>
<p><img alt="归并排序的划分与合并阶段" src="../merge_sort.assets/merge_sort_overview.png" /></p>
<h2 id="1151">11.5.1. &nbsp; 算法流程<a class="headerlink" href="#1151" title="Permanent link">&para;</a></h2>
<p><strong>「递归划分」</strong> 从顶至底递归地 <strong>将数组从中点切为两个子数组</strong>,直至长度为 1 </p>
<ol>

View File

@@ -1622,7 +1622,7 @@
<li>不断循环步骤 <code>2.</code> ,直至 <code>i</code> , <code>j</code> 相遇时跳出,最终把基准数交换至两个子数组的分界线;</li>
</ol>
<p>「哨兵划分」执行完毕后,原数组被划分成两个部分,即 <strong>左子数组</strong><strong>右子数组</strong>,且满足 <strong>左子数组任意元素 &lt; 基准数 &lt; 右子数组任意元素</strong>。因此,接下来我们只需要排序两个子数组即可。</p>
<div class="tabbed-set tabbed-alternate" data-tabs="1:9"><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" /><input id="__tabbed_1_5" name="__tabbed_1" type="radio" /><input id="__tabbed_1_6" name="__tabbed_1" type="radio" /><input id="__tabbed_1_7" name="__tabbed_1" type="radio" /><input id="__tabbed_1_8" name="__tabbed_1" type="radio" /><input id="__tabbed_1_9" 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><label for="__tabbed_1_5">&lt;5&gt;</label><label for="__tabbed_1_6">&lt;6&gt;</label><label for="__tabbed_1_7">&lt;7&gt;</label><label for="__tabbed_1_8">&lt;8&gt;</label><label for="__tabbed_1_9">&lt;9&gt;</label></div>
<div class="tabbed-set tabbed-alternate" data-tabs="1:19"><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" /><input id="__tabbed_1_5" name="__tabbed_1" type="radio" /><input id="__tabbed_1_6" name="__tabbed_1" type="radio" /><input id="__tabbed_1_7" name="__tabbed_1" type="radio" /><input id="__tabbed_1_8" name="__tabbed_1" type="radio" /><input id="__tabbed_1_9" name="__tabbed_1" type="radio" /><input id="__tabbed_1_10" name="__tabbed_1" type="radio" /><input id="__tabbed_1_11" name="__tabbed_1" type="radio" /><input id="__tabbed_1_12" name="__tabbed_1" type="radio" /><input id="__tabbed_1_13" name="__tabbed_1" type="radio" /><input id="__tabbed_1_14" name="__tabbed_1" type="radio" /><input id="__tabbed_1_15" name="__tabbed_1" type="radio" /><input id="__tabbed_1_16" name="__tabbed_1" type="radio" /><input id="__tabbed_1_17" name="__tabbed_1" type="radio" /><input id="__tabbed_1_18" name="__tabbed_1" type="radio" /><input id="__tabbed_1_19" 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><label for="__tabbed_1_5">&lt;5&gt;</label><label for="__tabbed_1_6">&lt;6&gt;</label><label for="__tabbed_1_7">&lt;7&gt;</label><label for="__tabbed_1_8">&lt;8&gt;</label><label for="__tabbed_1_9">&lt;9&gt;</label><label for="__tabbed_1_10">Java</label><label for="__tabbed_1_11">C++</label><label for="__tabbed_1_12">Python</label><label for="__tabbed_1_13">Go</label><label for="__tabbed_1_14">JavaScript</label><label for="__tabbed_1_15">TypeScript</label><label for="__tabbed_1_16">C</label><label for="__tabbed_1_17">C#</label><label for="__tabbed_1_18">Swift</label><label for="__tabbed_1_19">Zig</label></div>
<div class="tabbed-content">
<div class="tabbed-block">
<p><img alt="pivot_division_step1" src="../quick_sort.assets/pivot_division_step1.png" /></p>
@@ -1651,12 +1651,6 @@
<div class="tabbed-block">
<p><img alt="pivot_division_step9" src="../quick_sort.assets/pivot_division_step9.png" /></p>
</div>
</div>
</div>
<p align="center"> Fig. 哨兵划分 </p>
<div class="tabbed-set tabbed-alternate" data-tabs="2:10"><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" /><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></div>
<div class="tabbed-content">
<div class="tabbed-block">
<div class="highlight"><span class="filename">quick_sort.java</span><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="cm">/* 元素交换 */</span>
<a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a><span class="kt">void</span><span class="w"> </span><span class="nf">swap</span><span class="p">(</span><span class="kt">int</span><span class="o">[]</span><span class="w"> </span><span class="n">nums</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">j</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
@@ -1891,10 +1885,8 @@
<li>直至子数组长度为 1 时 <strong>终止递归</strong>,即可完成对整个数组的排序;</li>
</ol>
<p>观察发现,快速排序和「二分查找」的原理类似,都是以对数阶的时间复杂度来缩小处理区间。</p>
<p><img alt="quick_sort_overview" src="../quick_sort.assets/quick_sort_overview.png" /></p>
<p align="center"> Fig. 快速排序流程 </p>
<div class="tabbed-set tabbed-alternate" data-tabs="3:10"><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" /><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">JavaScript</label><label for="__tabbed_3_6">TypeScript</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></div>
<p><img alt="快速排序流程" src="../quick_sort.assets/quick_sort_overview.png" /></p>
<div class="tabbed-set tabbed-alternate" data-tabs="2:10"><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" /><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></div>
<div class="tabbed-content">
<div class="tabbed-block">
<div class="highlight"><span class="filename">quick_sort.java</span><pre><span></span><code><a id="__codelineno-10-1" name="__codelineno-10-1" href="#__codelineno-10-1"></a><span class="cm">/* 快速排序 */</span>
@@ -2047,7 +2039,7 @@
<p><strong>普通快速排序在某些输入下的时间效率变差</strong>。举个极端例子,假设输入数组是完全倒序的,由于我们选取最左端元素为基准数,那么在哨兵划分完成后,基准数被交换至数组最右端,从而 <strong>左子数组长度为 <span class="arithmatex">\(n - 1\)</span>、右子数组长度为 <span class="arithmatex">\(0\)</span></strong> 。这样进一步递归下去,<strong>每轮哨兵划分后的右子数组长度都为 <span class="arithmatex">\(0\)</span></strong> ,分治策略失效,快速排序退化为「冒泡排序」了。</p>
<p>为了尽量避免这种情况发生,我们可以优化一下基准数的选取策略。首先,在哨兵划分中,我们可以 <strong>随机选取一个元素作为基准数</strong>。但如果运气很差,每次都选择到比较差的基准数,那么效率依然不好。</p>
<p>进一步地,我们可以在数组中选取 3 个候选元素(一般为数组的首、尾、中点元素),<strong>并将三个候选元素的中位数作为基准数</strong>,这样基准数“既不大也不小”的概率就大大提升了。当然,如果数组很长的话,我们也可以选取更多候选元素,来进一步提升算法的稳健性。采取该方法后,时间复杂度劣化至 <span class="arithmatex">\(O(n^2)\)</span> 的概率极低。</p>
<div class="tabbed-set tabbed-alternate" data-tabs="4:10"><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" /><input id="__tabbed_4_5" name="__tabbed_4" type="radio" /><input id="__tabbed_4_6" name="__tabbed_4" type="radio" /><input id="__tabbed_4_7" name="__tabbed_4" type="radio" /><input id="__tabbed_4_8" name="__tabbed_4" type="radio" /><input id="__tabbed_4_9" name="__tabbed_4" type="radio" /><input id="__tabbed_4_10" name="__tabbed_4" type="radio" /><div class="tabbed-labels"><label for="__tabbed_4_1">Java</label><label for="__tabbed_4_2">C++</label><label for="__tabbed_4_3">Python</label><label for="__tabbed_4_4">Go</label><label for="__tabbed_4_5">JavaScript</label><label for="__tabbed_4_6">TypeScript</label><label for="__tabbed_4_7">C</label><label for="__tabbed_4_8">C#</label><label for="__tabbed_4_9">Swift</label><label for="__tabbed_4_10">Zig</label></div>
<div class="tabbed-set tabbed-alternate" data-tabs="3:10"><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" /><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">JavaScript</label><label for="__tabbed_3_6">TypeScript</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></div>
<div class="tabbed-content">
<div class="tabbed-block">
<div class="highlight"><span class="filename">quick_sort.java</span><pre><span></span><code><a id="__codelineno-20-1" name="__codelineno-20-1" href="#__codelineno-20-1"></a><span class="cm">/* 选取三个元素的中位数 */</span>
@@ -2349,7 +2341,7 @@
<h2 id="1145">11.4.5. &nbsp; 尾递归优化<a class="headerlink" href="#1145" title="Permanent link">&para;</a></h2>
<p><strong>普通快速排序在某些输入下的空间效率变差</strong>。仍然以完全倒序的输入数组为例,由于每轮哨兵划分后右子数组长度为 0 ,那么将形成一个高度为 <span class="arithmatex">\(n - 1\)</span> 的递归树,此时使用的栈帧空间大小劣化至 <span class="arithmatex">\(O(n)\)</span></p>
<p>为了避免栈帧空间的累积,我们可以在每轮哨兵排序完成后,判断两个子数组的长度大小,仅递归排序较短的子数组。由于较短的子数组长度不会超过 <span class="arithmatex">\(\frac{n}{2}\)</span> ,因此这样做能保证递归深度不超过 <span class="arithmatex">\(\log n\)</span> ,即最差空间复杂度被优化至 <span class="arithmatex">\(O(\log n)\)</span></p>
<div class="tabbed-set tabbed-alternate" data-tabs="5:10"><input checked="checked" id="__tabbed_5_1" name="__tabbed_5" type="radio" /><input id="__tabbed_5_2" name="__tabbed_5" type="radio" /><input id="__tabbed_5_3" name="__tabbed_5" type="radio" /><input id="__tabbed_5_4" name="__tabbed_5" type="radio" /><input id="__tabbed_5_5" name="__tabbed_5" type="radio" /><input id="__tabbed_5_6" name="__tabbed_5" type="radio" /><input id="__tabbed_5_7" name="__tabbed_5" type="radio" /><input id="__tabbed_5_8" name="__tabbed_5" type="radio" /><input id="__tabbed_5_9" name="__tabbed_5" type="radio" /><input id="__tabbed_5_10" name="__tabbed_5" type="radio" /><div class="tabbed-labels"><label for="__tabbed_5_1">Java</label><label for="__tabbed_5_2">C++</label><label for="__tabbed_5_3">Python</label><label for="__tabbed_5_4">Go</label><label for="__tabbed_5_5">JavaScript</label><label for="__tabbed_5_6">TypeScript</label><label for="__tabbed_5_7">C</label><label for="__tabbed_5_8">C#</label><label for="__tabbed_5_9">Swift</label><label for="__tabbed_5_10">Zig</label></div>
<div class="tabbed-set tabbed-alternate" data-tabs="4:10"><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" /><input id="__tabbed_4_5" name="__tabbed_4" type="radio" /><input id="__tabbed_4_6" name="__tabbed_4" type="radio" /><input id="__tabbed_4_7" name="__tabbed_4" type="radio" /><input id="__tabbed_4_8" name="__tabbed_4" type="radio" /><input id="__tabbed_4_9" name="__tabbed_4" type="radio" /><input id="__tabbed_4_10" name="__tabbed_4" type="radio" /><div class="tabbed-labels"><label for="__tabbed_4_1">Java</label><label for="__tabbed_4_2">C++</label><label for="__tabbed_4_3">Python</label><label for="__tabbed_4_4">Go</label><label for="__tabbed_4_5">JavaScript</label><label for="__tabbed_4_6">TypeScript</label><label for="__tabbed_4_7">C</label><label for="__tabbed_4_8">C#</label><label for="__tabbed_4_9">Swift</label><label for="__tabbed_4_10">Zig</label></div>
<div class="tabbed-content">
<div class="tabbed-block">
<div class="highlight"><span class="filename">quick_sort.java</span><pre><span></span><code><a id="__codelineno-30-1" name="__codelineno-30-1" href="#__codelineno-30-1"></a><span class="cm">/* 快速排序(尾递归优化) */</span>