排序算法时间复杂度

复习一下排序算法,及各排序算法的时间复杂度(了解简单时间复杂度的计算)

1.常见时间复杂度的分类

时间复杂度描述例子
O(1)常数时间:与输入大小无关访问数组中的某元素
O(log n)对数时间:规模缩小一半二分查找
O(n)线性时间:与输入成正比遍历数组
O(n log n)线性对数时间快速排序、归并排序
O(n^2)二次方时间:嵌套循环冒泡排序、插入排序
O(2^n)指数时间未优化递归解决斐波那契数列
O(n!)阶乘时间解决全排列问题

2.排序时间复杂度(按常见度粗略排序)

排序算法最好时间复杂度最坏时间复杂度平均时间复杂度空间复杂度稳定性
冒泡排序O(n)O(n²)O(n²)O(1)稳定
选择排序O(n²)O(n²)O(n²)O(1)不稳定
插入排序O(n)O(n²)O(n²)O(1)稳定
希尔排序O(n log n)O(n²)O(n¹.³) ~ O(n log²n)O(1)不稳定
快速排序O(n log n)O(n²)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)不稳定
计数排序O(n + k)O(n + k)O(n + k)O(k)稳定
桶排序O(n + k)O(n²)O(n + k)O(n + k)稳定
基数排序O(nk)O(nk)O(nk)O(n + k)稳定

3.常见排序算法简要代码实现

1. 冒泡排序(Bubble Sort)

// 冒泡排序:每轮将最大值“冒”到最后
void bubble_sort(int arr[], int n) {
    for (int i = 0; i < n - 1; i++) {
        // 每次比较相邻两个元素,将大的移到右边
        for (int j = 0; j < n - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                // 交换两个元素
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

2. 选择排序(Selection Sort)

// 选择排序:每轮选择最小值放到前面
void selection_sort(int arr[], int n) {
    for (int i = 0; i < n - 1; i++) {
        int min_idx = i;  // 当前轮次的最小值索引
        for (int j = i + 1; j < n; j++) {
            if (arr[j] < arr[min_idx]) {
                min_idx = j;
            }
        }
        // 交换最小值与当前位置
        if (min_idx != i) {
            int temp = arr[i];
            arr[i] = arr[min_idx];
            arr[min_idx] = temp;
        }
    }
}

3. 插入排序(Insertion Sort)

// 插入排序:将每个元素插入到前面有序序列中
void insertion_sort(int arr[], int n) {
    for (int i = 1; i < n; i++) {
        int key = arr[i];    // 当前要插入的元素
        int j = i - 1;

        // 向右移动比 key 大的元素
        while (j >= 0 && arr[j] > key) {
            arr[j + 1] = arr[j];
            j--;
        }

        // 插入到正确位置
        arr[j + 1] = key;
    }
}

4. 快速排序(Quick Sort)

// 快速排序:分治法,选择一个基准值,将小的放左边,大的放右边

// 分区函数,返回基准值最终位置
int partition(int arr[], int low, int high) {
    int pivot = arr[low];  // 选择第一个元素作为基准
    int left = low;
    int right = high;

    while (left < right) {
        // 从右往左找比 pivot 小的
        while (left < right && arr[right] >= pivot)
            right--;
        arr[left] = arr[right];  // 移动到左边空位

        // 从左往右找比 pivot 大的
        while (left < right && arr[left] <= pivot)
            left++;
        arr[right] = arr[left];  // 移动到右边空位
    }

    arr[left] = pivot;  // 基准放到最终位置
    return left;
}

// 快排主函数
void quick_sort(int arr[], int low, int high) {
    if (low < high) {
        int pivot_idx = partition(arr, low, high);
        quick_sort(arr, low, pivot_idx - 1);   // 排左边
        quick_sort(arr, pivot_idx + 1, high);  // 排右边
    }
}

5. 归并排序(Merge Sort)

// 合并两个有序子数组:arr[left..mid] 和 arr[mid+1..right]
void merge(int arr[], int left, int mid, int right) {
    int n1 = mid - left + 1;
    int n2 = right - mid;

    // 临时数组
    int L[n1], R[n2];

    // 拷贝数据
    for (int i = 0; i < n1; i++) L[i] = arr[left + i];
    for (int j = 0; j < n2; j++) R[j] = arr[mid + 1 + j];

    int i = 0, j = 0, k = left;

    // 合并两个有序数组
    while (i < n1 && j < n2) {
        if (L[i] <= R[j])
            arr[k++] = L[i++];
        else
            arr[k++] = R[j++];
    }

    // 复制剩余元素
    while (i < n1) arr[k++] = L[i++];
    while (j < n2) arr[k++] = R[j++];
}

// 归并排序主函数
void merge_sort(int arr[], int left, int right) {
    if (left < right) {
        int mid = (left + right) / 2;

        merge_sort(arr, left, mid);        // 排左半部分
        merge_sort(arr, mid + 1, right);   // 排右半部分
        merge(arr, left, mid, right);      // 合并
    }
}

四、常见算法介绍

  1. 冒泡排序

    原理:两两比较相邻元素,将较大的元素逐步“冒泡”到数组末尾。

    特点:简单易懂,但性能较低。

    适用场景:小数据量或数据接近有序时。

  2. 选择排序

    原理:每次从未排序部分选择最小(或最大)的元素,放到已排序部分末尾。

    特点:实现简单,但多次交换导致效率低。

    适用场景:数据量小,稳定性不要求高。

  3. 插入排序

    原理:将未排序元素逐一插入到已排序部分的适当位置。

    特点:对几乎有序的数据效果较好。

    适用场景:小规模数据、接近有序数据。

  4. 快速排序

    原理:选定一个基准值,将数组划分为小于和大于基准值的两部分,递归排序。

    特点:平均性能优越,但最坏情况下效率低(如有序数组)。

    适用场景:大规模数据,效率高要求。

  5. 归并排序

    原理:将数组递归分成两部分,分别排序后合并。

    特点:稳定且效率高,但需要额外空间。

    适用场景:需要稳定性,且内存足够的场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值