目录
自适应容器:栈和队列
STL算法能用于栈和队列吗?
不可以,因为栈和队列对于容器做出了严格的要求,例如:在栈和容器中数据不可以随意被访问,即迭代器不可以随处访问元素,只可以以特定的规律访问栈和队列的元素,这对于STL算法显然是不可接受的,因此STL算法不可用于stack栈和queue队列。
什么样的容器才适合作stack和queue的底层容器?
容器种类 |
数据插入删除方式 |
|
Stack |
栈顶插入栈顶删除 |
先进后出(FOLI) |
Queue |
队列尾部插入队列头部删除 |
先进先出(FILO) |
Queue队列的底层容器
标准容器类deque和list满足这些要求。默认情况下,如果没有为特定队列类实例化指定容器类,则使用标准容器deque。
基础容器可以是标准容器类模板之一,也可以是其他一些专门设计的容器类。这个底层容器应该至少支持以下操作:
empty |
size |
front |
back |
push_back |
pop_front |
Priority_queue优先级队列的底层容器
基础容器可以是任何标准容器类模板,也可以是其他一些特别设计的容器类。容器应该可以通过随机访问迭代器访问,并支持以下操作:
empty() |
size() |
front() |
push_back() |
pop_back() |
标准容器类vector和deque满足这些要求。默认情况下,如果没有为特定优先级队列类实例化指定容器类,则使用vector向量。
Stack栈的底层容器
标准容器类vector、deque和list满足这些要求。默认情况下,如果没有为特定堆栈类实例化指定容器类,则使用标准容器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。