STL(完结)

STL_API

  • 容器:包含序列容器关联容器
  • 迭代器

string 容器

  • string str //构造
  • str.assign(“abcd”,4) //选取前四个赋值
  • str.assign(“abcd”,1,3) //选取1到3的赋值
  • s[100] 和 s.at(100) 区别
  • += 的重载
  • str.append(“abc”)
  • int pos =str.find(“bc”) //返回第一次出现的位置索引,找不到返回-1
  • str.replace(1,3,“111”) //从1开始3个字符的位置替换成“111”
  • s1.compare(s2) //s1大于s2时返回1 ,小于返回-1,等于返回0
  • string str2 = str1.**substr **(1 , 3) //子串1开始3个元素提取
  • str.insert(1,“111”) //从第1个位置开始插入“111” vector中要告诉它迭代器的位置
  • str.erase(1,3) //从1开始删除3个元素
  • const char* p = str.c_str(); //与c风格字符串转换
  • 注意:**string不能隐式转换为 char **
  • s[i] = toupper( s[i] ), s[i] = tolower( s[i] )
  • v.insert(v.begin(),2,100) 在一开始加入2个100

vector 容器(***)

  • 动态数组、可变数组、单口容器

  • push_back() 、pop_back() 这两种指的在尾端操作,**尾插 **和 尾删

  • 迭代器 v.begin()、最后一位的下一位v.end() 、v.rbegin() 、v.rend()

  • for_each() 算法的使用(遍历)

  • insert () 可以在指定位置插入元素(插入到中间时后面需要后移,这样效率不高)

  • vector 实现动态 增长原理

    当插入新元素的时候,如果空间不足,那么vector会重新申请更大的一块内存空间,将原空间数据拷贝到新空间,释放旧空间的数据,再把新元素插入到新申请空间。

  • 巧用swap来收缩空间 ——vector(v).swap(v) 利用 初始化匿名对象,这个匿名的对象随着swap交换指针后,当前行运行完就释放了,完成v的空间收缩

  • reserve(int len)预留开辟len个空间,不用再随着增长多次开辟空间了

  • **v.front()**第一个元素,v.back(),最后一个元素

  • v.erase(v.begin,v.end) 全部删除 相当于 v.clear()

  • rbegin() 和 rend()

deque容器

迭代器见到:const_iterator / reverse_iterrator

  • 双口容器**_包含中控器和buffer结构,**不存在空间限制
  • 双端插入和删除元素效率较高
  • 指定位置插入也会导致数据元素移动,降低效率
  • 可以随机存取,效率高
  • push_front(), pop_front(), push_back(), pop_back()
  • deque d
  • size/resize/empty与之前一样
  • d.insert(d.begin() , d2.begin(), d2.end() ) //将d2的区间插入到d中

Stack 容器

  • stack 是没有迭代器的,它不让你遍历,他是“先进后出
  • stack s
  • s.push(10)
  • s.top() //栈顶
  • s.pop()
  • s.empty()

queue 容器

  • 队列——排队打饭例子,“先进先出
  • 它的头和尾是可以让你看到的,但是中间过程是不允许看到的,所以他不提供遍历功能,也就不提供迭代器
  • queue q
  • q.push(10)
  • q.pop() //弹出
  • q.front() //队头
  • q.back() //队尾
  • q.empty()

list 容器(**)

  • 双向循环链表

  • 对于任何位置的插入是常数时间, list 迭代器是不支持随机访问的

  • 迭代器可见:Bidirectional_iterator / const_iterator / reverse_iterator(逆向)

  • listL

  • L.push_back(10) //将10插入尾部

  • L.push_front(10) //将10插入头部

  • L.pop_front(10)

  • L.pop_back(10)

  • L.front()

  • L.back()

  • L.insert(L.begin(),1000) //插入1000

  • L.clear()

  • L.erase(beg,end)

  • L.remove(10) //删除容器中所有与 elem 值匹配的元素

  • L.size()

  • L.resize(10)

  • L.empty()

  • L.reverse() //反转

  • 注意sort( L.begin() , L.end() ) //不能这样所有不支持随机访问的迭代器,不可以用系统提供的算法

  • L.sort() //从小到大 如果需要从大到小的需求,择需要指定排序规则L.sort(规则函数)

  • L.remove(对象名) //删除自定义数据类型,从源码的角度看可以重载“==”

