包括算法、容器、迭代器
1、vector容器与iterator迭代器
#include "vector.h"
void main()
{
vector<int> v;//定义vector容器
for(vector<int>::iterator it = v.begin(); it != v.end(); it ++)//定义迭代器it(指针)
{
cout << *it <<" ";
}
}
2、string
(1)构造函数
默认构造函数:
string(); //构造一个空的字符串string s1。
拷贝构造函数:
string(const string &str); //构造一个与str一样的string。如string s1(s2)。
带参数的构造函数
string(const char *s); //用字符串s初始化
string(int n,char c); //用n个字符c初始化
(2)遍历
–》通过数组的方式
for(int i = 0; i < s1.length(); i ++)
cout << s1[i] << " ";//不会提示异常,导致程序终止
cout << s1.at[i] << endl;//会提示异常
–》迭代器
for(string::iterator it = s1.begin(); it != s1.end(); it ++)
cout << *it << " ";
(3)连接两个字符串
string s1,s2;
s1 = s1 + s2;
s1.append(s2);
(4)transform(s1.begin(), s1.end(), s1.begin(), toupper/tolower);//将s1全部转换为大写/小写
3、vector容器
—》》基本操作 vector
计算大小:v1.size();
插入元素:v1.push_back(1);
获取尾部元素:v1.back();
获取头部元素:v1.front();
删除尾部元素:v1.pop_back();
初始化:vector
vector<int> v3(v1.begin(), v1.begin()+2);//左闭右开赋值,相当于v1[0],v1[1]赋给v3
遍历:(1)数组方式遍历时,一定要提前声明内存空间
vector<int> v1(10);//而不是v1就可以了,默认每个内存空间为0
for(int j = 0; j < 10 ; j++)
{
v1[j] = v1[j] + 1;
}
(2) 迭代器遍历
—》正向遍历(借助正向迭代器)
for(vector<int>::iterator it = v.begin(); it != v.end(); it ++)//其中v.begin()指向第一个元素,v.end()指向最后一个元素的后一个位置
{
cout << *it << endl;
}
—》逆向遍历(借助逆向迭代器)
for(vector<int>::reverse_iterator rit = v.rbegin(); rit != v.rend(); rit ++)
{
cout << *rit << endl;
}
(3)
区间删除v1.erase(v1.begin(), v1.begin()+3);//删除前三个元素
指定位置删除v1.erase(v1.begin());//删除第一个元素
指定的值删除
for(vector<int>::iterator it = v.begin(); it != v.end())
{
if(*it == 2)
{
v.erase(it);//删除的时候会让it指针自动下移
}
else
it ++;
}
(4)插入v1.insert(v1.begin(), 100); v1.insert(v2.end(), 200);
4、双端数组deque
push_front() push_back()//前段、后端插入
pop_front() pop_back()//前段、后端弹出
查找某个值在数组下标的值
deque<int>::iterator it = find(d1.begin(), d1.end(), -33)
if(it != d1.end())
cout << distance(d1.begin(), it) << endl;//输出-33在队列的下标值
5、stack栈
s.push(i);//入栈
s.pop();//弹出栈顶元素
int tmp = s.top();//获取栈顶元素
6、queue队列
q.push(i);//入队
q.pop();//出列
int tmp = q.front();//获取对头元素
7、list双向链表容器
不可以随机存取元素,所以不支持at.(pos)函数与[]操作符,it++(OK) it+5(ERR)
push_back(i);
//遍历
list<int>::iterator it = l.begin();
while(it != l.end())
{
cout << *it << endl;
it ++;
}
在指定位置插入元素:
list<int>::iterator it = l.begin();
it++;
l.insert(it, a);//表示在1号位置插入元素a,原来的1号变2号,2号变3号……
删除元素
l.clear();//清空队列
l.erase(begin,end);//删除[begin,end)区间的元素
l.erase(pos);//删除pos位置的元素
l.remove(elem);//删除所有等于elem元素
删除0号到2号之间所有元素的操作
list<int>::iterator it1 = l.begin();
list<int>::iterator it2 = l.begin();
it2 ++;
it2 ++;
it2 ++;
l.erase(it1, it2);//删除0、1、2号元素
8、优先级队列priority_queue
按照值的大小放在队头、队尾
最大值优先级队列(默认)、最小值优先级队列
priority_queue<int> p1;
等同于
priority_queue<int, vector<int>, less<int> > p2;//最大值优先级队列
priority_queue<int, vector<int>, greater<int>> p3;//最小值优先级队列
9、set
一个集合容器,所包含的元素是唯一的,集合中的元素是按照一定的顺序排列(默认情况下是从小到大),元素插入是按排序规则插入的。
insert,erase
set<int> set1;等同于set<int, less<int>> set1;//默认从小到大
set<int, greater<int>> set2;//从大到小
//当插入的元素是一个类时,要制定按照类的那个元素的大小进行排序,可以通过建立仿函数的形式进行
struct FuncStudent//仿函数
{
bool operator()(const Student &left, const Student &right)
{
if(left.age < right.age)
{
return true;
}
else
{
return false;
}
}
main()
{
set set;
Student s1("s1", 31);
Student s2("s2", 32);
set.insert(s1);
set.insert(s2);//自动按照年龄大小进行排序
}
如何知道插入的结果:进入底层函数,查看返回值
pair(set ::iterator, bool) pair1 =set.insert(s1);
if(pair1.second == true)
{
cout <<"插入成功"<< endl;
}
set的查找(迭代器set<int>::iterator是指针)
set.find(elem)//查找elem元素,返回elem元素的迭代器
set.count(elem)//返回值等于elem元素的个数
set.lower_bound(elem)//返回第一个>=elem的迭代器
set.upper_bound(elem)//返回第一个>elem的迭代器
set.equal_range(elem)//返回大于等于和大于的迭代器
pair<set<int>::iterator, set<int>iterator> mypair = set.equal_range(elem);
set<int>::iterator it3 = mypair.first;//大于等于
set<int>::iterator it4 = mypair.second;//大于
10、multiset:同一个值可以出现多次
11、map、multimap
标准的关联式容器,一个map是一个键值对序列,即(key,value)对。他提供基于key的快速索引能力。
key是唯一的,元素是按照一定的顺序排列的。
multimap唯一的区别是相同键可以出现多次,而map每个键只能够出现一次。map支持map[key]=value,而multimap不支持[]操作符。
默认构造:map<int, string> map1;
map.count(key)//返回键值为key的个数,用于multimap
插入元素
map1.insert(pair<int, string>(1, "teacher01"));
map1.insert(make_pair(2, "teacher02"));
map1.insert(map<int, string>::value_type(3, "teacher03"));
map1[4] = "teacher04";
//前三种插入 若key已经存在 则报错
方法四 若key已经存在 则修改
//前三种插入方法返回值为pair判断是否插入失败
pair<map<int, string>::iterator, bool> mypair = map1.insert(make_pair(2, "teacher02"));
if(mypair.second != true)
cout << "error" << endl;
else//输出序号和值
cout << mypair.first->first << "\t" <second << endl;
遍历
for(map<int, string>::iterator it = map1.begin(); it != map1.end(); it ++)
{
cout << it->first << "\t" << it->second << endl;
}
删除
map<int, string>::iterator it = map1.begin();
map1.erase(it);
查找
map<int,string>::itrator it = map.find(key);//查找键key是否存在,若存在,返回该元素的迭代器;否则返回map.end()
map.equal_range(key);//返回两个迭代器的位置,第一个是大于等于key的迭代器的位置,第二个是大于key的迭代器的位置
mutimap的最重要的特性就是:一个key可以对应多个value,常用于分组,一个组下面有多个成员。
12、容器的共性(C++模板是容器的概念)
13、各个容器的使用时机
(1) deque的使用场景:比如排队购票系统
(2)list的使用场景:比如公交车乘客的存储,随时可能有乘客下车,支持频繁的不确实位置元素的移除插入。
(3)set的使用场景:比如对手机游戏的个人得分记录的存储,存储要求从高分到低分的顺序排列。
(4)map的使用场景:比如按ID号存储十万个用户,想要快速要通过ID查找对应的用户。
14、函数对象
一个函数对象,即一个重载了括号操作符“()”的对象,即为这个对象的操作符()进行重载
class A{
public:
int operator()(int x){return x;}
};
A a;
a(5);
这里的a就是一个函数对象
15、算法
入门:分清返回值是迭代器还是谓词(函数对象)。
常用的算法:
for_each: 用指定函数依次对指定范围内所有元素进行迭代访问。该函数不得修改序列中的元素。
for_each(vecInt.begin(), vecInt.end(), show);
transform: 与for_each类似,遍历所有元素,但可对容器的元素进行修改
int increase (int i)
{
return i+1;
}
main()
{
vector<int> vecIntA;
vecIntA.push_back(1);
vecIntA.push_back(3);
vecIntA.push_back(5);
vecIntA.push_back(7);
vecIntA.push_back(9);
transform(vecIntA.begin(),vecIntA.end(),vecIntA.begin(),increase); //vecIntA : {2,4,6,8,10}
}
for_each和transform比较:for_each所使用的函数对象,参数是引用,没有返回值;transform所使用的函数对象,参数一般不使用引用,而且还有返回值。
查找相关算法:
在iterator对标识元素范围内,查找一对相邻重复元素,找到则返回指向这对元素的第一个元素的迭代器adjacent_find(v1.begin(), v1.end())
在有序序列中查找value,找到则返回truebinary_seach(v1.begin(), v1.end(), 7)
利用等于操作符,把标志范围内的元素与输入值比较,返回相等的个数int iCount = count(vecInt.begin(),vecInt.end(),2);
返回满足条件的元素的个数
bool GreaterThree(int iNum)
{
if(iNum>=3)
{
return true;
}
else
{
return false;
}
}
int iCount = count_if(vecIntA.begin(), vecIntA.end(), GreaterThree);
利用底层元素的等于操作符,对指定范围内的元素与输入值进行比较。当匹配时,结束搜索,返回该元素的迭代器。
vector<int>::iterator it = find(vecInt.begin(), vecInt.end(), 5);
equal_range: 返回一对iterator,第一个表示lower_bound,第二个表示upper_bound。
map<char,int> mymap;
pair<map<char,int>::iterator,map<char,int>::iterator> ret;
mymap['a']=10;
mymap['b']=20;
mymap['c']=30;
ret = mymap.equal_range('b');
cout << "lower bound points to: ";
cout << ret.first->first << " => " << ret.first->second << endl;
cout << "upper bound points to: ";
cout << ret.second->first << " => " << ret.second->second << endl;
运行结果:
lower bound points to: 'b' => 20
upper bound points to: 'c' => 30
find_if: 使用输入的函数代替等于操作符执行find。返回被找到的元素的迭代器。
假设vector vecIntA,vecIntA包含1,3,5,3,9元素
vector::it = find_if(vecInt.begin(),vecInt.end(),GreaterThree);
merge: 合并两个有序序列,存放到另一个序列。
例如:vecIntA,vecIntB,vecIntC是用vector声明的容器,vecIntA已包含1,3,5,7,9元素,vecIntB已包含2,4,6,8元素
vecIntC.resize(9); //扩大容量
merge(vecIntA.begin(),vecIntA.end(),vecIntB.begin(),vecIntB.end(),vecIntC.begin());
sort: 以默认升序的方式重新排列指定范围内的元素。若要改排序规则,可以输入比较函数。
//学生类
Class CStudent:
{
public:
CStudent(int iID, string strName)
{
m_iID=iID;
m_strName=strName;
}
public:
int m_iID;
string m_strName;
}
//学号比较函数
bool Compare(const CStudent &stuA,const CStudent &stuB)
{
return (stuA.m_iIDvoid main()
{
vector vecStu;
vecStu.push_back(CStudent(2,"老二"));
vecStu.push_back(CStudent(1,"老大"));
vecStu.push_back(CStudent(3,"老三"));
vecStu.push_back(CStudent(4,"老四"));
sort(vecStu.begin(),vecStu.end(),Compare);
// 此时,vecStu容器包含了按顺序的"老大对象","老二对象","老三对象","老四对象"
}
reverse(vecInt.begin(), vecInt.end());//反转容器
copy(vecIntA.begin(), vecIntA.end(), vecIntB.begin()); //vecIntB: {1,3,5,7,9}拷贝容器
replace(beg,end,oldValue,newValue): // 将指定范围内的所有等于oldValue的元素替换成newValue。
replace_if : 将指定范围内所有操作结果为true的元素用新值替换。
用法举例:
replace_if(vecIntA.begin(),vecIntA.end(),GreaterThree,newVal)
其中 vecIntA是用vector<int>声明的容器
GreaterThree 函数的原型是 bool GreaterThree(int iNum)
swap: 交换两个容器的元素
vector<int> vecIntA;
vecIntA.push_back(1);
vecIntA.push_back(3);
vecIntA.push_back(5);
vector<int> vecIntB;
vecIntB.push_back(2);
vecIntB.push_back(4);
swap(vecIntA, vecIntB); //交换
accumulate: 对指定范围内的元素求和,然后结果再加上一个由val指定的初始值。
#include
vector<int> vecIntA;
vecIntA.push_back(1);
vecIntA.push_back(3);
vecIntA.push_back(5);
vecIntA.push_back(7);
vecIntA.push_back(9);
int iSum = accumulate(vecIntA.begin(), vecIntA.end(), 100); //iSum==125
fill: 将输入值赋给标志范围内的所有元素。
vector<int> vecIntA;
vecIntA.push_back(1);
vecIntA.push_back(3);
vecIntA.push_back(5);
vecIntA.push_back(7);
vecIntA.push_back(9);
fill(vecIntA.begin(), vecIntA.end(), 8); //8, 8, 8, 8, 8
16、算法应用–演讲比赛
先搭建基本框架,然后完善业务函数。
#include
using namespace std;
#include "string"
#include
#include
#include "set"
#include
#include "functional"
#include "iterator" //输出流迭代器的头文件
#include
#include "map"
#include "deque"
class Speaker
{
public:
string m_name;
int m_score[3];
};
//产生选手
int GenSpeaker(map<int, Speaker> &mapSpeaker, vector<int> &v)
{
string str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
random_shuffle(str.begin(), str.end());//随机排序
for (int i=0; i<24; i++)
{
Speaker tmp;
tmp.m_name = "选手";
tmp.m_name = tmp.m_name + str[i];
mapSpeaker.insert(pair<int, Speaker>(100+i, tmp) );
}
for (int i=0; i<24; i++)
{
v.push_back(100+i); //参加比赛的人员
}
return 0;
}
//选手抽签
int speech_contest_draw(vector<int> &v)
{
random_shuffle(v.begin(), v.end());
return 0;
}
//选手比赛
int speech_contest(int index, vector<int> &v1, map<int, Speaker> &mapSpeaker, vector<int> &v2 )//index表示第几轮 v1表示传入的选手编号 v2表示晋级的选手编号
{
//小组的比赛得分 记录下来;求出前三名 后3名
multimap<int, int, greater<int>> multmapGroup; //小组成绩
int tmpCount = 0;
for (vector<int>::iterator it=v1.begin(); it!=v1.end(); it++ )
{
tmpCount ++;
//打分
{
deque<int> dscore;
for (int j=0; j<10; j++) //10个评委打分
{
int score = 50+rand()%50;
dscore.push_back(score);
}
sort(dscore.begin(), dscore.end());
dscore.pop_back();
dscore.pop_front(); //去除最低分 最高分
//求平均分
int scoresum = accumulate(dscore.begin(), dscore.end(), 0);
int scoreavg = scoresum/dscore.size();
mapSpeaker[*it].m_score[index] = scoreavg; //选手得分 存入容器中
multmapGroup.insert(pair<int ,int>(scoreavg, *it ) );
}
//处理分组
if (tmpCount % 6 == 0)
{
cout << "小组的比赛成绩" << endl;
for (multimap<int, int, greater<int>>::iterator mit=multmapGroup.begin(); mit!=multmapGroup.end(); mit++ )
{
//编号 姓名 得分
cout << mit->second << "\t" << mapSpeaker[mit->second].m_name << "\t" << mit->first << endl;
}
//前三名晋级
while (multmapGroup.size() > 3)
{
multimap<int, int, greater<int>>::iterator it1 = multmapGroup.begin();
v2.push_back(it1->second); //把前三名 放到v2 晋级名单 中
multmapGroup.erase(it1);
}
multmapGroup.clear(); //情况本小组 比赛成绩
}
}
return 0;
};
//查看比赛结果
int speech_contest_print(int index, vector<int> &v, map<int, Speaker> &mapSpeaker)
{
printf("第%d轮 晋级名单\n", index+1);
for (vector<int>::iterator it=v.begin(); it!=v.end(); it++)
{
cout << "参赛编号: " << *it << "\t" << mapSpeaker[*it].m_name << "\t" << mapSpeaker[*it].m_score[index] << endl;
}
return 0;
};
void main()
{
//容器的设计
map<int, Speaker> mapSpeaker; //参加比赛的选手
vector<int> v1; //第1轮 演讲比赛 名单
vector<int> v2; //第2轮 演讲比赛 名单
vector<int> v3; //第3轮 演讲比赛 名单
vector<int> v4; //最后前三名 演讲比赛 名单
//产生选手 得到第一轮选手的比赛名单
GenSpeaker(mapSpeaker, v1);
//第1轮 选手抽签 选手比赛 查看比赛结果
cout << "\n\n\n任意键,开始第1轮比赛" << endl;
cin.get();
speech_contest_draw(v1);
speech_contest(0, v1, mapSpeaker, v2);
speech_contest_print(0, v2, mapSpeaker);
//第2轮 选手抽签 选手比赛 查看比赛结果
cout << "\n\n\n任意键,开始第2轮比赛" << endl;
cin.get();
speech_contest_draw(v2);
speech_contest(1, v2, mapSpeaker, v3);
speech_contest_print(1, v3, mapSpeaker);
//第3轮 选手抽签 选手比赛 查看比赛结果
cout << "\n\n\n任意键,开始第3轮比赛" << endl;
cin.get();
speech_contest_draw(v3);
speech_contest(2, v3, mapSpeaker, v4);
speech_contest_print(2, v4, mapSpeaker);
cout<<"hello..."<"pause");
return ;
}