01 上次课程回顾

昨天讲了三个容器

string  string是对char*进行的封装

vector 单口容器 动态数组

deque(双端队列)

函数对象/谓词:

一元函数对象:

for_each:

谓词: predicate

一元谓词:

find_if

二元函数对象: transform

transform操作: 两个容器相加 放到第三个

class myplus {

public:

int operator()(int v1,int v2){

return v1 + v2;

}

private:

};

void test03() {

vector<int> v1,v2,v3;

for (int i = 0; i < 10; i++)

{

v1.push_back(i);

v2.push_back(i+1);

}

/*

template<class _InIt1,

class _InIt2,

class _OutIt,

class _Fn> inline

_OutIt transform(const _InIt1 _First1, const _InIt1 _Last1,

const _InIt2 _First2, _OutIt _Dest, _Fn _Func)

{   // transform [_First1, _Last1) and [_First2, ...) with _Func

_Adl_verify_range(_First1, _Last1);

auto _UFirst1 = _Get_unwrapped(_First1);

const auto _ULast1 = _Get_unwrapped(_Last1);

const auto _Count = _Idl_distance<_InIt1>(_UFirst1, _ULast1);

auto _UFirst2 = _Get_unwrapped_n(_First2, _Count);

auto _UDest = _Get_unwrapped_n(_Dest, _Count);

for (; _UFirst1 != _ULast1; ++_UFirst1, (void)++_UFirst2, ++_UDest)

{

*_UDest = _Func(*_UFirst1, *_UFirst2);  ←!最后的处理,这里是二元函数对象

}

_Seek_wrapped(_Dest, _UDest);

return (_Dest);

}

v1+v2 放到v3的开始位置

*/

v3.resize(v1.size());

for_each(v1.begin(), v1.end(), print2);

cout << endl;

for_each(v2.begin(), v2.end(), print2);

cout << endl;

for_each(v3.begin(), v3.end(), print2);

cout << endl;

transform(v1.begin(), v1.end(), v2.begin(),v3.begin(), myplus()); // 匿名函数对象

cout << "--------------" << endl;

for_each(v1.begin(), v1.end(), print2);

cout << endl;

for_each(v2.begin(), v2.end(), print2);

cout << endl;

for_each(v3.begin(), v3.end(), print2);

cout << endl;

}

二元谓词:

class mycompare04 {

public:

bool operator()(int v1,int v2) {

return v1 > v2; // 从大到小排序

}

};

// 二元谓词 应用举例: sort

void test04()

{

vector<int> v;

v.push_back(5);

v.push_back(2);

v.push_back(7);

v.push_back(9);

/*

template<class _RanIt,

class _Pr> inline

void sort(const _RanIt _First, const _RanIt _Last, _Pr _Pred)

{   // order [_First, _Last), using _Pred

_Adl_verify_range(_First, _Last);

const auto _UFirst = _Get_unwrapped(_First);

const auto _ULast = _Get_unwrapped(_Last);

_Sort_unchecked(_UFirst, _ULast, _ULast - _UFirst, _Pass_fn(_Pred));

}

*/

sort(v.begin(), v.end(),mycompare04());

for (vector<int>::iterator it = v.begin(); it != v.end(); it++ )

{

cout << *it << endl;

}

}

02 stack容器课堂练习

03 queue容器课堂练习

04list容器概念

STL中的list是双向链表

一个节点有两个指针

05 list容器基本操作

mylist.sort(); // 默认从小到大

传入函数对象或者函数指针让他从大到小

对于对象的排序要指定排序方法。

示例:

06 set集合概念

二叉树:

一个节点 每个节点最多有两个子节点

二叉搜索树:

左子树都比父节点小

右子树都比父节点大

这个就叫二叉搜索树

有可能出现左边深度很高 右边深度没那么高的清空

平衡二叉搜索树(平衡二叉树)(尽量保证左子树和右子树深度一样):

红黑树是平衡二叉树的一种 也是达到上面的效果

set容器:

内部是树,自动形成平衡二叉搜索树的机制,

以平衡二叉树(红黑树)为底层实现机制

set容器元素唯一

multiset可以插入重复元素

07 set初始化_插入和删除_find查找

功能:函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置.

注意:如果所有元素都小于val,则返回last的位置,且last的位置是越界的!!

