小白思路:哈希排序

算法思想

将大量杂乱数据按照大小顺序排出每个数字重复多少次。通过两个数组实现。原始数据数组a和按照数字大小排出的重复次数数字count。a的数字大小对应count的下标,count下标对应的值是该下标重复出现的次数。用循环遍历统计。

注意

  1. a数组下标从0开始,并且每一个下标位置都有具体的值,count数组下标对应的就是这个数字出现的次数,如果限定了count的大小范围,则不用从0开始考虑

  1. 代码针对一个具体问题:假设一个公司有一万个员工,年龄集中在21~60岁,要统计出最年轻的一千名员工的平均年龄

  1. 在计算前一千名员工平均年龄的时候,不是一下子找出这一千个人计算平均年龄的(实际上也办不到),而是拆解成一步一步的去算,每一步都算出一个平均数,下一次用这个平均数来算出总数,保证最后恰好统计到1000个人。

代码实现

代码(疯狂注释版)

  • 加了很多print用来测试写的对不对,小白第一次用rand()生成限定范围的值,后来都注释掉了,只留了最后用来统计的count数组。

#include <iostream>
#include<malloc.h>
#include<stdio.h>
#include<stdlib.h>

using namespace std;

//HashSort
// 时间复杂度:O(n)
//算法思想:很多数据的情况下要统计部分数据有多少、平均值等,初始化一个数组,每次遇到对应数组序号的值
//则对应序号的数组值+1,这样就能统计出每个值有多少个数字
//即:数组下标是数字的值,数组的值是数字出现的次数
int main()
{
    //随机生成一万个年龄在21-60岁的员工年龄(整数),使用rand()产生随机数。
    //要随机数在21-60之间,则用随机数对40取余,会产生0-39之间的数,之后加上21,则产生21~60之间的数
    //伪随机数,只是为了方便用了rand(),不是真正的随机数
    int a[10000];//年龄数组,共一万个随机年龄
    for (int i = 0; i < 10000; i++)
    {
        a[i] = rand() % 40 + 21;
    }
    //打印部分年龄测试
    /*for (int x = 0; x < 100; x++)
    {
        cout << a[x] << " ";
    }*/
    cout << endl;
    //年龄人数数组初始化,设置61个值可以使下标从0~60,共61个数
    int count[61] = { 0 };
    //遍历年龄数组,每遇到一个年龄,则对应人数数组下标位置的值++
    for (int j = 0; j < 10000; j++)
    {
        count[a[j]]++;
    }
    //打印出年龄人数数组
    for (int y = 21; y < 61; y++)
    {
        cout << y << "岁: " << count[y] << "  ";
    }
    /*//验算最后是不是10000人的数据
    int sum = 0;
    for (int n = 0; n < 61; n++) 
        sum += count[n];
    cout << endl;
    cout << sum; 
    */
    //不能一次直接找到前一千个人,所以循环遍历,分为两种情况:
    //1.加上某个年龄的人数后正好是一千人;2.加上某个年龄的人数后超过一千人,只取这里人数的一部分算
    // 一定只有这两种情况,要么加上下一个年龄段的人数不足或正好够了,要么加上后人数直接超了
    //核心想法:不是一次性找出前一千人是谁和算出平均值的,而是分步,每一步都算出一个平均值,用于计算加上下一个年龄人的人数后的平均值
    int num = 0;
    float average = 0;//平均年龄
    for (int z = 21; (z < 61) && (num < 1000); z++)
    {
        if (num + count[z] <= 1000)
        {
            //当前人数加上这个年龄段人数小于等于1000则这个年龄段人全部都加上算平均
            average = (average * num + z * count[z]) / (num + count[z]);
            num += count[z];
        }
        else 
        {
            //当前人数加上这个年龄段人数大于1000则计算还差多少人满1000,缺的人数用当前年龄补上
            average = (average * num + (1000 - num) * z) / 1000;
            num = 1000;
        }
    }
    cout << "\n\n —————————————— \n\n" << "人数: " << num << "    平均年龄: " << average << endl;
}

代码(纯享版)

#include <iostream>
#include<malloc.h>
#include<stdio.h>
#include<stdlib.h>

using namespace std;

int main()
{
    int a[10000];//年龄数组,共一万个随机年龄
    for (int i = 0; i < 10000; i++)
    {
        a[i] = rand() % 40 + 21;
    }
    
    int count[61] = { 0 };
    for (int j = 0; j < 10000; j++)
    {
        count[a[j]]++;
    }
    //打印出年龄人数数组
    for (int y = 21; y < 61; y++)
    {
        cout << y << "岁: " << count[y] << "  ";
    }
    
    int num = 0;
    float average = 0;//平均年龄
    for (int z = 21; (z < 61) && (num < 1000); z++)
    {
        if (num + count[z] <= 1000)
        {
            average = (average * num + z * count[z]) / (num + count[z]);
            num += count[z];
        }
        else 
        {
            average = (average * num + (1000 - num) * z) / 1000;
            num = 1000;
        }
    }
    cout << "\n\n —————————————— \n\n" << "人数: " << num << "    平均年龄: " << average << endl;
}

运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值