数据结构与算法之计数排序

计数排序是一种非比较排序算法,主要用于整数排序。计数排序的基本思想是,对于给定的输入序列中的每一个元素 x,确定小于 x 的元素个数。利用这一信息,可以直接把 x 放到它在输出序列中的位置上。

计数排序的步骤如下:

  1. 找出待排序的数组中最大和最小的元素;

  2. 统计数组中每个值为 i 的元素出现的次数,存入数组 C 的第 i 项;

  3. 对所有的计数累加(从 C 中的第一个元素开始,每一项和前一项相加);

  4. 反向填充目标数组:将每个元素 i 放在新数组的第 C(i) 项,每放一个元素就将 C(i) 减去 1。

计数排序的时间复杂度为 O(n + k),其中 k 表示数据范围。虽然时间复杂度比较小,但计数排序的缺点是它只能用于整数排序,而且当数据范围很大时,需要大量的辅助空间。计数排序是一种非比较排序算法,主要用于整数排序。计数排序的基本思想是,对于给定的输入序列中的每一个元素 x,确定小于 x 的元素个数。利用这一信息,可以直接把 x 放到它在输出序列中的位置上。

计数排序的步骤如下:

  1. 找出待排序的数组中最大和最小的元素;

  2. 统计数组中每个值为 i 的元素出现的次数,存入数组 C 的第 i 项;

  3. 对所有的计数累加(从 C 中的第一个元素开始,每一项和前一项相加);

  4. 反向填充目标数组:将每个元素 i 放在新数组的第 C(i) 项,每放一个元素就将 C(i) 减去 1。

计数排序的时间复杂度为 O(n + k),其中 k 表示数据范围。虽然时间复杂度比较小,但计数排序的缺点是它只能用于整数排序,而且当数据范围很大时,需要大量的辅助空间。

在这里插入图片描述

一、C 实现 计数排序 及代码详解

计数排序(Counting Sort)是一种线性时间复杂度的排序算法,它的基本思想是统计每个元素出现的次数,然后根据元素的值和出现次数直接计算每个元素的位置。

计数排序适用于待排序的元素范围比较小的情况,时间复杂度为 O(n+k),其中 k 是待排序元素的范围大小。如果 k 太大,则会导致排序时间过长和占用过多的内存空间,此时不适合使用计数排序。

以下是 C 语言实现计数排序的代码及注释:

#include <stdio.h>
#include <stdlib.h>

/* 计数排序函数,arr为待排序数组,n为数组大小 */
void counting_sort(int arr[], int n)
{
    int max_element = 0;
    int i, j;

    /* 找到最大值,确定桶的大小 */
    for (i = 0; i < n; i++) {
        if (arr[i] > max_element) {
            max_element = arr[i];
        }
    }

    /* 创建桶 */
    int *count = (int*)calloc(max_element + 1, sizeof(int));

    /* 统计每个元素出现的次数 */
    for (i = 0; i < n; i++) {
        count[arr[i]]++;
    }

    /* 对桶进行求和操作 */
    for (i = 1; i <= max_element; i++) {
        count[i] += count[i - 1];
    }

    /* 定义一个临时数组,用于存储排好序的结果 */
    int *sorted = (int*)malloc(n * sizeof(int));

    /* 根据桶的统计结果排序 */
    for (i = n - 1; i >= 0; i--) {
        sorted[count[arr[i]] - 1] = arr[i];
        count[arr[i]]--;
    }

    /* 将排序好的结果拷贝回原数组 */
    for (i = 0; i < n; i++) {
        arr[i] = sorted[i];
    }

    /* 释放内存 */
    free(count);
    free(sorted);
}

