順序容器部分習題(基礎)

9.4: 編寫一個函數,接受一個對指向vector的迭代器,和一個int值.在兩個迭代器指定的範圍查找給定的值,返回一個bool值來指出是否找到

#include <iostream>
#include <vector>
#include <iterator>
using namespace std;
// 注意迭代器的類型 和迭代器的寫法iterator
bool search(vector<int>::iterator beg, vector<int>::iterator ed, int i)
{
    while (beg != ed)
    {
        if (*beg == i)
            return true;
        ++beg;
    }
    return false;
}
int main()
{
    vector<int> vec{1, 2, 3, 4, 5};
    int i;
    cout << "輸入想要找的值" << endl;
    cin >> i;

    int fag =  search(vec.begin(), vec.end(), i);
    if (fag)
        cout << "找到" << endl;
    else
        cout << "未找到" << endl;

    return 0;
}

9.5重寫上一題,返回一個迭代器指向找到的元素:

#include <iostream>
#include <vector>
#include <iterator>
using namespace std;

vector<int>::const_iterator find(vector<int>::const_iterator begin, 
                            vector<int>::const_iterator end, int i)
{ // 此時*begin不可以被修改
    while (begin != end)
    {
        if (*begin == i)  
            return begin;  // 找到返回該元素迭代器
        ++begin;
    }
    return end; // 未找到返回最後一個迭代器
}
int main()
{
    vector<int> vec{1, 3, 4, 5, 6 };
    cout << "請輸入要查找的值" << endl;
    int i;
    cin >> i;
    auto a = find(vec.cbegin(), vec.cend(), i);
    if (a != vec.cend())
        cout << "找到" << endl;
    else
        cout << "未找到" << endl;

    return 0;
}

20:編寫程序從一個list拷貝元素到兩個deque中,值爲偶數的所有元素都拷貝到一個deque中,而奇數都拷貝到另一個deque中

#include <iostream>
#include <list>
#include <deque>
using namespace std;

int main()
{
    list<int>list1{1, 2, 3, 4, 5};
    deque<int>deque_d;
    deque<int>deque_f;

    auto i = list1.begin();
    while (i != list1.end())
    {
        if (*i % 2 == 0)
        {
            deque_d.push_back(*i);
            ++i;
        }
        else
        {
            deque_f.push_back(*i);
            ++i;
        }

    }

    cout << "list1 的元素是: ";
    for (auto &i : list1)
        cout << i << " ";

    cout <<"\n偶數爲: ";
    for (auto i = deque_d.begin(); i != deque_d.end(); ++i)
    {
        cout << *i << " ";
    }

    cout << "\n奇數是: ";
    for (auto &i : deque_f)
    {
        cout << i << " ";
    }

    return 0;
}
//list1 的元素是: 1 2 3 4 5 
//偶數爲: 2 4 
//奇數是: 1 3 5 

24:編寫程序,分別使用at,下標運算符,front,和begin提取一個vector中的一個元素,在空vector中測試:

#include <iostream> 
#include <vector>
#include <list>
using namespace std;

int main()
{
    // 訪問元素
//  vector<int>vec = {1, 2, 3};
//  cout << vec.front() << " " << vec.back() << " " << vec.at(1) << " "
//          << vec[1] ;


    list<int> list1 = {1, 2, 3};
    auto i = list1.begin();
    auto e = list1.end();

    // 範圍性刪除
//  i = list1.erase(++i, ++list1.begin()); // 當刪除迭代器範圍相等時 
                                        //  相當於刪除一個元素
    list1.erase(i, --e);

    auto it = list1.begin();
    while (it != list1.end())
    {
        cout << *it++ << " ";
    }
    return 0;
}

26:使用下面代碼定義的ia,將ia拷貝到一個vector和一個list中,使用單迭代器版本的erase從list中刪除奇數元素,從vector中刪除偶數元素
int ia[] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89};

#include <iostream>
#include <list>
#include <vector>
using namespace std;
//刪除操作 拷貝操作
int main()
{
    int ia[] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89};
    vector<int>vec (ia, ia+11); // 拷貝數組內容
    list<int>list1(vec.begin(), vec.end()); // 拷貝容器內容

    auto it = vec.begin();
    while (it != vec.end()) // 去除偶數部分
    {
        if (*it % 2 == 0)
        {
            it = vec.erase(it);
        }
        else
            ++it;
    }

    auto i = vec.begin();
    cout << " 奇數 :" << endl; 
    while (i != vec.end())
    {
        cout << *i++ << " ";
    }
    cout << endl;

    cout << " 偶數 :" << endl;
    // 去除奇數部分
    for (auto it = list1.begin(); it != list1.end(); )
    {
        if (*it % 2 != 0)
            it = list1.erase(it);
        else
            ++it;
    }
    for (auto &it : list1)
        cout << it << " "; 
    cout << endl;

    return 0;
}

