news 2026/5/5 23:17:36

C++数据结构--大数据查重

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++数据结构--大数据查重

一.哈希表在大数据查重中的应用

哈希表在大数据查重中可以查找重复或统计重复出现的数字,但是其空间的占用率较高

例如,我们定义一个数组,存储了10000个随机数,然后利用C++SLT中提供的哈希表解(unordered_map与unordered_set)决如下问题:

1.查找第一个重复的数字

遍历查找,将没有找到的数字存放在哈希表中,找到的数字直接输出。

for (auto key : vec) { if (!un_set.count(key)) { un_set.emplace(key); } else { cout << key << endl; break; } }

2.查找全部重复的数字

为了保证所有重复的数字只输出一次,我们再定义一个哈希表2,遍历查找,将没有找到的数字存放在哈希表1中,找到的数字再判断其是否在哈希表2中,在则说明这个重复的数字已经输出过了,不在则将其存入哈希表2中并输出结果。

for (auto key : vec) { if (!un_set.count(key)) { un_set.emplace(key); } else if(un_set.count(key)&&!un_set1.count(key)) { un_set1.emplace(key); cout << key << endl; } }

3.统计重复的数字及其出现次数

利用C++STL的unordered_map。

unordered_map<int,int>un_map; for (auto key : vec) { if (!un_map.count(key)) { un_map.emplace( key,1 ); } else { ++un_map[key]; } } for (auto pair : un_map) { if (pair.second > 1) { cout << pair.first << " : " << pair.second << endl; } }

4.去除重复出现的数字

C++STL的unordered_set本就不允许数字重复。

unordered_map<int, int>un_set; for (auto key : vec) { un_set.emplace(key); }

二.位图算法

位图法,就是用一个位(0或者1)来存储数据的状态(无法统计重复元素的次数),比较适合状态简单,数据量比较大,要求内存使用率低的问题场景。

位图法解决问题,首先需要知道待处理数据中的最大值,然后按照size=(maxNumber/32)+1的大小来开辟一个char类型的数组,当需要在位图中查找某个元素是否存在的时候,首先需要计算该数字对应的数组中的比特位,然后读取值,0表示不存在,1表示已存在。

位图法有一个很大的缺点,就是数据没有多少,但是最大值却很大,比如有10个整数,最大值是10亿,那么就得按10亿这个数字计算开辟位图数组的大小,太浪费内存空间。

例如,我们定义一个数组存储{ 12, 12,78,90,123,8,8,9,9 },我们想要查找所有重复出现(第一个重复出现)的数字

