【C++】-- STL之位图(一)

简介: 【C++】-- STL之位图

一、位图概念

1.使用场景

假如给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中?

计算一下40亿个无符号整数会占多大内存呢?

可以采用如下方法:

(1)放进set或unordered_set中,再用find进行查找

(2)排序,再使用二分法查找,排序的时间复杂度是O(N*logN),二分查找的时间复杂度是O(logN)

但是,16GB的大小,这会很消耗内存,我们不可能把16GB的数据全部加载到内存中。还有另外一种比较节省内存的方式——位图。

2.位图

       位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景。通常是用来判断某个数据存不存在的。

       数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使用一个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,为0代表不存在。比如:

一个bit位代表一个整数在不在,因此现在一个整数大小(4个字节32位)可以表示32个整数在不在,那么对于第一小节的40亿个整数16GB就可以用500MB进行表示了,500MB是可以加载到内存中的,这也提高了效率。

二、位图介绍

1.构造

有3种构造方式:分为默认0、整数、字符串3种类型

1. bitset();//默认
2. bitset (unsigned long val);//参数传整数,10进制或16进制都可以
3. template<class charT, class traits, class Alloc>  explicit bitset (const basic_string<charT,traits,Alloc>& str,    typename basic_string<charT,traits,Alloc>::size_type pos = 0,    typename basic_string<charT,traits,Alloc>::size_type n =      basic_string<charT,traits,Alloc>::npos);//字符串

用3种构造方式构造3个位图对象:

1. #include<iostream>
2. #include<string>
3. #include<bitset>
4. using namespace std;
5. 
6. int main()
7. {
8.  bitset<16> bs1;
9.  bitset<16> bs2(125);
10.   bitset<32> bs3("101000101010");
11. 
12.   cout << "bs1:" << bs1 << endl;
13.   cout << "bs2:" << bs2 << endl;
14.   cout << "bs3:" << bs3 << endl;
15. 
16.   return 0;
17. }

打印结果如下:

2.operator[ ]

返回下标位置的值:

bool operator[] (size_t pos) const;reference operator[] (size_t pos);

修改bs1第3位和第6位的值:

1.  bs1[3] = 1;
2.  bs1[6] = 1;
3.  cout << "bs1:" << bs1 << endl;

3.count( )

返回位图对象中1的个数:

size_t count() const;

返回bs3中1的个数:

cout << bs3.count() << endl;

4.size( )

返回该位图对象的位数:

size_t size() const;

返回bs1、bs2、bs3的位数:

1.  cout << "bs1:" << bs1.size() << endl;
2.  cout << "bs2:" << bs2.size() << endl;
3.  cout << "bs3:" << bs3.size() << endl;

5.test( )

返回该位在不在:

bool test (size_t pos) const;

返回bs2的每一位在不在:

1.  cout << boolalpha;//把布尔值打印成true或false
2.  for (size_t i = 0; i < bs2.size(); i++)
3.  {
4.    cout << bs2.test(i) << endl;
5.  }

6.any( )

是否有至少1位为1:

bool any() const;

判断bs3是否至少有1位为1:

1.  if (bs3.any())
2.  {
3.    cout << "bs3至少有1位为1" << endl;
4.  }
5.  else
6.  {
7.    cout << "bs3没有1位为1" << endl;
8.  }

7.none( )

是否全为0:

bool none() const;

判断bs3是否全为0:

1.  if (bs3.none())
2.  {
3.    cout << "bs3全为0" << endl;
4.  }
5.  else
6.  {
7.    cout << "bs3不全为0" << endl;
8.  }

8.all( )

是否所有位都为1:

bool all() const noexcept;

判断bs3是否全为1:

1.  if (bs3.all())
2.  {
3.    cout << "bs3全为1" << endl;
4.  }
5.  else
6.  {
7.    cout << "bs3不全为1" << endl;
8.  }

9.set( )

标记分以下两种:

1. bitset& set();//每个bit位都标记为1
2. bitset& set (size_t pos, bool val = true);//把第pos位标记为val

将bs4全标记为1 ,再将第6位标记为0,再将第6为标记为1:

1.  bitset<16> bs4;
2.  bs4.set();
3.  cout << bs4 << endl;
4.  bs4.set(6,0);
5.  cout << bs4 << endl;
6.  bs4.set(6, 1);
7.  cout << bs4 << endl;

10.reset( )

删除分为以下两种:

1. bitset& reset();//删除所有位,每一位都置为0
2. bitset& reset (size_t pos);//删除指定pos位,置为0

