热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C++Primer第二部分容器和算法

1,标准库定义了3种类型的顺序容器:vector、list和deque。它们的差别主要在于访问元素的方式,以及添加或删除元素相关操作运算代价。标准库还提供了三种容器适配器:stac

第9章 顺序容器

1,标准库定义了3种类型的顺序容器:vector、list和deque。它们的差别主要在于访问元素的方式,以及添加或删除元素相关操作运算代价。标准库还提供了三种容器适配器:stack、queue和priority_queue。

2,将一个容器复制给另一个容器时,类型必须匹配,包括容器类型和元素类型。

vector<int> ivec;
vector<double> dvec(ivec); //error
list<int> ilist(ivec); // error

3,可以用一对指针或一对迭代器,把它们之间的值复制给容器,可以允许类型不一致。

vector<string> svec;
list<string> slist(svec.begin(),svec.end());
vector<string>::iterator mid = svec.begin() + svec.size() / 2;
deque<string> front(svec.begin(),mid); // 不包括 *mid
// 用指针初始化
char* word[] = {"monday","tuesday","wesday"};
size_t words_size = sizeof(word) / sizeof(char*);
list<string> words2(word, word + words_size);

4,注意除了引用外,所有内置或复合类型都可以做容器的元素类型。引用不支持一般意义的赋值操作。除输入输出标准库类型(以及auto_ptr)外,所有其他标准库类型都是有效的容器元素类型。

5,list容器的迭代器不支持算术运算,也不支持关系运算。因为list里的元素,没有序号或位置这个概念。

6,所有相同类型的容器都支持关系操作符来实现两个容器的比较:

1)如果两个容器具有相同的长度而且所有元素都相等,那么两个两个容器相等;否则,就不相等。

2)如果两个容器的长度不相同,但较短的容器中所有元素都等于较长容器中对应的元素,则称较短的容器小于另一容器。

3)如果两个容器都不是对方的初始子序列,则它们的比较结果取决于所比较的第一个不相等的元素。

如果容器内的元素不支持比较大小,则容器就不能比较大小。

7,获得容器元素的引用,有两种方法:1)front与back成员函数;2)迭代器解引用。

list<int> ilist;
if (!ilist.empty())
{
list<
int>::reference val = ilist.front();
list<
int>::reference val1 = *ilist.begin();
list<
int>::reference last = ilist.back();
list<
int>::reference last1 = *--ilist.end();
}
return 0;

注意取引用时,一定要保证ilist非空。

8,在使用erase删除容器内两个迭代器之间的元素时,erase(elem1,elem2),这里删除的元素不包括elem2。

9,容器的赋值,顺序容器有几下几种赋值操作:

1)c1=c2:删除c1的所有元素,然后将c2的元素复制给c1,c1和c2的类型(容器类型与元素类型)必须相同。

2)c1.swap(c2):顾名思义,交换c1与c2的值,实际上这个操作,只是交换了彼此的地址。交换后c1批向了原来c2的指针内容。

3)c.assign(b,e):重新设置c的元素,将迭代器b与e之间的所有元素复制到c中,当然b与e不能是c的的迭代器。

4)c.assign(n,t):将容器c重新设置为存储n个值为t的元素。

注意assign操作允许发生类型转换。可以将char*元素assign给存储string的容器。swap是速度最快的,没有删除元素的成本。

10,一般意义下vector的元素是按顺序存储的,这就造成了,如果插入元素,则库将进行重新内存分配,并涉及到的旧vector的销毁。而实际中vector容器预留了这些额外的存储区用于存放新添加的元素。因此在实际上,比起list与deqeue容器,vector的增长效率通常会更高。

11,vector容器实际空间可能会比元素所占的空间更大,capacity成员函数用于返回容器实际的容量大小,一般比size要大。如果一直往vector内插入元素,则直到size==capacity之间,vector都不用重新进行内存分配。但如果再往里插入元素时,将又会重新分配,capacity又会比size大。


第10章 关联容器

1,pair类型:

pair<string, string> name("ronny", "young"); // 定义并初始化
name = make_pair("ronny", "young");
string fullName = name.first + name.second;

2,关联容器

1)关联容器map实际上是装有n个pair类型的集合。map定义了三个类型别名,key_type、mapped_type、value_type分别表示键的类型、键所关联的值的类型和map里pair类型。

2)当使用下标访问map的值时,如果下标不存在,则导致在map中新添一个新的元素,它的键即为该下标值。

3)map的迭代器指向的是pair类型,所以当对迭代器解引用时,得到的是一个pair类型。这与下标得到的类型不同。

4)统计单词出现次数的例子:

map<string, int> word_cnt;
string word;
while (cin >> word)
{
++word_cnt[word];
}

5)利用insert返回的类型来重写上面的程序,insert返回了一个pair类型,它的first成员为一个迭代器,而second成员为一个bool变量,表明该元素是否被插入。

map<string, int> word_cnt;
string word;
while (cin >> word)
{
pairint>::iterator, bool>
ret = word_cnt.insert(make_pair(word, 1));
if (!ret.second)
++(ret.first)->second;
}