32
編寫改變容器的循環程序

// 很好的題 刪除偶數部分 複製奇數部分
#include <iostream>
#include <vector>
#include <list>
using namespace std;

int main()
{
    vector<int>vec = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    auto it = vec.begin();
    while (it != vec.end())
    {
        if (*it % 2 == 0)
        {
            it = vec.erase(it);   // 刪除偶數
        }
        else if (*it % 2 != 0)
        {
        //關鍵是要看看這一句
            it = vec.insert(it, *it); // *it++ 是錯誤的
            it += 2;     // 需要跳過本身和複製的一個數
            // 如果是list類型容器就不能用it+=2需要分開
            //it++;
            //it++;
        }
    }

    cout << "結果爲:\n";
    for (auto &it : vec)
    {
        cout << it++ << " ";
    }
    return 0;
}

33:探討insert
使用後迭代器是否失效

#include <iostream>
#include <vector>
using namespace std;
//特別注意
int main()
{
    vector<int> vec = {1, 2, 3, 4, 5};
    auto begin = vec.begin();
    while (begin != vec.end())
    {
        ++begin;
        begin = vec.insert(begin, 42); // insert 是插入begin之前返回42的迭代器
//      vec.insert(begin, 43); // 這是錯的 迭代器會失效   
        ++begin;
    }

    for (auto &it : vec)
    {
        cout << it << " ";
    }
    return 0;
}
//結果:
//1 42 2 42 3 42 4 42 5 42

//vector是如何增長的課本318:
35: 解釋一個vector的capacity和size的區別:
vector 的 capacity 表示在不分配新內存的條件下能存放多少元素 而size() 表示已經存放了多少元素

37:爲什麼list或array沒有capacity函數:
list 的標準庫是雙鏈表 不需要分配,每次需要時再申請 array是有固定大小的

38:探究vector如何增長:

#include <iostream>
#include <vector>
using namespace std;

int main()
{
    vector<int> vec;
    cout << "vec:size: " << vec.size()<< endl;
    cout << "capacity: " << vec.capacity()<<endl;
    cout << endl;

    // 加入24個元素
    for (vector<int>::size_type ix = 0; ix != 24; ix++)
        vec.push_back(ix);
   // 此時size 應該爲 24 , capacity 應該大於或等於24    
    cout << "vec:size: " << vec.size()<< endl;
    cout << "capacity: " << vec.capacity()<<endl;
    cout << endl;   

    vec.reserve(50); // 將capacity設爲至少爲50甚至更大    
   // 此時size 應該爲 24 , capacity 應該大於或等於50    
    cout << "vec:size: " << vec.size()<< endl;
    cout << "capacity: " << vec.capacity()<<endl;
    cout << endl;

    //接下來用光預留的空間
    while (vec.size() != vec.capacity())
    {
        vec.push_back(0);
    }


   // 此時size 應該爲 50 , capacity 應該也是50   
    cout << "vec:size: " << vec.size()<< endl;
    cout << "capacity: " << vec.capacity()<<endl;
    cout << endl;

    vec.push_back(100);  // 在向其中加一個元素
   // 此時size 應該爲 51 , capacity 應該大於51   
    cout << "vec:size: " << vec.size()<< endl;
    cout << "capacity: " << vec.capacity()<<endl;
    cout << endl;

    return 0;
}

swap使用:

#include <iostream>
#include <list>
#include <vector>
using namespace std;

int main()
{
    vector<int> vec = {1, 2, 3, 4};
    vector<int> vec1 = {4, 3, 2,1};
    cout << "交換前 vec爲: ";
    for (auto i : vec)
    {
        cout << i;
    }
    cout << endl;

    auto it = vec.begin();
    cout << "交換前v的it指向的是 "<<*it <<endl;

    auto it1 = vec1.begin();
    cout << "交換前v1的it1迭代器指向的是 :"<<*it1 << endl;

    vec1.swap(vec); // 交換兩個容器

    cout << "交換後vec 爲";
    for (auto i : vec)
    {
        cout << i ;
    }
    cout << endl;
    cout << "交換後v原來的it現在指向" << *it <<endl;
    cout << "交換後v1原來的it1現在指向" << *it <<endl;

    return 0;
}
/*
   若交換前定義一個it 指向元素值爲1 的迭代器,交換後it還是指向1,改變的只是容器內部的數據結構
   交換後迭代器不變 ,引用, 指針都不變 
 */

