“自适应容器:栈和队列”详解

目录

自适应容器:栈和队列

STL算法能用于栈和队列吗?

什么样的容器才适合作stack和queue的底层容器?

Queue队列的底层容器

Priority_queue优先级队列的底层容器

Stack栈的底层容器

栈的实质

栈的实例化

函数的使用

emplace()与push()的区别

其他函数的用法

队列的实质

队列的实例化

函数的使用

运行结果

关联容器与顺序容器的一大不同

Priority_queue与queue的区别

Priority_queue实例化

函数的使用

c2678解决方法

错误出现原因

改正方法


自适应容器:栈和队列

STL算法能用于栈和队列吗?

不可以,因为栈和队列对于容器做出了严格的要求,例如:在栈和容器中数据不可以随意被访问,即迭代器不可以随处访问元素,只可以以特定的规律访问栈和队列的元素,这对于STL算法显然是不可接受的,因此STL算法不可用于stack栈和queue队列。

什么样的容器才适合作stack和queue的底层容器?

 

容器种类

数据插入删除方式

Stack

栈顶插入栈顶删除

先进后出(FOLI)

Queue

队列尾部插入队列头部删除

先进先出(FILO)

Queue队列的底层容器

标准容器类dequelist满足这些要求。默认情况下,如果没有为特定队列类实例化指定容器类,则使用标准容器deque

基础容器可以是标准容器类模板之一,也可以是其他一些专门设计的容器类。这个底层容器应该至少支持以下操作:

empty

size

front

back

push_back

pop_front

Priority_queue优先级队列的底层容器

基础容器可以是任何标准容器类模板,也可以是其他一些特别设计的容器类。容器应该可以通过随机访问迭代器访问,并支持以下操作

empty()

size()

front()

push_back()

pop_back()

标准容器类vector和deque满足这些要求。默认情况下,如果没有为特定优先级队列类实例化指定容器类,则使用vector向量。

Stack栈的底层容器

标准容器类vectordequelist满足这些要求。默认情况下,如果没有为特定堆栈类实例化指定容器类,则使用标准容器deque

基础容器可以是任何标准容器类模板,也可以是其他一些特别设计的容器类。容器应支持下列操作

empty

size

back

push_back

pop_back

栈的实质

栈和队列底层均是顺序容器,只不过是对他们的行为做了一些限定,如:栈的LIFO(后进先出)特性……等。

栈是LIFO(后进先出)系统,只能从栈顶插入或删除元素。可将栈视为一叠盘子,最后叠上去的盘子首先被取下来,而不能取下中间或底部的盘子。图24.1说明了这种“在顶部添加和删除”的元素组织方式。

 

栈的实例化

 

函数的使用

emplace()与push()的区别

#include <iostream>  
#include <string>  
#include <stack>  
#include <vector>  
using namespace std;  
  
struct Student   
{  
    string name;  
    float mark;  
  
    Student(string name, float mark)  
    {  
        this->name = name;  
        this->mark = mark;  
    }  
};  
  
int main()  
{  
    stack<Student, vector<Student>> StackArray;  
    Student stud1("张三", 98.8);  
    StackArray.emplace("李四",89.1); // emplace函数可以调用Student结构体的构造函数生成对象进行插入  
    StackArray.push(stud1); // 对现成的对象进行插入  
}  

运行结果

 

其他函数的用法

Top()

访问栈顶的元素

Pop()

删除栈顶的元素

Swap()

将两个数组的元素进行交换

Empty()

判断数组是否为空

Size()

求数组中元素的个数

// 自适应容器:栈和队列.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。  
//  
  
#include <iostream>  
#include <string>  
#include <stack>  
#include <vector>  
using namespace std;  
  
struct Student   
{  
    string name;  
    float mark;  
  
    Student(string name, float mark)  
    {  
        this->name = name;  
        this->mark = mark;  
    }  
    friend ostream& operator << (ostream& Output, Student& stud);  
};  
ostream& operator << (ostream& Output, Student& stud)  
{  
    Output << stud.name << "的成绩为" << stud.mark;  
    return Output;  
}  
  
int main()  
{  
    stack<Student, vector<Student>> StackArray, StackArray1;  
    Student stud1("张三", 98.8);  
    StackArray.emplace("李四",89.1); // emplace函数可以调用Student结构体的构造函数生成对象进行插入  
    StackArray.push(stud1); // 对现成的对象进行插入  
  
    cout << StackArray.top() << endl; //访问栈顶元素  
    cout << "StackArray元素个数为" << StackArray.size() << endl;  
    while (!StackArray.empty())  
    {  
        cout << StackArray.top() << endl; // 访问栈顶元素  
        StackArray.pop(); // 删除栈顶元素  
    }  
    StackArray.swap(StackArray1); // 交换两个数组中的元素  
}  