set/multiset 容器

  • set 里面自动排序(从小到大),不允许有重复的值,不允许通过迭代器修改set元素的值

  • multiset 允许重复(键值重复),他和set的底层实现是红黑树

  • set s1

  • s1.insert(10) //只能这么插入

  • clear / empty / erase(迭代器或者值 ) / size

  • 对于set来说,key就是value

  • set::iterator pos = s1.find(3) //找到返回迭代器,没找到返回s1.end()

  • s1.count(1) //查找 key 的元素的个数,有的话返回1,没有返回0(因为set中没有重复元素)


  • set::iterator it = s1.lower_bound(3) //返回第一个key>=3的元素的迭代器,没找到就返回s1.end()

  • set::iterator it2 = s1.upper_bound(3) //返回第一个key>3的元素的迭代器,没找到就返回s1.end()

  • pair< set::iterator, set::iterator > ret = s1.equal_range(3) //返回容器中key与 3 相等的上下限的两个迭代器,上下限就是lower_bound 与 upper_bound 获取第一个值就 ret.first


  • pair<string , int > p(string(“Tom”),100) //创建对组(不需要引用任何头文件)-

  • pair<string , int > p = make_pair(“Jerry”, 200)

  • set在使用 insert 插入时,返回的是一个pair对组 <迭代器,是否成功标识>,multiset允许插入重复值

  • 对于使用仿函数来改变set容器里面默认从小到大排序的规则

  • set里面存储自定义数据类型,一上来就要指定好数据类型

map / multimap 容器

  • map 所有的元素都是pair,但是 map 不允许有相同的 key 值

  • multimap 与 map 的区别是它的 key 值是可以重复的

  • map<int,int> m


  • m.insert(pair<int,int>(1,10))

  • m.insert(make_pair(2,20)) //推荐

  • m.insert(map<int,int> :: value_type(3,30)) //不推荐

  • m[1] = 10 //尽量 保证这个key存在


  • swap / size / empty / clear / erase(迭代器,键值,区间,都可以)

  • m.find(key) //找到返回迭代器,找不到返回m.end()

  • m.count(3)

  • map<int,int>::iterator ret = m.lower_bound(3)

  • map<int,int>::iterator ret = m.upper_bound(3)

  • pair< map<int,int>::iterator , map<int,int>::iterator > p1 = m.equal_range(3)

  • 指定map的默认排序规则

函数对象(仿函数)

  • 是一个类,不是一个函数

  • 可以储存属性,即可以有自己的状态(例如调用次数)

  • 函数对象可以作为参数进行传递

  • 重载“()”

  • 作为类型,与模板进行配合使用

谓词

  • 普通函数或者重载的operator()返回值是bool类型的函数对象(仿函数),根据参数的数量分为一元谓词二元谓词

  • find_if(v.begin() , v.end() , _pr_pred(仿函数)) //返回迭代器

  • lambda表达式的形式

内建 函数对象(仿函数)

  • negate n --cout<< n(10) //取反

  • plusp – cout<< p(1,1) //加法

  • sort( v.begin() , v.end() , **greater() **) //匿名对象,记得包含 #include此外,还有 less()

  • for_each(v.begin(),v.end(),[](int val){cout << val << “”}) //lambda,后面如果是函数就用函数名,如果是仿函数就用函数对象

适配器的使用

