栈
stack是一种先进后出(First
In Last Out, FILO)的数据结构,它只有一个出口,只能操作最顶端元素。
头文件: stack
定义:stack<data_type> stack_name;
如: s t a c k < i n t > s stack <int> s stack<int>s;
操作:
empty()-- 返回bool型,表示栈内是否为空 s.empty()
size()-- 返回栈内元素个数 s.size()
top()-- 返回栈顶元素值 s.top()
pop()-- 移除栈顶元素 s.pop();
push(data_typea) – 向栈压入一个元素a s.push(a);
#include <iostream>
#include <stack>
using namespace std;
int main(void)
{
stack<int>s; //声明存储int类型数据的栈
s.push(1); //{} -> {1}
s.push(2); //{1} -> {1,2}
s.push(3); //{1,2} -> {1,2,3}
printf("%d\n",s.top());//3
s.pop(); //从栈顶移除{1,2,3} -> {1,2}
printf("%d\n",s.top());//2
s.pop(); //{1,2} -> {1}
printf("%d\n",s.top());//1
s.pop(); //{1} -> {}
return 0;
}
队列
queue是一种先进先出(First In First Out, FIFO)的数据结构,从底端加入元素,从顶端取出元素
头文件: queue
定义:queue <data_type> queue_name;
如: q u e u e < i n t > q queue <int> q queue<int>q;
操作:
empty()-- 返回bool型,表示queue是否为空 (q.empty() )
size()-- 返回queue内元素个数 (q.size() )
front()-- 返回queue内的下一个元素 (q.front() )
back()-- 返回queue内的最后一个元素(q.back() )
pop()-- 移除queue中的一个元素(q.pop(); )
push(data_type a) – 将一个元素a置入queue中(q.push(a); )
//队列
#include <iostream>
#include <queue>
using namespace std;
int main(void)
{
queue<int> q; //声明存储int类型数据的队列
q.push(1); //{} -> {1}
q.push(2); //{1} -> {1,2}
q.push(3); //{1,2} -> {1,2,3}
printf("%d\n",q.front());//1
q.pop(); //从队尾移除 {1,2,3} -> {2,3}
printf("%d\n",q.front());//2
q.pop(); //{2,3} -> {3}
printf("%d\n",q.front());//3
q.pop(); //{3} -> {}
return 0;
}
向量(vector)
向量的内部实现是一个链表。
头文件: vector
定义:vector <data_type> vector_name;
如: v e c t o r < i n t > v vector <int> v vector<int>v;
操作:
1.empty()-- 返回bool型,表示vector是否为空 (v.empty() ) 2.size()-- 返回vector内元素个数 (v.size() )
3.push_back(data_type a) 将元素a插入最尾端
4.pop_back()将最尾端元素删除
5.v[i]类似数组取第i个位置的元素
6.a.clear() //清空向量中的元素
7.复制 a = b ; //将b向量复制到a向量中
8.删除 - erase
b.erase(b.begin()) ; //将起始位置的元素删除
a.erase(a.begin()+5);//删除链表元素a[5];
b.erase(b.begin(), b.begin()+3) ; //将(b.begin(), b.begin()+3) 之间的元素删除
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
vector<int> a;
for (int i = 0; i < 5; ++i)
{
a.push_back(5 - i);
}
cout << "Size: " << a.size() << endl;
a.pop_back();
a[0] = 1;
cout << "Size: " << a.size() << endl;
for (int i = 0; i < (int)a.size(); ++i)
{
cout << a[i] << ", " << endl;
}
cout << endl;
return 0;
}
因为向量的内部实现是一个链表,我们在push_back数据的时候,内部其实是在往链表上加节点,所以我们不能在任何位置直接以a[5]=10的方式加入元素,但是如果实在想这样的话也没关系。我们就预先建立一个长度为6的链表(因为vector是从0开始的)如下:
vector<int>a(10,0);//建立了一个初始长度为10,初始值为0的链表。
这样我们就可以以这样的方式向vector中加入元素
a[5]=10;
或者
cin>>a[5];
这样类似于建立一个数组,但是与数组不同的是我们可以超过初始的长度加入元素。使链表的长度再增长。
a.push_back(4);
可以自己检验一下
#include <bits/stdc++.h>
using namespace std;
int main()
{
vector<int>a(6,0);
a[5]=10;
for(int i=0; i<a.size(); i++)
cout<<a[i]<<" ";
a.push_back(4);
cout<<endl;
for(int i=0; i<a.size(); i++)
cout<<a[i]<<" ";
return 0;
}
向量数组特别常用,定义方式如下:
vector<int>a[10];
优先队列:priority_queue
一个拥有权值观念的queue,自动依照元素的权值排列,权值最高排在前面。缺省情况下,priority_queue是利用一个max_heap完成的
头文件: queue
定义:priority_queue<Type, Container, Functional>Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector),Functional 就是比较的方式,当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆
一般是:
升序队列
priority_queue <int,vector<int>,greater<int> > q;
降序队列
priority_queue <int,vector<int>,less<int> >q;
greater和less是std实现的两个仿函数
(就是使一个类的使用看上去像一个函数。其实现就是类中实现
一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了)
操作:
q.push(elem)将元素elem置入优先队列
q.top()返回优先队列的下一个元素
q.pop()移除一个元素
q.size()返回队列中元素的个数
q.empty()返回优先队列是否为空
#include <bits/stdc++.h>
using namespace std;
int main()
{
priority_queue<int,vector<int>,greater<int> >a;
int b[10]={1,4,6,7,8,23,4,24,5,43};
for(int i=0;i<=9;i++)
{
a.push(b[i]);
}
while(!a.empty())
{
cout<<a.top()<<" ";
a.pop();
}
}
upper_bound 和 lower_bound
lower_bound( )和upper_bound( )都是利用二分查找的方法在一个排好序的数组中进行查找的。
在从小到大的排序数组中
lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
在从大到小的排序数组中,重载lower_bound()和upper_bound()
lower_bound( begin,end,num,greater< type>() ):从数组的begin位置到end-1位置二分查找第一个小于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num,greater< type>() ):从数组的begin位置到end-1位置二分查找第一个小于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
#include <algorithm>
#include <vector>
using namespace std;
int main(){
int a[10] = {1,3,5,2,4,6,7,5,2,5};
sort(a, a + 10);
for (int i = 0; i < 10; ++i) cout<<a[i]<<" ";
cout<<endl;
int *s, *e;
s= lower_bound(a, a + 10, 5);
e= upper_bound(a, a + 10, 5);
cout<<e-s<<endl; //此处输出的是5的个数
while(s!= e){
cout<<*s++<<" ";
}
cout<<endl;
cout<<*e<<endl;
return 0;
}
set和multiset
set 和 multiset会根据特定的排序准则,自动将元素排序,两者的不同之处在于multiset可以允许元素重复而set不允许元素重复。
头文件: set
定义:set <data_type> set_name;
如:set s;//默认由小到大排序
如果想按照自己的方式排序,可以重载小于号。
struct new_type{
int x, y;
bool operator < (const new_type &a)const{
if(x!= a.x) return x < a.x;
return y < a.y;
}
}
set<new_type> s;
操作:
s.insert(elem) – 安插一个elem副本,返回新元素位置。
s.erase(elem) – 移除与elem元素相等的所有元素,返回被移除 的元素个数。
s.erase(pos) – 移除迭代器pos所指位置上的元素,无返回值。
s.clear() – 移除全部元素,将整个容器清空
s.size() – 返回容器大小。
s.empty() – 返回容器是否为空。
s.count(elem) – 返回元素值为elem的元素的个数。
s.lower_bound(elem) – 返回 元素值>= elem的第一个元素位置。
s.upper_bound(elem) – 返回元素值 > elem的第一个元素的位置。
以上位置均为一个迭代器。
s.begin() – 返回一个双向迭代器,指向第一个元素。
s.end() – 返回一个双向迭代器,指向最后一个元素的下一 个位置
#include <iostream>
#include <set>
#include <algorithm>
using namespace std;
int main(){
set<string>s1;
set<string>::iterator iter1;
s1.insert("abc");
s1.insert("abc");
s1.insert("abc");
s1.insert("bca");
s1.insert("aaa");
cout << "ITERATE:" << endl;
for (iter1 = s1.begin(); iter1 != s1.end(); iter1++){
cout << (*iter1) << endl;
}
cout<< "FIND:" << endl;
iter1 = s1.find("abc");
if(iter1 != s1.end()) {
cout << *iter1 << endl;
}else{
cout << "NOT FOUND" << endl;
}
return 0;
}
#include <iostream>
#include <set>
#include <algorithm>
using namespace std;
struct T1{
int key;
int value1, value2;
bool operator<(const T1 &b)const{
return (key < b.key);
}
};
int main(){
set<T1> s;
set<T1>::iterator iter1;
T1 t={2,33,44};
T1 tt;
tt.key=5;
tt.value1=22;
tt.value2=88;
s.insert(t);
s.insert(tt);
cout << "ITERATE:" <<endl;
for (iter1 = s.begin(); iter1 != s.end(); iter1++){
cout << (*iter1) .key<<" "<<(*iter1).value1<<" "<< (*iter1).value2<<endl;
}
cout << "FIND:" << endl;
iter1 = s.find(t);
if(iter1 != s.end()) {
cout << (*iter1) .key<<" "<<(*iter1).value1<<" "<< (*iter1).value2<<endl;
}
else{
cout << "NOT FOUND"<<endl;
}
return 0;
}
map和multimap
1、map简介
所有元素都会根据元素的键值自动排序,map的所有元素都是pair,pair的第一个元素被视为键值,第二个元素为实值。map不允许两个元素有相同的键值,但multimap可以
map是一类关联式容器。它的特点是增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响。
对于迭代器来说,可以修改实值,而不能修改key。
2、map的功能
自动建立Key - value的对应。key 和 value可以是任意你需要的类型。
根据key值快速查找记录,查找的复杂度基本是Log(N),如果有1000个记录,最多查找10次,1,000,000个记录,最多查找20次。
快速插入Key -Value 记录。
快速删除记录
根据Key 修改value记录。
遍历所有记录。
头文件:map
定义:map <data_type1, data_type2>map_name;
如:map <string, int> m;//默认按string由小到大排序
操作:
m.begin() 返回一个双向迭代器,指向第一个元素。
m.end() 返回一个双向迭代器,指向最后一个元素的下一个 位置。
m.clear() 讲整个容器清空。
m.erase(elem) 移除键值为elem的所有元素,返回个数,对 于map来说非0即1。
m.erase(pos) 移除迭代器pos所指位置上的元素。
直接元素存取:m[key]= value;
查找的时候如果没有键值为key的元素,则安插一个键值为key的新元素,实值为默认(一般0)。
m.insert(elem) 插入一个元素elem
a)运用value_type插入
map<string,float> m;
m.insert(map<string,float>:: value_type (“Robin”, 22.3));
b)运用pair<>
m.insert(pair<string,float>(“Robin”, 22.3));
c)运用make_pair()
m.insert(make_pair(“Robin”,22.3));
#include <iostream>
#include <map>
#include <algorithm>
using namespace std;
int main(){
map<string, int> m2;
map<string, int>::iterator m2i, p1, p2;
m2["abd"] = 2;
m2["abc"] = 1;
m2["cba"] = 2;
m2.insert(make_pair("aaa", 9));
m2["abf"] = 4;
m2["abe"] = 2;
cout << m2["abc"] << endl;
m2i = m2.find("cba");
if(m2i != m2.end())
cout << m2i->first << ": " <<m2i->second << endl;
else
cout << "find nothing" << endl;
cout<< "Iterate" << endl;
for(m2i = m2.begin(); m2i != m2.end(); m2i++)
cout << m2i->first << ": " <<m2i->second << endl;
return 0;
}
sort
sort默认从小到大排序
头文件: algorithm
sort(begin, end);
sort(begin, end, cmp);
cmp是自定义的排序方式
bool cmp(int a, int b){
return a > b;
}
//对动态数组进行排序
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
int main()
{
int a[10];
vector <int> b;
for(int i=0;i<5;i++)
{
cin>>a[i];
b.push_back(a[i]);
}
sort(a,a+5);
sort(b.begin(),b.end());
for(int i=0;i<5;i++)
cout<<a[i]<<" ";
cout<<endl;
for(int i=0;i<5;i++)
cout<<b[i]<<" ";
return 0;
}
//对结构体进行排序
#include<bits/stdc++.h>
using namespace std;
struct sd
{
int x,y;
}a[123461];
bool cmp(sd a,sd b)
{
return a.y<b.y;//升序排列;a>b为降序排列;
}
int main()
{
int m,n,t;
while(cin>>t)
{
for(int i=0;i<t;i++)
cin>>a[i].x>> a[i].y;
sort(a,a+t,cmp);
for(int i=0;i<t;i++)
cout<<a[i].x<<" "<< a[i].y <<endl;
}
}