队列的实质

STL queue是一个模板类,要使用它,必须包含头文件<queue>。queue是一个泛型类,只允许在末尾插入元素以及从开头删除元素。queue不允许访问中间的元素,但可以访问开头和末尾的元素。从这种意义上说,std::queue的行为与超市收银台前的队列极其相似。

队列的实例化

 

函数的使用

#include <iostream>  
#include <string>  
#include <list>  
#include <queue>  
#include <functional>  
using namespace std;  
  
struct Student  
{  
    string name;  
    float mark;  
  
    Student(string name, float mark)  
    {  
        this->name = name;  
        this->mark = mark;  
    }  
    bool operator < (const Student& stud)  
    {  
        return this->mark < stud.mark;  
    }  
    friend ostream& operator << (ostream& Output, Student& stud);  
};  
ostream& operator << (ostream& Output, Student& stud)  
{  
    Output << stud.name << "的成绩为" << stud.mark;  
    return Output;  
}  
  
int main()  
{  
    Student stud1("张三", 89), stud2("李四", 81), stud3("赵六", 93.2);  
    queue<Student, list<Student>> QueueArray, QueueArray1(QueueArray); // 不能用{}来初始化  
    QueueArray.push(stud1); // 向queue队列尾部进行插入  
    QueueArray.emplace(stud2); // 向queue队列尾部进行插入  
    QueueArray.push(stud3); // 向queue队列尾部进行插入  
  
    cout << "数组的大小为" << QueueArray.size() << endl; // 数组的大小  
    cout << "头部元素为:" << QueueArray.front() << endl; // 数组的头部元素  
    cout << "尾部元素为:" << QueueArray.back() << endl; // 数组的尾部元素  
  
    while (!QueueArray.empty()) // 判断数组是否为空  
    {  
        cout << QueueArray.front() << endl;  
        QueueArray.pop(); // 从数组的头部进行删除元素  
    }  
    QueueArray.swap(QueueArray1); // 交换QueueArray与QueueArray1  
}  

 

运行结果

 

关联容器与顺序容器的一大不同

只有关联容器才可以进行排序:

 

Priority_queue与queue的区别

由于priority_queue中含有默认排序或者自定义排序,因此在queue的访问权限上有进一步加以限制:

不可以从队列的两端进行访问,即back()&front()函数不可用,我们只能用top()来访问队列头部的元素。

Priority_queue实例化

函数的使用

#include <iostream>  
#include <string>  
#include <list>  
#include <queue>  
#include <functional>  
using namespace std;  
  
struct Student  
{  
    string name;  
    float mark;  
  
    Student(string name, float mark)  
    {  
        this->name = name;  
        this->mark = mark;  
    }  
    bool operator > (const Student& stud) const  
    {  
        return this->mark > stud.mark;  
    }  
    bool operator < (const Student& stud) const  
    {  
        return this->mark < stud.mark;  
    }  
    friend ostream& operator << (ostream& Output, const Student& stud); // 注意是"const Student"类型的变量  
};  
ostream& operator << (ostream& Output, const Student& stud)  
{  
    Output << stud.name << "的成绩为" << stud.mark;  
    return Output;  
}  
  
int main()  
{  
    Student stud1("张三", 89), stud2("李四", 81), stud3("赵六", 93.2);  
    priority_queue <Student, vector<Student>, greater<Student>> PriorQueueArray; // 对priority_queue对象进行排序必须要有可用于比较的运算符  
    PriorQueueArray.emplace(stud1);  
    PriorQueueArray.push(stud2);  
    PriorQueueArray.push(stud3);  
  
    cout << "队列的元素为" << PriorQueueArray.size() << endl;  
    cout << "队列的MIN为" << PriorQueueArray.top() << endl;  
  
    while (!PriorQueueArray.empty())  
    {  
        cout << PriorQueueArray.top() << endl; // 访问队列头部元素  
        PriorQueueArray.pop(); // 删除队列头部元素  
    }  
}  

c2678解决方法

错误出现原因

重载运算符左右操作对象类型不同,例如:

bool operator < (const Student& stud)  
{  
    return this->mark < stud.mark;  
}  

这样的话相当于“非const对象<const对象”,此时会抛出错误“左值为非const类型的对象”。

改正方法

bool operator < (const Student& stud) const  
{  
    return this->mark < stud.mark;  
}  

重载函数加const修饰符,本质是使编译时加入的this指针变为const,即左操作数变为const。

猜你喜欢

转载自blog.csdn.net/weixin_45590473/article/details/108173414