C++容器

STL初识

STL为标准模板库,包括

  • 容器

各种数据结构,用来存放数据

1.序列是容器,数据有固定的位置

2.关联式容器,数据间没有数据关系

  • 算法

各种常见算法,如遍历,删除,查找

1.质变算法,运算过程中会改变区间内元素的值

2.非质变算法,不会改变元素的值

  • 迭代器

连接容器与算法

每种容器有自己专属的迭代器,其作用类似于指针

迭代器有五种

输入迭代器只读
输出迭代器只写
前向迭代器读写,并能向前推动迭代器
双向迭代器读写,并进行双向操作
随机访问迭代器读写,跳跃式访问任意数据

最常用的为双向和随机访问迭代器

  • 仿函数

行为类似函数,可作为算法的某种策略

  • 适配器

修饰仿函数,迭代器接口,容器

  • 空间配置器

负责空间的配置与管理

vector容器

迭代器:iterator

存放默认数据类型

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
void myprint(int a)
{
	cout << a << endl;
}
int main()
{   
	vector<int> v;  //<>内为要操作的数据类型
	v.push_back(10); //向v中添加元素,尾插
	v.push_back(20);
	v.push_back(30);
	v.push_back(40);
	v.push_back(50);
	
	//通过迭代器访问元素
	 //获取迭代器,并指向容器首个元素
	vector<int>::iterator itBegin = v.begin();
	//结束迭代器指向最后元素的下一个位置
	vector<int>::iterator itEnd = v.end();
	//第一种遍历
	while (itBegin!=itEnd)
	{
		cout << *itBegin << endl;
		itBegin++;
	}
	//第二种遍历
	for(vector<int>::iterator it = v.begin();it!=v.end();it++)
	 {
			cout<< *it <<endl;
	 }
	//第三种遍历,for_each算法,包含算法头文件
	for_each(v.begin(), v.end(), myprint);



	return 0;
}

存放自定义数据类型

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
class Person
{
public:
	Person(string name, int age)
	{
		this->name = name;
		this->age = age;
	}
	string name;
	int age;

};
void myprint(Person a)
{
	cout << a.name << "  " << a.age << endl;
}
int main()
{   
	Person p1("Ash", 20);
	Person p2("Bob", 25);
	Person p3("Cindy", 30);
	Person p4("David", 35);
	Person p5("Emma", 40);
	vector<Person> v;  //<>内为要操作的数据类型
	v.push_back(p1); //向v中添加元素,尾插
	v.push_back(p2);
	v.push_back(p2);
	v.push_back(p4);
	v.push_back(p5);
	
	//通过迭代器访问元素
	 //获取迭代器,并指向容器首个元素
	vector<Person>::iterator itBegin = v.begin();
	//结束迭代器指向最后元素的下一个位置
	vector<Person>::iterator itEnd = v.end();
	//第一种遍历
	while (itBegin!=itEnd)
	{
		cout << itBegin->name<<"   "<<itBegin->age << endl;
		itBegin++;
	}
	//第二种遍历
	for(vector<Person>::iterator it = v.begin();it!=v.end();it++)
	 {
			cout<< it->name<<"   "<<it->age <<endl;
	 }
	//第三种遍历,for_each算法,包含算法头文件
	for_each(v.begin(), v.end(), myprint);



	return 0;
}

vector容器的嵌套

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
int main()
{
	vector<vector<int>> v;
	vector<int> v1;
	vector<int> v2;
	vector<int> v3;
	vector<int> v4;
	for (int i = 0; i < 3; i++)
	{
		v1.push_back(i);
		v2.push_back(i + 3);
		v3.push_back(i + 6);
		v4.push_back(i + 9);
	}
	v.push_back(v1);
	v.push_back(v2);
	v.push_back(v3);
	v.push_back(v4);
	for (vector<vector<int>>::iterator it = v.begin(); it != v.end(); it++)
	{
		for (vector<int>::iterator it2 = (*it).begin(); it2 != (*it).end(); it2++)
		{
			cout <<*it2 << " ";
		}
		cout << endl;
	}
	return 0;
}

string容器

string容器的本质是一个含有char*成员变量的类

构造函数

#include<iostream>
using namespace std;
#include<vector>
#include<string>
//string容器的构造方式
int main()
{
	string s1;  //默认构造
	const char* str = "cefvec";
	string s2(str);      //拷贝c语言字符串
	string s3(s2);   //拷贝string类型字符串
	string s4(5, '-');  //拷贝n个字符


	return 0;
}

