C++STL学习笔记

C++STL泛型编程

ANSI C++中包含了一个C++ STL(Standard Template Library),即C++标准模板库,又称C++泛型库,它在std命名空间中定义了常

用的数据结构和算法,使用起来很方便。

STL提供三种类型的组件:容器、迭代器、算法,它们都支持泛型程序设计标准。

容器主要有两类:顺序容器和关联容器。顺序容器和关联容器又称为一级容器

顺序容器:顺序容器表示线性数据结构,包括vector、list、deque

关联容器:关联容器是非线性数据结构,可快速定位容器中的数据,包括set、multiset、map、multimap

容器适配器:容器适配器是顺序容器的受限版本,用于处理特殊情况,包括stack、queue、priority_queue

迭代器的作用是遍历容器。

STL算法包含四类:排序算法、不可变序算法、变序性算法、数值算法

STL容器类及其头文件:

vector <vector>  直接访问任意元素,快速插入、删除尾部元素

duque <deque> 直接访问任意元素,快速插入、删除头部和尾部元素

list    <list>  快速插入、删除任意位置元素

set   <set>  快速查询元素,无重复关键字

multiset  <set>  与set相同,但允许重复关键字

map  <map>  关键字/值对映射,不允许重复关键字,使用关键字快速查询元素

multimap  <map>  与map相同,但允许重复关键字

stack  <stack>  后进先出容器

queue  <queue>  先进先出容器

priority_queue  <queue>  高优先级元素先删除

STL迭代器:

每个容器都有自己的迭代器类型,函数begin()返回指向容器首元素的迭代器,函数end()返回指向容器尾元素之后位置的迭代器。

迭代器的类型:

1.输入迭代器:用于从容器中读取元素,每一步只能沿向前的方向移动一个元素;

2.输出迭代器:用于从容器中写入元素,每一步只能沿向前的方向移动一个元素;

3.向前迭代器:包含输入输出迭代器的所有功能,既支持读操作又支持写操作;

4.双向迭代器:包含向前迭代器的所有功能,还有向后移动的能力,每一步可以自由选择向前还是向后移动;

5.随机访问迭代器:好汉双向迭代器的所有功能,具有按任意顺序访问任意元素的能力,即能向前或向后跳过任意多个元素

预定义的迭代器:

STL容器使用关键字来预定义迭代器。STL中预定义的迭代器有iterator、const_iterator、reverse_iterator和const_reverse_iterator。

每个一级容器中读定义了这些迭代器。

由于迭代器是容器类中用typedef定义的,因此,需要用作用域解析运算符来引用它们。

例如:vector<int>::inerator  p1 =  intVector.begin()

const_iterator与iterator类似,差别在于不能通过const_iterator修改元素值,即const_iterator是只读的。

reverse_iterator:反向迭代器。

vector<int>::reverse_iterator p1 = intVector.rbegin();   函数rbegin()返回一个指向容器尾元素的reverse_iterator,函数rend()返回一个

指向容器首元素(逆序中)下一个位置的reverse_iterator

istream_iterator和ostream_iterator

 这两个迭代器用于序列化元素,既可以用它们序列化容器中的元素,也可以用于序列化输入/输出流中的元素。

一个例子:使用istream_iterator从输入流中读取数据,以及使用ostream_iterator向输出流写入数据。

#include <iostream>
#include <iterator>
#include <cmath>
using namespace std;

int main()
{
	cout<<"please input three numbers:";
	istream_iterator<int> inputIterator(cin);	//输入迭代器
	ostream_iterator<int> outputIterator(cout);	//输出迭代器

	int number1 = *inputIterator;	//解引用,从cin读取一个整数
	inputIterator++;		//将迭代器移动到输入流中下一个数据
	int number2 = *inputIterator;
	inputIterator++;
	int number3 = *inputIterator;
	cout<<"the largest number is:";
	*outputIterator = max(max(number1, number2), number3);	//解引用,向cout写入了一个整数
	return 0;
}


顺序容器:

STL提供了三个顺序容器:vector、list、deque。deque和vector都是用数组实现的,list是用链表实现的。

vector:如果数据以附加方式加入到vector(即加入到尾部),那么vector具有很好的效率,但是在其他任意位置(除了尾部)插入和删除

