C++ STL vector容器學習

来源:http://www.cnblogs.com/zc110747/archive/2016/05/06/5466088.html
-Advertisement-
Play Games

STL(Standard Template Library)標準模板庫是C++最重要的組成部分,它提供了一組表示容器、迭代器、函數對象和演算法的模板。其中容器是存儲類型相同的數據的結構(如vector,list, deque, set, map等),演算法完成特定任務,迭代器用來遍歷容器對象,扮演容器和 ...


  STL(Standard Template Library)標準模板庫是C++最重要的組成部分,它提供了一組表示容器、迭代器、函數對象和演算法的模板。其中容器是存儲類型相同的數據的結構(如vector,list, deque, set, map等),演算法完成特定任務,迭代器用來遍歷容器對象,扮演容器和演算法之間的膠合劑。   

模板類vector   在計算中,矢量(vector)對應數組,它的數據安排以及操作方式,與array非常類似。在C++中,使用vector模板類時,需要頭文件包含#include<vector>,並聲明使用using std::vector或者using namespace std; (1)vector初始化 要創建vector模板對象,可使用<type>表示法來指出所使用的類型,vector通過類函數重載,支持多種初始化方式。
 int a[5] = {5, 1, 2, 0, 3};
 vector<int> v0(a, a+4);    
 vector<int> v1(v0);
 vector<int> v2(v0.begin(), v0.begin()+2);
 vector<int> v3(5);
如果編譯器支持C++11, 可以採用列表初始化,結果相同。
 vector<int> v{5, 1, 2, 0, 3};

(2)vector方法

C++ STL除了分配空間外,還提供了一些基本方法,下麵將詳細講解這些方法。 push_back 向容器的末尾添加元素,容器內元素個數加1 pop_back 刪除容器尾端元素,容器內元素個數減1.
v1.push_back(rand()%100); 
v1.pop_back();
size 容器內當前元素個數 capacity 容器當前容量 empty 判斷容器是否為空
cout<<v1.size()<<endl;     
cout<<v1.capacity()<<endl; 
if(!v1.empty())
{
    v1.pop_back();
    cout<<"v1 is not empty!"<<endl;     
}   
resize 修改當前容器內元素個數,大於當前數則插入相應數據,小於則刪除末尾相應區間。 reserve 修改當前容器容量,大於當前容量則申請相應空間,小於則不處理。
v1.resize(9, 6);           
v1.reserve(14);            
insert 在容器指定區間插入一個或者多個元素 earse 刪除容器內一個或者指定區間內所有元素
v0.insert(v0.begin(), a[0]);          
v1.insert(v1.begin(), a, a+2);       
v1.insert(v1.begin(), v0.begin()+2, v0.begin()+4); 
    
v1.earse(v1.end()-6);                 
v1.earse(v1.end()-6, v1.end());  
front 返回容器的第一個元素 back  返回容器的最後一個元素
cout<<v1.front()<<endl; 
cout<<v1.end()<<endl;
clear 清空容器內元素,僅修改size,不影響容器容量 swap  交換兩容器內內容,用於容量收縮
 v1.clear();
 vector<int>().swap(v1);
begin 返回指向vector首位的迭代器 end   返回指向vector末位的迭代器 基於迭代器,就可以簡單的實現vector的遍歷。
for(vector<int>::iterator iter0=vt1.begin(); iter0!=vt1.end(); iter0++)
{cout<<*iter0;}

當然,C++11提供了類型推導,上述語句可簡化為為

for(auto iter0=vt1.begin(); iter0!=vt1.end(); iter0++)
{cout<<*iter0;}
不過vector重載了[]運算符,也可以用
for(unsinged int i=0; i<vt1.size(); i++)
{cout<<vt1[i];}
在下小節中,將根據STL提供演算法,用於更方便的遍歷和處理vector。 (3)用於vector的演算法(常見演算法)   STL提供大量的演算法用於容器的操作,這裡主要以常用的for_each(遍歷), sort(排序), random_shuffle(隨機排列)三種演算法來簡單演示STL演算法的應用,使用演算法要包含頭文件#include <algorithm>。   for_each 遍歷容器,將被指向的函數應用於容器區間的每個元素。
void ShowInt(int &s)
{
   cout<<s<<" ";
}
for_each(v1.begin(), v1.end(), ShowInt);
 //C++11支持lambada表達式,可以寫成一句話:
for_each(v1.begin(), v1.end(), [](int &s){
        cout<<s<<" ";
});

  sort 容器內對象元素按照指定的規則進行排序,預設按照從小到大排列(不包含比較函數),當然也可以自定義比較函數

