《C++STL标准程序库开发指南》第三章,容器

本章重点介绍,各种容器的定义和使用方法。

容器是,用来存储和组织其他对象的对象。容器适配器,严格地说并不是容器,
而是,使用容器的对象,是在容器的基础上发展起来的。

作为容器的成员,必须满足的三个条件:
1 元素必须是可复制的。所有容器均会产生1份元素副本,不会发生alias现象;
				   所有容器操作为传回的均是其元素的副本。这导致复制构造函数的执行非常频繁。
2 元素必须是可指派(assign)的。
3 元素必须是可释放的(经过析构函数释放内存)。使用者从容器中将元素删除时,容器必须释放其元素
									   所占的内存。按这种需求,析构函数不能设置为private类型。

作为容器的成员函数(操作),其中3个最重要的能力:
1 容器均能提供value,而非refrence(引用)
2 所有的元素自动形成顺序。
3 函数使用者必须确保传递的参数符合要求。

容器的种类和数据类型

STL容器通常分为3类:
1 序列式容器(sequence 容器):vector动态数组 deque双向队列,list双向串行
2 关联性容器:set,multiset,map,multimap,hash(哈希)table
3 容器配接器:stack,queue,priority_queue

STL容器的数据结构,3种:
1 string类
2 bitset
3 valarray

序列式容器概述:
vector类模板

template <class T,class Allocator=allocator<T>> class vector;
vector 就像一个动态数组,是典型的“将元素置于动态数组中加以管理”的抽象概念。

vector高级编程

1 vector相关的元素访问方法
	vector<typename T>c;
	c.at(index);
	c(index);
	c.front();
	c.back();

2 迭代器相关函数
	begin(),end(),
	rbegin(),rend() 逆向迭代
	
3 元素查找和搜索
	find(),find_if()两个算法均可以使用迭代器、,两个迭代器参数决定了搜索和查找的范围
					函数返回值均为迭代器类型。
	find()函数的原型:
			template<class InputIterator,class T>
			inline InputIterator find(InputIterator first,InputIterator last,const T& value)
			template<class InputIterator,class T,class Predicate>
			inline InputIterator find_if(InputIterator first,InputIterator last,Predicate prediccate)

4 vector型容器中的字符串处理
	使用vector管理字符串,可以处理字符串中的每个字符,并且vector可以自动管理内存。

5 元素排序
	sort()
  插入元素
  	push_back() insert()
  删除元素
  	pop_back()		//删除最后一个元素 
  	erase() 		//删除由迭代器指定的元素,可以删除区间范围的元素
  	clear() 		//实现删除向量vector的所有元素
  	remove()		//
  对象交换
  	swap()
  	template<class T,class A>
  	void swap(const vector<T,A>&v1,const vector<T,A>&v2);
  
  vector<bool>类(*****************************)
  针对元素类别为bool的vector设计了特殊版本,目的是获取优化的vector。

list类模板

list由双向链表实现,list优势在于,在任何位置执行插入和删除动作都非常迅速
template<class Tclass Allocator=allocator<T>> class list;
1 list不支持随机存取
2 在list的任何位置执行元素的插入和移除都非常快,可以迅速实现。
3 list不支持随机存取,不提供下标操作符和at()函数
4 list没有提供容量,空间重新分配等操作函数,每个元素都有自己的内存
5 list提供特殊成员函数,专门用于移动元素,和同名算法相比,速度更快

list 的定义和容量

头文件中,4种构造函数
explicit list(const _A& _A1 = _A()):allocator(_A1),_Head(_Buynode()),_Size(0){}
explicit list(size_type _N,const _Ty& _V=_Ty(),const _A& _A1 = _A()):allocator(_A1),_Head(_Buynode()),_Size(0)
{
	insert(begin(),_N,_V);
}
list(const _Myt& _X):allocator(_X.alloctor),Head(_Buynode()),_Size(0)
{
	insert(begin(),_X.begin(),_X,end());
}
list(const _Ty* _F,const _Ty* _L,const _A& _A1 = A()):allocator(_A1),_Head(_Buynode()),_Size(0)
{
	insert(begin(),_F,_L);
}

list(A) listname;
list(A) listname(size);
list(A) listname(size,value);
list(A) listname(elselist);
list(A) listname(first,last);

list<int> mylist;

list提供两个成员函数,push_front(),push_back()
list型容器,具有一些特殊函数
merge()
	void merge(list& x);
	void merge(list& x,greater<T> pr);
remove()
	void remove(const Type& _Val);
remove_if()
	template <class Pred> void remove_if(Pred pr);
	typedef binder2nd<not_equal_to<_Ty>> Pred;
sort()
	void sort()
	void sort(greater<T> pr)
splice()
	//merge()函数并不是非常灵活,有一定局限性
	void splice(iterator it,list& x);
	void splice(iterator it,list& x,iterator first);
	void splice(iterator it,list& x,iterator first,iterator last);
