泛型算法
泛型算法就是不依赖于类型实现的算法,使用泛型算法需要包含头文件:
#include
注意:大部分泛型算法不支持list和forward_list
排序
给指定范围内的元素进行排序,默认使用"<",也可以提供比较器
//使用"<"排序
void sort(起始位置,结束位置);
//使用比较器
void sort(起始位置,结束位置,比较器);
查找
按值查找,指定查找范围,找到了返回位置(迭代器),找不到返回结束位置。
如果查找的数据是类类型,该类需要支持"=="运算符(重载==)
iterator find(起始位置,结束位置,const value_type &val);
遍历
遍历给定范围内的所有元素,将取出的每一个元素使用第三个参数(函数/函数对象)进行处理。
void for_each(起始位置,结束位置,函数/函数对象);
其他
merge --------- 合并已排序
search -------- 子序列查找
copy ---------- 拷贝
unique -------- 去除相邻重复
swap ---------- 交换
equal --------- 判等
reverse ------- 翻转指定范围内的元素
max/min ------- 求较大/较小
练习:
使用for_each,实现对一个存储string的容器中匹配字符串的内容改为指定的新内容
array<string,5> as = {"hello","welcome","UK","Japan","Friday"};
//将容器中元素内容为"hello"改成"byebye"
/*03-for_each操作string*/
#include <iostream>
#include <algorithm>
#include <array>
using namespace std;
//函数
void modify(string &s) {
if (s == "hello")
s = "byebye";
}
int main() {
array<string, 5> as = {"hello", "welcome", "UK", "Japan", "Friday"};
cout << as.begin() << endl; //打印地址
for_each(as.begin(), as.end(), modify);//地址到地址执行,某个函数
for (array<string, 5>::iterator it = as.begin(); it != as.end(); it++) {
cout << *it << " ";
}
cout << endl;
return 0;
}
适配器容器
适配器容器包括栈,队列和优先队列,这些容器是在线性容器的基础上封装而成的,STL中的适配器容器需要提供一个底层的线性容器来实例化。
堆栈 ------ stack
堆栈是先进后厨的数据结构,只允许在一端(栈顶)访问,可以使用vector,deque(默认),list作为底层容器类型。
使用时包含头文件:#include
实例化语法
stack<元素类型,底层容器类型=deque> 堆栈对象
比如:stack<int,vector<int>> sv;
成员函数
入栈/压栈:push -----> push_back
出栈/弹栈:pop -----> pop_back
获取栈顶元素:top -----> back
获取元素个数:size -----> size
判空:empty -----> empty
应用
使用堆栈计算算术表达式(转换)
(10 + 2) / 3 + 6 * 5
队列 ------ queue
队列是先进先出的数据结构,底层容器之能是deque和list,默认使用deque
使用需要包含头文件:#include
实例化语法
queue<元素类型,底层容器类型=deque> 队列对象;
比如:queue<int,list<int>> qi;
成员函数
入队:push ------- push_back
出队:pop ------ pop_front
判空:empty ----- empty
获取队首元素:front ----- front
获取队尾元素:back ----- back
获取元素个数:size ---- size
优先队列 --------- priority_queue
优先队列和优者先出的数据结构,底层容器可以使vector(默认)和deque
使用需要包含头文件:#include
实例化语法
priority_queue<元素类型,底层容器类型=vector> 优先队列对象;
比如:priority_queue<int,deque<int>> pi;
//元素类型必须支持"<"运算符,以大者为先(重载函数必须加const)
priority_queue<元素类型,底层容器类型=vector,比较器类型> 优先队列对象;
//使用比较器比较大小,以大者为先
成员函数
入队:push
出队:pop
判空:empty
获取最优元素:top
/*06 - 优先队列的使用*/
#include <iostream>
#include <deque>
#include <queue>
using namespace std;
int main()
{
priority_queue<int> qi;
//入队
qi.push(4);
qi.push(5);
qi.push(8);
qi.push(1);
qi.push(3);
qi.push(2);
//出队
while(!qi.empty()){
cout<<qi.top()<<" ";//优者先出.最大的数先出来
qi.pop();
}
cout<<endl;
return 0;
}
练习:
class student{
int id;
string name;
int age;
};
1.使用有线队列存储student对象,构造完成后,默认比较器按id从大到小输出
2.提供函数对象比较器,按age从小到大,name从大到小输出
(3)优先队列实现的原理
使用了选择排序的方法,利用比较器每次选出一个最大的即可
简单选择排序:两两比较选出一个最大的,和第一个元素交换这种方法效率一般
有线队列使用的是堆排序的方法 ----- 构造二叉堆(大根堆)
二叉树:
关联容器
管理容器内部使用平衡二叉树来实现,一共有4种:映射(map),多重映射(multimap),集合(set),多重集合(multiset)
映射 ------- map
使用其需要包含头文件:#include
特性
1.映射是一个key-value的序列,key要求唯一
2.映射支持顺序迭代,顺序迭代采取中序遍历,得到的是key的有序序列
3.key的比较默认使用"<"运算符,也可以提供比较器
4.映射中的元素以pair为单位访问,pair有两个成员
一个first对应key,second对应value
5.支持以key作为下标的运算,得到的是这个key对应的value
实例化语法
map<key类型,value类型> 映射对象;//key必须支持"<"
map<key类型,value类型,比较器类型> //映射对象;
成员函数
构造pair对象的方法
1.使用pair的构造函数
pair<f_type,s_type> 对象名(xxx,yyy);
2.使用make_pair来构造
pair<f_type,s_type> make_pair(xxx,yyy);
迭代器:begin/end
//插入
pair<iterator,bool> insert(const pair<key_type,value_type> &pa);
//查找
iterator find(const key_type &key);
作业:
使用函数模板实现简单选择排序
1.两两比较,选出一个最大/最小和首元素交换
2.扫描剩余的元素,选出次大元素和第二个元素交换
3.重复以上过程,直到只剩最后一个元素位置
使用映射,实现票选西游代言人的程序
唐僧
孙悟空
猪八戒
沙和尚
白龙马
//value的类型
class Cand{
//....
private:
string name;
int votes;//票数
};
map<char,Cand> cc;
//循环20次投20票 ------ 输入key
最后输出选举结果
/*02-映射实现投票*/
#include <iostream>
#include <map>
using namespace std;
class Cand
{
public:
Cand(string name = "") : name(name), votes(0) {}
//投票
void vote()
{
this->votes++;
}
int get_votes() const
{
return this->votes;
}
string get_name() const
{
return this->name;
}
friend ostream &operator<<(ostream &os, const Cand &c)
{
return os << c.name << ":" << c.votes;
}
private:
string name;
int votes;
};
int main()
{
map<char, Cand> cc;
typedef map<char, Cand>::iterator IT;
//-----------------
cc.insert(pair<char, Cand>('A', Cand("唐僧")));
cc.insert(make_pair('B', Cand("孙悟空")));
cc['C'] = Cand("猪八戒");
cc['D'] = string("沙和尚");
cc['E'] = Cand("白龙马");
//-----------------
//投票
for (int i = 0; i < 20; i++) //可以投20票
{
for (IT it = cc.begin(); it != cc.end(); it++)
{
cout << it->first << "-" << it->second << endl;
}
char key;
cout << "请投票:";
cin >> key;
IT it = cc.find(key);
if (it == cc.end())
{
cout << "无效票" << endl;
continue;
}
//票数+1
it->second.vote();
}
cout << "---------------------------" << endl;
//输出选举结果
IT win = cc.begin();
for (IT it = cc.begin(); it != cc.end(); it++)
{
cout << it->first << "-" << it->second << endl;
//记录票数最多的人
if (it->second.get_votes() > win->second.get_votes())
win = it;
}
cout << "恭喜" << win->second.get_name() << "当选为本年度西游首席带盐人!" << endl;
return 0;
}