文章目录
- 关于仿函数
- stack
- deque(双端对列)
- queue
- priority_queue
- map(重点)
- set(去重)
关于仿函数
//C++不能重载的运算符sizeof、 ::、 ? :、 .、 *、
class Add
{
public:
int operator()(int a, int b)const
{
return a + b;
}
};
//函数对象,仿函数,函子
int main()
{
Add add;
int x = 10, y = 20, z = 30;
z = add(x, y); //C++11
z = add.operator()(x, y); //重载了括号调用
cout << z << endl;
}
template<class _Ty>
class Add
{
public:
_Ty operator()(const _Ty& a, const _Ty& b)const
{
return a + b;
}
};
int main()
{
Add<int>iadd;
Add<double>dadd;
int x = 10, y = 20, z = 0;
z = Add<int>()(x, y); //Add<int>():类型名+() 创建了不具名对象(右值)
z = Add<int>().operator()(x, y); //仿函数
return 0;
}
int main()
{
std::vector<int>ar = { 1,4,5,6,7,8,3,2,9,0 };
std::sort(ar.begin(),ar.end(),std::less<int>());
for (auto& x : ar)
{
cout << x << " ";
}
cout << endl;
std::sort(ar.begin(), ar.end(), std::greater<int>()); //仿函数,从大到小排序
for (auto& x : ar)
{
cout << x << " ";
}
cout << endl;
}
struct my_less
{
bool operator()(const _Ty& a, const _Ty& b)const
{
return a < b;
}
};
template<class _Ty>
struct my_greater
{
bool operator()(const _Ty& a, const _Ty& b)const
{
return a > b;
}
};
template<class _BI,class _Fn>
void my_sort(_BI _first, _BI _last,_Fn fn)
{
cout << typeid(_BI).name() << endl;
cout << typeid(_Fn).name()<< endl;
for (_BI i = _first;i != _last; ++i) //插入排序
{
_BI k = i;
for (_BI j = i+1; j!=_last; ++j)
{
if (*k > *j)
{
k = j;
}
}
if (k!= i)
{
std::swap(*k, *i);
}
}
}
int main()
{
std::vector<int>ar = { 1,4,5,6,7,8,3,2,9,0 };
my_sort(ar.begin(), ar.end(),my_less<int>());
//std::sort(ar.begin(),ar.end(),std::less<int>());
for (auto& x : ar)
{
cout << x << " ";
}
cout << endl;
my_sort(ar.begin(), ar.end(),my_greater<int>()); //仿函数,从大到小排序
for (auto& x : ar)
{
cout << x << " ";
}
cout << endl;
}
运行结果:
stack
- 关于栈的返回值:以引用形式返回,以值的形式接受(不能以引用接受,会产生失效引用,或者会修改栈顶的值)
- 默认情况栈的底层实现,双端对列实现
class PtrInt
{
int* ptr;
public:
PtrInt(int x = 0) :ptr(new int(x))
{
cout << "Create PtrInt:" << endl;
}
PtrInt(const PtrInt& pt) :ptr(new int())
{
if (pt.ptr != nullptr)
{
*ptr = *pt.ptr;
}
cout << "Copy Create:" << endl;
}
PtrInt& operator=(const PtrInt& pt)
{
if (this != &pt)
{
delete ptr;
ptr = new int();
if (pt.ptr != nullptr)
{
*ptr = *pt.ptr;
}
cout << "operator=()" << endl;
}
return *this;
}
PtrInt(PtrInt&& pt) :ptr(pt.ptr)
{
pt.ptr = nullptr;
cout << "move create" << endl;
}
PtrInt& operator=(PtrInt&& pt)
{
if (this != &pt)
{
delete ptr;
ptr = pt.ptr;
pt.ptr = nullptr;
}
cout << "move operator=()" << endl;
return *this;
}
~PtrInt()
{
delete ptr;
ptr = nullptr;
cout << "Destory PtrInt" << endl;
}
void SetValue(int x)
{
if (ptr != nullptr)
{
*ptr = x;
}
else
{
ptr = new int(x);
}
}
int GetValue()const
{
if (ptr != nullptr)
{
return *ptr;
}
else
{
return -1;
}
}
void Print()const
{
if (ptr != nullptr)
{
cout << *ptr << endl;
}
}
};
int main()
{
stack<PtrInt>ist;
ist.push(PtrInt(10));
ist.push(PtrInt(20));
ist.push(PtrInt(30));
stack<PtrInt, std::list<PtrInt>>list; //链栈
stack<PtrInt, std::vector<PtrInt>>sqst; //顺序栈
PtrInt &val = ist.top(); //返回值为引用,但是以引用接受,最好以值接受,以引用返回
//为什么以引用的形式返回,因为以值返回会产生将亡值对象
val.Print();
ist.pop();
//val.Print(); //栈顶已经析构掉了,引用失效
return 0;
}
deque(双端对列)
既可以在尾部插入,也可以在头部插入(栈没有迭代器,不能进行迭代)
int main()
{
deque<int>deq;
deq.push_back(12);
deq.push_back(23);
deq.push_front(100);
deq.push_front(120);
for (auto& x : deq)
{
cout << x << endl;
}
}
queue
队列的底层实现可以为双端队列,或者list,但是不允许为vector,因为vector没有pop_front的方法
int main()
{
queue<int, deque<int>>qu;
queue<int, list<int>>lqu;
lqu.push(12);
lqu.push(23);
int x = lqu.front(); //不要拿引用接受
lqu.pop();
cout << x << endl;
//queue<int, std::vector<int>>vqu; //不允许拿vector构建队列
}
priority_queue
int main()
{
std::priority_queue<int,std::vector<int>,greater<int>>qu; //从小到大取元素(小堆序),默认大堆序
qu.push(12);
qu.push(23);
qu.push(8);
qu.push(34);
qu.push(56);
qu.push(3);
while (!qu.empty())
{
int val = qu.top();
qu.pop();
cout << val << endl;
}
}
map(重点)
底层实现(红黑树):关联容器。
template<class T1,class T2>
struct my_pair
{
using first_type = T1; //重命名
using second_type = T2;
first_type first;
second_type second;
};
my_pair<int, string>myp{ 12, "hhh" };
template<class _Key,class _Val>
class my_map
{
using value_type = my_pair<_Key, _Val>;
struct _rbnode
{
value_type data; //data.first=>Key data.second=>Value
};
};
int main()
{
//std::map<int, std::string>ismap;
// key value
//value_type由pair进行重命名
std::map<std::string, int>simap;
//关键码不允许重复
simap.insert(std::map<std::string, int>::value_type("hhh",12));
simap.insert(std::map<std::string, int>::value_type("ppp", 34));
simap.insert(std::map<std::string, int>::value_type("rrr", 56));
simap.insert(std::map<std::string, int>::value_type("www", 23));
simap.insert(std::map<std::string, int>::value_type("aaa", 78));
simap.insert(std::map<std::string, int>::value_type("bbb", 45));
for (auto& x:simap)
{
cout << x.first << " " << x.second << endl;
}
}
int main()
{
using SIMP = std::map<std::string, int>;
using ValType = std::map<std::string, int>::value_type;
SIMP simap;
simap.insert(ValType("hhh", 12));
simap.insert(ValType("www", 23));
simap.insert(ValType("rrr", 34));
simap.insert(ValType("ttt", 21));
simap.insert(ValType("uuu", 6));
simap.insert(ValType("kkk", 10));
for (auto& x : simap)
{
cout << x.first << " " << x.second << endl;
}
std::map<string, int, greater<string>>::iterator ita = simap.begin();
auto it = simap.begin(); //可以直接用auto推导
for (; it != simap.end(); ++it)
{
cout << it->first << " " << it->second << endl;
}
}
at与operator[] 的区别:
at:通过关键码查询值,如果找不到,直接报错
operator[]:通过关键码查询值,如果找不到,则在红黑树中构建一个元素,并且将value的值赋值0
用map统计文件中单词的个数,并进行排序(状态机)
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#include<deque>
#include<queue>
#include<stack>
#include<list>
#include<map>
using namespace std;
#define BEGIN 0
#define IN_WORD 1
#define OUT_WORD 2
int main()
{
FILE* fp = fopen("day0513.cpp", "r");
if (nullptr == fp)exit(EXIT_FAILURE);
int const len = 256;
char str[len] = {};
int tag = BEGIN;
int posi;
std::map<string, int>simap;
while (!feof(fp))
{
fgets(str, 256, fp);
for (int i = 0; str[i] != '\0' && i < len; ++i)
{
switch (tag)
{
case BEGIN:
if (isalpha(str[i]))
{
posi = i;
tag = IN_WORD;
}
else
{
tag = OUT_WORD;
}
break;
case IN_WORD:
if (!isalpha(str[i]))
{
std::string word(&str[posi], i - posi); //i-posi分离出每个单词
//cout << word << endl;
simap[word] += 1;
tag = OUT_WORD;
}
break;
case OUT_WORD:
if (isalpha(str[i]))
{
posi = i;
tag = IN_WORD;
}
break;
}
}
}
fclose(fp);
fp = nullptr;
/*for (auto& x : simap)
{
cout << x.first << " " << x.second << endl;
}*/
std::multimap<int,string>ismap;
for (auto& x :simap)
{
ismap.insert(std::multimap<int, string>::value_type(x.second, x.first));
}
for (auto& x : ismap)
{
cout << x.first << " " << x.second << endl;
}
return 0;
}
关于map的底层
为什么打印出来的数据为:12,23,34,45,56,67 ?
因为底层为中序遍历
unordered_map(底层哈希链表):与map的区别是在于关键码是否有序
map的插入:
int main()
{
std::map<int ,string>age_namemap;
int age;
string name;
while(cin>>age>>name,age>=16||name!="end")
{
age_namemap[age]=name;
age_namemap.insert(std::map<int,string>::value_type(age,name));
age_namemap.insert(pair<const int,string>(age,name));
//age_namemap.insert(age,name);//error
}
}
多重map:允许关键码重复。
find
在map中进行查找,找到则返回该关键码迭代器,未找到则返回simap.end()
int main()
{
std::map<string,int>simap;
simap["aaa"]=20;
simap["bbb"]=21;
simap["ccc"]=22;
std::map<string,int>::iterator it=simap.find("aaa");
//std::map<string,int>::iterator it=simap.find("nnn");
if(it!=simap.end())
{
cout<<it->first<<" "<<it->second<<endl;
}
else
{
cout<<"no key"<<endl;
}
return 0;
}
equal_range
- 返回容器中所有拥有给定关键元素的范围
- 范围以第二个迭代器定义
- 一个指向首个不小于key的元素
- 另一个指向首个大于key的元素
- 首个迭代器可以换用lower_bound()获得
- 而第二个迭代器可以换用upper_bound()获得
int main()
{
std::map<int ,std::string>ismap;
ismap[12]="hhh";
ismap[34]="ttt";
ismap[23]="qqq";
ismap[67]="zzz";
ismap[45]="ddd";
ismap[56]="aaa";
auto it=ismap.equal_range(45);
auto Lt=ismap.lower_bound(45);
auto Rt=ismap.upper_bound(45);
auto p=ismap.begin();
for(;p!=ismap.begin();++p)
{
cout<<p->first<<endl;
}
}
multimap多重map(底层红黑树)
int main()
{
std::multimap<int,std::string>ismap;
ismap.insert(std::multimap<int,std::string>::value_type(18,"aaa"));
ismap.insert(std::multimap<int,std::string>::value_type(20,"bbb"));
ismap.insert(std::multimap<int,std::string>::value_type(18,"ccc"));
ismap.insert(std::multimap<int,std::string>::value_type(21,"ddd"));
ismap.insert(std::multimap<int,std::string>::value_type(34,"eee"));
ismap.insert(std::multimap<int,std::string>::value_type(23,"fff"));
ismap.insert(std::multimap<int,std::string>::value_type(23,"ggg"));
ismap.insert(std::multimap<int,std::string>::value_type(22,"hhh"));
ismap.insert(std::multimap<int,std::string>::value_type(26,"mmm"));
auto it=ismap.equal_range(18);
for(auto p=it.first;p!=it.second;++p)
{
cout<<p->first<<"---->"<<p->second<<endl;
}
}
set(去重)
set:底层也是红黑树实现的
set中的元素排好序了
set容器中没有重复的元素
insert
int main()
{
std::set<int>iset;
for (int i = 0; i < 100; ++i)
{
auto it = iset.insert(rand() % 100);
if (it.second)
{
cout << "insert 成功" << endl;
}
else
{
cout << "已经有重复值" << *it.first <<endl;
}
}
std::set<int>::iterator it = iset.begin();
for (; it != iset.end(); ++it)
{
cout << *it << endl;
}
}
map与unordered_map的区别
int main()
{
std::map<int, std::string>ismap;
std::unordered_map<int, std::string>isunmap;
ismap[12] = "hhh";
ismap[34] = "ttt";
ismap[23] = "qqq";
ismap[67] = "zzz";
ismap[45] = "ddd";
ismap[56] = "aaa";
isunmap[12] = "hhh";
isunmap[34] = "ttt";
isunmap[23] = "qqq";
isunmap[67] = "zzz";
isunmap[45] = "ddd";
isunmap[56] = "aaa";
cout << "map" << endl;
for (auto& x : ismap)
{
cout << x.first << " " << x.second << endl;
}
cout << "------------------" << endl;
for (auto& x : isunmap)
{
cout << x.first << " " << x.second << endl;
}
}
无序map的底层是哈希表