C++提高编程(黑马笔记)
C++提高编程
模版
特点:
- 只是一个框架,不可以直接使用
- 通用并不是万能的
泛型主要利用模版
函数模版
语法:
template<typename T>
函数
# include<iostream>
using namespace std;
template<typename T>
void MySwap(T& a, T& b) {
T temp = a;
a = b;
b = temp;
}
void test01() {
int a = 10;
int b = 20;
MySwap(a, b);
cout << a << " " << b << endl;
char c = 'a';
char d = 'b';
MySwap<char>(c, d);
cout << c << " " << d << endl;
}
int main() {
test01();
system("pause");
return 0;
}
注意事项:
- 自动类型推导,必须推导出一致的数据类型T,才可以使用
- 模版必须确定出T的数据类型才可以使用
# include<iostream>
using namespace std;
template<typename T>
void MySwap(T& a, T& b) {
T temp = a;
a = b;
b = temp;
}
template<class T>
void func() {
cout << "func" << endl;
}
void test01() {
int a = 10;
int b = 20;
MySwap(a, b);
char c = 'a';
//MySwap(c, a);
//func();
func<int>();
}
int main() {
test01();
system("pause");
return 0;
}
普通函数与函数模版的区别:
- 普通函数可以发生自动类型转换
- 函数模版调用时,如果利用自动类型推导,不会发生自动类型转换
- 如果利用显示指定类型的方式,可以发生自动类型转换
# include<iostream>
using namespace std;
template<typename T>
T MyAdd1(T a, T b) {
return a + b;
}
int MyAdd2(int a, int b) {
return a + b;
}
void test01() {
int a = 10;
int b = 20;
char c = 'a'; // 97
int ans = 0;
ans = MyAdd2(a, c);
cout << ans << endl;
//ans = MyAdd1(a, c);
ans = MyAdd1<int>(a, c);
cout << ans << endl;
}
int main() {
test01();
system("pause");
return 0;
}
普通函数与函数模版的调用规则:
- 都可实现,优先调用普通函数
- 可以通过空模版参数列表来强制调用函数模版
- 函数模版也可以重载
- 如果函数模版可以更好的匹配,优先调用函数模版
# include<iostream>
using namespace std;
void MySwap(int &a, int &b) {
cout << "普通函数" << endl;
}
template<typename T>
void MySwap(T &a, T &b) {
cout << "函数模版" << endl;
}
template<typename T>
void MySwap(T& a, T& b, int x) {
cout << "重载函数模版" << endl;
}
void test01() {
int a = 10;
int b = 2;
MySwap(a, b);
MySwap<>(a, b);
MySwap(a, b, 100);
char c = 'a';
char d = 'b';
MySwap(c, d);
}
int main() {
test01();
system("pause");
return 0;
}
局限性:
- 传入class类时,需要进行函数模版的重载
# include<iostream>
# include<string>
using namespace std;
class Person {
public:
Person(string name, int age) {
this->m_name = name;
this->m_age = age;
}
string m_name;
int m_age;
};
template<typename T>
bool MyCompare(T &a, T &b) {
if (a == b) {
return true;
}
return false;
}
template<> bool MyCompare(Person & a, Person & b) {
if (a.m_age == b.m_age && a.m_name == b.m_name) {
return true;
}
return false;
}
void test01() {
Person p1("张三", 19);
Person p2("罗向", 55);
Person p3("张三", 19);
if (MyCompare(p1, p2)) {
cout << "p1 p2 一样" << endl;
}
else {
cout << "p1 p2 不一样" << endl;
}
if (MyCompare(p1, p3)) {
cout << "p1 p3 一样" << endl;
}
else {
cout << "p1 p3 不一样" << endl;
}
}
int main() {
test01();
system("pause");
return 0;
}
类模版
语法:
template<typename T>
类
# include<iostream>
# include<string>
using namespace std;
template <class NameType, class AgeType>
class Person {
public:
Person(NameType name, AgeType age) {
this->m_name = name;
this->m_age = age;
}
void show() {
cout << m_name << " " << m_age << endl;
}
NameType m_name;
AgeType m_age;
};
void test01() {
Person<string, int> p("孙悟空", 999);
p.show();
}
int main() {
test01();
system("pause");
return 0;
}
类模版与函数模版区别:
类模版与函数模版区别主要有两点:
- 类模版没有自动类型推导的使用方式
- 类模版在模版参数列表中可以有默认参数
# include<iostream>
# include<string>
using namespace std;
template <class NameType, class AgeType = int>
class Person {
public:
Person(NameType name, AgeType age) {
this->m_name = name;
this->m_age = age;
}
void show() {
cout << m_name << " " << m_age << endl;
}
NameType m_name;
AgeType m_age;
};
void test01() {
//Person p("孙悟空", 999);
Person<string> p("财务科", 98);
p.show();
}
int main() {
test01();
system("pause");
return 0;
}
类模版中成员函数创建时机:
- 普通类中成员函数一开始就可以创建
- 类模版中成员函数在调用时才创建
# include<iostream>
# include<string>
using namespace std;
class Person1 {
public:
void show1() {
cout << 1 << endl;
}
};
class Person2 {
public:
void show2() {
cout << 2 << endl;
}
};
template<class T>
class MyClass {
public:
T obj;
void func1() {
obj.show1();
}
void func2() {
obj.show2();
}
};
void test01() {
MyClass<Person1> c;
c.func1();
//c.func2();
}
int main() {
test01();
system("pause");
return 0;
}
类模版对象做函数参数:
三种传入方式:
- 指定传入的类型(直接显示对象的数据类型)
- 参数模版化(将对象中的参数变为模版进行传递)
- 整个类模版化(将这个对象类型 模版化进行传递)
# include<iostream>
# include<string>
using namespace std;
template<class T1, class T2>
class Person {
public:
Person(T1 name, T2 age) {
this->m_name = name;
this->m_age = age;
}
void showPerson() {
cout << m_name << " " << m_age << endl;
}
T1 m_name;
T2 m_age;
};
void show1(Person<string, int> &p) {
p.showPerson();
}
template<class T1, class T2>
void show2(Person<T1, T2> &p) {
p.showPerson();
}
template<class T>
void show3(T& p) {
p.showPerson();
}
void test01() {
Person<string, int> p("孙悟空", 999);
show1(p);
show2(p);
show3(p);
}
int main() {
test01();
system("pause");
return 0;
}
类模版与继承:
注意事项:
- 当子类继承的父类是一个类模版时,子类在声明的时候,要指定出父类中的T类型
- 如果不指定,编译器无法给子类分配内存
- 如果想灵活指定出父类中T的类型,子类也虚变为类模版
# include<iostream>
# include<string>
using namespace std;
template<class T>
class Base {
public:
T m;
};
class Son1 : public Base<int> {
};
template<class T1, class T2>
class Son2 : public Base<T2> {
T1 obj;
};
void test01() {
Son2<int, char> s2;
}
int main() {
test01();
system("pause");
return 0;
}
类模版成员函数类外实现:
# include<iostream>
# include<string>
using namespace std;
template<class T1, class T2>
class Person {
public:
Person(T1 name, T2 age);
void showPerson();
T1 m_name;
T2 m_age;
};
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age) {
this->m_name = name;
this->m_age = age;
}
template<class T1, class T2>
void Person<T1, T2>::showPerson() {
cout << m_name << " " << m_age << endl;
}
void test01() {
Person<string, int> p("猪八戒", 888);
p.showPerson();
}
int main() {
test01();
system("pause");
return 0;
}
类模版分文件编写:
问题:类模版中成员函数创建时机是在调用阶段,导致分文件编写时链接不到
解决:
- 直接包含
.cpp
源文件 - 将声明和实现写到同一个文件中,更改后缀名为
.hpp
person.h
#pragma once
# include<iostream>
# include<string>
using namespace std;
template<class T1, class T2>
class Person {
public:
Person(T1 name, T2 age);
void showPerson();
T1 m_name;
T2 m_age;
};
person.cpp
#include "person.h"
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age) {
this->m_name = name;
this->m_age = age;
}
template<class T1, class T2>
void Person<T1, T2>::showPerson() {
cout << m_name << " " << m_age << endl;
}
main.cpp
# include<iostream>
# include<string>
# include "person.cpp"
using namespace std;
void test01() {
Person<string, int> p("猪八戒", 888);
p.showPerson();
}
int main() {
test01();
system("pause");
return 0;
}
person.hpp
#pragma once
# include<iostream>
# include<string>
using namespace std;
template<class T1, class T2>
class Person {
public:
Person(T1 name, T2 age);
void showPerson();
T1 m_name;
T2 m_age;
};
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age) {
this->m_name = name;
this->m_age = age;
}
template<class T1, class T2>
void Person<T1, T2>::showPerson() {
cout << m_name << " " << m_age << endl;
}
main.cpp
# include<iostream>
# include<string>
# include "person.hpp"
using namespace std;
void test01() {
Person<string, int> p("猪八戒", 888);
p.showPerson();
}
int main() {
test01();
system("pause");
return 0;
}
类模版与友元:
# include<iostream>
# include<string>
using namespace std;
template<class T1, class T2>
class Person;
template<class T1, class T2>
void showPerson2(Person<T1, T2> &p) {
cout << p.m_name << " " << p.m_age << endl;
}
template<class T1, class T2>
class Person {
//类内实现
friend void showPerson(Person<T1, T2> &p) {
cout << p.m_name << " " << p.m_age << endl;
};
//类外实现
friend void showPerson2<>(Person<T1, T2> &p);
public:
Person(T1 name, T2 age) {
this->m_name = name;
this->m_age = age;
};
private:
T1 m_name;
T2 m_age;
};
void test01() {
Person<string, int> p("猪八", 888);
showPerson2(p);
}
int main() {
test01();
system("pause");
return 0;
}
STL
基本概念
- STL广义上分为,容器,算法,迭代器
- 容器和算法之间通过迭代器进行无缝连接
六大组件:
容器,算法,迭代器,仿函数,适配器(配接器),空间配置器
- 容器:各种数据结构
- 算法:各种常用算法
- 迭代器:容器与算法之间的胶合剂
- 仿函数:行为类似函数,算法的某种策略
- 适配器:一种用来修饰容器或者仿函数或迭代器接口的东西
- 空间配置器:负责空间的配置与管理
容器:
- 序列式容器:强调值的排序
- 关联式容器:二叉树结构
算法:
- 质变算法:运算过程中会更改区间内的元素的内容。例如拷贝,替换,删除等
- 非质变算法:运算过程中不会更改区间内的元素的内容。例如查找,计数,遍历等
迭代器:
种类 | 功能 | 支持运算 |
---|---|---|
输入迭代器 | 只读数据 | 只读,支持++ == ! = |
输出迭代器 | 只写数据 | 只写,支持++ |
前向迭代器 | 读写操作,向前推进迭代器 | 读写,支持++ == ! = |
双向迭代器 | 读写操作,向前和向后操作 | 读写,支持++ – |
随机访问迭代器 | 读写操作,跳跃访问任意数据 | 读写,支持++ – [n] -n < <= > >= |
vector存放内置数据类型:
容器:vector
算法:for_each
迭代器:vector<int>::iterator
# include<iostream>
# include<string>
# include<vector>
# include<algorithm>
using namespace std;
void MyPrint(int val) {
cout << val << endl;
}
void test01() {
vector<int> v;
v.push_back(10);
v.push_back(23);
v.push_back(90);
//第一种
vector<int>::iterator isBegin = v.begin();
vector<int>::iterator isEnd = v.end();
while (isBegin != isEnd) {
cout << *isBegin << endl;
isBegin++;
}
//第二种
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << *it << endl;
}
//第三种
for_each(v.begin(), v.end(), MyPrint);
}
int main() {
test01();
system("pause");
return 0;
}
vector存放自定义数据类型:
# include<iostream>
# include<string>
# include<vector>
# include<algorithm>
using namespace std;
class Person {
public:
Person(string name, int age) {
this->m_age = age;
this->m_name = name;
}
string m_name;
int m_age;
};
void test01() {
vector<Person> v1;
Person p1("a", 10);
Person p2("b", 101);
v1.push_back(p1);
v1.push_back(p2);
for (vector<Person>::iterator it = v1.begin(); it != v1.end(); it++) {
cout << (*it).m_name << " " << (*it).m_age << endl;
cout << it->m_name << " " << it->m_age << endl;
}
vector<Person*> v2;
Person p3("c", 10);
Person p4("d", 101);
v2.push_back(&p3);
v2.push_back(&p4);
for (vector<Person*>::iterator it = v2.begin(); it != v2.end(); it++) {
cout << (*it)->m_name << " " << (*it)->m_age << endl;
}
}
int main() {
test01();
system("pause");
return 0;
}
容器嵌套容器:
# include<iostream>
# include<string>
# include<vector>
# include<algorithm>
using namespace std;
void test01() {
vector<vector<int>> v;
vector<int> v1;
vector<int> v2;
v1.push_back(1);
v1.push_back(2);
v2.push_back(3);
v2.push_back(5);
v.push_back(v1);
v.push_back(v2);
for (vector<vector<int>>::iterator it = v.begin(); it != v.end(); it++) {
for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++) {
cout << *vit << " ";
}
cout << endl;
}
}
int main() {
test01();
system("pause");
return 0;
}
string容器
本质:一个类
string
与char*
区别:
char*
是一个指针string
是一个类,类内部封装了char*
,管理这个字符串,是一个char*
的容器
构造函数:
string();
string(const char* s);
string(const string& str);
string(int n, char c)
void test01() {
string s1;
const char* str = "abc";
string s2(str);
cout << s2 << endl;
string s3(s2);
cout << s3 << endl;
string s4(10, 'c');
cout << s4 << endl;
}
赋值操作:
string& operator=(const char* s);
string& operator=(const string &s);
string& operator=(char c);
string& assign(const char *s);
string& assign(const char *s, int n);
string& assign(const string &s);
string& assign(int n, char c);
void test01() {
string s1;
s1 = "abc";
cout << s1 << endl;
string s2 = s1;
cout << s2 << endl;
string s3, s4, s5, s6;
s3.assign(s1);
cout << s3 << endl;
s4.assign(s1, 2);
cout << s4 << endl;
s5.assign("abh");
cout << s5 << endl;
s6.assign(10, 'e');
cout << s6 << endl;
}
字符串拼接:
string& operator+=(const char* str);
string& operator+=(const char c);
string& operator+=(const string& str);
string& append(const char* s);
string& append(const char* s, int n);
string& append(const string &s);
string& append(const string &s, int pos, int n);
void test01() {
string s1, s2, s3, s4, s5, s6;
s1 = "c";
s1 += "abc";
cout << s1 << endl;
s1 += 'm';
cout << s1 << endl;
s1 += s1;
cout << s1 << endl;
s2 = "l";
s2.append("hj");
cout << s2 << endl;
s2.append("abhasahdjhsady", 9);
cout << s2 << endl;
s2.append(s1);
cout << s2 << endl;
s2.append(s1, 3, 2);
cout << s2 << endl;
}
查找和替换:
int find(const string& str, int pos = 0) const;
int find(const char* s, int pos = 0) const;
int find(const char* s, int pos = 0, int n) const;
int find(const char c, int pos = 0) const;
int rfind(const string& str, int pos = npos) const;
int rfind(const char* s, int pos = npos) const;
int rfind(const char* s, int pos, int n) const;
int rfind(const char c, int pos = 0) const;
string& replace(int pos, int n, const string& str);
string& replace(int pos, int n, const char* s);
void test01() {
string s1, s2, s3, s4, s5, s6;
s1 = "abcdefg";
int ans = 0;
ans = s1.find("c");
ans = s1.find("fj");
ans = s1.rfind("de"); // 从右往左
cout << ans << endl;
s1.replace(1, 4, "11111");
cout << s1 << endl;
}
字符串比较:
按ASCLL
码进行对比
=
返回 0>
返回 1<
返回 -1
原型:
int compare(const string &s) const;
int compare(const char *s) const;
void test01() {
string s1, s2, s3, s4, s5, s6;
s1 = "abcdefg";
s2 = "abcdefg";
s3 = "zzz";
s4 = "aaa";
int ans = 0;
ans = s1.compare(s2);
ans = s1.compare(s3);
ans = s1.compare(s4);
cout << ans << endl;
}
字符存取:
char& operator[](int n);
char& at(int n);
void test01() {
string s1, s2, s3, s4, s5, s6;
s1 = "abcdefg";
for (int i = 0; i < s1.size(); i++) {
cout << s1[i] << " " << s1.at(i) << endl;
}
}
插入和删除:
string& insert(int pos, const char* s);
string& insert(int pos, const string& s);
string& insert(int pos, int n, char c);
string& erase(int pos, int n = npos);
void test01() {
string s1, s2, s3, s4, s5, s6;
s1 = "abcdefg";
s2 = "cde";
s1.insert(2,"zzz");
s1.insert(3, s2);
s1.insert(1, 10, 'a');
s1.erase(1, 10);
cout << s1 << endl;
}
子串:
string substr(int pos = 0, int n = npos) const
void test01() {
string s1, s2, s3, s4, s5, s6;
s1 = "abcdefg";
s2 = s1.substr(3, 5);
cout << s2 << endl;
}
vector容器
与数组非常相似,也称为单端数组,与数组的区别是可以动态扩展
动态扩展:
- 不是在原空间之后接新空间,而是找更大的内存空间,将原数据拷贝到新空间
构造函数:
vector<T> v;
vector(v.begin(), v.end());
vector(n, elem);
vector(const vector &vec)
void test01() {
vector<int> v1;
for (int i = 0; i < 10; i++) {
v1.push_back(i);
}
PrintVector(v1);
vector<int> v2(v1.begin(), v1.end());
PrintVector(v2);
vector<int> v3(10, 10);
PrintVector(v3);
vector<int> v4(v3);
PrintVector(v4);
}
赋值操作:
vector& operator=(const vector &vec);
assign(beg, end);
assign(n, elem);
void test01() {
vector<int> v1;
for (int i = 0; i < 10; i++) {
v1.push_back(i);
}
PrintVector(v1);
vector<int> v2 = v1;
PrintVector(v2);
vector<int> v3, v4;
v3.assign(v2.begin(), v2.end());
PrintVector(v3);
v4.assign(10, 12);
PrintVector(v4);
}
容量和大小:
empty();
capacity();
size();
resize(int num);
resize(int num, elem);
void test01() {
vector<int> v1;
for (int i = 0; i < 10; i++) {
v1.push_back(i);
}
PrintVector(v1);
if (v1.empty()) {
cout << "空" << endl;
}
else {
cout << v1.size() << endl;
cout << v1.capacity() << endl;
}
v1.resize(20);
cout << v1.size() << " " << v1.capacity() << endl;
}
插入和删除:
push_back(ele);
pop_back();
insert(const_iterator pos, ele);
insert(const_iterator pos, int count, ele);
erase(const_iterator pos);
erase(const_iterator start, const_iterator end);
clear();
void test01() {
vector<int> v1;
for (int i = 0; i < 10; i++) {
v1.push_back(i);
}
PrintVector(v1);
v1.pop_back();
PrintVector(v1);
v1.insert(v1.begin(), 2, 'c');
PrintVector(v1);
v1.erase(v1.begin());
PrintVector(v1);
}
数据存取:
at(int idx);
operator[];
front();
back();
void test01() {
vector<int> v1;
for (int i = 0; i < 10; i++) {
v1.push_back(i);
}
PrintVector(v1);
cout << v1.at(3) << " " << v1[8] << endl;
cout << v1.front() << " " << v1.back() << endl;
}
互换容器与预留空间:
swap(vec);
reserve(int len);
void test01() {
vector<int> v1, v2;
v1.reserve(100000);
int cnt = 0;
int* p = NULL;
for (int i = 0; i < 100000; i++) {
v1.push_back(i);
if (p != &v1[0]) {
p = &v1[0];
cnt++;
}
}
cout << cnt << endl;
//PrintVector(v1);
//for (int i = 100; i >= 90; i--) {
// v2.push_back(i);
//}
//PrintVector(v2);
//v1.swap(v2);
//PrintVector(v1);
//PrintVector(v2);
}
deque容器
双端数组,可以对头端进行插入删除操作
deque与vector区别:
- deque对头部的插入删除速度快
- vector访问元素的速度快
工作原理:
deque内部有中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据
中控器维护的是每个缓冲区的地址,使得使用deque时像一片连续的内存空间
构造函数:
deque<T>
deque(beg, end);
deque(n, else);
deque(const deque &deq);
void test01() {
deque<int> q1;
for (int i = 0; i < 10; i++) {
q1.push_back(i);
}
Print(q1);
deque<int> q2(q1.begin(), q1.end());
Print(q2);
deque<int> q3(10, 100);
Print(q3);
deque<int> q4(q3);
Print(q4);
}
赋值操作:
deque& operator=(const deque &deq);
assign(beg, end);
assign(n, elem);
void test01() {
deque<int> q1, q2, q3, q4;
for (int i = 0; i < 10; i++) {
q1.push_back(i);
}
Print(q1);
q2 = q1;
Print(q2);
q3.assign(q1.begin(), q1.end());
Print(q3);
q4.assign(10, 100);
Print(q4);
}
大小操作:
deque.empty();
deque.size();
deque.resize(num);
deque.resize(num, elem);
void test01() {
deque<int> q1, q2, q3, q4;
for (int i = 0; i < 10; i++) {
q1.push_back(i);
}
Print(q1);
if (q1.empty()) {
cout << "空" << endl;
}
else {
//deque没有容量的概念
cout << q1.size() << endl;
q1.resize(20);
cout << q1.size() << endl;
}
}
插入删除:
push_back(elem);
push_front(elem);
pop_back();
pop_front();
insert(pos, elem);
insert(pos, n, elem);
insert(pos, beg, end);
clear();
erase(beg, end);
erase(pos);
void test01() {
deque<int> q1, q2, q3, q4;
for (int i = 0; i < 10; i++) {
q1.push_back(i);
q2.push_front(i);
}
PrintDeque(q1);
q1.push_front(2);
PrintDeque(q1);
q1.pop_front();
q1.pop_back();
PrintDeque(q1);
q1.insert(q1.begin(), 99);
PrintDeque(q1);
q1.insert(q1.begin(), 10, 99);
PrintDeque(q1);
q1.insert(q1.begin(), q2.begin(), q2.end());
PrintDeque(q1);
q1.erase(q2.begin(), q2.end());
PrintDeque(q1);
}
数据存取与排序:
at(int idx);
operator[];
front();
back();
sort(iterator beg, iterator end);
void test01() {
deque<int> q1, q2, q3, q4;
for (int i = 0; i < 10; i++) {
q1.push_back(i);
q1.push_back(i + 10);
}
PrintDeque(q1);
cout << q1.at(2) << " " << q1[3] << endl;
cout << q1.front() << " " << q1.back() << endl;
sort(q1.begin(), q1.end());
PrintDeque(q1);
}
stack容器
构造函数与赋值:
stack<T> stk;
stack(const stack &stk);
stack& operator=(const stack &stk);
数据存取与大小操作:
push(elem);
pop();
top();
empty();
size();
void test01() {
stack<int> s1, s2;
for (int i = 0; i < 10; i++) {
s1.push(i);
}
s2 = s1;
while (!s1.empty()) {
cout << s1.top() << " " << s1.size() << endl;
s1.pop();
}
}
queue容器
构造函数:
queue<T> que;
queue(const queue &que);
赋值操作:
queue& operator=(const queue &que);
数据存取:
push(elem);
pop();
back();
front();
大小操作:
empty();
size();
void test01() {
queue<int> q1, q2;
for (int i = 0; i < 10; i++) {
q1.push(i);
}
while (!q1.empty()) {
cout << q1.front() << " " << q1.back() << " " << q1.size() << endl;
q1.pop();
}
}
list容器
优点:
- 动态内存分配,不会内存浪费和溢出
- 插入和删除便利,不会造成原有迭代器失效
缺点:
- 空间时间额外消耗大
构造函数:
list<T> list;
list(beg, end);
list(n, elem);
list(const list &lst);
void test01() {
list<char> list1, list2;
list<char> list3(10, 'c');
list<char> list4(list3);
}
赋值和交换:
assign(beg, end);
assign(n, elem);
list& operator=(const list &lst);
swap(lst);
void test01() {
list<char> list1, list2;
list<char> list3(10, 'c');
list<char> list4(list3);
list1.assign(list3.begin(), list3.end());
list2.assign(10, 'b');
PrintList(list1);
PrintList(list2);
PrintList(list3);
swap(list2, list3);
PrintList(list2);
PrintList(list3);
}
大小操作:
size();
empty();
resize(num);
resize(num, elem);
void test01() {
list<int> list1, list2;
for (int i = 0; i < 10; i++) {
list1.push_back(i);
}
PrintList(list1);
if (list1.empty()) {
cout << "空" << endl;
}
else {
cout << list1.size() << endl;
list1.resize(20, 0);
}
cout << list1.size() << endl;
PrintList(list1);
}
插入删除:
push_back(elem);
pop_back();
push_front(elem);
pop_front();
insert(pos, elem);
insert(pos, n, elem);
insert(pos, beg, end);
clear();
erase(beg, end);
erase(pos);
remove(elem);
void test01() {
list<int> list1, list2;
for (int i = 0; i < 10; i++) {
list1.push_back(i);
list1.push_back(19);
}
PrintList(list1);
list1.push_front(99);
list1.remove(19);
PrintList(list1);
list1.pop_front();
list1.pop_back();
PrintList(list1);
list1.insert(list1.end(), 9);
list1.insert(list1.end(), 9);
PrintList(list1);
list<int>::iterator it = list1.end();
it--;
list1.erase(it);
PrintList(list1);
}
数据存取与反转排序:
front();
back();
reverse();
sort();
void test01() {
list<int> list1, list2;
for (int i = 0; i < 10; i++) {
list1.push_back(i);
list1.push_back(i + 10);
}
PrintList(list1);
cout << list1.front() << " " << list1.back() << endl;
list1.reverse();
PrintList(list1);
list1.sort();
PrintList(list1);
}
set/multiset容器
本质:关联式容器,底层用二叉树实现
区别:
set
不允许有重复元素,multiset
允许
构造和赋值:
set<T> st;
set(const set &st);
set& operator=(const set &st);
void test01() {
set<int> s1;
set<int> s2(s1);
set<int> s3 = s1;
}
大小和交换:
size();
empty();
swap(st);
void test01() {
set<int> s1, s2;
for (int i = 0; i < 10; i++) {
s1.insert(i);
s2.insert(i + 10);
}
PrintSet(s1);
PrintSet(s2);
if (s1.empty()) {
cout << "空" << endl;
}
else {
cout << s1.size() << endl;
}
s1.swap(s2);
PrintSet(s1);
PrintSet(s2);
}
插入删除:
insert(elem);
clear();
erase(pos);
erase(beg, end);
erase(elem);
void test01() {
set<int> s1, s2;
for (int i = 0; i < 10; i++) {
s1.insert(i);
s2.insert(i + 10);
}
PrintSet(s1);
PrintSet(s2);
s2.erase(19);
PrintSet(s2);
}
查找统计:
find(key);
count(key);
void test01() {
set<int> s1, s2;
for (int i = 0; i < 10; i++) {
s1.insert(i);
s2.insert(i + 10);
}
PrintSet(s1);
PrintSet(s2);
set<int>::iterator it = s1.find(6);
cout << *it << endl;
if (s1.find(90) != s1.end()) {
cout << "找到90" << endl;
}
else {
cout << "找不到90" << endl;
}
cout << s1.count(15) << " " << s2.count(15) << endl;
}
pair对组创建:
pair<type, type> p (v1, v2);
pair<type, type> p = make_pair (v1, v2);
void test01() {
pair<string, int> p1("Tom", 11);
cout << p1.first << " " << p1.second << endl;
pair<string, int> p2 = make_pair("Steve", 18);
cout << p2.first << " " << p2.second << endl;
}
排序:
- 默认排序规则为从小到大
class MyCompare {
public:
bool operator()(int v1, int v2)const {
return v1 > v2;
}
};
void test01() {
set<int> s1, s2;
s1.insert(10);
s1.insert(40);
s1.insert(20);
s1.insert(90);
PrintSet(s1);
set<int, MyCompare> s3;
s3.insert(10);
s3.insert(40);
s3.insert(20);
s3.insert(90);
for (set<int, MyCompare>::iterator it = s3.begin(); it != s3.end(); it++) {
cout << (*it) << " ";
}
cout << endl;
}
map/multimap容器
简介:
- 所有元素都是pair
- 第一个元素为key,第二个元素是value
- 根据value自动排序
本质:
- 关联式容器,底层用二叉树实现
区别:
- map不允许重复key值元素
- multimap允许重复key元素
构造赋值:
map<T1, T2> mp;
map(const map &mp);
map& operator=(const map &mp);
void test01() {
map<int, char> m1;
map<int, char> m2(m1);
map<int, char> m3 = m2;
}
大小交换:
size();
empty();
swap(st);
void test01() {
map<int, char> m1, m2;
m1.insert(pair<int, char>(1, 'a'));
m1.insert(pair<int, char>(2, 'c'));
m1.insert(pair<int, char>(3, 'b'));
if (m1.empty()) {
cout << "空" << endl;
}
else {
PrintMap(m1);
cout << m1.size() << endl;
}
m2.insert(pair<int, char>(1, 'p'));
m2.insert(pair<int, char>(2, 'm'));
m2.insert(pair<int, char>(3, 'n'));
m1.swap(m2);
PrintMap(m1);
PrintMap(m2);
}
插入删除:
insert(elem);
clear();
erase(pos);
erase(beg, end);
erase(key);
void test01() {
map<int, char> m1, m2;
m1.insert(pair<int, char>(1, 'a'));
m1.insert(pair<int, char>(2, 'c'));
m1.insert(pair<int, char>(3, 'b'));
m2.insert(pair<int, char>(1, 'p'));
m2.insert(pair<int, char>(2, 'm'));
m2.insert(pair<int, char>(3, 'n'));
PrintMap(m2);
m2.erase(2);
PrintMap(m2);
m2.erase(m2.begin());
PrintMap(m2);
}
查找统计:
find(key);
count(key);
void test01() {
map<int, char> m1, m2;
m2.insert(pair<int, char>(1, 'p'));
m2.insert(pair<int, char>(2, 'm'));
m2.insert(pair<int, char>(3, 'n'));
m2.insert(pair<int, char>(4, 'p'));
PrintMap(m2);
map<int, char>::iterator pos = m2.find(2);
cout << (*pos).first << " " << (*pos).second << endl;
cout << m2.count(1) << endl;
}
排序:
void test01() {
map<int, int> m1, m2;
m2.insert(pair<int, int>(1, 10));
m2.insert(pair<int, int>(2, 30));
m2.insert(pair<int, int>(3, 20));
m2.insert(pair<int, int>(4, 40));
PrintMap(m2);
map<int, int, MyCompare> m3;
m3.insert(pair<int, int>(1, 10));
m3.insert(pair<int, int>(2, 30));
m3.insert(pair<int, int>(3, 20));
m3.insert(pair<int, int>(4, 40));
for (map<int, int, MyCompare>::iterator it = m3.begin(); it != m3.end(); it++) {
cout << (*it).second << " ";
}
cout << endl;
}
函数对象
概念:
- 重载函数调用操作符的类,其对象称为函数对象
- 函数对象使用重载的()时,行为类似函数调用,也叫仿函数
本质:
函数对象(仿函数)是一个类,不是一个函数
特点:
- 可以像普通函数一样使用
- 可以有自己的状态
- 可以作为参数传递
class MyAdd {
public:
int operator()(int v1, int v2) {
return v1 + v2;
}
};
class MyPrint {
public:
MyPrint() {
this->cnt = 0;
}
void operator()(string test) {
cout << test << endl;
this->cnt++;
}
int cnt;
};
void doPrint(MyPrint p, string text) {
}
void test01() {
MyAdd m;
cout << m(10, 11) << endl;
MyPrint p;
p("hello");
p("hello");
p("hello");
cout << p.cnt << endl;
doPrint(p, "helloo");
}
谓词:
- 返回bool类型的仿函数称为谓词
- 如果operator()接受一个参数,那么叫做一元谓词
- 如果operator()接受两个参数,那么叫做二元谓词
class JudgeFour {
public:
bool operator()(int v) {
return v > 4;
}
};
void test01() {
vector<int> v;
for (int i = 0; i < 6; i++) {
v.push_back(i);
}
vector<int>::iterator it = find_if(v.begin(), v.end(), JudgeFour());
if (it == v.end()) {
cout << "没找到" << endl;
}
else {
cout << *it << endl;
}
}
class JudgeFour {
public:
bool operator()(int v1, int v2) {
return v1 > v2;
}
};
void test01() {
vector<int> v;
for (int i = 0; i < 6; i++) {
v.push_back(i);
}
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << *it << " ";
}
cout << endl;
sort(v.begin(), v.end(), JudgeFour());
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
内建函数对象:
分类:
- 算术仿函数
- 关系仿函数
- 逻辑仿函数
用法:
- 这些仿函数所产生的对象,用法和一般函数完全相同
- 引入头文件
#include<functional>
算术仿函数:
template<class T> T plus<T>
加法template<class T> T minus<T>
减法template<class T> T multiplies<T>
乘法template<class T> T divides<T>
除法template<class T> T modulus<T>
取模template<class T> T negate<T>
取反
void test01() {
plus<int> p;
cout << p(10, 20) << endl;
minus<int> mi;
cout << mi(30, 20) << endl;
multiplies<int> mu;
cout << mu(2, 90) << endl;
divides<int> d;
cout << d(90, 2) << endl;
modulus<int> mo;
cout << mo(99, 2) << endl;
negate<int> n;
cout << n(9) << endl;
}
关系仿函数:
template<class T> bool equal_to<T>
等于template<class T> bool not_equal_to<T>
不等于template<class T> bool greater<T>
大于template<class T> bool greater_equal<T>
大于等于template<class T> bool less<T>
小于template<class T> bool less_equal<T>
小于等于
void test01() {
vector<int> v;
v.push_back(10);
v.push_back(70);
v.push_back(30);
v.push_back(40);
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << *it << " ";
}
cout << endl;
sort(v.begin(), v.end(), greater<int>());
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
逻辑仿函数:
template<class T> bool logical_and<T>
与template<class T> bool logical_or<T>
或template<class T> bool logical_not<T>
非
void test01() {
vector<bool> v;
v.push_back(true);
v.push_back(false);
v.push_back(true);
v.push_back(false);
for (vector<bool>::iterator it = v.begin(); it != v.end(); it++) {
cout << *it << " ";
}
cout << endl;
vector<bool> c;
c.resize(v.size());
transform(v.begin(), v.end(), c.begin(), logical_not<bool>());
for (vector<bool>::iterator it = c.begin(); it != c.end(); it++) {
cout << *it << " ";
}
}
遍历算法
for_each:
for_each(iterator beg, iterator end, _func);
void print01(int v) {
cout << v << " ";
}
class print02 {
public:
void operator()(int v) {
cout << v << " ";
}
};
void test01() {
vector<int> v;
for (int i = 0; i < 10; i++) {
v.push_back(i);
}
for_each(v.begin(), v.end(), print01);
cout << endl;
for_each(v.begin(), v.end(), print02());
}
transform:
拷贝到另一个容器
transform(iterator beg1, iterator end1, iterator beg2, _func)
void print01(int v) {
cout << v << " ";
}
class Transform {
public:
int operator()(int v) {
return v;
}
};
void test01() {
vector<int> v;
for (int i = 0; i < 10; i++) {
v.push_back(i);
}
for_each(v.begin(), v.end(), print01);
cout << endl;
vector<int> c;
c.resize(v.size());
transform(v.begin(), v.end(), c.begin(), Transform());
for_each(c.begin(), c.end(), print01);
cout << endl;
}
查找算法
函数原型:
find(iterator beg, iterator end, value);
查找返回下标find_if(iterator beg, iterator end, _Pred);
条件查找adjacent_find(iterator beg, iterator end);
查找相邻重复元素bool binary_search(iterator beg, iterator end, value);
二分查找count(iterator beg, iterator end, value)
统计元素出现次数count_if(iterator beg, iterator end, _Pred)
条件统计
void MyPrint(vector<int> v) {
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
class GreaterFive {
public:
int operator()(int v) {
return v > 5;
}
};
void test01() {
vector<int> v;
for (int i = 0; i < 10; i++) {
v.push_back(i);
if (i > 7) {
v.push_back(7);
v.push_back(7);
}
}
MyPrint(v);
vector<int>::iterator it1 = find(v.begin(), v.end(), 9);
cout << *it1 << endl;
vector<int>::iterator it2 = find_if(v.begin(), v.end(), GreaterFive());
cout << *it2 << endl;
vector<int>::iterator it3 = adjacent_find(v.begin(), v.end());
cout << *it3 << endl;
bool ans = binary_search(v.begin(), v.end(), 7);
cout << ans << endl;
int res = count(v.begin(), v.end(), 7);
cout << res << endl;
int cnt = count_if(v.begin(), v.end(), GreaterFive());
cout << cnt << endl;
}
排序算法
函数原型:
sort(iterator beg, iterator end, _Pred)
排序random_shuffle(iterator beg, iterator end)
随机排序merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
合并两个容器 存储到另一个容器reverse(iterator beg, iterator end)
反转
void MyPrint(vector<int> v) {
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
void Print(int v) {
cout << v << " ";
}
void test01() {
vector<int> v;
for (int i = 0; i < 10; i++) {
v.push_back(i);
}
MyPrint(v);
sort(v.begin(), v.end(), MySort());
MyPrint(v);
random_shuffle(v.begin(), v.end());
MyPrint(v);
}
void test02() {
vector<int> v, c;
for (int i = 0; i < 10; i++) {
v.push_back(i);
c.push_back(i + 10);
}
vector<int> target;
target.resize(v.size() + c.size());
merge(v.begin(), v.end(), c.begin(), c.end(), target.begin());
for_each(target.begin(), target.end(), Print);
cout << endl;
reverse(target.begin(), target.end());
MyPrint(target);
}
拷贝替换算法
函数原型:
copy(iterator beg, iterator end, iterator dest)
拷贝到另一个容器replace(iterator beg, iterator end, oldvalue, newvalue)
指定范围内更换元素replace(iterator beg, iterator end, _pred, newvalue)
条件替换swap(container c1, container c2)
互换两个容器的元素
void MyPrint(vector<int> v) {
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
void Print(int v) {
cout << v << " ";
}
class MyWeici {
public:
int operator()(int v1) {
return v1 > 5;
}
};
void test02() {
vector<int> v, c;
for (int i = 0; i < 10; i++) {
v.push_back(i);
}
MyPrint(v);
vector<int> target;
target.resize(v.size());
copy(v.begin(), v.end(), target.begin());
MyPrint(target);
replace(target.begin(), target.end(), 6, 99);
MyPrint(target);
replace_if(target.begin(), target.end(), MyWeici(), 99);
MyPrint(target);
swap(v, target);
MyPrint(v);
MyPrint(target);
}
算术生成算法
函数原型:
accumulate(iterator beg, iterator end, value)
计算容器元素和fill(iterator beg, iterator end, value)
向容器中填充指定元素
void test02() {
vector<int> v, c;
for (int i = 0; i < 10; i++) {
v.push_back(i);
}
MyPrint(v);
int sum = accumulate(v.begin(), v.end(), 0);
cout << sum << endl;
c.resize(20);
fill(c.begin(), c.end(), 100);
MyPrint(c);
}
集合算法
函数原型:
set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
交集set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
并集set_difference(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
差集
void test02() {
vector<int> v, c;
for (int i = 0; i < 10; i++) {
v.push_back(i);
c.push_back(i + 5);
}
MyPrint(v);
MyPrint(c);
vector<int> target;
//target.resize(min(v.size(), c.size()));
//set_intersection(v.begin(), v.end(), c.begin(), c.end(), target.begin());
//target.resize(v.size() + c.size());
//set_union(v.begin(), v.end(), c.begin(), c.end(), target.begin());
target.resize(max(v.size(), c.size()));
set_difference(v.begin(), v.end(), c.begin(), c.end(), target.begin());
MyPrint(target);
}