基于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.pswp.cn/news/160112.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/160112.shtml
英文地址,請注明出處:http://en.pswp.cn/news/160112.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python獲取透明圖

import cv2 import os import numpy as nproot "./test" for file in os.listdir(root):# 讀取圖片image cv2.imread(os.path.join(root, file), cv2.IMREAD_UNCHANGED)new np.zeros((image.shape[0], image.shape[1], image.shape[2]), np.uint8)# 檢查圖片是否為…

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)}…

uiautomator2快速入門app自動化測試教程

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 前言一、環境準備1.安裝軟件2.安裝庫 二、adb 連接手機1. 準備工作2. 第一種連接方式&#xff1a;USB連接3. 第二種連接方式&#xff1a;WLAN連接4. 第三種連接方式…

②⑩ 【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;每一個角色又可以被分配…

Mysql 中如何導出數據?

文章目錄 前言MySQL 導出數據使用 SELECT ... INTO OUTFILE 語句導出數據SELECT ... INTO OUTFILE 語句有以下屬性:導出表作為原始數據導出SQL格式的數據將數據表及數據庫拷貝至其他主機 后言 前言 hello world歡迎來到前端的新世界 &#x1f61c;當前文章系列專欄&#xff1a;…

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;是行業中評估因果效應的既…

自定義類型:結構體

1.結構體類型的聲明 1.1結構體的概念 結構是?些值的集合&#xff0c;這些值稱為成員變量。結構的每個成員可以是不同類型的變量。 1.2 結構的聲明 struct tag {member-list; }variable-list; 例如描述?個學?&#xff1a; struct Stu {char name[20];//名字int age;//年…

【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…