C++容器类库-2017-7-18

容器类库

常见的容器,如vector、list、map、set、queue、stack、deque、multimap、multiset等,基本可以满足日常的开发需要。C++11引入了定长数组array,具有C风格数据的特性,更有C++的便利操作;还有unordered_set、unordered_map等新的非排序容器,可以适应不需要排序的场景。


Vector:

在c++中,vector是一个十分有用的容器,下面对这个容器做一下总结。

1 基本操作

(1)头文件#include<vector>.

(2)创建vector对象,vector<int> vec;

(3)尾部插入数字:vec.push_back(a);

(4)使用下标访问元素,cout<<vec[0]<<endl;记住下标是从0开始的。

(5)使用迭代器访问元素.

vector<int>::iterator it;
for(it=vec.begin();it!=vec.end();it++)
    cout<<*it<<endl;

(6)插入元素:    vec.insert(vec.begin()+i,a);在第i+1个元素前面插入a;

(7)删除元素:    vec.erase(vec.begin()+2);删除第3个元素

vec.erase(vec.begin()+i,vec.end()+j);删除区间[i,j-1];区间从0开始

(8)向量大小:vec.size();

(9)清空:vec.clear();

2

vector的元素不仅仅可以使int,double,string,还可以是结构体,但是要注意:结构体要定义为全局的,否则会出错。下面是一段简短的程序代码:

C++ operator关键字(重载操作符)

一、为什么使用操作符重载?
对于系统的所有操作符,一般情况下,只支持基本数据类型和标准库中提供的class,对于用户自己定义的class,如果想支持基本操作,比如比较大小,判断是否相等,等等,则需要用户自己来定义关于这个操作符的具体实现。比如,判断两个人是否一样大,我们默认的规则是按照其年龄来比较,所以,在设计person 这个class的时候,我们需要考虑操作符==,而且,根据刚才的分析,比较的依据应该是age。那么为什么叫重载呢?这是因为,在编译器实现的时候,已经为我们提供了这个操作符的基本数据类型实现版本,但是现在他的操作数变成了用户定义的数据类型class,所以,需要用户自己来提供该参数版本的实现。

#include <stdio.h>
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;

typedef struct rect{   //类型别名,结构体,结构体的定义必须是全局的
 int id;
 int length;
 int width;
 //对于向量元素是结构体的,可在结构体内部定义比较函数,下面按照id,length,width升序排序。
 //操作符重载
 bool operator< (const rect &a) const{
  if (id!= a.id)
   return id < a.id;
  else{
   if (length != a.length)
    return length < a.length;
   else
    return width < a.width;
  }

 }
}Rect;

int main(){
 vector<Rect> vec;
 Rect rect;
 rect.id = 1;
 rect.length = 2;
 rect.width = 3;
 vec.push_back(rect);
 vector<Rect>::iterator it = vec.begin();
 cout << (*it).id << ' ' << (*it).length << ' ' << (*it).width << endl;
 return 0;

}

 3  算法

(1) 使用reverse将元素翻转:需要头文件#include<algorithm>

reverse(vec.begin(),vec.end());将元素翻转(在vector中,如果一个函数中需要两个迭代器,

一般后一个都不包含.)

(2)使用sort排序:需要头文件#include<algorithm>,

sort(vec.begin(),vec.end());(默认是按升序排列,即从小到大).

可以通过重写排序比较函数按照降序比较,如下:

定义排序比较函数:

bool Comp(const int &a,const int &b)
{
    return a>b;
}
调用时:sort(vec.begin(),vec.end(),Comp),这样就降序排序。


