STL之序列式容器

STL之序列式容器

 

 STL容器即是将运用最广的一些数据结构实现出来,根据其在容器的排列特性,将其分为序列式容器和关联是容器。本文主要记录序列式容器,以及其常用的功能函数。

 

1、vector

vector和数组一样维护了一个连续的线性空间,vector空间运用较灵活,数组是静态空间一旦配置了就无法修改,而vector是动态空间,随着元素的加入其内部机制会动态扩充空间以容纳新元素。

vector常用功能函数:

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

/*Menu
01-0-输出vector
01-1-vector 相关函数
01-2-vector 容量大小相关
01-3-vector相关算法
*/

void VecPrint(const vector<int> &v);//01-0
void VecCreate(); //01-1
void VecCapacity(); //01-2
void VecAlgorithm(); //01-3
void VecTraverse(); //01-4

//01-0
void VecPrint(const vector<int> &v)
{
	cout<<"Print Vector!"<<endl;
	cout<<'[';
	for(int i=0;i<v.size();i++)
	{
		if(i==v.size()-1)
		{
			cout<<v[i]<<']'<<endl;
		}else
		{
			cout<<v[i]<<',';
		}
	}
}
//01-1
void VecCreate()
{
	//case 1
	//vector 内存空间一般按照2倍方式增长,但是有的编译器可能按照其它算法增长
	vector<int> v1;
	for(int i=0;i<10;i++)
	{
		v1.push_back(i+1);
		cout<<v1[i]<<'\t'<<v1.capacity()<<endl;
	}
	//case 2
	int arr[] = {1,2,3,4,5,6,7,8,9,10};
	vector<int> v2(arr,arr+sizeof(arr)/sizeof(int));
	VecPrint(v2);
	//case 3
	vector<int> v3(10,6);
	VecPrint(v3);
	for(int i=0;i<3;i++)
	{
		v3.pop_back();
		cout<<v3.capacity()<<endl; //空间分配后就不会自动回收
	}
}
void  TestVecCreate()
{
	VecCreate();
}
//01-2
void VecCapacity()
{
	//case 1
	vector<int> v1;
	for(int i=0;i<10;i++)
	{
		v1.push_back(i+1);
	}
	VecPrint(v1);
	cout<<"Size:"<<v1.size()<<'\t'<<"Capacity:"<<v1.capacity()<<endl;
	//case 2
	v1.resize(5);
	cout<<"Size:"<<v1.size()<<'\t'<<"Capacity:"<<v1.capacity()<<endl;
	//case 3 使用swap回收空间
	vector<int>(v1).swap(v1);//通过匿名对象方式回收空间
	cout<<"Size:"<<v1.size()<<'\t'<<"Capacity:"<<v1.capacity()<<endl;
	VecPrint(v1);
}
void TestVecCapacity()
{
	VecCapacity();
}
//01-3
void VecAlgorithm()
{
	//case 1 开辟10万次数据用了多少空间
	std::vector<int> v;
	int *p = NULL;
	int num = 0;
	for (int i = 0; i < 10000; ++i)
	{
		v.push_back(i);
		if(p!=&v[0])
		{
			p = &v[0];
			num++;
		}
	}
	cout<<num<<endl; //重新分配了num次空间
	//case 2 reserve 预留空间,如果知道空间大致数量的话直接通过reserve预留空间,防止多次重新分配空间,从而提高效率
	std::vector<int> v2;
	v2.reserve(10000);
	int *p2 = NULL;
	int num2 = 0;
	for (int i = 0; i < 10000; ++i)
	{
		v2.push_back(i);
		if(p2!=&v2[0])
		{
			p2 = &v2[0];
			num2++;
		}
	}
	cout<<"reserve:"<<num2<<endl; //重新分配了num次空间
	//case 3 数据存存取
	std::vector<int> v3;
	for(int i=0;i<5;++i)
	{
		v3.push_back(i+1);
	}
	cout<<v3.front()<<endl; //去第一个元素
	cout<<v3.back()<<endl; //取最后一个元素
	//case 4 插入删除
	std::vector<int> v4;
	v4.insert(v4.begin(),10);
	VecPrint(v4);
	v4.insert(v4.begin(),5,6);
	VecPrint(v4);
	v4.pop_back();
	VecPrint(v4);
	v4.insert(v4.end(),5,8);
	VecPrint(v4);
	v4.erase(v4.begin());
	VecPrint(v4);
	v4.erase(v4.begin(),v4.end());
	if(v4.empty())
	{
		cout<<"Is empty!\n";
	}
}
void TestVecAlgorithm()
{
	VecAlgorithm();
}
//01-4
void VecTraverse()
{
	std::vector<int> v;
	for(int i=0;i<10;i++)
		v.push_back(i+1);
	VecPrint(v);
	//case 1 逆序遍历
	//逆序输出需要使用revers_iterator迭代器,否则会出错
	for(vector<int>::reverse_iterator it=v.rbegin();it!=v.rend();it++)
	{
		cout<<*it<<'\t';
	}
	cout<<endl;
	//case 2 vector 迭代器是随机访问迭代器 支持跳跃式访问
	vector<int>::iterator itBegin = v.begin();
	itBegin = itBegin +3;
	cout<<*itBegin<<endl;
}
void TestVecTraverse()
{
	VecTraverse();
}

