深入了解计数排序算法

简介: 深入了解计数排序算法

计数排序(Counting Sort)是一种简单、高效的排序算法,它不基于比较,而是利用数组下标的计数来实现排序。本文将详细介绍计数排序的工作原理,提供示例和Python、Go、Java以及C语言的实现代码。


计数排序的基本思想


计数排序的核心思想是统计数组中每个元素的出现次数,然后根据元素的大小依次放置到有序的结果数组中。具体步骤如下:

1.统计频次: 遍历待排序数组,统计每个元素出现的频次,以数组的值为索引。

2.计算累积频次: 计算每个元素的累积频次,确定元素在排序数组中的位置。

3.构建有序数组: 根据元素的累积频次,将元素放入有序数组中,同时更新累积频次。


计数排序的关键在于构建辅助数组,辅助数组用于存储每个元素的出现次数,以及计算每个元素在排序后的数组中的位置。


计数排序的示例


让我们通过一个示例来理解计数排序的工作原理。假设我们有一个整数数组 [3, 1, 4, 1, 5, 9, 2, 6, 5],我们希望按升序排序它。

1.统计频次: 统计每个元素的出现次数。

待排序数组: [3, 1, 4, 1, 5, 9, 2, 6, 5]
频次数组:   [0, 1, 1, 1, 2, 1, 1, 0, 1]


1.计算累积频次: 计算每个元素的累积频次。

累积频次数组: [0, 1, 2, 3, 5, 6, 7, 7, 8]


1.构建有序数组: 根据元素的累积频次,将元素放入有序数组中。

排序后的数组: [1, 1, 2, 3, 4, 5, 5, 6, 9]


计数排序的时间复杂度


计数排序的时间复杂度为O(n + k),其中n是数组的长度,k是数组中元素的取值范围。计数排序的时间复杂度非常稳定,性能优异,尤其适合对整数进行排序。但需要注意,计数排序仅适用于非负整数或确定范围的整数排序。


计数排序是一种稳定的排序算法,通过对元素的频次统计和累积频次计算,实现了线性时间的排序。


示例代码


以下是计数排序的示例代码,分别使用Python、Go、Java和C语言编写。

Python 计数排序


def counting_sort(arr):
    max_val = max(arr)
    counts = [0] * (max_val + 1)
    
    # 统计每个元素的频次
    for num in arr:
        counts[num] += 1
        
    # 计算每个元素的累积频次
    for i in range(1, max_val + 1):
        counts[i] += counts[i - 1]
        
    # 构建有序数组
    sorted_arr = [0] * len(arr)
    for i in range(len(arr)):
        sorted_arr[counts[arr[i]] - 1] = arr[i]
        counts[arr[i]] -= 1
        
    return sorted_arr
    
arr = [3, 1, 4, 1, 5, 9, 2, 6, 5]
sorted_arr = counting_sort(arr)
print("排序后的数组:", sorted_arr)


Go 计数排序


package main

import "fmt"

func countingSort(arr []int) []int {
    maxVal := arr[0]
    for _, num := range arr {
        if num > maxVal {
            maxVal = num
        }
    }
    
    counts := make([]int, maxVal+1)
    
    // 统计每个元素的频次
    for _, num := range arr {
        counts[num]++
    }
    
    // 计算每个元素的累积频次
    for i := 1; i <= maxVal; i++ {
        counts[i] += counts[i-1]
    }
    
    // 构建有序数组
    sortedArr := make([]int, len(arr))
    for i := len(arr) - 1; i >= 0; i-- {
        sortedArr[counts[arr[i]]-1] = arr[i]
        counts[arr[i]]--
    }
    
    return sortedArr
}

func main() {
    arr := []int{3, 1, 4, 1, 5, 9, 2, 6, 5}
    sortedArr := countingSort(arr)
    fmt.Println("排序后的数组:", sortedArr)
}


Java 计数排序


import java.util.Arrays;

