排序算法学习笔记

1. 排序的定义

排序(Sorting)是将一组数据按照一定的顺序排列的过程。排序的顺序可以是升序或降序。

2. 排序算法的分类

排序算法可以分为内部排序和外部排序:

  • 内部排序:数据在内存中进行排序。
  • 外部排序:数据量大于内存容量时,需要借助外部存储进行排序。

3. 常见排序算法

3.1 冒泡排序(Bubble Sort)

冒泡排序是一种简单的交换排序算法,通过重复地遍历要排序的列表,比较相邻元素并交换顺序,直到列表有序。

c 复制代码
void bubbleSort(int* arr, int n) {
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

3.2 选择排序(Selection Sort)

选择排序是一种简单的选择排序算法,通过在未排序部分中找到最小(或最大)元素,并将其放到已排序部分的末尾,直到排序完成。

c 复制代码
void selectionSort(int* arr, int n) {
    for (int i = 0; i < n - 1; i++) {
        int minIndex = i;
        for (int j = i + 1; j < n; j++) {
            if (arr[j] < arr[minIndex]) {
                minIndex = j;
            }
        }
        int temp = arr[minIndex];
        arr[minIndex] = arr[i];
        arr[i] = temp;
    }
}

3.3 插入排序(Insertion Sort)

插入排序是一种简单的插入排序算法,通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

c 复制代码
void insertionSort(int* arr, int n) {
    for (int i = 1; i < n; i++) {
        int key = arr[i];
        int j = i - 1;
        while (j >= 0 && arr[j] > key) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
}

3.4 快速排序(Quick Sort)

快速排序是一种高效的分治排序算法,通过选择一个基准元素,将数组分成两部分,一部分比基准元素小,另一部分比基准元素大,递归地对两部分进行排序。

c 复制代码
int partition(int* arr, int low, int high) {
    int pivot = arr[high];
    int i = low - 1;
    for (int j = low; j <= high - 1; j++) {
        if (arr[j] < pivot) {
            i++;
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }
    int temp = arr[i + 1];
    arr[i + 1] = arr[high];
    arr[high] = temp;
    return i + 1;
}

void quickSort(int* arr, int low, int high) {
    if (low < high) {
        int pi = partition(arr, low, high);
        quickSort(arr, low, pi - 1);
        quickSort(arr, pi + 1, high);
    }
}

3.5 归并排序(Merge Sort)

归并排序是一种高效的分治排序算法,通过将数组分成两个子数组,对每个子数组进行排序,然后合并两个已排序的子数组。

c 复制代码
void merge(int* arr, int l, int m, int r) {
    int n1 = m - l + 1;
    int n2 = r - m;
    int L[n1], R[n2];
    for (int i = 0; i < n1; i++) {
        L[i] = arr[l + i];
    }
    for (int i = 0; i < n2; i++) {
        R[i] = arr[m + 1 + i];
    }
    int i = 0, j = 0, k = l;
    while (i < n1 && j < n2) {
        if (L[i] <= R[j]) {
            arr[k] = L[i];
            i++;
        } else {
            arr[k] = R[j];
            j++;
        }
        k++;
    }
    while (i < n1) {
        arr[k] = L[i];
        i++;
        k++;
    }
    while (j < n2) {
        arr[k] = R[j];
        j++;
        k++;
    }
}

void mergeSort(int* arr, int l, int r) {
    if (l < r) {
        int m = l + (r - l) / 2;
        mergeSort(arr, l, m);
        mergeSort(arr, m + 1, r);
        merge(arr, l, m, r);
    }
}

3.6 堆排序(Heap Sort)

堆排序是一种基于堆这种数据结构的排序算法,通过构建最大堆或最小堆,将堆顶元素与末尾元素交换,然后对剩余元素进行调整,直到排序完成。

c 复制代码
void heapify(int* arr, int n, int i) {
    int largest = i;
    int left = 2 * i + 1;
    int right = 2 * i + 2;
    if (left < n && arr[left] > arr[largest]) {
        largest = left;
    }
    if (right < n && arr[right] > arr[largest]) {
        largest = right;
    }
    if (largest != i) {
        int temp = arr[i];
        arr[i] = arr[largest];
        arr[largest] = temp;
        heapify(arr, n, largest);
    }
}

void heapSort(int* arr, int n) {
    for (int i = n / 2 - 1; i >= 0; i--) {
        heapify(arr, n, i);
    }
    for (int i = n - 1; i > 0; i--) {
        int temp = arr[0];
        arr[0] = arr[i];
        arr[i] = temp;
        heapify(arr, i, 0);
    }
}

4. 排序算法的比较

排序算法 时间复杂度(平均) 时间复杂度(最坏) 时间复杂度(最好) 空间复杂度 稳定性
冒泡排序 O(n^2) O(n^2) O(n) O(1) 稳定
选择排序 O(n^2) O(n^2) O(n^2) O(1) 不稳定
插入排序 O(n^2) O(n^2) O(n) O(1) 稳定
快速排序 O(n log n) O(n^2) O(n log n) O(log n) 不稳定
归并排序 O(n log n) O(n log n) O(n log n) O(n) 稳定
堆排序 O(n log n) O(n log n) O(n log n) O(1) 不稳定
相关推荐
strongwyy3 小时前
esp32墨水屏学习3
学习
_dindong3 小时前
Linux系统编程:线程概念
linux·运维·笔记·学习
Olrookie4 小时前
若依前后端分离版学习笔记(十六)——scoped、路由跳转
前端·笔记
Olrookie4 小时前
若依前后端分离版学习笔记(十七)——ruoyi开发规范&流程,请求流程,依赖引入,组件注册&通信
前端·笔记
上园村蜻蜓队长4 小时前
FPGA自学笔记--VIVADO FIFO IP核控制和使用
笔记·fpga开发
小二·4 小时前
前端笔记:HTML output标签介绍及用法
javascript·笔记·html5
杰尼君4 小时前
STM32CubeMX笔记(11)-- AD模块使用
笔记·stm32·嵌入式硬件
_JinHao5 小时前
Cesium Viewer对象详解——Cesium基础笔记(快速入门)
前端·javascript·笔记·3d·webgl
贝塔实验室5 小时前
LDPC码的概念
科技·学习·程序人生·算法·学习方法·程序员创富·改行学it
尘似鹤5 小时前
微信小程序学习(三)
学习