vector<int>vec{ 12, 12,78,90,123,8,8,9,9 }; int max = vec[0]; for (size_t i = 1; i < vec.size(); i++) { if (vec.at(i) > max) { max = vec.at(i); } } int* bitmap = new int[max / 32 + 1](); unique_ptr<int[]> ptr(bitmap); for (auto key : vec) { int index = key / 32; int offset = key % 32; if ((bitmap[index]&(1<<offset))==0) { bitmap[index] = bitmap[index] | (1 << offset); } else { cout << key << endl; //break; } }

三.布隆过滤器

1.Bloom Filter是通过一个位数组+k个哈希函数构成的(综合了前两个方法)。
2.Bloom Filter的空间和时间利用率都很高,但是它有一定的错误率,虽然错误率很低,Bloom Filter判断某个元素不在一个集合中,那该元素肯定不在集合里面;Bloom Filter判断某个元素在一个集合中,那该元素有可能在,有可能不在集合当中。
3.Bloom Filter的查找错误率,当然和位数组的大小,以及哈希函数的个数有关系,具体的错误率计算有相应的公式
4.Bloom Filter默认只支持add增加和query查询操作,不支持delete删除操作(因为存储的状态位有可能也是其它数据的状态位,删除后导致其它元素查找判断出错)。

增加一个元素
1、经过k个哈希函数计算,得到bitmap位数组里面的一组位的序号
2、把相应的位置成1
搜索一个元素
1、经过k个哈希函数计算,得到bitmap位数组里面的一组位的序号
2、判断上面几个位置的值如果全是1,证明相应的key存在,如果有一个是0,则证明key不在bloom filter中

过小的布隆过滤器很快所有的bit位均为1,那么查询任何值都会返回“可能存在”,起不到过滤的目的。布隆过滤器的长度会直接影响误报率,布隆过滤器越长其误报率越小。另外,哈希函数的个数也需要权衡,个数越多则布隆过滤器bit位置为1的速度越快,且布隆过滤器的效率越低;但是如果太少的话,那误报率就会变高。

四.Topk问题

Topk问题,就是找出一组数据中前(第)k大或前(第)k小的问题。

1.大小根堆解法

利用大根堆过滤前top k小的数据;小根堆过滤前top k大的数据

(1)查找vector中值最小的前五个元素

priority_queue<int> maxheap; int k = 5; for (size_t i = 0; i < k; i++) { maxheap.push(vec[i]); } for (size_t i = 5; i < 1000; i++) { if (vec[i] < maxheap.top()) { maxheap.pop(); maxheap.push(vec[i]); } } for (size_t i = 0; i < 5; i++) { cout << maxheap.top() << " "; maxheap.pop(); }

(2)查找最大的五个元素

priority_queue<int,vector<int>,greater<int>> minheap; int k = 5; for (size_t i = 0; i < k; i++) { minheap.push(vec[i]); } for (size_t i = k; i < vec.size(); i++) { if (minheap.top() < vec[i]) { minheap.pop(); minheap.push(vec[i]); } } while (!minheap.empty()) { cout << minheap.top() << " "; minheap.pop(); }

(3)查找重复次数最多的三个元素

unordered_map<int, int>un_map; for (auto key : vec) { un_map[key]++; } int k = 3; using Type = pair<int, int>; using Comp = function<bool(Type&, Type)>; priority_queue<Type, vector<Type>, Comp>minheap([](Type& a, Type b)->bool {return a.second > b.second; }); auto it = un_map.begin(); for (int i = 0; i < k; i++, ++it) { minheap.push(*it); } for (int i = k; i < un_map.size(); i++, ++it) { if (minheap.top().second < it->second) { minheap.pop(); minheap.push(*it); } } while (!minheap.empty()) { cout << minheap.top().first << " :" << minheap.top().second << " " << endl;; minheap.pop(); }

2.快排分割解法

(1)找值最小的三个元素

int Partaion(int arr[], int begin, int end) { int i = begin; int j = end; int val = arr[i]; while (i < j) { while (i<j && arr[j]>val) j--; if (i < j) { arr[i] = arr[j]; i++; } while (i < j && arr[i] < val) i++; if (i < j ) { arr[j] = arr[i]; j--; } } arr[i] = val; return i; } void SelectTopk(int arr[], int begin, int end, int k) { int pos = Partaion(arr, begin, end); if (pos == k - 1) { return; } else if (pos > k - 1) { SelectTopk(arr, begin, pos - 1,k); } else { SelectTopk(arr, pos + 1, end,k); } }

(2)找值最大的三个元素

int Partaion(int arr[], int begin, int end) { int i = begin; int j = end; int val = arr[i]; while (i < j) { while (i<j && arr[j]<val) j--; if (i < j) { arr[i] = arr[j]; i++; } while (i < j && arr[i] > val) i++; if (i < j) { arr[j] = arr[i]; j--; } } arr[i] = val; return i; } void SelectTopk(int arr[], int begin, int end, int k) { int pos = Partaion(arr, begin, end); if (pos == k - 1) { return; } else if (pos > k - 1) { SelectTopk(arr, begin, pos - 1, k); } else { SelectTopk(arr, pos + 1, end, k); } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/5 23:16:53

GLA与GDN:高效Transformer注意力机制对比与实践

1. 研究背景与核心问题 在自然语言处理领域&#xff0c;Transformer架构已经成为当前语言模型的主流选择。然而随着模型规模的不断扩大&#xff0c;传统全连接注意力机制的计算开销和内存占用问题日益突出。GLA&#xff08;Gated Linear Attention&#xff09;和GDN&#xff08…

作者头像 李华
网站建设 2026/5/5 23:12:28

联邦学习+元学习:强强联合,开启下一代隐私保护AI新范式

联邦学习元学习&#xff1a;强强联合&#xff0c;开启下一代隐私保护AI新范式 引言&#xff1a;当联邦学习遇见元学习 在数据孤岛与隐私法规日益严格的今天&#xff0c;联邦学习&#xff08;Federated Learning&#xff09; 已成为打破数据壁垒的关键技术。然而&#xff0c;传…

作者头像 李华
网站建设 2026/5/5 23:11:31

用 AI 剪视频?这个开源项目让我重新理解“效率“

点击上方卡片关注我设置星标 学习更多AI出海知识对长期使用Claude Code的技术开发者而言&#xff0c;有个痛点始终难以解决&#xff1a;作为AI编程的核心工具&#xff0c;Claude原生不支持视频解析&#xff0c;面对技术教程录屏、项目演示视频、操作流程录像&#xff0c;只能手…

作者头像 李华
网站建设 2026/5/5 23:10:29

避坑指南:在Unity 2021.3.2中移除启动Logo,为什么你的代码可能不生效?

深度解析&#xff1a;Unity 2021.3.2启动Logo移除失效的六大技术陷阱 当你信心满满地在Unity 2021.3.2项目中粘贴了从技术论坛找到的启动Logo移除代码&#xff0c;却发现那个熟悉的Unity图标依然顽固地出现在屏幕中央——这种挫败感我太熟悉了。作为经历过三次完整项目迭代的Un…

作者头像 李华
网站建设 2026/5/5 23:09:29

碧蓝航线自动化脚本终极指南:7个步骤快速实现游戏全自动管理

碧蓝航线自动化脚本终极指南&#xff1a;7个步骤快速实现游戏全自动管理 【免费下载链接】AzurLaneAutoScript Azur Lane bot (CN/EN/JP/TW) 碧蓝航线脚本 | 无缝委托科研&#xff0c;全自动大世界 项目地址: https://gitcode.com/gh_mirrors/az/AzurLaneAutoScript 想要…

作者头像 李华