C++容器

一、顺序容器

vector、deque、list、forward_list、array、string

vector:连续内存空间存储,快速随机访问;尾部插入,中间插入/删除耗费时间

string:连续内存空间存储,快速随机访问;尾部插入,中间插入/删除耗费时间
deque:随机访问;两端插入/删除
list:不连续,不支持随机访问,任意插入/删除
forward_list:不支持size()
array:大小不变 array<int,42> a;必须指定容器大小42

容器操作

iterator、const_iterator、size_type、differeence_type、value_type、reference(同value_type&)、const_reference
C c; C c1(c2); C c(c1.begin(),c1.end()); C c{a,b,c...};
c1=c2; c1={a,b,c..} ;a.swap(b);  swap(a,b);
c.insert();  c.emplace();  c.erase();  c.clear(); 
reverse_iterator  c.rbegin()      c.crbegin()        const_iterator c.cbegin()
初始化: C seq(n)  C seq(n,t) 如果元素类型为内置类型,且具有默认构造函数,可用seq(n)来初始化,若元素类型没有默认构造函数,则除了通过大小参数外,还得提供元素初始化器或是显式的元素初始值seq(n,t)。
赋值:seq.assign(c1.begin(),c1.end());  seq.assign(n,t);    seq.assign(il);
对string使用swap()会导致迭代器、引用和指针失效

添加元素:push_back enplace_back()除forward_list和array   push_front()  emplace()除vector和string

c.insert(p,t); c.insert(p,c1.begin(),c1.end());  c.insert(p,n,t);  c.insert(p,il);   皆为在p迭代器指向的元素前插入,并返回新添加的第一个元素的迭代器,否则返回p
向vector和string中添加元素会引起存储空间的重新分配
push_back()和insert()是拷贝对象并插入 emplace(args)是传入构造函数所需的参数直接构造一个对象并插入emplace(args)  emplace(p,args);
访问元素:c.front() c.back()返回引用
下标运算符【】和at()成员函数  如果下标越界,at()会抛出out_of_range异常  c[i]  c.at(i)
删除元素:c.pop_back()  c.pop_front()  c.erase(p); c.erase(c.begin(),c,begin()+1);  erase()返回指向删除元素后的第一个元素的迭代器 c.clear() 
forward-list操作
插入或删除元素:lst.before_begin()  lst.cbefore_begin()  lst.insert_after(p,t);lst.insert_after(p,n,t) lst.insert_after(p,c.begin(),c.end())返回插入的最后一个元素的迭代器
lst.erase_after(p);  lst.erase_after(lst.begin(),lst.end());  返回被删元素之后的元素的迭代器
string操作
string s(cp,n);cp指向的数组前n个字符的拷贝 string s(s2,pos2);string s2从下标pos2开始的拷贝 string s(s2,pos2,len2);当我们从一个const char*创建string时,拷贝到空字符停止
s.sbustr(pos,n);  返回一个string,包含从pos开始的n个字符
s.insert(s.size(),5,'!');  s.erase(s.size()-5,5);  s.append();  s.replace() replace(pos,len,args)  replace(b,e,args)
s.find()  s.rfind()  s.find_first_of()  s.find_last_of()  s.find_first_no_of()  s.find_last_no_of() 返回第一个匹配的下标

string与数值之间的转换:to_string(val)  stoi()  stol()  stoul()  stoll()   stoull()  stof()  stod()  stold()  

模式匹配
赫夫曼编码
strlen() strcat() strcpy()
转义字符

函数/方法/实现

vector

成员函数:push_back() size() erase() insert() emplace() unique() swap() merge() remove() reverse()  

非成员函数:for_each() sort() copy() random_shufflr() transform() find()

string

成员函数:size() length() find() append() repalce()

非成员函数:#include <numeric> 

二、关联容器

无序容器使用哈希函数来组织元素

三、STL函数(泛型算法)

