有Leetcode中一道题,谈桶排序,基数排序和计数排序

几种非比较排序

在LeetCode中有个题目叫Maximum Gap,是求一个非排序的正数数列中按顺序排列后的最大间隔。这个题用桶排序和基数排序都可以实现。下面说一下桶排序、基数排序和计数排序这三种非比较排序。

桶排序

这种排序的主要思想是,把数列分配到多个桶中,然后再在各个桶中使用排序算法进行排序,当然也可以继续使用桶排序。

假设数组的最大值是A,最小值是B,长度是L,则每个桶的大小可以是S=Max(1,(A-B)/(L-1))则可以分为(A-B)/S+1个桶。

对于数列中的数字x,用(x-B)/S 来得到x应该在的桶的序号,然后把x放在相应的桶中。循环上面步骤。

桶排序对于数列中的数字是均匀排列的情况非常适用。

下面贴一个Leetcode Maximum Gap 的代码,其中用了桶排序的思想

class Solution:
    # @param num, a list of integer
    # @return an integer
    def maximumGap(self, num):
        N = len(num)
        if N < 2:
            return 0
        A = min(num)
        B = max(num)
        bucketRange = max(1, int((B - A - 1) / (N - 1)) + 1) #ceil( (B - A) / (N - 1) )
        bucketLen = ((B - A) / bucketRange + 1)
        buckets = [None] * bucketLen
        for K in num:
            loc = (K - A) / bucketRange
            bucket = buckets[loc]
            if bucket is None:
                bucket = {'min' : K, 'max' : K}
                buckets[loc] = bucket
            else:
                bucket['min'] = min(bucket['min'], K)
                bucket['max'] = max(bucket['max'], K)
        maxGap = 0
        for x in range(bucketLen):
            if buckets[x] is None:
                continue
            y = x + 1
            while y < bucketLen and buckets[y] is None:
                y += 1
            if y < bucketLen:
                maxGap = max(maxGap, buckets[y]['min'] - buckets[x]['max'])
            x = y
        return maxGap

基数排序

基数排序严蔚敏的数据结构中有详细介绍。主要是思想是用数字的关键字基数进行分配。这里的关键字基数通常是是进制的基数。比如十进制的话就是10,二进制就是2。通常使用链式基数排序,主要就是分配和和收集的过程。分配是里按关键字的不同值分配到各个队列中,然后收集。重复执行这个过程。

计数排序

计数排序是直接计算数字x在数列中应该在的位置。统计比它小的数字有多少个就知道它的位置了。

一个简单的C代码

void COUNTINGSORT(int *A, int *B, int array_size, int k)
{
        int C[k+1], i, value, pos;
        for(i=0; i<=k; i++)
        {
            C[i] = 0;
        }
        for(i=0; i< array_size; i++)
        {
            C[A[i]] ++;
        }
        for(i=1; i<=k; i++)
        {
            C[i] = C[i] + C[i-1];
        }
        for(i=array_size-1; i>=0; i--)
        {
            value = A[i];
            pos = C[value];
            B[pos-1] = value;
            C[value]--;
        }
}

最后贴一张各个排序算法的时间复杂度

参考文献:

1、 http://www.cnblogs.com/kaituorensheng/archive/2013/02/23/2923877.html

2、http://bookshadow.com/weblog/2014/12/14/leetcode-maximum-gap/

3、http://hxraid.iteye.com/blog/646760

时间: 2024-10-25 22:13:25

有Leetcode中一道题,谈桶排序,基数排序和计数排序的相关文章

大话桶排序 基数排序和计数排序

一:计数排序 (1)当输入的元素是 n 个 0 到 k 之间的整数时,它的运行时间是 Θ(n + k).计数排序不是比较排序,排序的速度快于任何比较排序算法.由于用来计数的数组C的长度取决于待排序数组中数据的范围(等于待排序数组的最大值与最小值的差加上1),这使得计数排序对于数据范围很大的数组,需要大量时间和内存.例如:计数排序是用来排序0到100之间的数字的最好的算法,但是它不适合按字母顺序排序人名.但是,计数排序可以用在基数排序中的算法来排序数据范围很大的数组. (2)算法的步骤如下: 1.

Java实现基于桶式排序思想和计数排序思想实现的基数排序