int main(int argc, char const *argv[])
{
//01-1
	//TestVecCreate();
//-01-2
	//TestVecCapacity();
//-01-3
	//TestVecAlgorithm();
//-01-4
	TestVecTraverse();
	return 0;
}

 

2、deque

deque是一个双向开口的连续线性空间,可在头尾两端分别做元素的删除和插入操作。相对于vector其允许于常数时间内在头部进行插入删除;其没有所谓的容量空间观念,它是动态地以分段连续空间组合而成,随时可以增加一段新的空间并链接起来;其没有vector中的重新分配空间-拷贝-释放等过程。

deque常用功能函数如下:

#include <iostream>
#include <deque>
#include <algorithm>
using namespace std;

/*Menu
02-0-输出deque
02-1- deque创建方法
02-2- deque常用方法
02-3- deque排序方法
*/

void DeqPrint(const deque<int> &d); //02-0
void DeqCreate(); //02-1
void DeqMethod(); //02-2
void DeqAlgorithm(); //02-3

//02-0
void DeqPrint(const deque<int> &d)
{
	cout<<'[';
	for(deque<int>::const_iterator it=d.begin();it!=d.end();it++)
	{
		if(it==d.end()-1)
		{
			cout<<*it<<']'<<endl;	
		}else
		{
			cout<<*it<<',';
		}
	}
}
//02-1
//deque 和vector区别在于其用常数时间在头部插入删除数据
void DeqCreate()
{
	//create method 1
	deque<int> d;
	d.push_back(1);
	d.push_back(2);
	d.push_back(3);
	d.push_back(4);
	DeqPrint(d);
	//create method 2
	deque<int> d2(d.begin(),d.end());
	d2.push_back(100);
	DeqPrint(d2);
	//交换
	cout<<"swap:\n";
	d.swap(d2);
	DeqPrint(d2);
	DeqPrint(d);
}
void TestDeqCreate()
{
	DeqCreate();
}
//02-2
void DeqMethod()
{
	//case 1 
	deque<int> d;
	d.push_back(1);
	d.push_back(2);
	d.push_front(11);
	d.push_front(21);
	DeqPrint(d);
	d.pop_back();
	d.pop_front();
	DeqPrint(d);
	cout<<"Front:"<<d.front()<<'\t'<<"Back:"<<d.back()<<endl;
	//case 2 insert
	deque<int>d2;
	d2.push_back(10);
	d2.push_back(20);
	d2.insert(d2.begin(),d.begin(),d.end());
	DeqPrint(d2);
	//case3 除了头部操作外,其它和vector类似
}
void TestDeqMethod()
{
	DeqMethod();
}
//02-3
bool DeqCompare(int val1,int val2)
{
	return val1>val2;
}
void DeqAlgorithm()
{
	deque<int> d;
	d.push_back(15);
	d.push_back(2);
	d.push_front(11);
	d.push_front(21);
	DeqPrint(d);
	//sort() 正常从小到大
	sort(d.begin(),d.end());
	DeqPrint(d);
	//使用仿函数 设置sort的排序规则
	sort(d.begin(),d.end(),DeqCompare);
	DeqPrint(d);
}
void TestDeqAlgorithm()
{
	DeqAlgorithm();
}

int main(int argc, char const *argv[])
{
//02-1
	//TestDeqCreate();
//02-2
	//TestDeqMethod();
//02-3
	TestDeqAlgorithm();
	return 0;
}

 

3、stack

stack是一种后进先出的容器,其不允许遍历操作,运行新增、移除、取得顶部元素等操作。

stack常用功能函数如下:

#include <iostream>
#include <stack>
#include <algorithm>
using namespace std;

/*Menu
03-0- stack输出
03-1- stack 创建
*/

void StaPrint(stack<int> &s); //03-0
void StaCreate(); //03-1

//03-0
void StaPrint(stack<int> &s)
{
	cout<<'[';
	while(s.size()!=0)
	{
		if(s.size()==1)
		{
			cout<<s.top()<<']';
			s.pop();
		}else
		{
			cout<<s.top()<<',';
			s.pop();
		}
	}
	cout<<endl;
}
//03-1
void StaCreate()
{
	stack<int> s;
	s.push(1);
	s.push(2);
	s.push(3);
	StaPrint(s);
	cout<<s.size()<<endl;
}
void TestStaCreate()
{
	StaCreate();
}

int main(int argc, char const *argv[])
{
//03-1
	TestStaCreate();
	return 0;
}

 

4、queue

queue使用一种先进先出的容器,其不允许遍历操作,其有两个出口,queue允许新增元素、移除元素、从最底端加入、最顶端取出元素。

