更多算法例题链接: 【数据结构与算法】递推法和递归法解题(递归递推算法典型例题)
C++ 内置模板(STL)
迭代器讲解
什么是迭代器(iterator)
迭代器(iterator)的定义:迭代器是一种检查容器内元素并遍历元素的数据类型。
迭代器提供对一个容器中的对象的访问方法,并且定义了容器中对象的范围。
容器vector
和string
有迭代器类型同时拥有返回迭代器的成员。
如:容器有成员 .begin()
和 .end()
,其中 .begin()
成员复制返回指向第一个元素的迭代器,即指向第一个元素的“地址”,而 .end()
成员返回指向容器尾元素的下一个位置的迭代器.
即 .begin()
指向的是第一个合法元素的位置,.end()
指向是容器后第一个不合法元素的地址。
示例
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<int> nums;
nums.push_back(1);
nums.push_back(2);
nums.push_back(4);
nums.push_back(8);
nums.push_back(16);
vector<string> fruits;
fruits.push_back("orange");
fruits.push_back("apple");
fruits.push_back("raspberry");
vector<char> empty;
// 求和 vector nums 中的所有整数(若存在),仅打印结果。
int sum = 0;
for (vector<int>::iterator it = nums.begin(); it != nums.end(); ++it)
sum += *it;
cout << "Sum of nums: " << sum << "\n";
// 打印 vector fruits 中的首个 fruis ,不检查是否有一个。
if (!fruits.empty())
cout << "First fruit: " << fruits.front() << "\n";
if (empty.empty())
cout << "vector 'empty' is indeed empty.\n";
return 0;
}
/*输出:
Sum of nums: 31
First fruit: orange
vector 'empty' is indeed empty
*/
相应的还有容器反向迭代器成员 .rbegin()
.rend()
,.rbegin()
返回容器的元素前最后一个不合法的地址,rend()
返回容器的最后一个合法地址。
容器迭代器的使用
每种容器类型都定义了自己的迭代器类型:vector:vector<int>::iterator iter;//定义一个名为iter的变量
数据类型是由vector<int>
定义的 iterator
类型。简单说就是容器类定义了自己的 iterator
类型,用于访问容器内的元素。每个容器定义了一种名为iterator
的类型,这种类型支持迭代器的各种行为。
容器(vector)(线性表的使用)
Vector 容器(类:线性表中有 vector
和 list
,两者作用比较相似。vector
的主要作用就是可变长度的数组,就把他当成数组使用即可。
#include <iostream>
#include <vector>
int main()
{
// 创建含有整数的 vector
std::vector<int> v = {7, 5, 16, 8};
// 将二个整数添加到 vector
v.push_back(25);
v.push_back(13);
// 迭代并打印 vector 的值
std::cout << "v = { ";
for (int n : v)
std::cout << n << ", ";
std::cout << "};\n";
}
/*输出:
v = { 7, 5, 16, 8, 25, 13, };
*/
-
vector
容器的定义
#include <vector> //头文件
vector<int> a; //定义了一个int类型的vector容器a
vector<int> b[100]; //定义了一个int类型的vector容器b组
struct rec
{
···
};
vector<rec> c; //定义了一个rec类型的vector容器c
vector<int>::iterator it; //vector的迭代器,与指针类似
-
vector
容器的操作
a.size() //返回实际长度(元素个数),O(1)复杂度
a.empty() //容器为空返回1,否则返回0,O(1)复杂度
a.clear() //把vector清空
a.begin() //返回指向第一个元素的迭代器,*a.begin()与a[0]作用相同
a.end() //越界访问,指向vector尾部,指向第n个元素再往后的边界
a.front() //返回第一个元素的值,等价于*a.begin和a[0]
a.back() //返回最后一个元素的值,等价于*--a.end()和a[size()-1]
a.push_back(x) //把元素x插入vector尾部
a.pop_back() //删除vector中最后一个元素
- 遍历容器的方法
(1)迭代器使用与指针类似,可如下遍历整个容器。
for ( vector<int>::iterator it=a.begin() ; it!=a.end() ; it++ )
cout<<*iterator<<endl;
(2) 当成数组使用。
for( int i=0;i<a.size();i++) cout<<a[i]<<endl;
代码示例:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
// 创建含有整数的 vector
vector<int> v ;
v.push_back(7);
v.push_back(5);
v.push_back(16);
v.push_back(8);
// 将二个整数添加到 vector
v.push_back(25);
v.push_back(13);
// 迭代并打印 vector 的值
cout << "v = { ";
for ( vector<int>::iterator it=v.begin() ; it!=v.end() ; it++ )
cout << *it << ", ";
cout << "};\n";
cout << "v = { ";
for (int j = 0; j < v.size(); ++j) {
cout << v[j] << ", ";
}
cout << "};\n";
}
队列的使用
队列的使用:
1.queue
的定义方法
queue<string> myqueue;
queue<int> myqueue_int;
-
queue
的基本操作
front():返回 queue 中第一个元素的引用。
back():返回 queue 中最后一个元素的引用。
push(const T& obj):在 queue 的尾部添加一个元素的副本。
pop():删除 queue 中的第一个元素。
size():返回 queue 中元素的个数。
empty():如果 queue 中没有元素的话,返回 true
集合(set)的使用
在C++中,set
是一个基于红黑树实现的关联容器,它可以自动将元素排序并保持唯一性。默认情况下,set
使用元素类型的<运算符来比较和排序其元素。如果你想要一个自定义的排序准则,可以在声明set
时指定一个比较函数或函数对象。
#include <bits/stdc++.h>
using namespace std;
// 1.set 的定义 set<数据类型> 变量名
set<int> intSet;
set<string> stringSet;
int main()
{
string s1="测试1";
string s2="测试2";
string s3="测试3";
//2. 插入操作
stringSet.insert(s3);
stringSet.insert(s1);
//5. 返回集合元素数量
printf("前2次插入操作完成后的元素数量为%d\n",stringSet.size());
stringSet.insert(s2);
printf("前3次插入操作完成后的元素数量为%d\n",stringSet.size());
//6.遍历整个集合,借助迭代器实现
//定义方式 容器类型< type> ::iterator name
set<string> ::iterator setStringIterator;
for(setStringIterator=stringSet.begin();setStringIterator!=stringSet.end();setStringIterator++)
cout<<*setStringIterator<<" ";
puts("");
//3. 删除操作
stringSet.erase(s3);
printf("删除操作完成后的元素数量为%d\n",stringSet.size());
for(setStringIterator=stringSet.begin();setStringIterator!=stringSet.end();setStringIterator++)
cout<<*setStringIterator<<" ";
puts("");
//4. 判断是否由此元素
if(stringSet.count(s2)!=0) cout<<"存在元素"<<s2<<endl;
}
映射(map)的使用
map
是一个关联容器,它提供一对一的 hash。
第一个可以称为关键字(key),每个关键字只能在 map 中出现一次
第二个可能称为该关键字的值(value)
map 以模板(泛型)方式实现,可以存储任意类型的数据,包括使用者自定义的数据类型。Map 主要用于资料一对一映射(one-to-one)的情況,map 在 C++ 的內部的实现自建一颗红黑树,这颗树具有对数据自动排序的功能。在 map 内部所有的数据都是有序的。
比如,像是管理班级内的学生,Key 值为学号,Value 放其他信息的结构体或者类。
-
map
的定义:
//map的定义
map<char, int> mymap1;
map<string, int> mymap2;
- 容量:
int map.size();//查询map中有多少对元素
bool empty();// 查询map是否为空
- 插入
map.insert(make_pair(key,value));
//或者
map.insert(pair<char, int>(key, value))
//或者
map[key]=value
- 遍历
map<string, string>::iterator it;
for (it = mapSet.begin(); it != mapSet.end(); ++it)
{
cout << "key" << it->first << endl;
cout << "value" << it->second << endl;
}
- 查找
m.count(key)://由于map不包含重复的key,因此m.count(key)取值为0,或者1,表示是否包含。
m.find(key)://返回迭代器,判断是否存在。
整体应用代码示例:
#include<bits/stdc++.h>
//#include<vector>
//#include<stack>
//#include<string>
//#include<queue>
//#include<deque>
//#include<map>
using namespace std;
//map是每个键对应一个值
//映射类似于函数的对应关系,每个x对应一个y.
//map特性:map会按照键的顺序从小到大自动排序,键的类型必须可以比较大小
void test01(){
//初始化定义
map<int, string> mp;
// 插入元素
mp.insert(make_pair(1, "One"));
mp.insert(make_pair(2, "Two"));
mp.insert(make_pair(3, "Three"));
mp.insert(make_pair(4, "Four"));
// 查看元素是否存在
if (mp.count(2) > 0) {
cout << "Key 2 exists!" << endl;
}
// 查找元素
map<int,string>::iterator it = mp.find(3);
if (it != mp.end()) {
cout << "Value of key 3: " << it->second << std::endl;
}
// 删除元素
mp.erase(2); // 通过键删除元素
mp.erase(mp.find(4)); // 通过迭代器删除元素
// 清空map
mp.clear();
// 判断map是否为空
if (mp.empty()) {
cout << "Map is empty!" << std::endl;
}
}
void test02(){
/*mp.find(key) 返回键为key的映射的迭代器 $O(logN)
注意:用find函数来定位数据出现位置,它返回一个迭代器。当数据存在时,返回数据所在位置的迭代器,数据不存在时,返回mp.end()
mp.erase(it) 删除迭代器对应的键和值O(1)
mp.erase(key) 根据映射的键删除键和值 O(logN)
mp.erase(first,last) 删除左闭右开区间迭代器对应的键和值 O(last-first)
mp.size() 返回映射的对数$ O(1)$ mp.clear() 清空map中的所有元素O(N)
mp.insert() 插入元素,插入时要构造键值对
mp.empty() 如果map为空,返回true,否则返回false
mp.begin() 返回指向map第一个元素的迭代器(地址)
mp.end() 返回指向map尾部的迭代器(最后一个元素的下一个地址)
mp.rbegin() 返回指向map最后一个元素的迭代器(地址)
mp.rend() 返回指向map第一个元素前面(上一个)的逆向迭代器(地址)
mp.count(key) 查看元素是否存在,因为map中键是唯一的,所以存在返回1,不存在返回0
mp.lower_bound() 返回一个迭代器,指向键值>= key的第一个元素
mp.upper_bound() 返回一个迭代器,指向键值> key的第一个元素
*/
}
void test03(){
map<int,int> mp;
mp[1] = 2;
mp[2] = 3;
mp[3] = 4;
map<int,int>::iterator it = mp.begin();
while(it != mp.end()) {
cout << it->first << " " << it->second << "\n";
it ++;
}
cout<<"******"<<endl;
map<int,int> mp1;
mp1[1] = 2;
mp1[2] = 3;
mp1[3] = 4;
map<int,int>::reverse_iterator it1 = mp1.rbegin();
while(it1 != mp1.rend()) {
cout << it1->first << " " << it1->second << "\n";
it1 ++;
}
}
void test04(){
map<int, int> m;
m.insert(make_pair(1, 2));
m.insert(make_pair(2, 2));
m.insert(make_pair(1, 2));
m.insert(make_pair(8, 2));
m.insert(make_pair(6, 2));
map<int, int>::iterator it1 = m.lower_bound(2);
cout << it1->first << "\n";//it1->first=2
map<int, int>::iterator it2 = m.upper_bound(2);
cout << it2->first << "\n";//it2->first=6
//?? 为什么不是8
cout<<"***"<<endl;
map<int,int>::iterator it = m.begin();
while(it != m.end()) {
cout << it->first << " " << it->second << "\n";
it ++;
}
}
int main()
{
cout<<"test01():"<<endl;
test01();
cout<<"************"<<endl;
cout<<"test02():"<<endl;
test02();
cout<<"************"<<endl;
cout<<"test03():"<<endl;
test03();
cout<<"************"<<endl;
cout<<"test04():"<<endl;
test04();
return 0;
}
算法设计例题
例题一:(容器vector)快递的分拣
样例:
输入:
10
10124214 北京
12421565 上海
sdafasdg213 天津
fasdfga124 北京
145252 上海
235wtdfsg 济南
3242356fgdfsg 成都
23423 武汉
23423565f 沈阳
1245dfwfs 成都
输出:
北京 2
10124214
fasdfga124
上海 2
12421565
145252
天津 1
sdafasdg213
济南 1
235wtdfsg
成都 2
3242356fgdfsg
1245dfwfs
武汉 1
23423
沈阳 1
23423565f
题解:
//1. 创建有个vector容器 用来保存地址
vector<string> city;
//2. 再创建一个 用来保存快递单号
vector<string> dig[1000];
//3. 定义一个映射函数,因为城市可能会再次出现,我们需要知道之前有没有。
//4. 读入操作并按照顺序进行存放
题解示例:
#include<iostream>
#include<vector>
using namespace std;
//创建有个vector容器 用来保存地址
vector<string> city;
//再创建一个 用来保存快递单号
vector<string> dig[1000];
int Myfind(string s){
//寻找到该城市的位置 下标
for(int i=0;i<city.size();i++)
{
if(city[i]==s) return i;
}
return -1;
}
int main()
{
int n;
cin>>n;//输入有几个快递
for(int i=0;i<n;i++)
{
string d,c;
cin>>d>>c;///输入快递单号 和 快递地址
int flag=Myfind(c);//输出该地址的位置
if(flag==-1){//如果没找到这个地址
city.push_back(c);//把这个城市添加到city这个容器中
dig[city.size()-1].push_back(d);//在对应位置的数值后添加 快递单号
}
else dig[flag].push_back(d);//在对应位置的数值后添加 快递单号
}
for(int i=0;i<city.size();i++)
{
cout<<city[i]<<" "<<dig[i].size()<<endl;
for(int j=0;j<dig[i].size();j++)
cout<<dig[i][j]<<endl;
}
}
例题二:(queue)银行排队问题
输入样例:
5
IN xiaoming N
IN Adel V
IN laozhao N
OUT N
IN CLZ V
输出样例:
Adel
CLZ
laozhao
题解:
#include <iostream>
#include <queue>
using namespace std;
queue<string> V; // VIP队列
queue<string> N; // 普通队列
int main()
{
int M;
cin >> M; // 输入操作的次数
while (M--) // 每次进行一个操作
{
string op, name, type;
cin >> op; // 读入 进入还是出去
if (op == "IN")
{
cin >> name >> type; // 读取名字 和 类型
if (type == "V")
V.push(name); // 如果是VIP类型,加入VIP队列
else
N.push(name); // 否则加入普通队列
}
else
{
cin >> type; // 读取类型
if (type == "V")
V.pop(); // 如果是VIP类型,从VIP队列出队
else
N.pop(); // 否则从普通队列出队
}
}
// 打印结果
while (V.size())
{
cout << V.front() << endl; // 输出VIP队列中的元素
V.pop(); // 出队
}
while (N.size())
{
cout << N.front() << endl; // 输出普通队列中的元素
N.pop(); // 出队
}
return 0;
}
例题三:(map)重复的单词
输入样例:
5
sdfggfds
fgsdhsdf
dsfhsdhr
sdfhdfh
sdfggfds
输出
sdfggfds
题解:文章来源:https://www.toymoban.com/news/detail-850956.html
#include <iostream>
#include <map>
using namespace std;
map<string,bool> mp;
int main ()
{
int n;
string ans="NO";
cin>>n;
for(int i=0;i<n;i++)
{
string word;
cin>>word;
if(mp.count(word)){
ans=word;
break;
}
else mp[word]=1;
}
cout<<ans<<endl;
}
感谢阅读!!!
更多算法例题链接: 【数据结构与算法】递推法和递归法解题(递归递推算法典型例题)文章来源地址https://www.toymoban.com/news/detail-850956.html
到了这里,关于【数据结构与算法】C++的STL模板(迭代器iterator、容器vector、队列queue、集合set、映射map)以及算法例题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!