C++万字笔记(黑马程序员):常用的STL容器与STL算法

这里写目录标题

string

构造函数

在这里插入图片描述
eg:

string s1;
const char *str = "";

string s2(str);//字符串初始化
string s3(s1);//string对象初始化对象
string s4(10, 'a');//字符初始化

赋值

  • 等号赋值 & assign赋值 (assgin可以赋值子串)
    在这里插入图片描述

eg:右值大致分为两种:string型和char*型

	string s1 = "abc";//等号char * 字符串赋值
	cout << "s1 = " << s1 << endl;
	
	string s2 = s1;//等号对象赋值
	cout << "s2 = " << s2 << endl;
	
	string s3 = 's';//字符赋值给字符串
					//有的编译器要报错,换成字符串类型的单个字符"s",才能通过编译
	cout << "s3 = " << s3 << endl;
	
	string sa1, sa2, sa3, sa4;		
	
	sa1.assign("hello NoneYY");//等价s1
	cout << "sa1 = " << sa1 << endl;
	
	sa2.assign("hello NoneYY", 5);//将前五个字符赋值给字符串(第一个参数为string时候,有的编译器会出错)
	cout << "sa2 = " << sa2 << endl;
	
	sa3.assign(sa1);//类似拷贝构造
	cout << "sa3 = " << sa1 << endl;
	
	sa4.assign(10, 'a');//n个字符赋值法
	cout << "sa4 = " << sa4 << endl;
  • 补充:
  1. 子串

substr()成员函数可以获得子串

  1. assign前一个参数放string对象时候 (assign获取子串)

后面参数为 begin位置和截取多少个
在这里插入图片描述
在这里插入图片描述

拼接

