基于Hash表的排序--C语言

我们知道,C语言里面是没有hash表的,但是我们可以用一个结构体表示,对结构体排序,我们可以用qsort排序。
下面我们用一个LeedCode上面的一道题目讲解。
347. 前 K 个高频元素
这个题目是让我们求解前k个高频元素,求解思路如下:我们构建一个Hash表,Hash表用一个结构体表示,该结构体存放元素值和元素的个数,我们先把数组里面的值存放到Hash表里面,然后我们对该Hash表按照元素个数进行进行排序,这样就可以找到前k个高频元素了。

1 定义Hash表
#define Hash_SIZE 20001
#define OFFSET 10000 

typedef struct {
    int val;			//存放值
    int cnt;			//cnt存储出现次数
}HashTable;
HashTable hash[Hash_SIZE];

hash就是我们要的Hash表。

2 将数组值存放到Hash表中
for (i = 0; i < numsSize; i++) {     		   //将值和出现的次数放入hash表中
        hash[(nums[i] + OFFSET) % Hash_SIZE].cnt++;   //偏移使下标>=0
        hash[(nums[i] + OFFSET) % Hash_SIZE].val = nums[i];
    }

    for (i = 0; i < Hash_SIZE; i++) {   		  //对原hash表进行优化,从开始存储
        if (hash[i].cnt != 0) {
            hash[j].cnt = hash[i].cnt;
            hash[j].val = hash[i].val;
            j++;
        }
    }
3 对Hash表按照元素个数进行排序
int comp(const void* a, const void* b) {	//cnt大到小
    return (((HashTable*)b)->cnt - ((HashTable*)a)->cnt);
}

qsort(hash, j, sizeof(HashTable), comp);

全部代码:

#define Hash_SIZE 20001
#define OFFSET 10000 

typedef struct {
    int val;
    int cnt;			//cnt存储出现次数
}HashTable;
HashTable hash[Hash_SIZE];

int comp(const void* a, const void* b) {	//cnt大到小
    return (((HashTable*)b)->cnt - ((HashTable*)a)->cnt);
}

int* topKFrequent(int* nums, int numsSize, int k, int* returnSize) {
    memset(hash, 0, sizeof(hash));   			//初始化0
    int i, j = 0;

    for (i = 0; i < numsSize; i++) {     		   //将值和出现的次数放入hash表中
        hash[(nums[i] + OFFSET) % Hash_SIZE].cnt++;   //偏移使下标>=0
        hash[(nums[i] + OFFSET) % Hash_SIZE].val = nums[i];
    }

    for (i = 0; i < Hash_SIZE; i++) {   		  //对原hash表进行优化,从开始存储
        if (hash[i].cnt != 0) {
            hash[j].cnt = hash[i].cnt;
            hash[j].val = hash[i].val;
            j++;
        }
    }

    qsort(hash, j, sizeof(HashTable), comp);
    for (i = 0; i < k; i++)	nums[i] = hash[i].val;	//输出前k个高频元素

    *returnSize = k;
    return nums;
}

其他

为什么OFFSET是10000,Hash_Size是20001,我看别人的解释是这个题目数的范围是-10000到+10000。超过这个范围会报错

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值