unique()
	void unique();
	template <class BinaryPredicate>
	void unique(BinaryPredicate _Pred);

reverse()
	void reverse();

deque(双端队列)类模板

double-ended queue
容器deque是典型的双端队列,完成了标准C++数据结构中队列的所有功能。

depue和vector相比,具有诸多优点之处
(1)deque可以在两端迅速插入和删除元素,而vector只提供了成员函数push_back和pop_back()
 (2) 存取元素时,容器deque会稍慢一些
 (3) deque的迭代器指针是之智能指针
 (4) 在内存区块受限制的系统中,deque型容器可以包含更多元素,因为deque型容器使用多块内存;
 (5) deque不支持对容器和内存重新分配时机的控制
 (6) deque的内存区块不使用时,会被释放
 (7) 在序列中间插入和删除元素时,deque的速度很慢,需要移动相关的所有元素;
 (8) 容器deque的迭代器属于随机存取迭代器

<deque> 4种构造函数
explicit deque(const A& a1 = A());
explicit deque(size_type n,const T& v = T(),const A& a1 = A());
deque(const deque& x);
deque(const_iterator first,const_iterator last,const A& a1 = A());

deque<typename T>name;
deque<typename T>name(size);
deque<typename T>name(size,value);
deque<typename T>name(elsedeque);		//用复制构造函数
deque<typename T>name(elsedeque.first(),elsedeque.end());
//使用迭代器创建deque容器对象

deque容器基础成员函数

赋值
push_front()	//用于在容器的头部插入新元素
push_back()		//用于在容器的尾部插入新元素

pop_front()		//用于获取容器的头元素
pop_back()		//用于获取容器的尾元素

deque容器还提供运算符[]

const_reference operator[](size_type pos) const;
reference operator[](size_type pos);

迭代器相关函数
(1) begin rbegin end rend;	//返回值为迭代器,或者逆迭代器
(2)	back front		//返回值为引用
(3) bool empty() const
(4) const_reference at(size_type pos) const;
    refrence at(size_type pos);
(5) assign()
	void assign(const_iterator first,const_iterator last);
	void assign(size_type n,const T& x = T());

deque的高级编程

元素交换
template <class T,class Allocator>
void swap(deque<T,Allocator>& x,deque<T,Allocator>&y);
插入和删除
iterator insert(iterator it,const T& x = T());
void insert(iterator it,size_type n,const T& x);
void insert(iterator it,const_iterator first,const_iterator last);
erase()
clear()  == erase(begin,end)
查找
find()

相关联容器概述

相关联容器包括:set,multiset,map,multimap,其中set可以视为一种特殊的map
其元素的值即为键值。
相关联容器其实是,相关联数组概念的推广
相关联容器根据特定的排序准则,自动为其元素排序。相关联容器中的元素都已经是排序,是已经排序的。
所有关联式容器都有一个可供选择的template参数,指明排序原则。
排序准则以函数形式呈现,用于比较元素或元素键。模板情况下以“operator<”进行比较
程序员可以提供自己定义的比较函数
通常,关联式容器由二叉树实作出来。
关联容器优点:提供对元素的快速访问,却不能实现任意位置的操作。

在这里插入图片描述
set/multiset类模板

集合set定义
template<class Key,class Traits = less<key>,class Allocator = allocator<Key>> class set
Key是存储在集合元素中的数据类型,Traits是实现集合内部排序的仿函数,默认less<Key>
Allocator代表集合的内存配置器,负责内存的分配和销毁

set的构造函数
在这里插入图片描述
排序准则
STL先建立一个抽象概念阶层体系,形成一个软件组件分类学,最后再以实际工具(template)将各个概念实现。
理论架构《Generic Programming and the STL》《泛型程序设计与STL》

std::set<int,std::greater<int>> s1;
set<int> s2(less<int>());

#include<iostream>
#include<set>
using namespace std;
void OutPut(set<int> &s)
{
	set<int>::iterator it;
	for(it=s.begin();it!=s.end();it++)
		cout<<" "<<*it<<", ";
	cout<<endl;
}
void OutPutM(multiset<int>& s)
{
	multiset<int>::iterator it;
	for(it=s.begin();it!=s.end();it++)
		cout<<" "<<*it<<", ";
	cout<<endl;
}
int main()
{
	set<int> s1;
	s1.insert(10);s1.insert(15);s1.insert(25);s1.insert(20);s1.insert(30);
	OutPut(s1);
	
	// set<int> s2(less<int>());
	// s2.insert(10);s2.insert(15);s2.insert(25);s2.insert(20);s2.insert(30);
	// OutPut(s2);
	
	set<int>::allocator_type s1_Alloc;
	s1_Alloc=s1.get_allocator();

	set<int>s3(less<int>(),s1_Alloc);
	s3.insert(1);s3.insert(5);s3.insert(2);s3.insert(2);
	OutPut(s3);

	set<int>s4(s1);
	OutPut(s4);

	multiset<int> sml;
	sml.insert(10);sml.insert(15);sml.insert(25);sml.insert(20);sml.insert(30);sml.insert(20);
	OutPutM(sml);

	return 0;
}
输出:
 10,  15,  20,  25,  30, 
 1,  2,  5, 
 10,  15,  20,  25,  30, 
 10,  15,  20,  20,  25,  30,

