C++提高编程(黑马笔记)

C++提高编程

模版

特点:

  • 只是一个框架,不可以直接使用
  • 通用并不是万能的

泛型主要利用模版

函数模版

语法:

cpp 复制代码
template<typename T>
函数
cpp 复制代码
# 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的数据类型才可以使用
cpp 复制代码
# 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;
}

普通函数与函数模版的区别:

  • 普通函数可以发生自动类型转换
  • 函数模版调用时,如果利用自动类型推导,不会发生自动类型转换
  • 如果利用显示指定类型的方式,可以发生自动类型转换
cpp 复制代码
# 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;
}

普通函数与函数模版的调用规则:

  1. 都可实现,优先调用普通函数
  2. 可以通过空模版参数列表来强制调用函数模版
  3. 函数模版也可以重载
  4. 如果函数模版可以更好的匹配,优先调用函数模版
cpp 复制代码
# 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类时,需要进行函数模版的重载
cpp 复制代码
# 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;
}

类模版

语法:

cpp 复制代码
template<typename T>
类
cpp 复制代码
# 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;
}

类模版与函数模版区别:

类模版与函数模版区别主要有两点:

  1. 类模版没有自动类型推导的使用方式
  2. 类模版在模版参数列表中可以有默认参数
cpp 复制代码
# 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;
}

类模版中成员函数创建时机:

  • 普通类中成员函数一开始就可以创建
  • 类模版中成员函数在调用时才创建
cpp 复制代码
# 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;
}

类模版对象做函数参数:

三种传入方式:

  1. 指定传入的类型(直接显示对象的数据类型)
  2. 参数模版化(将对象中的参数变为模版进行传递)
  3. 整个类模版化(将这个对象类型 模版化进行传递)
cpp 复制代码
# 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的类型,子类也虚变为类模版
cpp 复制代码
# 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;
}

类模版成员函数类外实现:

cpp 复制代码
# 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

cpp 复制代码
#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

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

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

cpp 复制代码
#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

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;
}

类模版与友元:

cpp 复制代码
# 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广义上分为,容器,算法,迭代器
  • 容器和算法之间通过迭代器进行无缝连接

六大组件:

容器,算法,迭代器,仿函数,适配器(配接器),空间配置器

  1. 容器:各种数据结构
  2. 算法:各种常用算法
  3. 迭代器:容器与算法之间的胶合剂
  4. 仿函数:行为类似函数,算法的某种策略
  5. 适配器:一种用来修饰容器或者仿函数或迭代器接口的东西
  6. 空间配置器:负责空间的配置与管理

容器:

  • 序列式容器:强调值的排序
  • 关联式容器:二叉树结构

算法:

  • 质变算法:运算过程中会更改区间内的元素的内容。例如拷贝,替换,删除等
  • 非质变算法:运算过程中不会更改区间内的元素的内容。例如查找,计数,遍历等

迭代器:

种类 功能 支持运算
输入迭代器 只读数据 只读,支持++ == ! =
输出迭代器 只写数据 只写,支持++
前向迭代器 读写操作,向前推进迭代器 读写,支持++ == ! =
双向迭代器 读写操作,向前和向后操作 读写,支持++ --
随机访问迭代器 读写操作,跳跃访问任意数据 读写,支持++ -- [n] -n < <= > >=

vector存放内置数据类型:

容器:vector

算法:for_each

迭代器:vector<int>::iterator

cpp 复制代码
# 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存放自定义数据类型:

cpp 复制代码
# 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;
}

容器嵌套容器:

cpp 复制代码
# 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容器

本质:一个类

stringchar*区别:

  • char*是一个指针
  • string是一个类,类内部封装了char*,管理这个字符串,是一个char*的容器

构造函数:

  • string();
  • string(const char* s);
  • string(const string& str);
  • string(int n, char c)
cpp 复制代码
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);
cpp 复制代码
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);
cpp 复制代码
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);
cpp 复制代码
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;
cpp 复制代码
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);
cpp 复制代码
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);
cpp 复制代码
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
cpp 复制代码
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)
cpp 复制代码
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);
cpp 复制代码
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);
cpp 复制代码
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();
cpp 复制代码
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();
cpp 复制代码
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);
cpp 复制代码
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);
cpp 复制代码
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);
cpp 复制代码
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);
cpp 复制代码
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);
cpp 复制代码
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);
cpp 复制代码
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();
cpp 复制代码
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();
cpp 复制代码
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);
cpp 复制代码
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);
cpp 复制代码
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);
cpp 复制代码
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);
cpp 复制代码
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();
cpp 复制代码
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);
cpp 复制代码
void test01() {
	set<int> s1;
	set<int> s2(s1);
	set<int> s3 = s1;
}

大小和交换:

  • size();
  • empty();
  • swap(st);
cpp 复制代码
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);
cpp 复制代码
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);
cpp 复制代码
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);
cpp 复制代码
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;
}

排序:

  • 默认排序规则为从小到大
cpp 复制代码
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);
cpp 复制代码
void test01() {
	map<int, char> m1;
	map<int, char> m2(m1);
	map<int, char> m3 = m2;
}

大小交换:

  • size();
  • empty();
  • swap(st);
cpp 复制代码
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);
cpp 复制代码
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);
cpp 复制代码
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;
}

排序:

cpp 复制代码
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;
}

函数对象

概念:

  • 重载函数调用操作符的类,其对象称为函数对象
  • 函数对象使用重载的()时,行为类似函数调用,也叫仿函数

本质:

函数对象(仿函数)是一个类,不是一个函数

特点:

  • 可以像普通函数一样使用
  • 可以有自己的状态
  • 可以作为参数传递
cpp 复制代码
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()接受两个参数,那么叫做二元谓词
cpp 复制代码
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;
	}
}
cpp 复制代码
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> 取反
cpp 复制代码
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> 小于等于
cpp 复制代码
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>
cpp 复制代码
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);
cpp 复制代码
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)
cpp 复制代码
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) 条件统计
cpp 复制代码
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) 反转
cpp 复制代码
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) 互换两个容器的元素
cpp 复制代码
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) 向容器中填充指定元素
cpp 复制代码
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) 差集
cpp 复制代码
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);
}
相关推荐
cuisidong199717 分钟前
5G学习笔记三之物理层、数据链路层、RRC层协议
笔记·学习·5g
乌恩大侠19 分钟前
5G周边知识笔记
笔记·5g
小刘|22 分钟前
《Java 实现希尔排序:原理剖析与代码详解》
java·算法·排序算法
jjyangyou27 分钟前
物联网核心安全系列——物联网安全需求
物联网·算法·安全·嵌入式·产品经理·硬件·产品设计
van叶~43 分钟前
算法妙妙屋-------1.递归的深邃回响:二叉树的奇妙剪枝
c++·算法
简简单单做算法44 分钟前
基于Retinex算法的图像去雾matlab仿真
算法·matlab·图像去雾·retinex
knighthood20011 小时前
解决:ros进行gazebo仿真,rviz没有显示传感器数据
c++·ubuntu·ros
云卓SKYDROID1 小时前
除草机器人算法以及技术详解!
算法·机器人·科普·高科技·云卓科技·算法技术
半盏茶香1 小时前
【C语言】分支和循环详解(下)猜数字游戏
c语言·开发语言·c++·算法·游戏
徐子童1 小时前
双指针算法习题解答
算法