C++容器

C++容器

容器的概念

C++中容器的定义如下:数据存储上,有一种对象类型,它可以持有其他对象或指向其他对象的指针,这种对象类型叫容器。容器类是一种对特定代码重用问题的良好的解决方案。容器另一个好处就是可以自行扩展,解决问题时通常不知道需要存储多少个对象,数组在这方面也是力不从心。容器可以申请内存、释放内存,并且使用最优的算法来执行命令。

顺序容器

向量(vector)

vector是一个动态的顺序容器,具有连续内存地址的数据结构,通过下标运算符“[ ]”直接有效地访问向量的任何元素。相比于数组,vector会消耗更多的内存以有效地动态增长。而相比于其他序列容器(deques,lists),vector能更快地索引元素(就像数组一样),而且能相对高效地在尾部插入和删除元素。
注意:当需要使用vector的时候,需要包含头文件:#include ,一般加上“using namespace std;”,如果不加,则在调用时候必须用std::vector<…>这样的形式,即在vector前加上std::,这表示运用的是std命名空间下的vector容器。

编写程序,对一个大小为10的向量容器进行修改和访问。

#include<iostream>
#include<vector>
using namespace std;

int main()
{
	vector<int> a(10, 1);		//大小为10,初始值为1的向量a
	int i;
	cout << "初始化变量";
	for ( i = 0; i < a.size(); i++)
	{
		cout << a[i] << " ";
	}
	cout << "\n插入数据:";
	cin >> a[2];
	cin >> a[5];
	cin >> a[8];
	cout << "赋值后遍历:";
	for (i = 0; i < a.size(); i++)
	{
		cout << a[i] << " ";
	}

	cout << endl;
	return 0;
}

实现效果
二维向量,与数组相同,向量也可以增加维数。
例如,声明一个m*n大小的二维向量方式可以像如下形式:

vector< vector<int> > a(3,vector<int>(4)); //相当于a[3][4]

编写程序,实现vector的基本操作。

#include<iostream>
#include<vector>
using namespace std;

int main()
{
	int i = 0;
	vector<int>a;
	for ( i = 0; i < 10; i++)		
	{
		a.push_back(i);				//10个元素依次进入数组
	}
	
	cout << "初始化遍历:";
	for (i = 0; i < a.size(); i++)
	{
		cout << a[i] << " ";
	}

	cout << "\n迭代  遍历:";
	vector<int>::iterator it;		//迭代器进行访问
	for (it = a.begin(); it != a.end(); it++)
	{
		cout << *it << " ";
	}

	cout << "\n插入  遍历:";
	a.insert(a.begin() + 4, 0);		//在第5个元素之前加0
	for (unsigned int i = 0; i < a.size(); i++)
	{
		cout << a[i] << " ";
	}

	cout << "\n擦除  遍历:";
	a.erase(a.begin() + 2);
	for (unsigned int i = 0; i < a.size(); i++)
	{
		cout << a[i] << " ";
	}

	cout << "\n迭代  遍历:";
	a.erase(a.begin() + 3, a.begin() + 5);
	for (vector<int>::iterator it = a.begin(); it != a.end(); it++)
	{
		cout << *it << " ";
	}

	cout << endl;
	return 0;
}

在这里插入图片描述

列表

list是STL实现的双向链表,相对于vector的连续线性空间,list就显得复杂太多,它允许快速地插入和删除,但是随机访问却比较慢。它的数据由若干个节点构成,每一个节点都包括一个信息块、一个前驱指针和一个后驱指针,可以向前也可以向后进行访问,但不能随机访问。它的好处是每次插入或者删除就会配置或者释放一个元素空间,而且它对于空间的运用绝对精准,一点也不多余。列表的定义在头文件“#include ”中。

编写程序,创建一个list实例并赋值。

#include<iostream>
#include<list>
using namespace std;