set(multiset)

提供了查找函数find(),还提供了
low_bound()upper_bound()equal_range()

Visual C++6.0中提供另外两个函数
key_comp()		用于键值比较
value_comp()	用于实值比较

key_compare key_comp() const;
// key_compare决定了集合中元素的排列顺序
value_compare value_comp() const;

关联式容器-----map/multimap类模板

map类型通常理解为关联数组(associative array)。只是multimap允许重复元素,而map不允许。

容器类型map和multimap示意图
在这里插入图片描述
在STL中,两种类型的模板如下:

template<class Key,class T,class Compare=less<Key>,class Allocator=allocator<pair<const Key,T >>>class map;

template<class Key,class T,class Compare=less<Key>,class Allocator=allocator<pair<const Key,T>>> class multimap;
//数据对(pair)

map和multimap成员函数

bool empty() const;
begin() end() rbegin() rend()

map和multimap的高级编程

insert()
erase()
clear()
void swap(map& str);
size_type count(const Key& key) const;
iterator find(const Key& key);
const_iterator find(const Key& key)const;

元素大小比较

(1)键值比较
	key_compare key_comp() const;

(2)实值比较
	value_compare value_comp() const;

(3)获取内存分配器
	Allocator get_allocator() const;

特殊容器用法

位段类模板
堆栈类模板
队列类模板
优先队列模板

bitset类模板
	  创造一个内含位或布尔值且大小固定的数组(array)bitset();		//位段的构造函数
	bitset(unsigned long val);	//位段的构造函数
	explicit bitset(const string& str,size_t pos=0,size_t n=-1);
	//位段的构造函数
bitset的成员函数
size()
count()
any()
none()
test(size_t idx)
set()
set(size_t idx,in value)
reset()
reset(size_t idx)
flip()						//反转所有位的值
flip(size_t idx)			//反转“idx”位置上的位
to_ulong()
==
!=
^=
|=
&=
<<=
>>=
[size_t idx]
=
~
~()
<<()
>>()
&()
|()
^()
to_string()

stack类模板

namespace std{
	template<class T, class Container=deque<T>>
	class stack;
}
std::stack<int,std::vector<int>> sv;

队列queue类模板

namespace std{
	template<class T, class Container=deque<T>>
	class queue;
}
std::queue<std::string> buffer;
std::queue<std::string,std::list<std::string>>buffer;

Priority Queues类模板

#include<queue>
namespace std{
	template<class T,class Container=vector<T>,class Compare=less<typename Container::value_type>>
	class priority_queue;
}
std::priority_queue<float> buffer;

在容器priority_queue中需要使用STL中的堆(heap)算法

类模板的核心成员函数

#include<iostream>
#include<queue>
#include<vector>
#include<list>
#include<queue>
using namespace std;
void print(double& Ele)
{
	cout<<Ele<<", ";
}
template<class T>
void Out(priority_queue<T,deque<T>,less<T>>& p)
{
	while(!p.empty())
	{
		cout<<p.top()<<", ";
		p.pop();				//弹出队列
	}
}
template<class T>
void OutG(priority_queue<T,deque<T>, greater<T>>& pg)
{
	while(!pg.empty())
	{
		cout<<pg.top()<<", ";
		pg.pop();
	}
	cout<<endl;
}
int main()
{
	priority_queue<double,deque<double>,less<double>>p1,p2;
	p1.push(11.5);
	p1.push(22.5);
	p1.push(32.5);
	p1.push(21.1);
	p1.push(15.6);
	p1.push(8.9);
	p1.push(55.0);
	p2 = p1;
	Out(p1);
	p1 = p2;
	priority_queue<double,deque<double>,greater<double>> p3;
	while(p2.size())
	{
		p3.push(p2.top());
		p2.pop();
	}
	OutG(p3);
	return 0;
}
输出:
55, 32.5, 22.5, 21.1, 15.6, 11.5, 8.9,
8.9, 11.5, 15.6, 21.1, 22.5, 32.5, 55,
如何实现优先队列priority_queue,其相对队列queue的不同之处在于:优先队列实现内部自动排序,
可根据实际情况自定义排序准则,也可以自己编写函数,或仿函数用于内部优先级的确定。
发布了30 篇原创文章 · 获赞 5 · 访问量 2218

猜你喜欢

转载自blog.csdn.net/weixin_44408476/article/details/104880553