習題首頁
知識點1:所有的容器類都共享公共的介面,不同容器按不同方式對其進行擴展,每種容器提供了不同的性能和功能的權衡
vector:可變大小,支持快速隨機訪問,尾位置洗掉\插入速度很快,其余很慢,將元素保存在連續的記憶體空間
deque:雙端佇列,支持快速隨機訪問,頭尾部插入\洗掉資料很快
list:雙向鏈表,只支持雙向順序訪問,在其任何位置插入\洗掉資料都很快,不支持元素隨機訪問(訪問一個元素得歷遍整個容器,記憶體開銷大)
array:固定大小陣列,不能添加或洗掉元素(不是普通的內置陣列)
string:專門用于保存字符,隨機訪問快,在尾部插入\洗掉速度快,將元素保存在連續的記憶體空間
平常就使用vector,C++程式應該使用標準庫容器,而不是原始的資料結構如:內置陣列,
習題9.1
(a)list,因為可能需要在容器的中間位置插入元素
(b)deque,因為需要在頭部進行元素的洗掉,deque效率更高
(c)vector,無具體的洗掉插入操作,未知數量,vector是個不錯的選擇,
知識點2:一個容器的元素型別可以是另一個容器
c.empty():c中存盤了元素,回傳false.
c.cbegin():回傳const_iterator
c.clear():清空容器
c.swap(b):交換c與b中的元素
要訪問順序容器和關聯容器中的元素,需要通過“迭代器(iterator)”進行,
迭代器是一個變數,相當于容器和操縱容器的演算法之間的中介,迭代器可以指向容器中的某個元素,通過迭代器就可以讀寫它指向的元素,
習題9.2
list<deque<int>> li;
習題9.3
迭代器指向同一個容器或者最后一個元素之后的位置,可以反復遞增begin直到end
迭代器指向的元素范圍是左閉合區間,注意end指向的是最后一個元素之后的位置, 如:[begin,end)
習題9.4
bool findInt(vector<int>&vec, int c){
for (auto i : vec){
if (i == c){
return true;
}
}
return false;
}
習題9.5
int findInt(vector<int>&vec, int c){
for (auto i : vec){
if (i == c){
return i;
}
}
return -1;
}
習題9.6
兩個迭代器不在統一容器內不能直接比較
程式修改為:
while(iter1!=iter2)
習題9.7
vector<int>::size_type;
習題9.8
list<string>::const_iterator;
list<string>::iterator;
習題9.9
begin回傳容器的iterator型別
cbegin回傳容器的const_iterator型別
習題9.10
P298 一個const成員,回傳容器的const_iterator型別,另一個非常量成員,回傳容器的iterator型別,
知識點3:當一個容器初始化為另一個容器的拷貝時,兩個容器的容器型別和元素型別都必須相同,
不過,當傳遞迭代器引數來拷貝一個范圍時,就不要求容器型別是相同,如下:
forwar_list<string> words(articles.begin(),articles.end());
知識點4:為了使用array型別,我們必須同時指定元素型別和大小:
array<int,42> i; //型別為:保存42個int的陣列
array<string,10> j; //型別為:保存10個string的陣列
習題9.11
vector<int> vec; // 0
vector<int> vec(0); //0
vector<int> vec(10,1); //10個1
vector<int> vec{1,2,3,4,5};//1,2,3,4,5
vector<int> vec(other_vec);//same as other_vec
vector<int> vec(other_vec.begin(),other_end());//same as other_vec
習題9.12
當一個容器初始化為另一個容器的拷貝時,兩個容器的型別和元素型必須相同,使用迭代器,則不要求型別相同,
接受迭代器創建拷貝,拷貝的是兩個迭代器之間的內容,而直接接受一個容器,就是拷貝整個容器的內容了,
習題9.13
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
#include <list>
using namespace std;
int main() {
//目標初試化的容器
vector<int> vec1(5,5);
list<int> vec2(2,2);
//創建初始化容器
vector<double> vec3(vec1.begin(), vec1.end());
vector<double> vec4(vec2.begin(), vec2.end());
/驗證
for (auto i : vec3){
cout << i << " ";
}
for (auto j : vec4){
cout << j << " ";
}
system("pause");
return 0;
}