先删除bs5的第2位的标记 ,再删除所有位的标记:

1.  bitset<16> bs5(0xFFFF);
2.  cout << bs5 << endl;
3.  bs5.reset(2);
4.  cout << bs5 << endl;
5.  bs5.reset();
6.  cout << bs5 << endl;

11.flip( )

取反分为以下两种:

1. bitset& flip();//全部取反
2. bitset& flip (size_t pos);//把第pos位取反

先对bs5的第2位取反,再对bs5全部取反:

1.  bitset<16> bs5(0xFFFF);
2.  cout << bs5 << endl;
3.  bs5.flip(2);
4.  cout << bs5 << endl;
5.  bs5.flip();
6.  cout << bs5 << endl;


相关文章
|
3月前
|
存储 算法 C++
C++ STL 初探:打开标准模板库的大门
C++ STL 初探:打开标准模板库的大门
126 10
|
7天前
|
编译器 C语言 C++
【c++丨STL】list模拟实现(附源码)
本文介绍了如何模拟实现C++中的`list`容器。`list`底层采用双向带头循环链表结构,相较于`vector`和`string`更为复杂。文章首先回顾了`list`的基本结构和常用接口,然后详细讲解了节点、迭代器及容器的实现过程。 最终,通过这些步骤,我们成功模拟实现了`list`容器的功能。文章最后提供了完整的代码实现,并简要总结了实现过程中的关键点。 如果你对双向链表或`list`的底层实现感兴趣,建议先掌握相关基础知识后再阅读本文,以便更好地理解内容。
15 1
|
19天前
|
算法 C语言 C++
【c++丨STL】list的使用
本文介绍了STL容器`list`的使用方法及其主要功能。`list`是一种双向链表结构,适用于频繁的插入和删除操作。文章详细讲解了`list`的构造函数、析构函数、赋值重载、迭代器、容量接口、元素访问接口、增删查改操作以及一些特有的操作接口如`splice`、`remove_if`、`unique`、`merge`、`sort`和`reverse`。通过示例代码,读者可以更好地理解如何使用这些接口。最后,作者总结了`list`的特点和适用场景,并预告了后续关于`list`模拟实现的文章。
34 7
|
2月前
|
存储 编译器 C语言
【c++丨STL】vector的使用
本文介绍了C++ STL中的`vector`容器,包括其基本概念、主要接口及其使用方法。`vector`是一种动态数组,能够根据需要自动调整大小,提供了丰富的操作接口,如增删查改等。文章详细解释了`vector`的构造函数、赋值运算符、容量接口、迭代器接口、元素访问接口以及一些常用的增删操作函数。最后,还展示了如何使用`vector`创建字符串数组,体现了`vector`在实际编程中的灵活性和实用性。
66 4
|
2月前
|
C语言 C++ 容器
【c++丨STL】string模拟实现(附源码)
本文详细介绍了如何模拟实现C++ STL中的`string`类,包括其构造函数、拷贝构造、赋值重载、析构函数等基本功能,以及字符串的插入、删除、查找、比较等操作。文章还展示了如何实现输入输出流操作符,使自定义的`string`类能够方便地与`cin`和`cout`配合使用。通过这些实现,读者不仅能加深对`string`类的理解,还能提升对C++编程技巧的掌握。
81 5
|
2月前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
63 2
|
2月前
|
存储 算法 Linux
【c++】STL简介
本文介绍了C++标准模板库(STL)的基本概念、组成部分及学习方法,强调了STL在提高编程效率和代码复用性方面的重要性。文章详细解析了STL的六大组件:容器、算法、迭代器、仿函数、配接器和空间配置器,并提出了学习STL的三个层次,旨在帮助读者深入理解和掌握STL。
61 0
|
23天前
|
存储 编译器 C语言
【c++丨STL】vector模拟实现
本文深入探讨了 `vector` 的底层实现原理,并尝试模拟实现其结构及常用接口。首先介绍了 `vector` 的底层是动态顺序表,使用三个迭代器(指针)来维护数组,分别为 `start`、`finish` 和 `end_of_storage`。接着详细讲解了如何实现 `vector` 的各种构造函数、析构函数、容量接口、迭代器接口、插入和删除操作等。最后提供了完整的模拟实现代码,帮助读者更好地理解和掌握 `vector` 的实现细节。
31 0
|
3月前
|
存储 搜索推荐 C++
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器2
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器
69 2
|
3月前
|
存储 程序员 C++
C++常用基础知识—STL库(2)
C++常用基础知识—STL库(2)
89 5