算法 - 排序 - 交换排序 (Swap Sort)

本文介绍了交换排序的概念,包括冒泡排序和快速排序,并提供了这两种排序算法的C++实现。冒泡排序通过n-1次冒泡进行排序,而快速排序是一种递归的分区过程。文章包含性能分析和详细代码展示。

算法 - 排序 - 交换排序 (Swap Sort)

返回分类:全部文章 >> 基础知识

返回上级:算法 - 查找与排序 (Searching and Sorting)

常用交换排序:

  • 冒泡排序(Bubble Sort),也称起泡排序;

  • 快速排序(Quick Sort),也称分区排序,它也是一个递归的过程。

本文将用C++实现插入冒泡排序和快速排序算法。

在查看本文之前,需要一些程序语言的基础。

所有排序方法中,统一使用如下库与结构:

// Author: https://blog.youkuaiyun.com/DarkRabbit
// Sorted Dependency

#pragma once

#include <algorithm>
#include <vector>
#include <stack>

template<typename T>
struct MyItem
{
   
   
    int key;
    T data;

    MyItem(){
   
    key = -1; }
    MyItem(const int& k) : key(k){
   
    }
    MyItem(const int& k, const T& d) : key(k), data(d){
   
    }
};

数据表统一使用了std::vector<MyItem<T>>,如果你使用静态数组MyItem<T>[]或指针数组MyItem<T>*,那么还要传入元素数量size

示例所用数据:

  • 元素数量为size = 15

  • 关键字为key = { 123, 122, 565, 22, 3, 64, 73, 44, 287, 6, 9, 83, 25, 42, 13 }



1 交换排序简述 (Introduction)

交换排序基本思路:根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置。

常见交换排序:

  • 冒泡排序(Bubble Sort),也称起泡排序

  • 快速排序(Quick Sort),也称分区排序,它也是一个递归的过程

假设元素数量为 n ,交换过程:

  • 冒泡排序:通过 n-1 次冒泡进行排序,检测到第 i 个关键字时,从 j = {n-1, n-2, n-3 …} 开始依次两两逆序比较(也可以从0开始正序比较),如果左边大则交换。

  • 快速排序:起始 i = 0, j = n-1

    • (1)以下标 i 的元素为关键元素,即 key = item[i]
    • (2)从 j 开始依次逆序搜索,直到找到小于 key 的关键字,将item[j]item[i]交换;
    • (3)从 i 开始依次正序搜索,直到找到大于 key 的关键字,将item[i]item[j]交换;
    • (4)重复(2)和(3)再将其元素以 i 为中点分成两段,再分别重复(2)(3)(4),直到检测所有元素(不可再分)。

具体过程:

key = { 123, 122, 565, 22, 3, 64, 73, 44, 287, 6, 9, 83, 25, 42, 13 }

冒泡排序:
    第一次搜索:
        从13开始,比42小,交换,比25小,交换..直到比9大
        从9开始,比6大
        从6开始...
        直到3比较完,结束
    重复过程。

冒泡排序详细过程:
 1:   3 123 122 565  22   6  64  73  44 287   9  13  83  25  42
 2:   3   6 123 122 565  22   9  64  73  44 287  13  25  83  42
 3:   3   6   9 123 122 565  22  13  64  73  44 287  25  42  83
 4:   3   6   9  13 123 122 565  22  25  64  73  44 287  42  83
 5:   3   6   9  13  22 123 122 565  25  42  64  73  44 287  83
 6:   3   6   9  13  22  25 123 122 565  42  44  64  73  83 287
 7:   3   6   9  13  22  25  42 123 122 565  44  64  73  83 287
 8:   3   6   9  13  22  25  42  44 123 122 565  64  73  83 287
 9:   3   6   9  13  22  25  42  44  64 123 122 565  73  83 287
10:   3   6   9  13  22  25  42  44  64  73 123 122 565  83 287
11:   3   6   9  13  22  25  42  44  64  73  83 123 122 565 287
12:   3   6   9  13  22  25  42  44  64  73  83 122 123 287 565
13:   3   6   9  13  22  25  42  44  64  73  83 122 123 287 565

key = { 123, 122, 565, 22, 3, 64, 73, 44, 287, 6, 9, 83, 25, 42, 13 }

快速排序:
    第一次划分: key=123 i=0 j=14
        从 j 逆序查找,直到找到 13 ,交换 123 和 13
        从 i 正序查找,直到找到 565 ,交换 123 和 565
        继续从 j 逆序查找,直到找到 42 ,交换 123 和 42
        继续从 i 正序查找,直到找到 287 ,交换 123 和 287
        继续从 j 逆序查找,直到找到 25 ,交换 123 和 25
        继续从 i 正序查找,与 j 碰撞,得到第一次搜索后的表
        然后以 i 或 j 为分割点,将表分成左右两份
        结束第一次划分
    分别对两份表进行同样操作,直到不可再分。

快速排序详细过程:
1:
     (1):  13 122 123  22   3  64  73  44 287   6   9  83  25  42 565
     (2):  13 122  42  22   3  64  73  44 123   6   9  83  25 287 565
     (3):  13 122  42  22   3  64  73  44  25   6   9  83 123 287 565