普通适配器

  • bind2nd(MyPrint(),num) //绑定数据-

  • class MyPrint:public binary_function<参数类型1 , 参数类型2 , 返回值> //继承

  • const修饰operator()


    取反适配器

  • not1(函数对象) //表示取反——一元取反适配器,继承unary_function<参数类型1.返回值类型>

  • 高端一点:auto pos = find_if(v.begin() , v.end() , not1( bind2nd(greater() , 5) ) )

  • sort(v.begin() , v.end() , not2(less() ) )


    函数指针适配器——将函数指针适配为函数对象

  • for_each(v.begin(), v.end(), bin2nd( ptr_fun(MyPrint相当于普通函数指针),100 )) ** //相当于将普通函数指针适配成函数对象**了


    成员函数适配器

  • for_each( v.begin(), v.end(), mem_fun_ref(&Person::showPerson )) //成员函数的适配mem_fun_ref

常用遍历算法

  • for_each(beg , end , _callback) //__callback可以使普通函数也可以是仿函数

  • for_each 是有返回值的,返回的是与_callback类型一样的对象,这个对象里面可以存储属性

  • for_each 可以绑定参数进行输出,for_each( v.begin() , v.end() , bind2nd( myPrint(), 10000 ) ),记住在使用bind2nd时需要引入#include头文件

  • transform( v.begin() , v.end() , vTarget.begin() , 仿函数 ) // **搬运 **功能,注意使用前要给 vTarget 对象分配内存——vTarget.resize(v.size() )

  • transform另一个用法,那么将两个容器搬运到一个目标容器:transform( v1.begin() , v1.end() , v2.begin() , vTarget.begin() , 仿函数 )

常用查找算法

  • find(v.begin() , v.end() , 5) //返回迭代器,找不到返回v.end()
  • find查找自定义数据类型,v.find(v.begin() , v.end() , p1) ,需要重载“==”,返回仍然是迭代器
  • find_if
  • adjacent_find(v.begin() , v.end() ) //返回迭代器,两个重复的元素,返回第一个迭代器
  • binary_search(v.begin() , v.end() , 4) //返回布尔值
  • count(v.begin() , v.end() , 4 ) //返回 int
  • count_if(v.begin() , v.end() , 仿函数)

常用排序算法

  • merge(v1.begin() , v1.end() , v2.begin() , v2.end() , vTarget.begin()) //两个有序容器合并,记得要给vTarget 开辟空间

  • sort(v.begin() , v.end() , 可以选择补充的条件(仿函数),不补充也可以,默认从小到大)

  • random_shuffle(beg , end) //洗牌,需要在main里面设置随机种子,srand(unsigned int)time(NULL)

  • reverse(v.begin() , v.end()) //翻转

常用拷贝和替换算法

  • copy(v.begin() , v.end() , vTarget.begin() )
  • copy高端操作copy(vTarget.begin() , vTarget.end() , ostream_iterator(cout , " ")) //等于是把对象数据复制到流对象里,其实就是用copy来实现对象的元素数据的输出操作,这种方式不能换行,记住就行
  • replace(v.begin() , v.end() , 3 ,300) //将 3 替换为 300,输出的时候我们又可以像上一点那样,copy(v.begin() ,v.end(), ostream_iterator(cout," ")),记得包含头文件#include
  • replace_if(v.begin(), v.end() , MyCopare() , 300) //MyCopare()是一个匿名对象(仿函数),满足条件的替换成300,同样输出可用copy(v.begin(),v.end(),ostream_iterater(cout," ") )
  • swap(v1 , v2)

常用算数生成算法

  • accumulate(v.begin() , v.end() , 0 ) //它的头文件要运用**#include ,** 返回值int,这里的0,是一个起始累加值
  • fill(v.begin() , v.end() ,101) //填充101

常用集合算法

  • get_intersection(v1.begin() ,v1.end(), v2.begin(), v2.end() , vTarget.begin()) //交集,返回值是vTarget最后一个元素的迭代器,之前要有vTarget.resize(min(v1.size(),v2.size()))分配空间,copy(vTarget.begin() , 上面返回的结果itEnd , ostream_iterator(cout , " "))

  • set_union(v1.begin() ,v1.end(), v2.begin(), v2.end() , vTarget.begin()) //并集

  • set_difference(v1.begin() ,v1.end(), v2.begin(), v2.end() , vTarget.begin()) //v1差v2

