C++STL——顺序容器

顺序容器详解

      • vector:向量容器
      • deque:双端队列容器
      • list:链表容器
      • vector、deque、list对比
      • 总结:

vector:向量容器

1.底层数据结构:动态开辟的数组;涉及到扩容操作时,每次以原空间的2倍进行扩容。
2.基本操作:

vector< int >vec; // 实例化一个vec
//插入:
vec.push_back(20);// 容器末尾添加元素20
vec,insert(it,20);//it迭代器指向的位置添加一个元素20
//删除:
vec.pop_back();//容器末尾删除元素
vec.erase(it);//删除it指向位置的元素
//查询:
vec[i];//vector提供了了operator[]运算符重载函数,底层数组最大的特点就是下标随机访问
iterator//迭代器遍历
find,for_each等接口

注意:对容器通过迭代器进行连续插入(insert)或者删除(erase)操作时,一定要更新迭代器,否则一次插入/删除操作后,迭代器就失效了。
3.常用方法介绍:

vector<int>vec;
vec.size();//返回容器中有效元素的个数
vec.empty();//判断容器是否为空
vec.resize();//容器扩容,不仅给容器底层开辟指定大小的空间,还会进行初始化操作。
vec.reserve();//容器扩容,预留空间,多用于已知元素个数的场景,只给容器底层开辟指定大小的空间,不会对其进行初始化操作。
vec.swap();//两个容器交换元素(同类型容器)

4.基本操作代码示例:

#include
#include
int main()
{

	vector<int>vec;
	//vec.reserve(20);//开辟20个大小int类型(4字节)的空间
	vec.resize(20);//开辟20个大小int类型(4字节)的空间,并且全部初始化为0       
	cout << vec.empty() << endl;
	cout << vec.size() << endl;
	for (auto it : vec)
	{
		cout << it << " ";
	}
	cout << endl;
	for (int i = 0; i < 20; ++i)
	{
		vec.push_back(rand() % 100 + 1);
	}
	cout << vec.empty() << endl;
	cout << vec.size() << endl;
	for (auto it : vec)
	{
		cout << it << " ";
	}
	cout << endl;

	int size = vec.size();
	for (int i = 0; i < size; ++i)
	{
		//[]:vector的operator[]运算符重载函数
		cout << vec[i] << " ";
	}
	cout << endl;
	//把vec容器中所有的偶数全部删除
	auto it2 = vec.begin();
	while (it2 != vec.end())
	{
		if (*it2 % 2 == 0)
		{
			//连续删除时为防止迭代器失效,需要更新迭代器it2的位置
			it2 = vec.erase(it2);
		}
		else
		{
			++it2;
		}
	}
	//通过迭代器遍历vector容器
	auto it1 = vec.begin();
	for (; it1 != vec.end(); ++it1)
	{
		cout << *it1 << " ";
	}
	cout << endl;
	//给vector容器中所有的奇数前面都添加一个小于奇数1的偶数
	for (it1 = vec.begin(); it1 != vec.end(); ++it1)
	{
		if (*it1 % 2 == 1)
		{
			//连续插入时为防止迭代器失效,需要更新迭代器it1的位置
			it1 = vec.insert(it1, *it1 - 1);
			++it1;
		}
	}
	//通过范围for遍历vector容器
	for (auto a:vec)
	{
		cout << a << " ";
	}
	cout << endl;
	return 0;
}

deque:双端队列容器

1.底层数据结构:动态开辟的二维数组。
2.扩容方式:一位数组从2开始,以2倍的方式进行扩容,每次扩容后,原来的第二维数组,从新的第一位数组的下标oldzie/2位置开始存放,上下都预留相同的空间,方便支持deque的首尾元素添加。
3.基本操作:

deque<int>deq;//实例化deq
//插入
deq.push_back(20);//向末尾插入元素20,时间复杂度O(1);
deq.push_front(20);//向首部插入元素20,时间复杂度O(1);
deq.insert(it,20);//向it指向的位置插入元素,时间复杂度O(N);
//删除:
deq.pop_back();//从末尾删除元素,时间复杂度O(1);
deq.pop_front();//从首部删除元素,时间复杂度O(1);
deq.erase();//从it指向的位置删除元素,时间复杂度O(N);
//查询
iterator迭代器遍历;//时间复杂度O(N)

注意:对容器通过迭代器进行连续插入(insert)或者删除(erase)操作时,一定要更新迭代器,否则一次插入/删除操作后,迭代器就失效了。
4.常用方法:

size();//返回容器有效元素的个数
empty();//判断容器是否为空
resize();//容器扩容,不仅给容器底层开辟指定大小的内存空间,还会给其初始化
swap();//两个容器交换元素(同类型容器)

5.基本操作代码示例:

