C++的STL-----容器

C++中的容器,顾名思义就是用来存放数据的,我们知道常用的数据结构有:栈、队列、数组、链表、集合、哈希等等。在这里头,又分为序列式容器以及关联式容器

  • 序列式容器:序列中每个元素都有它固定的位置,强调值与值之间的排序
  • 关联式容器:类似二叉树,各个元素之间没有严格的物理上排序

vector

vector是类似数组的数据结构,不同的是数组是固定大小,而vector可以动态扩增。我们可以通过创建vector对象,并指定其数据类型来存放数据。此外,每一个容器都有迭代器。通过迭代器可以遍历容器中的各个元素,使用 vector::iterator 获取vector这种容器的迭代器类型,然后v.begin(),v.end()分别代表容器的第一个位置以及末尾的位置。

int main() {
	vector<int> v;
	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	v.push_back(40);
	
	vector<int>::iterator pBegin = v.begin();
	vector<int>::iterator pEnd = v.end();

	while (pBegin != pEnd) {
		cout << *pBegin << endl;
		pBegin++;
	}
	//第二种遍历方式
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << endl;
	}
	cout << endl;
	
	system("pause");
	return 0;
}

我们也可以通过其他方式来给vector赋值

int main() {
	vector<int> v1; //无参构造
	for (int i = 0; i <5; i++){
		v1.push_back(i);
	}
	vector<int> v2 = v1; // 拷贝构造
	
	vector<int> v3; // 使用assign赋值
	v3.assign(v1.begin(), v1.end());
	
	vector<int> v4; //赋予十个元素,每个元素的值都为100
	v4.assign(10, 100);

	vector<int> v5(10, 100);//赋予十个元素,每个元素的值都为100
	system("pause");
	return 0;
}

如果我们想获取vector的大小以及容量可以通过以下几个函数:

	vector<int> v1(10,0);
	cout << "v1是否为空" << v1.empty() << endl;
	cout << "v1的容量 = " << v1.capacity() << endl;
	cout << "v1的大小 = " << v1.size() << endl;

这里的容量与大小的区别在于capacity指的是容器可以容纳最大数量,而size指的是目前容器有多少个元素。
如果我们想要对vector进行增加、删除以及查找数据的操作,容器中也是有提供指定的函数来支持。

int main() {
	vector<int> v1;
	//尾插
	v1.push_back(10);
	v1.push_back(20);
	v1.push_back(30);
	v1.push_back(40);
	v1.push_back(50);
	//尾删
	v1.pop_back();
	
	//插入
	v1.insert(v1.begin(), 100);
	v1.insert(v1.begin(), 2, 1000);
	
	cout << "v1的第一个元素为: " << v1.front() << endl;
	cout << "v1的最后一个元素为: " << v1.back() << endl;
	
	//不通过迭代器的查询:
	for (int i = 0; i < v1.size(); i++){
		cout << v1.ai(i) << endl;	
	}

	for (int i = 0; i < v1.size(); i++){
		cout << v1[i] << endl;	
	}
	
	//删除
	v1.erase(v1.begin());
	
	//清空
	v1.erase(v1.begin(), v1.end());
	v1.clear();
	
	system("pause");
	return 0;
}

erase只是删除容器中的元素,但是不会清除内存,而clear则是清除容器所在内存中的内容。

deque

deque提供双向插入、删除,也就是双端数组。vector对于头部的插入与删除效率过低,而deque速度比vector快不少。除此之外,deque的构造以及其他操作和vector基本差不多。在deque中,也可以通过empty()、size()、capacity()、front()、back()等查看相关属性。

int main() {
	deque<int> d1; //无参构造函数
	for (int i = 0; i < 10; i++)
	{
		d1.push_back(i);
	}
	
	deque<int> d2(d1.begin(),d1.end());

	deque<int>d3(10,100);

	deque<int>d4 = d3;

	deque<int>d5;
	d5 = d1;

	deque<int>d6;
	d6.assign(d1.begin(), d1.end());

	deque<int>d7;
	d7.assign(10, 100);
	
	system("pause");
	return 0;
}

因为deque支持双向操作,因此除却push_back()外,还有push_front()来在容器头部插入数据。

int main() {
	deque<int> d;
	//尾插
	d.push_back(10);
	d.push_back(20);
	//头插
	d.push_front(100);
	d.push_front(200);

	//尾删
	d.pop_back();
	//头删
	d.pop_front();
	
	d.insert(d.begin(), 1000);
	d.insert(d.begin(), 2,10000);
	
	deque<int>d2;
	d2.push_back(1);
	d2.push_back(2);
	d2.push_back(3);
	
	d.insert(d.begin(), 1000);
	d.insert(d.begin(), 2, 10000);
	d.insert(d.begin(),d2.begin(),d2.end())system("pause");
	return 0;
}

栈与队列

学过数据结构的朋友都知道栈是一种先进后出的数据结构;而队列则是先进先出的数据结构。
由于栈只有一个出入口,所以往栈中增添、删除元素的操作叫做入栈、出栈,也叫压栈、弹栈。

