美文网首页
线性排序

线性排序

作者: 麦兜的夏天 | 来源:发表于2019-07-21 21:19 被阅读0次

时间复杂度为线性( O(n) )的排序方式叫做线性排序。常见的线性排序有桶排序、计数排序、基数排序。

桶排序

(1)就是将数据放入已经排好序的桶中,然后对桶中的数据分别进行排序,最后按照桶的顺序将数据拿出来,就是排完序的样子。
例如:需要对100万个用户按照年龄进行排序,可以将0-9岁的放到1号桶,10-19岁的放到2号桶,20-29岁的放到3号桶。。。。100-119岁。。。然后在将各个桶里面的数据利用其它排序方法(例如快排)排好序,最后按照桶的大小顺序将元素取出来。
(2)

    private int indexFor(int a, int min, int step) {
        return (a - min) / step;
    }

    public void bucketSort(int[] arr) {

        int max = arr[0], min = arr[0];
        for (int a : arr) {
            if (max < a)
                max = a;
            if (min > a)
                min = a;
        }
        // 桶的个数
        int bucketNum = max / 10 - min / 10 + 1;
        List buckList = new ArrayList<List<Integer>>();
        // 创建桶
        for (int i = 1; i <= bucketNum; i++) {
            buckList.add(new ArrayList<Integer>());
        }
        // 将数据放入合适的桶中
        for (int i = 0; i < arr.length; i++) {
            int index = indexFor(arr[i], min, 10);
            ((ArrayList<Integer>) buckList.get(index)).add(arr[i]);
        }
          // 将排好序的数放入原数组中
        ArrayList<Integer> bucket = null;
        int index = 0;
        for (int i = 0; i < bucketNum; i++) {
            bucket = (ArrayList<Integer>) buckList.get(i);
            insertSort(bucket);
            for (int k : bucket) {
                arr[index++] = k;
            }
        }

    }

    // 把桶內元素插入排序
    private void insertSort(List<Integer> bucket) {
        for (int i = 1; i < bucket.size(); i++) {
            int temp = bucket.get(i);
            int j = i - 1;
            for (; j >= 0 && bucket.get(j) > temp; j--) {
                bucket.set(j + 1, bucket.get(j));
            }
            bucket.set(j + 1, temp);
        }
    }

(3)时间复杂度分析:
如果要排序的数据有 n 个,我们把它们均匀地划分到 m 个桶内,每个桶里就有 k=n/m 个元素。每个桶内部使用快速排序,时间复杂度为 O(k * logk)。m 个桶排序的时间复杂度就是 O(m * k * logk),因为 k=n/m,所以整个桶排序的时间复杂度就是 O(n*log(n/m))。当桶的个数 m 接近数据个数 n 时,log(n/m) 就是一个非常小的常量,这个时候桶排序的时间复杂度接近 O(n)。

(4)桶排序的弊端:
要保证桶排序法的时间复杂度为线性的,需要让各个桶内的元素数量均匀,如果出现极端情况,比如所有的元素都几种到了同一个桶里面,那么桶排序的时间复杂度就会退化为O(nlogn)。由此看来,桶排序的应用场景非常有限。

计数排序

(1)计数排序法是一种特殊的桶排序法,它是将数据范围缩到最小。
例如:同样是将100万个人按照年龄排序,可以将0岁放入1号桶,2岁放入2号桶。。。。。

(2)那么“计数”体现在什么地方?
同样是上面的例子,我们将数据规模缩小来说明这个事。
假如有8位小朋友,年龄分别是:2,5,3,0,2,3,0,3
创建一个数据来存储各个年龄的人数:

数组:[2,0,2,3,0,1]
索引:[0,1,2,3,4,5]

事实上现在除了知道每个年龄的人数之外,还知道了在它前面有多少人。比如:3岁的有3人,前面有4人。

(3)应用中,为了把这个事办的更省心一些,会直接在每一个年龄的上面标一个数字,这个数字表示该年龄前面所有年龄人数之和加上该年龄的人数。例如:上面的例子

个数:[2,2,4,7,7,8]
年龄:[0,1,2,3,4,5]

排序的时候,遍历到第一个3的时候,将它放到索引为6的位置,然后将它上面的数字减一,第二次遇到3时,将它放到第5的位置,上的数字再减一,所有的年龄都是同样的操作。

(4)

// 计数排序,a 是数组。假设数组中存储的都是非负整数。
public void countingSort(int[] a) {
  if (a.length <= 1) return;

  // 查找数组中数据的范围
  int max = a[0];
  for (int i = 1; i < a.length; ++i) {
    if (max < a[i]) {
      max = a[i];
    }
  }

  int[] c = new int[max + 1]; // 申请一个计数数组 c,下标大小 [0,max]
  for (int i = 0; i <= max; ++i) {
    c[i] = 0;
  }

  // 计算每个元素的个数,放入 c 中
  for (int i = 0; i < a.length; ++i) {
    c[a[i]]++;
  }

  // 依次累加
  for (int i = 1; i <= max; ++i) {
    c[i] = c[i-1] + c[i];
  }

  // 临时数组 r,存储排序之后的结果
  int[] r = new int[a.length];
  // 计算排序的关键步骤
  for (int i = a.length - 1; i >= 0; --i) {
    int index = c[a[i]]-1;
    r[index] = a[i];
    c[a[i]]--;
  }

  // 将结果拷贝给 a 数组
  for (int i = 0; i < a.length; ++i) {
    a[i] = r[i];
  }
}

待续。。

相关文章

  • 线性排序

    桶排序、计数排序、基数排序 一、线性排序算法介绍 1.线性排序算法包括桶排序、计数排序、基数排序。2.线性排序算法...

  • 线性排序

    时间复杂度为线性( O(n) )的排序方式叫做线性排序。常见的线性排序有桶排序、计数排序、基数排序。 桶排序 (1...

  • 线性排序

    一、线性排序算法介绍 线性排序算法包括桶排序、计数排序、基数排序。 线性排序算法的时间复杂度为O(n)。 此3种排...

  • 桶排序、计数排序、基数排序

    一、线性排序算法介绍 线性排序算法包括桶排序、计数排序、基数排序。 线性排序算法的时间复杂度为O(n)。 此3种排...

  • 11|线性排序:如何根据年龄给100万用户数据排序?

    一、线性排序算法介绍 1.线性排序算法包括桶排序、计数排序、基数排序。2.线性排序算法的时间复杂度为O(n)。3....

  • 排序算法三(桶,计数,基数)

    桶排序,计数排序,基数排序算法的时间复杂度都是线性的,所以把这类排序算法叫作线性排序。 桶排序 概念:将要排序的数...

  • 7基础算法之桶排序,计数排序,基数排序

    桶排序、计数排序、基数排序。因为这些排序算法的时间复杂度是线性的,所以我们把这类排序算法叫作线性排序(Linear...

  • 线性排序

    线性排序就是可以在O(n)时间复杂度内完成的排序。常见的排序方式有:桶排序,计数排序,基数排序。之所以能做到线性时...

  • 数据结构与算法之线性排序

    线性排序的三大排序算法:桶排序、计数排序、基数排序 这三个算法都不是基于比较的排序算法,所以能做到线性的时间复杂度...

  • 线性排序

    桶排序 核心思想是将要排序的数据分到几个有序的桶里,每个桶里的数据再单独进行排序。桶内排序完之后,再把每个桶里的数...

网友评论

      本文标题:线性排序

      本文链接:https://www.haomeiwen.com/subject/oqpvlctx.html