排序算法烩菜(一)——计数排序

计数排序

计数排序是一种非比较性质的排序算法,元素从未排序状态变为已排序状态的过程,是由额外空间的辅助和元素本身的值决定的。计数排序过程中不存在元素之间的比较和交换操作,根据元素本身的值,将每个元素出现的次数记录到辅助空间后,通过对辅助空间内数据的计算,即可确定每一个元素最终的位置。比较排序算法的时间复杂度理论值是O(nlogn),计数排序某些情况下可以比比较排序更快。

  • 时间复杂度:best:O(n+k); worst:O(n+k); average:O(n+k)
  • 空间复杂度:O(k)
  • 稳定性:稳定
  • 适用于:元素集中,整数排序
  • 算法过程:
    1. 根据待排序集合中最大元素和最小元素的差值范围,申请额外空间;
    2. 遍历待排序集合,将每一个元素出现的次数记录到元素值对应的额外空间内;
    3. 对额外空间内数据进行计算,得出每一个元素的正确位置(即将a[i]的值加上前面所有的值,因为额外空间的需要排序的元素(下标)是有序的,加上之后就表示a[i]对应的下标元素应该在的排序后的位置);
    4. 将待排序集合每一个元素移动到计算得出的正确位置上。
  • 实现:
# python实现
def countingSort(arr):  # the elements in the array are all integers
    maximum, minimum = max(arr), min(arr)
    countArr = [0] * (maximum - minimum + 1)
    for i in arr: # record the number of times of every element in the array
        countArr[i - minimum] += 1
    for i in range(1, len(countArr)): # calculate the position of every element
        countArr[i] += countArr[i-1]
    targetArr = [None] * len(arr)
    for i in range(len(arr)-1, -1, -1): # reverse-order traversal is for the stability
        countIndex = arr[i] - minimum
        targetArr[countArr[countIndex] - 1] = arr[i]
        countArr[countIndex] -= 1
    return targetArr
class Solution
{
public:
    int* coutSort(int* data, int length)
    {
        if (data == nullptr || length <= 0)
            return nullptr;

        //确定数列最大值
        int max = data[0];
        int min = data[0];
        for (int i = 1; i < length; ++i)
        {
            if (data[i] > max)
                max = data[i];
            if (data[i] < min)
                min = data[i];
        }
        int d = max - min;
        // 确定统计数组长度并进行初始化
        int* coutData = new int[d + 1];
        for (int i = 0; i <= d; ++i)
            coutData[i] = 0;
        // 遍历数组,统计每个数出现的次数
        for (int i = 0; i < length; ++i)
                ++coutData[data[i] - min];
        // 统计数组做变形,后面的元素等于前面的元素之和
        for (int i = 1; i <= d; ++i)
            coutData[i] += coutData[i - 1];
    // 倒序遍历原始数列,从统计数组找到正确的位置,输出到结果数组
        int* sortedArray = new int[length];
        for (int i = length - 1; i >= 0; i--)
        {
            sortedArray[coutData[data[i] - min] - 1] = data[i];        // 找到data[i]对应的coutData的值,值为多少,表示原来排序多少,(因为从1开始,所以再减1)
            coutData[data[i] - min]--;        // 然后将相应的coutData的值减1,表示下次再遇到此值时,原来的排序是多少。
        }
        return sortedArray;
    }
};

参考链接:
https://www.jianshu.com/p/86c2375246d7
https://www.cnblogs.com/wyr-123-wky/p/11093919.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值