bitmap算法思想

10 篇文章 0 订阅

Bit-map的基本思想就是用一个bit位来标记某个元素对应的Value,而Key即是该元素。由于采用了Bit为单位来存储数据,因此在存储空间方面可以大大节省。
假设这样一个需求:在20亿个不重复的随机整数进行排序,并假设32位操作系统,4G内存
先看占用内存
在Java中,int占4字节,1字节=8位(1 byte = 8 bit)
如果每个数字用int存储,那就是20亿个int,因而占用的空间约为 (2000000000*4/1024/1024/1024)≈7.45G
如果按位存储就不一样了,20亿个数就是20亿位,占用空间约为 (2000000000/8/1024/1024/1024)≈0.233G
高下立判,无需多言
至于它的排序原理, 当我们把这些数用bit位来标记。
然后遍历一遍 , 取出标记为1的key, 就得到了一个有序序列。

而且, 可以看出, 如果是一大堆重复的随机整数, 这样操作, 还会起到一上去重的巧妙操作。
还是, 就是可以快速查找某一个数, 看它是否存在。比如:int数组中的一个元素是4字节占32位,那么除以32就知道元素的下标,对32求余数(%32)就知道它在哪一位,如果该位是1,则表示存在。

STL标准库中的bitset的底层实现原理也是内似:
bitset,中文叫位图,类似于每一个元素都是0或者1的数组,但位图的空间利用率比数组高很多。在Linux系统中,位图广泛应用于进程id的分配和文件描述符(file describer)的分配。并且,位图可以用于排序。位图的基本原理是用一个bit位代表一个整数,如果位图中的第N为1,那么就表示整数N存在。在c++的STL中实现了位图,包含在头文件中。bitset与vector很相似,都是位的集合,并且提供常数时间的特定位访问。他们之间的差别来自于主要体现在两个方面。首先,bitset的大小是不可变的,它的大小由模板参数N确定,N是整数常量。而vector的大小是可变的;其次,bitset并不是一个序列式容器,更准确地说,bitset并不是标准的STL容器。bitset并没有iterator,也没有begin()和end()。这样设计的理由是bitset中的元素就是bit位,不能容纳任何其他元素,并且bitset中bit位有特定的操作都需要实现,例如与、或、非以及异或。因此,不能够也不需要把bitset设计成STL标准容器

END

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现分页式存储管理的基本思路是将物理内存划分为固定大小的页框,每个进程拥有一定数量的页面,每个页面存放进程中的一段程序或数据。当进程需要访问某个页面时,操作系统会将该页面所在的页框调入物理内存中,并将原先的页面调出到磁盘中,以实现内存空间的管理。 为了管理内存中的页框,通常使用位示图来表示每个页框的使用情况。位示图是一个二进制数组,每个元素表示一个页框是否被使用,为1表示已经被使用,为0表示空闲。 FIFO算法思想是按照页面进入内存的先后顺序进行置换。当内存中的页面已满时,选择最早进入内存的页面进行置换。为了实现FIFO算法,可以使用一个队列来记录页面进入内存的顺序。每次页面被访问时,将其加入队列尾部,当内存已满时,选择队列头部的页面进行置换。 LRU算法思想是选择最近最少使用的页面进行置换。为了实现LRU算法,可以使用一个链表来记录页面的使用情况。每次页面被访问时,将其从链表中删除并插入到链表尾部。当内存已满时,选择链表头部的页面进行置换。 下面是一个java程序示例,实现了分页式存储管理,并体现了FIFO和LRU算法思想: ```java public class PageReplacement { private int[] memory; // 物理内存 private int[] pageTable; // 页面表 private byte[] bitMap; // 位示图 private Queue<Integer> fifoQueue; // FIFO队列 private LinkedList<Integer> lruList; // LRU链表 private int pageSize; // 页面大小 private int pageFrameNum; // 页面帧数 private int pageTableSize; // 页面表大小 private int missCount; // 缺页次数 public PageReplacement(int pageSize, int pageFrameNum) { this.pageSize = pageSize; this.pageFrameNum = pageFrameNum; this.pageTableSize = 1 << (32 - Integer.numberOfLeadingZeros(pageSize * pageFrameNum - 1)); this.memory = new int[pageSize * pageFrameNum]; this.pageTable = new int[pageTableSize]; this.bitMap = new byte[pageFrameNum / 8]; this.fifoQueue = new LinkedList<>(); this.lruList = new LinkedList<>(); this.missCount = 0; } public void accessPage(int pageNum) { int pageFrame = pageTable[pageNum]; if (pageFrame == 0) { // 页面不在内存中 missCount++; pageFrame = findFreePageFrame(); if (pageFrame == -1) { // 内存已满,需要进行页面置换 pageFrame = replacePageFrame(); } loadPage(pageNum, pageFrame); } updatePageTable(pageNum, pageFrame); } private int findFreePageFrame() { for (int i = 0; i < pageFrameNum; i++) { if ((bitMap[i / 8] & (1 << (i % 8))) == 0) { return i; } } return -1; } private int replacePageFrame() { int pageFrame; if (!fifoQueue.isEmpty()) { // 使用FIFO算法进行页面置换 pageFrame = fifoQueue.remove(); } else { // 使用LRU算法进行页面置换 pageFrame = lruList.removeFirst(); } unloadPage(pageFrame); return pageFrame; } private void loadPage(int pageNum, int pageFrame) { pageTable[pageNum] = pageFrame; bitMap[pageFrame / 8] |= (1 << (pageFrame % 8)); fifoQueue.add(pageFrame); lruList.add(pageFrame); System.arraycopy(/* 从磁盘中读取页面内容 */); } private void unloadPage(int pageFrame) { int pageNum = findPageNum(pageFrame); pageTable[pageNum] = 0; bitMap[pageFrame / 8] &= ~(1 << (pageFrame % 8)); fifoQueue.remove(pageFrame); lruList.remove(pageFrame); System.arraycopy(/* 将页面内容写回磁盘 */); } private void updatePageTable(int pageNum, int pageFrame) { pageTable[pageNum] = pageFrame; lruList.remove(pageFrame); lruList.add(pageFrame); } private int findPageNum(int pageFrame) { for (int i = 0; i < pageTableSize; i++) { if (pageTable[i] == pageFrame) { return i; } } return -1; } public int getMissCount() { return missCount; } } ``` 在上述程序中,accessPage方法用于访问某个页面,如果该页面不在内存中,则进行缺页处理。findFreePageFrame方法用于查找空闲的页面帧,replacePageFrame方法用于选择页面进行置换,loadPage方法用于将某个页面调入内存,unloadPage方法用于将某个页面调出内存,updatePageTable方法用于更新页面表和LRU链表,findPageNum方法用于查找某个页面所在的页面表项。程序中实现了FIFO和LRU算法思想,当内存已满时,使用FIFO队列或LRU链表选择页面进行置换。程序中的具体实现可能需要根据具体情况进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值