algorithm和numeric数值泛型算法
int a[]={1,2,3,4,5};
int * result=find(begin(ia),end(ia),ia);
算法永远不会改变底层容器的大小
算法分类:只读、写、重排
只读算法
find、count、accumulate(numeric(头文件中)
int sum=accumulate(vec.sbegin(),vec.cend(),0);//和的初值设为0
string sum=accumulate(vec.rbegin(),vec.cend(),string(""));//最后的初值不能设为“”;因为“”是const char *,不能再往上加值
equal(vec1.cbegin(),vec1.cend(),vec2.cbegin());//vec2至少与vec1一样长,且元素可比较
写操作算法
向输入范围写入元素,最多写入与给定序列一样多的元素
fill(vec.begin(),vec.end(),0);//将每个元素重置为0
fill_n(vec.begin(),vec.size(),0);//将所有元素重置为0
fill_n(dest,n,val);//假定写入指定个元素是安全的
插入迭代器是一种向容器中添加元素的迭代器,保证有足够的元素空间来容纳输出数据
fill_n(back_inserter(vec),10,0);向vec的末尾添加10个元素,通过back_inserter,赋值运算符会调用push_back
拷贝算法
int a1[]={0,1,2,3,4,5,6};
int a2[sizeof(a1)/sizeof(*a1)];
auto ret=copy(begin(a1),end(a1),begin(a2));
ret指向拷贝到a2的尾元素之后的位置,copy返回目的位置迭代器的值
copy()
replace(vec.begin(),vec.end(),0,42);
replace(vec.begin(),vec.end(),back_inserter(vec2),0,42);//vec2保留vec的原值,vec中的0变为42
重排元素算法
sort()、unique()、erase()
消除重复单词
vector<string> words;
sort(words.begin(),words.end());
auto end_unique=unique(words.begin(),words.end());//unique后words的大小并未改变
words.erase(end_unique,words.end());
sort()
为什么只有字符串可以排序
reverse()
只有字符串可以逆序??

定制操作
1向算法传递函数,比如sort(),定制函数排序的方法  stable_sort(words.begin(),words.end(),isShorter);//保持原有的排序方法
2lamba
find_if() 返回第一个使谓词返回非0值的元素,不存在返回尾后元素

四、各容器的底层原理

STL共有六大组件
1、容器 2、算法 3、迭代器 4、仿函数 6、适配器

STL容器的实现原理

STL来管理数据十分方便,省去了我们自己构建数据结构的时间.其实,STL的实现也是基于我们常见的数据结构.


序列式容器:
vector-数组,元素不够时再重新分配内存,拷贝原来数组的元素到新分配的数组中。
list-双链表。
deque-分配中央控制器map(并非map容器),map记录着一系列的固定长度的数组的地址.记住这个map仅仅保存的是数组的地址,真正的数据在数组中存放着.deque先从map中央的位置(因为双向队列,前后都可以插入元素)找到一个数组地址,向该数组中放入数据,数组不够时继续在map中找空闲的数组来存数据。当map也不够时重新分配内存当作新的map,把原来map中的内容copy的新map中。所以使用deque的复杂度要大于vector,尽量使用vector。
stack-基于deque。
queue-基于deque。
heap-完全二叉树,使用最大堆排序,以数组(vector)的形式存放。
priority_queue-基于heap。
slist-单向链表。

 

关联式容器:
set,map,multiset,multimap-基于红黑树(RB-tree),一种加上了额外平衡条件的二叉搜索树。
hash table-散列表。将待存数据的key经过映射函数变成一个数组(一般是vector)的索引,例如:数据的key%数组的大小=数组的索引(一般文本通过算法也可以转换为数字),然后将数据当作此索引的数组元素。有些数据的key经过算法的转换可能是同一个数组的索引值(碰撞问题,可以用线性探测,二次探测来解决),STL是用开链的方法来解决的,每一个数组的元素维护一个list,他把相同索引值的数据存入一个list,这样当list比较短时执行删除,插入,搜索等算法比较快。
hash_map,hash_set,hash_multiset,hash_multimap-基于hash table。


1.堆、优先级队列

//堆插入元素
void MinHeapFixup(int a[],int i)
{
	int j=(i-1)/2;
	int temp=a[i];
	while(j>=0 &&i!=0)
	{
		if(a[j]<=a[i])
			break;
		a[i]=a[j];
		i=j;
		j=(j-1)/2;
	}
	a[i]=temp;
}
//堆删除元素
void MinHeapFixdown(int a[],int i,int n)
{
	int j=2*i+1;
	int temp=a[i];
	while (j<=n-1)
	{
		if(a[j]>=a[i])
			break;
		if(a[j+1]<a[i])
			j++;
		a[i]=a[j];
		i=j;
		j=2*j+1;
	}
	a[i]=temp;
}
//初始化堆,从(n-1-1)/2开始执行堆元素下沉操作
void init(int a[])
{
	for (int i=strlen(a)/2-1;i>=0;i--)
	{
		MinHeapFixdown(a,i,n);
	}
}
//堆排序
//由最大堆、最小堆的特性,我们可以得到数根节点,即a[0]永远是最小或最大的,我们可以将a[0]和a[n-1]交换,再对a[0]到a[n-2]的堆进行堆排序,直到a[0]和a[1]交换
void MinHeapsortTodescendarray(int a[],int n)
{
	for(int i=n-1;i>=1;i--)
	{
		swap(a[i],a[0]);
		MinHeapFixdown(a,0,i);
	}
}

2.map

红黑树

3.hash(哈希表)

解决哈希冲突

开放定址法
开链法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值