C++容器

来源:互联网 发布:python老男孩10期网盘 编辑:程序博客网 时间:2024/05/29 02:40

一、顺序容器

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(哈希表)

解决哈希冲突

开放定址法
开链法

原创粉丝点击