加号拼接 & append拼接
char* 与string型
随心所欲型
(注意: “” 与 “” 拼接时候,中间必须有string型,详细原因见c++primer
在这里插入图片描述
eg:(中文字符一个占两位)(只演示append)

	string s1("我");
	
	s1.append("喜欢C--", 5);			//char*型,拼接前面n个字符
	cout << "s1 = " << s1 << endl;
	
	s1.append("-++--", 1, 2);	//随心所欲法,起始位置,和个数。
	cout << "s1 = " << s1 <<endl;

在这里插入图片描述

  • 补充:
  1. 一个中文占两位在这里插入图片描述

查找与替换

  1. 查找

从左到右;
从右到左;
字符、string、char*;
char*的都有前n个的方法参数
未找到返回-1

  1. 替换

char*、string
起始位置 和 原来字符串要被替换的个数
传入的字符串有多少,替换后就有多少

在这里插入图片描述
eg:(比较简单)
在这里插入图片描述

  • 补充:
    如果查找不到就会返回一个值
    string::npos

字符串比较

字符串内部比较函数

str1.compare(str2)
返回 1,0,-1
str1大就返回1

字符存取

  • 读取
  1. 中括号【】访问,下标访问
  2. 成员函数at访问

str.at(i)

  1. 中括号改
  2. at一样

str.at(i) = ‘x’;

string插入和删除

在这里插入图片描述

string子串

  • 截取子串:起始地址,个数
    在这里插入图片描述
    邮件截取姓名eg:
#include<iostream>
using namespace std;
#include<string>

int main()
{
    
    
	string s = "[email protected]";
	
	int pos = s.find('@');
	cout << s.substr(0, pos) << endl;
	
}

在这里插入图片描述
string完结散花!


vector

(似数组,也叫单端数组,可以动态扩展)
(动态扩展机制:找一块更大空间,拷贝过去,删除原来的)
在这里插入图片描述

构造

  • 一个个赋初值
    v.push_back(value);
  • 构造函数,传入迭代器,左闭右开:
    vector<int>v (v1.begin(), v1.end());
  • 个数构造,第一个参数个数,第二个值:
    vector<char> v (10, 'A');
  • 拷贝构造(常用):
    vector<int> v1(v2);

赋值

等号 和 assign方法
在这里插入图片描述
eg:

v2.assign(v1.begin(), v1.end());

v3.assign(10, 100) //10个100

vector大小和容量

在这里插入图片描述

vector<int> v;
	for(int i = 0; i < 10; i++)
	{
    
    
		v.push_back(i);
	}
	
	if(!v.empty())//空判断
	{
    
    
		cout << "capacity: " << v.capacity() << endl;
		cout << "size: " << v.size() << endl;
		
	}
		
	v.resize(20, 0);//改大小
	for(vector<int>::iterator it = v.begin(); it != v.end(); it++ )
	{
    
    
		cout << *it << ' ';
	}

插入与删除

在这里插入图片描述

	vector<int> v;
	
	for(int i = 0; i < 10; i++)
	{
    
    
		v.push_back(i);//尾部插入
	}
	
	v.insert(v.begin(), 100);//迭代器位置插入
	v.insert(v.begin(), 2, 101);//插入,个数,值
	
	//删除,清空
	v.erase(v.begin());//删除某个位置
	v.erase(v.begin(), v.begin()+2);//删除区间,end前一个位置
	
	//全部删除
	v.clear();

存取

at()
[ ]括号
front()
back()
在这里插入图片描述

互换

在这里插入图片描述

  • 巧用:配合匿名对象,收缩内存
#include<iostream>
#include<vector>
using namespace std;

int main()
{
    
    
	vector<int> v;
	
	for(int i = 0; i < 1000; i++)
	{
    
    
		v.push_back(i);//尾部插入
	}
	
	v.resize(3);//只要前面3个
	//巧用swap收缩内存
	cout << "收缩前:\n" << "capacity:" << v.capacity() << "\nsize: " << v.size() << endl;
	//匿名对象,用完一行编译器就回收了
	vector<int>(v).swap(v);
	
	cout << "收缩后:\n" << "capacity:" << v.capacity() << "\nsize: " << v.size() << endl;
	
	return 0;
}

预留内存

reserve();
在这里插入图片描述

这里插入的数据较多,动态扩展次数会增多

	vector<int> v;
	
	int num = 0;//统计分配内存次数
	int *p = nullptr;
	for(int i = 0; i < 100000; i++)
	{
    
    
		v.push_back(i);//尾部插入
		if(p != &v[0])
		{
    
    
			p = &v[0];
			num++;
		}
	}
	cout << "内存分配次数: " << num << endl;

在这里插入图片描述
如果提前知道大概的大小,可以用reserve预留,减少动态扩展次数

	vector<int> v;
	//预留内存
	v.reserve(100000);
	
	int num = 0;//统计分配内存次数
	int *p = nullptr;
	for(int i = 0; i < 100000; i++)
	{
    
    
		v.push_back(i);//尾部插入
		if(p != &v[0])
		{
    
    
			p = &v[0];
			num++;
		}
	}
	cout << "内存分配次数: " << num << endl;

在这里插入图片描述
vector完结散花~~~


deque 双端数组

在这里插入图片描述

概念&构造

  1. 与vector相比,deque头部插入快,随机访问慢一点
  2. 构造方法:
    deque<int> q默认构造
    deque<int> q( Q.begin(), Q.end() )区间[ )元素赋值,Q不是必须deque类型
    deque<int> q( 10, 101 )10个101
    deque<int> q(Q)拷贝构造
    在这里插入图片描述
  3. 小细节:
  • 只读的引用参数,使用迭代器用const_itreator
  • 区间赋值可以用其他类型的迭代器
#include<iostream>
#include<vector>
#include<deque>
using namespace std;

void Print(const deque<int>&d)//只读引用
{
    
    				//只读迭代器
	for(deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
	{
    
    
		cout << *it << ' ';
	}
}

int main()
{
    
    
	vector<int> v;
	//预留内存
	v.reserve(100);
	
	for(int i = 0; i < 100; i++)
	{
    
    
		v.push_back(i);//尾部插入
	}
	
	//赋值打印
	deque<int>d(v.begin(), v.end());//这里赋值用的vector类型的迭代器
	Print(d);
	
	return 0;
}

赋值

几乎和vector一样,简略概括下

  • =
  • assign(beg, end);区间
  • assign(n,elem);n个元素
    在这里插入图片描述

大小操作

比较简单
与vector相比,没有容量

  • 空判断
  • 大小判断
  • 重置
    在这里插入图片描述

插入&删除

使用大同小异,略例子
在这里插入图片描述

存取

与vector一样,下标、at、front、back
在这里插入图片描述

排序(stl的算法)

在这里插入图片描述

Stack 和 Queue

构造、存取、大小、是否空
在这里插入图片描述

List(链表)容器

构造(和vector几乎一样)

空构造、区间构造、拷贝构造、几个几
在这里插入图片描述

赋值 & 交换

assign和=,
swap
在这里插入图片描述

大小&设置大小

在这里插入图片描述

插入和删除(多了个move)

多了个remove
在这里插入图片描述

存取(front,back,无法下标访问)

在这里插入图片描述
迭代器也不支持随机访问,只能++、–,不能it = it + 1
在这里插入图片描述

反转&排序

在这里插入图片描述

set / multiset容器

特点、构造与赋值

  • 插入时候自动排序
  • 底层是二叉树实现
  • set不能重复,multiset可以重复
  • 头文件只用包含set就可以用两个了

  • 构造赋值一样,=(指整个对象)和取名

插入(只能insert,不支持push)

插入、清除所有、删除某位子元素、删除区间、删除某个值(类似remove)
在这里插入图片描述

insert有返回值,一个pair
在这里插入图片描述

查找和统计

  • 不支持随机访问,
  • find返回迭代器
  • count统计某个数据有多少个
    在这里插入图片描述

pair创建

在这里插入图片描述

从大到小(仿函数)(与自定义数据类型排序)

class MyPare
{
    
    
	public:
		bool operator() (int v1, int v2)
		{
    
    
			return v1 > v2;
		}
};

void test01()
{
    
    
	set<int, MyPare> p;
	p.insert(12);
	p.insert(5);
	p.insert(18);
	p.insert(3);
	p.insert(1);
	p.insert(20);
	
	for(auto it = p.begin(); it != p.end(); it++)
	{
    
    
		cout << *it << " ";
	}
	
}

自定义数据类型

class Person
{
    
    
	public:
		string name;
		int age;
		
		Person(string name, int age)
		{
    
    
			this->age = age;
			this->name = name;
		}
};

class MyPare
{
    
    
	public:
		bool operator() (const Person &p1, const Person &p2)
		{
    
    
			return p1.age < p2.age;
		};
};

void test01()
{
    
    
	Person p1("M", 20);
	Person p2("Z", 21);
	Person p3("D", 19);
	
	set<Person, MyPare>s;
	s.insert(p1);
	s.insert(p2);
	s.insert(p3);
	
	for(set<Person, MyPare>::iterator it = s.begin(); it != s.end(); it++)
	{
    
    
		cout << it->name << " " << it->age << endl;
	}
	
}

map/multimap容器

概念,细节

  • 会根据键值自动排序
  • 一个可以重复key,一个不可以
  • 关联式容器,底层二叉树实现
    在这里插入图片描述
    构造和赋值
    在这里插入图片描述
    插入用pair
    在这里插入图片描述

大小、空(和之前的容器差不多)

在这里插入图片描述

插入、删除

  • 插入用pair
  • 删除有 pos、区间、全部 和 根据键值删除
    在这里插入图片描述
    插入
    在这里插入图片描述

查找、统计

查找是否存在

  • 找到返回该元素迭代器,否则返回end
    在这里插入图片描述

map排序(键值)

class MyPare
{
    
    
	public:
		bool operator() (string p1, string p2)
		{
    
    
			return p1 > p2;
		}
	
};

void test01()
{
    
    
	map<string, int, MyPare>m;
	m.insert(make_pair("1", 10));
	m.insert(make_pair("3", 30));
	m.insert(make_pair("2", 20));
	m.insert(make_pair("4", 40));
	
	for(auto it = m.begin(); it != m.end(); it++)
	{
    
    
		cout << it->first << ' ' << it->second << endl;
	}
}

函数对象

概念

是个对象
看起来像函数调用
可以作为参数传递
在这里插入图片描述

class MyPare
{
    
    
	public:
		string operator() (string s)
		{
    
    
			return s+"!!!";
		}
	
};

void test01()
{
    
    
	MyPare myPrint;
	cout << myPrint("仿函数(函数对象)") << endl;
}

在这里插入图片描述

谓词

概念

bool的仿函数
在这里插入图片描述

一元谓词例子:查找大于10的数(匿名对象,find_if算法)

class MyPare
{
    
    
	public:
		bool operator() (int val)
		{
    
    
			return val > 10;
		}
	
};

void test01()
{
    
    
	vector<int> v;
	v.push_back(7);
	v.push_back(10);
	v.push_back(19);
	v.push_back(7);
	v.push_back(7);
	
	//MyPare()匿名函数对象
	vector<int>::iterator iter = find_if(v.begin(), v.end(), MyPare());
	
	if(iter != v.end())
	{
    
    
		cout << *iter;
	}
	
}

在这里插入图片描述

二元谓词例子(sort排序匿名对象法)

class MyPare
{
    
    
	public:
		bool operator() (int val1, int val2)
		{
    
    
			return val1 > val2;
		}
	
};

void test01()
{
    
    
	vector<int> v;
	for(int i = 0; i < 10; i ++)
	{
    
    
		v.push_back(i);
	}
	
	sort(v.begin(), v.end(), MyPare());
	
	for(auto it = v.begin(); it != v.end(); it++)
	{
    
    
		cout << *it << " ";
	}	
}

内建函数

大致分类

使用需要包含头文件 <functional>
在这里插入图片描述

算术仿函数

在这里插入图片描述
eg:

  1. 取反
    在这里插入图片描述

关系仿函数

在这里插入图片描述
eg:

  1. 大于关系(最常用)
    和我们在排序里面写的大于仿函数类似
    在这里插入图片描述
void test01()
{
    
    
	vector<int>v;
	
	v.push_back(20);
	v.push_back(30);
	v.push_back(10);
	v.push_back(60);
	v.push_back(40);
	
	sort(v.begin(), v.end(), greater<int>());
	
	for(vector<int>::iterator it = v.begin(); it < v.end(); it++)
	{
    
    
		cout << *it << ' ';
	}
}

逻辑仿函数(在开发中几乎用不到)

在这里插入图片描述

STL常用算法

遍历for_each

  • 第三参数 函数名 或 函数对象方法
    在这里插入图片描述
void print(int val)
{
    
    
	cout << val << ' ';
}

class MyPrint
{
    
    
	public:
		void operator() (int val)
		{
    
    
			cout << val << ' ';
		}
};

void test01()
{
    
    
	vector<int>v;
	
	v.push_back(20);
	v.push_back(30);
	v.push_back(10);
	v.push_back(60);
	v.push_back(40);
	
	//调用普通函数,写函数名
	for_each(v.begin(), v.end(), print);
	
	cout << endl;
	
	//函数对象(仿函数),匿名函数方法
	for_each(v.begin(), v.end(), MyPrint());
}

搬运算法transform

  • 原容器区间、目标容器起始、操作函数(需要返回值)
  • 目标容器设置大小
    在这里插入图片描述
    在这里插入图片描述
class Trasform
{
    
    
	public:
		int operator() (int val)
		{
    
    
			return val+2;
		}
};

class MyPrint
{
    
    
	public:
		void operator() (int val)
		{
    
    
			cout << val << ' ';
		}
};

void test01()
{
    
    
	vector<int>v;
	
	v.push_back(20);
	v.push_back(30);
	v.push_back(10);
	v.push_back(60);
	v.push_back(40);
	
	vector<int>vTarget;
	//目标容器需要提前设置
	vTarget.resize(v.size());
	
	//Transform函数对象,对搬运的值进行操作,需要有返回值
	transform(v.begin(), v.end(), vTarget.begin(), Trasform());
	
	//遍历打印
	for_each(vTarget.begin(), vTarget.end(), MyPrint());
}

查找算法

在这里插入图片描述

find

第三个参数是查找值,
如果是自定义数据类型,需要重载比较方法在这里插入图片描述
重载了 ==

class Person
{
    
    
public:
	Person(string name, int age)
	{
    
    
		this->name = name;
		this->age = age;
	}
	bool operator== ( const Person &p )
	{
    
    
		if (this->name == p.name && this->age == p.age)
		{
    
    
			return true;
		}
		return false;
	}
	string name;
	int age;
};

void test01()
{
    
    
	vector<Person>v;

	Person p1("aaa", 10);
	Person p2("bbb", 20);
	Person p3("ccc", 30);
	Person p4("ddd", 40);

	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);

	vector<Person>::iterator it = find(v.begin(), v.end(), p2);
	if (it != v.end())
	{
    
    
		cout << "Found!\n" << endl;
	}
	else
	{
    
    
		cout << "No有" << endl;
	}
}

find_if

  • 第三个参数返回bool,是谓词(返回bool类型的仿函数)
    在这里插入图片描述
    自定义类型写的谓词
    在这里插入图片描述

adjacent_find查找相邻重复元素

  • 相邻,重复,返回第一个
    在这里插入图片描述

binary_search二分查找

  • 无序不可用,返回true或false,类似find
    在这里插入图片描述

count统计元素个数

在这里插入图片描述
eg:(无他,就重载了 ==)

class Person
{
    
    
public:
	Person(string name, int age)
	{
    
    
		this->name = name;
		this->age = age;
	}

	bool operator == (const Person& p)
	{
    
    
		if (p.age == this->age)
		{
    
    
			return true;
		}
		return false;
	}

	string name;
	int age;
};

void test01()
{
    
    
	vector<Person>v;

	Person p1("aaa", 20);
	Person p2("bbb", 19);
	Person p3("ccc", 21);
	Person p4("ddd", 22);

	Person p5("mzd", 20);

	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);

	int num = count(v.begin(), v.end(), p5);

	cout << " 结果 " << num << endl;
}