2:
     (4):   9  13  42  22   3  64  73  44  25   6 122  83 123 287 565
     (5):   9   6  13  22   3  64  73  44  25  42 122  83 123 287 565
     (6):   9   6   3  13  22  64  73  44  25  42 122  83 123 287 565
     (7):   9   6   3  13  22  64  73  44  25  42 122  83 123 287 565
3:
     (8):   3   6   9  13  22  64  73  44  25  42 122  83 123 287 565
4:
     (9):   3   6   9  13  22  64  73  44  25  42 122  83 123 287 565
5:
    (10):   3   6   9  13  22  64  73  44  25  42 122  83 123 287 565
6:
    (11):   3   6   9  13  22  42  64  44  25  73 122  83 123 287 565
    (12):   3   6   9  13  22  42  25  44  64  73 122  83 123 287 565
7:
    (13):   3   6   9  13  22  25  42  44  64  73 122  83 123 287 565
8:
    (14):   3   6   9  13  22  25  42  44  64  73 122  83 123 287 565
9:
    (15):   3   6   9  13  22  25  42  44  64  73  83 122 123 287 565
10:
    (16):   3   6   9  13  22  25  42  44  64  73  83 122 123 287 565


2 性能分析 (Performance Analysis)

排序方法 最好时间 最差时间 平均时间 辅助空间 稳定性
冒泡排序 O(n) O(n2) O(n2) O(1) 稳定
快速排序 O(n log2n) O(n2) O(n log2n) O(n log2n) 至 O(n2) 不稳定

3 冒泡排序C++代码 (Bubble Sort C++ Code)

// Author: https://blog.youkuaiyun.com/DarkRabbit
// Bubble Sort
### 快速排序算法的实现与原理 快速排序是一种基于分治思想的高效排序算法,其核心在于通过选择一个基准值(pivot)将数组划分为两个子数组[^1]。左侧子数组的所有元素均小于或等于基准值,右侧子数组的所有元素均大于基准值。然后递归地对这两个子数组进行相同的操作,直到整个数组有序。 #### 快速排序的基本原理 快速排序的核心步骤可以分为三步: 1. **选择基准值**:从数组中选取一个元素作为基准值(pivot)。通常可以选择第一个元素、最后一个元素或中间位置的元素。 2. **分区操作**:重新排列数组,使得所有小于等于基准值的元素位于基准值左侧,所有大于基准值的元素位于右侧。 3. **递归排序**:对基准值左右两侧的子数组分别递归应用上述过程。 #### 时间复杂度分析 快速排序的时间复杂度取决于分区操作的平衡性。在平均情况下,快速排序的时间复杂度为 \(O(n \log n)\)[^3],其中 \(n\) 为待排序数组的长度。然而,在最坏情况下(例如数组已经有序且每次都选择最左或最右元素作为基准值),时间复杂度会退化为 \(O(n^2)\)[^4]。尽管如此,由于快速排序在实际应用中的常数因子较小,因此它仍然是最常用的排序算法之一。 #### 空间复杂度分析 快速排序的空间复杂度主要由递归调用栈决定。在理想情况下(即每次分区都能均匀分割数组),递归深度为 \(O(\log n)\),因此空间复杂度为 \(O(\log n)\)。但在最坏情况下,递归深度可能达到 \(O(n)\),导致空间复杂度退化为 \(O(n)\)[^1]。 #### Java实现代码 以下是一个使用Java语言实现的快速排序算法示例: ```java public class QuickSort { public static void quickSort(int[] arr, int low, int high) { if (low < high) { // 找到分区点 int pivotIndex = partition(arr, low, high); // 对左侧子数组进行递归排序 quickSort(arr, low, pivotIndex - 1); // 对右侧子数组进行递归排序 quickSort(arr, pivotIndex + 1, high); } } private static int partition(int[] arr, int low, int high) { // 选择最右元素作为基准值 int pivot = arr[high]; int i = low - 1; for (int j = low; j < high; j++) { if (arr[j] <= pivot) { i++; // 交换元素 swap(arr, i, j); } } // 将基准值放置到正确位置 swap(arr, i + 1, high); return i + 1; } private static void swap(int[] arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } public static void main(String[] args) { int[] arr = {10, 7, 8, 9, 1, 5}; quickSort(arr, 0, arr.length - 1); System.out.println("Sorted array: "); for (int num : arr) { System.out.print(num + " "); } } } ``` #### Python实现代码 以下是使用Python语言实现的快速排序算法示例: ```python def quick_sort(arr): if len(arr) <= 1: return arr else: # 选择基准值 pivot = arr[len(arr) // 2] # 分别存放比基准小和大的元素 left = [x for x in arr if x < pivot] middle = [x for x in arr if x == pivot] right = [x for x in arr if x > pivot] # 递归地对左右两边进行快排,并合并结果 return quick_sort(left) + middle + quick_sort(right) # 测试代码 if __name__ == "__main__": arr = [10, 7, 8, 9, 1, 5] sorted_arr = quick_sort(arr) print("Sorted array:", sorted_arr) ``` #### 快速排序的特点 - **高效性**:快速排序在大多数情况下比其他 \(O(n \log n)\)排序算法更快[^1]。 - **不稳定性**:快速排序是一种不稳定的排序算法,即相等元素的相对顺序可能会改变[^2]。 - **适用场景**:适用于大规模数据的排序任务,尤其是在内存访问成本较低的情况下表现优异。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值