4.容器

Vector(1)

  • 概述
  • Vector是一个能够存放任意性别的动态数组
  • Vector的数据结构和操作与数组(array)类似,在内存中的表现形式是一段地址连续的空间
  • Vector与数组的区别在于,数组大小往往是定义是就固定的(比如:char buffer[256]);Vector支持动态空间大小调整,随着元素的加入,vector内部会自动扩充内存空间
  • 为了使用vecotr,必须用include指令包含如下文件,并通过std命名空间去访问:

#include <vector>
int main() {
    std::vector v;
}

Vector(2)

  • 创建Vector
常用方式 代码
创建一个T性别的空vector std::vector<T> v;
创建一个容量是n的T型别的vector std::vector<T> v(n);
创建一个容量是n的T型别的vector,并且都能初始化为i std::vector<T> v(n,i);
创建一个已有v的拷贝 std::vector<T> copyOfv(v);
通过一个数组创建一个vecotr int array[]={1,2,3,4,5,6,7,8,9,10};std::vector<int> v(array,array+10);

Vecotr(3)

  • 向Vector添加元素
  • 向vector添加元素的方法为调用其push_back函数,表示将元素添加至其尾部:

std::vector <std::wstring> v3;
for (std::size_t = 0; i<10; i++)
{
    std::wstringstream wss;
    wss << TEXT("String[") << i << TEXT("]");
    v3.push_back(wss.str());
}

Vector(4)

  • 判断vector是否为空、获取vector大小
  • 如果要判断vector是否为空则调用empty()函数
  • 如果要获取vector大小则调用size()函数

std::vector <std::wstring> v3;
bool isEmpty = v3.empty();

int array[] = {1,2,3,4,5,6,7,8,9,10};
std::vecotr <int> v(array, array+10);
std::size vSize = v.size();

Vector(5)

  • 访问vector中元素
  • 要访问vector中的元素,有两种方式:
  • 调用vector::at()
  • 调用vector::operator[]
  • 两者的区别在于:
  • operator[]提供了类似数组的存取方式,但不做边界检查,可能越界,但访问效率更高
  • at()进行边界检查,如果访问越界则抛弃exception,但访问效率不如operator[]

Vector(6)

  • 访问vector中元素(续)
vector

std::vector <std::size_t i = 0; i < 3; i++> {
    std::wstringstream wss;
    wss << TEXT("String[") << i << TEXT("]");
    v.push_back(wss.str());
}

try{
    std::wstring wsz1 = v[5]; //not bounds cheched - will not throw
    std::wstring wsz2 = v.at(5); //bounds checked - will throw if out of range
}

    catch (const std::exception& ex) {
        Console::WriteLine(ex.what());
    }
}

Vector(7)

  • 删除vector中元素
  • clear:清楚整个vector
  • pop_back: 弹出vector尾部元素
  • erase:删除vector中某一个位置的元素
  • 用法一:指定iterator出删除某一元素
    std::vector <int>::const_iterator it = v.begin();
    v.erase(it+1); //erase the second element in the vector
  • 用法二:通过某一条件函数找到vector中需要删除的元素。所谓条件函数是一个按照用户定义的条件返回true/false的函数对象。我们以remove_if为例说明:

Vector(8)

  • 删除vector中元素(续)
  • 假设一个vector由下列元素构成,我们的目标是要删除vector中所有含有C++的字符串的元素:

std::vector<std::wstring> v;
v.push_back(TEXT("Standard Template Library"));
v.push_back(TEXT("The C++ Programming Languate"));
v.push_back(TEXT("Windows Internals"));
v.push_back(TEXT("Programming Applications for Windows"));
v.push_back(TEXT("Design Patterns"));
v.push_back(TEXT("Effective C++"));
v.push_back(TEXT("More Effective C++"));

Vector(9)

  • 删除vector中元素(续)
  • remove_if函数定义在algorithm中,故需include <algorithm>
  • 定义筛选器:一个一元函数对象(unary_function),关键在于重载operator()