count_if

  • 同find_if,一个谓词
    在这里插入图片描述

排序算法

  • 排序、洗牌、合并、反转
    在这里插入图片描述

sort排序

在这里插入图片描述

内建函数的排序:greater
在这里插入图片描述

random_shuffler打乱

只用写区间就可以了
在这里插入图片描述
eg:

#include<ctime>
void test01()
{
    
    
	/* 初始化随机种子 */
	srand( (unsigned int)time(NULL) );
	
	vector<int> v;
	for(int i = 0; i < 10; i++)
	{
    
    
		v.push_back(i);
	}

	random_shuffle(v.begin(), v.end());

	for_each(v.begin(), v.end(), MyPrint());
		
}

merge合并(两个容器需要是有序的,合并后也是有序的)(但是不是有序也可以合并)

在这里插入图片描述

reverse反转

在这里插入图片描述

拷贝、替换算法

在这里插入图片描述

copy

  • 起始地址、目标首地址
    在这里插入图片描述

replace替换(旧换新)

在这里插入图片描述
在这里插入图片描述

replace_if按条件替换

在这里插入图片描述

swap互换两个容器

在这里插入图片描述

算术生成算法

包含头文件 numeric

  • 求总和、添加
    在这里插入图片描述

accumulate计算区间和

  • 第三个参数起始值
    在这里插入图片描述