元素,vector效率则很低。

deque:(double-ended queue)双端队列,与向量很像,在其两端进行插入操作则效率很高,但是在内部进行插入和删除操作,效率

还是很低。

list:适合于需要频繁在容器中间进行插入和删除操作的应用。

顺序容器中的共同函数:

assign(n, elem)    将指定元素的n份拷贝加入到容器中

assign(beg, end)   赋值从迭代器beg和end之间的元素

push_back(elem)   将元素附加到容器

pop_back()   删除容器尾元素

front()    返回容器首元素

back()   返回容器尾元素

insert(position, elem)   将元素插入到容器的指定位置

1.vector:

vector的构造函数:

vector(n, element)  构造一个向量,填入指定元素的n份拷贝

vector(beg, end)  构造一个向量,用迭代器beg至end之间的 元素进行初始化

vector(size)   构造一个指定规模的向量

  一个使用vector的例子:

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

int main()
{
	double values[] = {1,2,3,4,5,6,7};
	vector<double> doubleVector(values, values + 7);	//构造一个响亮

	for(vector<double>::iterator it = doubleVector.begin(); it != doubleVector.end(); it++)
	{
		cout<<*it<<" ";
	}
	cout<<"\n";

	doubleVector.assign(5, 9.9);	//assgn()函数会清除容器中的所有元素
	for(vector<double>::iterator it = doubleVector.begin(); it != doubleVector.end(); it++)
	{
		cout<<*it<<" ";
	}
	cout<<"\n";
	return 0;
}

2.deque:

双端队列在两端进行插入和删除操作都是很高效的。

deque的两个特有函数:

push_front(element): 将元素插入到队首

pop_front() : 删除队首元素

3.list:

list是作为双向链表实现的,因此,可高效地在列表的任意位置进行插入和删除操作。

list的两个特有函数:

push_front(element): 将元素插入到列表头

pop_front() : 删除列表头元素

remove(element):删除列表中所有与指定元素相等的元素

remove_if(oper):  删除所有令oper(element)为真的元素

splice(pos, list2): 将list2中所有元素移动到此列表指定位置之前,调用此函数后,list2变为空

splice(pos1, list2, pos2): 将list2中从pos2开始的元素移动到本列表pos1之前,调用此函数后,list2变为空

splice(pos1, list2, beg, end): 将list2中从beg至end之间的元素移动到本列表pos1之前,调用此函数后,list2变为空

sort(): 将列表按升序排序

sort(oper): 排序列表,排序标准由oper指定

merge(list2): 假定本列表和list2都已排序,将list2合并至本列表,调用此函数后,list2变为空

merge(list2, oper): 假定本列表和list2都已排序,按oper指出的排序标准将list2合并至本列表

reverse():  反转本列表

vector和deque的迭代器都是随机访问迭代器,而list的迭代器是双向迭代器。因此,不能用下标运算符[ ]访问列表中的元素。

list、set、multiset、map和multimap支持双向迭代器;

stack、queue、priority_queue不支持迭代器。


关联容器:

STL提供了4个关联容器:set、multiset、map、multimap。这些容器提供了通过关键字快速存储和访问数据元素的能力。关联容器

中的数据元素根据某种排序标准进行了排序,默认情况下,使用<运算符进行排序。、

关联容器的共同函数:

find(key): 搜索容器中具有指定关键字的元素,返回指向此元素的迭代器

lower_bound(key): 搜索容器中具有指定关键字的第一个元素,返回指向此元素的迭代器

upper_bound(key): 搜索容器中具有指定关键字的最后一个元素,返回指向此元素之后位置的迭代器

count(key): 返回容器中具有指定关键字的元素的数目。

默认情况下,集合中的元素是按升序存放的,为了指定降序方式,可以这样写:

multiset<int, greater<int>>set1(values, values + 3);  greater<int> 之后的空格是必须的,如果缺少这个空格,C++会将其与>>运算

符混淆。

greater<int>和less<int>,下面看它们的定义:

		// TEMPLATE STRUCT greater
template<class _Ty>
	struct greater
		: public binary_function<_Ty, _Ty, bool>
	{	// functor for operator>
	bool operator()(const _Ty& _Left, const _Ty& _Right) const
		{	// apply operator> to operands
		return (_Left > _Right);
		}
	};

		// TEMPLATE STRUCT less