bool CompareInt(int &t1, int &t2)
{
    if(t1<t2)
      return true;
    return false;
}
sort(v1.begin(), v1.end(), CompareInt); 
sort(v1.begin(), v1.end());
//C++11 lambada
sort(v1.begin(), v1.end(), [](int &t1, int &t2}->bool{
        if(t1<t2)
             return true;
        return false;
});
  lower_bound 返回不小於元素值的第一個迭代器(相等或者大於),值可被插入的第一個位置   upper_bound 返回不破壞排序的情況下,值可被插入的最後一個位置
auto iter0 = lower_bound(v1.begin(), v1.end(), 34);
cout<<*iter0<<endl;          
iter0 = upper_bound(v1.begin(), v1.end(), 34);
cout<<*iter0<<endl;  

  random_shuffle 隨機排列容器內元素,其中第三個變數為提供的自定義隨機函數。

random_shuffle(v1.begin(), v1.end());
//C++11 lambada
random_shuffle(v1.begin, v1.end(), [](const unsigned int n)->unsigned int{
        return rand()%n;
});
(4) vector用於自定義數據類型   vector容器方便了對於數據的排序,插入,刪除及遍歷操作處理。結合運算符重載,類模板相關定義,將用戶自定義數據類型通過vector進行管理,屬於比較難以理解,但也是運用較多的部分。   因為C++11取消了關鍵字export,也不建議使用,因此類模板的聲明和實現,包括友元函數的實現都要聲明在同一個文件內。
/*****************************************
#device.h
#用戶自定義類模板
#命名空間 user
#用戶自定義類模板 device<T>
#構造函數重載
#一元、 二元運算符重載 
*******************************************/
#include <string>
#include <iostream>
 
using namespace std;
namespace user
{
    //自定義類模板
    template<class T>
    class device
    {
        public:
            //構造函數重載
            device(){}
            device(T a){id = a; name=" ";}
            device(string str){name = str; id=0;}
            device(string str, T a){name = str; id = a;}
            ~device(){};
            void show_info();
 
            //一元運算符重載
            device<T>& operator++(int);
 
            //二元運算符重載
            friend device<T>& operator+ <T>(device<T>&d, string &s);
            friend  bool operator< <T>(device<T> &d1, device<T> &d2);
            friend ostream& operator<< <T>(ostream &out, const device<T> &d);
        private:
            T        id;
            string    name;
    };
 
    template<class T>
    void device<T>::show_info(void)
    {
        cout<<"id:"<<id<<" ";
        cout<<"name:"<<name<<endl;
    }
 
    template<class T>
    ostream& operator<<(ostream &out, const device<T> &d)
    {
        out<<"id:"<<d.id<<" name:"<<d.name<<"\n";
        return out;
    }
 
    template<class T>
    bool operator<(device<T> &d1, device<T> &d2)
    {
        if(d1.id < d2.id)
            return true;
        else if(d1.id == d2.id && d1.name<d2.name)
            return true;
        else
            return false;
    }
 
    template<class T>
    device<T>& device<T>::operator++(int)
    {
        this->id++;
        return *this;
    }
 
    template<class T>
    device<T>& operator+(device<T> &d, string &s)
    {
        d.name  = s + d.name;
        return d;
    }
} 

 vectorDemo.cpp主要涉及智能指針,用戶自定義類型及STL vector容器及演算法的相應應用。

/*****************************************
#VectorDemo.cpp
#vector容器方法
#迭代器
#STL演算法
#lambada表達式
#智能指針
*******************************************/
#include "VectorDemo.h"
#include <vector>
#include <iostream>
#include <algorithm>
#include <memory>
#include "device.h"
#include <string>
 
using namespace std;
using namespace user;

//函數模板
template<class T>
void ShowDevice(shared_ptr<device<T>> &s)
{
    cout<<*s;
}
 
template<class T>
void show_genericity_demo(vector<shared_ptr<device<T>>> &d)
{
    //<<** 三次重載,第一次取智能指針,第二次取對象, 第三次輸出
    for(auto iter=d.begin(); iter!=d.end(); iter++)
    {
        cout<<**iter; //(*iter)->show_info();
    }
    cout<<endl;
}
 
template<class T>
bool genericity_compare(shared_ptr<device<T>> &d1, shared_ptr<device<T>> &d2)
{
    //重載運算符< 比較
    if((*d1) < (*d2))
        return true;
    else
        return false;
}
 
