zoukankan      html  css  js  c++  java
  • STL学习

    侯捷STL学习(一)

    • 开始跟着《STL源码剖析》的作者侯捷真人视频,学习STL,了解STL背后的真实故事!
    • 视频链接:侯捷STL
    • 还有很大其他视频需要的留言

    第一节:STL版本和重要资源

    • STL和标准库的区别

    第二节:STL六大部件

    • 迭代器将容器和算法结合起来
    • 分配器实现,适配器用的地方很多

    • 实例:

    • 理解容器的前闭后开的设计。迭代器类似于指针,很多操作和指针差不多++,--运算。vec.begin(),vec.end()指向容器最后一个元素的下一个位置,解引用*(vec.end())错误!
    • auto关键字的应用
    std::vector<double> vec;
    for(auto elem: vec)
    {
       std::cout<<elem<<std::endl;
    }

    第三节:容器之分类和各种测试(一)

    分类结构

    • 红色框中标注的是C++11开始有的容器
    • Array数组容器,大小固定的
    • Deque:两段都可以进行插入删除操作,但是从内存上讲不通,怎么实现的要从后面的学习知道。
    • List:是一个双向的循环链表,注意是双向的。
    • Forward-List:单向链表,当能用单向链表的时候尽量用,可以减少内存空间,一个指针在32位pc上占4个字节,当数据量很多上百万,不可忽略!
    • Set键值都一样,MultiSet允许元素有重复。
    • Set/Map用红黑树实现,RB-tree是自平衡的二叉树。
    • Unorder Containers:是C++标准库里卖的内容。
    • 根据这些图例,可以知道这些容器在内存用到的数据结构是什么样的。
    • HashTable实现方法很多,但基本都用Separate Chaining(分离链地址法实现)。

    测试Array

    • 指针void* a -> *(long*)a;
    • array<long, size> c使用初始化大小,#include<array>
    • c.data()返回这个数组的初始地址,和数组的地址对比
    • qsort应用:qsort(c.data,size,size(long),comparelongs)
    • bsearch()应用,查找前必须排好序了:bsearch(&target,(c.data()),size,size(long),comparelongs)
    • qsort,bsearch包含头文件#include<cstdlib>,C本身库函数
    #include <array>
    #include <iostream>
    #include <ctime> 
    #include <cstdlib> //qsort, bsearch, NULL
    
    namespace jj01
    {
    void test_array()
    {
        cout << "
    test_array().......... 
    ";
         
    array<long,ASIZE> c;    
                
    clock_t timeStart = clock();                                    
        for(long i=0; i< ASIZE; ++i) {
            c[i] = rand(); 
        }
        cout << "milli-seconds : " << (clock()-timeStart) << endl;  //
        cout << "array.size()= " << c.size() << endl;       
        cout << "array.front()= " << c.front() << endl; 
        cout << "array.back()= " << c.back() << endl;   
        cout << "array.data()= " << c.data() << endl;   
        
    long target = get_a_target_long();
    
        timeStart = clock();
        ::qsort(c.data(), ASIZE, sizeof(long), compareLongs);
    long* pItem = (long*)::bsearch(&target, (c.data()), ASIZE, sizeof(long), compareLongs); 
        cout << "qsort()+bsearch(), milli-seconds : " << (clock()-timeStart) << endl;   //    
        if (pItem != NULL)
            cout << "found, " << *pItem << endl;
        else
            cout << "not found! " << endl;  
    }
    }

    第四节:容器之分类和各种测试(二)

    测试Vector

    • 主要通过程序细节说明
    • namespace命名空间的说明
    • vector的增长速度是2倍增长,当capacity不够时,容量增长为前面的2倍。是在另外的2倍空间!
    • try...catch...捕获函数,字符串最大占一个指针大小,空间不够的时候抛出,abort()退出
    • ::find()模板函数,加冒号表明是全局函数,当没有冒号时,编译器在当前没有找到,也会到全局去找。
    • 用两种查找算法比较,find()用时更少。
    #include <vector>
    #include <stdexcept>
    #include <string>
    #include <cstdlib> //abort()   //qsort, bsearch, NULL
    #include <cstdio>  //snprintf()
    #include <iostream>
    #include <ctime> 
    #include <algorithm>    //sort()
    namespace jj02
    {
    void test_vector(long& value)
    {
        cout << "
    test_vector().......... 
    ";
         
    vector<string> c;   
    char buf[10];
                
    clock_t timeStart = clock();                                
        for(long i=0; i< value; ++i)
        {
            try {
                snprintf(buf, 10, "%d", rand());
                c.push_back(string(buf));           
            }
            catch(exception& p) {
                cout << "i=" << i << " " << p.what() << endl;   
                     //曾經最高 i=58389486 then std::bad_alloc
                abort();
            }
        }
        cout << "milli-seconds : " << (clock()-timeStart) << endl;  
        cout << "vector.max_size()= " << c.max_size() << endl;  //1073747823
        cout << "vector.size()= " << c.size() << endl;      
        cout << "vector.front()= " << c.front() << endl;    
        cout << "vector.back()= " << c.back() << endl;  
        cout << "vector.data()= " << c.data() << endl;
        cout << "vector.capacity()= " << c.capacity() << endl << endl;      
    
                                                                                    
    string target = get_a_target_string();
        {
        timeStart = clock();
    auto pItem = find(c.begin(), c.end(), target);
        cout << "std::find(), milli-seconds : " << (clock()-timeStart) << endl;  
         
        if (pItem != c.end())
            cout << "found, " << *pItem << endl << endl;
        else
            cout << "not found! " << endl << endl;
        }
    
        {
        timeStart = clock();
        sort(c.begin(), c.end());
        cout << "sort(), milli-seconds : " << (clock()-timeStart) << endl; 
        
        timeStart = clock();        
    string* pItem = (string*)::bsearch(&target, (c.data()), 
                                       c.size(), sizeof(string), compareStrings); 
        cout << "bsearch(), milli-seconds : " << (clock()-timeStart) << endl; 
           
        if (pItem != NULL)
            cout << "found, " << *pItem << endl << endl;
        else
            cout << "not found! " << endl << endl;  
        }
        
        c.clear();
        test_moveable(vector<MyString>(),vector<MyStrNoMove>(), value); 
    }   
    }

    第五节:容器之分类和各种测试(三)

    测试List,双向链表

    • list.max_size()按理list是动态申请空间的,为什么最大的size呢?
    • list双向链表实现
    • 有趣的c.sort(),这里注意在STL标准库全局有一个sort函数,但这里调用的是list容器自身内部的sort函数。注意在STL容器中有些自身有sort函数,此时用自身的排序算法更快。
    #include <list>
    #include <stdexcept>
    #include <string>
    #include <cstdlib> //abort()
    #include <cstdio>  //snprintf()
    #include <algorithm> //find()
    #include <iostream>
    #include <ctime> 
    namespace jj03
    {
    void test_list(long& value)
    {
        cout << "
    test_list().......... 
    ";
         
    list<string> c;     
    char buf[10];
                
    clock_t timeStart = clock();                            
        for(long i=0; i< value; ++i)
        {
            try {
                snprintf(buf, 10, "%d", rand());
                c.push_back(string(buf));       
            }
            catch(exception& p) {
                cout << "i=" << i << " " << p.what() << endl;   
                abort();
            }
        }
        cout << "milli-seconds : " << (clock()-timeStart) << endl;      
        cout << "list.size()= " << c.size() << endl;
        cout << "list.max_size()= " << c.max_size() << endl;    //357913941
        cout << "list.front()= " << c.front() << endl;  
        cout << "list.back()= " << c.back() << endl;        
            
    string target = get_a_target_string();      
        timeStart = clock();        
    auto pItem = find(c.begin(), c.end(), target);                      
        cout << "std::find(), milli-seconds : " << (clock()-timeStart) << endl;     
        
        if (pItem != c.end())
            cout << "found, " << *pItem << endl;
        else
            cout << "not found! " << endl;  
            
        timeStart = clock();        
        c.sort();                       
        cout << "c.sort(), milli-seconds : " << (clock()-timeStart) << endl;                
            
        c.clear();
        test_moveable(list<MyString>(),list<MyStrNoMove>(), value);                             
    }   
    }

    测试forward-list,单向链表

    • forward-list单向链表,C++11出现的
    • push_front在链表头插入,不提供在尾部插入,效率低些。
    • front取链表头的元素,不提供back()操作取链表尾的元素。
    • c.sort()用它自身的排序算法
    #include <forward_list>
    #include <stdexcept>
    #include <string>
    #include <cstdlib> //abort()
    #include <cstdio>  //snprintf()
    #include <iostream>
    #include <ctime> 
    namespace jj04
    {
    void test_forward_list(long& value)
    {
        cout << "
    test_forward_list().......... 
    ";
         
    forward_list<string> c;     
    char buf[10];
                
    clock_t timeStart = clock();                                
        for(long i=0; i< value; ++i)
        {
            try {
                snprintf(buf, 10, "%d", rand());
                c.push_front(string(buf));                      
            }
            catch(exception& p) {
                cout << "i=" << i << " " << p.what() << endl;   
                abort();
            }
        }
        cout << "milli-seconds : " << (clock()-timeStart) << endl;  
        cout << "forward_list.max_size()= " << c.max_size() << endl;  //536870911
        cout << "forward_list.front()= " << c.front() << endl;  
    
    
    string target = get_a_target_string();  
        timeStart = clock();            
    auto pItem = find(c.begin(), c.end(), target);  
        cout << "std::find(), milli-seconds : " << (clock()-timeStart) << endl;     
        
        if (pItem != c.end())
            cout << "found, " << *pItem << endl;
        else
            cout << "not found! " << endl;  
            
        timeStart = clock();        
        c.sort();                       
        cout << "c.sort(), milli-seconds : " << (clock()-timeStart) << endl;        
        
        c.clear();   
    }                                            
    }

    测试slist

    • Gnu C之前的单链表,forward-list是C++11才出现的
    • #include<extslist>头文件
    #include <extslist>
        //注意, 上一行並沒有引發警告訊息如 #include <exthash_set> 所引發者: 
        //...4.9.2includec++ackwardackward_warning.h 
        //[Warning] ...
        
    #include <stdexcept>
    #include <string>
    #include <cstdlib> //abort()
    #include <cstdio>  //snprintf()
    #include <iostream>
    #include <ctime> 
    namespace jj10
    {
    void test_slist(long& value)
    {
        cout << "
    test_slist().......... 
    ";
         
        __gnu_cxx::slist<string> c;     
        char buf[10];
                
        clock_t timeStart = clock();                                
        for(long i=0; i< value; ++i)
        {
            try {
                snprintf(buf, 10, "%d", rand());
                c.push_front(string(buf));          
            }
            catch(exception& p) {
                cout << "i=" << i << " " << p.what() << endl;   
                abort();
            }
        }
        cout << "milli-seconds : " << (clock()-timeStart) << endl;          
    }                                                           
    }

    测试deque

    • 双向开口,是分段连续,感觉是连续的,其实不是。
    • 内存上两边都可以扩充
    • 每次512扩充,两边扩充申请buffer,buffer由指针指向
    • max_size由限制,使用全局的sort排序

    #include <deque>
    #include <stdexcept>
    #include <string>
    #include <cstdlib> //abort()
    #include <cstdio>  //snprintf()
    #include <iostream>
    #include <ctime> 
    namespace jj05
    {
    void test_deque(long& value)
    {
        cout << "
    test_deque().......... 
    ";
         
    deque<string> c;    
    char buf[10];
                
    clock_t timeStart = clock();                                
        for(long i=0; i< value; ++i)
        {
            try {
                snprintf(buf, 10, "%d", rand());
                c.push_back(string(buf));                       
            }
            catch(exception& p) {
                cout << "i=" << i << " " << p.what() << endl;   
                abort();
            }
        }
        cout << "milli-seconds : " << (clock()-timeStart) << endl;      
        cout << "deque.size()= " << c.size() << endl;
        cout << "deque.front()= " << c.front() << endl; 
        cout << "deque.back()= " << c.back() << endl;   
        cout << "deque.max_size()= " << c.max_size() << endl;   //1073741821    
        
    string target = get_a_target_string();  
        timeStart = clock();            
    auto pItem = find(c.begin(), c.end(), target);  
        cout << "std::find(), milli-seconds : " << (clock()-timeStart) << endl; 
        
        if (pItem != c.end())
            cout << "found, " << *pItem << endl;
        else
            cout << "not found! " << endl;  
            
        timeStart = clock();        
        sort(c.begin(), c.end());                       
        cout << "sort(), milli-seconds : " << (clock()-timeStart) << endl;      
        
        c.clear();
        test_moveable(deque<MyString>(),deque<MyStrNoMove>(), value);                               
    }                                                           
    }

    测试stack

    • 栈,数据结构上和deque差不多
    • 两段插入插入删除受限的容器
    • 也有人叫做容器的适配器adapter
    • 没有提供容器的迭代器iterator,否则对迭代器的操作会破坏堆栈的结构
    • 也没有提供find,sort的功能;但是有时候让你实现堆栈的排序操作

    #include <stack>
    #include <stdexcept>
    #include <string>
    #include <cstdlib> //abort()
    #include <cstdio>  //snprintf()
    #include <iostream>
    #include <ctime> 
    namespace jj17
    {
    void test_stack(long& value)
    {
        cout << "
    test_stack().......... 
    ";
         
    stack<string> c;    
    char buf[10];
                
    clock_t timeStart = clock();                                
        for(long i=0; i< value; ++i)
        {
            try {
                snprintf(buf, 10, "%d", rand());
                c.push(string(buf));                        
            }
            catch(exception& p) {
                cout << "i=" << i << " " << p.what() << endl;
                abort();
            }
        }
        cout << "milli-seconds : " << (clock()-timeStart) << endl;  
        cout << "stack.size()= " << c.size() << endl;
        cout << "stack.top()= " << c.top() << endl; 
        c.pop();
        cout << "stack.size()= " << c.size() << endl;
        cout << "stack.top()= " << c.top() << endl; 
        
        
        {
    stack<string, list<string>> c;      //以 list 為底層 
        for(long i=0; i< 10; ++i) {
                snprintf(buf, 10, "%d", rand());
                c.push(string(buf));                        
        }
        cout << "stack.size()= " << c.size() << endl;
        cout << "stack.top()= " << c.top() << endl; 
        c.pop();
        cout << "stack.size()= " << c.size() << endl;
        cout << "stack.top()= " << c.top() << endl; 
        }   
        
        {
    stack<string, vector<string>> c;    //以 vector 為底層 
        for(long i=0; i< 10; ++i) {
                snprintf(buf, 10, "%d", rand());
                c.push(string(buf));                        
        }
        cout << "stack.size()= " << c.size() << endl;
        cout << "stack.top()= " << c.top() << endl; 
        c.pop();
        cout << "stack.size()= " << c.size() << endl;
        cout << "stack.top()= " << c.top() << endl; 
        }
    
        {
    stack<string, set<string>> c;   //以 set 為底層 
    /*!
        for(long i=0; i< 10; ++i) {
                snprintf(buf, 10, "%d", rand());
                c.push(string(buf));                        
        }
        cout << "stack.size()= " << c.size() << endl;
        cout << "stack.top()= " << c.top() << endl; 
        c.pop();
        cout << "stack.size()= " << c.size() << endl;
        cout << "stack.top()= " << c.top() << endl; 
        
    //[Error] 'class std::set<std::basic_string<char> >' has no member named 'push_back'
    //[Error] 'class std::set<std::basic_string<char> >' has no member named 'back'
    //[Error] 'class std::set<std::basic_string<char> >' has no member named 'pop_back'
    */
        }
                
    //!stack<string, map(string>> c5;   ////以 map 為底層, [Error] template argument 2 is invalid
    //!stack<string>::iterator ite1;    //[Error] 'iterator' is not a member of 'std::stack<std::basic_string<char> >'
            
    }                                                           
    }

    测试queue

    • 堆,数据结构上有deque衍生出来的
    • 没有提供容器的迭代器iterator,否则对迭代器的操作会破坏堆栈的结构

    #include <queue>
    #include <stdexcept>
    #include <string>
    #include <cstdlib> //abort()
    #include <cstdio>  //snprintf()
    #include <iostream>
    #include <ctime> 
    namespace jj18
    {
    void test_queue(long& value)
    {
        cout << "
    test_queue().......... 
    ";
         
    queue<string> c;    
    char buf[10];
                
    clock_t timeStart = clock();                                
        for(long i=0; i< value; ++i)
        {
            try {
                snprintf(buf, 10, "%d", rand());
                c.push(string(buf));                        
            }
            catch(exception& p) {
                cout << "i=" << i << " " << p.what() << endl;
                abort();
            }
        }
        cout << "milli-seconds : " << (clock()-timeStart) << endl;  
        cout << "queue.size()= " << c.size() << endl;
        cout << "queue.front()= " << c.front() << endl; 
        cout << "queue.back()= " << c.back() << endl;       
        c.pop();
        cout << "queue.size()= " << c.size() << endl;
        cout << "queue.front()= " << c.front() << endl; 
        cout << "queue.back()= " << c.back() << endl;   
        
        
        {
    queue<string, list<string>> c;      //以 list 為底層 
        for(long i=0; i< 10; ++i) {
                snprintf(buf, 10, "%d", rand());
                c.push(string(buf));                        
        }
        cout << "queue.size()= " << c.size() << endl;
        cout << "queue.front()= " << c.front() << endl; 
        cout << "queue.back()= " << c.back() << endl;       
        c.pop();
        cout << "queue.size()= " << c.size() << endl;
        cout << "queue.front()= " << c.front() << endl; 
        cout << "queue.back()= " << c.back() << endl;   
        }   
        
        {
    queue<string, vector<string>> c;    //以 vector 為底層 
        for(long i=0; i< 10; ++i) {
                snprintf(buf, 10, "%d", rand());
                c.push(string(buf));                        
        }
        cout << "queue.size()= " << c.size() << endl;
        cout << "queue.front()= " << c.front() << endl; 
        cout << "queue.back()= " << c.back() << endl;       
        //!c.pop();  //[Error] 'class std::vector<std::basic_string<char> >' has no member named 'pop_front'
        cout << "queue.size()= " << c.size() << endl;
        cout << "queue.front()= " << c.front() << endl; 
        cout << "queue.back()= " << c.back() << endl;   
        }   
    
        {
    queue<string, set<string>> c;       //以 set 為底層 
    /*!
        for(long i=0; i< 10; ++i) {
                snprintf(buf, 10, "%d", rand());
                c.push(string(buf));                        
        }
        cout << "queue.size()= " << c.size() << endl;
        cout << "queue.front()= " << c.front() << endl; 
        cout << "queue.back()= " << c.back() << endl;       
        c.pop();
        cout << "queue.size()= " << c.size() << endl;
        cout << "queue.front()= " << c.front() << endl; 
        cout << "queue.back()= " << c.back() << endl;
    //[Error] 'class std::set<std::basic_string<char> >' has no member named 'push_back'
    //[Error] 'class std::set<std::basic_string<char> >' has no member named 'front'
    //[Error] 'class std::set<std::basic_string<char> >' has no member named 'pop_front'
    */      
        }
        
    //! queue<string, map<string>> c5;  //以 map 為底層, [Error] template argument 2 is invalid
    //! queue<string>::iterator ite1;   //[Error] 'iterator' is not a member of 'std::queue<std::basic_string<char> >'  
    }                                                           
    }
    C/C++基本语法学习 STL C++ primer
     
    分类: STL
  • 相关阅读:
    hdu 3440 House Man
    hdu 2018 母牛的故事
    poj 1639 Picnic Planning 度限制mst
    uva 10870
    矩阵快速幂 模板与简单讲解
    1118sync_binlog innodb_flush_log_at_trx_commit 浅析
    1117Mysql prepare预处理语句
    1116Xlinux初学习之正则表达式和通配符
    1111分析存储引擎
    1111MySQL配置参数详解
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/6922584.html
Copyright © 2011-2022 走看看