习题9.1
(a)使用list要好一些,由于它需要插入容器,list的底层是双向链表。
在任何位置插入数据都很方便,且支持双向访问。
(b)使用deque,deque是双端队列,支持随机访问,在首尾添加或删除原元素很快。
(c)使用lvector,不需要插入和删除,只需要排序的话,在随机访问
方面毫无疑问的选择vector。
总结:
常用的容器三种
vector:底层是可变大小数组,特点是随机访问速度快。
list:底层是双向链表,特点是插入和删除元素速度快。
deque:底层是双端队列,特点是随机访问速度快,且在首尾添加删除元素快速。
原则
(1)容器首选vector,数组连续,空间开销小
(2)涉及随机插入删除,选择list,链表方便,但是空间上不连续,导致额外空间开销大,酌情考虑。
(3)deque,中和前两个特点,如果需要随机访问,但元素的删除和插入只在两端,使用deque。
习题9.2
list
习题9.3
他们指向同一个容器中的元素,或者是容器最后一个元素之后的位置
begin可以通过递增来到达end。
习题9.4
#include
#include
using namespace std;
bool vecFindValue(vector
{
for (auto it = beg; it != end; it++)
{
if (*it == i)
{
return true;
}
}
return false;
}
int main(int argc, char** argv)
{
vector
bool consult = vecFindValue(vec.begin(), vec.end(), 3);
cout << consult << endl;
system("pause");
return 0;
}
习题9.5
#include
#include
using namespace std;
vector
{
for (auto it = beg; it != end; it++)
{
if (*it == i)
{
return it;
}
}
return end;
}
int main(int argc, char** argv)
{
vector
auto consult = vecFindValue(vec.begin(), vec.end(), 8);
if(consult != vec.end())
cout << *consult << endl;
else
cout << "Can't find the value" << endl;
system("pause");
return 0;
}
习题9.6
iterator没有比较这种操作,修改为while(iter1 != iter2)
习题9.7
vector
习题9.8
写:list
读:list
习题9.9
cbegin返回const_iterator,begin返回iterator
习题9.10
it1是vector
习题9.11
vector
vector
vector
vector
vector
vector
习题9.12
接收另一个容器拷贝,是将其全部元素复制到本容器中来。
二使用迭代器,是将begin和end之间的元素复制进来。
习题9.13
#include
#include
#include
using namespace std;
int main(int argc, char** argv)
{
list
vector
//! from list
vector
for (auto i : ilst) cout << i;
cout << endl;
for (auto t : dvc) cout << t;
cout << endl;
//! from vector
vector
for (auto i : ivc) cout << i;
cout << endl;
for (auto t : dvc2) cout << t;
system("pause");
return 0;
}
习题9.14
#include
#include
#include
#include
using namespace std;
int main(int argc, char** argv)
{
list
//! from list
vector
for (auto i : vec) cout << i << endl;
system("pause");
return 0;
}
习题9.15
#include
#include
#include
#include
using namespace std;
int main(int argc, char** argv)
{
vector
vector
if (vec_1 == vec_2)
{
cout << "vec_1 is same as vec_2" << endl;
}
else
{
cout << "not" << endl;
}
system("pause");
return 0;
}
习题9.16
#include
#include
#include
#include
using namespace std;
int main(int argc, char** argv)
{
vector
list
vector
if (vec == vec_2)
{
cout << "true" << endl;
}
else
{
cout << "false" << endl;
}
system("pause");
return 0;
}
习题9.17
两个容器得相同类型,且支持该比较操作符。
习题9.18
#include
#include
#include
#include
#include
using namespace std;
int main(int argc, char** argv)
{
string buf;
deque
while (cin >> buf)
{
deq.push_back(buf);
}
for (auto i : deq)
{
cout << i << endl;
}
system("pause");
return 0;
}
习题9.19
#include
#include
#include
#include
#include
using namespace std;
int main(int argc, char** argv)
{
string buf;
list
while (cin >> buf)
{
lis.push_back(buf);
}
for (const auto i : lis)
{
cout << i << endl;
}
system("pause");
return 0;
}
习题9.20
#include
#include
#include
#include
#include
using namespace std;
int main(int argc, char** argv)
{
string buf;
list
deque
deque
for (auto i : lis)
{
if (i % 2)
sinDeq.push_back(i);
else
douDeq.push_back(i);
}
for (auto i : sinDeq)
{
cout << i;
}
cout << endl;
for (auto i : douDeq)
{
cout << i;
}
system("pause");
return 0;
}
练习9.21
是相同的,插入一个元素到原begin的前面,然后返回新插入元素的
iterator,将它赋值给iter,它与插入后的begin相同。然后重复此操作,
可以一直在首位插入值。
练习9.22
1、循环不会终止。
2、在insert之后mid不再是最中间的位置,迭代器失效。
练习9.23
都是相同的值
练习9.24
std::cout << v.at(0);
std::cout << v[0];
std::cout << v.front();
std::cout << *(v.begin());
练习9.25
elems相等删除他们指定的元素;
不相等,删除他们范围内的元素;
如果都是end,不删除任何元素。
第二个迭代器指向元素位置一定在第一个迭代器后面。
练习9.26
解释下两点
删除元素后,其本身的end()返回的迭代器永远不失效,不必担心。
删除元素后,后面的元素后替补该位置,因此如果删除后,继续判断
该位置的元素(此元素是后面元素补上来的)。如果不符合,再后移判断。
直接后移会出现漏判的情况。
#include
#include
#include
#include
#include
using namespace std;
int main(int argc, char** argv)
{
int ia[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89 };
//! init
vector
list
//! remove odd value
for (auto it = lst.begin(); it != lst.end();)
if (*it & 0x1)
it = lst.erase(it);
else
++it;
//! remove even value
for (auto it = vec.begin(); it != vec.end();)
if (!(*it & 0x1))
it = vec.erase(it);
else
++it;
//! print
cout << "list : ";
for (auto i : lst) cout << i << " ";
cout << "\nvector : ";
for (auto i : vec) cout << i << " ";
cout << std::endl;
system("pause");
return 0;
}
练习9.27
#include
#include
#include
#include
#include
#include
using namespace std;
int main(int argc, char** argv)
{
forward_list
for (auto prev = flst.before_begin(), curr = flst.begin();
curr != flst.end();)
if (*curr & 0x1)
curr = flst.erase_after(prev);
else
prev = curr++;
for (auto i : flst) cout << i << " ";
system("pause");
return 0;
}
练习9.28
#include
#include
#include
#include
#include
#include
using namespace std;
bool sertElemAfterFind(forward_list
{
auto i_before = forList.before_begin();
for (auto i = forList.begin(); i != forList.end(); i++, i_before++)
{
if (str1 == *i)
{
forList.insert_after(i, str2);
return true;
}
}
forList.insert_after(i_before, str2);
return false;
}
int main(int argc, char** argv)
{
forward_list
sertElemAfterFind(flst, "f", "ss");
for (auto i : flst) cout << i << " ";
system("pause");
return 0;
}
练习9.29
添加75个0进vec;
从vec末尾删除90个元素。
练习9.30
如果元素是class,但是该类没有default构造函数,就有问题了。
练习9.31
list和forward_list没有 += 操作。
list将该操作替换成advance(iter, 2);即可
forward_list版本:
#include
#include
#include
#include
#include
#include
using namespace std;
bool sertElemAfterFind(forward_list
{
auto i_before = forList.before_begin();
for (auto i = forList.begin(); i != forList.end(); i++, i_before++)
{
if (str1 == *i)
{
forList.insert_after(i, str2);
return true;
}
}
forList.insert_after(i_before, str2);
return false;
}
int main(int argc, char** argv)
{
forward_list
auto iter = vi.begin();
auto iter_bef = vi.before_begin();
while (iter != vi.end()) {
if (*iter % 2) {
iter = vi.insert_after(iter, *iter);
advance(iter, 1);
advance(iter_bef, 2);
}
else
iter = vi.erase_after(iter_bef);
}
for (auto i : vi) cout << i << " ";
system("pause");
return 0;
}
练习9.32
不合法,给iter自增,会导致越界。
练习9.33
崩溃,在插入或删除操作之后,导致iter失效。
练习9.34
遇到奇数,不断插入奇数。
练习9.35
capacity是vector当前最大能够容纳多少个元素,size是vector
当前容纳的元素个数。
练习9.36
不可能
练习9.37
arry是固定大小数组,list是双向链表不需要变长,使用再分配内存即可
练习9.38
略
练习9.39
cin的输入中,当元素到达capacity值,capacity会自动变大。
而reseize是增大了size,当然size到一定地步,capacity会再次自动变大。
练习9.40
略
练习9.41
vector
string str(vec.begin(), vec.end());
练习9.42
s.reseize(100);
练习9.43
#include
#include
#include
#include
#include
#include
using namespace std;
void Replace(string& s, const string& oldVal, const string& newVal)
{
for (auto beg = s.begin(); std::distance(beg, s.end()) >=
std::distance(oldVal.begin(), oldVal.end());) {
if (string{ beg, beg + oldVal.size() } == oldVal) {
beg = s.erase(beg, beg + oldVal.size());
beg = s.insert(beg, newVal.cbegin(), newVal.cend());
std::advance(beg, newVal.size());
}
else
++beg;
}
}
int main(int argc, char** argv)
{
string str{ "To drive straight thru is a foolish, tho courageous act." };
Replace(str, "thru", "through");
Replace(str, "tho", "though");
std::cout << str << std::endl;
system("pause");
return 0;
}
练习9.44
void Replace(string& s, string const& oldVal, string const& newVal)
{
for (string::size_type i = 0; i != s.size(); ++i)
if (s.substr(i, oldVal.size()) == oldVal) {
s.replace(i, oldVal.size(), newVal);
i += newVal.size() - 1;
}
}
练习9.45
#include
#include
#include
#include
#include
#include
using namespace std;
std::string pre_suffix(const std::string name, const std::string pre,const std::string su)
{
auto ret = name;
ret.insert(ret.begin(),pre.begin(),pre.end());
ret.append(su);
return ret;
}
int main(int argc, char** argv)
{
std::string name("alan");
std::cout << pre_suffix(name, "Mr.", ",Jr.") << std::endl;
system("pause");
return 0;
}
练习9.46
#include
#include
#include
#include
#include
#include
using namespace std;
std::string pre_suffix(const std::string& name, const std::string& pre,
const std::string& su)
{
std::string ret(name);
ret.insert(0, pre);
ret.insert(ret.size(), su);
return ret;
}
int main(int argc, char** argv)
{
std::string name("alan");
std::cout << pre_suffix(name, "Mr.", ",Jr.") << std::endl;
system("pause");
return 0;
}