浅析STL中常见顺序容器的常用方法

    

目录

  •      STL容器种类
  •      顺序容器 

   STL容器种类

容器概念

        容器,顾名思义,存储数据的器具。我们可以把它类比为数组。但是容器对象封装的许多对容器操作的方法,使用容器操作数据也更加方便。在c++中,容器类型被认为是一种可以创建具体对象的模板。容器可以被认为是一种对象。容器内的类型应该一致。容器的数据归容器所有:当容器过期时,里面的的数据也过期。(如果容器内是指针,指针指向内容并不一定过期)

容器分类

  • 基本容器         不保证元素按照特定顺序存储,也不保证元素顺序不变   
  • 顺序容器          是对基本容器的改进,要求元素按照严格的顺序排列。即除首元素和尾元素外,每个元素前后都有一个元素。
  • 关联容器          是对容器的另一种改进,关联容器要求值与键关联在一起。键,通常意义上说,是一种标识。例如,一个人的姓名通常与年龄和性别相关联。姓名是一种键值。通过姓名查找相关联的年龄和性别等信息。
  • 无序关联容器      也是对容器概念的一种改进,与关联容器一样,无序关联容器也与键值相关联,他与关联容器的差别在于无序关联容器的底层实现。关联容器底层使用的是树的结构实现,无序关联容器是基于哈希表实现的。无序关联容器,具有更高效的添加,删除,查找元素的算法效率。

  顺序容器

在STL中的顺序容器有以下种:vector、deque、list、forward_list根据顺序容器的特点,这些容器都有一些通用操作。

                    

顺序容器通用方法
表达式返回类型                      说明
X a(n,t); 声明一个名为a的由n个t值组成的序列
X (n,t); 创建一个由n个t值组成的无序序列
X a(i,j); 声明一个名为a的序列,并初始化为区间[i,j)的内容
X (i,j); 创建一个匿名序列,并初始化为区间[i,j)的内容。
a.insert(p,t);迭代器将t插入p前面
a.insert(p,n,t);void将n个t插入到p前面
a.insert(p,i,j);void将区间[i,j)中元素插入到p前面
a.erase(p);迭代器删除p指向的内容
a.erase(p,q)迭代器删除区间[p,q)中的元素
a.clear()void删除所有元素

        说明:X指容器类型,a指代容器对象,n表示整数,p,q,i,j表示迭代器。在这里我们使用vector容器演示上述常用方法。

代码如下:

#include<iostream>
#include<vector>
#include<iterator>
using namespace std;
int main(void)
{
	int n = 5;
	vector<int> v_one(5, n);//将容器v_one声明为5个5

	vector<int>::iterator ip;//声明vector迭代器
	for (ip = v_one.begin(); ip != v_one.end(); ip++)//将容器内容输出
	{
		cout << *ip << " ";
	}
	cout << endl;

	vector<int> v_two(v_one.begin(), v_one.end());//将容器v_two声明为容器v_one[v_one.begin(),v_one.end())内容
	for (ip = v_two.begin(); ip != v_two.end(); ip++)
	{
		cout << *ip << " ";
	}
	cout << endl;
	ip = v_two.begin() + 3;//将迭代器赋值为v_two索引值为3的指针,即第四个元素
	v_two.insert(ip, 6);//在第四个5前面插入元素6
	for (ip = v_two.begin(); ip != v_two.end(); ip++)
	{
		cout << *ip << " ";
	}
	cout << endl;
	v_one.insert(v_one.begin() + 1, 3, 3);//在v_one中的第二个元素前插入3个3
	for (ip = v_one.begin(); ip != v_one.end(); ip++)
	{
		cout << *ip << " ";
	}
	cout << endl;
	v_one.insert(v_one.begin(), v_two.begin(), v_two.end());//在容器v_one首元素前插入容器v_two的所有元素
	for (ip = v_one.begin(); ip != v_one.end(); ip++)
	{
		cout << *ip << " ";
	}
	cout << endl;
	v_one.erase(v_one.begin());//删除v_one第一个元素
	for (ip = v_one.begin(); ip != v_one.end(); ip++)
	{
		cout << *ip << " ";
	}
	cout << endl;
	v_one.erase(v_one.begin(), v_one.begin() + 3);//删除容器v_one前三个元素
	for (ip = v_one.begin(); ip != v_one.end(); ip++)
	{
		cout << *ip << " ";
	}
	cout << endl;
	v_one.clear();//删除v_one所有元素
	for (ip = v_one.begin(); ip != v_one.end(); ip++)//元素被清空返回空
	{
		cout << *ip << " ";
	}
	return 0;
}

  1. vector

        模板类vector 类似于String类,是一种动态数组,在STL中我们把它称为容器,可以在运行阶段设置vector对象的长度,可以在末尾附加数据,可以在中间插入数据,它是new创建动态数组的替代品,vector使用new和delete管理内存,但是是自动完成的。在头文件vector中声明了vector 的模板。

       vector中常用的其他方法

