C++Prime 第九章前30题
练习9.1
(a)选择list,因为可能在容器中间插入元素.也可以选择vector,全部读取完毕后,直接sort.
(b)选择deque,因为插入删除操作只在头部进行.
(c)选择vector.
练习9.2
list<deque<int> > data;
练习9.3
迭代器范围:两个迭代器指向同一容器,或者是容器最后一个元素之后的位置,begin递增若干次后等于end.
练习9.4
#include <iostream>
#include <list>
#include <string>
#include <vector>
#include <forward_list>
#include <deque>
using namespace std;
typedef vector<int>::iterator Iter;
bool find_value(Iter beg, Iter end, int n)
{
auto p = beg;
while (p != end)
if (*p++ == n)
return true;
return false;
}
int main()
{
vector<int> data{ 1,2,3,4,5,6,7 };
if (find_value(data.begin(), data.end(), 3))
cout << "find it\n";
else
cout << "Don't find!\n";
return 0;
}
练习9.5
#include <iostream>
#include <list>
#include <string>
#include <vector>
#include <forward_list>
#include <deque>
using namespace std;
typedef vector<int>::iterator Iter;
Iter find_value(Iter beg, Iter end, int n)
{
auto p = beg;
while (p != end)
{
if (*p == n )
return p;
p++;
}
return p;
}
int main()
{
vector<int> data{ 1,2,3,4,5,6,7 };
if (data.end() != find_value(data.begin(), data.end(), 3))
cout << "find it\n";
else
cout << "Don't find!\n";
return 0;
}
练习9.6
只有vector string array deque的迭代器可以执行关系运算.改正: while(iter1 != iter2)
练习9.7
vector<int>::size_type;
//or
vector<int>::iterator;//const_iterator
练习9.8
string::const_iterator;
list<string>::iterator;
练习9.9
begin()的返回值取决于容器的类型.容器是const 的,则begin()返回的是const_iterator,否则返回iterator
cbegin()一定返回常量迭代器const_iterator
练习9.10
it1是vector<int>::iterator
it2,it3,it3是vector<int>::const_iterator
练习9.11
vector<int> a1;//默认初始化,空对象
vector<int> a2(a1);//a2 == a1
vector<int> a22 = a1; //a22 == a1
vector<int> a3{ 1,2,3 }; //a2 == {1,2,3}
vector<int> a32 = { 1,2,3 };
vector<int> a4(a3.begin(), a3.end()); //a4 == a3
vector<int> a42(a3.begin(), a3.begin() + 2);
vector<int> a5(10);//10个0
vector<int> a6(10, 2);//10个2
练习9.12
接受一个容器创建其copy要求 :两个容器类型必须相同,元素类型必须相同.
接受两个迭代器创建copy的构造函数:两个容器类型可以不同,元素类型也可以不同(要能转换成接受容器的元素类型)
练习9.13
list<int> a{1,2,3,4};
vector<double> b(a.begin(),a.end());
for (const auto& x : b)
cout << x << " ";
cout << endl;
练习9.14
list<char*> lc;
vector<string> data;
data.assign(lc.begin(), lc.end());
练习9.15
#include <iostream>
#include <list>
#include <string>
#include <vector>
#include <forward_list>
#include <deque>
using namespace std;
int main()
{
list<int> k1{ 1,2,3,4 };
list<int>k2{ 1,3 };
if (k1 == k2)
cout << "相等" << endl;
else
cout << "不等" << endl;
return 0;
}
练习9.16
方法一:逐个元素比较,还要考虑两个容器长度不等的情况.
方法二:先用list初始化一个vector<int>,然后比较两个vector<int>即可,代码简洁,效率不如方法一.
练习9.17
三点限制.
其一:c1和c2必须是相同类型的容器.
其二:c1和c2的元素类型必须相同.
其三:c1和c2的元素必须支持"="和"<"运算符.比如没有重载"="或"<"的自定义类,不能按照题目判断.
练习9.18
#include <iostream>
#include <list>
#include <string>
#include <vector>
#include <forward_list>
#include <deque>
#include <algorithm>
using namespace std;
template<class T>
void print(const T& t)
{
for (const auto x : t)
cout << x << " ";
cout << endl<<endl;
}
int main()
{
deque<string> data;
string tmp;
while (cin >> tmp ) //从头插入
data.push_front(tmp);
print(data);
cin.clear();
deque<string> data2;
while (cin >> tmp)//从尾部插入
data2.push_back(tmp);
print(data2);
cin.clear();
deque<string> data3;
auto ptr = data3.begin();
while (cin >> tmp)//从头插入,使用insert,并且使用insert的返回值
ptr = data3.insert(ptr, tmp);
print(data3);
cin.clear();
deque<string> data4;
auto ptr2 = data4.end();
while (cin >> tmp )//从尾部倒着往前插入
ptr2 = data4.insert(ptr2, tmp);
print(data4);
cin.clear();
deque<string> data5;
while (cin >> tmp )
data5.emplace_back(tmp);//使用C++11新标准的emplace,注意emplace的参数要符合某个构造函数
print(data5);
cin.clear();
deque<string> data6;
auto ptr3 = data6.begin();
while (cin >> tmp )//可以看出emplace和insert返回值的规则应该是相同的,书中没有提及.
ptr3 = data6.emplace(ptr3, tmp);
return 0;
}
练习9.19
list和deque可以使用inset,push_back,push_front,emplce所有函数,本体直接把deque换成list无问题.
vector和string,不能使用头插类的两个push_front和emplace_front,insert没问题,用insert来实现头部插入
forward_list不支持尾插的两个,同时insert和emplace也是自己的专有版本.
array不支持上述所有.
虽然支持,却不一定最优,合理选择容器和方法.
练习9.20
#include <iostream>
#include <deque>
#include <string>
#include <vector>
#include <forward_list>
#include <list>
#include <algorithm>
using namespace std;
template<class T>
void print(const T& t)
{
for (const auto x : t)
cout << x << " ";
cout << endl<<endl;
}
int main()
{
list<int> data{1,2,3,4,5,6};
deque<int> d1, d2;
for (auto p = data.begin(); p != data.end(); ++p)
{
int num = *p % 2;
if (num)
d1.push_back(*p);
else
d2.push_back(*p);
}
print(d1);
print(d2);
return 0;
}
练习9.21
每一次插入都要移动当前所有元素,极其无效率.
练习9.22
对vector,string,deque(就是除了链表的那些) 一旦插入数据,迭代器,指针,引用全部失效.
修改:
不会!
练习9.23
全为首元素的值,
练习9.24
int main()
{
vector<int> data;
try
{
cout << data.at(0) << endl;
}
catch (out_of_range) {
cout << "下标范围不对" << endl;
}
data.push_back(123);
if (!data.empty())
{
cout << data[0] << endl;
cout << data.front() << endl;
cout << *data.begin() << endl;
}
return 0;
}
练习9.25
范围的两个迭代器相等,不删.
第二个迭代器时尾后,第一个不是尾后,则删除第一个迭代器所指及其后的所有元素
都是超尾迭代器.不删,
练习9.26
#include <iostream>
#include <deque>
#include <string>
#include <vector>
#include <forward_list>
#include <list>
#include <algorithm>
#include <exception>
using namespace std;
template<class T>
void print(const T& t)
{
for (const auto x : t)
cout << x << " ";
cout << endl<<endl;
}
int main()
{
int ia[] = { 0,1,2,3,5,8,13,21,55,89 };
vector<int> vi(begin(ia),end(ia));
list<int> li(vi.begin(),vi.end());
print(vi);
print(li);
cout << "删除后:\n";
auto p = vi.begin();
while(p != vi.end())
{
if (!(*p % 2))
p = vi.erase(p);
else
++p;
}
auto q = li.begin();
while (q != li.end())
{
if (*q % 2)
q = li.erase(q);
else
++q;
}
print(vi);
print(li);
return 0;
}
练习9.27
forward_list<int> a{1,2,3,4,5,6,7,8};
auto pre = a.before_begin();
auto p = a.begin();
while (p != a.end())
{
if (*p % 2)
p = a.erase_after(pre);
else
{
pre = p;
++p;
}
}
练习9.28
#include <iostream>
#include <deque>
#include <string>
#include <vector>
#include <forward_list>
#include <list>
#include <algorithm>
#include <exception>
using namespace std;
template<class T>
void print(const T& t)
{
for (const auto x : t)
cout << x << " ";
cout << endl<<endl;
}
void insertToList(forward_list<string> &word,const string& s1, const string& s2)
{
auto pre = word.before_begin(), p = word.begin();
bool find_s1 = false;
while (p != word.end())
{
if (*p == s1)
{
find_s1 = true;
p = word.insert_after(p, s2);
break;
}
else
{
pre = p;
++p;
}
}
if (!find_s1)
p = word.insert_after(pre, s2);
}
int main()
{
forward_list<string> word;
auto p = word.before_begin();
string wd;
while (cin >> wd)
p = word.insert_after(p,wd);
cout << "插入前:" << endl;
print(word);
cout << "输入两个字符:第一个查找,第二个插入." << endl;
string s1, s2;
cin.clear();
cin >> s1 >> s2;
insertToList(word, s1, s2);
cout << "插入后:" << endl;
print(word);
return 0;
}
练习9.29
扩充75的容量,新元素执行值初始化.
删除后部90个元素.
练习9.30
resize的要求如果是类类型,要么该类具有默认构造函数,要么显示初始化
既然是单参数版本的resize,这个唯一的参数用来指明容量的大小,则无法进行显示初始化,故类必须包含默认构造方法