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'; // 97int 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. 如果函数模版可以更好的匹配,优先调用函数模版
# 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;
}

类模版与函数模版区别:

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

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

类模版对象做函数参数:

三种传入方式:

  1. 指定传入的类型(直接显示对象的数据类型)
  2. 参数模版化(将对象中的参数变为模版进行传递)
  3. 整个类模版化(将这个对象类型 模版化进行传递)
# 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广义上分为,容器,算法,迭代器
  • 容器和算法之间通过迭代器进行无缝连接

六大组件:

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

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

容器:

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

算法:

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

迭代器:

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

本质:一个类

stringchar*区别:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/467552.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[VulnHub靶机渗透] Nyx

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【python】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏…

LeetCode、452. 用最少数量的箭引爆气球【中等,贪心,区间问题】

文章目录 前言LeetCode、452. 用最少数量的箭引爆气球【中等&#xff0c;贪心&#xff0c;区间问题】题目链接与分类思路贪心&#xff0c;连续区间数量问题 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客…

8868体育助力西甲最新积分榜 皇马4球大胜稳坐榜一

西甲联赛第24轮的四场比赛于2月10日全面收官。其中&#xff0c;皇马在主场迎战吉罗纳队&#xff0c;以4-0的大比分击败对手&#xff0c;将领先优势扩大到5分&#xff0c;稳坐西甲榜首&#xff0c;掌握了争冠的主动权。 威尼修斯的世界波为皇马打开胜利之门&#xff0c;第6分钟就…

ASCII码和EASCII码对照表

ASCII ASCII&#xff0c;是American Standard Code for Information Interchange的缩写&#xff0c; 是基于拉丁字母的一套电脑编码系统。它主要用于显示现代英语。ASCII的局限在于只能显示26个基本拉丁字母、阿拉伯数字和英式标点符号&#xff0c;因此只能用于显示现代美国英语…

数字图像处理(实践篇)四十六 OpenCV-Python 目标定位(Features2D + Homography)

目录 一 单映射Homography 二 涉及的函数 三 实践 一 单映射Homography 在计算机视觉中,平面的单应性被定义为一个平面到另外一个平面的投影映射。 单映射Homography 就是将一张图像上的点映射到另一张图像上的对应点的3x3变换矩阵。从下图中可以看出&#x

23种计模式之Python/Go实现

目录 设计模式what?why?设计模式&#xff1a;设计模式也衍生出了很多的新的种类&#xff0c;不局限于这23种创建类设计模式&#xff08;5种&#xff09;结构类设计模式&#xff08;7种&#xff09;行为类设计模式&#xff08;11种&#xff09; 六大设计原则开闭原则里氏替换原…

第2讲投票系统后端架构搭建

创建项目时&#xff0c;随机选择一个&#xff0c;后面会生成配置properties文件 生成文件 maven-3.3.3 设置阿里云镜像 <?xml version"1.0" encoding"UTF-8"?><!-- Licensed to the Apache Software Foundation (ASF) under one or more cont…

数据结构与算法:单链表

朋友们大家好&#xff0c;本节来到数据结构与算法的新内容&#xff1a;单链表 在上篇文章中&#xff0c;我们知道顺序表通常需要预分配一个固定大小的内存空间&#xff0c; 通常以二倍的大小进行增容&#xff0c;可能会造成空间的浪费&#xff0c;本篇文章我们介绍的链表可以解…

Linux-进程信号

Linux进程信号 初步认识信号信号的存储结构信号的处理方式信号的产生硬件异常产生的信号核心转储sigset_t信号集信号集的操作函数对block表的操作对pending表的操作对handler表的操作信号的捕捉用户态和内核态 信号的处理过程可重入函数volatile关键字 初步认识信号 生活中有哪…

本地搭建three.js官方文档

因为three.js官网文档是国外的网站&#xff0c;所以你没有魔法的情况下打开会很慢&#xff0c;这时我们需要在本地搭建一个官方文档便于我们学习查看。 第一步&#xff1a;首先我们先访问GitHub地址 GitHub - mrdoob/three.js: JavaScript 3D Library. 下载不下来的小伙伴们私…

Docker笔记-搭建Python环境、安装依赖、打包镜像、导入镜像、编写bash脚本灵活调用

说明 适合无联网的机器及多Python的机器进行部署。 制作docker版Python环境 有网络及有docker的&#xff0c;拉取指定版本的python如&#xff1a; docker pull python:3.7 安装好后进入容器&#xff1a; docker run -it <name> /bin/bash 使用pip安装各种依赖&…

Java基于SpringBoot+vue的租房网站,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…