当前位置: 首页 > article >正文

排序算法--计数排序

唯一种没有比较的排序(指没有前后比较,还是有交换的)。统计每个元素出现的次数,直接计算元素在有序序列中的位置,要求数据是整数且范围有限。适用于数据为小范围整数(如年龄、成绩),数据重复率较高时效率更优。可用于小范围整数排序、基数排序的底层排序(作为基数排序的稳定排序子过程)、统计频率分布(快速获取元素分布直方图)、海量数据预处理(配合外部排序处理大数据文件)

以数组的下标当做数值,有这个数的时候a[i]++;

 1绝对映射:

2相对映射:

#include <stdlib.h>
#include <assert.h>

// 计数排序核心函数(稳定排序版本)
void countingSort(int arr[], int n) {
    if (n <= 1) return; // 无需排序

    // 1. 确定数据范围
    int max = arr[0], min = arr[0];
    for (int i = 1; i < n; i++) {
        if (arr[i] > max) max = arr[i];
        if (arr[i] < min) min = arr[i];
    }
    const int range = max - min + 1; // 实际数值范围

    // 2. 创建计数数组并初始化
    int* count = (int*)calloc(range, sizeof(int));
    assert(count != NULL);

    // 3. 统计每个元素出现次数
    for (int i = 0; i < n; i++) {
        count[arr[i] - min]++; // 偏移处理负数
    }

    // 4. 计算累计位置(保证稳定性)
    for (int i = 1; i < range; i++) {
        count[i] += count[i - 1];
    }

    // 5. 反向填充结果数组(关键稳定性操作)
    int* output = (int*)malloc(n * sizeof(int));
    assert(output != NULL);
    
    for (int i = n - 1; i >= 0; i--) {
        output[count[arr[i] - min] - 1] = arr[i];
        count[arr[i] - min]--;
    }

    // 6. 复制回原数组
    for (int i = 0; i < n; i++) {
        arr[i] = output[i];
    }

    // 7. 释放内存
    free(count);
    free(output);
}
#include <stdio.h>
// 打印数组
void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int main() {
    // 测试数据(包含负数)
    int arr[] = {-5, 2, -3, 4, 1, 2, 8, 5, 3, -1};
    int n = sizeof(arr) / sizeof(arr[0]);

    printf("排序前: ");
    printArray(arr, n);

    countingSort(arr, n);

    printf("排序后: ");
    printArray(arr, n);

    return 0;
}

优化建议:

1.通过min值偏移处理负数,支持全整数范围排序

2.通过反向遍历填充输出数组,保留相同元素的原始顺序,已保证稳定性

3.动态计算range值,避免不必要的内存浪费

void countingSortSpaceOptimized(int arr[], int n) {
    // ...(省略范围计算步骤)...
    
    // 直接根据计数数组覆盖原数组(非稳定)
    int idx = 0;
    for (int i = 0; i < range; i++) {
        while (count[i]-- > 0) {
            arr[idx++] = i + min;
        }
    }
}


http://www.kler.cn/a/532634.html

相关文章:

  • 【数据结构】栈与队列
  • Debezium Oracle Connector SCN处理优化指南
  • 深度学习 Pytorch 基础网络手动搭建与快速实现
  • 分析哲学:从 语言解剖到 思想澄清的哲学探险
  • 构建一个数据分析Agent:提升分析效率的实践
  • 使用 PyTorch 实现逻辑回归并评估模型性能
  • 【NLP 20、Encoding编码 和 Embedding嵌入】
  • 文字加持:让 OpenCV 轻松在图像中插上文字
  • 逻辑运算短路现象记录
  • PostCss
  • 关于deepseek的一些普遍误读
  • Vant框架:助力移动端开发的利器
  • SpringBoot 连接Elasticsearch带账号密码认证 ES连接 加密连接
  • 7.2.背包DP
  • 获取 ARM Cortex - M 系列处理器中 PRIMASK 寄存器的值
  • Azure DevOps Server:集成奇安信开源卫士(OpenSourceSafe)
  • 16 旋转操作模块(rotation.rs)
  • napalm_ce 报错 No module named ‘netmiko.ssh_exception‘ 解决方案(随手记)
  • 17 形状边缘偏移量模块(side_offsets.rs)
  • git-secret 使用教程
  • JVM- 垃圾回收算法
  • Leetcode922: 按奇偶排序数组 II
  • [Go]一、Go语言基础
  • 基于 docker 的mysql 5.7 主主集群搭建
  • fpga系列 HDL:XILINX Vivado ZYNQ-7000 PS-PL数据交互 AXI4 实现笔记
  • ros 发布Topic