排序算法(三):时间复杂度O(n)的排序算法

O(n) 级的排序算法存在已久,但他们只能用于特定的场景

一、计数排序

计数排序限制:

举个例子,我们需要对一列数组排序,这个数组中每个元素都是 [1, 9]区间内的整数。那么我们可以构建一个长度为 9 的数组用于计数,计数数组的下标分别对应区间内的 9 个整数。然后遍历待排序的数组,将区间内每个整数出现的次数统计到计数数组中对应下标的位置。最后遍历计数数组,将每个元素输出,输出的次数就是对应位置记录的次数。
计数排序限制:数据需要分布在一定的范围内

1、算法步骤

举个例子,班上有 1010 名同学:他们的考试成绩分别是:7, 8, 9, 7, 6, 7, 6, 8, 6, 67,8,9,7,6,7,6,8,6,6,他们需要按照成绩从低到高坐到 0~90~9 共 1010 个位置上。
用计数排序完成这一过程需要以下几步:

  1. 第一步仍然是计数,统计出:44 名同学考了 66 分,33 名同学考了 77 分,22 名同学考了 88 分,1 名同学考了 99 分;
  2. 然后从头遍历数组:第一名同学考了 77 分,共有 44 个人比他分数低,所以第一名同学坐在 44 号位置(也就是第 55 个位置);
  3. 第二名同学考了 88 分,共有 77 个人(44 + 33)比他分数低,所以第二名同学坐在 77 号位置;
  4. 第三名同学考了 99 分,共有 99 个人(44 + 33 + 22)比他分数低,所以第三名同学坐在 99 号位置;
  5. 第四名同学考了 77 分,共有 44 个人比他分数低,并且之前已经有一名考了 77 分的同学坐在了 44 号位置,所以第四名同学坐在 55 号位置。
  6. …依次完成整个排序

计数排序并不是把计数数组的下标直接作为结果输出,而是通过计数的结果,计算出每个元素在排序完成后的位置,然后将元素赋值到对应位置。这样排序后的元素仍是原来的对象,且排序算法是稳定的

**如果将计数数组的下标直接作为结果输出,则排序后的元素不是原来的对象,算法也就没有稳定性可言。**在实际工作中,如果排序后的元素不是原来的对象,这样的排序算法几乎无法使用。因为被排序的对象往往都会携带其他的属性,但这份算法将被排序对象的其他属性都丢失了。

在这里插入图片描述

2、算法实现

vector<int> countSort(vector<int> arr){
   
	/-----处理空数组情况-----/
    if(arr.size() == 0) return arr;

	/-----初始化数据范围----/
    int maxNum = arr[0], minNum = arr[0];  //初始化最大最小值
    vector<int> res(arr.size());           //初始化排序结果
    for(int i = 1; i < arr.size(); i++){
      //计算最大最小值
        if(arr[i] > maxNum) maxNum = arr[i];
        if(arr[i] < minNum) minNum = arr[i];
    }
    int rangeNum = maxNum - minNum + 1;   //计算数据范围

	/-----对数
  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值