queue常用功能函数如下:

#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;

/*Menu
04-0 queue
04-1 queue创建方法
*/

void QuePrint(queue<int> &q); //04-0
void QueCreate(); //04-1

//04-0
void QuePrint(queue<int> &q)
{
	cout<<'[';
	while(!q.empty())
	{
		if(q.size()==1)
		{
			cout<<q.front()<<']';
			q.pop();
		}else
		{
			cout<<q.front()<<',';
			q.pop();
		}
	}
	cout<<endl;
}
//04-1
void QueCreate()
{
	queue<int> q;
	q.push(1);
	q.push(2);
	q.push(3);
	cout<<"front:"<<q.front()<<'\t'<<"back:"<<q.back()<<endl;
	QuePrint(q);
	cout<<q.size()<<endl;
}
void TestQueCreate()
{
	QueCreate();
}

int main(int argc, char const *argv[])
{
//04-1
	TestQueCreate();
	return 0;
}

 

5、list

list是双向开口的数据结构,其节点不保证在连续空间,相对于vector,其对资源利用更好,不浪费资源,其插入和删除都是常数时间。其不仅是一个双向链表,还是一个双向环状链表,所以它只需要一个指针便可以完整表现整个链表。其迭代器具备前移、后移的能力,其有一个重要性质:插入操作和接合操作(splice)都不会造成原有的list迭代器失效。

list常用功能函数如下:

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

/*Menu
05-0 list输出
05-1 list创建
05-2 
05-3 
*/

void ListPrint(list<int> &l);//05-0
void ListCreate();//05-1
void ListMethod();//05-2
void ListAlgorithm();//05-3

//05-0
void ListPrint(list<int> &l)
{
	list<int>::iterator it = l.begin();
	int i=0;
	for(;it!=l.end();it++,i++)
	{
		if(i==l.size()-1){
			cout<<*it;
		}else
			cout<<*it<<"->";
	}
	cout<<endl;
}
//05-1
void ListCreate()
{
	//case 1
	list<int> l;
	for(int i=0;i<10;i++)
	{
		l.push_back(i+1);
	}
	ListPrint(l);
	//case 2
	list<int> l2(10,10);
	ListPrint(l2);
	//case 3
	list<int> l3(l.begin(),l.end());
	ListPrint(l3);
}
void TestListCreate()
{
	ListCreate();
}
//05-2
void ListMethod()
{
	list<int> l;
	for(int i=0;i<10;i++)
	{
		l.push_back(i+1);
	}
	//case 1 逆序输出
	//list 不支持随机访问
	int i=0;
	for(list<int>::reverse_iterator it=l.rbegin();it!=l.rend();it++,i++)
	{
		if(i==l.size()-1){
			cout<<*it;
		}else
			cout<<*it<<"->";
	}
	cout<<endl;
	//case 2 插入节点
	list<int> l2;
	l2.push_back(11);
	l2.push_back(12);
	l2.push_back(13);
	l2.push_front(3);
	l2.push_front(2);
	l2.push_front(1);
	ListPrint(l2);
	//case 3 删除节点
	l2.pop_back();
	l2.pop_front();
	ListPrint(l2);
	//case 4 插入操作
	l2.insert(l2.begin(),1);
	l2.insert(l2.end(),13);
	ListPrint(l2);
	//case 5 remove 删除所有与elem值相匹配的元素
	// erase 参数为删除迭代器指向的位置
	l2.push_back(13);
	l2.remove(13);
	l2.erase(l2.begin());
	ListPrint(l2);
	//case 6
	if(!l2.empty())
	{
		cout<<"size:"<<l2.size()<<endl;
	}
	l2.resize(8);//比实际size大就补0
	ListPrint(l2); 
	l2.resize(3);//比实际size小就去前n个
	ListPrint(l2);
	l2.swap(l);
	cout<<"l:\t";
	ListPrint(l);
	cout<<"l2:\t";
	ListPrint(l2);
}
void TestListMethod()
{
	ListMethod();
}
//05-3
bool ListCompare(int val1,int val2)
{
	return val1>val2;
}
void ListAlgorithm()
{
	list<int> l;
	for(int i=0;i<10;i++)
	{
		l.push_back(i+1);
	}
	//case 1
	l.reverse();
	ListPrint(l);
	//case 2
	//sort() 不支持随机迭代器的无法使用系统中的sort函数,可以使用其自带sort功能
	l.sort();
	ListPrint(l);
	//case 3 从大到小
	//如果使用自定义类型,如类成员,必须使用自定义排序规则
	//同理,remove时候,也需要自定义删除规则
	l.sort(ListCompare);
	ListPrint(l);

}
void TestListAlgorithm()
{
	ListAlgorithm();
}

int main(int argc, char const *argv[])
{

//05-1
	//TestListCreate();
//05-2
	//TestListMethod();
//05-3
	TestListAlgorithm();
	return 0;
}

 

6、说明

当前已在mingw32(gcc 4.9.2)上测试通过。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昕光xg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值