知識點5:賦值運算子和swap要求左右的運算物件有相同的型別,assign操作不適用于關聯容器和array
習題9.14
list<string> names;
vector<const char*> oldstyle;
names.assign(oldstyle.cbegin(),oldstyle.cend());
知識點6:關系運算子左右的運算物件必須是相同型別的容器,且必須保持相同型別的元素
1.如果兩個容器具有相同大小且所有元素都兩兩對應相等,則這兩個容器相等,否則不相等
2.如果兩個容器大小不同,但小的容器中的每個元素都大于大的容器,則小的容器大于大的容器
3.如果兩個容器都不是另一個容器的前綴子序列,則它們的比較結果取決于第一個不相等的元素比較結果
4.只有當其元素型別也定義了相應的比較運算子時,我們才可以使用關系運算子來比較兩個容器
習題9.15
bool isEquel(vector<int> &a, vector<int> &b) {
if (a == b) return true;
else return false;
}
習題9.16
bool isEquel(vector<int> &a, list<int> &b) {
vector<int> c(b.begin(), b.end());
if (a == c) return true;
else return false;
}
習題9.17
只有當其元素型別也定義了相應的比較運算子時,我們才可以使用關系運算子來比較兩個容器
知識點7:順序容器操作
push_back 將一個元素追加到一個容器的尾部,除了array和forwar_list之外,每個順序容器都支持push_back,放入容器中的是物件值的一個拷貝,而不是物件本身
push_front 將一個元素追加到一個容器的頭部,vector不支持這個
insert 將一個元素插入到特定位置,支持插入范圍內的元素
emplace 在容器中直接構造元素,傳遞給empalce函式的引數必須與元素型別的建構式相匹配
習題9.18
#include<iostream>
#include<string>
#include<deque>
using namespace std;
int main() {
string s;
deque<string> deq;
while (cin >> s) {
deq.push_back(s);
}
for (auto it:deq) {
cout << it << endl;
}
system("pause");
return 0;
}
習題9.19
將deque改成list
習題9.20
#include <iostream>
#include <vector>
#include <deque>
using namespace std;
int main() {
list<int> s = {0,1,2,3,4,5,6,7,8,9,10};
deque<int> odd, even;
for (auto i:s){
if (i % 2 ){
odd.push_back(i);
}
else
{
even.push_back(i);
}
}
cout << "odd中的奇數為:";
for (auto i : odd){
cout << i << " ";
}
cout << endl << "even中的偶數為:";
for (auto i : even){
cout << i << " ";
}
system("pause");
return 0;
}
習題9.21
不改變
習題9.22
#include<iostream>
#include<string>
#include<vector>
using namespace std;
void func(vector<int> &iv, int some_val) {
int extra = 0;
vector<int>::iterator iter = iv.begin();
while (iter != (iv.begin() + iv.size() / 2 + extra)) {
if (*iter == some_val) {
iter = iv.insert(iter, 2 * some_val);
++extra;
++iter;
}
++iter;
}
}
int main() {
vector<int> iv = { 1,2,3,4 };
func(iv, 2);
for (auto i : iv) {
cout << i << " ";
}
system("pause");
return 0;
}
知識點8:訪問元素
迭代器end指向的是容器尾元素之后的(不存在)的元素,
在呼叫front和back(或者解參考begin和end回傳的迭代器)之前,要保證容器為非空,否則操作的行為將是未定義的,是嚴重的程式設計錯誤,
在容器中訪問元素的成員函式(如front、back、下標和at)回傳的都是參考,如果使用auto來保存函式的回傳值,必須將變數定義為參考型別,
為了確保下標是合法的,可以使用at成員函式,如果下標越界,at會拋出一個out_of_range例外,
習題9.23
四個值都是*c.begin(),即第一個元素
習題9.24
#include<iostream>
#include<vector>
using namespace std;
int main() {
vector<int> vec;
int a = vec.at(0),
b = vec[0],
c = vec.front();
auto d = vec.begin();
cout << "a: " << a << endl;
cout << "b: " << b << endl;
cout << "c: " << c << endl;
cout << "d: " << *d << endl;
system("pause");
return 0;
}
知識點9:洗掉元素
pop_front和pop_back成員函式分別洗掉首元素和尾元素,vector和string不支持,
成員函式erase從容器中指定位置洗掉元素,
習題9.25
如果elem1與elem2相等,則一個元素都不會洗掉,
如果elem2是尾后迭代器,則會從elem1元素洗掉到最后一個元素,
如果elem1與elem2都是尾后迭代器,則一個元素都不會洗掉,
習題9.26
#include<vector>
#include<iostream>
#include<list>
using namespace std;
int main() {
int ia[] = { 0,1,1,2,3,5,8,13,21,55,89 };
vector<int> vec(ia, end(ia));
list<int> li(ia, end(ia));
for (auto it = li.begin(); it != li.end();) {
if (*it % 2 == 1) {
it = li.erase(it);
}
else {
++it;
}
}
for (auto i : li) {
cout << i << " ";
}
cout << endl;
for (auto it = vec.begin();it != vec.end();) {
if (*it % 2 == 0) {
it = vec.erase(it);
}
else {
++it;
}
}
for (auto i : vec) {
cout << i << " ";
}
cout << endl;
system("pause");
return 0;
}
知識點10:
forward_list的相關操作比較特殊,有其自己特殊的洗掉和插入操作
習題9.27
#include<iostream>
#include<forward_list>
using namespace std;
int main() {
forward_list<int> flst = { 0,1,2,3,4,5,6,7,8,9 };
auto prev = flst.before_begin();
auto curr = flst.begin();
while (curr != flst.end()) {
if (*curr % 2) {
curr = flst.erase_after(prev);
}
else {
prev = curr;
++curr;
}
}
for (auto i : flst) {
cout << i << " ";
}
system("pause");
return 0;
}
習題9.28
#include<forward_list>
#include<iostream>
#include<string>
using namespace std;
void func(forward_list<string> &flst, string a, string b) {
auto it = flst.begin();
auto prev = flst.before_begin();
bool flag = false;
while (it != flst.end()) {
if (*it == a) {
it = flst.insert_after(it, b);
flag = true;
break;
}
else {
prev = it;
++it;
}
}
if (!flag) flst.insert_after(prev, b);
}
int main() {
forward_list<string> flst = { "abc","bcd","eee" };
string a = "eee", b = "fff";
func(flst, a, b);
for (auto i : flst) {
cout << i << " ";
}
cout << endl;
system("pause");
return 0;
}
知識點11:改變容器大小
resize可以增大或縮小容器,array不支持
習題9.29
vec.resize(100)會將75個值為0的元素添加到vec的末尾,
vec.resize(10)會從vec末尾洗掉90個元素,
習題9.30
元素型別必須提供一個默認建構式
知識點12:容器操作可能會使迭代器失效
1.向容器中添加元素和從容器中洗掉元素的操作都可能會使指向容器元素的指標、參考或者迭代器失效,
2.必須保證每次改變容器的操作之后都正確地重新定位迭代器,
3.對于list和forward_list,變動之后指向容器的迭代器(包括首前迭代器、尾后迭代器)、指標和參考仍然有效,
4.不要保存end回傳的迭代器,
習題9.31
list
#include<iostream>
#include<vector>
#include<list>
using namespace std;
int main() {
list<int> lst = { 0,1,2,3,4,5,6,7,8,9 };
auto iter = lst.begin();
while (iter != lst.end()) {
if (*iter % 2) {
iter = lst.insert(iter, *iter);
++iter;
++iter;
}
else {
iter = lst.erase(iter);
}
}
for (auto i : lst) {
cout << i << " ";
}
system("pause");
return 0;
}
forward_list
#include<iostream>
#include<vector>
#include<forward_list>
using namespace std;
int main() {
forward_list<int> lst = { 0,1,2,3,4,5,6,7,8,9 };
auto iter = lst.begin();
auto prev = lst.before_begin();
while (iter != lst.end()) {
if (*iter % 2) {
iter = lst.insert_after(iter, *iter);
prev = iter;
++iter;
}
else {
iter = lst.erase_after(prev);
}
}
for (auto i : lst) {
cout << i << " ";
}
system("pause");
return 0;
}
習題9.32
不合法的原因:解引運算子和遞增的優先級一樣,結合律從右往左,函式實參求值順序不定
習題9.33
程式會崩潰,因為begin迭代器的值在插入一個元素之后已經失效
習題9.34
程式是為了復制奇數,但是由于每次插入奇數后回傳的是仍是同一個奇數,于是會進入無限回圈,所以應在每次插入奇數后跳兩次,
#include<vector>
#include<iostream>
using namespace std;
int main() {
vector<int> v = { 1,2,3,4,5};
auto iter = v.begin();
while (iter != v.end()) {
if (*iter % 2) {
iter = v.insert(iter, *iter);
++iter;
}
++iter;
}
for (auto i : v) {
cout << i << " ";
}
system("pause");
return 0;
}
知識點13:vector物件是如何增長的
vector將元素連續存盤,當沒有記憶體空間時,會分配比新空間需求更大的記憶體空間,
容器的size是指它保存了多少元素,capacity是指容器的最大容量,后者至少和前者一樣大,具體會分配多少額外空間得看標準庫的具體實作,
可以呼叫shrink_to_fit來要求vector將超出當前大小的多余記憶體退還給系統,
習題9.35
容器的size是指它已經保存元素的個數,capacity指的是不分配記憶體空間的前提下它最多可以保存的元素,
習題9.36
不可能
9.37
vector中的元素在記憶體中是連續存放的,所以需要capacity,list的元素不是連續存放的,不需要capacity,array的大小是固定的,
習題9.38
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<string> v;
for (string buffer; cin >> buffer; v.push_back(buffer))
cout << v.size() << " " << v.capacity() << endl;
return 0;
}
習題9.39
首先為svec預留了1024的空間,其次將輸入添加到svec中,最后將svec的size增大當前的一半,
習題9.40
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void func(int val){
vector<string> svec;
string s = "string";
svec.reserve(1000);
for (int i = 0; i < val; i++)
{
svec.push_back(s);
}
svec.resize(svec.size() + svec.size() / 2);
cout << "輸入" << val << "個詞之后size" << svec.size() << endl;
cout << "輸入" << val << "個詞之后capacity" << svec.capacity() << endl;
}
int main() {
func(256);
func(512);
func(1000);
func(1048);
system("pause");
return 0;
}