int main()
{
    int arr[] = {8, 2, 3, 5, 1};
    int n = sizeof(arr) / sizeof(arr[0]);
    int i;

    counting_sort(arr, n);

    for (i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    return 0;
}

计数排序的核心代码包括四个部分:

  1. 找到最大值,确定桶的大小;
  2. 创建桶,并统计每个元素出现的次数;
  3. 对桶进行求和操作,得到每个元素的位置;
  4. 根据桶的统计结果排序,并将排序好的结果拷贝回原数组。

这里需要注意的是,由于计数排序的桶大小取决于待排序元素的最大值,因此需要使用动态内存分配来创建桶,并在排序结束后释放内存。同时,在排序过程中需要使用一个临时数组来存储排好序的结果。

最后,在 main 函数中调用 counting_sort 函数,并打印排序后的结果。计数排序(Counting Sort)是一种线性时间复杂度的排序算法,它的基本思想是统计每个元素出现的次数,然后根据元素的值和出现次数直接计算每个元素的位置。

计数排序适用于待排序的元素范围比较小的情况,时间复杂度为 O(n+k),其中 k 是待排序元素的范围大小。如果 k 太大,则会导致排序时间过长和占用过多的内存空间,此时不适合使用计数排序。

以下是 C 语言实现计数排序的代码及注释:

#include <stdio.h>
#include <stdlib.h>

/* 计数排序函数,arr为待排序数组,n为数组大小 */
void counting_sort(int arr[], int n)
{
    int max_element = 0;
    int i, j;

    /* 找到最大值,确定桶的大小 */
    for (i = 0; i < n; i++) {
        if (arr[i] > max_element) {
            max_element = arr[i];
        }
    }

    /* 创建桶 */
    int *count = (int*)calloc(max_element + 1, sizeof(int));

    /* 统计每个元素出现的次数 */
    for (i = 0; i < n; i++) {
        count[arr[i]]++;
    }

    /* 对桶进行求和操作 */
    for (i = 1; i <= max_element; i++) {
        count[i] += count[i - 1];
    }

    /* 定义一个临时数组,用于存储排好序的结果 */
    int *sorted = (int*)malloc(n * sizeof(int));

    /* 根据桶的统计结果排序 */
    for (i = n - 1; i >= 0; i--) {
        sorted[count[arr[i]] - 1] = arr[i];
        count[arr[i]]--;
    }

    /* 将排序好的结果拷贝回原数组 */
    for (i = 0; i < n; i++) {
        arr[i] = sorted[i];
    }

    /* 释放内存 */
    free(count);
    free(sorted);
}

int main()
{
    int arr[] = {8, 2, 3, 5, 1};
    int n = sizeof(arr) / sizeof(arr[0]);
    int i;

    counting_sort(arr, n);

    for (i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    return 0;
}

计数排序的核心代码包括四个部分:

  1. 找到最大值,确定桶的大小;
  2. 创建桶,并统计每个元素出现的次数;
  3. 对桶进行求和操作,得到每个元素的位置;
  4. 根据桶的统计结果排序,并将排序好的结果拷贝回原数组。

这里需要注意的是,由于计数排序的桶大小取决于待排序元素的最大值,因此需要使用动态内存分配来创建桶,并在排序结束后释放内存。同时,在排序过程中需要使用一个临时数组来存储排好序的结果。

最后,在 main 函数中调用 counting_sort 函数,并打印排序后的结果。

在这里插入图片描述

二、C++ 实现 计数排序 及代码详解

计数排序(Counting Sort)是一种非比较排序算法,其思想是先统计待排序序列中每个元素出现的次数,然后根据元素大小依次在输出序列中放置相应个数的元素。

1.算法步骤

  • 统计待排序序列中每个元素出现的次数,得到计数数组 C。
  • 对计数数组 C 进行前缀和运算,得到累加数组 D,其中 D[i] 表示序列中不大于 i 的元素个数。
  • 倒序遍历原序列,根据元素在累加数组 D 中的对应位置进行元素放置,同时减少计数数组 C 中对应元素的值,以便后续相同元素的正确放置。

2.代码实现

计数排序的时间复杂度为 O(n+k),其中 n 为序列长度,k 为元素取值范围(即序列中最大元素的值加一)。以下是 C++ 实现的代码:

void countingSort(vector<int>& arr) {
    if (arr.empty()) {
        return;
    }
    int max_val = *max_element(arr.begin(), arr.end());
    vector<int> cnt(max_val + 1, 0);
    for (int num : arr) {
        cnt[num]++;
    }
    for (int i = 1; i <= max_val; i++) {
        cnt[i] += cnt[i - 1];
    }
    vector<int> res(arr.size(), 0);
    for (int i = arr.size() - 1; i >= 0; i--) {
        res[cnt[arr[i]] - 1] = arr[i];
        cnt[arr[i]]--;
    }
    arr = res;
}

3.代码解释

  • 第 2~5 行:判断输入数组是否为空,若为空则直接返回。
  • 第 6 行:获取输入数组中的最大值 max_val,用于初始化计数数组。
  • 第 7~9 行:初始化计数数组 cnt,统计输入数组中每个元素出现的次数。
  • 第 10~12 行:对计数数组 cnt 进行前缀和运算,得到累加数组 cnt,其中 cnt[i] 表示序列中不大于 i 的元素个数。
  • 第 13 行:初始化输出数组 res。
  • 第 14~17 行:倒序遍历输入数组 arr,根据元素在累加数组 cnt 中的对应位置进行元素放置,同时减少计数数组 cnt 中对应元素的值,以便后续相同元素的正确放置。
  • 第 18 行:将排序后的结果存储回原始数组 arr。计数排序(Counting Sort)是一种非比较排序算法,其思想是先统计待排序序列中每个元素出现的次数,然后根据元素大小依次在输出序列中放置相应个数的元素。

1.算法步骤

  • 统计待排序序列中每个元素出现的次数,得到计数数组 C。
  • 对计数数组 C 进行前缀和运算,得到累加数组 D,其中 D[i] 表示序列中不大于 i 的元素个数。
  • 倒序遍历原序列,根据元素在累加数组 D 中的对应位置进行元素放置,同时减少计数数组 C 中对应元素的值,以便后续相同元素的正确放置。

2.代码实现

计数排序的时间复杂度为 O(n+k),其中 n 为序列长度,k 为元素取值范围(即序列中最大元素的值加一)。以下是 C++ 实现的代码:

void countingSort(vector<int>& arr) {
    if (arr.empty()) {
        return;
    }
    int max_val = *max_element(arr.begin(), arr.end());
    vector<int> cnt(max_val + 1, 0);
    for (int num : arr) {
        cnt[num]++;
    }
    for (int i = 1; i <= max_val; i++) {
        cnt[i] += cnt[i - 1];
    }
    vector<int> res(arr.size(), 0);
    for (int i = arr.size() - 1; i >= 0; i--) {
        res[cnt[arr[i]] - 1] = arr[i];
        cnt[arr[i]]--;
    }
    arr = res;
}

3.代码解释

  • 第 2~5 行:判断输入数组是否为空,若为空则直接返回。
  • 第 6 行:获取输入数组中的最大值 max_val,用于初始化计数数组。
  • 第 7~9 行:初始化计数数组 cnt,统计输入数组中每个元素出现的次数。
  • 第 10~12 行:对计数数组 cnt 进行前缀和运算,得到累加数组 cnt,其中 cnt[i] 表示序列中不大于 i 的元素个数。
  • 第 13 行:初始化输出数组 res。
  • 第 14~17 行:倒序遍历输入数组 arr,根据元素在累加数组 cnt 中的对应位置进行元素放置,同时减少计数数组 cnt 中对应元素的值,以便后续相同元素的正确放置。
  • 第 18 行:将排序后的结果存储回原始数组 arr。

在这里插入图片描述

三、Java 实现 计数排序 及代码详解

计数排序是一种非比较排序算法,它的基本思想是利用一个辅助数组来记录每个元素出现的次数,然后再将辅助数组中的元素依次累加,得到每个元素在排序后的序列中的位置。具体实现步骤如下:

  1. 找到待排序序列中的最大值和最小值。

  2. 建立一个辅助数组,数组长度为最大值和最小值之间的差值加一。

  3. 遍历待排序序列,将每个元素出现的次数记录在辅助数组中。

  4. 根据辅助数组计算每个元素在排序后的序列中的位置,存储到一个新的数组中。

下面是 Java 实现计数排序的代码及注释:

public static void countingSort(int[] arr) {
    // 找到待排序序列中的最大值和最小值
    int max = arr[0], min = arr[0];
    for (int i = 1; i < arr.length; i++) {
        if (arr[i] > max) {
            max = arr[i];
        }
        if (arr[i] < min) {
            min = arr[i];
        }
    }

    // 建立一个辅助数组
    int[] count = new int[max - min + 1];

    // 遍历待排序序列,将每个元素出现的次数记录在辅助数组中
    for (int i = 0; i < arr.length; i++) {
        count[arr[i] - min]++;
    }

    // 根据辅助数组计算每个元素在排序后的序列中的位置
    for (int i = 1; i < count.length; i++) {
        count[i] += count[i - 1];
    }

    // 存储排序后的元素到一个新的数组中
    int[] sortedArr = new int[arr.length];
    for (int i = arr.length - 1; i >= 0; i--) {
        sortedArr[count[arr[i] - min] - 1] = arr[i];
        count[arr[i] - min]--;
    }

    // 将排序后的数组赋值给原数组
    for (int i = 0; i < arr.length; i++) {
        arr[i] = sortedArr[i];
    }
}

以上就是 Java 实现计数排序的代码及注释。计数排序是一种非比较排序算法,它的基本思想是利用一个辅助数组来记录每个元素出现的次数,然后再将辅助数组中的元素依次累加,得到每个元素在排序后的序列中的位置。具体实现步骤如下:

  1. 找到待排序序列中的最大值和最小值。

  2. 建立一个辅助数组,数组长度为最大值和最小值之间的差值加一。

  3. 遍历待排序序列,将每个元素出现的次数记录在辅助数组中。

  4. 根据辅助数组计算每个元素在排序后的序列中的位置,存储到一个新的数组中。

下面是 Java 实现计数排序的代码及注释:

public static void countingSort(int[] arr) {
    // 找到待排序序列中的最大值和最小值
    int max = arr[0], min = arr[0];
    for (int i = 1; i < arr.length; i++) {
        if (arr[i] > max) {
            max = arr[i];
        }
        if (arr[i] < min) {
            min = arr[i];
        }
    }

    // 建立一个辅助数组
    int[] count = new int[max - min + 1];

    // 遍历待排序序列,将每个元素出现的次数记录在辅助数组中
    for (int i = 0; i < arr.length; i++) {
        count[arr[i] - min]++;
    }

    // 根据辅助数组计算每个元素在排序后的序列中的位置
    for (int i = 1; i < count.length; i++) {
        count[i] += count[i - 1];
    }

    // 存储排序后的元素到一个新的数组中
    int[] sortedArr = new int[arr.length];
    for (int i = arr.length - 1; i >= 0; i--) {
        sortedArr[count[arr[i] - min] - 1] = arr[i];
        count[arr[i] - min]--;
    }

    // 将排序后的数组赋值给原数组
    for (int i = 0; i < arr.length; i++) {
        arr[i] = sortedArr[i];
    }
}

以上就是 Java 实现计数排序的代码及注释。

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值