基于C#实现Bitmap算法

在所有具有性能优化的数据结构中,我想大家使用最多的就是 hash 表,是的,在具有定位查找上具有 O(1)的常量时间,多么的简洁优美,但是在特定的场合下:
①:对 10 亿个不重复的整数进行排序。
②:找出 10 亿个数字中重复的数字。
当然我只有普通的服务器,就算 2G 的内存吧,在这种场景下,我们该如何更好的挑选数据结构和算法呢?

一、问题分析

这年头,大牛们写的排序算法也就那么几个,首先我们算下放在内存中要多少 G:
(10 亿 * 32)/(102410241024*8)=3.6G,可怜的 2G 内存直接爆掉,所以各种神马的数据结构都玩不起来了,当然使用外排序还是可以解决问题的,由于要走 IO 所以暂时剔除,因为我们要玩高性能,无望后我们想想可不可以在二进制位上做些手脚?
比如我要对{1,5,7,2}这四个 byte 类型的数字做排序,该怎么做呢?我们知道 byte 是占 8 个 bit 位,其实我们可以将数组中的值作为 bit 位的 key,value 用”0,1“来标识该 key 是否出现过?下面看图:
image.png
从图中我们精彩的看到,我们的数组值都已经作为 byte 中的 key 了,最后我只要遍历对应的 bit 位是否为 1 就可以了,那么自然就成有序数组了。
可能有人说,我增加一个 13 怎么办?很简单,一个字节可以存放 8 个数,那我只要两个 byte 就可以解决问题了。
image.png
可以看出我将一个线性的数组变成了一个 bit 位的二维矩阵,最终我们需要的空间仅仅是:3.6G/32=0.1G 即可,要注意的是 bitmap 排序不是 N 的,而是取决于待排序数组中的最大值,在实际应用上关系也不大,比如我开 10 个线程去读 byte 数组,那么复杂度为:O(Max/10)。

二、代码

我想 bitmap 的思想大家都清楚了,这一次又让我们见证了二进制的魅力,当然这些移位都是位运算的工作了,熟悉了你就玩转了。

1、Clear 方法(将数组的所有 bit 位置 0)

比如要将当前 4 对应的 bit 位置 0 的话,只需要 1 左移 4 位取反与 B[0] & 即可。
image.png

 #region 初始化所用的bit位为0/// <summary>/// 初始化所用的bit位为0/// </summary>/// <param name="i"></param>static void Clear(byte i){//相当于 i%8 的功能var shift = i & 0x07;//计算应该放数组的下标var arrindex = i >> 3;//则将当前byte中的指定bit位取0,&后其他对方数组bit位必然不变,这就是 1 的妙用var bitPos = ~(1 << shift);//将数组中的指定bit位置一  “& 操作”a[arrindex] &= (byte)(bitPos);}#endregion

2、Add 方法(将 bit 置 1 操作)

同样也很简单,要将当前 4 对应的 bit 位置 1 的话,只需要 1 左移 4 位与 B[0] | 即可。
image.png

 #region 设置相应bit位上为1/// <summary>/// 设置相应bit位上为1/// </summary>/// <param name="i"></param>static void Add(byte i){//相当于 i%8 的功能var shift = i & 0x07;//计算应该放数组的下标var arrindex = i >> 3;//将byte中的 1 移动到i位var bitPos = 1 << shift;//将数组中的指定bit位置一  “| 操作”a[arrindex] |= (byte)bitPos;}#endregion

3、Contain 方法(判断当前 bit 位是否是 1)

如果看懂了 Clear 和 Add,我相信最后一个方法已经不成问题了。

 #region 判断当前的x在数组的位中是否存在/// <summary>///判断当前的x在数组的位中是否存在/// </summary>/// <param name="i"></param>/// <returns></returns>static bool Contain(byte i){var j = a[i >> 3] & (1 << (i & 0x07));if (j == 0)return false;return true;}#endregion

