stack / queue / list 容器
stack容器
stack 基本概念
概念:stack是一種先進後出(First In Last Out,FILO)的數據結構,它只有一個出口

棧中只有頂端的元素纔可以被外界使用,因此棧不允許有遍歷行爲
棧中進入數據稱爲 --- 入棧 push
棧中彈出數據稱爲 --- 出棧 pop
生活中的棧:


stack 常用接口
功能描述:棧容器常用的對外接口
構造函數:
stack<T> stk;//stack採用模板類實現, stack對象的默認構造形式stack(const stack &stk);//拷貝構造函數
賦值操作:
stack& operator=(const stack &stk);//重載等號操作符
數據存取:
push(elem);//向棧頂添加元素pop();//從棧頂移除第一個元素top();//返回棧頂元素
大小操作:
empty();//判斷堆棧是否爲空size();//返回棧的大小
示例:
#include <stack>
//栈容器常用接口
void test01()
{
//创建栈容器 栈容器必须符合先进后出
stack<int> s;
//向栈中添加元素,叫做 压栈 入栈
s.push(10);
s.push(20);
s.push(30);
while (!s.empty()) {
//输出栈顶元素
cout << "栈顶元素为: " << s.top() << endl;
//弹出栈顶元素
s.pop();
}
cout << "栈的大小为:" << s.size() << endl;
}
int main() {
test01();
return 0;
}
運行/觀察結果: 運行後會按輸出語句打印對應內容,變量值可結合初始化、賦值和函數調用順序推導。
總結:
- 入棧 --- push
- 出棧 --- pop
- 返回棧頂 --- top
- 判斷棧是否爲空 --- empty
- 返回棧大小 --- size
queue 容器
queue 基本概念
概念:Queue是一種先進先出(First In First Out,FIFO)的數據結構,它有兩個出口

隊列容器允許從一端新增元素,從另一端移除元素
隊列中只有隊頭和隊尾纔可以被外界使用,因此隊列不允許有遍歷行爲
隊列中進數據稱爲 --- 入隊 push
隊列中出數據稱爲 --- 出隊 pop
生活中的隊列:

queue 常用接口
功能描述:棧容器常用的對外接口
構造函數:
queue<T> que;//queue採用模板類實現,queue對象的默認構造形式queue(const queue &que);//拷貝構造函數
賦值操作:
queue& operator=(const queue &que);//重載等號操作符
數據存取:
push(elem);//往隊尾添加元素pop();//從隊頭移除第一個元素back();//返回最後一個元素front();//返回第一個元素
大小操作:
empty();//判斷堆棧是否爲空size();//返回棧的大小
示例:
#include <queue>
#include <string>
class Person
{
public:
Person(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
void test01() {
//创建队列
queue<Person> q;
//准备数据
Person p1("唐僧", 30);
Person p2("孙悟空", 1000);
Person p3("猪八戒", 900);
Person p4("沙僧", 800);
//向队列中添加元素 入队操作
q.push(p1);
q.push(p2);
q.push(p3);
q.push(p4);
//队列不提供迭代器,更不支持随机访问
while (!q.empty()) {
//输出队头元素
cout << "队头元素-- 姓名: " << q.front().m_Name
<< " 年龄: "<< q.front().m_Age << endl;
cout << "队尾元素-- 姓名: " << q.back().m_Name
<< " 年龄: " << q.back().m_Age << endl;
cout << endl;
//弹出队头元素
q.pop();
}
cout << "队列大小为:" << q.size() << endl;
}
int main() {
test01();
return 0;
}
運行/觀察結果: 運行後會打印示例中的變量值或地址;地址值與運行環境有關,以同類對象的相對位置和指針變化爲觀察重點。
總結:
- 入隊 --- push
- 出隊 --- pop
- 返回隊頭元素 --- front
- 返回隊尾元素 --- back
- 判斷隊是否爲空 --- empty
- 返回隊列大小 --- size
list容器
list基本概念
**功能:**將數據進行鏈式存儲
鏈表(list)是一種物理存儲單元上非連續的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接實現的
鏈表的組成:鏈表由一系列結點組成
結點的組成:一個是存儲數據元素的數據域,另一個是存儲下一個結點地址的指針域
STL中的鏈表是一個雙向循環鏈表

由於鏈表的存儲方式並不是連續的內存空間,因此鏈表list中的迭代器只支持前移和後移,屬於雙向迭代器
list的優點:
- 採用動態存儲分配,不會造成內存浪費和溢出
- 鏈表執行插入和刪除操作十分方便,修改指針即可,不需要移動大量元素
list的缺點:
- 鏈表靈活,但是空間(指針域) 和 時間(遍歷)額外耗費較大
List有一個重要的性質,插入操作和刪除操作都不會造成原有list迭代器的失效,這在vector是不成立的。
總結:STL中List和vector是兩個最常被使用的容器,各有優缺點
list構造函數
功能描述:
- 創建list容器
函數原型:
list<T> lst;//list採用採用模板類實現,對象的默認構造形式:list(beg,end);//構造函數將[beg, end)區間中的元素拷貝給本身。list(n,elem);//構造函數將n個elem拷貝給本身。list(const list &lst);//拷貝構造函數。
示例:
#include <list>
void printList(const list<int>& L) {
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
void test01()
{
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
printList(L1);
list<int>L2(L1.begin(),L1.end());
printList(L2);
list<int>L3(L2);
printList(L3);
list<int>L4(10, 1000);
printList(L4);
}
int main() {
// 程序从 main 函数开始执行,下面的语句会按顺序运行。
test01();
// 返回 0 表示程序正常结束。
return 0;
}
運行/觀察結果: 運行後會按輸出語句打印對應內容,變量值可結合初始化、賦值和函數調用順序推導。
總結:list構造方式同其他幾個STL常用容器,熟練掌握即可
list 賦值和交換
功能描述:
- 給list容器進行賦值,以及交換list容器
函數原型:
assign(beg, end);//將[beg, end)區間中的數據拷貝賦值給本身。assign(n, elem);//將n個elem拷貝賦值給本身。list& operator=(const list &lst);//重載等號操作符swap(lst);//將lst與本身的元素互換。
示例:
#include <list>
void printList(const list<int>& L) {
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
//赋值和交换
void test01()
{
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
printList(L1);
//赋值
list<int>L2;
L2 = L1;
printList(L2);
list<int>L3;
L3.assign(L2.begin(), L2.end());
printList(L3);
list<int>L4;
L4.assign(10, 100);
printList(L4);
}
//交换
void test02()
{
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
list<int>L2;
L2.assign(10, 100);
cout << "交换前: " << endl;
printList(L1);
printList(L2);
cout << endl;
L1.swap(L2);
cout << "交换后: " << endl;
printList(L1);
printList(L2);
}
int main() {
//test01();
test02();
return 0;
}
運行/觀察結果: 運行後會按輸出語句打印對應內容,變量值可結合初始化、賦值和函數調用順序推導。
總結:list賦值和交換操作能夠靈活運用即可
list 大小操作
功能描述:
- 對list容器的大小進行操作
函數原型:
size();//返回容器中元素的個數empty();//判斷容器是否爲空resize(num);//重新指定容器的長度爲num,若容器變長,則以默認值填充新位置。
//如果容器變短,則末尾超出容器長度的元素被刪除。resize(num, elem);//重新指定容器的長度爲num,若容器變長,則以elem值填充新位置。 //如果容器變短,則末尾超出容器長度的元素被刪除。
示例:
#include <list>
void printList(const list<int>& L) {
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
//大小操作
void test01()
{
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
if (L1.empty())
{
cout << "L1为空" << endl;
}
else
{
cout << "L1不为空" << endl;
cout << "L1的大小为: " << L1.size() << endl;
}
//重新指定大小
L1.resize(10);
printList(L1);
L1.resize(2);
printList(L1);
}
int main() {
test01();
return 0;
}
運行/觀察結果: 運行後會按輸出語句打印對應內容,變量值可結合初始化、賦值和函數調用順序推導。
總結:
- 判斷是否爲空 --- empty
- 返回元素個數 --- size
- 重新指定個數 --- resize
list 插入和刪除
功能描述:
- 對list容器進行數據的插入和刪除
函數原型:
- push_back(elem);//在容器尾部加入一個元素
- pop_back();//刪除容器中最後一個元素
- push_front(elem);//在容器開頭插入一個元素
- pop_front();//從容器開頭移除第一個元素
- insert(pos,elem);//在pos位置插elem元素的拷貝,返回新數據的位置。
- insert(pos,n,elem);//在pos位置插入n個elem數據,無返回值。
- insert(pos,beg,end);//在pos位置插入[beg,end)區間的數據,無返回值。
- clear();//移除容器的所有數據
- erase(beg,end);//刪除[beg,end)區間的數據,返回下一個數據的位置。
- erase(pos);//刪除pos位置的數據,返回下一個數據的位置。
- remove(elem);//刪除容器中所有與elem值匹配的元素。
示例:
#include <list>
void printList(const list<int>& L) {
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
//插入和删除
void test01()
{
list<int> L;
//尾插
L.push_back(10);
L.push_back(20);
L.push_back(30);
//头插
L.push_front(100);
L.push_front(200);
L.push_front(300);
printList(L);
//尾删
L.pop_back();
printList(L);
//头删
L.pop_front();
printList(L);
//插入
list<int>::iterator it = L.begin();
L.insert(++it, 1000);
printList(L);
//删除
it = L.begin();
L.erase(++it);
printList(L);
//移除
L.push_back(10000);
L.push_back(10000);
L.push_back(10000);
printList(L);
L.remove(10000);
printList(L);
//清空
L.clear();
printList(L);
}
int main() {
test01();
return 0;
}
運行/觀察結果: 運行後會按輸出語句打印對應內容,變量值可結合初始化、賦值和函數調用順序推導。
總結:
- 尾插 --- push_back
- 尾刪 --- pop_back
- 頭插 --- push_front
- 頭刪 --- pop_front
- 插入 --- insert
- 刪除 --- erase
- 移除 --- remove
- 清空 --- clear
list 數據存取
功能描述:
- 對list容器中數據進行存取
函數原型:
front();//返回第一個元素。back();//返回最後一個元素。
示例:
#include <list>
//数据存取
void test01()
{
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
//cout << L1.at(0) << endl;//错误 不支持at访问数据
//cout << L1[0] << endl; //错误 不支持[]方式访问数据
cout << "第一个元素为: " << L1.front() << endl;
cout << "最后一个元素为: " << L1.back() << endl;
//list容器的迭代器是双向迭代器,不支持随机访问
list<int>::iterator it = L1.begin();
//it = it + 1;//错误,不可以跳跃访问,即使是+1
}
int main() {
test01();
return 0;
}
運行/觀察結果: 運行後會按輸出語句打印對應內容,變量值可結合初始化、賦值和函數調用順序推導。
總結:
- list容器中不可以通過或者at方式訪問數據
- 返回第一個元素 --- front
- 返回最後一個元素 --- back
list 反轉和排序
功能描述:
- 將容器中的元素反轉,以及將容器中的數據進行排序
函數原型:
reverse();//反轉鏈表sort();//鏈表排序
示例:
void printList(const list<int>& L) {
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
bool myCompare(int val1 , int val2)
{
return val1 > val2;
}
//反转和排序
void test01()
{
list<int> L;
L.push_back(90);
L.push_back(30);
L.push_back(20);
L.push_back(70);
printList(L);
//反转容器的元素
L.reverse();
printList(L);
//排序
L.sort(); //默认的排序规则 从小到大
printList(L);
L.sort(myCompare); //指定规则,从大到小
printList(L);
}
int main() {
test01();
return 0;
}
運行/觀察結果: 運行後會按輸出語句打印對應內容,變量值可結合初始化、賦值和函數調用順序推導。
總結:
- 反轉 --- reverse
- 排序 --- sort (成員函數)
排序案例
案例描述:將Person自定義數據類型進行排序,Person中屬性有姓名、年齡、身高
排序規則:按照年齡進行升序,如果年齡相同按照身高進行降序
示例:
#include <list>
#include <string>
class Person {
public:
Person(string name, int age , int height) {
m_Name = name;
m_Age = age;
m_Height = height;
}
public:
string m_Name; //姓名
int m_Age; //年龄
int m_Height; //身高
};
bool ComparePerson(Person& p1, Person& p2) {
if (p1.m_Age == p2.m_Age) {
return p1.m_Height > p2.m_Height;
}
else
{
return p1.m_Age < p2.m_Age;
}
}
void test01() {
list<Person> L;
Person p1("刘备", 35 , 175);
Person p2("曹操", 45 , 180);
Person p3("孙权", 40 , 170);
Person p4("赵云", 25 , 190);
Person p5("张飞", 35 , 160);
Person p6("关羽", 35 , 200);
L.push_back(p1);
L.push_back(p2);
L.push_back(p3);
L.push_back(p4);
L.push_back(p5);
L.push_back(p6);
for (list<Person>::iterator it = L.begin(); it != L.end(); it++) {
cout << "姓名: " << it->m_Name << " 年龄: " << it->m_Age
<< " 身高: " << it->m_Height << endl;
}
cout << "---------------------------------" << endl;
L.sort(ComparePerson); //排序
for (list<Person>::iterator it = L.begin(); it != L.end(); it++) {
cout << "姓名: " << it->m_Name << " 年龄: " << it->m_Age
<< " 身高: " << it->m_Height << endl;
}
}
int main() {
test01();
return 0;
}
運行/觀察結果: 運行後會按輸出語句打印對應內容,變量值可結合初始化、賦值和函數調用順序推導。
總結:
- 對於自定義數據類型,必須要指定排序規則,否則編譯器不知道如何進行排序
- 高級排序只是在排序規則上再進行一次邏輯規則制定,並不複雜