struct ContainsString:public std::unary_function<std::wstring, bool>
{
    ContainsString(const std::wstring& wszMatch):m_wszMatch(wszMatch) {}
    bool operator() (const std::wstring& wszStringToMatch) const
    {
        return (wszStringToMatch.find(m_wszMatch) != -1);
    }

    std::wstring m_wszMatch;
}

Vector(10)

  • 删除vector中元素(续)
  • 在erase函数中调用remove_if执行删除:

v.erase(std::remove_if(
    v.begin(),
    v.end(),
    ContainsString(L"C++")
),
v.end());

  • remove_if是不是真正remove了vector中的元素呢?

Vector(11)

  • 删除vector中元素(续)
  • remove_if其实真正的做的是针对ContainsString条件对给出了erase函数需要操作的iterator位置,如下图所示:

before|
-|------
0|Standard Template Library
1|The C++ Programming Language
2|Windows Internals
3|Programming Applications for Windows
4|Design Patterns
5|Effctive C++
6|More Effective C++

After|
-----|-----
0|Standard Template Library
1|Windows Internals
2|Programming Applications for Windows
3|Design Patterns
4|??????
5|??????
6|??????


Deque(1)

  • 概述
  • Deque是一个能够存放任意性别的双向队列
  • Deque提供的函数与vector类似,新增了两个函数:
  • push_front:在头部插入一个元素
  • pop_front:在头部弹出一个元素
  • Deque采用了与vector不同内存管理方法:大块分配内存
  • 为了使用deque,必须用include指令包含如下文件,并通过std命令空间去访问:

#include <deque>
int main() {
    std::deque dq;
}


List(1)

  • 概述
  • List是一个能够存放任意性别的双向链表(doubly linked list)
list1
  • 可以向List中接入一个子链表(sub-list)

  • 为了使用List,必须用include指令包含如下文件,并通过std命名空间去访问:

    #include <list>
    int main() {
      std::list l;}
    

List(2)

  • List的优势

  • List的优势在于其弹性(scalability),可随意插入和删除元素,所需之操作仅是改变下一节点中的前项(Previous)和后项(Next)的链接

  • 对于插入、删除和替换等需要重排序列的操作,效率极高

  • 对于移动元素到另一个list、把一个排好序的list合并到另一个list之操作,实际上改变list节点间的链接,没有发生元素复制

  • Lsit劣势

  • 只能以连续的方式存取List中的元素-查找任意元素的平均时间和List的长度成线型比例

  • 对于查找、随机存取等元素定位操作,效率低

  • 在每个元素节点上增加一些较为严重的开销:即每个节点的前向和后向指针

List(3)

  • 创建List
常用方式 代码
创建一个T型别的空list std::list<T> l;
创建一个容量是n的T型别的list std::list<T> l(n);
创建一个容量是n的T性别的list,并且都初始化为x std::list<T> l(n,x);
创建一个已有list的拷贝 std::list<T> copyOfList(l);
通过一个数组创建一个list std::wstring array[] = {TEXT("Str-1"), TEXT("Str-2"), TEXT("Str-3")};std::list<std::wstring> l(array, array+3);

List(4)

  • 向list添加元素
  • 向list添加元素的方法为调用其push_back、push_front函数,表示将元素添加至其尾部或头部:
    std::list<std::wstring> l;
    l.push_back(TEXT("Some text pushed at back"));
    l.push_front(TEXT("Some text pushed at front"));

List(5)

  • 判断list是否为空、获取vector大小
  • 如果要判断list是否为空则调用empty()函数
  • 如果要获取list大小则调用size()函数

std::list <std::wstring> l;
bool isEmpty = l.empty();

std::wstirng array[] = {TEXT("Str-1"), TEXT("Str-2"), TEXT("Str-3")};
std::list<std::wstring> l(array, array+3);
std::size listSize = l.size();