public class CountingSort {
    public static int[] countingSort(int[] arr) {
        int maxVal = Arrays.stream(arr).max().getAsInt();
        int[] counts = new int[maxVal + 1];
        
        // 统计每个元素的频次
        for (int num : arr) {
            counts[num]++;
        }
        
        // 计算每个元素的累积频次
        for (int i = 1; i <= maxVal; i++) {
            counts[i] += counts[i - 1];
        }
        
        // 构建有序数组
        int[] sortedArr = new int[arr.length];
        for (int i = arr.length - 1; i >= 0; i--) {
            sortedArr[counts[arr[i]] - 1] = arr[i];
            counts[arr[i]]--;
        }
        
        return sortedArr;
    }
    
    public static void main(String[] args) {
        int[] arr = {3, 1, 4, 1, 5, 9, 2, 6, 5};
        int[] sortedArr = countingSort(arr);
        System.out.print("排序后的数组: ");
        System.out.println(Arrays.toString(sortedArr));
    }
}


C 语言 计数排序


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

void countingSort(int arr[], int n) {
    int maxVal = arr[0];
    for (int i = 1; i < n; i++) {
        if (arr[i] > maxVal) {
            maxVal = arr[i];
        }
    }
    
    int *counts = (int *)malloc((maxVal + 1) * sizeof(int));
    int *sortedArr = (int *)malloc(n * sizeof(int));
    
    // 初始化计数数组
    for (int i = 0; i <= maxVal; i++) {
        counts[i] = 0;
    }
    
    // 统计每个元素的频次
    for (int i = 0; i < n; i++) {
        counts[arr[i]]++;
    }
    
    // 计算每个元素的累积频次
    for (int i = 1; i <= maxVal; i++) {
        counts[i] += counts[i - 1];
    }
    
    // 构建有序数组
    for (int i = n - 1; i >= 0; i--) {
        sortedArr[counts[arr[i]] - 1] = arr[i];
        counts[arr[i]]--;
    }
    
    // 将有序数组拷贝回原数组
    for (int i = 0; i < n; i++) {
        arr[i] = sortedArr[i];
    }
    
    free(counts);
    free(sortedArr);
}

int main() {
    int arr[] = {3, 1, 4, 1, 5, 9, 2, 6, 5};
    int n = sizeof(arr) / sizeof(arr[0]);
    countingSort(arr, n);
    printf("排序后的数组: ");
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    return 0;
}


以上示例代码展示了不同编程语言中的计数排序算法实现。这些示例帮助你理解计数排序的工作原理,并提供了可供参考和使用的代码示例。计数排序是一种稳定且高效的排序算法,尤其适用于整数排序。


目录
打赏
0
5
4
0
107
分享
相关文章
数据结构算法--6 希尔排序和计数排序
**希尔排序**是插入排序的改进版,通过分组插入来提高效率。它逐步减少元素间的间隔(增量序列),每次对每个间隔内的元素进行插入排序,最终增量为1时进行最后一次直接插入排序,实现整体接近有序到完全有序的过程。例如,对数组`5, 7, 4, 6, 3, 1, 2, 9, 8`,先以间隔`d=4`排序,然后`d=2`,最后`d=1`,完成排序。计数排序则适用于0到100的数值,通过统计每个数出现次数,创建对应计数数组,再根据计数重建有序数组,时间复杂度为`O(n)`。
【算法】排序——归并排序和计数排序
上两篇文章讲解了插入排序、选择排序以及交换排序,每种类型的排序大类下都有一到两种排序,今天给大家带来的是归并排序,和前面几种排序一样都属于比较排序中的一种,是通过比较数组中的元素来实现排序的,还给大家带来一种非比较排序计数排序,让我们开始今天的排序之吧!!!
【C/排序算法】:归并排序和计数排序
【C/排序算法】:归并排序和计数排序
67 0
前端算法之计数排序
前端算法之计数排序
59 1
排序算法之八:计数排序
排序算法之八:计数排序
排序算法之八:计数排序
【数据结构】八大排序之计数排序算法
【数据结构】八大排序之计数排序算法
67 4
|
11月前
|
【C语言/数据结构】排序(归并排序|计数排序|排序算法复杂度)
【C语言/数据结构】排序(归并排序|计数排序|排序算法复杂度)
69 0
排序算法--------计数排序
排序算法--------计数排序

热门文章

最新文章