• 6.5-数据结构&算法-标准模板STL/STL容器/向量


    一、标准模板库(STL)
    1.定义了一系列的容器模板,实现泛型化的数据结构。
    1)向量(vector),内存连续,支持下标访问和随机迭代,只有在尾部进行插入和删除效率才比较高。
    2)列表(list),内存不连续,不支持下标访问和随机迭代,在任何位置进行插入和删除效率都很高。
    3)双端队列(deque),内存连续,支持下标访问和随机迭代,在首尾两端进行插入和删除效率都比较高。
    以上三种合称为线性容器。
    4)堆栈(stack),后进先出
    5)队列(queue),先进先出
    6)优先队列(priority_queue),优者先出
    以上三种合称为适配器容器,通过某种线性容器适配。
    7)映射(map),键值对(KVP)的集合,按键升序,键唯一。
    8)集合(set),没有值只有键的映射。
    9)多重映射(multimap),允许重复键的映射。
    10)多重集合(multiset),没有值只有键的多重映射。
    以上四种合称为关联容器。通过有序树表达数据的关联性。
    2.泛型函数
    template<typename T>
    void swap (T& a, T& b) {
      T c = a;
      a = b;
      b = c;
    }
    template<typename IT>
    void print (IT begin, IT end) {
      while (begin != end)
        cout << *begin++ << ' ';
      cout << endl;
    }
    int a[5] = {1, 2, 3, 4, 5};
    print (a, a + 5);
    List list;
    list.push_back (...);
    ...
    print (list.begin (), list.end ());
    3.实用工具
    auto_ptr
    string
    pair
     
    二、STL容器共性
    1.所有的容器都支持拷贝构造和拷贝赋值,可以完整意义上的容器对象副本。
    2.所有的容器都支持“==”运算符。容器的相等:容器的类型相同,容器中元素的类型相同,容器中元素的个数相等,对应元素还要满足相等性的判断。
    3.容器中元素都是放入源对象拷贝。
    int b;
    int a[3];
    a[0] = b;
     
    4.容器中元素需要支持完整的拷贝语义。auto_ptr不适合放在容器中使用。
    5.如果需要对容器的元素进行排序或者查找操作,该元素的类型还需要支持“<”和“==”操作符。
     
    三、向量(vector)
    1.基本特点
    1)连续内存和下标访问
    2)动态内存管理
    int a[10];
    int *b = new int[10];
    3)通过预分配内存空间减小动态内存管理的额外开销
    4)可以再随机位置做插入和删除,但只有在接近尾部的操作才是高效的。
    2.定义变量
    #include <vector>
    using namespace std;
    vector<int> vi;
    vector<string> vs;
    3.迭代器
    vector<...>::iterator - 正向迭代器
    vector<...>::const_iterator - 常正向迭代器
    vector<...>::reverse_iterator - 反向迭代器
    vector<...>::const_reverse_iterator - 常反向迭代器
    向量的四种迭代器都是随机迭代器,可以和整数做加减运算。
    通过vector<...>调用,begin()返回起始迭代器,end()返回终止迭代器,最后一个元素的下一个位置。rbegin()返回起始反向迭代器,rend()返回终止反向迭代器。
    通过const vector<...>&/*调用以上函数,返回的将是const_iterator/const_reverse_interator。
    4.预分配和初始化
    vector<int> vi (10);
    将vi初始化10个int元素,初始值为0。
    vector<类> vc (10);
    将vi初始化10个类类型的元素,通过无参构造函数初始化。
    vector<int> vi (10, 8);
    将vi初始化10个int元素,初始值为8。
    vector<类> vc (10, 类 (...));
    将vi初始化10个类类型的元素,通过拷贝构造函数初始化。
    5.size()/resize()/clear()/capacity()/reserve()
    size() - 获取元素个数,而不是容量。
    resize() - 增减元素的个数,增引发构造,减引发析构。如果在新增元素时发现当前容量不够,自动扩容。但是在减少元素时不会自动收缩容量。
    clear() - 清空所有的元素,导致析构。同样不会自动收缩容量。
    capacity() - 获取容量,以元素为单位。
    reserve() - 手动扩容。新增部分不做初始化。
    6.insert()/erase()/sort()/find()
    insert()/erase() - 根据迭代器参数做插入和删除。
    sort()/find() - 全局算法函数,排序(快速)和查找
    7.类类型对象的向量
    1)无参构造
    2)拷贝构造
    3)拷贝赋值
    4)operator==:find
    5)operator</operator基本类型/比较器
    练习:编写程序读取m.dat中的电影票房记录,找出票房前十名,按票房从高到低的顺序写入另一文件中。
     
    四、双端队列(deque)
    1.连续内存,下标访问和随机迭代,在首尾两端都可以进行高效的增删。
    2.因为要维护首尾两端的开放性,因此双端队列和向量相比,其空间和时间复杂度要略高一些。
    3.比vector多了push_front/pop_front,少了reserve。
    五、列表(list)
    front/back
    push_front/pop_front
    push_back/pop_back
    insert/erase/remove
    size
    1.sort
    2.unique - 将连续出现的相同元素唯一化。
    23 35 35 35 60 12 35 35 99 35 22
    |unique
    V
    23 35 60 12 35 99 35 22
    3.splice - 将参数链表的部分或全部剪切到调用链表的特定位置。
    void splice (
      iterator pos,
      list&    lst);
    list1.splice (pos, list2);
    将list2中的全部数据剪切到list1的pos处。
    void splice (
      iterator pos,
      list     &lst,
      iterator del);
    将list2中del所指向数据剪切到list1的pos处。
    void splice (
      iterator pos,
      list&    lst,
      iterator start,
      iterator end );
    将list2中start和end之间的数据剪切到list1的pos处。
    class.cpp
    #include <vector>
    #include <algorithm>
    #include "print.h"
    class A {
    public:
        A (int i = 0) : m_i (i) {
            cout << "无参构造:" << this << endl;
        }
        A (const A& that) : m_i (that.m_i) {
            cout << "拷贝构造:" << &that << "->" << this
                << endl;
        }
        A& operator= (const A& that) {
            cout << "拷贝赋值:" << &that << "->" << this
                << endl;
            if (&that != this)
                m_i = that.m_i;
            return *this;
        }
        ~A (void) {
            cout << "析构函数:" << this << endl;
        }
        operator int& (void) {
            return m_i;
        }
        /*
        operator const int& (void) const {
            return static_cast<int&> (
                const_cast<A&> (*this));
        }
        */
        bool operator== (const A& that) const {
            return m_i == that.m_i;
        }
        /*
        bool operator< (const A& that) const {
            return m_i < that.m_i;
        }
        */
        bool operator() (const A& a, const A& b) const {
            return a.m_i < b.m_i;
        }
    private:
        int m_i;
    };
    int main (void) {
        cout << "---- 1 ----" << endl;
        vector<A> va (3);
        cout << "---- 2 ----" << endl;
        va.push_back (A ());
        cout << "---- 3 ----" << endl;
        va.erase (va.begin ());
        cout << "---- 0 ----" << endl;
        va[0] = A (10);
        va[1] = A (50);
        va[2] = A (70);
        va.push_back (A (60));
        vector<A>::iterator it = find (va.begin (),
            va.end (), A (70));
        if (it == va.end ())
            cout << "没找到!" << endl;
        else
            cout << "找到了:" << *it << endl;
    //    sort (va.begin (), va.end ());
        sort (va.begin (), va.end (), va[0]);
        print (va.begin (), va.end ());
        return 0;
    }
    deque.cpp
    #include <deque>
    #include <algorithm>
    #include "print.h"
    int main (void) {
        deque<int> di;
        di.push_back (24);
        di.push_back (33);
        di.push_front (18);
        di.push_front (68);
        di.insert (di.begin () + 2, 47);
        print (di.begin (), di.end ()); // 68 18 47 24 33
        di.pop_back ();
        di.pop_front ();
        di.erase (di.begin () + 1);
        print (di.begin (), di.end ()); // 18 24
        di.push_back (20);
        sort (di.begin (), di.end ());
        print (di.begin (), di.end ()); // 18 20 24
        size_t size = di.size ();
        for (size_t i = 0; i < size; ++i)
            cout << di[i] << ' ';
        cout << endl;
        di.resize (10);
        print (di.begin (), di.end ());
        return 0;
    }

    fe.cpp

    #include <iostream>
    //#include <algorithm>
    using namespace std;
    template<typename IT, typename DOIT>
    void for_each (IT begin, IT end, DOIT doit) {
        while (begin != end)
            doit (*begin++);
    }
    void print (int& x) {
        cout << x << endl;
    }
    void add (int& x) {
        ++x;
    }
    int main (void) {
        int a[5] = {1, 2, 3, 4, 5};
        for_each (a, a + 5, print);
        for_each (a, a + 5, add);
        for_each (a, a + 5, print);
        return 0;
    }
    insert.cpp
    #include <algorithm>
    #include <vector>
    #include "print.h"
    template<typename iterator, typename type>
    iterator find (iterator begin, iterator end,
        const type& key) {
        for (; begin != end; ++begin)
            if (*begin == key)
                break;
        return begin;
    }    
    bool cmpInt (const int& a, const int& b) {
        return a > b;
    }
    class CmpInt {
    public:
        CmpInt (bool less = true) : m_less (less) {}
        bool operator() (const int& a, const int& b) const{
            return m_less ? (a < b) : (a > b);
        }
    private:
        bool m_less;
    };
    int main (void) {
        int ai[] = {10, 20, 30, 40, 50};
        vector<int> vi (ai, &ai[5]);
        print (vi.begin (), vi.end ());
        vector<int>::iterator it = vi.begin ();
        it = vi.insert (it + 1, 15);
        print (vi.begin (), vi.end ());
        ++++++it;
        it = vi.erase (it);
        print (vi.begin (), vi.end ());
        cout << *it << endl; // 50
        vi.insert (vi.begin (), 37);
        vi.insert (vi.begin () + 2, 43);
        vi.insert (vi.begin () + 4, 29);
        vi.push_back (18);
        vi.push_back (24);
        print (vi.begin (), vi.end ());
        sort (vi.begin (), vi.end ());
        print (vi.begin (), vi.end ());
        sort (vi.begin (), vi.end (),
            /*cmpInt*/CmpInt (false));
        print (vi.begin (), vi.end ());
        it = ::find (vi.begin (), vi.end (), 18);
        if (it == vi.end ())
            cout << "没找到!" << endl;
        else
            cout << "找到了:" << *it << endl;
        return 0;
    }

    list.cpp

    #include <list>
    #include "print.h"
    int main (void) {
        list<int> li;
        li.push_back (34);
        li.push_back (28);
        li.push_back (34);
        li.push_back (34);
        li.push_back (55);
        li.push_back (34);
        print (li.begin (), li.end ());
        li.unique ();
        print (li.begin (), li.end ());
        li.sort ();
        print (li.begin (), li.end ());
        li.unique ();
        print (li.begin (), li.end ());
        list<int> li2;
        li2.push_front (100);
        li2.push_front (200);
        li2.push_front (300);
        list<int>::iterator pos = li.begin ();
        ++pos;
    //    li.splice (pos, li2);
        list<int>::iterator start = li2.begin ();
        ++start;
    //    li.splice (pos, li2, start);
        list<int>::iterator end = li2.end ();
        li.splice (pos, li2, start, end);
        print (li.begin (), li.end ());
        cout << li2.size () << endl;
        return 0;
    }
    print.h
    #ifndef _PRINT_H
    #define _PRINT_H
    #include <iostream>
    using namespace std;
    template<typename iterator>
    void print (iterator begin, iterator end) {
        while (begin != end)
            cout << *begin++ << ' ';
        cout << endl;
    }
    #endif // _PRINT_H
    size.cpp
    #include <iostream>
    #include <vector>
    using namespace std;
    void print (const vector<int>& vi) {
        cout << "大小:" << vi.size () << endl;
        cout << "容量:" << vi.capacity () << endl;
        for (vector<int>::const_iterator it = vi.begin ();
            it != vi.end (); ++it)
            cout << *it << ' ';
        cout << endl;
    }
    int main (void) {
        vector<int> vi (5, 3);
        print (vi);
        vi.push_back (4);
        print (vi);
        vi[6] = 100;
        cout << vi[6] << endl;
        vi.push_back (5);
        cout << vi[6] << endl;
        vi.resize (12);
        print (vi);
        vi.resize (2);
        print (vi);
        vi.clear ();
        print (vi);
        vi.reserve (20);
        print (vi);
        cout << vi[19] << endl;
        vi.reserve (5);
        print (vi);
        return 0;
    }
    top.cpp
    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    class Movie {
    public:
        friend istream& operator>> (istream& is,
            Movie& movie) {
            return is >> movie.m_title >> movie.m_comp
                >> movie.m_gross;
        }
        friend ostream& operator<< (ostream& os,
            const Movie& movie) {
            return os << movie.m_title << ' '
                << movie.m_comp << ' ' << movie.m_gross;
        }
        bool operator< (const Movie& movie) const {
            return gross () > movie.gross ();
        }
    private:
        double gross (void) const {
            string str (m_gross);
            size_t pos = 0;
            while ((pos = str.find_first_of ("$,", pos)) !=
                string::npos)
                str.erase (pos, 1);
            return atof (str.c_str ());
        }
        string m_title;
        string m_comp;
        string m_gross;
    };
    bool read (const char* file, vector<Movie>& vm) {
        ifstream ifs (file);
        if (! ifs) {
            perror ("打开票房文件失败");
            return false;
        }
        Movie movie;
        while (ifs >> movie)
            vm.push_back (movie);
        ifs.close ();
        return true;
    }
    bool write (const char* file, const vector<Movie>& vm){
        ofstream ofs (file);
        if (! ofs) {
            perror ("打开排行文件失败");
            return false;
        }
        for (vector<Movie>::const_iterator it = vm.begin();
            it != vm.end (); ++it)
            ofs << *it << endl;
        ofs.close ();
        return true;
    }
    int main (int argc, char* argv[]) {
        if (argc < 3) {
            cerr << "用法:" << argv[0]
                << " <票房文件> <排行文件>" << endl;
            return -1;
        }
        vector<Movie> vm;
        if (! read (argv[1], vm))
            return -1;
        sort (vm.begin (), vm.end ());
        if (vm.size () > 10)
            vm.resize (10);
        if (! write (argv[2], vm))
            return -1;
        return 0;
    }
    vector.cpp
    #include <iostream>
    #include <vector>
    using namespace std;
    class A {
    public:
        A (int i = 0) : m_i (i) {};
        int m_i;
    };
    void print (const vector<int>& vi) {
        size_t size = vi.size ();
        cout << size << endl;
        for (size_t i = 0; i < size; ++i)
            cout << vi[i] << ' ';
        cout << endl;
    }
    int main (void) {
        vector<int> vi;
        vi.push_back (10);
        vi.push_back (20);
        vi.push_back (30);
        vi.push_back (20);
        vi.push_back (10);
        print (vi);
        vi.pop_back ();
        print (vi);
        ++vi.front ();
        vi.back () = 100;
        cout << vi.front () << ' ' << vi.back () << endl;
        typedef vector<int>::iterator IT;
        typedef vector<int>::const_iterator CIT;
        typedef vector<int>::reverse_iterator RIT;
        typedef vector<int>::const_reverse_iterator CRIT;
        for (IT it = vi.begin (); it != vi.end (); ++it)
            ++*it;
        const vector<int>& cvi = vi;
        for (CIT it = cvi.begin (); it != cvi.end (); ++it)
            cout << /*--*/*it << ' ';
        cout << endl;
        for (CRIT it = cvi.rbegin (); it!=cvi.rend(); ++it)
            cout << *it << ' ';
        cout << endl;
        vector<string> vs;
        vs.push_back ("beijing");
        vs.push_back ("tianjin");
        vs.push_back ("shanghai");
        cout << *(vs.begin () + 2) << endl;
        *const_cast<char*> ((vs.end () - 1)->c_str ())='S';
        cout << *(vs.end () - 1) << endl;
        vector<int> vi2 (10);
        print (vi2);
        vector<A> va (10);
        for (vector<A>::const_iterator it = va.begin ();
            it != va.end (); ++it)
            cout << it->m_i << ' ';
        cout << endl;
        vector<int> vi3 (10, 8);
        print (vi3);
        vector<A> va2 (10, A (8));
        for (vector<A>::const_iterator it = va2.begin ();
            it != va2.end (); ++it)
            cout << it->m_i << ' ';
        cout << endl;
        return 0;
    }
     
     
     
  • 相关阅读:
    Asp.net MVC中表单验证属性的使用
    asp.net mvc3用file上传文件大小限制问题
    Asp.net MVC中ReturnUrl的使用
    Asp.net mvc+EF+Sql Server2008数据库缓存依赖
    .Net有哪些大型项目、大型网站的案例?
    Canvas 继续学习
    React 表单与事件
    React Ajax
    React生命周期
    React 添加一个事件
  • 原文地址:https://www.cnblogs.com/xuxaut-558/p/10028408.html
Copyright © 2020-2023  润新知