最后上总的代码:

 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Diagnostics;using System.Threading;using System.IO;namespace ConsoleApplication2{public class Program{static byte n = 7;static byte[] a;public static void Main(){//节省空间的做法a = new byte[(n >> 3) + 1];for (byte i = 0; i < n; i++)Clear(i);Add(4);Console.WriteLine("插入4成功!");var s = Contain(4);Console.WriteLine("当前是否包含4:{0}", s);s = Contain(5);Console.WriteLine("当前是否包含5:{0}", s);Console.Read();}#region 初始化所用的bit位为0/// <summary>/// 初始化所用的bit位为0/// </summary>/// <param name="i"></param>static void Clear(byte i){//相当于 i%8 的功能var shift = i & 0x07;//计算应该放数组的下标var arrindex = i >> 3;//则将当前byte中的指定bit位取0,&后其他对方数组bit位必然不变,这就是 1 的妙用var bitPos = ~(1 << shift);//将数组中的指定bit位置一  “& 操作”a[arrindex] &= (byte)(bitPos);}#endregion#region 设置相应bit位上为1/// <summary>/// 设置相应bit位上为1/// </summary>/// <param name="i"></param>static void Add(byte i){//相当于 i%8 的功能var shift = i & 0x07;//计算应该放数组的下标var arrindex = i >> 3;//将byte中的 1 移动到i位var bitPos = 1 << shift;//将数组中的指定bit位置一  “| 操作”a[arrindex] |= (byte)bitPos;}#endregion#region 判断当前的x在数组的位中是否存在/// <summary>///判断当前的x在数组的位中是否存在/// </summary>/// <param name="i"></param>/// <returns></returns>static bool Contain(byte i){var j = a[i >> 3] & (1 << (i & 0x07));if (j == 0)return false;return true;}#endregion}}

image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/160112.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI原生应用为百度带来新增量

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; AI将彻底改变每一个行业!得益于AI和基础模型的驱动&#xff0c;百度在AI原生应用领域厚积薄发。 11月21日&#xff0c;百度Q3财报发布&#xff0c;数据显示&#xff1a;三季度营收达344.47亿元&…

Redis篇---第九篇

系列文章目录 文章目录 系列文章目录前言一、如果有大量的 key 需要设置同一时间过期,一般需要注意什么?二、什么情况下可能会导致 Redis 阻塞?三、缓存和数据库谁先更新呢?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击…

Axios简单使用与配置安装-Vue

安装Axios npm i axios main.js 导入 import Axios from axios Vue.prototype.$axios Axios简单发送请求 get getTest() {this.$axios({method: GET,url: https://apis.jxcxin.cn/api/title?urlhttps://apis.jxcxin.cn/}).then(res > {//请求成功回调console.log(res)}…

②⑩ 【MySQL Log】详解MySQL日志:错误日志、二进制日志、查询日志、慢查询日志

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ MySQL日志 ②⑩ MySQL日志&#xff1a;错误日志…

SpringBoot3.x最简集成SpringDoc-OpenApi

为什么使用SpringDoc 在SpringBoot低版本时一般使用Swagger扫描接口生成Json格式的在线文档&#xff0c;然后通过swagger-ui将Json格式的文档以页面形式展示文档。可惜遗憾的是swagger更新到3.0.0版本(springfox)后不更新了。 SpringBoot3.x以后需要的JDK版本最低为Java17&…

MQ和redis的内部原理一些总结

首先&#xff0c;先知道内部原理&#xff1b;其次&#xff0c;就是查官方文档实战了。 但是如果不熟悉内部原理&#xff0c;那么仅仅只是安装官方文档&#xff0c;并不能排除跟踪问题和故障、预防风险等策略&#xff1b; 以下总结图解&#xff1a;&#xff08;mysql 8.0新增的…

YOLO目标检测——卫星遥感舰船检测数据集下载分享【含对应voc、coco和yolo三种格式标签】

实际项目应用&#xff1a;卫星遥感舰船检测数据集说明&#xff1a;卫星遥感舰船检测数据集&#xff0c;真实场景的高质量图片数据&#xff0c;数据场景丰富&#xff0c;含船一个类别标签说明&#xff1a;使用lableimg标注软件标注&#xff0c;标注框质量高&#xff0c;含voc(xm…

Redis的持久化

redis是一个内存数据库,是把数据存储在内存中的,而我们知道内存中的数据是不持久的,一旦服务器重启或者进程重启,内存的数据就丢失了.为了让数据达到持久化的效果,就必须把数据写到硬盘上. redis相对于mysql这样的关系型数据库最明显的优势就是快.所以为了保证速度快,数据还得…

动态跳过测试用例

动态跳过测试用例 说明 我们可以通过指定环境变量来动态判断是否执行指定的测试用例设置环境变量有很多种方法&#xff0c;例如命令行方式&#xff0c;格式&#xff1a;--env keyval1,key2val2 &#xff0c;若需要指定多个环境变量则需要逗号来隔开&#xff0c;而不是空格 t…

Live800:企业提升客户互动体验,有哪些关键因素?

如今&#xff0c;随着信息时代的不断发展&#xff0c;企业已经不再是单向的商业机构&#xff0c;他们需要与客户进行及时的沟通与反馈&#xff0c;从而更好地提升客户互动体验&#xff0c;达到营销和用户体验的双赢局面。那么&#xff0c;企业如何提升客户互动体验呢&#xff1…

设计模式——RBAC 模型详解

1.什么是 RBAC 呢&#xff1f; RBAC 即基于角色的权限访问控制&#xff08;Role-Based Access Control&#xff09;。这是一种通过角色关联权限&#xff0c;角色同时又关联用户的授权方式。 简单地说&#xff1a;一个用户可以拥有若干角色&#xff0c;每一个角色又可以被分配…

Linux程序之可变参数选项那些事!

一、linux应用程序如何接收参数&#xff1f; 1. argc、argv Linux应用程序执行时&#xff0c;我们往往通过命令行带入参数给程序&#xff0c;比如 ls /dev/ -l 其中参数 /dev/ 、-l都是作为参数传递给命令 ls 应用程序又是如何接收这些参数的&#xff1f; 通常应用程序都…

Raspberry Pi 5 新一代单板计算机:树莓派5代 (介绍、入门、解疑)

树莓派5代正式发布后&#xff0c;硬件和性能的全面升级让众多开发者们都想入手感受一波&#xff0c;外观上Raspberry Pi 5 与前代产品非常相似&#xff0c;不过&#xff0c;在保留信用卡大小的整体尺寸的同时&#xff0c;也更新了一些设计元素&#xff0c;以适应新芯片组的功能…

python实现调和反距离空间插值法AIDW

1 简介 AIDW 主要是针对 IDW 的缺点进行了改进&#xff0c;考虑了样本点与预测点的位置&#xff0c;即方向和距离&#xff0c;具体见下图&#xff1a; 2 改进 IDW 公式&#xff1a; 从IDW算法可看出&#xff0c;插值点的估算值仅与插值样本距插值点的远近相关&#xff0c;并未…

贝叶斯AB测试

AB测试是用来评估变更效果的有效方法&#xff0c;但很多时候会运行大量AB测试&#xff0c;如果能够在测试中复用之前测试的结果&#xff0c;将有效提升AB测试的效率和有效性。原文: Bayesian AB Testing[1] 随机实验&#xff0c;又称AB测试&#xff0c;是行业中评估因果效应的既…

【Mysql】[Err] 1293 - Incorrect table definition;

基本情况 SQL文件描述 /* Navicat MySQL Data TransferSource Server : cm4生产-200 Source Server Version : 50725 Source Host : 192.168.1.200:3306 Source Database : db_wmsTarget Server Type : MYSQL Target Server Version : 50725 File…

vxe编辑保存表格

业务需求&#xff1a; 1、需要点击编辑时&#xff0c;全部表格显示编辑框&#xff0c;点击保存&#xff0c;全部保存。 2、因为位置问题&#xff0c;产品经理把24小时分成了两行&#xff0c;开发就得分两个表格。列标题是写死的&#xff0c;文字偏移也是写死的&#xff0c;其他…

服务器主机安全的重要性及防护策略

在数字化时代&#xff0c;服务器主机安全是任何组织都必须高度重视的问题。无论是大型企业还是小型企业&#xff0c;无论是政府机构还是个人用户&#xff0c;都需要确保其服务器主机的安全&#xff0c;以防止数据泄露、网络攻击和系统瘫痪等严重后果。 一、服务器主机安全的重…

__int128类型movaps指令crash

结论 在使用__int128时&#xff0c;如果__int128类型的内存起始地址不是按16字节对齐的话&#xff0c;有些汇编指令会抛出SIGSEGV使程序crash。 malloc在64位系统中申请的内存地址&#xff0c;是按16字节对齐的&#xff0c;但一般使用时经常会申请一块内存自己切割使用&#…

static和extern

1.extern extern 是⽤来声明外部符号的&#xff0c;如果⼀个全局的符号在A⽂件中定义的&#xff0c;在B⽂件中想使⽤&#xff0c;就可以使⽤ extern 进⾏声明&#xff0c;然后使⽤。 即在一个源文件中想要使用另一个源文件&#xff0c;即可通过这个extern来声明使用。 2.st…