6)set容器是一个集合,它存储了键,且惟一不能修改。set的操作与map基本一致,只是没有mapped_type,而且vale_type就是key_type。在使用insert时,返回的也是pair类型的值。set不提供下标操作,只能使用find来查找元素是否存在,并且返回一个迭代器,如果不存在,则返回指向最后一个元素下一个的迭代器(end)。如果简单的判断某个键是否存在,则可以直接使用cout函数,它返回1或0。

7)multimap与multiset容器允许一个键值对应多个实例,实际上一个键值的多个实例是按顺序存储在一起的。它们的find的操作返回键值第一个实例的迭代器,cout返回键值有多少个实例。另外lower_bound与upper_bound分别用于返回所查找键值的第一个实例我迭代器与最后一个实例迭代器的下一位。

multimap<string, string> books;
typedef multimap<string, string>::iterator authors_it;
string search_item = "matin";
authors_it beg = books.lower_bound(search_item);
authors_it end = books.upper_bound(search_item);
while (beg != end)
{
cout <<(beg++)->second <}

更加方便的是equal_range函数,它返回了一个迭代器的pair对象,其实正好放着lower_bound和upper_bound


第11章 泛型算法

1,泛型算法大部分在algorithm头文件中,而还有一些算术算法,它们在头文件numeric中。

2,int
sum=accumulate(vec.begin,vec.end(),42)。accumulate返回一对迭代器之间元素和。注意第三个参数是很重要的,一方面它指定了sum的类型,使该类型可以进行加法运算;另一方面限制了容器的类型必须与第三个参数类型保持一致或可以转换。得到的sum为第三个参数的类型。

3,find_first_of用于查找第二段范围里的对象在第一段范围里出现的第一个位置。

while (it=find_first_of(it,roster1.end,roster2.begin(),roster2.end())
!=roster1.end())

上面代码用来循环查找,roster2中的元素在roster1中出现的位置。find_first_of的两个范围内的对象,并不要求容器类型一致,只需要容器内的元素可以进行比较即可。

4,写入算法:

fill(vec.begin(),vec.end(),0):将一对迭代器范围内的值设置为第三个参数的值。

fill_n(vec.begin(),10,0):如果vec内元素小于10个时,这段代码将会出现问题。用插入迭代器可以解决fill_n(back_inserter(vec),10,0);

copy(ilst.begin(),ilist.end(),back_inserter(ivec))会将ilist内的元素复制到ivec中。

replace(ilst.begin(),ilst.end(),0,42):将ilst中所有值为0的元素全部值设为42.

replace_copy(ilst.begin(),ilst.end(),back_inserter(ivec),0,42):ilst没有发生变化,ivec将储存ilst的一份副本,其实值为0的都变为了42.

5,去重复、排序算法

char * arStr[] = { "the", "quick", "red", "fox", "jumps", "over", "the", "slow", "red", "turtle" };
vector<string> sVec(arStr, arStr + 10);
sort(sVec.begin(), sVec.end());
vector<string>::iterator end_uniuqe = unique(sVec.begin(), sVec.end());
sVec.erase(end_uniuqe,sVec.end());
stable_sort(sVec.begin(), sVec.end(), isShorter);
vector<string>::size_type len = count_if(sVec.begin(), sVec.end(), LongerThan6);
bool isShorter(const string& s1, const string& s2)
{
return s1.size() <s2.size();
}
bool LongerThan6(const string& s)
{
return s.size() >= 6;
}

上面程序中,unique是一个去重复的函数,返回已经没有重复的序列最后一位下一个元素位置。

stable_sort可以保留重复元素开始的相对位置

7,插入迭代器:

front_inserter:调用push_front插入

back_inserter:调用push_back插入

inserter:调用insert插入

list<int>::iterator it = find(ilst.begin(),ilst.end(),42);
// 先将ivec的一份拷贝中值为100的元素换为0,然后将其插入到ilst的迭代器it的前面
replace_copy(ivec.begin(),ivec.end(),inserter(ilst,it),100,0);

上面三种操作一般都与copy或replace_copy函数一起用,作为其一个实参。

list<int> lst1, lst2, lst3;
for (list<int>::size_type i = 0; i != 5; i++)
{
lst1.push_back(i);
}
copy(lst1.begin(), lst1.end(), inserter(lst2, lst2.begin()));
copy(lst1.begin(), lst1.end(), front_inserter(lst3));

C++ Primer 第二部分 容器和算法,布布扣,bubuko.com


推荐阅读
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 本文介绍了一种解析GRE报文长度的方法,通过分析GRE报文头中的标志位来计算报文长度。具体实现步骤包括获取GRE报文头指针、提取标志位、计算报文长度等。该方法可以帮助用户准确地获取GRE报文的长度信息。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • PDF内容编辑的两种小方法,你知道怎么操作吗?
    本文介绍了两种PDF内容编辑的方法:迅捷PDF编辑器和Adobe Acrobat DC。使用迅捷PDF编辑器,用户可以通过选择需要更改的文字内容并设置字体形式、大小和颜色来编辑PDF文件。而使用Adobe Acrobat DC,则可以通过在软件中点击编辑来编辑PDF文件。PDF文件的编辑可以帮助办公人员进行文件内容的修改和定制。 ... [详细]
author-avatar
小刺猬HF
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有