表达式                                   说明
a.front()索引容器首元素
a.back()索引容器尾元素
a.push_back(t)从vector 容器结尾插入t
a.pop_back(t)从vector容器后删除t
a[n]索引下标为n的元素
a.at(t)索引下标为n的元素

示例代码:

#include<iostream>
#include<vector>
using namespace std;
int main(void)
{
	int n = 5;
	int i;
	vector<int> v_one;
		v_one.push_back(1);
		v_one.push_back(2);
		v_one.push_back(3);
		v_one.push_back(4);
		v_one.push_back(5);//向容器中插入0~5
	for (int i = 0; i < n; i++)
	{
		cout << v_one[i]<<" ";
	}
	cout << endl;
	cout << "v_one.front()=" << v_one.front() << endl;//输出容器首元素
	cout << "v_one.back()=" << v_one.back();//输出容器尾元素
	v_one.pop_back();
	v_one.pop_back();//删除后两个元素
	cout << endl;
	for (int i = 0; i < n-2; i++)
	{
		cout << v_one.at(i) << " ";
	}
	return 0;
}

代码结果:

1 2 3 4 5

v_one.front()=1

v_one.back()=5

1 2 3

 2.list

list模板类表示双向链表,定义在头文件list中。除第一个和最后一个元素外,每个元素都与前后的元素相链接。这意味着可以双向遍历容器list,我们知道链表的插入和删除的时间复杂度是O(1),所以list的插入和删除的时间是固定的。而vector 底层实现是一个动态数组,插入和删除的时间是线性的,vector 强调的是快速索引,而list强调快速地插入和删除数据。由于list的底层实现是链表,所以不允许快速访问。下面是list成员函数:

成员函数

说明
void merge(list<T,Alloc>& x)将链表x与调用链表合并,且两链表内部已排序,最终链表存在调用链表中。时间复杂度为O(n)
void remove(const T& val)从链表中删除示例元素,时间复杂度为O(n)
void sort()将链表进行排序,时间复杂度为nlogn
void splice(lierator pos,list<T,Alloc> x)将链表x的内容插入到pos前,x将为空。时间复杂度O(1)
void unique()将连续相同的元素压缩为单个元素,时间复杂度为O(n)

代码示例:

