21天学通C++读书笔记(二十三:自适应容器:栈和队列)

1. 栈和队列的行为特征

  • 栈和队列与数组或 list 极其相似,但对插入、访问和删除元素的方式有一定的限制。可将元素插入到什么位置以及可从什么位置删除元素决定了容器的行为特征
1.1 栈
  • 栈是 LIFO(后进先出)系统,只能从栈顶插入或删除元素

  • 泛型 STL 容器 std::stack 模拟了栈的这种行为21天学通C++读书笔记(二十三:自适应容器:栈和队列)_第1张图片

1.2 队列
  • 队列是 FIFO(先进先出)系统,元素被插入到队尾,最先插入的元素最先删除
    在这里插入图片描述

  • 泛型 STL 容器 std::queue 模拟了队列的这种行为

2. 使用STL stack 类

2.1 实例化stack
template<
    class elementType,
    class Container = deque<Type>
> class stack;
  • 参数 elementType 是stack 存储的对象类型
  • 第二个模板参数 Container 是 stack 使用的默认底层容器实现类
  • stack 默认在内部使用 std::deque 来存储数据,但可指定使用 vector 或 list 来存储数据
#include 
#include 

int main () {
    using namespace std;

    stack<int> numsInStack;
    stack<double> dblsInStack;
    // 将第二个模板参数(stack 在内部使用的集合类)指定为 vector
    stack<double, vector<double> > doublesStackedInVec;
    // 使用一个stack 对象的拷贝来创建另一个stack对象
    stack<int> numsInStackCopy(numsInStack);
    
    return 0;
}
2.2 stack 的成员函数
  • stack 改变了另一种容器(如 deque、list 或 vector)的行为,通过限制元素插入或删除的方式实现其功能,从而提供严格遵守栈机制的行为特征
  • std::stack 的成员函数
函数 描述
push() 在栈顶插入元素 numsInStack.push (25);
pop() 删除栈顶的元素 numsInStack.pop ( );
empty() 检查栈是否为空并返回一个布尔值 if (numsInStack.empty ( )) DoSomething ( );
size() 返回栈中的元素数 size_t numElements = numsInStack.size ( );
top() 获得指向栈顶元素的引用 cout << "Element at the top = " << numsInStack.top ( );
2.3 使用 push() 和 pop() 在栈顶插入和删除元素
#include 
#include 
	
int main () {
    using namespace std;
    stack<int> numsInStack;
    cout << "Pushing {25, 10, -1, 5} on stack in that order:" << endl;
    numsInStack.push(25);
    numsInStack.push(10);
    numsInStack.push(-1);
    numsInStack.push(5);
    
    cout << "Stack contains " << numsInStack.size() << " elements" << endl;
    while (numsInStack.size() != 0) {
        cout << "Popping topmost element: " << numsInStack.top() << endl;
        numsInStack.pop(); // pop: removes topmost element
    }
    
    if (numsInStack.empty()) { // true: due to previous pop()s
        cout << "Popping all elements empties stack!" << endl;
    }
    return 0;
}

3. 使用STL queue 类

  • STL queue 是一个模板类,要使用它,必须包含头文件 queue
  • queue 是一个泛型类,只允许在末尾插入元素以及从开头删除元素
  • queue 不允许访问中间的元素,但可以访问开头和末尾的元素
3.1 实例化queue
template <
    class elementType,
    class Container = deque<Type>
> class queue;
  • 其中 elementType 是 queue 对象包含的元素的类型
  • Container 是 std::queue 用于存储其数据的集合类型,可将该模板参数设置为 std::list、vector 或 deque,默认为 deque
#include 
#include 

int main () {
    using namespace std;
    queue<int> numsInQ;
    queue<double> dblsInQ;
    queue<double, list<double> > dblsInQInList;
    queue<int> copyQ(numsInQ);
    
    return 0;
}
3.2 queue 的成员函数
函数 描述
push() 在队尾(即最后一个位置)插入一个元素
pop() 将队首(即最开始位置)的元素删除
front() 返回指向队首元素的引用
back() 返回指向队尾元素(即最后插入的元素)的引用
empty() 检查队列是否为空并返回一个布尔值
size() 返回队列中的元素数

STL queue 没有提供 begin() 和 end() 等函数,这是有意为之的,旨在只允许对 queue 执行符合队列行为特征的操作

3.3 使用 push() 在队尾插入以及使用 pop() 从队首删除
#include 
#include 