習題9.41
vector<char> v = { 'a','b','c' };
string s(v.begin(), v.end());
習題9.42
利用reverse()操作預留足夠的記憶體,這樣就不用在程序中進行修改記憶體的操作,
string s;
s.reserve(100);
知識點14:append和replace函式
append()直接在字串之后加上相關的引數
replace函式提供了兩種指定洗掉元素范圍的方式
習題9.43
#include<iostream>
#include<string>
using namespace std;
void func(string &s, string &oldVal, string &newVal) {
auto iter = s.begin();
while (iter + oldVal.size() != s.end()) {
if (oldVal == string(iter, iter + oldVal.size())) {
iter = s.erase(iter, iter + oldVal.size());
iter = s.insert(iter, newVal.begin(), newVal.end());
iter += newVal.size();
}
else {
++iter;
}
}
}
int main() {
string s("though,you don't love me");
string oldVal("though");
string newVal("tho");
func(s, oldVal, newVal);
cout << s;
system("pause");
return 0;
}
習題9.44
#include<iostream>
#include<string>
using namespace std;
void func(string &s, string &oldVal, string &newVal) {
string::size_type i = 0;
auto s_len = s.size(), old_len = oldVal.size();
while (i + old_len <= s_len) {
if (oldVal == s.substr(i, i + old_len)) {
s.replace(i, i + old_len, newVal);
i += newVal.size();
}
else {
++i;
}
}
}
int main() {
string s("though,you don't love me");
string oldVal("though");
string newVal("tho");
func(s, oldVal, newVal);
cout << s << endl;
system("pause");
return 0;
}
習題9.45
#include<iostream>
#include<string>
using namespace std;
void func(string &name, string &pre, string &post) {
name.insert(0, pre);
name.append(post);
}
int main() {
string nm = "Allen", pre = "Mr.", post = " Jr.";
func(nm, pre, post);
cout << nm;
system("pause");
return 0;
}
習題9.46
void func(string &name, string &pre, string &post) {
name.insert(0, pre);
name.insert(name.size(), post);
}
習題9.47
#include<string>
#include<iostream>
using namespace std;
int main() {
string str("ab2c3d7R4E6");
string numbers{ "123456789" };
string alphabet{ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" };
string::size_type pos = 0;
while ((pos = str.find_first_of(numbers, pos)) != string::npos) {
cout << str[pos] << " ";
++pos;
}
cout << endl;
pos = 0;
while ((pos = str.find_first_of(alphabet, pos)) != string::npos) {
cout << str[pos] << " ";
++pos;
}
cout << endl;
pos = 0;
while ((pos = str.find_first_not_of(alphabet, pos)) != string::npos) {
cout << str[pos] << " ";
++pos;
}
cout << endl;
pos = 0;
while ((pos = str.find_first_not_of(numbers, pos)) != string::npos) {
cout << str[pos] << " ";
++pos;
}
cout << endl;
system("pause");
return 0;
}
習題9.48
string::npos
習題9.49
#include<fstream>
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main() {
string FileName;
cout << "請輸入要打開的單詞檔案:" << endl;
cin >> FileName;
ifstream inFile(FileName);
if (!inFile) {
cout << "打開失敗!" << endl;
return 0;
}
vector<string> ans;
string up("bdfhklt"), down("gjpqy"), s;
string::size_type pos = 0,poschar;
while (inFile >> s) {
if ((pos = s.find_first_of(up)) == string::npos) {
if ((pos = s.find_first_of(down)) == string::npos) {
ans.push_back(s);
}
}
}
for (auto i : ans) {
cout << i << endl;
}
system("pause");
return 0;
}
習題9.50
#include<string>
#include<iostream>
#include<vector>
using namespace std;
int main() {
vector<string> vec = { "2","3","4","50" };
int sum = 0;
for (auto i : vec) {
sum += stoi(i);
}
cout << sum << endl;
system("pause");
return 0;
}
習題9.51
#include<iostream>
#include<string>
using namespace std;
const string mm[12] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sept","Oct","Nov","Dec" };
int findmonth(const string &mon) {
int pos;
for (int i = 0;i < 12;++i) {
if ((pos = mon.find(mm[i])) != string::npos) {
return i + 1;
}
}
}
class Date {
public:
Date(const string &str) {
string data_str = str;
string::size_type index1 = 0;
string::size_type index2 = 0;
if (str.find(',') != string::npos) {
index1 = str.find(' ');
index2 = str.find(',',index1+1);
string mon = str.substr(0, index1 - 1);
month = findmonth(mon);
day = stoi(str.substr(index1 + 1, index2));
year = stoi(str.substr(index2 + 1));
}
else if (str.find('/') != string::npos) {
index1 = str.find_first_of('/');
index2 = str.find_first_of('/', index1 + 1);
year = stoi(str.substr(index2 + 1));
month = stoi(str.substr(index1 + 1, index2 - 1));
day = stoi(str.substr(0, index1));
}
else {
index1 = str.find_first_of(' ');
index2 = str.find_first_of(' ', index1 + 1);
string mon = str.substr(0, index1);
month = findmonth(mon);
day = stoi(str.substr(index1 + 1, index2 - 1));
year = stoi(str.substr(index2 + 1));
}
}
void getdate() {
cout << "Year:" << year << " " << "Month:" << month << " " << "Day:" << day << endl;
}
private:
unsigned year, month, day;
};
int main() {
string d1 = "January 1,1900", d2 = "1/1/1990", d3 = "Jan 1 1900";
Date a(d1), b(d2), c(d3);
a.getdate();
b.getdate();
c.getdate();
system("pause");
return 0;
}
習題9.52
#include<iostream>
#include<stack>
#include<string>
using namespace std;
bool isnum(char a) {
if (a >= '0'&&a <= '9') {
return true;
}
else return false;
}
int main() {
string expr("(1+2)+(3+4)+5");
stack<char> st;
int sum = 0;
int len = expr.size();
for (int i = 0;i < len;i++) {
if (expr[i] == '('|| isnum((expr[i]))) {
st.push(expr[i]);
}
else if (expr[i] == '+') {
continue;
}
else if (expr[i] == ')') {
while (st.top() != '(') {
sum += st.top() - '0';
st.pop();
}
st.pop();
}
}
while (!st.empty()) {
sum += st.top() - '0';
st.pop();
}
cout << sum << endl;
system("pause");
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/4974.html
標籤:C++
上一篇:L1-043 閱覽室 (20分)
下一篇:L1-044 穩贏 (15分)