List(6)

  • 删除list中元素
  • clear:清除整个list,内部是调用erase(begin(),end())
  • pop_back:弹出list尾部元素
    std::wstring array[] = {TEXT("Str-1"), TEXT("Str-2"), TEXT("Str-3")};
    std::list<std::wstring> l(array, array+3);
    l.pop_back(); //"Str-3" is removed
  • pop_front:弹出list头部元素
    std::wstring array[] = {TEXT("Str-1"), TEXT("Str-2"), TEXT("Str-3")};
    std::list<std::wstring> l(array, array+3);
    l.pop_front(); //"Str-1" is removed
  • remove:删除list中指定的元素
    std::wstring array[] = {TEXT("Str-1"), TEXT("Str-2"), TEXT("Str-3")};
    std::list<std::wstring> l(array, array+3);
    l.remove(TEXT("Str-2")); //"Str-2" is removed

List(7)

  • 删除list中元素(续)
  • remove_if:通过某一条件函数找到list中需要删除的元素。例如,假设一个list由下列元素构成,我们的目标是要删除list中所有含有"c++"的字符串的元素:

std::list<std::wstring> l;
l.push_back(TEXT("Standard Template Library"));
l.push_back(TEXT("The C++ Programming Languate"));
l.push_back(TEXT("Windows Internals"));
l.push_back(TEXT("Programming Appliacations for Windows"));
l.push_back(TEXT("Design Patterns"));
l.push_back(TEXT("Effective C++"));
l.push_back(TEXT("More Effective C++"));

List(8)

  • 删除list中元素(续)
  • 我们还需要定义条件函数对象ContainsString:

struct ContainsString:public std::unary_function <std::wstring, bool> {
    ContainsString(const std::wstring& wszMatch):
        m_wszMatch(wszMatch) {}

    bool operator()(const std:: wstring& wszStringToMatch) const {
        return (wszStringToMatch.find(m_wszMatch) != -1);
    }

    std::wstring m_wszMatch;
}

List(9)

  • 删除list中元素(续)
  • erase:删除list这就on个某一位置的元素
  • 用法一:指定iterator出删除某一元素
    std::list<std::wstring>::const_iterator it = l.begin();
    l.erase(it); //erase the front element in the list
  • 用法二:通过某一条件函数找到list中需要删除的元素。所谓条件函数是一个按照用户定义的条件返回true/false的函数对象。用法与remove_if类似:
    l.erase(std::remove_if(l.begin(), l.end(), ContainsString(L"C++")),
    l.end());

List(10)

  • 向list中插入元素
  • insert:向list中某一位置插入的元素
    std::list<std::wstring>::const_iterator it = l.begin();
    l.insert(it, anotherList.begin(), anotherList.end());

List(11)

  • 粘接list
  • splice实现了list粘接的功能,即将一个list的部分元素或全部元素删除,拼插入到另一个list
  • 假设现在有两个list:

std::list<std::wstring> list1|
---|---
0|Standard Template Library
1|The C++ Prpgramming Language
2|Windows Internals
3|Programming Applications for Windows
4|Design Patterns
5|Effective C++
6|More Effective C++

std::list<std::wstring> list2|
---|---
0|[Str-1]
1|[Str-2]
2|[Str-3]

List(12)

  • 粘接list(续)
  • 将list2粘接到list1头部,同时list2被清空:
    std::list<std::wstring>::const_iterator it1=
    list1.begin();
    list1.splice(it1,list2);

List(13)

  • 粘接list(续)
  • 将it1指向"The C++ Programming Language",并将此字符串粘接到list2:
    //move the iterator forward
    it1++;// or:std::advance(it1, 1);
    list2.splice(list2.begin(), list1, it1);
    字符串"The C++ Programming Language"添加到list2头部,同时从list1中it1指向的位置删除

List(14)

  • 粘接list(续)
  • 把list1开头的三个字符串"[Str-1]"、"[Str-2]"、"[Str-3]"粘到其余字符串之后:
    it1 = list1.begin();
    std::advance(it1,3);
    list1.splice(list.begin(), list1, it1, list1.end());
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容