//综合案例
#include<iostream>
using namespace std;
#include<vector>
#include<map>
#include<string>
#include<algorithm>
#include<deque>
#include<numeric>
#include<functional>

class Speaker
{
public:
	string m_Name;  //name
	int m_Score[3];
};

void createSpeaker(vector<int>& v, map<int,Speaker>& m)
{
	string nameSeed = "ABCDEFGHIJKLMNOPQRSTUVWX";
	for (int i = 0; i < nameSeed.size(); i++)
	{
		string name = "选手";
		name += nameSeed[i];
		Speaker sp;
		sp.m_Name = name;
		for (int j = 0; j < 3; j++)
		{
			sp.m_Score[j] = 0;
		}
		v.push_back(i + 100);
		m.insert(make_pair(i + 100, sp));
	}
}

void speechDraw(vector<int>& v)
{
	random_shuffle(v.begin(), v.end());

}


void speechContest(int index, vector<int>& v1, map<int, Speaker>& m, vector<int>& v2)
{
	multimap<int, int, greater<int>> groupMap;
	int num = 0;
	for (auto it = v1.begin(); it != v1.end(); it++)
	{
		num++;
		deque<int>d;
		for (int i = 0; i < 10; i++)
		{
			int socre = rand() % 41 + 60;
			d.push_back(socre);
		}
		sort(d.begin(), d.end());
		d.pop_back();
		d.pop_front();
		int sum = accumulate(d.begin(), d.end(), 0);
		int avg = sum / d.size();
		m[*(it)].m_Score[index - 1] = avg;
		groupMap.insert(make_pair(avg, *it));
		if (num % 6 == 0)
		{
			/*
			cout << "小组比赛成绩" << endl;
			for (auto mit = groupMap.begin(); mit != groupMap.end(); mit++)
			{
				cout << "编号: " << mit->second << "姓名: " << m[mit->second].m_Name << "得分: " << m[mit->second].m_Score[index - 1] << endl;
			}
			*/
			int count = 0;
			for (multimap<int, int, greater<int>>::iterator mit = groupMap.begin(); \
				mit != groupMap.end(), count < 3; mit++,count++)
			{
				v2.push_back(mit->second);
			}
			groupMap.clear();
			
		}
	}
}

void showScore(int index, vector<int>& v, map<int, Speaker>& m)
{
	cout << "第" << index << "轮,比赛成绩如下:" << endl;
	for (auto it = m.begin(); it != m.end(); it++)
	{
		cout << "选手编号: " << it->first << "\t" << "姓名: " << it->second.m_Name << "\t" << "分数: "\
			<< it->second.m_Score[index - 1] << endl;

	}
	cout << "晋级选手编号: " << endl;
	for (auto it = v.begin(); it != v.end(); it++)
	{
		cout << *it << endl;

	}
}

int main()
{
	vector<int>v1;
	map<int, Speaker>m;
	createSpeaker(v1,m);
	//测试
	for (map<int, Speaker>::iterator it = m.begin(); it != m.end(); it++)
	{
		cout << "编号:" << (*it).first << "\t" << "姓名:" << (*it).second.m_Name << "\t" << "得分:" << it->second.m_Score[0] << endl;
	}
	speechDraw(v1);//抽签
	vector<int>v2;
	speechContest(1, v1, m, v2);

	//显示比赛结果
	showScore(1, v2, m);

	//第二轮比赛
	speechDraw(v2);
	vector<int>v3;
	speechContest(2, v2, m, v3);
	showScore(2, v3, m);

	//第三轮比赛
	speechDraw(v3);
	vector<int>v4;
	speechContest(3, v3, m, v4);
	showScore(3, v4, m);

	return 0;
}

贪吃蛇

  • 墙模块

    • 二维数组维护
    • 初始化二维数组
    • 画出墙壁
    • 提供对外接口setwall和getwall
  • 蛇模块

    • 初始化蛇
    • 销毁所有节点
    • 添加新节点
  • 食物模块

    • foodX foodY
    • setFood 对外接口,随机设置食物
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值