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;
}

原文地址:https://www.cnblogs.com/xuxaut-558/p/10028408.html

时间: 2024-11-05 16:11:06

6.5-数据结构&算法-标准模板STL/STL容器/向量的相关文章

C++的标准模板库STL中实现的数据结构之顺序表vector的分析与使用

摘要 本文主要借助对C++的标准模板库STL中实现的数据结构的学习和使用来加深对数据结构的理解.即联系数据结构的理论分析和详细的应用实现(STL),本文是系列总结的第一篇,主要针对线性表中的顺序表(动态数组)STL vector进行分析和总结. 引言 因为前段时间对台大的机器学习基石和技法课程进行了学习,发如今详细的实现中经常涉及到各种类型的数据结构,比方线性表.二叉树.图等,在使用这些数据结构时感到有些吃力.主要是对一些主要的数据结构理解的不够.所以趁着暑假假期.近期一段时间总会抽出时间复习一

标准模板库(STL)学习探究之vector容器

标准模板库(STL)学习探究之vector容器  C++ Vectors vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库.vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据.为了可以使用vector,必须在你的头文件中包含下面的代码:#include <vector>构造函数. Vectors 包含着一系列连续存储的元素,其行为和数组类

八、C++ 标准模板库-STL概述

C++ 标准模板库-STL概述 一.基本概念 1.1 泛型程序设计 C++ 语言的核心优势之一就是便于软件的重用,重用在两个方面有体现: 面向对象的思想:继承和多态,标准类库 泛型程序设计(generic programming) 的思想: 模板机制,以及标准模板库 STL 简单地说就是使用模板的程序设计法.将一些常用的数据结构(比如链表,数组,二叉树)和算法(比如排序,查找)写成模板,以后则不论数据结构里放的是什么对象,算法针对什么样的对象,则都不必重新实现数据结构,重新编写算法. 标准模板库

标准模板库--STL

标准模板库STL 1.泛型程序设计 C++ 语言的核心优势之一就是便于软件的重用 C++中有两个方面体现重用: 1.面向对象的思想:继承和多态,标准类库 2.泛型程序设计(generic programming) 的思想: 模板机制,以及标准模板库STL 简单地说就是使用模板的程序设计法. 将一些常用的数据结构(比如链表,数组,二叉树)和算法(比如排序,查找)写成模板,以后则不论数据结构里放的是什么对象,算法针对什么样的对象,则都不必重新实现数据结构,重新编写算法.标准模板库 (Standard

PKU C++程序设计实习 学习笔记6 标准模板库STL

标准模板库STL 8.1 STL概述 1.泛型程序设计 C++ 语言的核心优势之一就是便于软件的重用 C++中有两个方面体现重用:1.面向对象的思想:继承和多态,标准类库  2.泛型程序设计(generic programming) 的思想: 模板机制,以及标准模板库 STL 简单地说就是使用模板的程序设计法. 将一些常用的数据结构(比如链表,数组,二叉树)和算法(比如排序,查找)写成模板,以后则不论数据结构里放的是什么对象,算法针对什么样的对象,则都不必重新实现数据结构,重新编写算法. 标准模

实验8 标准模板库STL

一.实验目的与要求: 了解标准模板库STL中的容器.迭代器.函数对象和算法等基本概念. 掌握STL,并能应用STL解决实际问题. 二.实验过程: 完成实验8标准模板库STL中练习题,见:http://acm.hpu.edu.cn/contest.php?cid=1020,密码c++08,共有5道题.将答题过程简单记录到实验过程中. 将答题结果写到实验结果中,并根据答题结果进行分析.反思,将其写到实验分析中,并写上实验时间.

C++ 标准模板库STL 队列 queue 使用方法与应用介绍

C++ 标准模板库STL 队列 queue 使用方法与应用介绍 queue queue模板类的定义在<queue>头文件中. 与stack模板类很相似,queue模板类也需要两个模板参数,一个是元素类型,一个容器类型,元素类型是必要的,容器类型是可选的,默认为deque类型. 定义queue对象的示例代码如下: queue<int> q1; queue<double> q2; queue的基本操作有: 入队,如例:q.push(x); 将x接到队列的末端. 出队,如例:

C++笔记(6):标准模板库STL:容器、迭代器和算法

STL(Standard Template Library)是C++标准库的一部分.STL的代码从广义上讲分为三类:容器.迭代器和算法. 1.容器 2.迭代器 3.算法  -------------------------------------------------------------------------------------------------------------------------- 1.容器 顺序容器容器是特定类型对象的集合.顺序容器为程序员提供控制元素存储和访问

C++标准模板库-STL库基本算法

原文链接:http://blog.csdn.net/wangfengwf/article/details/11580989#t9 16.4  STL库基本算法 标准C++STL库中算法组件为一个很重要的组成部分,该组件提供了大多数最常见的通用算法的实现,并且这些实现是经过很多测试试验并被公认在处理上是高效的.将这些最常见的算法通用化实现,最大的优势就是开发者在应用中不需要为具体的常见算法的实现而费神,只需要包含相应的头文件直接使用即可,不仅仅提高的软件开发的效率,同时还有助于软件重用性的提高.