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. 暑假集训D12总结

    刷题 今天终于不考试= = 上午刷了一大圈线段树板子题,于是算是学会了Zkw线段树= = 下午昨天的dalao又来讲几何,然而仍然没有笔记= = 于是刷了一大圈计算几何的水题= =,并没哟啥可以写出题 ...

  2. 【ACM】hdu_1106_排序_201308071928

    排序Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submissio ...

  3. 洛谷 P3004 [USACO10DEC]宝箱Treasure Chest

    P3004 [USACO10DEC]宝箱Treasure Chest 题目描述 Bessie and Bonnie have found a treasure chest full of marvel ...

  4. EL表达式无法被解析

    刚困死了,但是手上还在debug一个东西.然后就发现

  5. 为什么用clojure作为storm 的主要开发语言

    Why you choose Clojure as the development language of Storm? Could you talk about your long practica ...

  6. 为大家推荐一本书《jQuery Mobile 即学即用》

    这是人民邮电出版社出版的一本面向前端开发者的书. 非常喜欢书名"即学即用"这是每一个程序开发者的理想模式. 不同国家的人有不同的思维方式.这本书的作者是 [阿根廷] Maximil ...

  7. NYOJ_268_荷兰国旗问题

    荷兰国旗问题 时间限制:3000 ms  |  内存限制:65535 KB 难度:1 描写叙述 荷兰国旗有三横条块构成,自上到下的三条块颜色依次为红.白.蓝.现有若干由红.白.蓝三种颜色的条块序列.要 ...

  8. luogu1120 小木棍【数据加强版】 暴力剪枝

    题目大意 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50.现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度.给出每段小木棍的长度,编程帮 ...

  9. bzoj4465: [Jsoi2013]游戏中的学问

    DP 一个人要么加入一个圈,要么三个人开一圈 #include<cstdio> #include<iostream> #include<cstring> #incl ...

  10. Swift - 获取当前时间的时间戳(时间戳与时间互相转换)

    (本文代码已升级至Swift3) 1,时间戳 时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数. 2,获取当前时间的时 ...