功能:函数upper_bound()返回的在前闭后开区间查找的关键字的上界,返回大于val的第一个元素位置

注意:返回查找元素的最后一个可安插位置,也就是“元素值>查找值”的第一个元素的位置。同样,如果val大于数组中全部元素,返回的是last。(注意:数组下标越界)

equal_range返回的是一个pair

pair.first 是lower_bound

pair.second 是 upper_bound

从大到小排序:

方法一:

方法二:

其实内部就是等价于这个:

实现对特定类的排序:

multiset:

08 上午课程回顾

栈和队列没提供迭代器 因为内部有自己的实现规则

09 对组

10 map集合概念和四种插入方式区别

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>

#include <map>

#include <string>

using namespace std;

// map容器初始化

void test01()

{

// map容器的模板参数 需要制定key类型 value类型

map<int, string> mymap; // 默认构造

map<int, string> mymap2(mymap); // 拷贝构造

}

// map插入操作

void test02() {

map<int, int> mymap;

// 第一种插入方式

//pair<int, int> mypair(1, 5);

//mymap.insert(mypair);

mymap.insert(pair<int,int>(1,5));

// 第二种

pair<map<int,int>::iterator,bool> ret = mymap.insert(make_pair(2,10));

if (ret.second) {

cout << "插入成功" << endl;

}

else {

cout << "插入失败" << endl;

}

// 第三种

mymap.insert(map<int, int>::value_type(3, 15));

// 第四种

mymap[4] = 20;

mymap[2] = 100;  // 如果key存在,会修改容器指定key元素的值

// 如果你访问的key不存在,他会帮你把这个数据插入进去

pair<map<int, int>::iterator, bool> ret2 = mymap.insert(map<int, int>::value_type(2, 210)); // 不能再插入了 已经有2这个key了

if (ret2.second) {

cout << "插入成功" << endl;

}

else {

cout << "插入失败" << endl;

}

for (map<int, int>::iterator it = mymap.begin(); it != mymap.end(); it++)

{

cout << "key:" << it->first << " value:" << it->second << endl;

}

cout << endl;

}

int main(void)

{

test02();

return 0;

}

12  multimap课堂案例

 

/*

公司今天照片了5个员工

5个员工进入公司之后 需要指派员工在哪个部门工作

人员信息有:姓名 年龄 电话 工资等组成

通过Multimap进行信息的插入 保存 显示

分部门显示员工信息 显示全部员工信息

*/

#include <iostream>

#include <vector>

#include <map>

using namespace std;

/*

    公司今天入职了5个员工

    5个员工进入公司之后需要指派员工在哪个部门工作

    人员信息有:姓名年龄电话工资等组成

    通过multimap进行信息的插入保存显示

    分部门显示员工信息显示全部员工信息

*/

#define SALE_DEPARTMENT 1 // 销售部

#define DEVELOP_DEPARTMENT 2 // 开发部

#define FINACIAL_DEPARTMENT 3 // 财务部

class Yuangong

{

public:

string name;

int age;

string tele;

double salary;

};

// 创建员工 5

// 返回值 void

void Create_Yuangong( vector<Yuangong> &v )

{

// 名字的随机数种子

string nameseed = "ABCDE";

for(int i = 0;i<5;i++)

{

// 循环创建员工

Yuangong yg;

yg.name = "员工";

// 名字加随机数种子

yg.name += nameseed[i];

// 年龄是随机数

yg.name = rand() %30;

// 薪水是随机数

yg.salary = rand() %10000 + 10000;

// 手机号是固定的

yg.tele = "+86-88888888";

// 把这名员工放到vector

v.push_back(yg);

}

}

// 给员工指派部门

//  入参:存放员工的vector容器, multimap<int,Yuangong>

void Set_YG_Group(vector<Yuangong>& v,multimap<int,Yuangong> & group){

for(vector<Yuangong>::iterator it = v.begin();it != v.end(); it++){

cout << "当前员工信息:" << endl;

cout << "名字:" << it->name << "年龄: " << it->age << "工资:" <<it->salary << "电话:" << it->tele << endl;

int departmentID = -1;

while(true){

cout << "请输入部门(1 销售部 2 开发部 3 财务部) : " << endl;

scanf("%d",& departmentID);

if(departmentID == SALE_DEPARTMENT){

group.insert(make_pair(SALE_DEPARTMENT,*it));

break;

}

else if(departmentID == DEVELOP_DEPARTMENT)

{

group.insert(make_pair(DEVELOP_DEPARTMENT,*it));

break;

}

else if(departmentID == FINACIAL_DEPARTMENT)

{

group.insert(make_pair(FINACIAL_DEPARTMENT,*it));

break;

}

else{

cout << "输入错误,请重新输入:" << endl;

}

}

}

}