int main()
{
	list<int>lst;
	for (int i = 0; i <= 5; i++)
	{
		lst.push_back(i);
	}
	
	cout << "在元素末尾操作数据:" << endl;
	lst.push_back(999);
	for (list<int>::iterator it = lst.begin(); it != lst.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;
	lst.pop_back();
	for (list<int>::iterator it = lst.begin(); it != lst.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;


	cout << "在元素开头操作数据:" << endl;
	lst.push_front(888);
	for (list<int>::iterator it = lst.begin(); it != lst.end(); ++it)
	{
		cout << *it << " ";
	}


	cout << endl;
	return 0;
}

【程序小结】本例中使用push_back()函数在列表容器的末尾插入数据,push_front()函数是在列表开头插入数据。
实现效果

编写程序,对列表容器进行顺序遍历和逆序遍历。

#include<iostream>
#include<list>
using namespace std;

int main()
{
	int a[5] = { 22,33,44,55,66 };
	list<int> lst(a, a + 5);		//将数组a的前5个元素作为列表容器lst的初值
	cout << "正序输出:";
	for (list<int>::iterator it = lst.begin(); it != lst.end(); ++it)
	{
		cout << " " << *it;

	}
	cout << '\n';
	lst.clear();

	cout << "逆序输出:";
	for (int i = 1; i <= 5; ++i)
	{
		lst.push_back(i);
	}
	for (list<int>::reverse_iterator rit = lst.rbegin(); rit != lst.rend(); ++rit)
	{
		cout << ' ' << *rit;
	}
	cout << endl;
	return 0;
}

【程序小结】先定义了一个数组a并赋初值。然后将数组a的前5个元素作为列表容器的初值,再定义迭代器指针,从列表头开始依次遍历。接着,再使用迭代器从列表的尾部依次遍历。
在这里插入图片描述

关联容器

关联容器主要有映射(map)和集合(set),支持通过键来高效地查找和读取元素。map的元素以键-值对(key-value)的形式组织:键用作元素在map类型下进行索引,而值则表示所存储和读取的数据。set仅包含一个键,并有效地支持关于某个键是否存在的查询。set和map类型的对象不允许为同一个键添加第二个元素。如果一个键必须对应多个实例,则需使用多重映射(multimap)或多重集合(mutiset)类型,这两种类型允许多个元素拥有相同的键。

映射map

映射map就是标准模板库中的一个关联容器,它提供一对一的数据处理能力。map的元素是由key和value两个分量组成的对偶(key,value)。元素的键key是唯一的,给定一个key,就能唯一地确定与其相关联的另一个分量value。

编写程序,遍历map容器。

#include<iostream>
#include<string>
#include<map>
using namespace std;

int main()
{
	cout << "正序输出:\n";
	map<int, string>M;
	M.insert(pair<int, string>(1, "M_first"));
	M.insert(pair<int, string>(2, "M_second"));
	M.insert(pair<int, string>(3, "M_third"));
	map<int, string>::iterator iter;
	for (iter = M.begin(); iter != M.end(); iter++)
	{
		cout << iter->first << " " << iter->second << endl;
	}



	cout << endl;
	return 0;
}
cout << "\n逆序输出:";
map<int, string>::reverse_iterator iter;
for (iter = M.rbegin(); iter != M.rend(); iter++)
{
	cout << iter->first << " " << iter->second << endl;
}

set类容器

set的使用

使用set之前必须包含set头文件,set支持的操作基本与map提供的相同。

verctor<int> ivec;
for(verctor<int>::size_type i=0;i!=10;++i)
{
ivec.push_back(i);
ivec.push_back(i);
}
//用ivec初始化set
set<int> iset(ivec.begin(),ivec.end());
cout<<ivec.size()<<endl;		//输出20
cout<<iset.size()<<endl;		//输出10

set中添加元素

直接插入
set<string> set1;
set1.insert("the");
使用迭代器
set<string> set2;
set2.insert(Iveco。begin(),ivec.end());
从set中获取元素

set没有下标操作,为了通过键从set中获取元素,可使用find()运算。如果仅是判断某个元素是否存在,也可使用count()操作,返回值只能是1或0。

容器适配器

容器适配器有三种:stack、queue和priority_queue。stack可以与数据结构中的栈对应,它具有先进后出的特性,而queue则可以理解为队列,它具有先进先出的特性,priority_queue则是带优先级的队列,其元素可以按照某种优先级顺序进行删除。

综合应用

编写程序,使用向量容器,根据年龄的大小,对5位青少年进行排序。

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
struct Person
{
	char name[10];
	int age;
};

bool comp(const Person& a, const Person& b)
{
	return a.age < b.age;		//自定义 小于
}


int main()
{
	vector<Person> v_per;
	int n = 5;
	while (n--)
	{
		Person people;
		string name;
		int age;
		cin >> name >> age;
		strcpy_s(people.name, name.c_str());
		people.age = age;
		v_per.push_back(people);
	}

	cout << "-----------------排序前---------------" << endl;
	for (vector<Person>::iterator it = v_per.begin(); it != v_per.end(); it++)
	{
		cout << "姓名:" << it->name << "\t年龄:" << it->age << endl;
	}

	sort(v_per.begin(), v_per.end(), comp);
	cout << "-----------------排序后---------------" << endl;
	for (vector<Person>::iterator it = v_per.begin(); it != v_per.end(); it++)
	{
		cout << "姓名:" << it->name << "\t年龄:" << it->age << endl;
	}

	cout << endl;
	return 0;
}

【程序小结】本例中先定一个关于人的结构体,该结构体例有两个成员,分别表示一个人的姓名和年龄。再定义一个bool型的比较函数comp(),并返回两个年龄之间的比较。在main()函数中,定义一个向量对象v_per。然后通过while循环,依次输入5个人的年龄和姓名。最后定义迭代器,依次将该容器遍历出来。

在这里插入图片描述

面试常见问题

如何选取合适的容器?
答:如果用户需要高效的随机存取,而不在乎插入和删除的效率,使用vector;如果用户需要大量的插入和删除,而不关心随机存取,则应使用list;如果用户需要随机存取,而且关心两端数据的插入和删除,则应使用deque。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值