int main()
{
	deque<int>deq;
	deq.resize(20);
	cout<<deq.empty()<<endl;
	cout << deq.size() << endl;
	for (auto a : deq)
	{
		cout << a << " ";
	}
	cout << endl;
	for (int i = 0; i < 10; ++i)
	{
		deq.push_back(rand() % 100 + 1);
	}
	for (auto a : deq)
	{
		cout << a << " ";
	}
	cout << endl;
	cout << deq.empty() << endl;
	cout << deq.size() << endl;

	cout << "push_back()" << endl;

	for (auto a : deq)
	{
		cout << a << " ";
	}
	cout << endl;
	for (int i = 10; i < 20; ++i)
	{
		deq.push_front(rand() % 100 + 1);
	}
	cout << "push_front()" << endl;
	for (int i = 0; i < 20; ++i)
	{
		cout << deq[i] << " ";
	}
	cout << endl;
	for (int i = 0; i < 5; ++i)
	{
		deq.pop_back();
	}
	for (auto a : deq)
	{
		cout << a << " ";
	}
	cout << endl;
	for (int i = 0; i < 5; ++i)
	{
		deq.pop_front();
	}
	for (auto a : deq)
	{
		cout << a << " ";
	}
	cout << endl;
	auto it1 = deq.begin();
	while (it1 != deq.end())
	{
		if (*it1 % 2 == 0)
		{
			it1 = deq.erase(it1);
		}
		else
		{
			++it1;
		}
	}
	for (auto a : deq)
	{
		cout << a << " ";
	}
	cout << endl;
	for (it1 = deq.begin(); it1 != deq.end(); ++it1)
	{
		if (*it1 % 2 != 0)
		{
			it1 = deq.insert(it1, *it1 - 1);
			++it1;
		}
	}
	auto it2 = deq.begin();
	for (; it2 != deq.end(); ++it2)
	{
		cout << *it2 << " ";
	}
	cout << endl;

	return 0;
}

list:链表容器

1.底层数据结构:双向循环链表 pre data next
2.基本操作:

list<int>mylist;
//插入
mylist.push_back(20);//向末尾插入元素20,时间复杂度O(1);
mylist.push_front(20);//向首部插入元素20,时间复杂度O(1);
mylist.insert(it,20);//向it指向的位置插入元素,时间复杂度O(1);
//删除:
mylist.pop_back();//从末尾删除元素,时间复杂度O(1);
mylist.pop_front();//从首部删除元素,时间复杂度O(1);
mylist.erase();//从it指向的位置删除元素,时间复杂度O(1);
//链表中进行插入insert/erase操作时,先要进行一个查询操作,对于链表来说,查询的效率并不高,要进行遍历
//查询
iterator迭代器遍历;//时间复杂度O(N)

注意:对容器通过迭代器进行连续插入(insert)或者删除(erase)操作时,一定要更新迭代器,否则一次插入/删除操作后,迭代器就失效了。
3.常用方法介绍:

size();//返回容器有效元素的个数
empty();//判断容器是否为空
resize();//容器扩容,不仅给容器底层开辟指定大小的内存空间,还会给其初始化
swap();//两个容器交换元素(同类型容器)

4.常用操作代码示例:

int main()
{
	list<int>lst;
	//lst.reverse();
	lst.resize(10);
	cout << lst.empty() << endl;
	cout << lst.size() << endl;
	for (auto a : lst)
	{
		cout << a << " ";
	}
	cout << endl;
	//cout << "push_back()" << endl;
	for (int i = 0; i < 10; ++i)
	{
		lst.push_back(rand() % 100 + 1);
	}
	for (auto a : lst)
	{
		cout << a << " ";
	}
	cout << endl;
	cout << lst.empty() << endl;
	cout << lst.size() << endl;
	for (auto a : lst)
	{
		cout << a << " ";
	}
	cout << endl;
	cout << "push_front" << endl;
	for (int i = 0; i < 10; ++i)
	{
		lst.push_front(rand() % 100 + 1);
	}
	for (auto a : lst)
	{
		cout << a << " ";
	}
	cout << endl;
	for (int i = 0; i < 5; ++i)
	{
		lst.pop_back();
	}
	for (auto a : lst)
	{
		cout << a << " ";
	}
	cout << endl;
	for (int i = 0; i < 5; ++i)
	{
		lst.pop_front();
	}
	for (auto a : lst)
	{
		cout << a << " ";
	}
	cout << endl;
	auto it1 = lst.begin();
	while (it1 != lst.end())
	{
		if (*it1 % 2 == 0)
		{
			it1 = lst.erase(it1);
		}
		else
		{
			++it1;
		}
	}
	for (auto a : lst)
	{
		cout << a << " ";
	}
	cout << endl;
	for (it1 = lst.begin(); it1 != lst.end(); ++it1)
	{
		if (*it1 % 2 != 0)
		{
			it1 = lst.insert(it1,*it1-1);
			++it1;
		}
	}
	for (auto a : lst)
	{
		cout << a << " ";
	}
	cout << endl;
	return 0;
}

vector、deque、list对比

vector和deque之间的区别?
1.底层数据结构:vector(数组),deque(双端队列)。
2.前中后插入删除元素的时间复杂度:末尾都是O(1),中都是O(N),前deque O(1)、vector O(N),
3.对于内存的使用效率:deque内存使用效率更加高效,因为vector需要的内存空间必须是连续的,deque可以分块进行数据存储,不需要内存空间必须是一片连续的。
4.在中间进行insert或者earse时,vector和deque他们的效率谁能好一点(vector)?谁能差一点(deque)?
由于deque的第二维内存空间不是连续的,所以在deque中间进行元素的insert和erase,造成元素移动的时候比vector要慢。
vector和list之间的区别?
1.底层数据结构:vector(数组)、list(双向循环链表)
2.性能分析:
数组:增加删除O(N) 查询O(N) 随机访问O(1)
链表:(不考虑搜索的时间)增加删除O(1) 查询O(N)
3.使用场景:查询多则使用vector,插入删除多则使用list

总结:

vector的特点: 动态数组,内存是连续的,以原大小2倍的方式进行扩容,默认定义vector< T >vec时,其实并没有开辟内存,只有当进行插入操作时,才会按照0-1-2-8-4…来扩容。
deque的特点: 动态开辟的二维数组,第二维是固定长度的数组空间,扩容时仅第一维的数组进行二倍扩容,内存是部分连续的,即每一个第二维是连续的。
list的特点: 内存是不连续的,在不考虑查询操作时,插入删除的效率极高。

你可能感兴趣的:(C++STL——顺序容器)