Sort the coding languages by applications. (#721)

This commit is contained in:
Yudong Jin
2023-09-04 03:19:08 +08:00
committed by GitHub
parent 8d5e84f70a
commit 9c3b7b6422
55 changed files with 6826 additions and 6826 deletions

View File

@ -36,10 +36,10 @@
![冒泡排序流程](bubble_sort.assets/bubble_sort_overview.png)
=== "Java"
=== "Python"
```java title="bubble_sort.java"
[class]{bubble_sort}-[func]{bubbleSort}
```python title="bubble_sort.py"
[class]{}-[func]{bubble_sort}
```
=== "C++"
@ -48,10 +48,16 @@
[class]{}-[func]{bubbleSort}
```
=== "Python"
=== "Java"
```python title="bubble_sort.py"
[class]{}-[func]{bubble_sort}
```java title="bubble_sort.java"
[class]{bubble_sort}-[func]{bubbleSort}
```
=== "C#"
```csharp title="bubble_sort.cs"
[class]{bubble_sort}-[func]{bubbleSort}
```
=== "Go"
@ -60,6 +66,12 @@
[class]{}-[func]{bubbleSort}
```
=== "Swift"
```swift title="bubble_sort.swift"
[class]{}-[func]{bubbleSort}
```
=== "JS"
```javascript title="bubble_sort.js"
@ -72,30 +84,6 @@
[class]{}-[func]{bubbleSort}
```
=== "C"
```c title="bubble_sort.c"
[class]{}-[func]{bubbleSort}
```
=== "C#"
```csharp title="bubble_sort.cs"
[class]{bubble_sort}-[func]{bubbleSort}
```
=== "Swift"
```swift title="bubble_sort.swift"
[class]{}-[func]{bubbleSort}
```
=== "Zig"
```zig title="bubble_sort.zig"
[class]{}-[func]{bubbleSort}
```
=== "Dart"
```dart title="bubble_sort.dart"
@ -108,16 +96,28 @@
[class]{}-[func]{bubble_sort}
```
=== "C"
```c title="bubble_sort.c"
[class]{}-[func]{bubbleSort}
```
=== "Zig"
```zig title="bubble_sort.zig"
[class]{}-[func]{bubbleSort}
```
## 效率优化
我们发现,如果某轮“冒泡”中没有执行任何交换操作,说明数组已经完成排序,可直接返回结果。因此,可以增加一个标志位 `flag` 来监测这种情况,一旦出现就立即返回。
经过优化,冒泡排序的最差和平均时间复杂度仍为 $O(n^2)$ ;但当输入数组完全有序时,可达到最佳时间复杂度 $O(n)$ 。
=== "Java"
=== "Python"
```java title="bubble_sort.java"
[class]{bubble_sort}-[func]{bubbleSortWithFlag}
```python title="bubble_sort.py"
[class]{}-[func]{bubble_sort_with_flag}
```
=== "C++"
@ -126,10 +126,16 @@
[class]{}-[func]{bubbleSortWithFlag}
```
=== "Python"
=== "Java"
```python title="bubble_sort.py"
[class]{}-[func]{bubble_sort_with_flag}
```java title="bubble_sort.java"
[class]{bubble_sort}-[func]{bubbleSortWithFlag}
```
=== "C#"
```csharp title="bubble_sort.cs"
[class]{bubble_sort}-[func]{bubbleSortWithFlag}
```
=== "Go"
@ -138,6 +144,12 @@
[class]{}-[func]{bubbleSortWithFlag}
```
=== "Swift"
```swift title="bubble_sort.swift"
[class]{}-[func]{bubbleSortWithFlag}
```
=== "JS"
```javascript title="bubble_sort.js"
@ -150,30 +162,6 @@
[class]{}-[func]{bubbleSortWithFlag}
```
=== "C"
```c title="bubble_sort.c"
[class]{}-[func]{bubbleSortWithFlag}
```
=== "C#"
```csharp title="bubble_sort.cs"
[class]{bubble_sort}-[func]{bubbleSortWithFlag}
```
=== "Swift"
```swift title="bubble_sort.swift"
[class]{}-[func]{bubbleSortWithFlag}
```
=== "Zig"
```zig title="bubble_sort.zig"
[class]{}-[func]{bubbleSortWithFlag}
```
=== "Dart"
```dart title="bubble_sort.dart"
@ -186,6 +174,18 @@
[class]{}-[func]{bubble_sort_with_flag}
```
=== "C"
```c title="bubble_sort.c"
[class]{}-[func]{bubbleSortWithFlag}
```
=== "Zig"
```zig title="bubble_sort.zig"
[class]{}-[func]{bubbleSortWithFlag}
```
## 算法特性
- **时间复杂度为 $O(n^2)$、自适应排序**:各轮“冒泡”遍历的数组长度依次为 $n - 1$、$n - 2$、$\dots$、$2$、$1$ ,总和为 $(n - 1) n / 2$ 。在引入 `flag` 优化后,最佳时间复杂度可达到 $O(n)$ 。

View File

@ -14,10 +14,10 @@
![桶排序算法流程](bucket_sort.assets/bucket_sort_overview.png)
=== "Java"
=== "Python"
```java title="bucket_sort.java"
[class]{bucket_sort}-[func]{bucketSort}
```python title="bucket_sort.py"
[class]{}-[func]{bucket_sort}
```
=== "C++"
@ -26,10 +26,16 @@
[class]{}-[func]{bucketSort}
```
=== "Python"
=== "Java"
```python title="bucket_sort.py"
[class]{}-[func]{bucket_sort}
```java title="bucket_sort.java"
[class]{bucket_sort}-[func]{bucketSort}
```
=== "C#"
```csharp title="bucket_sort.cs"
[class]{bucket_sort}-[func]{bucketSort}
```
=== "Go"
@ -38,6 +44,12 @@
[class]{}-[func]{bucketSort}
```
=== "Swift"
```swift title="bucket_sort.swift"
[class]{}-[func]{bucketSort}
```
=== "JS"
```javascript title="bucket_sort.js"
@ -50,30 +62,6 @@
[class]{}-[func]{bucketSort}
```
=== "C"
```c title="bucket_sort.c"
[class]{}-[func]{bucketSort}
```
=== "C#"
```csharp title="bucket_sort.cs"
[class]{bucket_sort}-[func]{bucketSort}
```
=== "Swift"
```swift title="bucket_sort.swift"
[class]{}-[func]{bucketSort}
```
=== "Zig"
```zig title="bucket_sort.zig"
[class]{}-[func]{bucketSort}
```
=== "Dart"
```dart title="bucket_sort.dart"
@ -86,6 +74,18 @@
[class]{}-[func]{bucket_sort}
```
=== "C"
```c title="bucket_sort.c"
[class]{}-[func]{bucketSort}
```
=== "Zig"
```zig title="bucket_sort.zig"
[class]{}-[func]{bucketSort}
```
## 算法特性
桶排序适用于处理体量很大的数据。例如,输入数据包含 100 万个元素,由于空间限制,系统内存无法一次性加载所有数据。此时,可以将数据分成 1000 个桶,然后分别对每个桶进行排序,最后将结果合并。

View File

@ -12,10 +12,10 @@
![计数排序流程](counting_sort.assets/counting_sort_overview.png)
=== "Java"
=== "Python"
```java title="counting_sort.java"
[class]{counting_sort}-[func]{countingSortNaive}
```python title="counting_sort.py"
[class]{}-[func]{counting_sort_naive}
```
=== "C++"
@ -24,10 +24,16 @@
[class]{}-[func]{countingSortNaive}
```
=== "Python"
=== "Java"
```python title="counting_sort.py"
[class]{}-[func]{counting_sort_naive}
```java title="counting_sort.java"
[class]{counting_sort}-[func]{countingSortNaive}
```
=== "C#"
```csharp title="counting_sort.cs"
[class]{counting_sort}-[func]{countingSortNaive}
```
=== "Go"
@ -36,6 +42,12 @@
[class]{}-[func]{countingSortNaive}
```
=== "Swift"
```swift title="counting_sort.swift"
[class]{}-[func]{countingSortNaive}
```
=== "JS"
```javascript title="counting_sort.js"
@ -48,30 +60,6 @@
[class]{}-[func]{countingSortNaive}
```
=== "C"
```c title="counting_sort.c"
[class]{}-[func]{countingSortNaive}
```
=== "C#"
```csharp title="counting_sort.cs"
[class]{counting_sort}-[func]{countingSortNaive}
```
=== "Swift"
```swift title="counting_sort.swift"
[class]{}-[func]{countingSortNaive}
```
=== "Zig"
```zig title="counting_sort.zig"
[class]{}-[func]{countingSortNaive}
```
=== "Dart"
```dart title="counting_sort.dart"
@ -84,6 +72,18 @@
[class]{}-[func]{counting_sort_naive}
```
=== "C"
```c title="counting_sort.c"
[class]{}-[func]{countingSortNaive}
```
=== "Zig"
```zig title="counting_sort.zig"
[class]{}-[func]{countingSortNaive}
```
!!! note "计数排序与桶排序的联系"
从桶排序的角度看,我们可以将计数排序中的计数数组 `counter` 的每个索引视为一个桶,将统计数量的过程看作是将各个元素分配到对应的桶中。本质上,计数排序是桶排序在整型数据下的一个特例。
@ -131,10 +131,10 @@ $$
计数排序的实现代码如下所示。
=== "Java"
=== "Python"
```java title="counting_sort.java"
[class]{counting_sort}-[func]{countingSort}
```python title="counting_sort.py"
[class]{}-[func]{counting_sort}
```
=== "C++"
@ -143,10 +143,16 @@ $$
[class]{}-[func]{countingSort}
```
=== "Python"
=== "Java"
```python title="counting_sort.py"
[class]{}-[func]{counting_sort}
```java title="counting_sort.java"
[class]{counting_sort}-[func]{countingSort}
```
=== "C#"
```csharp title="counting_sort.cs"
[class]{counting_sort}-[func]{countingSort}
```
=== "Go"
@ -155,6 +161,12 @@ $$
[class]{}-[func]{countingSort}
```
=== "Swift"
```swift title="counting_sort.swift"
[class]{}-[func]{countingSort}
```
=== "JS"
```javascript title="counting_sort.js"
@ -167,30 +179,6 @@ $$
[class]{}-[func]{countingSort}
```
=== "C"
```c title="counting_sort.c"
[class]{}-[func]{countingSort}
```
=== "C#"
```csharp title="counting_sort.cs"
[class]{counting_sort}-[func]{countingSort}
```
=== "Swift"
```swift title="counting_sort.swift"
[class]{}-[func]{countingSort}
```
=== "Zig"
```zig title="counting_sort.zig"
[class]{}-[func]{countingSort}
```
=== "Dart"
```dart title="counting_sort.dart"
@ -203,6 +191,18 @@ $$
[class]{}-[func]{counting_sort}
```
=== "C"
```c title="counting_sort.c"
[class]{}-[func]{countingSort}
```
=== "Zig"
```zig title="counting_sort.zig"
[class]{}-[func]{countingSort}
```
## 算法特性
- **时间复杂度 $O(n + m)$** :涉及遍历 `nums` 和遍历 `counter` ,都使用线性时间。一般情况下 $n \gg m$ ,时间复杂度趋于 $O(n)$ 。

View File

@ -62,12 +62,12 @@
在代码实现中,我们使用了与堆章节相同的从顶至底堆化 `sift_down()` 函数。值得注意的是,由于堆的长度会随着提取最大元素而减小,因此我们需要给 `sift_down()` 函数添加一个长度参数 $n$ ,用于指定堆的当前有效长度。
=== "Java"
=== "Python"
```java title="heap_sort.java"
[class]{heap_sort}-[func]{siftDown}
```python title="heap_sort.py"
[class]{}-[func]{sift_down}
[class]{heap_sort}-[func]{heapSort}
[class]{}-[func]{heap_sort}
```
=== "C++"
@ -78,12 +78,20 @@
[class]{}-[func]{heapSort}
```
=== "Python"
=== "Java"
```python title="heap_sort.py"
[class]{}-[func]{sift_down}
```java title="heap_sort.java"
[class]{heap_sort}-[func]{siftDown}
[class]{}-[func]{heap_sort}
[class]{heap_sort}-[func]{heapSort}
```
=== "C#"
```csharp title="heap_sort.cs"
[class]{heap_sort}-[func]{siftDown}
[class]{heap_sort}-[func]{heapSort}
```
=== "Go"
@ -94,6 +102,14 @@
[class]{}-[func]{heapSort}
```
=== "Swift"
```swift title="heap_sort.swift"
[class]{}-[func]{siftDown}
[class]{}-[func]{heapSort}
```
=== "JS"
```javascript title="heap_sort.js"
@ -110,38 +126,6 @@
[class]{}-[func]{heapSort}
```
=== "C"
```c title="heap_sort.c"
[class]{}-[func]{siftDown}
[class]{}-[func]{heapSort}
```
=== "C#"
```csharp title="heap_sort.cs"
[class]{heap_sort}-[func]{siftDown}
[class]{heap_sort}-[func]{heapSort}
```
=== "Swift"
```swift title="heap_sort.swift"
[class]{}-[func]{siftDown}
[class]{}-[func]{heapSort}
```
=== "Zig"
```zig title="heap_sort.zig"
[class]{}-[func]{siftDown}
[class]{}-[func]{heapSort}
```
=== "Dart"
```dart title="heap_sort.dart"
@ -158,6 +142,22 @@
[class]{}-[func]{heap_sort}
```
=== "C"
```c title="heap_sort.c"
[class]{}-[func]{siftDown}
[class]{}-[func]{heapSort}
```
=== "Zig"
```zig title="heap_sort.zig"
[class]{}-[func]{siftDown}
[class]{}-[func]{heapSort}
```
## 算法特性
- **时间复杂度 $O(n \log n)$、非自适应排序**:建堆操作使用 $O(n)$ 时间。从堆中提取最大元素的时间复杂度为 $O(\log n)$ ,共循环 $n - 1$ 轮。

View File

@ -19,10 +19,10 @@
![插入排序流程](insertion_sort.assets/insertion_sort_overview.png)
=== "Java"
=== "Python"
```java title="insertion_sort.java"
[class]{insertion_sort}-[func]{insertionSort}
```python title="insertion_sort.py"
[class]{}-[func]{insertion_sort}
```
=== "C++"
@ -31,10 +31,16 @@
[class]{}-[func]{insertionSort}
```
=== "Python"
=== "Java"
```python title="insertion_sort.py"
[class]{}-[func]{insertion_sort}
```java title="insertion_sort.java"
[class]{insertion_sort}-[func]{insertionSort}
```
=== "C#"
```csharp title="insertion_sort.cs"
[class]{insertion_sort}-[func]{insertionSort}
```
=== "Go"
@ -43,6 +49,12 @@
[class]{}-[func]{insertionSort}
```
=== "Swift"
```swift title="insertion_sort.swift"
[class]{}-[func]{insertionSort}
```
=== "JS"
```javascript title="insertion_sort.js"
@ -55,30 +67,6 @@
[class]{}-[func]{insertionSort}
```
=== "C"
```c title="insertion_sort.c"
[class]{}-[func]{insertionSort}
```
=== "C#"
```csharp title="insertion_sort.cs"
[class]{insertion_sort}-[func]{insertionSort}
```
=== "Swift"
```swift title="insertion_sort.swift"
[class]{}-[func]{insertionSort}
```
=== "Zig"
```zig title="insertion_sort.zig"
[class]{}-[func]{insertionSort}
```
=== "Dart"
```dart title="insertion_sort.dart"
@ -91,6 +79,18 @@
[class]{}-[func]{insertion_sort}
```
=== "C"
```c title="insertion_sort.c"
[class]{}-[func]{insertionSort}
```
=== "Zig"
```zig title="insertion_sort.zig"
[class]{}-[func]{insertionSort}
```
## 算法特性
- **时间复杂度 $O(n^2)$、自适应排序**:最差情况下,每次插入操作分别需要循环 $n - 1$、$n-2$、$\dots$、$2$、$1$ 次,求和得到 $(n - 1) n / 2$ ,因此时间复杂度为 $O(n^2)$ 。在遇到有序数据时,插入操作会提前终止。当输入数组完全有序时,插入排序达到最佳时间复杂度 $O(n)$ 。

View File

@ -51,12 +51,12 @@
- **后序遍历**:先递归左子树,再递归右子树,最后处理根节点。
- **归并排序**:先递归左子数组,再递归右子数组,最后处理合并。
=== "Java"
=== "Python"
```java title="merge_sort.java"
[class]{merge_sort}-[func]{merge}
```python title="merge_sort.py"
[class]{}-[func]{merge}
[class]{merge_sort}-[func]{mergeSort}
[class]{}-[func]{merge_sort}
```
=== "C++"
@ -67,12 +67,20 @@
[class]{}-[func]{mergeSort}
```
=== "Python"
=== "Java"
```python title="merge_sort.py"
[class]{}-[func]{merge}
```java title="merge_sort.java"
[class]{merge_sort}-[func]{merge}
[class]{}-[func]{merge_sort}
[class]{merge_sort}-[func]{mergeSort}
```
=== "C#"
```csharp title="merge_sort.cs"
[class]{merge_sort}-[func]{merge}
[class]{merge_sort}-[func]{mergeSort}
```
=== "Go"
@ -83,6 +91,14 @@
[class]{}-[func]{mergeSort}
```
=== "Swift"
```swift title="merge_sort.swift"
[class]{}-[func]{merge}
[class]{}-[func]{mergeSort}
```
=== "JS"
```javascript title="merge_sort.js"
@ -99,38 +115,6 @@
[class]{}-[func]{mergeSort}
```
=== "C"
```c title="merge_sort.c"
[class]{}-[func]{merge}
[class]{}-[func]{mergeSort}
```
=== "C#"
```csharp title="merge_sort.cs"
[class]{merge_sort}-[func]{merge}
[class]{merge_sort}-[func]{mergeSort}
```
=== "Swift"
```swift title="merge_sort.swift"
[class]{}-[func]{merge}
[class]{}-[func]{mergeSort}
```
=== "Zig"
```zig title="merge_sort.zig"
[class]{}-[func]{merge}
[class]{}-[func]{mergeSort}
```
=== "Dart"
```dart title="merge_sort.dart"
@ -147,6 +131,22 @@
[class]{}-[func]{merge_sort}
```
=== "C"
```c title="merge_sort.c"
[class]{}-[func]{merge}
[class]{}-[func]{mergeSort}
```
=== "Zig"
```zig title="merge_sort.zig"
[class]{}-[func]{merge}
[class]{}-[func]{mergeSort}
```
实现合并函数 `merge()` 存在以下难点。
- **需要特别注意各个变量的含义**。`nums` 的待合并区间为 `[left, right]` ,但由于 `tmp` 仅复制了 `nums` 该区间的元素,因此 `tmp` 对应区间为 `[0, right - left]` 。

View File

@ -41,11 +41,9 @@
哨兵划分的实质是将一个较长数组的排序问题简化为两个较短数组的排序问题。
=== "Java"
```java title="quick_sort.java"
[class]{QuickSort}-[func]{swap}
=== "Python"
```python title="quick_sort.py"
[class]{QuickSort}-[func]{partition}
```
@ -57,9 +55,19 @@
[class]{QuickSort}-[func]{partition}
```
=== "Python"
=== "Java"
```java title="quick_sort.java"
[class]{QuickSort}-[func]{swap}
[class]{QuickSort}-[func]{partition}
```
=== "C#"
```csharp title="quick_sort.cs"
[class]{QuickSort}-[func]{swap}
```python title="quick_sort.py"
[class]{QuickSort}-[func]{partition}
```
@ -69,6 +77,14 @@
[class]{quickSort}-[func]{partition}
```
=== "Swift"
```swift title="quick_sort.swift"
[class]{}-[func]{swap}
[class]{}-[func]{partition}
```
=== "JS"
```javascript title="quick_sort.js"
@ -85,38 +101,6 @@
[class]{QuickSort}-[func]{partition}
```
=== "C"
```c title="quick_sort.c"
[class]{}-[func]{swap}
[class]{}-[func]{partition}
```
=== "C#"
```csharp title="quick_sort.cs"
[class]{QuickSort}-[func]{swap}
[class]{QuickSort}-[func]{partition}
```
=== "Swift"
```swift title="quick_sort.swift"
[class]{}-[func]{swap}
[class]{}-[func]{partition}
```
=== "Zig"
```zig title="quick_sort.zig"
[class]{QuickSort}-[func]{swap}
[class]{QuickSort}-[func]{partition}
```
=== "Dart"
```dart title="quick_sort.dart"
@ -131,6 +115,22 @@
[class]{QuickSort}-[func]{partition}
```
=== "C"
```c title="quick_sort.c"
[class]{}-[func]{swap}
[class]{}-[func]{partition}
```
=== "Zig"
```zig title="quick_sort.zig"
[class]{QuickSort}-[func]{swap}
[class]{QuickSort}-[func]{partition}
```
## 算法流程
快速排序的整体流程如下图所示。
@ -141,10 +141,10 @@
![快速排序流程](quick_sort.assets/quick_sort_overview.png)
=== "Java"
=== "Python"
```java title="quick_sort.java"
[class]{QuickSort}-[func]{quickSort}
```python title="quick_sort.py"
[class]{QuickSort}-[func]{quick_sort}
```
=== "C++"
@ -153,10 +153,16 @@
[class]{QuickSort}-[func]{quickSort}
```
=== "Python"
=== "Java"
```python title="quick_sort.py"
[class]{QuickSort}-[func]{quick_sort}
```java title="quick_sort.java"
[class]{QuickSort}-[func]{quickSort}
```
=== "C#"
```csharp title="quick_sort.cs"
[class]{QuickSort}-[func]{quickSort}
```
=== "Go"
@ -165,6 +171,12 @@
[class]{quickSort}-[func]{quickSort}
```
=== "Swift"
```swift title="quick_sort.swift"
[class]{}-[func]{quickSort}
```
=== "JS"
```javascript title="quick_sort.js"
@ -177,30 +189,6 @@
[class]{QuickSort}-[func]{quickSort}
```
=== "C"
```c title="quick_sort.c"
[class]{}-[func]{quickSort}
```
=== "C#"
```csharp title="quick_sort.cs"
[class]{QuickSort}-[func]{quickSort}
```
=== "Swift"
```swift title="quick_sort.swift"
[class]{}-[func]{quickSort}
```
=== "Zig"
```zig title="quick_sort.zig"
[class]{QuickSort}-[func]{quickSort}
```
=== "Dart"
```dart title="quick_sort.dart"
@ -213,6 +201,18 @@
[class]{QuickSort}-[func]{quick_sort}
```
=== "C"
```c title="quick_sort.c"
[class]{}-[func]{quickSort}
```
=== "Zig"
```zig title="quick_sort.zig"
[class]{QuickSort}-[func]{quickSort}
```
## 算法特性
- **时间复杂度 $O(n \log n)$、自适应排序**:在平均情况下,哨兵划分的递归层数为 $\log n$ ,每层中的总循环数为 $n$ ,总体使用 $O(n \log n)$ 时间。在最差情况下,每轮哨兵划分操作都将长度为 $n$ 的数组划分为长度为 $0$ 和 $n - 1$ 的两个子数组,此时递归层数达到 $n$ 层,每层中的循环数为 $n$ ,总体使用 $O(n^2)$ 时间。
@ -237,10 +237,10 @@
为了进一步改进,我们可以在数组中选取三个候选元素(通常为数组的首、尾、中点元素),**并将这三个候选元素的中位数作为基准数**。这样一来,基准数“既不太小也不太大”的概率将大幅提升。当然,我们还可以选取更多候选元素,以进一步提高算法的稳健性。采用这种方法后,时间复杂度劣化至 $O(n^2)$ 的概率大大降低。
=== "Java"
=== "Python"
```java title="quick_sort.java"
[class]{QuickSortMedian}-[func]{medianThree}
```python title="quick_sort.py"
[class]{QuickSortMedian}-[func]{median_three}
[class]{QuickSortMedian}-[func]{partition}
```
@ -253,10 +253,18 @@
[class]{QuickSortMedian}-[func]{partition}
```
=== "Python"
=== "Java"
```python title="quick_sort.py"
[class]{QuickSortMedian}-[func]{median_three}
```java title="quick_sort.java"
[class]{QuickSortMedian}-[func]{medianThree}
[class]{QuickSortMedian}-[func]{partition}
```
=== "C#"
```csharp title="quick_sort.cs"
[class]{QuickSortMedian}-[func]{medianThree}
[class]{QuickSortMedian}-[func]{partition}
```
@ -269,6 +277,14 @@
[class]{quickSortMedian}-[func]{partition}
```
=== "Swift"
```swift title="quick_sort.swift"
[class]{}-[func]{medianThree}
[class]{}-[func]{partitionMedian}
```
=== "JS"
```javascript title="quick_sort.js"
@ -285,38 +301,6 @@
[class]{QuickSortMedian}-[func]{partition}
```
=== "C"
```c title="quick_sort.c"
[class]{}-[func]{medianThree}
[class]{}-[func]{partitionMedian}
```
=== "C#"
```csharp title="quick_sort.cs"
[class]{QuickSortMedian}-[func]{medianThree}
[class]{QuickSortMedian}-[func]{partition}
```
=== "Swift"
```swift title="quick_sort.swift"
[class]{}-[func]{medianThree}
[class]{}-[func]{partitionMedian}
```
=== "Zig"
```zig title="quick_sort.zig"
[class]{QuickSortMedian}-[func]{medianThree}
[class]{QuickSortMedian}-[func]{partition}
```
=== "Dart"
```dart title="quick_sort.dart"
@ -333,16 +317,32 @@
[class]{QuickSortMedian}-[func]{partition}
```
=== "C"
```c title="quick_sort.c"
[class]{}-[func]{medianThree}
[class]{}-[func]{partitionMedian}
```
=== "Zig"
```zig title="quick_sort.zig"
[class]{QuickSortMedian}-[func]{medianThree}
[class]{QuickSortMedian}-[func]{partition}
```
## 尾递归优化
**在某些输入下,快速排序可能占用空间较多**。以完全倒序的输入数组为例,由于每轮哨兵划分后右子数组长度为 $0$ ,递归树的高度会达到 $n - 1$ ,此时需要占用 $O(n)$ 大小的栈帧空间。
为了防止栈帧空间的累积,我们可以在每轮哨兵排序完成后,比较两个子数组的长度,**仅对较短的子数组进行递归**。由于较短子数组的长度不会超过 $n / 2$ ,因此这种方法能确保递归深度不超过 $\log n$ ,从而将最差空间复杂度优化至 $O(\log n)$ 。
=== "Java"
=== "Python"
```java title="quick_sort.java"
[class]{QuickSortTailCall}-[func]{quickSort}
```python title="quick_sort.py"
[class]{QuickSortTailCall}-[func]{quick_sort}
```
=== "C++"
@ -351,10 +351,16 @@
[class]{QuickSortTailCall}-[func]{quickSort}
```
=== "Python"
=== "Java"
```python title="quick_sort.py"
[class]{QuickSortTailCall}-[func]{quick_sort}
```java title="quick_sort.java"
[class]{QuickSortTailCall}-[func]{quickSort}
```
=== "C#"
```csharp title="quick_sort.cs"
[class]{QuickSortTailCall}-[func]{quickSort}
```
=== "Go"
@ -363,6 +369,12 @@
[class]{quickSortTailCall}-[func]{quickSort}
```
=== "Swift"
```swift title="quick_sort.swift"
[class]{}-[func]{quickSortTailCall}
```
=== "JS"
```javascript title="quick_sort.js"
@ -375,30 +387,6 @@
[class]{QuickSortTailCall}-[func]{quickSort}
```
=== "C"
```c title="quick_sort.c"
[class]{}-[func]{quickSortTailCall}
```
=== "C#"
```csharp title="quick_sort.cs"
[class]{QuickSortTailCall}-[func]{quickSort}
```
=== "Swift"
```swift title="quick_sort.swift"
[class]{}-[func]{quickSortTailCall}
```
=== "Zig"
```zig title="quick_sort.zig"
[class]{QuickSortTailCall}-[func]{quickSort}
```
=== "Dart"
```dart title="quick_sort.dart"
@ -410,3 +398,15 @@
```rust title="quick_sort.rs"
[class]{QuickSortTailCall}-[func]{quick_sort}
```
=== "C"
```c title="quick_sort.c"
[class]{}-[func]{quickSortTailCall}
```
=== "Zig"
```zig title="quick_sort.zig"
[class]{QuickSortTailCall}-[func]{quickSort}
```

View File

@ -24,14 +24,14 @@ $$
此外,我们需要小幅改动计数排序代码,使之可以根据数字的第 $k$ 位进行排序。
=== "Java"
=== "Python"
```java title="radix_sort.java"
[class]{radix_sort}-[func]{digit}
```python title="radix_sort.py"
[class]{}-[func]{digit}
[class]{radix_sort}-[func]{countingSortDigit}
[class]{}-[func]{counting_sort_digit}
[class]{radix_sort}-[func]{radixSort}
[class]{}-[func]{radix_sort}
```
=== "C++"
@ -44,14 +44,24 @@ $$
[class]{}-[func]{radixSort}
```
=== "Python"
=== "Java"
```python title="radix_sort.py"
[class]{}-[func]{digit}
```java title="radix_sort.java"
[class]{radix_sort}-[func]{digit}
[class]{}-[func]{counting_sort_digit}
[class]{radix_sort}-[func]{countingSortDigit}
[class]{}-[func]{radix_sort}
[class]{radix_sort}-[func]{radixSort}
```
=== "C#"
```csharp title="radix_sort.cs"
[class]{radix_sort}-[func]{digit}
[class]{radix_sort}-[func]{countingSortDigit}
[class]{radix_sort}-[func]{radixSort}
```
=== "Go"
@ -64,6 +74,16 @@ $$
[class]{}-[func]{radixSort}
```
=== "Swift"
```swift title="radix_sort.swift"
[class]{}-[func]{digit}
[class]{}-[func]{countingSortDigit}
[class]{}-[func]{radixSort}
```
=== "JS"
```javascript title="radix_sort.js"
@ -84,46 +104,6 @@ $$
[class]{}-[func]{radixSort}
```
=== "C"
```c title="radix_sort.c"
[class]{}-[func]{digit}
[class]{}-[func]{countingSortDigit}
[class]{}-[func]{radixSort}
```
=== "C#"
```csharp title="radix_sort.cs"
[class]{radix_sort}-[func]{digit}
[class]{radix_sort}-[func]{countingSortDigit}
[class]{radix_sort}-[func]{radixSort}
```
=== "Swift"
```swift title="radix_sort.swift"
[class]{}-[func]{digit}
[class]{}-[func]{countingSortDigit}
[class]{}-[func]{radixSort}
```
=== "Zig"
```zig title="radix_sort.zig"
[class]{}-[func]{digit}
[class]{}-[func]{countingSortDigit}
[class]{}-[func]{radixSort}
```
=== "Dart"
```dart title="radix_sort.dart"
@ -144,6 +124,26 @@ $$
[class]{}-[func]{radix_sort}
```
=== "C"
```c title="radix_sort.c"
[class]{}-[func]{digit}
[class]{}-[func]{countingSortDigit}
[class]{}-[func]{radixSort}
```
=== "Zig"
```zig title="radix_sort.zig"
[class]{}-[func]{digit}
[class]{}-[func]{countingSortDigit}
[class]{}-[func]{radixSort}
```
!!! question "为什么从最低位开始排序?"
在连续的排序轮次中,后一轮排序会覆盖前一轮排序的结果。举例来说,如果第一轮排序结果 $a < b$ ,而第二轮排序结果 $a > b$ ,那么第二轮的结果将取代第一轮的结果。由于数字的高位优先级高于低位,我们应该先排序低位再排序高位。

View File

@ -45,10 +45,10 @@
在代码中,我们用 $k$ 来记录未排序区间内的最小元素。
=== "Java"
=== "Python"
```java title="selection_sort.java"
[class]{selection_sort}-[func]{selectionSort}
```python title="selection_sort.py"
[class]{}-[func]{selection_sort}
```
=== "C++"
@ -57,10 +57,16 @@
[class]{}-[func]{selectionSort}
```
=== "Python"
=== "Java"
```python title="selection_sort.py"
[class]{}-[func]{selection_sort}
```java title="selection_sort.java"
[class]{selection_sort}-[func]{selectionSort}
```
=== "C#"
```csharp title="selection_sort.cs"
[class]{selection_sort}-[func]{selectionSort}
```
=== "Go"
@ -69,6 +75,12 @@
[class]{}-[func]{selectionSort}
```
=== "Swift"
```swift title="selection_sort.swift"
[class]{}-[func]{selectionSort}
```
=== "JS"
```javascript title="selection_sort.js"
@ -81,30 +93,6 @@
[class]{}-[func]{selectionSort}
```
=== "C"
```c title="selection_sort.c"
[class]{}-[func]{selectionSort}
```
=== "C#"
```csharp title="selection_sort.cs"
[class]{selection_sort}-[func]{selectionSort}
```
=== "Swift"
```swift title="selection_sort.swift"
[class]{}-[func]{selectionSort}
```
=== "Zig"
```zig title="selection_sort.zig"
[class]{}-[func]{selectionSort}
```
=== "Dart"
```dart title="selection_sort.dart"
@ -117,6 +105,18 @@
[class]{}-[func]{selection_sort}
```
=== "C"
```c title="selection_sort.c"
[class]{}-[func]{selectionSort}
```
=== "Zig"
```zig title="selection_sort.zig"
[class]{}-[func]{selectionSort}
```
## 算法特性
- **时间复杂度为 $O(n^2)$、非自适应排序**:外循环共 $n - 1$ 轮,第一轮的未排序区间长度为 $n$ ,最后一轮的未排序区间长度为 $2$ ,即各轮外循环分别包含 $n$、$n - 1$、$\dots$、$3$、$2$ 轮内循环,求和为 $\frac{(n - 1)(n + 2)}{2}$ 。