// 打印各部门员工信息

void show_YG_Info(multimap<int,Yuangong> & group){

int departmentID = -1;

while(true){

cout << "请输入要查看的部门(1 销售部 2 开发部 3 财务部) : " << endl;

scanf("%d", &departmentID);

// 验证输入有效性

if (departmentID < 1 || departmentID > 3){

continue;

}

multimap<int,Yuangong>::iterator pos = group.find(departmentID);

int ygcount = group.count(departmentID);

int num =0;

while( pos != group.end() && num < ygcount){

cout << "姓名: " << pos->second.name << " 年龄:" << pos->second.age << " 工资:" << pos->second.salary << " 电话:" << pos->second.tele << endl;

num++;

pos++;

}

}

}

int main(void)

{

vector<Yuangong> v; // 1.存放员工的容器未分组之前

multimap<int,Yuangong> Ygroup; // 2.存放分组后的员工信息

Create_Yuangong(v); // 3.创建员工并存到容器v

Set_YG_Group(v,Ygroup); // 4.员工分组

show_YG_Info(Ygroup); // 5.按分组显示员工信息

return 0;

}

 

 

 

 

13 容器元素深拷贝和浅拷贝问题

14 容器的共性机制

 

  1. 1.      除了queue和stack 每个容器都有迭代器
  2. 2.      通常STL不会抛出异常 需要使用者传入正确参数
  3. 3.      每个容器都提供了一个默认的构造函数和默认的拷贝构造函数
  4. 4.      大小相关的构造方法: 

1 size() 返回容器中元素的个数

   2 empty() 判断容器是否为空

15函数对象课堂基本练习

 

容器是值语义的

拷贝是值拷贝,push_back的时候是直接把值给原封不动拷贝了一份

执行的是原对象的拷贝构造函数

报错代码:

原因:test01执行完毕的时候执行了两次析构 释放了相同的内存区域 导致报错

解决办法:

重载拷贝构造函数:

(这里把等号操作符也重载了 因为声明变量的时候使用=调用的也是拷贝构造函数

16 stl预定义函数对象

(减法:minus)

(谓词)

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>

#include <functional>

#include <string>

#include <vector>

#include <algorithm> // 欧狗瑞泽姆

using namespace std;

/*

template<class T> T plus<T> // 加法仿函数

template<class T> T minute<T> // 减法仿函数

template<class T> T multiplies<T> // 乘法仿函数

template<class T> T divides<T> // 除法仿函数

template<class T> T modules<T> // 取模仿函数

template<class T> T negate<T> // 取反仿函数

*/

void test01() {

plus<int> myplus;

int ret = myplus(10, 20);

cout << ret << endl;

plus<string> myplus2;

string s1 = "aaa";

string s2 = "bbb";

string ret2 = myplus2(s2, s1);

cout << ret2 << endl;

cout << plus<int>()(10,20) << endl;

}

// transform

void print(int v) {

cout << v << " ";

}

void test02() {

vector<int> v1, v2,v3;

for (int i = 0; i < 10;i++) {

v1.push_back(i);

v2.push_back(i + 1);

}

v3.resize(v1.size()); //

for_each(v3.begin(), v3.end(), print);

cout << endl;

cout << " -------------- " << endl;

transform(v1.begin(), v1.end(), v2.begin(), v3.begin(), plus<int>());

for_each(v3.begin(), v3.end(), print);

cout << endl;

}

int main(void)

{

test02();

return 0;

}

C++进阶 STL(2) 第二天 一元/二元函数对象、一元/二元谓词、stack容器、queue容器、list容器(双向链表)、set容器、对组、map容器的更多相关文章

  1. STL算法设计理念 - 二元函数,二元谓词以及在set中的应用

    demo 二元函数对象 #include <iostream> #include <cstdio> #include <vector> #include <a ...

  2. C++STL 预定义函数对象和函数适配器

    预定义函数对象和函数适配器 预定义函数对象基本概念:标准模板库STL提前定义了很多预定义函数对象,#include <functional> 必须包含. 1使用预定义函数对象: void ...

  3. STL 算法中函数对象和谓词

    STL 算法中函数对象和谓词 函数对象和谓词定义 函数对象: 重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象.一个类对象,表现出一个函数的特 ...

  4. C++ STL 之 函数对象适配器

    谓词是指普通函数或重载的 operator()返回值是 bool 类型的函数对象(仿函数).如果operator 接受一个参数,那么叫做一元谓词,如果接受两个参数,那么叫做二元谓词,谓词可作为一个判断 ...

  5. STL算法中函数对象和谓词

    函数对象和谓词定义 函数对象: 重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象.一个类对象,表现出一个函数的特征,就是通过“对象名+(参数列 ...

  6. C++STL 函数对象和谓词

    函数对象:重载函数调用操作符的类,其对象常称为函数对象. 函数对象属于类对象,能突破函数概念,保持类的状态 谓词: 一元函数对象:函数参数1个: 二元函数对象:函数参数2个: 一元谓词 函数参数1个, ...

  7. C++ STL——stack和queue

    目录 一 stack容器 二 queue容器 注:原创不易,转载请务必注明原作者和出处,感谢支持! 注:内容来自某培训课程,不一定完全正确! 栈和队列作为经典的数据结构,我们再熟悉不过了.C++ ST ...

  8. c++的bind1st()与bind2nd() 二元算子转一元算子

    bind1st()和bind2nd()是两个函数,用于将二元算子转成一元算子. 何谓二元算子? 比如< > =等等这些就是二元算子,即需要两个操作数的运算符. 何谓一元算子? 比如++ - ...

  9. C++进阶 STL(1) 第一天 [容器,算法,迭代器] string容器 vector容器 deque容器

    课程大纲 02实现基本原理 容器,算法,迭代器 教室:容器 人:元素 教室对于楼:容器 序列式容器: 容器元素在容器中的位置是由进入容器的时间和地点来决定 序列式容器 关联式容器: 教室中 按年龄排座 ...

随机推荐

  1. hdu 1829 带权并查集的运用类似于食物链但是更简单些

    #include<stdio.h> #define N 1100000 struct node { int x,y; }f[N],pre[N]; int find(int x) { if( ...

  2. Python——迭代器和解析(3)

    用迭代工具模拟zip和map ====================================================================== 我们已经知道了zip怎样组合 ...

  3. [ajax 学习笔记] ajax初试

    ajax全称是:asynchronous javasctipt and xml. 1.为什么须要ajax? 一般web程序与server的交互是:页面发送请求等待server处理,server处理数据 ...

  4. 2016.04.07,英语,《Vocabulary Builder》Unit 11

    cant, from the Latin verbs canere and cantare, meaning 'sing'. by way of French, add an h to the roo ...

  5. SQL SERVER读书笔记:阻塞与死锁

    阻塞是事务隔离带来的副作用,而并不是SQL SERVER的错. 死锁则是互相争用资源而引发.由于死锁会选择牺牲者,所以死锁的危害没有阻塞大.但有时为了解决死锁,会采取对资源加锁,导致阻塞的方式来避免.

  6. HDU1269 有向图强连通分量

    题目大意:问一个有向图是否任意两点在两个方向上互相连通. 有向图强连通分量定义:如果一个图中的任意两点在两个方向上都互相连通,则该图为强连通图.极大强连通图为有向图的强连通分量(注意是极大,不是最大. ...

  7. bootstrap搜索样式

    <div class="container"> <div class="input-group"> <input type=&qu ...

  8. [ZJOI 2010] 数字计数

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1833 [算法] 数位DP [代码] #include <algorithm&g ...

  9. 网络:万维网(WWW)

    ylbtech-网络:万维网(WWW) www (万维网缩写)同义词 万维网一般指www(万维网缩写)WWW是环球信息网的缩写,(亦作“Web”.“WWW”.“'W3'”,英文全称为“World Wi ...

  10. Object源码分析(二)

    第五个方法:protected native Object clone() throws CloneNotSupportedException; 源码简介: clone方法首先会判对象是否实现了Clo ...