int main() {
	stack<int> s;
	s.push(10);
	s.push(20);
	s.push(30);
	cout << "栈的大小为:" << s.size() << endl;
	//栈不提供迭代器,也不支持随机访问
	while (!s.empty()) {
		//输出栈顶元素
		cout << "栈顶元素为: " << s.top() << endl;
		//弹出栈顶元素
		s.pop();
	}
	system("pause");
	return 0;
}

而队列有两个出口,这个数据结构允许从一端新增元素,从另一端删除元素,也叫作入队、出队。

int main() {
	queue<int> q;
	q.push(10);
	q.push(20);
	q.push(30);
	
	cout << "队列大小为:" << q.size() << endl;
	
	//和栈一样,队列不提供迭代器,更不支持随机访问	
	while (!q.empty()) {
		//输出队头、队尾元素
		cout << "队头元素" << q.front() << endl;
		cout << "队尾元素" << q.back() << endl;
		cout << endl;
		//弹出队头元素
		q.pop();
	}
	
	system("pause");
	return 0;
}

至于栈与队列的其他操作,和上述vector容器操作没有什么差异。

链表

和数组在物理存储单元上连续存储不一样,链表的连续性不是体现在物理结构上,而是逻辑结构,它是通过链表中的指针链接实现连续性的。我们都知道,链表是由一个又一个的结点组成,其中一个是数据域,一个是指针域。在STL中,链表是一个双向循环链表。
链表优点在于采用动态存储分配,不会造成内存浪费和溢出,以及执行插入和删除时不需要移动大量元素,但是缺点也是显而易见的:遍历的时候效率过低。

int main() {
	list<int>L1;
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	L1.push_back(40);
	
	list<int>L2(L1.begin(),L1.end());

	list<int>L3(L2);

	list<int>L4(10, 1000);
	
	list<int>L5;
	L5 = L1;

	list<int>L6;
	L6.assign(L1.begin(), L1.end());

	list<int>L7;
	L7.assign(10, 100);

	system("pause");
	return 0;
}

使用list容器的操作和vector几乎一样:

int main() {
	list<int> L;
	//尾插
	L.push_back(10);
	L.push_back(20);
	L.push_back(30);
	
	//头插
	L.push_front(100);
	L.push_front(200);
	L.push_front(300);
	
	//查看是否为空以及大小
	if (L.empty())
	{
		cout << "L为空" << endl;
	}
	else
	{
		cout << "L不为空" << endl;
		cout << "第一个元素为: " << L.front() << endl;
		cout << "最后一个元素为: " << L.back() << endl;
		cout << "L的大小为: " << L.size() << endl;
	}

	//尾删
	L.pop_back();

	//头删
	L.pop_front();

	//插入
	list<int>::iterator it = L.begin();
	L.insert(++it, 1000);

	//删除
	it = L.begin();
	L.erase(++it);
	
	L.push_back(10000);
	L.push_back(10000);
	L.push_back(10000);
	
	//删除容器中所有与elem值匹配的元素
	L.remove(10000);
  
    //清空
	L.clear();

	system("pause");
	return 0;
}

但是链表不支持 L.at(0) 、L[0]方式访问,以及链表的迭代器是双向迭代器,所以不支持随机访问。

pair与map
pair和map都是键值对映射的关系。pair是一对数据组成的对组,map中所有元素都是pair,其中pair里的第一个元素为key,起到索引的作用,第二个元素为value,保存key的值,所有的元素会根据键值的大小进行排序。

int main() {
	//两种方式创建pair
	pair<string, int> p1(string("Tom"), 20);
	cout << "姓名: " <<  p1.first << " 年龄: " << p1.second << endl;

	pair<string, int> p2 = make_pair("Jerry", 10);
	cout << "姓名: " <<  p2.first << " 年龄: " << p2.second << endl;

	map<int, int> m1; //几种插入方法
	m.insert(pair<int, int>(1, 10));
	m.insert(pair<int, int>(2, 20));
	m.insert(make_pair(3, 30));
	m[4] = 40;
	if (m.empty())
	{
		cout << "m为空" << endl;
	}
	else
	{
		cout << "m不为空" << endl;
		cout << "m的大小为: " << m.size() << endl;
	}
	
	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
	{
		cout << "key = " << it->first << " value = " << it->second << endl;
	}
	cout << endl;
	
	//清空
	m.erase(m.begin(),m.end());
	m.clear();
	
	system("pause");
	return 0;
}

集合

set容器也是会自动排序,默认从小到大。集合分为set和multiset,set不可以插入重复数据,而multiset可以。set也是可以通过empty、size来查看大小。

int main() {
	set<int> s1;

	s1.insert(10);
	s1.insert(30);
	s1.insert(20);
	s1.insert(40);
	//插入重复数据不会报错,但是也不会生效。
	s1.insert(20);
	
	//清空
	s1.erase(s1.begin());
	s1.erase(30);
	s1.clear();
	
	multiset<int> ms;
	ms.insert(10);
	ms.insert(10);

	for (multiset<int>::iterator it = ms.begin(); it != ms.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
	
	system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值