vector的定义和特性
是一个动态数组容器,可以存储一系列相同类型的元素。
- 大小:自动调整大小。
- 元素访问:通过索引来访问元素,索引从0开始,最后一个元素的索引是size()-1。
可以使用【】运算符或at()函数来访问元素。
- 元素添加和删除:可以是使用push_back()函数在vector的末尾添加元素,使用pop_back()函数检查vector是否为空,还可以使用resize()函数调整vector()的大小。
- 迭代器:vector使用了迭代器,可以用于遍历容器中的元素,可以使用begin()函数获得一个元素的迭代器,使用end()函数获取指向最后一个元素之后位置的迭代器。
- 常用函数;
-
push_back()函数:将元素添加到vector的末尾
-
pop_back():删除vector末尾的元素,(注:要保证vector非空)
-
begin和end():指向第一个元素和最后一个元素。
-
vector的排序去重:
-
sort函数排序(从小到大)
-
去重:unique函数。具体做法:将 重复的元素移动到vector的末尾,并返回第一个指向重复元素的迭代器。最后,可以使用vec.erase函数将重复元素从vector中删除。
-
stack
在C++中,stack(堆栈)主要用于实现LIFO(后进先出)的数据结构。它通常用于存储和管理具有特定顺序要求的元素,如函数调用的参数、局部变量和返回地址等。当需要对数据进行先进后出的操作时,可以使用stack容器。
-
stack的定义和结构:
template <class T,class Container=deque<T>> class stack;
-
stack的常用函数:
函数
描述
时间复杂度
push()
在栈顶插入元素x
O(1)
pop()
弹出栈顶元素
O(1)
top()
返回栈顶元素
O(1)
empty()
检查栈是否为空
(返回值为bool类型)
O(1)
size()
返回栈中元素的个数
O(1)
#include<bits/stdc++.h> using namespace std; int main() { //定义stack容器 stack<int>myStack; //向栈中插入元素 myStack.push(10); myStack.push(20); myStack.push(30); myStack.push(40); //获取栈顶元素 cout<<"栈顶元素是:"<<myStack.top()<<endl; //弹出栈顶元素 myStack.pop(); cout<<"弹出栈顶元素后,栈顶元素是:"<<myStack.top() <<endl; //检查栈是否为空 if(myStack.empty()) cout<<"栈顶为空"<<endl; else cout<<"栈不为空"<<endl; //获取栈的大小 cout<<"栈的大小:"<<myStack.size()<<endl; return 0; }
-
注:stack是不能遍历的。
-
如果将一个数组中的元素依次放入栈,再依次取出,则可以将数组翻转。
-
Set
C++中的set主要用于需要去重并按升序排序的情况。 set是一个内部自动有序且不含重复元素的容器,它的主要作用是自动去重并按升序排序。在需要去除重复元素的场景中,如用户ID列表、书籍ISBN号集合等,set是一个理想的选择。
以下是set的一些主要使用场景:
去重数据集:当需要存储不重复的元素时,如统计唯一访问者IP、唯一关键词等,可以使用set来自动去重。
构建有序元素集:如果需要保持数据的唯一性且有序,例如排序后的数组或列表,set可以提供一个有序的环境,方便数据操作和分析。
支持快速查找操作:set基于红黑树实现,可以在O(logN)的时间复杂度下进行插入、删除和查找操作,适合需要快速查找的场景。
-
格式:
template <class key,class Compare=less<key>, class Allocator=allocator<key>> class set;
-
set集合:
-
如何实现由大到小排列呢?
、、1
#include<bits/stdc++.h>
using namespace std;
int main()
{
set<int,greater<int>> mySet;
mySet.insert(25);
mySet.insert(17);
mySet.insert(39);
mySet.insert(42);
cout<<"排序後的列表是:"<<endl;
for(const auto& elem:mySet)
{
cout<<elem<<" ";
}
cout<<endl;
return 0;
}
。。2
#include<bits/stdc++.h>
using namespace std;
struct MyCompare{
bool operator()(const int& a,const int& b)const{
return a>b;}
};
int main()
{
set<int,MyCompare> mySet;
mySet.insert(25);
mySet.insert(17);
mySet.insert(39);
mySet.insert(42);
cout<<"排序後的列表是:"<<endl;
for(const auto& elem:mySet)
{
cout<<elem<<" ";
}
cout<<endl;
return 0;
}
-
multiset多重集合
st={x,x,x,y,z} st.erase(st.find(x))//删除的是第一个x
-
主要区别:允许存储重复的元素。
-
其中lower_bound()和upper_bound()一般与它组合使用。
-
erase删除的是全部的重复元素,如果只删除一个的情况可以考虑使用迭代器
-
-
unodered_set无序集合
-
在set的基础上破坏掉顺序。
-
底层逻辑是hash。
-
功能更少。如insert,erase,find,count
-
-
操作集合:
#include<bits/stdc++.h>
using namespace std;
int main()
{
set<int> mySet;
mySet.insert(25);
mySet.insert(17);
mySet.insert(39);
mySet.insert(39);
mySet.insert(42);
cout<<"排序後的列表是:"<<endl;
for(const auto& elem:mySet)
{
cout<<elem<<" ";
}
cout<<endl;
//查找元素
int setsearch=17;
auto it=mySet.find(setsearch);//auto表示自動類型推導
if(it!=mySet.end())
cout<<setsearch<<"找到啦"<<endl;
else
cout<<"沒有找到"<<endl;
//移除元素
int remove_set=39;
mySet.erase(remove_set);
//再次輸出
for(auto &elem:mySet)
{
cout<<elem<<" ";
}
cout<<endl;
//清空集合
mySet.clear();
//檢查集合是否為空
if(mySet.empty())
cout<<"清空後集合為空"<<endl;
else
cout<<"清空后集合不為空"<<endl;
return 0;
}
Queue(队列)
队列是一种特殊类型的线性数据结构,它拥有两个端点:队头和队尾。在队列中,新元素总是被添加到队尾,而移除操作则发生在队头。这种结构保证了元素的加入和移除顺序,从而实现了先进先出的管理方式。
C++标准库中的
std::queue
是一个容器适配器,它提供了一组操作来支持队列的基本功能,如push
(入队)、pop
(出队)、front
(访问队头元素)和back
(访问队尾元素)等。由于std::queue
是一个模板类,它可以与任何类型的数据一起工作,这使得它在处理各种数据类型时非常灵活。
-
常用函数:
-
push()在队尾插入元素
-
pop()弹出队首元素
-
front()返回队首的元素
-
back()返回队尾元素
-
empty()检查队列是否为空
-
size()返回队列中元素的个数
-
-
priority_queue优先队列
元素排列顺序不确定,主要是靠优先级来处理。其中top是最大的,其余元素的大小关系不关心。
template <class key,class Container=vector<key>, class Compare=less<typename Container::value_type>> class priority_queue;
-
格式
-
-
如何改成小根堆:
//仿函数 struct Compare{ bool operator()(int a,int b) { return a>b; } }; int main() { priority_queue<int,vector<int>,Compare> pq;//pq定義的優先隊列變量的名稱 }
-
//定义比较函数 auto compare=[](int a,int b) { return a>b; } ; priority_queue<int,vector<int>,decltype(compare)> pq(compare);//decltype用於查詢表達式的類型
-
deque双端队列
主要区别就是两端都能进能出。
template <class key, class Allocator=allocator<key>> class deque;
-
格式
-
函数中增加的部分:push_back()和pop_front(),即,可对两端进行操作。
-
-
两道例题:
CLZ银行只有两个接待窗口,VIP窗口和普通窗口,VIP用户进入
VIP窗口排队,剩下的进入普通窗口排队。现有M次操作,操作有四种类
型,如下:
·IN name V:表示一名叫name的用户到VIP窗口排邦队
·ouTV:表示VIP窗口队头的用户离开排邦队
·IN name N:表示一名叫name的用户到普通窗口排队
·OUTN:表示普通窗口队头的用户离开排队
求M次操作结束后VIP窗口队列和普通窗口队列中的姓名。
#include<bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int m;cin>>m;
queue<string>V,N;
while(m--)
{
string a;cin>>a;
if(a=="IN")
{
string b,c;cin>>b>>c;
if(c=="V")V.push(b);
else N.push(b);
}
else
{
string d;cin>>d;
if(d=="V")V.pop();
else N.pop();
}
}
//輸出(雖然是按需輸出,但是不是遍曆)
while(V.size())
{
cout<<V.front()<<"\n";
V.pop();
}
while(N.size())
{
cout<<N.front()<<"\n";
N.pop();
}
}
每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过几一1次合并之后,就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int m;cin>>m;
priority_queue<ll,vector<ll>,greater<ll>>pq;//greator把默認的大根堆修改為小根堆
for(int i=0;i<m;i++)
{
ll x;
cin>>x;
pq.push(x);
}
ll ans=0;
while(pq.size()>=2)
{
ll x=pq.top();pq.pop();
ll y=pq.top();pq.pop();
ans+=x+y;
pq.push(x+y);
}
cout<<ans;
}
Pair
-
定义
-
表示一对值的组合。
-
结构:
template<class T1,class T2> struct pair{ T1 first; T2 second; //構造函數 pair(); pair(const T1& x,const T2& y); //比較運算符重載 bool operator==(const pair& rhs)const; bool operator!=(const pair& rhs)const; };
-
使用实例:
#include<bits/stdc++.h> using namespace std; int main() { pair<int,double> p1(1,3.14); pair<char,string> p2('a',"hello"); cout<<p1.first<<","<<p1.second<<endl; cout<<p2.first<<","<<p2.second<<endl; return 0; }
-
-
pair的嵌套
-
例子:三维坐标
-
#include<bits/stdc++.h> using namespace std; int main() { pair<int,pair<int,int>> p1(3,make_pair(4,5)); cout<<p1.first<<","<<p1.second.first<<","<<p1.second.second<<endl; return 0; }
-
-
pair自带的排序规则
-
例子:三个二维坐标的排序
#include<bits/stdc++.h> using namespace std; int main() { vector<pair<int,int>>vec; vec.push_back(make_pair(3,2)); vec.push_back(make_pair(1,4)); vec.push_back(make_pair(2,5)); sort(vec.begin(),vec.end()); for(const auto& p:vec) { cout<<p.first<<","<<p.second<<endl; } return 0; }
-
结果为:
1,4
2,5
3,2(产生原因:按照first优先排列)
#include<bits/stdc++.h>
using namespace std;
struct person{
string name;
int age;
};
int main()
{
vector<person>people;
people.push_back({"Alice",25});
people.push_back({"Bob",29});
people.push_back({"Charlie",30});
//創建一個pair向量,每一個pair裡面包括一個person對象和一個評分
vector<pair<person,int>>scores;
//添加數據
scores.push_back({people[0],90});
scores.push_back({people[1],85});
scores.push_back({people[2],95});
//遍歷pair向量
for(const auto& p:scores)
{
cout<<"Name:"<<p.first.name<<endl;
cout<<"Age:"<<p.first.age<<endl;
cout<<"Scores:"<<p.second<<endl;
cout<<endl;
}
return 0;
}
Map
-
map:是一种关联容器,用来存放一组键值对,按照键来自动进行排序。
-
multimap()可以存储重复的键值对。
-
count函数:有意义,不像map中只能返回0和1.
-
-
unordered_map
-
无序,底层哈希函数。
-
平均复杂度极好。
-
-
代码示例:
#include<bits/stdc++.h>
using namespace std;
int main()
{
//創建併初始化
map<int,string> mymap={{1,"apple"},{2,"banana"},{3,"orange"}};
//插入元素
mymap.insert(make_pair(4,"grapes"));
//也可以使用
//mymap.insert({4,"grapes"});
//查找和訪問元素
cout<<"Value at key 2:"<<mymap[2]<<endl;
//遍歷並打印map中的元素
for(const auto& pair:mymap)
{
cout<<pair.first<<","<<pair.second<<endl;
}
//刪除元素
mymap.erase(3);
//判斷元素是否存在
if(mymap.count(3)==0)
cout<<"刪除成功"<<endl;
else
cout<<"刪除失敗"<<endl;
//清空
mymap.clear();
//判斷是否為空
if(mymap.empty())
cout<<"空"<<endl;
else
cout<<"不空"<<endl;
return 0;
}
-
multimap查找元素时不能用方括号:
auto range=mymultimap.equal_range(2);
for(auto it=range.first;it!=range.second;it++)
{
cout<<it->first<<","<<it->second<<endl;
}
-
unordered_map遍历时也是没有顺序的。
List
list是双向链表容器,以节点的形式存储元素,并使用指针将这些节点链接。
好处是内存不连续。
特点:
-
双向性:每一个节点都有前一个和下一个的指针,以常数时间内对任意位置数据进行操作。
-
动态大小
-
使用:
#include<bits/stdc++.h>
using namespace std;
int main()
{
list<int>mylist;
mylist.push_back(1);
mylist.push_back(2);
mylist.push_back(3);
//在鏈錶頭部插入元素
mylist.push_front(0);
//在第一個元素的後一個元素加上元素5
mylist.insert(++mylist.begin(),5);
//將list中的元素翻轉
reverse(mylist.begin(),mylist.end());
for(int num:mylist)
{
cout<<num<<" ";
}
cout<<endl;
//按區間刪除
mylist.erase(++ ++mylist.begin(),--mylist.end()) ;
cout<<"此時鏈錶的大小為:"<<mylist.size()<<endl;
//要注意:size返回uint類型,(int)size-1才行
return 0;
}
-
list常用函数:
总结
-
考查sort函数--3226宝藏排序2
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+9;
int a[N];
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)
{
cout<<a[i]<<' ';
}
return 0;
}
-
小兰吃糖果:
我感觉我的智商按在地上摩擦。想得太复杂,其实优先队列就可以解决。。。
#include<bits/stdc++.h>
using ll=long long;
using namespace std;
const int N=1e5+9;
int a[N];
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n;cin>>n;
priority_queue<int>pq;
ll sum=0;
for(int i=1;i<=n;i++)
{
int x;cin>>x;
pq.push(x);
sum+=x;
}
ll mx=pq.top();
if(sum-mx>=mx-1)
cout<<"Yes"<<'\n';
else
cout<<"No"<<'\n';
return 0;
}
甚至可以直接用变量
#include<bits/stdc++.h>
using ll=long long;
using namespace std;
const int N=1e5+9;
int a[N];
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n;cin>>n;
ll sum=0;
ll mx=0;
for(int i=1;i<=n;i++)
{
ll x;cin>>x;
mx=max(mx,x);
sum+=x;
}
if(sum-mx>=mx-1)
cout<<"Yes"<<'\n';
else
cout<<"No"<<'\n';
return 0;
}
-
小兰的字符串()--考查stack
我的想法:左括号和右括号的数量相同,通过率只有80%。遗漏的问题是没有考虑左右括号的顺序问题。所以这道题的最佳选择用栈。
遇到左括号入栈,遇到右括号出栈(配对)。
#include<bits/stdc++.h>
using namespace std;
const int N=105;
stack<char>stk;
char s[N];
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n;cin>>n;
cin>>s+1;
bool ans=true;
for(int i=1;i<=n;i++)
{
if(s[i]=='(')stk.push('(');
else
{
if(stk.size()&&stk.top()=='(' )stk.pop();
else ans=false;
}
}
if(stk.size())ans=false;//如果stk里面还有元素也不合法
cout<<(ans?"Yes": "No")<<'\n';
return 0;
}
-
快递分拣--map,string,vector的综合应用
#include<bits/stdc++.h>
using namespace std;
map<string,vector<string>>mp;
vector<string>citys;//存储城市的顺序
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n;cin>>n;
for(int i=1;i<=n;i++)
{
string a,b;cin>>a>>b;
if(!mp.count(b))citys.push_back(b);//如果b是没有出现过的城市,加入citys
mp[b].push_back(a);//把单号加入进去
}
for(const auto&city:citys)
{
cout<<city<<' '<<mp[city].size()<<'\n';//统计城市下的单号个数
for(const auto&i:mp[city])
{
cout<<i<<'\n';
}
}
return 0;
}
-
小明的完美序列--数字的值等于数字的个数
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+9;
map<int,vector<int>>a;
set<int>nums;
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n;cin>>n;
for(int i=1;i<=n;i++)
{
int x;cin>>x;
a[x].push_back(x);
nums.insert(x);
}
int ans=0;
for(const auto&num:nums)
{
if(a[num].size() != num)//不相符
{
int z=a[num].size();
while(1)
{
z--;
ans++;
if(z==num)break;// 减少到相符
else if(z==0)break;//直接减少到0
}
}
}
cout<<ans<<endl;
return 0;
}