Java數據結構第二十六期:解密位圖,海量數據處理的 “空間魔法”

專欄:Java數據結構秘籍

個人主頁:手握風云

目錄

一、位圖

1.1. 概念

1.2. 面試題

1.3. 位圖的實現

1.4. 位圖的應用


一、位圖

1.1. 概念

????????在數據結構中,位圖(也稱為位數組、位向量或位集)是一種緊湊的方式來表示一組布爾值(真/假、1/0)。它本質上是一個數組,其中每個元素代表一個位,該位的位置通常對應于一個標識符或索引。適用于海量數據,整數,數據無重復的場景。

1.2. 面試題

????????給40億個不重復的無符號整數,沒排過序。給一個無符號整數,如何快速判斷一個數是否在這40億個數中。

????????解法:

  1. 遍歷,時間復雜度O(n)
  2. 排序+二分查找,時間復雜度O(nlogn)+O(logn)。10億個byte大約是1G,10億個整數大約是4G,40億個整數大約就是16G,很明顯內存不夠

? ? ? ? 這時我們就可以使用位圖來解決上述問題。我們知道一個整數是32個比特位,那么每一個比特位就可以存儲不同的數字,0代表沒出現過,1代表出現過。那我們就可以根據一組數據的某種關系映射到里面。

? ? ? ? 如下圖所示,我們就可以以8個比特位為一組,每個數據進行/8的操作,然后將其儲存在比特位的下標里面。

? ? ? ? 這樣的話40億個整數只需大約476MB就可以解決。

1.3. 位圖的實現

? ? ? ? 在Java的集合框架中,也有BitSet類。

