数据结构与算法简记--排序算法(2) -线性排序

线性排序

  • 线性排序即时间复杂度为O(n)的排序算法
  • 桶排序------>分桶+归并排序-->取出结果
  • 计数排序------>分桶+计数-->先统计计数,再取出来,实现排序
  • 基数排序------>在每个位上桶排序
  • 桶排序的思想可用来对数据分类

桶排序--将要排序的数据分到几个有序的桶里,每个桶里的数据再单独进行排序(桶内使用归并排序保证稳定性),再把每个桶里的数据按照顺序依次取出

  • 适合用于外部排序(数据存储在磁盘),数据量比较大,内存不足时,把数据按区间分成若干个桶,每次处理一个桶

计数排序--获取数据项大小范围,设置 “范围大小+1” 个桶,n个桶只代表0~n-1个数字,分别对值为每个桶代表的数字的数据项计数,放入对应桶,再对桶顺序求和放入桶,最后从后遍历数据项,取对应下标桶的计数为其排序后下标,取完桶计数减一,遍历完则排序完成。

  • 计数排序只能用在数据范围不大的场景中,如果数据范围 k 比要排序的数据 n 大很多,就不适合用计数排序了。而且,计数排序只能给非负整数排序,如果要排序的数据是其他类型的,要将其在不改变相对大小的情况下,转化为非负整数。
  • 应用如:高考分数排名
  • 伪代码
  • // 计数排序,a是数组,n是数组大小。假设数组中存储的都是非负整数。
    public void countingSort(int[] a, int n) {
      if (n <= 1) return;
    
      // 查找数组中数据的范围
      int max = a[0];
      for (int i = 1; i < n; ++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 < n; ++i) {
        c[a[i]]++;
      }
    
      // 依次累加
      for (int i = 1; i <= max; ++i) {
        c[i] = c[i-1] + c[i];
      }
    
      // 临时数组r,存储排序之后的结果
      int[] r = new int[n];
      // 计算排序的关键步骤,有点难理解
      for (int i = n - 1; i >= 0; --i) {
        int index = c[a[i]]-1;
        r[index] = a[i];
        c[a[i]]--;
      }
    
      // 将结果拷贝给a数组
      for (int i = 0; i < n; ++i) {
        a[i] = r[i];
      }
    }

基数排序--对等长数据项进行排序,为保持稳定,从最后一位开始,每次按数据项的一位进行排序,排序过程可用桶排序或计数排序,各位排序完成则排序完成,复杂度O(k*n),k为位数

  • 基数排序对要排序的数据是有要求的,需要可以分割出独立的“位”来比较,而且位之间有递进的关系,如果 a 数据的高位比 b 数据大,那剩下的低位就不用比较了。除此之外,每一位的数据范围不能太大,要可以用线性排序算法来排序,否则,基数排序的时间复杂度就无法做到 O(n) 了。
  • 应用如:手机号排序

猜你喜欢

转载自www.cnblogs.com/wod-Y/p/11968507.html
今日推荐