1. 程式人生 > >C++STL基本容器的使用

C++STL基本容器的使用

類型 ace remove stack urn item ont 插入 one

容器主要分為:順序容器和關聯容器

順序容器和關聯容器,順序容器主要有:vector、list、deque等。其中vector表示一段連續的內存地址,基於數組的實現,list表示非連續的內存,基於鏈表實現。deque雙向隊列與vector類似,但是對於首元素提供刪除和插入的雙向支持。關聯容器主要有map和set。map是key-value形式的,set是單值。map和set只能存放唯一的key值,multimap和multiset可以存放多個相同的key值, 還有unorder_multimap等。

技術分享圖片

技術分享圖片

順序容器

vector

技術分享圖片

/*
* 什麽是vector, vector的特點
* vector類似一個動態數組,是一段地址連續的空間
* vector和array的區別:vector支持動態空間調整,隨著元素的增加,大小會改變
*/

技術分享圖片
   // 初始化:

    vector<int> v;
    vector<int> v2(10);  // 可以容納10個int
    vector<int> v3(10, 2); // 10個2
    vector<int> v4(v2);
    int arr[4] = {1,2,3,4};
    vector<int> v5(arr, arr+4);

    
// 其他操作, 是vector容器自帶的函數,不包含全局的算法(find查找,remove_if刪除等) // 添加元素 vec.push_back(3); // 在最後添加元素 insert(); /* iterator insert( iterator loc, const TYPE &val ); void insert( iterator loc, size_type num, const TYPE &val ); void insert( iterator loc, input_iterator start, input_iterator end ); insert() 函數有以下三種用法: 在指定位置loc前插入值為val的元素,返回指向這個元素的叠代器, 在指定位置loc前插入num個值為val的元素 在指定位置loc前插入區間[start, end)的所有元素 .
*/ // 刪: // erase iterator erase( iterator loc ); iterator erase( iterator start, iterator end ); // erase函數要麽刪作指定位置loc的元素,要麽刪除區間[start, end)的所有元素. // 返回值是指向刪除的最後一個元素的下一位置的叠代器.例如: vec.clear(); // 清空容器 vec.pop_back(); // 移除尾部元素,無返回值 // vec.back(); // 返回最有一個元素的引用 vec.begin(); // 返回當前容器首元素的叠代器 vec.end(); // 尾後叠代器 vec.rbegin(); // rbegin函數返回指向當前vector末尾的逆叠代器 vec.rend(); // rend()函數返回指向當前vector起始位置的逆叠代器. 類似與begin和end 其他 vec.empty(); // 判斷是否為空 vec.capacity(); // 返回當前vector在重新進行內存分配以前所能容納的元素數量. // reserve()函數為當前vector預留至少共容納size個元素的空間 // void resize( size_type size, TYPE val ); vec.resize(); // resize() 函數改變當前vector的大小為size,且對新創建的元素賦值val vec.size(); // 返回當前所容納的元素個數 // vec.swap(vec2) // vec和vec2交換 // 遍歷: void print(vector<int>& vec) { for (int i = 0; i < vec.size(); i++) cout << vec[i] << " "; for (vector<int>::iterator it = vec.begin(); it != vec.end(); it++) { cout << *it << " "; } for (auto item : vec) { cout << item << " "; } cout << endl; }
vector常用方法

deque

技術分享圖片

支持隨機訪問和快速插入和刪除

// 雙向隊列和向量很相似,但是它允許在容器頭部快速插入和刪除(就像在尾部一樣)。
// 就是比vector多了兩個方法:
push_front()
pop_back()
// 具體使用方法參考vector

技術分享圖片
#include <iostream>
#include <algorithm>
#include <deque>
using namespace std;


