位圖算法是一種使用二進制位來表示一個數是否存在的算法。
一個字節是八位二進制,可以表示兩種狀態,1和0。1表示存在,0表示不存在。
四個字節是32位二進制,可以表示32種狀態。
八個字節是64位二進制,可以表示64種狀態。
比如這道題:
給40億個不重複的無符號整數,沒排過序。給一個無符號整數,如何快速判斷一個數是否在這40億個數中。【騰訊】
這是一道騰訊的編程題,看起來也是難難的。如果你想要把這40億個數存起來,那得需要多少內存?1024*1024*1024*40=4G多的內存。但是如果用位圖的思想來做的話,在這裏它也只是要求判斷一個數在不在這些數中一個字節可以表示8位,4/8=0.5G的內存就可以表示這40個億整數。
#pragma once #include<iostream> #include<vector> using namespace std; class BitMap { public: size_t Resize(const size_t size); void Set(size_t x); void Reset(size_t x); bool Test(size_t x); protected: vector<size_t> _map; size_t _size; };
#define _CRT_SECURE_NO_WARNINGS 1 #include"Bit_Map.h" #include"commond1.h" size_t BitMap::Resize(const size_t size) { size_t newsize = _GetNextPrime(size); _map.resize(newsize); return newsize; } void BitMap::Set(size_t x) { size_t index = x >> 6;//x/32。在順序表的哪個下標處 while (_map.size() <=index) Resize(_map.size()); size_t tmp = 1 << (32 - (x % 32));//找到要修改的位 if (_map[index] & tmp) { return; } _map[index] = _map[index] | tmp; _size++; } void BitMap::Reset(size_t x) { size_t index = x >> 6;//x/32 size_t tmp = 1 << (32 - (x % 32)); if (_map[index] | tmp) { _map[index] = _map[index] & (~tmp); _size--; } } bool BitMap::Test(size_t x) { size_t index = x >> 6; if (_map[index] & (1 << (32 - (x % 32)))) return true; else return false; }
commond1.h #define _CRT_SECURE_NO_WARNINGS 1 #include<assert.h> //公有的全局函數要放在一個頭文件中,不能放在.cpp中,會有重定義鏈接錯誤 size_t _GetNextPrime(size_t size) { const int _PrimeSize = 28; static const unsigned long _PrimeList[_PrimeSize] = { 53ul, 97ul, 193ul, 389ul, 769ul, 1543ul, 3079ul, 6151ul, 12289ul, 24593ul, 49157ul, 98317ul, 196613ul, 393241ul, 786433ul, 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul, 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul, 1610612741ul, 3221225473ul, 4294967291ul }; for (int i = 0; i < _PrimeSize; ++i) { if (_PrimeList[i] > size) return _PrimeList[i]; } return 4294967291ul; }
我們要表示這40個億的數,我們就開能表示40個億數的空間。將要找的數通過x除以32(4個字節)來找到它是在第幾個size_t內,然後加上它的餘數x%32就可以找到它的最終位置。將那個位置置爲1就表示這個數存在。