容器适配器:stack栈 、queue队列、priority queue优先级队列、bitset位图 详解

目录

前言

[一、stack 栈](#一、stack 栈)

1.定义及初始化

2.常用操作

[(1)empty 成员函数](#(1)empty 成员函数)

[(2)pop 成员函数](#(2)pop 成员函数)

[(3)push 成员函数](#(3)push 成员函数)

[(4)size 成员函数](#(4)size 成员函数)

[(5)top 成员函数](#(5)top 成员函数)

[二、queue 队列](#二、queue 队列)

[1. 定义及初始化](#1. 定义及初始化)

2.常用操作

[(1)back 成员函数](#(1)back 成员函数)

[(2)empty 成员函数](#(2)empty 成员函数)

[(3)front 成员函数](#(3)front 成员函数)

[(4)pop 成员函数](#(4)pop 成员函数)

[(5)push 成员函数](#(5)push 成员函数)

[(6)size 成员函数](#(6)size 成员函数)

[三、priority queue 优先级队列](#三、priority queue 优先级队列)

1.定义及初始化

2.常用操作

[(1)empty 成员函数](#(1)empty 成员函数)

[(2)pop 成员函数](#(2)pop 成员函数)

[(3)push 成员函数](#(3)push 成员函数)

[(4)size 成员函数](#(4)size 成员函数)

[(5)top 成员函数](#(5)top 成员函数)

[3.深入 priority queue](#3.深入 priority queue)

[四、 bitset 位图](#四、 bitset 位图)

1.初始化方法

2.常用的符号和方法

(1)位操作符

(2)成员函数


前言

本文介绍了C++标准库中的四种容器适配器:1.stack栈(后进先出LIFO),包含初始化方法和常用操作(push/pop/top等);2.queue队列(先进先出FIFO),说明其特点和基本操作(push/pop/front/back等);3.priority_queue优先级队列(自动排序),详细讲解其堆实现原理和自定义比较方法;4.bitset位图(固定大小位集合),介绍位操作方法和转换函数。


一、stack 栈

1.定义及初始化

stack 是一种后进先出(LIFO, Last-In-First-Out)的数据结构,它只允许在栈顶进行插入和删除操作。

stack 只是很单纯地把各项操作转化为内部容器对应的函数调用。你可以使用任何支持 back()、push_back()和pop_back()成员函数的标准容器支持 stack。

使用push(入栈)将数据放入stack,使用pop(出栈)将元素从容器中移除。

使用stack,必须包含头文件<stack>:

cpp 复制代码
#include <stack>
cpp 复制代码
#include <stack>

// 默认初始化(使用deque作为底层容器)
std::stack<int> s1;

// 使用自定义底层容器初始化
std::stack<int, std::vector<int>> s2;

// 使用已有的容器初始化
std::vector<int> v = {1, 2, 3};
std::stack<int, std::vector<int>> s3(v);

2.常用操作

(1)empty 成员函数

检查栈是否为空,返回布尔值。

cpp 复制代码
std::stack<int> s;
bool is_empty = s.empty(); // true
(2)pop 成员函数

移除栈顶元素,无返回值。

cpp 复制代码
std::stack<int> s;
s.push(1);
s.push(2);
s.pop(); // 移除栈顶元素2
(3)push 成员函数

向栈顶添加元素。

cpp 复制代码
std::stack<int> s;
s.push(1);
s.push(2);
(4)size 成员函数

返回栈中元素的数量。

cpp 复制代码
std::stack<int> s;
s.push(1);
s.push(2);
s.push(3);
size_t size = s.size(); // 3
(5)top 成员函数

返回栈顶元素的引用,不修改栈。

cpp 复制代码
std::stack<int> s;
s.push(1);
s.push(2);
int top_val = s.top(); // 2

二、queue 队列

1. 定义及初始化

queue 是一种先进先出 (FIFO, First-In-First-Out)的数据结构,它允许在队尾插入元素,在队首删除元素

使用queue,必须引用头文件<queue>:

cpp 复制代码
#include <queue>
cpp 复制代码
#include <queue>

// 默认初始化(使用deque作为底层容器)
std::queue<int> q1;

// 使用自定义底层容器初始化
std::queue<int, std::list<int>> q2;

// 使用已有的容器初始化
std::list<int> l = {1, 2, 3};
std::queue<int, std::list<int>> q3(l);

2.常用操作

(1)back 成员函数

返回队尾元素的引用,不修改队列。

cpp 复制代码
std::queue<int> q;
q.push(1);
q.push(2);
int back_val = q.back(); // 2
(2)empty 成员函数

检查队列是否为空,返回布尔值。

cpp 复制代码
std::queue<int> q;
bool is_empty = q.empty(); // true
(3)front 成员函数

返回队首元素的引用,不修改队列。

cpp 复制代码
std::queue<int> q;
q.push(1);
q.push(2);
int front_val = q.front(); // 1
(4)pop 成员函数

移除队首元素,无返回值。

cpp 复制代码
std::queue<int> q;
q.push(1);
q.push(2);
q.pop(); // 移除队首元素1
(5)push 成员函数

向队尾添加元素。

cpp 复制代码
std::queue<int> q;
q.push(1);
q.push(2);
(6)size 成员函数

返回队列中元素的数量。

cpp 复制代码
std::queue<int> q;
q.push(1);
q.push(2);
q.push(3);
size_t size = q.size(); // 3

三、priority queue 优先级队列

1.定义及初始化

priority queue 是一种特殊的队列,它会根据元素的优先级自动排序,这里的第一个元素并不是第一个放入的元素,而是"优先级最高"的元素。默认情况下最大元素会位于队首

其内部数据结构为:大根堆,不能使用list作为其容器。

priority queue也是定义在头文件<queue>中:

cpp 复制代码
#include<queue>
cpp 复制代码
#include <queue>

// 默认初始化(使用vector作为底层容器,默认使用less比较器)
std::priority_queue<int> pq1;

// 使用自定义比较器初始化(最小元素位于队首)
std::priority_queue<int, std::vector<int>, std::greater<int>> pq2;

// 使用已有的容器初始化
std::vector<int> v = {3, 1, 4};
std::priority_queue<int> pq3(v.begin(), v.end()); // 队首元素是4

2.常用操作

(1)empty 成员函数

检查优先级队列是否为空,返回布尔值。

cpp 复制代码
std::priority_queue<int> pq;
bool is_empty = pq.empty(); // true
(2)pop 成员函数

移除队首元素(优先级最高的元素),无返回值。

cpp 复制代码
std::priority_queue<int> pq;
pq.push(1);
pq.push(3);
pq.push(2);
pq.pop(); // 移除元素3
(3)push 成员函数

向优先级队列中添加元素,会自动调整以保持优先级顺序。

cpp 复制代码
std::priority_queue<int> pq;
pq.push(1);
pq.push(3);
pq.push(2);
(4)size 成员函数

返回优先级队列中元素的数量。

cpp 复制代码
std::priority_queue<int> pq;
pq.push(1);
pq.push(2);
pq.push(3);
size_t size = pq.size(); // 3
(5)top 成员函数

返回队首元素(优先级最高的元素)的引用,不修改队列。

cpp 复制代码
std::priority_queue<int> pq;
pq.push(1);
pq.push(3);
pq.push(2);
int top_val = pq.top(); // 3

3.深入 priority queue

priority queue 的底层实现通常是二叉堆,它具有以下特点:

  1. 时间复杂度:

    • push 操作:O(log n)
    • pop 操作:O(log n)
    • top 操作:O(1)
  2. 自定义类型的优先级:

    • 对于自定义类型,需要重载比较运算符或提供自定义比较器。
    cpp 复制代码
    struct Person {
        std::string name;
        int age;
        
        // 重载小于运算符,使年龄大的人优先级更高
        bool operator<(const Person& other) const {
            return age < other.age;
        }
    };
    
    std::priority_queue<Person> pq;
    pq.push({"Alice", 30});
    pq.push({"Bob", 25});
    pq.push({"Charlie", 35});
    Person top_person = pq.top(); // Charlie, 35
  3. 使用自定义比较器:

    cpp 复制代码
    struct CompareByAge {
        bool operator()(const Person& a, const Person& b) {
            // 返回true表示a应该在b之后(即b的优先级更高)
            return a.age > b.age; // 年龄小的人优先级更高
        }
    };
    
    std::priority_queue<Person, std::vector<Person>, CompareByAge> pq;

四、 bitset 位图

1.初始化方法

bitset 是一种固定大小的位集合,它提供了位级别的操作。

位图,是一个类模板,它类似array类,具有固定的大小。当我们定义一个bitset 时,需要声明它包含多少个二进制位。例如:

cpp 复制代码
bitset<32>bitvec(1);//32位;低位为1,其他位为0
cpp 复制代码
#include <bitset>

// 默认初始化(所有位为0)
std::bitset<8> b1; // 00000000

// 使用整数初始化
std::bitset<8> b2(42); // 00101010(42的二进制表示)

// 使用字符串初始化
std::bitset<8> b3("10101010"); // 10101010

// 使用部分字符串初始化
std::bitset<8> b4("1010", 0, 4); // 00001010(只取前4位)

2.常用的符号和方法

(1)位操作符
  • &:按位与
  • |:按位或
  • ^:按位异或
  • ~:按位取反
  • <<:左移
  • >>:右移
(2)成员函数
  • set():设置所有位为1
  • set(pos):设置指定位置的位为1
  • reset():设置所有位为0
  • reset(pos):设置指定位置的位为0
  • flip():翻转所有位
  • flip(pos):翻转指定位置的位
  • test(pos):检查指定位置的位是否为1
  • any():检查是否有任何位为1
  • none():检查是否所有位都为0
  • count():返回为1的位的数量
  • size():返回位集合的大小
  • to_ulong():转换为unsigned long
  • to_ullong():转换为unsigned long long
  • to_string():转换为字符串

示例:

cpp 复制代码
std::bitset<8> b("10101010");

// 检查位
bool bit0 = b.test(0); // false(第0位是0)
bool bit1 = b.test(1); // true(第1位是1)

// 设置位
b.set(0); // 10101011
b.reset(1); // 10101001

b.flip(); // 01010110

// 检查状态
bool has_any = b.any(); // true
bool has_none = b.none(); // false
int count = b.count(); // 4(有4位为1)

// 转换
unsigned long ul = b.to_ulong(); // 86
std::string s = b.to_string(); // "01010110"

位操作示例:

cpp 复制代码
std::bitset<4> a("1010"); // 1010
std::bitset<4> b("1100"); // 1100

std::bitset<4> c = a & b; // 1000(按位与)
std::bitset<4> d = a | b; // 1110(按位或)
std::bitset<4> e = a ^ b; // 0110(按位异或)
std::bitset<4> f = ~a; // 0101(按位取反)
std::bitset<4> g = a << 1; // 0100(左移1位)
std::bitset<4> h = a >> 1; // 0101(右移1位)
相关推荐
刘景贤3 小时前
C/C++开发环境
开发语言·c++
OasisPioneer5 小时前
现代 C++ 全栈教程 - Modern-CPP-Full-Stack-Tutorial
开发语言·c++·开源·github
liulilittle5 小时前
XDP to TC : TUN eBPF NAT
c++
花开莫与流年错_5 小时前
ZeroMQ基本示例使用
c++·消息队列·mq·示例·zeromq
qq_416018726 小时前
C++中的模板方法模式
开发语言·c++·算法
jyyyx的算法博客7 小时前
KMP 算法
c++·kmp
Emberone7 小时前
从C到C++:一脚踹开面向对象的大门
开发语言·c++
DDzqss7 小时前
3.25打卡day45
c++·算法
JMchen1238 小时前
Android NDK开发从入门到实战:解锁应用性能的终极武器
android·开发语言·c++·python·c#·android studio·ndk开发