list:

 list是一个线性双向链表结构,它的数据由若干个节点构成,每一个节点都包括一个信息块(即实际存储的数据)、一个前驱指针和一个后驱指针。它无需分配指定的内存大小且可以任意伸缩,这是因为它存储在非连续的内存空间中,并且由指针将有序的元素链接起来。由于其结构的原因,list 随机检索的性能非常的不好,因为它不像vector 那样直接找到元素的地址,而是要从头一个一个的顺序查找,这样目标元素越靠后,它的检索时间就越长。检索时间与目标元素的位置成正比。虽然随机检索的速度不够快,但是它可以迅速地在任何节点进行插入和删除操作。因为list 的每个节点保存着它在链表中的位置,插入或删除一个元素仅对最多三个元素有所影响,不像vector 会对操作点之后的所有元素的存储地址都有所影响,这一点是vector 不可比拟的。

list 的特点:

(1) 不使用连续的内存空间这样可以随意地进行动态操作;
(2) 可以在内部任何位置快速地插入或删除,当然也可以在两端进行push 和pop 。
(3) 不能进行内部的随机访问,即不支持[ ] 操作符和vector.at() ;
(4) 相对于verctor 占用更多的内存。

初学list:需要掌握的知识:

(1)定义一个list 

(2)向list中加入元素 

(3)如何知道list是否为空 

(4)如何使用for循环来遍历一个list 

(5)如何使用STL的通用算法for_each来遍历list 

(6)list成员函数begin() 和 end() 以及它们的意义 

(7)iterator范围的概念和一个范围的最后一个位置实际上并不被处理这一事实 

第一:定义,插入,遍历打印。

    代码实现如下:

#include<stdio.h>
#include<iostream>
#include<list>
#include<string>
#include<algorithm>
using namespace std;

void PrintIt(string& StringToPoint)   //字符串
{
 cout << StringToPoint << endl;
}

int main()
{

 list<string> test;   //声明一个列表

 list<string>::iterator testiterator; //声明一个迭代器

 test.push_back("no");
 test.push_back("march");
 test.push_front("ok");
 test.push_front("loleina");
 test.push_front("begin");
 test.push_back("end");

 for (testiterator = test.begin(); testiterator != test.end(); ++testiterator)
 {
  cout << *testiterator << endl;
 }
 cout << "-------------" << endl;


 for_each(test.begin(), test.end(), PrintIt);   //使用了STL的通用算法for_each()来遍历,操作被很好的打包了,代码更加清晰了
 cout << "-------------" << endl;

 system("PAUSE");
 return 0;
}

定义了一个字符串类型的list。需要包含提供STL的 list类的头文件#include <list>即可;list的成员函数push_back()把一个对象放到一个list的后面,而 push_front()把对象放到前面。

我们想要遍历一个list,比如打印一个list中的所有对象来看看list上不同操作的结果。要一个元素一个元素的遍历一个list, 可以这样做:

A. 这个程序定义了一个iterator(类似指针),testiterator。它指向了这个list的第一个元素。 这可以调用testiterator.begin()来做到,它会返回一个指向list开头的iterator。然后把它和testiterator.end()的 返回值来做比较,到了那儿的时候就停下来。 容器的end()函数会返回一个指向容器的最后一个位置的iterator。 在上面的例子中,每一次执行for循环,我们就重复引用iterator来得到我们打印的字符串。

    注意:不能用testiterator.begin()+2来指向list中的第三个对象,因为STL的list是以双链的list来实现的,所有的数据存放不一定是连续存放的。 它不支持随机存取。

B.使用STL的通用算法for_each()来遍历一个iterator的范围,然后调用PrintIt()来处理每个对象。 不需要初始化、比较和给iterator增量。for_each()完成了这些工作。执行于对象上的操作被很好的 打包在这个函数以外了,不用再做那样的循环了,代码更加清晰了。

第二:count()和count_if() 的基本使用

     STL的通用算法count()和count_it()用来给容器中的对象记数。就象for_each()一样,count()和count_if() 算法也是在iterator范围内来做的。

#include<stdio.h>
#include<iostream>
#include<list>
#include<string>
#include<algorithm>
using namespace std;

class IsLoleina    //判别类
{ <

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值