//複雜容器vector模板,涉及智能指針和用戶自定義類型
int genericity_vector_Demo(void)
{
    shared_ptr<device<int>> spd[5] = {
        shared_ptr<device<int>>(new device<int>("TV", rand()%100)),
        shared_ptr<device<int>>(new device<int>("Phone", rand()%100)),
        shared_ptr<device<int>>(new device<int>("Computer", rand()%100)),
        shared_ptr<device<int>>(new device<int>("light", rand()%100)),
        shared_ptr<device<int>>(new device<int>("pot", rand()%100)),
    };
    
    //vector容器創建和初始化,對象為device對應的智能指針
    vector<shared_ptr<device<int>>> vspd(spd, spd+5);
    
    //遍歷顯示vector中的所有對象,傳入為shared_ptr指針,因此*號,在通過<< 運算符重載
    for_each(vspd.begin(), vspd.end(), ShowDevice<int>);
    cout<<endl;
 
    //排序 lambada表達式
     sort(vspd.begin(), vspd.end(), [](shared_ptr<device<int>> &t1, shared_ptr<device<int>> &t2)->bool{
            if((*t1)<(*t2))
                return true;
            return false;
        });
 
    //亂序排列容器內對象
    random_shuffle(vspd.begin(), vspd.end());
    show_genericity_demo<int>(vspd);
 
    cout<<*vspd.front()<<endl;
    cout<<*vspd.back()<<endl;
 
    vspd.push_back(shared_ptr<device<int>>(new device<int>("icebox", rand()%100)));
    vspd.push_back(shared_ptr<device<int>>(new device<int>("PlayStation", rand()%100)));
    
    //排序,因為容器元素為智能指針,不支持省略比較函數方法
    sort(vspd.begin(), vspd.end(), genericity_compare<int>);
    show_genericity_demo<int>(vspd);
 
    vspd.pop_back();
    show_genericity_demo<int>(vspd);
 
    //遍歷 +, ++運算符重載,實現對容器內對象元素修改.
    for_each(vspd.begin(), vspd.end(), [](shared_ptr<device<int>> &s){
        (*s) = (*s) + string("famlily ");
        (*s)++;
    });
    show_genericity_demo<int>(vspd);
 
    return 0;
}

  相關代碼:容器範例下載

  參考書籍:

  1. C++ Primer Plus

       2. STL源碼剖析


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ScriptsBundleTransform.cs BundleConfig.cs 這樣的話就能生成 CDN 站點下的JS文件引用了 對了這裡漏掉了一個地方, 但是如果CDN站點掛掉了怎麼辦,咱們繼續: SctiptsBundleExtensions.cs 這樣會生成如下的JS應用: 這樣的話當CD ...
  • (譯者註:使用EF開發應用程式的一個難點就在於對其DbContext的生命周期管理,你的管理策略是否能很好的支持上層服務 使用獨立事務,使用嵌套事務,並行執行,非同步執行等需求? Mehdi El Gueddari對此做了深入研究和優秀的工作並且寫了一篇優秀的文章,現在我將其翻譯為中文分享給大家。由於 ...
  • /*遍歷二叉樹*/ 在這裡呢首先簡單的介紹下幾種遍歷的方式。 例如下圖: 前序遍歷(先根遍歷):(1):先訪問根節點; (2):前序訪問左子樹;(3):前序訪問右子樹; 【1 2 3 4 5 6】 中序遍歷: (1):中序訪問左子樹;(2):訪問根節點; (3):中序訪問右子樹; 【3 2 4 1 ...
  • 二叉樹的簡介: 樹形結構是一類重要的非線性數據結構,其中以樹和二叉樹最為常用。二叉樹是每個結點最多有兩個子樹的有序樹。通常子樹的根被稱作“左子樹”(left subtree)和“右子樹”(right subtree)。二叉樹常被用作二叉查找樹和二叉堆或是二叉排序樹。(這些結構呢在後面的博客中將一一講 ...
  • 上篇文章搭建了zookeeper集群 那好,今天就可以搭建solr搜服服務的集群了,這個和redis 集群不同,是需要zk管理的,作為一個代理層 安裝四個tomcat,修改其埠號不能衝突。8080~8083 如果是正式環境下,則分別使用4台linux作為節點 修改server.xml文件修改埠號 ...
  • 今天終於看完了第一章,哈哈,萬事開頭難....剛開始被編程思想的第一章給矇住了,講一堆理論,沒什麼意思。從第二章開始,真正的開始講解Java相關的內容,有了一定的開發經驗後,再次閱讀起來,感覺收穫良多啊! 關於對象 與C這種面向過程的語言不通,Java是面向對象的,在它眼裡一切都是對象。 在Java ...
  • Eclipse自己帶有編譯器(JDK),因為安裝Eclipse時還需要安裝jre。 Eclipse需找JRE的順序: 1. 先到Eclipse的安裝目錄先尋找Eclipse.ini文件中的-vm參數(-vm javaw.exe路徑)是否配置,使用此配置下的jre啟動Eclipse 2. 如果沒有配置... ...
  • 恢復內容開始 1.首先說明什麼是JDBC在第一眼看到這個名詞之前,我覺得有必要知道它的英文全稱是什麼,Java Database Connectivity,從英文字面上理解就直譯為可連通的Java資料庫,說白了也就是想提供一套中間環節,去連接Java代碼與資料庫,使之可以直接通過操作Java代碼就可 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...