赋值操作

#include<iostream>
using namespace std;
#include<vector>
#include<string>
//string容器的赋值
int main()
{
	string s1;
	s1 = "hello";  //直接赋值

	string s2;
	s2 = s1; //

	string s3;
	s3.assign("hello world"); //使用assign函数赋值

	string s4;
	s4.assign("helloajci", 6); //使用assign函数赋值,指定长度

	string s5;
	s5.assign(s1);

	string s6;
	s6.assign(s1, 1, 3);  //输出字符串,并指定开始下标,和位数
	
	string s7;
	s7.assign('a', 7);
	return 0;
}

字符串拼接

#include<iostream>
using namespace std;
#include<vector>
#include<string>
//string容器的赋值
int main()
{
	string s1 = "我";
	s1 += "j";	   //+=在尾部拼接
	
	string s2 = "你好";
	s2 = s2+s1;
					//赋值号拼接
	string s3;
	s3.append(s2);   //append在尾部拼接

	s3.append(s2, 1, 3); //在s3尾部拼接s2的1号索引开始的三个字符
	return 0;
}

vector容器

与数组相比,vector容器可以进行扩容,原理是找到更大的空间,将原来数据拷贝到更大的空间

构造函数

#include<iostream>
using namespace std;
#include<vector>
void Myprint(vector<int>& v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}
int main()
{
	vector<int>v1;    //默认构造
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	Myprint(v1);

	vector<int>v2(10, 2);    //10个元素,每个元素为2
	Myprint(v2);

	vector<int>v3(v1.begin(), v1.end());    //v1的区间构造
	
	vector<int>v4(v3);    //v3的拷贝构造

	return 0;
}

赋值操作

#include<iostream>
using namespace std;
#include<vector>
void Myprint(vector<int>& v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}
int main()
{
	vector<int>v1;    //默认构造
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	Myprint(v1);

	vector<int>v2 = v1; //等号赋值

	vector<int>v3;
	v3.assign(v1.begin(), v1.end()); //assign函数赋值

	vector<int>v4(10, 1);  //构造函数赋值,表示10个1

	vector<vector<int>>v5;
	v5.push_back(v1);
	v5.push_back(v2);
	v5.push_back(v3);
	v5.push_back(v4);
	for (vector<vector<int>>::iterator it = v5.begin(); it != v5.end(); it++)
	{
		Myprint(*it);
	}
	return 0;
}

容量和大小

容量和大小,容量永远不小于大小

int main()
{
	vector<int>v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	cout << "大小为:" << v1.size() << endl; //即元素个数
	cout << "容量为:" << v1.capacity() << endl; //即分配的内存大小
	
	return 0;
}

此外还可以对容器大小进行重定义,如果重定义大小>原大小,则多出的部分默认用0填充,若小于原来,则多出的部分会被删除

#include<iostream>
using namespace std;
#include<vector>
void Myprint(vector<int>& v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}
int main()
{
	vector<int>v1;
	vector<int>v2;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	v2 = v1;
	cout << "大小为:" << v1.size() << endl; //即元素个数
	cout << "容量为:" << v1.capacity() << endl; //即分配的内存大小
	v1.resize(3);
	Myprint(v1);
	v2.resize(20, 100);
	Myprint(v2);
	return 0;
}

最后empty()函数可以判断容器是否为空,若为空则返回1;

插入和删除