template<class _Ty>
	struct less
		: public binary_function<_Ty, _Ty, bool>
	{	// functor for operator<
	bool operator()(const _Ty& _Left, const _Ty& _Right) const
		{	// apply operator< to operands
		return (_Left < _Right);
		}
	};

 

set和multimap的用法的例子

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

int main()
{
	int values[] = {1, 8, 2, 1, 3, 1, 2, 4, 5};
	set<int> set1(values, values + 8);
	set<int>::iterator it;
	//multiset<int> set1(values, values + 8);
	//multiset<int>::iterator it;
	cout<<"set:";
	for(it = set1.begin(); it != set1.end(); it++)
	{
		cout<<*it<<" ";
	}
	cout<<endl;
	//it = set1.lower_bound(2);
	it = set1.upper_bound(3);
	cout<<*it<<endl;
	return 0;
}

map的用法的例子:

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

int main()
{
	map<int, string> map1;
	map1.insert(map<int, string>::value_type(001, "hello"));	//添加元素
	map1.insert(map<int, string>::value_type(002, "my"));
	map1.insert(map<int, string>::value_type(003, "love"));
	map<int, string>::iterator it = map1.begin();
	for(; it != map1.end(); it++)
	{
		cout<<it->first<<" "<<it->second<<endl;
	}
}

 

容器适配器:

STL提供了三种容器适配器:stack、queue、priority_queue。这些容器称为适配器(adapter),因为它们是由顺序容器变化而来,用

于处理特殊情况。

1.stack:

栈是一种后进先出的容器,可以选择vector、deque、或list来构造一个stack对象。默认情况下,stack基于deque实现。

栈支持的函数:

push(element): 将元素添加到栈顶

pop():  删除栈顶元素

top():   返回栈顶元素,不删除它

size():  返回栈的大小

empty(): 若栈空返回真

一个使用stack的例子:

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

template<typename T>
void printStack(T &s)
{
	while(!s.empty())
	{
		cout<<s.top()<<" ";
		s.pop();
	}
	cout<<"\n";
}

int main()
{
	stack<int> s1;
	stack<int, vector<int> >s2;
	for(int i = 0; i < 8; i++)
	{
		s1.push(i);		//入栈
		s2.push(i);
	}
	cout<<"s1:";
	printStack(s1);
	cout<<"s2:";
	printStack(s2);
	return 0;
}

 

2.queue:

队列是一种先进先出容器,可以选择deque或list来构造一个queue对象。默认情况下,queue用deque实现。

队列支持的函数:

push(): 将元素插入到队尾

pop(): 删除队首元素

front():  返回队首元素,但不删除它

back():  返回队尾元素,但不删除它

size():  返回队列的大小

empty(): 若队列空则返回真

一个使用queue的例子:

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

template<typename T>
void printQueue(T &q)
{
	while(!q.empty())
	{
		cout<<q.front()<<" ";
		q.pop();
	}
	cout<<"\n";
}

int main()
{
	queue<int> q1;
	queue<int, list<int> > q2;
	for(int i = 0; i < 8; i++)
	{
		q1.push(i);
		q2.push(i);
	}
	cout<<"q1:";
	printQueue(q1);
	cout<<"q2:";
	printQueue(q2);
	return 0;
}

 

3.priority_queue:

在优先队列中,每个元素都被赋予一个优先级,优先级最高的元素首先被访问/删除,业就是说,优先队列是最高优先级最先出的。

可以选择vector或deque来构造一个priority_queue,默认是用vector来实现的,priority_queue类支持的函数与stack类相同。

priority_queue类支持的函数与stack类相同。

一个使用priority_queue的例子:

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

template<typename T>
void printPQueue(T &pq)
{
	while(!pq.empty())
	{
		cout<<pq.top()<<" ";
		pq.pop();
	}
	cout<<"\n";
}

int main()
{
	priority_queue<int> pq1;
	priority_queue<int, deque<int> > pq2;

	for(int i = 0; i < 8; i++)
	{
		pq1.push(i);
		pq2.push(i);
	}
	cout<<"pq1:";
	printPQueue(pq1);
	cout<<"pq2:";
	printPQueue(pq2);

	return 0;
}


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值