计数排序 前提:待排序表中的所有待排序关键字必须互不相同: 思想:计数排序算法针对表中的每个记录,扫描待排序的表一趟,统计表中有多少个记录的关键码比该记录的关键码小,假设针对某一个记录,统计出的计数值为c,则该记录在新的有序表中的存放位置即为c. 性能:空间复杂度:o(n):时间复杂度:o(n^2): 1 public int[] countSort(int[] array){ 2 int[] tempArray = new int[array.length]; //引入辅助数组 3 for(i

基本排序系列之计数排序

简述计数排序 看了好多别人写的计数排序,看了好久都没看懂,弄了好久最后发现这么简单居然花了几个小时,所以在这里写上,希望和我一样的初学者不会再绕弯路. 一.简述计数排序的思想: 设被排序的数组为A,排序后存储到B,C为临时数组.所谓计数,首先是通过一个数组C[i]计算大小等于i的元素个数,此过程只需要一次循环遍历就可以:在此基础上,计算小于或者等于i的元素个数,也是一重循环就完成.下一步是关键:逆序循环,从length[A]到1,将A[i]放到B中第C[A[i]]个位置上.原理是:C[A[i]]

排序算法之计数排序

mnesia在频繁操作数据的过程可能会报错:** WARNING ** Mnesia is overloaded: {dump_log, write_threshold},可以看出,mnesia应该是过载了.这个警告在mnesia dump操作会发生这个问题,表类型为disc_only_copies .disc_copies都可能会发生. 如何重现这个问题,例子的场景是多个进程同时在不断地mnesia:dirty_write/2 mnesia过载分析 1.抛出警告是在mnesia 增加dump

算法导论之六:线性时间排序之 决策树&amp;计数排序

本系列前五篇都是讲述的比较排序算法,从本文开始,将进入线性时间排序.什么是比较排序,简单的说,就是排序的过程依赖于数组中数据大小的比较,从而来确定数据在排好序输出时的位置. 比较排序法比较直观,但是也有它的不足,我们容易证明任何比较排序法,在最坏的情况下的时间复杂度的下限都是 nlgn.要证明这个问题,我们首先要搞清楚一个模型:决策树模型. 一.决策树模型 什么是决策树?决策树从形态上来讲,是一颗完全二叉树,它除叶子节点之外,其他层的节点都是满的.它的每一个叶子节点表示对输入数据组合的一种排序可

【排序】基数排序(计数排序、桶排序)

在此对于桶排序做出两种方法: 一.简化版桶排序 代码如下: <span style="font-size:18px;">/*简化版的桶排序*/ #include <stdio.h> int main() { int book[1001],i,j,t,n; for(i=0;i<=1000;i++) { book[i]=0; } scanf("%d",&n);//输入一个数n,表示接下来有n个数 for(i=1;i<=n;i+

常见排序算法之计数排序与基数排序

1.计数排序 顾名思义,是对待排序数组中的数据进行统计,然后根据统计的数据进行排序,例如: 待排序数组: a[] = { 100, 123, 112, 123, 201, 123, 112, 156, 156, 178, 185, 156, 123, 112 } 首先取出数组中最大值与最小值(这个不用说了吧) 最大值:201  最小值:100 因此该数组的数值范围为 201 - 100 + 1 = 102 开辟一个大小为102的数组 count[102] 并将所有元素初始化为0 再次遍历数组,以

三种线性排序算法(计数、基数、桶排序)的简单实现

一.计数排序 计数排序假设n个输入元素中的每一个都是介于0到k之间的整数.此处k为某个整数(输入数据在一个小范围内). 基本思想: 计数排序的基本思想是对每一个输入元素x,确定出小于x的元素的个数.然后再将x直接放置在它在最终输出数组中的位置上. 如下图所示: 由于数组中可能有相等的数,在处理时需要注意. 时间复杂度和空间复杂度分析 算法总时间Θ(k + n).当k=O(n)时,计数排序的运行时间是Θ(n). 空间复杂度是O(n+k).需要两个辅助数组:存放排序结果的数组B[n],存放临时结果的

线性排序算法---- 计数排序, 基数排序, 桶排序

排序算法里,除了比较排序算法(堆排序,归并排序,快速排序),还有一类经典的排序算法-------线性时间排序算法.听名字就让人兴奋! 线性时间排序,顾名思义,算法复杂度为线性时间O(n) , 非常快,比快速排序还要快的存在,简直逆天.下面我们来仔细看看三种逆天的线性排序算法, 计数排序,基数排序和桶排序. 1计数排序  counting Sort 计数排序 假设 n个 输入元素中的每一个都是在 0 到 k 区间内的一个整数,当 k= O(N) 时,排序运行的时间为 O(N). 计数排序的基本思想