void printDeq(deque<int> &d1)
{
    cout << "deque叠代器遍歷:";
    for (deque<int>::iterator it = d1.begin(); it != d1.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl << endl;
}
void test41()
{
    deque<int> d1;
    d1.push_back(1);
    d1.push_back(3);
    d1.push_back(5);
    d1.push_front(-11);
    d1.push_front(-33);
    d1.push_front(-55);

    printDeq(d1);
    cout <<"頭部元素:" << d1.front() << endl;
    cout <<"尾部元素:" << d1.back() <<endl;

    d1.pop_front(); // 彈出頭部元素
    d1.pop_back();  // 彈出尾部元素

    cout << "彈出頭部,和尾部之後: ";
    printDeq(d1);

    // 查找-33在數組下標的值
    deque<int>::iterator it = find(d1.begin(),d1.end(), -33);

    if (it != d1.end())
    {
                                // 計算下標
        cout <<"-33的數組下標是" << distance(d1.begin(), it) << endl;
    }
    else
    {
        cout <<"未找到"<<endl;
    }

}
int main40()
{
    test41();
    return 0;
}
deque例子

list

list,list是stl實現的雙向鏈表,

與向量vector想比,它允許快速的插入和刪除,但是隨機訪問卻是比較慢

結構圖:

技術分享圖片

技術分享圖片

優點:隨意插入和刪除,替換元素效率極高

缺點:查找慢(不能隨機訪問:就是只能從頭開始遍歷)

不建議想裏面插入數據,效率太低

技術分享圖片
/ 其他操作
// 初始化,創建
    list<int> lst1;          //創建空list
    list<int> lst2(3);       //創建含有三個元素的list
    list<int> lst3(3,2);     //創建含有三個元素為2的list
    list<int> lst4(lst2);    //使用lst2初始化lst4
    list<int> lst5(lst2.begin(),lst2.end());  //同lst4

    //
        lst1.assign(lst2.begin(),lst2.end());  //分配值,3個值為0的元素
        lst1.push_front(1);                    // 1加到list的首部
        lst1.push_back(10);                    //末尾添加值

         
        lst1.insert();                                                   //返回值是一個叠代器,指向被插入的元素。
        iterator insert( iterator pos, const TYPE &val );              // 插入元素val到位置pos
        void insert( iterator pos, size_type num, const TYPE &val ); // 插入num個元素val到pos之前
        void insert( iterator pos, input_iterator start, input_iterator end ); // 插入start到end之間的元素到pos的位置
    //
        lst1.pop_back();    // 刪除鏈表的最後一個元素。
        lst1.pop_front();   // 刪除連鏈表第一個元素 
        lst1.remove(1);     // 刪除鏈表中所有的1  void
        lst1.remove_if( UnPred pr)// 以一元謂詞pr為判斷元素的依據,遍歷整個鏈表。如果pr返回true則刪除該元素。

        lst1.erase()
            iterator erase( iterator pos );
            iterator erase( iterator start, iterator end );
            erase()函數刪除以pos指示位置的元素, 或者刪除start和end之間的元素。 返回值是一個叠代器,指向最後一個被刪除元素的下一個元素。
    
    lst1.clear()              // 清除所有元素
    //
        lst1.reverse();       // 將所有的list倒轉
        lst1.swap(list2);     // 1和2交換
        lst1.unique();        // 刪除重復的元素
            void unique();
            void unique( BinPred pr );
            unique()函數刪除鏈表中所有重復的元素。如果指定pr,則使用pr來判定是否刪除。

    //
        lst1.begin();         // 返回list的首元素的叠代器
        lst1.end();           // 返回list尾後叠代器
        lst1.front();         // 返回一個指向首元素的引用
        lst.back()              // 返回一個引用,指向list的最後一個元素。
        lst1.rbegin();        // 返回一個逆向叠代器,指向鏈表的末尾。 rend和begin和end用法類似

    // 其他
        lst1.empty();         // 判斷是否為空 true為空
        lst1.max_size();      //max_size()函數返回鏈表能夠儲存的元素數目。
        lst1.merge()
            void merge( list &lst );
            void merge( list &lst, Comp compfunction );
            merge()函數把自己和lst鏈表連接在一起,產生一個整齊排列的組合鏈表。如果指定compfunction,則將指定函數作為比較的依據。

        lst1.resize(); 
            void resize( size_type num, TYPE val )// resize()函數把list的大小改變到num。被加入的多余的元素都被賦值為val
        lst1.size();         // 返回鏈表的元素數量
        lst1.sort();         // 排序
                void sort();
                void sort( Comp compfunction );
                sort()函數為鏈表排序,默認是升序。如果指定compfunction的話,就采用指定函數來判定兩個元素的大小。

        // 遍歷:

         // list不能隨機訪問 就是 it++正確,但是不能it+2

            it = l.begin();
            it++;
            it++;
            it++;  // 此時it指向第4個元素,元素為3
            l.insert(it, 100); // 在3前面插入100    
                
        for (auto it = lst1.begin(); it != lst1.end(); it++)
            cout << *it << " ";
        for (auto it : lst1)
            cout << it << " ";
        // 加上&可以修改值
        for (auto& it : lst1)
            cout << it << " ";
list常用操作

stack

技術分享圖片


不允許遍歷
C++ Stack(堆棧) 是一個容器類的改編,為程序員提供了堆棧的全部功能,——也就是說實現了一個先進後出(FILO)的數據結構。
    stack<int> s;
    s.push(1);  // 在棧頂添加元素
    s.push(2);
    s.top();  // 返回棧頂元素
    s.pop(); //刪除棧頂元素
    s.empty(); // 判斷棧空
    s.size();  // 判斷棧中元素數量

技術分享圖片
//
// Created by lk on 18-6-3.
//
#include <iostream>
#include <stack>
#include <cstring>
#include <algorithm>
using namespace std;

// 出棧
void printStack(stack<int> &sta)
{
    while(!sta.empty())
    {
        cout << sta.top() << " "; // 獲取棧頂元素
        sta.pop();   // 出棧
    }
}
void test51()
{
    stack<int> s;
    // 入棧
    for(int i = 0; i != 10; i++)
    {
        s.push(i+1);
    }

    printStack(s);
}

// 棧模型
// 棧的算法 和數據類型的分離
// teacher節點
class Teacher
{
private:
    int   age;
    char  name[32];
public:
    Teacher()
    {
        age = 0;
        strcpy(name, "");
    }
    Teacher(char *name, int age)
    {
        this->age = age;
        strcpy(this->name, name);
    }
    void print()
    {
        cout << "name: " << name << "age: " << age << endl;
    }
    friend ostream& operator<<(ostream &out, Teacher &obj)
    {
        out << " name: " << obj.name << "  age: " << obj.age << endl;
        return out;
    }
};
// 存放類 類型
void test52()
{
    Teacher t1("t1", 31), t2("t2", 32), t3("t3", 33);
    stack<Teacher> Stack_Tea;
    Stack_Tea.push(t1);
    Stack_Tea.push(t2);
    Stack_Tea.push(t3);

    while(!Stack_Tea.empty())
    {
        // Teacher重載了<<所以可以 cout<<
        cout <<Stack_Tea.top();
        Stack_Tea.pop();
    }
}
// 存放 類指針 類型
void test53()
{
    Teacher t1("t1", 31), t2("t2", 32), t3("t3", 33);
    stack<Teacher*> Stack_Tea;
    Stack_Tea.push(&t1);
    Stack_Tea.push(&t2);
    Stack_Tea.push(&t3);

    // 出棧
    while(!Stack_Tea.empty())
    {
        cout << (* Stack_Tea.top()); // Stack_Tea.top() 就是&t1
        Stack_Tea.pop();
    }
}

int main()
{
    // test51();
     test52();
//    test53();
    return 0;
}
測試

queue

技術分享圖片


隊列,棧都不能提前分配空間,需要進棧出棧, 不能遍歷,
隊和棧是兩種封裝好的數據結構
back()    返回最後一個元素
empty()    如果隊列空則返回真
front()    返回第一個元素
pop()    刪除第一個元素
push()    在末尾加入一個元素
size()    返回隊列中元素的個數
技術分享圖片
//
// Created by lk on 18-6-3.
//
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;

// 隊列的基本類型
void test61()
{
    queue<int> q;  // 隊列,棧都不能提前分配空間,需要進棧出棧
    // 入隊
    q.push(1);
    q.push(3);
    q.push(5);

    cout << "隊頭元素:" << q.front() << endl; // 返回隊頭元素,不是刪除,棧的是刪除
    cout <<"隊的大小:" << q.size() <<endl;
    cout << "隊尾元素:" << q.back() << endl;
    // 出隊
    cout <<"出隊: ";
    while(!q.empty())
    {
        cout << q.front() << " ";
        q.pop();  // 刪除隊頭元素
    }
}

// 隊列的算法 和數據類型分離
// teacher 節點
class Teacher
{
private:
    int   age;
    char  name[32];
public:
    Teacher()
    {
        age = 0;
        strcpy(name, "");
    }
    Teacher(char *name, int age)
    {
        this->age = age;
        strcpy(this->name, name);
    }
    void print()
    {
        cout << "name: " << name << " age: " << age << endl;
    }
    friend ostream& operator<<(ostream &out, Teacher &obj)
    {
        out << "\tname: " << obj.name << " age: " << obj.age << endl;
        return out;
    }
};

// 存放類 類型
void test62()
{
    Teacher t1("t1", 31), t2("t2", 32), t3("t3", 33);

    queue<Teacher> queue_Tea;  // 隊列裏面存放的是 Teacher的數據類型
    queue_Tea.push(t1);   // 入隊
    queue_Tea.push(t2);
    queue_Tea.push(t3);

    cout << "老師節點的出隊:\n";
    while(!queue_Tea.empty())
    {
        cout << queue_Tea.front() << "\n";
        queue_Tea.pop();  // 出隊
    }
}
// 存放指針類型
// 類似棧 。。。
int main()
{
    // test61();
    test62();
    return 0;
}
測試

關聯容器

https://www.cnblogs.com/xiaokang01/p/9130699.html

C++STL基本容器的使用