After Width: | Height: | Size: 60 KiB |
@ -0,0 +1,74 @@
|
|||||||
|
---
|
||||||
|
comments: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# 排序算法
|
||||||
|
|
||||||
|
「排序算法 Sorting Algorithm」使得列表中的所有元素按照从小到大的顺序排列。
|
||||||
|
|
||||||
|
- 待排序的列表的 **元素类型** 可以是整数、浮点数、字符、或字符串;
|
||||||
|
- 排序算法可以根据需要设定 **判断规则** ,例如数字大小、字符 ASCII 码顺序、自定义规则;
|
||||||
|
|
||||||
|
![sorting_examples](index.assets/sorting_examples.png)
|
||||||
|
|
||||||
|
<p align="center"> Fig. 排序中的不同元素类型和判断规则 </p>
|
||||||
|
|
||||||
|
## 评价维度
|
||||||
|
|
||||||
|
排序算法主要可根据 **稳定性 、就地性 、自适应性 、比较类** 来分类。
|
||||||
|
|
||||||
|
### 稳定性
|
||||||
|
|
||||||
|
- 「稳定排序」在完成排序后,**不改变** 相等元素在数组中的相对顺序。
|
||||||
|
- 「非稳定排序」在完成排序后,相等素在数组中的相对位置 **可能被改变**。
|
||||||
|
|
||||||
|
假设我们有一个存储学生信息当表格,第 1, 2 列粉笔是姓名和年龄。那么在以下示例中,「非稳定排序」会导致输入数据的有序性丢失。因此「稳定排序」是很好的特性,**在多级排序中是必须的**。
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# 输入数据是按照姓名排序好的
|
||||||
|
# (name, age)
|
||||||
|
('A', 19)
|
||||||
|
('B', 18)
|
||||||
|
('C', 21)
|
||||||
|
('D', 19)
|
||||||
|
('E', 23)
|
||||||
|
|
||||||
|
# 假设使用非稳定排序算法按年龄排序列表,
|
||||||
|
# 结果中 ('D', 19) 和 ('A', 19) 的相对位置改变,
|
||||||
|
# 输入数据按姓名排序的性质丢失
|
||||||
|
('B', 18)
|
||||||
|
('D', 19)
|
||||||
|
('A', 19)
|
||||||
|
('C', 21)
|
||||||
|
('E', 23)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 就地性
|
||||||
|
|
||||||
|
- 「原地排序」无需辅助数据,不使用额外空间;
|
||||||
|
- 「非原地排序」需要借助辅助数据,使用额外空间;
|
||||||
|
|
||||||
|
「原地排序」不使用额外空间,可以节约内存;并且一般情况下,由于数据操作减少,原地排序的运行效率也更高。
|
||||||
|
|
||||||
|
### 自适应性
|
||||||
|
|
||||||
|
- 「自适应排序」的时间复杂度受输入数据影响,即最佳 / 最差 / 平均时间复杂度不相等。
|
||||||
|
- 「非自适应排序」的时间复杂度恒定,与输入数据无关。
|
||||||
|
|
||||||
|
我们希望 **最差 = 平均** ,即不希望排序算法的运行效率在某些输入数据下发生劣化。
|
||||||
|
|
||||||
|
### 比较类
|
||||||
|
|
||||||
|
- 「比较类排序」基于元素之间的比较算子(小于、相等、大于)来决定元素的相对顺序。
|
||||||
|
- 「非比较类排序」不基于元素之间的比较算子来决定元素的相对顺序。
|
||||||
|
|
||||||
|
「比较类排序」的时间复杂度最优为 $O(n \log n)$ ;而「非比较类排序」可以达到 $O(n)$ 的时间复杂度,但通用性较差。
|
||||||
|
|
||||||
|
## 理想排序算法
|
||||||
|
|
||||||
|
- **运行地快**,即时间复杂度低;
|
||||||
|
- **稳定排序**,即排序后相等元素的相对位置不变化;
|
||||||
|
- **原地排序**,即运行中不使用额外的辅助空间;
|
||||||
|
- **正向自适应性**,即算法的运行效率不会在某些输入数据下发生劣化;
|
||||||
|
|
||||||
|
然而,**没有排序算法同时具备以上所有特性**。排序算法的选型使用取决于具体的列表类型、列表长度、元素分布等因素。
|
After Width: | Height: | Size: 88 KiB |
After Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 50 KiB |
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
comments: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# 小结
|
||||||
|
|
@ -1,50 +0,0 @@
|
|||||||
{% if page.meta.comments %}
|
|
||||||
<h2 id="__comments">{{ lang.t("meta.comments") }}</h2>
|
|
||||||
<!-- Insert generated snippet here -->
|
|
||||||
<script
|
|
||||||
src="https://giscus.app/client.js"
|
|
||||||
data-repo="krahets/hello-algo"
|
|
||||||
data-repo-id="R_kgDOIXtSqw"
|
|
||||||
data-category="Announcements"
|
|
||||||
data-category-id="DIC_kwDOIXtSq84CSZk_"
|
|
||||||
data-mapping="pathname"
|
|
||||||
data-strict="0"
|
|
||||||
data-reactions-enabled="1"
|
|
||||||
data-emit-metadata="0"
|
|
||||||
data-input-position="bottom"
|
|
||||||
data-theme="preferred_color_scheme"
|
|
||||||
data-lang="zh-CN"
|
|
||||||
crossorigin="anonymous"
|
|
||||||
async
|
|
||||||
>
|
|
||||||
</script>
|
|
||||||
<!-- Synchronize Giscus theme with palette -->
|
|
||||||
<script>
|
|
||||||
var giscus = document.querySelector("script[src*=giscus]")
|
|
||||||
|
|
||||||
/* Set palette on initial load */
|
|
||||||
var palette = __md_get("__palette")
|
|
||||||
if (palette && typeof palette.color === "object") {
|
|
||||||
var theme = palette.color.scheme === "slate" ? "dark" : "light"
|
|
||||||
giscus.setAttribute("data-theme", theme)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Register event handlers after documented loaded */
|
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
|
||||||
var ref = document.querySelector("[data-md-component=palette]")
|
|
||||||
ref.addEventListener("change", function() {
|
|
||||||
var palette = __md_get("__palette")
|
|
||||||
if (palette && typeof palette.color === "object") {
|
|
||||||
var theme = palette.color.scheme === "slate" ? "dark" : "light"
|
|
||||||
|
|
||||||
/* Instruct Giscus to change theme */
|
|
||||||
var frame = document.querySelector(".giscus-frame")
|
|
||||||
frame.contentWindow.postMessage(
|
|
||||||
{ giscus: { setConfig: { theme } } },
|
|
||||||
"https://giscus.app"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
{% endif %}
|
|