vector初始化

#include <iostream>
#include <vector>
#include <string>

int main()
{
    vector<int> v1(10); // v1裏面有10個元素 都是0
    vector<int> v2{10}; // v2裏面有一個元素 10;

    vector<int> v3(10, 1); // v3裏面有10個元素都是1
    vector<int> v4{10, 1}; // v4裏面有連個元素10,1;

    // string容器初始化
    vector<string> v5{"hi"}; // 列表初始化 v5有一個元素  
    //注意
    vector<string> v6("hi"); //錯誤,不能使用字面值構建vector對象

    vector<string> v7{10};   // v7有10個默認初始化的元素
    vector<string> v8{10, "hi"}  // v8有10個"hi"元素
    vector<string> v9(10, "hi") // 和v8一樣

    int a[5] = {1, 2, 3, 4, 5};   // 字符容器也是如此
    vector<int>v1 (begin(a), end(a));
    vector<int> v2(a, a+5);
    return 0;
}

//訪問容器知識點:

//包括array在內的每一個順序容器都有一個front成員函數,除了forward_list之外的所有容器都有一個back成員函數,
在解引用前先檢查是否有元素
if (c.empty())
{

    auto val = *c.begin();
    auto val2 = *c.front();  // val val2 都是c容器的第一個元素
    auto last = c.end();
    auto val3 = *(--last);  // c容器的最後一個元素 或者--end()
    auto val4 = c.back();  // 不支持forward_list 其他都行

}
在順序容器中訪問元素的操作:
at和下標操作只適用於string vector arraydeque
back不適用於forward_list
c.back()  返回c的尾元素的引用 c不能爲空
c.front() 返回c的首元素的引用 c不能爲空
c[n] 返回c中下標爲n的元素的引用 n是無符號整數 若n>=c.size() 則錯誤
c.at(n) 返回下標爲n的元素的引用 下標不能越界
警告: 若空容器調用front或back則就像下標越界 錯誤

刪除元素
這些操作操作會改變array的大小所以不適用於array
forward_list 有特殊的erase
forward_list 不支持pop_back; vectorstring不支持pop_front;
c.pop_back() 刪除c的尾元素,若c爲空 則函數未定義。 函數返回void
c.pop_front() 刪除c的首元素, c不爲空 函數返回void
c.erase(p) 刪除迭代器p所指向的元素,返回p之後的元素的迭代器,p不能爲尾後迭代器
c.erase(b, e) 刪除b 和e 迭代器所指範圍內的元素包括本身,返回e之後的迭代器
c.clear() 刪除c中所有的元素
警告:
刪除deque中首尾之外的任何元素,都會使迭代器,引用,指針失效。指向vectorstring中刪除點之後位置的迭代器,引用,指針都會失效;
再刪除元素之前必須確保他們存在


改變容器的大小
c.resize(n)  調整c的大小爲n 如果n < c.size() 多出的會被刪除 若必須添加,就要對他初始化;
c.resize(n, t) 調整大小爲n 初始化爲t  

順序容器會不會失效總結
對vectorstring刪除或增加,刪除或增加 後面的迭代器,指針或引用對失效,前面的不會
對deque除了首尾之外的任何位置進行修改都會使指針,迭代器,引用失效。如果是對首尾修改,只有迭代器會失效其他不會
對list 和forward_list 不論修改哪,迭代器,指針,引用都不會失效
管理迭代器建議,對於vectorstringdeque 最好每次都重新確定其迭代器是否正確
最好使用 it = vi.insert(iter, a);

// 賦值:

#include <iostream>
#include <list>
#include <vector>
using namespace std;
// 使用assign 只需要元素類型可以轉換就好了
int main()
{
    list <const char *> list1={"hello", "world"};
    vector<string> vec(list1.cbegin(), list1.cend());  // 兩種方法
//  vec.assign(list1.cbegin(), list1.cend());   

    for (const auto &i : vec)
    {
        cout << i << endl;
    }
    return 0;
}

拷貝初始化:

#include <iostream>
#include <vector>
#include <list>
using namespace std;

int main()
{
    list<double>list1 = {1.1, 2.4, 3, 4};
    vector<int> vec (list1.begin(), list1.end());

    auto it = vec.begin();
    auto it1 = list1.begin();
    cout<< "拷貝前: " ;
    while(it1 != list1.end())  // 原來的
    {
        cout << *it1 << " ";
        ++it1;
    }
    cout << endl;
    cout << "拷貝後: ";
    while (it != vec.end())  // 拷貝過來的
    {
        cout << * it << " ";
        ++it;
    }
    cout << endl;
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章