fill 指定区间填充想要的值

在这里插入图片描述

常用的集合算法(不代表只能用 set 容器)

  • 并、交、差
    在这里插入图片描述

set_intersection 交集(有序)

  • 开辟目标容器大小时候,开辟小的容器大小
  • 算法会返回最后结束的地址,所以遍历的时候一般不用end
  • 所以常用一个迭代器接收
    在这里插入图片描述
void test01()
{
    
    
	vector<int>v1, v2;
	for(int i = 0; i <= 100; i++)
	{
    
    
		v1.push_back(i);
		v2.push_back(i + 50);
	}
		
	vector<int>vTarget;
	vTarget.resize( min(v1.size(), v2.size()) );
	
	auto vEnd = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
	
	for_each(vTarget.begin(), vEnd, MyPrint());	
}

set_union 并集

  • 也是排好序的
    在这里插入图片描述

set_difference 差集

  • v1与v2差积 和 v2与v1差积不一定一样
    在这里插入图片描述
void test01()
{
    
    
	vector<int>v1, v2;
	for(int i = 0; i <= 100; i++)
	{
    
    
		v1.push_back(i);
		v2.push_back(i + 50);
	}
		
	vector<int>vTarget;
	vTarget.resize( v1.size());
	
	auto vEnd = set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
	
	for_each(vTarget.begin(), vEnd, MyPrint());	
}


❀❀❀完结散花❀❀❀

猜你喜欢

转载自blog.csdn.net/foolbirdM/article/details/124235215