import java.util.BitSet;public class Test {public static void main(String[] args) {BitSet bitSet = new BitSet();// 設置位bitSet.set(0);bitSet.set(2);bitSet.set(4);// 獲取BitSet的大小System.out.println(bitSet.size());// 查詢位的狀態System.out.println(bitSet.get(0));System.out.println(bitSet.get(1));System.out.println(bitSet.get(2));// 清除位bitSet.clear(2);System.out.println(bitSet.get(2));}
}

public class MyBitSet {public byte[] elem;public int usedSize;public MyBitSet(byte[] elem) {this.elem = new byte[1];}/*** 有可能多給一個字節,但是無所謂* @param n 多少位*/public MyBitSet(int n) {this.elem = new byte[n / 8 + 1];}/*** 設置某一位為1,證明數據出現過* @param val 查找的數據*/public void set(int val) {}/**** @param val 輸入的數據* @return 判斷當前位是不是1*/public boolean get(int val) {return false;}/*** 將對應位置置為0* @param val 輸入的位數*/public void reSet(int val) {}// 獲取當前已經使用的位數public int getUsedSize() {return usedSize;}
}

? ? ? ? 我們先來看設置位方法。如果輸入的數據小于0,需要拋出下標越界的異常。對于輸入的數據,我們既要計算出需要對應在字節數組中的哪個字節,還要計算出在字節中的哪個bit位。之后我們還需要進行將對應的比特位下標置為1,并且不能改變其它位置的值。比如,我們要設置2位置為1,先將1左移2位,再進行按位或操作。

public void set(int val) {if (val < 0) {throw new IndexOutOfBoundsException();}int arrayIndex = val / 8;int bitIndex = val % 8;elem[arrayIndex] |= (1 << bitIndex);usedSize++;
}

? ? ? ? 對于get()方法,我們先左移對應的比特位,然后進行按位與的操作,如果結果不是0,說明該位置為1。

public boolean get(int val) {if (val < 0) {throw new IndexOutOfBoundsException();}int arrayIndex = val / 8;int bitIndex = val % 8;return (elem[arrayIndex] & (1 << bitIndex)) != 0;
}

? ? ? ? 對于reSet()方法,我們先假設原來這個地方為0,一進行按位與操作,就會將其變成1,所以我們先左移然后按位取反再進行安=按位與。

public void reSet(int val) {if (val < 0) {throw new IndexOutOfBoundsException();}int arrayIndex = val / 8;int bitIndex = val % 8;elem[arrayIndex] &= ~(1 << bitIndex);usedSize--;
}
  • 測試結果
public static void main(String[] args) {int[] array = {1, 3, 7, 4, 12, 16, 19, 13, 22, 18};MyBitSet bitSet = new MyBitSet(22);for (int i = 0; i < array.length; i++) {bitSet.set(array[i]);}System.out.println(bitSet.get(7));System.out.println(bitSet.get(5));System.out.println(bitSet.get(50));
}

? ? ? ? 出現異常正是因為沒有進行擴容,50 / 8結果是6,就會產生越界異常。

? ? ? ? 完整代碼實現:

import java.util.Arrays;public class MyBitSet {public byte[] elem;public int usedSize;public MyBitSet(byte[] elem) {this.elem = new byte[1];}/*** 有可能多給一個字節,但是無所謂* @param n 多少位*/public MyBitSet(int n) {this.elem = new byte[n / 8 + 1];}/*** 設置某一位為1,證明數據出現過* @param val 查找的數據*/public void set(int val) {if (val < 0) {throw new IndexOutOfBoundsException();}int arrayIndex = val / 8;// 擴容if (arrayIndex > elem.length - 1) {elem = Arrays.copyOf(elem, arrayIndex + 1);}int bitIndex = val % 8;elem[arrayIndex] |= (1 << bitIndex);usedSize++;}/**** @param val 輸入的數據* @return 判斷當前位是不是1*/public boolean get(int val) {if (val < 0) {throw new IndexOutOfBoundsException();}int arrayIndex = val / 8;int bitIndex = val % 8;if (arrayIndex >= elem.length) {return false;}return (elem[arrayIndex] & (1 << bitIndex)) != 0;}/*** 將對應位置置為0* @param val 輸入的位數*/public void reSet(int val) {if (val < 0) {throw new IndexOutOfBoundsException();}int arrayIndex = val / 8;int bitIndex = val % 8;elem[arrayIndex] &= ~(1 << bitIndex);usedSize--;}// 獲取當前已經使用的位數public int getUsedSize() {return usedSize;}public static void main(String[] args) {int[] array = {1, 3, 7, 4, 12, 16, 19, 13, 22, 18};MyBitSet bitSet = new MyBitSet(22);for (int i = 0; i < array.length; i++) {bitSet.set(array[i]);}System.out.println(bitSet.get(7));System.out.println(bitSet.get(5));System.out.println(bitSet.get(50));}
}

1.4. 位圖的應用

  1. 高效存儲與查詢大量布爾狀態;
  2. 集合運算(交集、并集、差集);
  3. 位圖排序(適合范圍已知的整數排序)
  4. 去重與計數;
  5. 布隆過濾器(Bloom Filter)底層實現

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/93977.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/93977.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/93977.shtml

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

相關文章

芯科科技即將重磅亮相IOTE 2025深圳物聯網展,以全面的無線技術及生態覆蓋賦能萬物智聯

作為低功耗無線連接領域的創新性領導廠商&#xff0c;Silicon Labs&#xff08;亦稱“芯科科技”&#xff09;將于8月27至29日攜其最前沿的人工智能&#xff08;AI&#xff09;和物聯網&#xff08;IoT&#xff09;解決方案在深圳舉辦的IOTE 2025國際物聯網展中盛大展出。這場亞…

Linux上安裝多個JDK版本,需要配置環境變量嗎

簡短回答&#xff1a;不需要同時配置多個 JDK 的 JAVA_HOME 和 PATH&#xff0c;但你可以安裝多個版本&#xff0c;并通過靈活的方式在它們之間切換。 文章目錄? 正確做法&#xff1a;安裝多個 JDK&#xff0c;但只讓一個生效&#xff08;通過環境變量或 alternatives&#xf…

MySQL有哪些高可用方案

大家好&#xff0c;我是鋒哥。今天分享關于【MySQL有哪些高可用方案】面試題。希望對大家有幫助&#xff1b; MySQL有哪些高可用方案? 超硬核AI學習資料&#xff0c;現在永久免費了&#xff01; MySQL 高可用方案是指確保 MySQL 數據庫在面對硬件故障、網絡故障、負載過重等…

【Windows】Windows平臺基于加速地址安裝vcpkg并集成到Visual Studio 2017

基礎運行環境 啟動&#xff1a; 適用于 VS 2017 的 x64 本機工具命令提示 ninja 下載壓縮包 https://gh-proxy.com/https:/github.com/ninja-build/ninja/releases/download/v1.13.1/ninja-win.zip 直接解壓到c:/Windows (無需配置環境變量) CMake 下載安裝包 https://gh-proxy…

LLMs之MCP:Chrome MCP的簡介、安裝和使用方法、案例應用之詳細攻略

LLMs之MCP&#xff1a;Chrome MCP的簡介、安裝和使用方法、案例應用之詳細攻略 目錄 Chrome MCP的簡介 1、特點 2、與類似項目的比較 Chrome MCP的安裝和使用方法 1、安裝 2、使用方法 加載 Chrome 擴展 與 MCP 協議客戶端一起使用 使用 STDIO 連接&#xff08;替代方…

【Java EE】多線程-初階 synchronized 關鍵字 - 監視器鎖 monitor lock

synchronized 關鍵字 - 監視器鎖 monitor lock5. synchronized 關鍵字 - 監視器鎖 monitor lock5.1 synchronized 的特性5.2 synchronized 使??例5.3 Java 標準庫中的線程安全類本節?標? 掌握 synchronized關鍵字5. synchronized 關鍵字 - 監視器鎖 monitor lock &#xf…

Java多線程:從基礎到實戰

引言多線程是Java并發編程的核心技術之一&#xff0c;廣泛應用于服務器開發、數據處理、實時系統等領域。通過多線程&#xff0c;程序可以充分利用CPU資源&#xff0c;提高執行效率&#xff0c;同時處理多個任務。本文將從多線程的基本概念、實現方式、線程狀態、同步與通信到常…

list集合可以一邊遍歷一遍修改元素嗎?

今天看來一下Java中list集合部分的八股&#xff0c;發現了一個以前沒注意過的問題&#xff0c;記錄一下list可以一邊遍歷一邊修改元素嗎&#xff1f;答&#xff1a;在 Java 中&#xff0c;List在遍歷過程中是否可以修改元素取決于遍歷方式和具體的List實現類。①&#xff1a;對…

Infusing fine-grained visual knowledge to Vision-Language Models

Infusing fine-grained visual knowledge to Vision-Language Models Authors: Nikolaos-Antonios Ypsilantis, Kaifeng Chen, Andr Araujo, Ond?ej Chum Deep-Dive Summary: 視覺-語言模型中注入細粒度視覺知識 摘要 大規模對比預訓練產生了強大的視覺-語言模型&#xf…

RK3576賦能無人機巡檢:多路視頻+AI識別引領智能化變革

隨著工業巡檢任務的復雜度不斷提升&#xff0c;無人機逐漸取代傳統人工&#xff0c;成為電力、能源、林業、農業等行業的“高空作業主力”。然而&#xff0c;巡檢并非簡單的拍攝和回放&#xff0c;它要求無人機實時采集多路畫面、快速分析異常&#xff0c;并穩定回傳數據。這對…

ollama Modelfile 文件生成

輸入 根據如下TEMPLATE和params寫一個modelfile文件&#xff0c;TEMPLATE為&#xff1a;{{- $lastUserIdx : -1 -}} {{- range $idx, $msg : .Messages -}} {{- if eq $msg.Role “user” }}{{ $lastUserIdx $idx }}{{ end -}} {{- end }} {{- if or .System .Tools }}<|i…

關聯規則挖掘2:FP-growth算法(Frequent Pattern Growth,頻繁模式增長)

目錄 一、核心思想&#xff1a;一個形象的比喻 二、核心思想的具體拆解 步驟一&#xff1a;構建FP-tree&#xff08;頻繁模式樹&#xff09; 步驟二&#xff1a;從FP-tree中挖掘頻繁項集 為什么這很高效&#xff1f; 三、總結 核心思想與優勢 適用場景與缺點 四、例題…

在IDEA中DEBUG調試時查看MyBatis-Plus動態生成的SQL語句

在IDEA中DEBUG調試時查看MyBatis-Plus動態生成的SQL語句前言&#xff1a;動態SQL調試的痛與解決方案一、準備工作&#xff1a;調試前的檢查清單二、基礎方法&#xff1a;SqlSessionTemplate斷點調試步驟1&#xff1a;定位SqlSessionTemplate類步驟2&#xff1a;在invoke方法上設…

Linux 文本處理三劍客:awk、grep、sed 完全指南

Linux 文本處理三劍客&#xff1a;awk、grep、sed 完全指南 1. 概述 Linux 系統提供了三個強大的文本處理工具&#xff1a;awk、grep 和 sed&#xff0c;它們各有所長&#xff0c;結合使用可以高效地處理文本數據。 awk&#xff1a;擅長文本分析和格式化輸出&#xff0c;是一…

pyecharts可視化圖表組合組件_Grid:打造專業數據儀表盤

pyecharts可視化圖表組合組件_Grid&#xff1a;打造專業數據儀表盤 目錄pyecharts可視化圖表組合組件_Grid&#xff1a;打造專業數據儀表盤引言圖表1&#xff1a;Grid-Overlap-多X/Y軸示例代碼解析1. 圖表創建2. 多軸配置3. 圖表重疊4. Grid布局效果與應用圖表2&#xff1a;Gri…

【電氣工程學習】

三極管中&#xff1a;集電極C,基極B&#xff0c;發射極E接線&#xff1a;棕正藍負黑信號NPN開關輸出的是我們的0V,也叫低電平PNP開關輸出的是24V,也就是高電平&#xff08;NPN開關導通時&#xff0c;相當于把輸出端“拉”到0V&#xff08;低電平&#xff09;&#xff0c;稱為“…

【嵌入式】CAN通信

CAN 總線最初由博世于1980年代為汽車行業開發&#xff0c;能夠簡化復雜的布線網絡&#xff0c;還確保可靠和安全的數據傳輸。 1.CAN技術解釋 CAN網絡中的每個節點&#xff0c;都是平等的&#xff0c;沒有主次之分&#xff0c;這一點和SPI和I2C不同。每個節點都可以在需要的時…

Apache ShenYu網關與Nacos的關聯及如何配合使用

Apache ShenYu 網關與 Nacos 之間的關系可以概括為 “協作互補”:Nacos 作為 服務注冊與配置中心,為 ShenYu 提供動態的服務發現和配置管理能力,而 ShenYu 作為 流量網關,依賴 Nacos 實現路由信息的動態更新和實時生效。以下是詳細解析: 1. 核心關系圖解 拉取服務列表/路…

【CPP】一個CPP的Library(libXXXcore)和測試程序XXX_main的Demo

一個CPP的Library和測試程序Demo 1. 思路描述 目錄結構 總控CMakeList.txt文件 2. Library代碼實現 2.1 XXXLib.hpp文件(對外的接口定義文件)和XXXLib.cpp文件 2.1.1 XXXLib.hpp文件 2.1.2 XXXLib.cpp文件 2.2 CXXXLibApi.hpp文件和CXXXLibApi.cpp文件(內部的API基類) 2.2.1 CX…

【YashanDB認證】學習YashanDB的探索之路:從入門到實踐

在國產數據庫蓬勃發展的浪潮中&#xff0c;選擇了YashanDB作為技術學習的切入點。這不僅讓我深入了解了數據庫的核心技術&#xff0c;也讓我深刻體會到國產數據庫在性能、可靠性和生態適配上的創新價值。以下是我在學習YashanDB過程中的經驗與感悟。 一、YashanDB基礎介紹 Ya…