C++中的容器类型及使用
容器的概念:
泛型编程是一种编程理念,其提出的动机是发明一种语言机制,能够在编程中编写完全一般化的可重复使用的算法,不会因为数据类型的不同而有差异。
美国的惠普实验室针对泛型编程开发了一系列软件工具,被称为标准模板库(STL),后续在C++中被广泛引入。STL中绝大多数的类型都使用了模板的编程技术,这相比传统的代码而言有更好重用特性。
在STL中最核心的内容是容器和迭代器。
容器指的是用来存储数据的集合,由于内部存储的数据使用模板实现,因此可以支持绝大多数数据类型。迭代器是配合容器进行高效遍历的工具,是一种特殊的指针。
容器的分类
首先容器分为:顺序容器和关联容器
顺序容器中有:string字符串、array数组(C++11引入)、vector向量、list列表、deque队列
特点: 顺序容器是一种各元素之间有顺序关系的结构集合,每个元素在容器都有固定的位置,但是可以用删除或插入等操作改变这个位置。
关联容器中有:map键值对映射、multimap多重键值对映射
特点:关联容器的各元素之间没有严格的物理上顺序关系;但是内部有排序,因此可以用迭代器遍历;关联容器内部的元素以键值对key-value pair的形式存在。
使用注意:容器类的使用需要引入头文件,所有的容器类都是属于std名
#include <array>
#include <vector>
#include <list>
#include <map>
#include <deque>
array 数组
特点:array是C++ 11中引入的容器类型,与传统数组相比,array更加安全和易于使用。
#include <iostream>
#include <array> // 引入头文件
using namespace std;
int main()
{
// 创建一个长度为5的int数组
array<int,5> arr = {2,4,6,8,10};
cout << arr[0] << endl; // 2
cout << arr[4] << endl; // 10
arr[1] = 666;
cout << arr.at(1) << endl; // 666
// 普通循环
for(int i=0;i<arr.size();i++)
{
cout << arr.at(i) << " ";
}
cout << endl;
// 给所有元素赋值
arr.fill(5);
// for-each循环
for(int i:arr)
{
cout << i << " ";
}
cout << endl;
// 迭代器:略
return 0;
}
vector 向量
特点:vector内部由数组实现,因此可以高效地进行元素的随机存取,但是插入和删除的效率较低,是最常用的一种顺序容器。
示例:
#include <iostream>
#include <vector> // 引入头文件
using namespace std;
int main()
{
// 创建一个长度为0的向量对象
vector<int> vec1;
cout << vec1.empty() << endl; // 1
// 创建一个长度为5的向量对象
vector<int> vec2(5);
vec2[0] = 123; // 修改元素
cout << vec2[0] << endl; // 123
cout << vec2.at(4) << endl; // 0
// 5个666
vector<int> vec3(5,666);
// 向后追加元素
vec3.push_back(888);
// 在第二个位置插入2
// 参数1:插入的位置
// 参数2:插入的元素
vec3.insert(vec3.begin()+1,2);
// 在倒数第二个位置插入222
vec3.insert(vec3.end()-1,222);
// 删除第一个元素
vec3.erase(vec3.begin());
// 删除最后一个元素
vec3.erase(vec3.end()-1);
vec3.pop_back(); // 删除最后一个元素
// 普通循环遍历
for(int i=0;i<vec3.size();i++)
{
cout << vec3.at(i) << " ";
}
cout << endl;
// 清空
vec3.clear();
// for-each遍历
for(int i:vec3)
{
cout << i << " ";
}
cout << endl;
// 迭代器遍历:略
return 0;
}
list 列表
特点:list内部由双向链表实现,因此元素的内存空间是不连续的,能高效地进行插入和删除操作,但是随机存取的效率较低,并且list只能通过迭代器指针来访问数据。总结:能高效的进行插入删除操作;随机存取效率较低。
示例:
#include <iostream>
#include <list> // 引入头文件
using namespace std;
int main()
{
// 创空
list<string> lis2;
// 判空
cout << lis2.empty() << endl;
// 创建一个四个hello元素的列表对象
list<string> lis1(4, "hello");
// 向后追加元素
lis1.push_back("bye");
// 向前追加元素
lis1.push_front("start");
// 取出头部元素
cout << lis1.front() << endl;
// 取出尾部元素
cout << lis1.back() << endl;
// 删除头部元素
lis1.pop_front();
// 删除尾部元素
lis1.pop_back();
// 在第二个位置插入元素"2B"
lis1.insert(++lis1.begin(), "2B");
// 在倒数第二个位置插入元素"2Y"
lis1.insert(--lis1.end(), "2Y");
// 保存迭代器指针
// list<string>::iterator 整体为迭代器类型
list<string>::iterator iter = lis1.begin();
// 修改第一个元素,此时迭代器指向第一个元素
*iter = "One";
// 取出元素,此时迭代器指向第一个元素
cout << *iter << endl;
// 移动迭代器
// 参数1:移动的迭代器指针
// 参数2:移动的距离,可以为负,反向移动
advance(iter, 3);
// 在第四个元素的位置插入"444"
lis1.insert(iter, "444");
// 删除倒数第一个元素
lis1.erase(--lis1.end());
// 清空
//lis1.clear();
// 排序——按照大小和编码
lis1.sort();
// 不能下标所以不支持普通的for循环遍历,但是支持for-each遍历
for (string s:lis1)
cout << s << " ";
cout << endl;
// 迭代器遍历:略
return 0;
}
deque队列
deque 的性能位于 vector 和 list 之间,是一种性能均衡的容器;由于队列特性,首尾两端操作比较高效;deque 基本支持所有的常用API接口;
将 vector 向量与 list 列表中的 vector 与 list 改为 deque。
关联容器
map是单重键值对映射;multimap允许一个键对应多个值,map更为常用。
键必须唯一,通常使用字符串类型;值可以重复,可以是任何类型。
示例:
#include <iostream>
#include <map> // 引入头文件
using namespace std;
int main()
{
// 创建一个元素为空的map对象
map<string, int> map1;
// 判空
cout << "是否为空:" << map1.empty() << endl;
// 添加元素 方法2
//将键值对做成一个对象,类型为pair,也是一个模板的类,pair<键和值的类型>
map1.insert(pair<string,int>("country", 86));
// 添加元素 方法1
map1["heigth"] = 180;
map1["salary"] = 10000;
map1["age"] = 40;
map1["weight"] = 180;
// 再次赋值就是修改键对应的值
map1["weigth"] = 70;
// 删除元素——返回0删除失败,成功则为删除的数量
if(map1.erase("salary"))
cout << "删除成功,还剩下" << map1.size() << "个键值对" << endl;
else
cout << "删除失败" << endl;
// map1.find("");返回迭代器指针,迭代器指针有两个属性first,second
// 如果有对应的键,则指向键值对
// 如果没有对应的键,则指向“最后一个元素的后面”
// 取出元素
//cout << map1.find("salary")->second << endl; 取出某个键对应的值
map<string,int>::iterator iter = map1.find("salary");
if(iter != map1.end())
{
int value = iter->second;
cout << value << endl;
}
else
cout << "没有对应的值!" << endl;
// 清空
map1.clear();
cout << map1.empty() << endl;
return 0;
}
map1.find(“”);函数返回的迭代器指针,其指向的位置有两个属性first键second值;
定义一个指针iter接收find函数返回值
map<string, int>::iterator iter = map1.find(“salary”);
有对应键:iter指向键值对;
无对应键:iter指向最后一个元素的后面,输出随机值。
避免取出随机值:
if(iter != map1.end()) //有键值对
cout << iter->second << endl;//取值second
else // 无键值对
迭代器
特点:所有的容器类型都支持迭代器遍历。
分类:iterator是读写迭代器;const_iterator是只读迭代器。
示例:
#include <iostream>
#include <array>
#include <vector>
#include <list>
#include <deque>
#include <map>
using namespace std;
int main()
{
string str = "ABC678%^";
// string的只读迭代器
string::const_iterator iter_s;
for(iter_s = str.begin(); iter_s != str.end(); iter_s++)
cout << *iter_s << " ";
cout << endl;
array<double,6> arr;
arr.fill(3.14);
// array的读写迭代器
array<double,6>::iterator iter_a;
for(iter_a = arr.begin(); iter_a != arr.end(); iter_a++)
cout << ++(*iter_a) << " ";
cout << endl;
vector<int> vec1(4,4);
// vector的只读迭代器
vector<int>::const_iterator iter_vec = vec1.begin();
while(iter_vec != vec1.end())
{
cout << *iter_vec << " ";
iter_vec++;
}
cout << endl;
list<string> lis1;
lis1.push_back("fhdjks");
lis1.push_back("fhfggks");
lis1.push_back("dsdsghs");
lis1.push_back("fh***");
// list的读写迭代器
list<string>::iterator iter_lis = lis1.begin();
while(iter_lis != lis1.end())
{
cout << (*iter_lis).append("~") << " ";
iter_lis++;
}
cout << endl;
deque<int> deq(5,5);
// deque的读写迭代器,也可以只读
deque<int>::iterator iter_d;
for(iter_d = deq.begin(); iter_d != deq.end(); iter_d++)
cout << *iter_d << " ";
cout << endl;
map<string,string> map1;
map1["城市"] = "济南";
map1["name"] = "Tom";
map1["age"] = "7";
map1["friend"] = "Jerry";
// map的只读迭代器
for(map<string,string>::const_iterator iter = map1.begin();
iter != map1.end();iter++)
{
cout << iter->first << "-"; // 键
cout << iter->second << endl; // 值
}
return 0;
}
以上为本人目前对容器的了解,内容不多,这些可以随时查到,鄙人首次学习C++,纯小白,如有错误,还请各位大神不吝赐教,引用大佬的一句话:计算机,只要肯学习,永远是yyds。