#include<iostream>
#include<list>
using namespace std;
int main(void)
{
	list<int> l_one{1,1,3,5,};
	list<int> l_two{6,2,4};//声明三个list,并且l_one已排好序
	list<int> l_three{1,2};
	l_two.sort();//将l_two排序
	list<int>::iterator ls;//声明list迭代器
	for (ls = l_two.begin(); ls != l_two.end(); ls++)//输出已排序后的l_two
	{
		cout << *ls << " ";
	}
	l_two.merge(l_one);//合并list_one和list_two,链表在l_two中
	cout << endl;
	for (ls = l_two.begin(); ls != l_two.end(); ls++)//输出已合并后的l_two
	{
		cout << *ls << " ";
	}
	l_two.splice(l_two.begin() , l_three);//在l_two前插入链表l_three内容
	cout << endl;
	for (ls = l_two.begin(); ls != l_two.end(); ls++)
	{
		cout << *ls << " ";
	}
	cout << endl;
	l_two.unique();//压缩连续的元素为单个元素,注意不连续的元素相同无法删除
	for (ls = l_two.begin(); ls != l_two.end(); ls++)
	{
		cout << *ls << " ";
	}
	l_two.remove(1);//将链表中为1的元素都删除
	cout << endl;
	for (ls = l_two.begin(); ls != l_two.end(); ls++)
	{
		cout << *ls << " ";
	}
	return 0;
}

代码结果:

2 4 6

1 1 2 3 4 5 6

1 2 1 1 2 3 4 5 6

1 2 1 2 3 4 5 6

2 2 3 4 5 6

容器适配器

       除顺序容器外,STL定义了三个顺序容器适配器:Stack、queue、和priority_queue.适配器是是标准库的一个通用概念。容器、迭代器、和函数都有适配器。适配器接受已有的容器类型、使其行为看起来像另一种事物。例如Stack容器适配器接受一个容器,进行改造使其看起来像Stack这种结构。

1.queue

        queue模板类声明在头文件queue中,根据队列的特点,模板类queue不允许随机访问队列中元素,不允许遍历队列。它的基本操作是添加队尾元素,删除队首元素,查看队首和队尾元素的值,检查队列元素,判断队列元素是否为空等。

          方法                                      说明
bool empty() const如果队列为空,返回true,否则,返回falsre
size_type size()const返回队列元素的数目
T& front()返回指向队首元素的引用
T& back()返回指向队尾元素的引用
void push(const T& x)在队尾插入x
void pop()删除队首元素

 

代码示例:

#include<iostream>
#include<queue>
using namespace std;
int main(void)
{
	queue<int> q_one;
	if (q_one.empty())//判断是否为空队列
	{
		cout << "queue is empty!" << endl;
		q_one.push(1);
		q_one.push(2);
		q_one.push(3);
		q_one.push(4);//从队尾插入数据
		cout << "Now q_one has " << q_one.size() << " elements";//检查队列元素个数
		cout << endl;
		cout << "q_one.front()=" << q_one.front() << endl;
		cout << "q_one.back()=" << q_one.back() << endl;
		q_one.pop();
		cout << "q_one.front()=" << q_one.front();

	}
	return 0;
}

代码结果:

 

2.Stack

       与queue相似,stack在头文件stack中定义,不允许随机访问和遍历栈。它的操作有压入栈顶元素和弹出栈顶元素,查看栈的值,查看元素数目,测试栈是否为空。

          方法                                    说明
bool empty()const如果栈为空,则返回true,否则,返回false
size_type size() const返回栈中元素数目
T& top()返回指向栈的元素的引用
void push(const T& x)在栈顶元素插入x
void pop删除栈顶元素

示例代码:

 

#include<iostream>
#include<stack>
using namespace std;
int main(void)
{
	stack<int> s_one;
	if (s_one.empty())//判断是否为空队列
	{
		cout << "stack is empty!" << endl;
		s_one.push(1);
		s_one.push(2);
		s_one.push(3);
		s_one.push(4);//从队尾插入数据
		cout << "Now s_one has " << s_one.size() << " elements";//检查队列元素个数
		cout << endl;
		cout << "s_one.top()=" << s_one.top() << endl;
		s_one.pop();
		cout << "s_one.top()=" << s_one.top();

	}
	return 0;
}

代码结果:

stack is empty!

Now s_one has 4 elements

s_one.top()=4

s_one.top()=3

关于关联容器将在下一篇中分析它们的常用用法,小伙伴们记得一键三连哦!!!              

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值