算法学习(6):不基于比较的排序

不基于比较的排序

不基于比较排序的意思

前面文章中提到的排序都是数组中的数字相互比较大小进行排序,所以叫基于比较的排序,本文中所要讲的排序是不比较的排序,所以叫不基于比较的排序。

计数排序

算法思想

一个整数数组arr,里面所代表的数字大小有一个确定的范围,例如:年龄。人年龄的范围可以确定为0-200,所以准备一个长度为200的额外的数组,数组的下标就代表0-200岁的年龄,下标指向的值代表arr中该年龄出现的次数。遍历arr数组,用准备的额外的数组统计每个年龄出现的次数,最后额外数组中下标从大到小,指向的值是多少,就输出多少个下标的值。

计数排序的时间复杂度

需要遍历一遍数组arr,所以时间复杂度是0(N)

算法缺点

如果数组arr中数字的范围太大,需要准备的数组长度就太长,不适用于这种算法。

基数排序(桶排序)

算法思想

以10进制的整数数组举例,准备10个桶(要保证先进先出,所以队列最佳)分别代表数字0-9。数组从左往右遍历,先看个位数,个位数是几就进与所代表数字与其相同的桶,遍历完之后,桶从左到右依次出桶,要保证先进先出,这样就可以保留个位数字上的大小的优先级;然后看十位数字,重复上面的操作,周而复始直到最大的数字的最高位那次遍历结束(超过位数的数字此位数按0算),然后出桶,这时便排好序了。


能够排好序的原因是每次遍历都会从低位开始保留大小优先级,详细算法解释见https://www.bilibili.com/video/BV13g41157hKp=5&vd_source=77d06bb648c4cce91c6939baa0595bcd P5 01:58:40

桶排序算法的限制

要排的东西必须有进制,10进制准备10个桶,2进制准备2个桶,是几进制就准备几个桶。

桶排序的C++代码实现

int getDigit(int x, int d);

int maxbits(vector<int>& arr);

void radixSort(vector<int>& arr, int left, int right, int digit);

void RadixSort(vector<int>& arr)
{
    if (arr.size() < 2)
        return;
    radixSort(arr, 0, arr.size() - 1, maxbits(arr));
}

int maxbits(vector<int>& arr)
{
    int max = INT_MIN;
    for (int i = 0; i < arr.size(); i++)
    {
        max = arr[i] > max ? arr[i] : max;
    }
    int res = 0;
    while (max != 0)
    {
        max /= 10;
        res++;
    }
    return res;
}

void radixSort(vector<int>& arr, int left, int right, int digit)
{
    int i = 0, j = 0;
    const int radix = 10;
    vector<int> bucket;
    bucket.resize(arr.size());
    for (int d = 1; d <= digit; d++)
    {
        int count[radix] = {0};
        for (i = left; i <= right; i++)
        {
            j = getDigit(arr[i], d);
            count[j]++;
        }
        for (i = 1; i < radix; i++)
        {
            count[i] += count[i - 1];
        }
        for (i = right; i >= left; i--)
        {
            j = getDigit(arr[i], d);
            bucket[count[j] - 1] = arr[i];
            count[j]--;
        }
        for (i = left, j = 0; i <= right; i++, j++)
        {
            arr[i] = bucket[j];
        }
    }
}

int getDigit(int x, int d)
{
    if (d == 1)
    {
        return x % 10;
    }
    int temp = x / (10 * (d - 1));
    return temp % 10;
}

上述代码radixSort函数中的实现方法与思路中叙述的方法不一样,是因为radixSort函数中的方法是经过优化后的方法,优化后方法的思路见https://www.bilibili.com/video/BV13g41157hK?p=5&vd_source=77d06bb648c4cce91c6939baa0595bcd P5 02:11:50

不基于比较的排序算法的总结

考虑到不基于比较的排序的缺点,必须根据数据状况来具体决定是否采用这种算法。

posted @ 2022-07-20 14:30  小肉包i  阅读(120)  评论(0)    收藏  举报