int main () {
    using namespace std;
    queue<int> numsInQ;
    
    cout << "Inserting {10, 5, -1, 20} into queue" << endl;
    numsInQ.push(10);
    numsInQ.push(5);  // elements are inserted at the end
    numsInQ.push(-1);
    numsInQ.push(20);
    
    cout << "Queue contains " << numsInQ.size() << " elements" << endl;
    cout << "Element at front: " << numsInQ.front() << endl;
    cout << "Element at back: " << numsInQ.back() << endl;
    
    while (numsInQ.size() != 0) {
        cout << "Deleting element: " << numsInQ.front() << endl;
        numsInQ.pop();  // removes element at front
    }
    
    if (numsInQ.empty()) {
        cout << "The queue is now empty!" << endl;
    }
    return 0;
}

4. 使用STL 优先级队列

  • STL priority_queue 是一个模板类,要使用它,也必须包含头文件 queue
  • priority_queue 与 queue 的不同之处在于,包含最大值(或二元谓词认为是最大值)的元素位于队首,且只能在队首执行操作
4.1 实例化priority_queue 类
template <
    class elementType,
    class Container=vector<Type>,
    class Compare=less<typename Container::value_type>
> class priority_queue;
  • 其中 elementType 是一个模板参数,指定了优先级队列将包含的元素的类型
  • 第二个模板参数指定 priority_queue 在内部将使用哪个集合类来存储数据
  • 第三个参数让程序员能够指定一个二元谓词,以帮助队列判断哪个元素应位于队首,。如果没有指定二元谓词,priority_queue 类将默认使用 std::less,它使用运算符 < 比较对象
#include 
#include 

int main () {
    using namespace std;
    
    // Priority queue of int sorted using std::less <> (default)
    priority_queue<int> numsInPrioQ;
    priority_queue<double> dblsInPrioQ;
    
    // A priority queue of integers sorted using std::greater <>
    priority_queue<int, deque<int>, greater<int> > numsInDescendingQ;
    priority_queue<int> copyQ(numsInPrioQ);
    
    return 0;
}
4.2 priority_queue 的成员函数
函数 描述
push() 在优先级队列中插入一个元素
pop() 删除队首元素,即最大的元素
top() 返回指向队列中最大元素(即队首元素)的引用
empty() 检查优先级队列是否为空并返回一个布尔值
size() 返回优先级队列中的元素个数
4.3 使用push()在priority_queue末尾插入以及使用pop()在priority_queue开头删除
#include 
#include 

int main () {
    using namespace std;
    
    priority_queue<int> numsInPrioQ;
    cout << "Inserting {10, 5, -1, 20} into the priority_queue" << endl;
    numsInPrioQ.push(10);
    numsInPrioQ.push(5);  
    numsInPrioQ.push(-1);
    numsInPrioQ.push(20);
    
    cout << "Deleting the " << numsInPrioQ.size() << " elements" << endl;
    while (!numsInPrioQ.empty()) {
        cout << "Deleting topmost element: " << numsInPrioQ.top() << endl;
        numsInPrioQ.pop();
    }
    return 0;
}
  • 通过使用谓词将值最小的元素放在 priority_queue 开头
#include 
#include 
#include 

int main () {
    using namespace std;

    // greater 表示内置类型从大到小排序,less 表示内置类型从小到大排序
    // greater 谓词导致包含的整数最小的元素被认为是最大的,因此放在队首
    priority_queue<int, vector<int>, greater<int> > numsInPrioQ;
    
    cout << "Inserting {10, 5, -1, 20} into the priority queue" << endl;
    numsInPrioQ.push(10);
    numsInPrioQ.push(5);
    numsInPrioQ.push(-1);
    numsInPrioQ.push(20);
    
    cout << "Deleting " << numsInPrioQ.size() << " elements" << endl;
    while (!numsInPrioQ.empty ()) {
        cout << "Deleting topmost element " << numsInPrioQ.top () << endl;
        numsInPrioQ.pop ();
    }
    return 0;
}
Q&A
  • 能否对队列中的所有元素进行迭代?
    • 队列不支持迭代器,只能访问队尾的元素
  • STL 算法能否用于自适应容器?
    • STL 算法使用迭代器。由于 stack 和 queue 类都没有提供标记范围两端的迭代器,因此无法将 STL 算法用于这些容器

你可能感兴趣的:(C++入门学习笔记,c++,算法,数据结构)