int main()
{
	vector<int>v1;
	//尾插和尾删
	v1.push_back(3); //尾插
	v1.pop_back();   //尾删
	//插入
	v1.insert(v1.begin(), 2); //将2插入到开头
	v1.insert(v1.begin(), 2,100);  //将100插入到开头2次
	//删除
	v1.erase(v1.begin()); //删除开头的元素
	v1.erase(v1.begin(), v1.end()); //删除两个迭代器之间的元素
	Myprint(v1);
	//全部删除
	v1.clear();
	return 0;

元素的访问

int main()
{
	vector<int>v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	//通过中括号访问
	cout << v1[0] << endl;
	//通过at访问
	cout << v1.at(1) << endl;
	//通过迭代器访问
	vector<int>::iterator it = v1.begin();
	cout << *it << endl;
	//访问首尾元素
	v1.front();
	v1.back();
	return 0;
}

互换容器

swap函数互换两个容器,可以在实际运用中收缩内存(让容器的容量与大小适配,避免给太小的容器分配太大的容量

#include<iostream>
using namespace std;
#include<vector>
void Myprint(vector<int>& v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}
int main()
{
	vector<int>v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	vector<int>v2;
	for (int i = 10; i >0; i--)
	{
		v2.push_back(i);
	}
	//互换前
	Myprint(v1);
	Myprint(v2);
	v1.swap(v2);
	//互换后
	Myprint(v1);
	Myprint(v2);


	//内存收缩
	vector<int>v3;
	for (int i = 0; i < 1000000; i++)
	{
		v3.push_back(i);
	}
	//方法一
	/*cout<<"v3.capacity()="<<v3.capacity()<<endl;
	v3.shrink_to_fit();
	cout<<"v3.capacity()="<<v3.capacity()<<endl;*/
	//方法二
	vector<int>(v3).swap(v3);  //匿名对象
	cout<<"v3.capacity()="<<v3.capacity()<<endl;
	cout<<"v3.size()="<<v3.size()<<endl;
	return 0;
}

预留空间

当存入较大量数据时,为避免多次进行动态扩展,可以在一开始就预留足够的空间

#include<iostream>
using namespace std;
#include<vector>
int main()
{
	vector<int>v1;
	int num = 0;
	int* p = NULL;
	v1.reserve(1000000);
	for (int i = 0; i < 1000000; i++)
	{
		v1.push_back(i);
		if (p != &v1[0])
		{
			p = &v1[0];
			num++;
		}
	}
	cout<<"num:"<<num<<endl;   //35  1
	return 0;
}

deque容器

该容器可实现前后插入

构造函数

基本与vector一样,

赋值操作

容器之间可以通过等号直接复制,或assign函数进行复制

deque<int>v1;
deque<int>v2;
deque<int>v3;
v2 = v1;
v3.assign(v1);

大小操作

1.v,empty()     判断容器的是否为空

2.v.size()      返回容器中元素个数

3.v.resize(num)    重新指定容器大小,若变大则多余空间填充默认值若变小则删除多余数据

4.v.resize(num,hun)     在三的基础上在多余空间填充hun

插入和删除

1.v.push_back()  or  v.push_front()  尾插和头插

2.v.pop_back()  or  v.pop_front()  尾插和头插

数据获取

1.通过[ ] 索引获取

2.front()  back()获取头尾元素

排序

通过sort进行排序,传入要排序的区间

#include<iostream>
using namespace std;
#include<deque>
#include<algorithm>
void printvector(const deque<int>v1)     //打印容器内容,const修饰防止数据被修改,!!!!!但要使用常量迭代器
{
	for (deque<int>::const_iterator it = v1.begin(); it != v1.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;


}
void test()
{
	//构造函数
	deque<int>v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	printvector(v1);
	deque<int>v2(v1.begin(), v1.end());
	printvector(v2);
	deque<int>v3(v1);
	printvector(v3);

	//大小操作
	if (v1.empty())
	{
		int size = v1.size();
		cout << size << endl;
	}
	

	//插入操作
	deque<int>v4;       //头插尾插
	v4.push_back(10);
	v4.push_front(20);
	v4.push_back(10);
	v4.push_front(20);
	printvector(v4);
	
	v4.insert(v4.begin(), 30);
	printvector(v4);

	v4.insert(v4.begin(), v3.begin(), v3.end()); //在v4的头部插入v3的内容
	printvector(v4);


	//删除操作
	v4.pop_back();
	v4.pop_front();
	v4.erase(v4.begin());    //定点删除
	//v4.erase(v4.begin(), v4.end()); //删除区间内的元素
	printvector(v4);
	v4.clear();            //清除
}
void mysort()
{
	deque<int>v1;
	v1.push_back(3);
	v1.push_back(1);
	v1.push_back(5);
	v1.push_back(8);
	v1.push_back(9);
	v1.push_back(4);
	printvector(v1);
	sort(v1.begin(), v1.end());
	printvector(v1);
}
int main()
{
	mysort(); 

	return 0;
}

stack   栈

构造函数   

stack<int> v1;  stack<int> v2; v2(v1);

赋值    =  

入栈 push();

出栈  pop();

获取栈顶  top();

判空  empty();

获取元素个数  size();

queue  队列

构造函数    queue<int> v1;  queue<int> v2; v2(v1);

赋值   =   

入队  push();

出队  pop();

获取头尾元素  front();  back();

判空  empty();

获取元素个数  size();

list   链表

构造函数  v(v1)  v(10,1)--十个一  v(beg,end) 将【beg,end)赋值给v

赋值操作 

1.assign(beg,end)  将[beg,end)赋值

2.assign(n,num)      n个num

3.等号赋值

4.swap(liat1)   将list1 与本身链表互换

大小操作

1.size()    返回元素个数

2.empty()     判空

3.resize(num)    重新设置链表大小,多于元素删除

4.resize(num,hun)   重新设置链表大小,多于元素删除,空位填充hun

插入和删除

1.push_back()   push_front()  pop_back()   pop_front() 

2.insert(pos,num)   在pos位置插入num元素的拷贝,返回新数据的位置

3.insert(pos,n,else)  在pos位置插入n个else,无返回值

4.insert(beg,end)  在pos位置插入区间元素,无返回值

5.clear()   清除所有数据

6.erase(pos)    删除pos位置的数据,返回下一个数据的位置

7.erase(beg,end)  删除区间元素

8.remove(num)   删除与num匹配的元素

数据存取

1.front()  back()  返回首尾元素

反转和排序

1.reverse()    反转链表

2.sort()     链表排序  成员函数  v.sort()    默认从小到大,可以通过函数定义排序规则

set 

 关联式容器 集合容器 二叉树  自动排序

分为set和multiset,前者不允许存入相同的数据,后者可以

set插入数据会返回pair<set<int>::iterator,bool> 类型的数据

multiset则不会

构造函数    =    v(v1)

大小及交换

1.empty()   判空

2.size()   

3.swap()交换两个集合容器

插入和删除

1.insert() 

2.clear() 清除所有元素

3.erase(num) 删除与num匹配的所有元素

4.erase(pos) 删除迭代器所指位置,返回下一个迭代器

5. erase(beg,end) 删除区间元素并返回下一个元素的迭代器

查找和统计

1.find(key)  若key存在返回key的迭代器,否则返回v.end()迭代器

2.count(key)  返回0 or1

对组

#include<iostream>
using namespace std;
#include<set>
void test()
{
	pair<string, int> p1("Tom", 20);
	pair<string, int> p2 = make_pair("Jerry", 25);
	cout << p1.first << " " << p1.second << endl;
}
int main()
{
	test();


	return 0;
}

排序

默认是从小到大排序,通过仿函数自定义排序规则

自定义数据类型同理

map

本质二叉树(红黑树) map(key,val)根据key 自动排序  log(n)

其内部存储的是键值对组pair

构造函数

map<int,int> m;   m(m1) m = m1

#include<iostream>
using namespace std;
#include<map>
void myprint(const map<int,int>& m)
{
	for (auto it = m.begin(); it != m.end(); it++)
	{
		cout<<it->first<<" "<<it->second<<endl;
	}
}
int main()
{
	map<int, int> m1;
	m1.insert(pair<int, int>(1, 4));
	m1.insert(pair<int, int>(4, 2));
	m1.insert(pair<int, int>(3, 0));
	m1.insert(pair<int, int>(6, 0));
	map<int, int> m2(m1);
	map<int, int> m3;
	m3 = m1;
	myprint(m3);
	return 0;
}

大小及交换

同set

插入和删除

同set

区别 3.erase(key) 删除与key匹配的元素

查找和统计

同set

排序

默认按照key从小到大,利用仿函数自定义

#include<iostream>
using namespace std;
#include<map>
class mycompare
{
public:
	bool operator()(int v1, int v2) const
	{
		return v1 > v2;

	}
};
void myprint(const map<int,int, mycompare>& m)
{
	for (auto it = m.begin(); it != m.end(); it++)
	{
		cout<<it->first<<" "<<it->second<<endl;
	}
}
int main()
{
	map<int, int,mycompare> m1;
	m1.insert(pair<int, int>(1, 4));
	m1.insert(pair<int, int>(4, 2));
	m1.insert(pair<int, int>(3, 0));
	m1.insert(pair<int, int>(6, 0));
	/*map<int, int> m2(m1);
	map<int, int> m3;
	m3 = m1;*/
	myprint(m1);
	return 0;
}

unordered_map

unordered_map是<unordered_map>头文件中的关联式容器,其底层是哈希表,存放的键值对不能重复,与map不同的是它不会进行排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值