1.关于set

C++ STL 之所以得到广泛的赞誉,也被非常多人使用。不仅仅是提供了像vector, string, list等方便的容器,更重要的是STL封装了很多复杂的数据结构算法和大量经常使用数据结构操作。vector封装数组,list封装了链表。map和set封装了二叉树等。在封装这些数据结构的时候。STL依照程序猿的使用习惯。以成员函数方式提供的经常使用操作。如:插入、排序、删除、查找等。

让用户在STL使用过程中,并不会感到陌生。

关于set,必须说明的是set关联式容器。set作为一个容器也是用来存储同一数据类型的数据类型。并且能从一个数据集合中取出数据,在set中每一个元素的值都唯一,并且系统能依据元素的值自己主动进行排序。应该注意的是set中数元素的值不能直接被改变。C++ STL中标准关联容器set, multiset, map, multimap内部採用的就是一种很高效的平衡检索二叉树:红黑树,也成为RB树(Red-Black Tree)。RB树的统计性能要好于一般平衡二叉树,所以被STL选择作为了关联容器的内部结构。

关于set有以下几个问题:

(1)为何map和set的插入删除效率比用其它序列容器高?

大部分人说,非常easy。由于对于关联容器来说,不须要做内存拷贝和内存移动。

说对了,确实如此。

set容器内全部元素都是以节点的方式来存储。其节点结构和链表差点儿相同。指向父节点和子节点。

结构图可能例如以下:

  A

   / \

  B C

 / \ / \

  D E F G

因此插入的时候仅仅须要稍做变换。把节点的指针指向新的节点就能够了。

删除的时候类似。稍做变换后把指向删除节点的指针指向其它节点也OK了。

这里的一切操作就是指针换来换去,和内存移动没有关系。

(2)为何每次insert之后,曾经保存的iterator不会失效?

iterator这里就相当于指向节点的指针,内存没有变,指向内存的指针怎么会失效呢(当然被删除的那个元素本身已经失效了)。

相对于vector来说,每一次删除和插入,指针都有可能失效。调用push_back在尾部插入也是如此。由于为了保证内部数据的连续存放,iterator指向的那块内存在删除和插入过程中可能已经被其它内存覆盖或者内存已经被释放了。

即使时push_back的时候。容器内部空间可能不够。须要一块新的更大的内存,仅仅有把曾经的内存释放,申请新的更大的内存,复制已有的数据元素到新的内存。最后把须要插入的元素放到最后。那么曾经的内存指针自然就不可用了。特别时在和find等算法在一起使用的时候,牢记这个原则:不要使用过期的iterator。

(3)当数据元素增多时。set的插入和搜索速度变化怎样?

假设你知道log2的关系你应该就彻底了解这个答案。

在set中查找是使用二分查找。也就是说。假设有16个元素,最多须要比較4次就能找到结果,有32个元素,最多比較5次。那么有10000个呢?最多比較的次数为log10000,最多为14次,假设是20000个元素呢?最多只是15次。看见了吧。当数据量增大一倍的时候,搜索次数仅仅只是多了1次,多了1/14的搜索时间而已。

你明确这个道理后,就能够安心往里面放入元素了。

set用法:

begin()        ,返回set容器的第一个元素

end()      ,返回set容器的最后一个元素

clear()          ,删除set容器中的全部的元素

empty()    ,推断set容器是否为空

max_size()   ,返回set容器可能包括的元素最大个数

size()      ,返回当前set容器中的元素个数

rbegin     ,返回的值和end()同样

rend()     ,返回的值和rbegin()同样

简单操作实例:

#include <iostream>
#include <set> using namespace std; int main()
{
set<int> s;
s.insert(1);
s.insert(2);
s.insert(3);
s.insert(1);
cout<<"set 的 size 值为 :"<<s.size()<<endl;
cout<<"set 的 maxsize的值为 :"<<s.max_size()<<endl;
cout<<"set 中的第一个元素是 :"<<*s.begin()<<endl;
cout<<"set 中的最后一个元素是:"<<*s.end()<<endl;
s.clear();
if(s.empty())
{
cout<<"set 为空 。! ! "<<endl;
}
cout<<"set 的 size 值为 :"<<s.size()<<endl;
cout<<"set 的 maxsize的值为 :"<<s.max_size()<<endl;
return 0;
}

执行结果:

小结:插入3之后尽管插入了一个1,可是我们发现set中最后一个值仍然是3哈,这就是set 。还要注意begin() 和 end()函数是不检查set是否为空的。使用前最好使用empty()检验一下set是否为空.


count() 用来查找set中某个某个键值出现的次数。这个函数在set并非非常有用,由于一个键值在set仅仅可能出现0或1次,这样就变成了推断某一键值是否在set出现过了。

演示样例代码:

#include <iostream>
#include <set> using namespace std; int main()
{
set<int> s;
s.insert(1);
s.insert(2);
s.insert(3);
s.insert(1);
cout<<"set 中 1 出现的次数是 :"<<s.count(1)<<endl;
cout<<"set 中 4 出现的次数是 :"<<s.count(4)<<endl;
return 0;
}
按 Ctrl+C 复制代码

执行结果:

equal_range() ,返回一对定位器,分别表示第一个大于或等于给定关键值的元素和 第一个大于给定关键值的元素,这个返回值是一个pair类型,假设这一对定位器中哪个返回失败,就会等于end()的值。

详细这个有什么用途我还没遇到过~~~

演示样例代码:

#include <iostream>
#include <set> using namespace std; int main()
{
set<int> s;
set<int>::iterator iter;
for(int i = 1 ; i <= 5; ++i)
{
s.insert(i);
}
for(iter = s.begin() ; iter != s.end() ; ++iter)
{
cout<<*iter<<" ";
}
cout<<endl;
pair<set<int>::const_iterator,set<int>::const_iterator> pr;
pr = s.equal_range(3);
cout<<"第一个大于等于 3 的数是 :"<<*pr.first<<endl;
cout<<"第一个大于 3的数是 : "<<*pr.second<<endl;
return 0;
}

执行结果:

erase(iterator)  ,删除定位器iterator指向的值

erase(first,second),删除定位器first和second之间的值

erase(key_value),删除键值key_value的值

看看程序吧:

#include <iostream>
#include <set> using namespace std; int main()
{
set<int> s;
set<int>::const_iterator iter;
set<int>::iterator first;
set<int>::iterator second;
for(int i = 1 ; i <= 10 ; ++i)
{
s.insert(i);
}
//第一种删除
s.erase(s.begin());
//另外一种删除
first = s.begin();
second = s.begin();
second++;
second++;
s.erase(first,second);
//第三种删除
s.erase(8);
cout<<"删除后 set 中元素是 :";
for(iter = s.begin() ; iter != s.end() ; ++iter)
{
cout<<*iter<<" ";
}
cout<<endl;
return 0;
}

执行结果:

小结:set中的删除操作是不进行不论什么的错误检查的,比方定位器的是否合法等等,所以用的时候自己一定要注意。

find()  。返回给定值值得定位器。假设没找到则返回end()。

演示样例代码:

#include <iostream>
#include <set> using namespace std; int main()
{
int a[] = {1,2,3};
set<int> s(a,a+3);
set<int>::iterator iter;
if((iter = s.find(2)) != s.end())
{
cout<<*iter<<endl;
}
return 0;
}

insert(key_value); 将key_value插入到set中 。返回值是pair<set<int>::iterator,bool>,bool标志着插入是否成功,而iterator代表插入的位置。若key_value已经在set中,则iterator表示的key_value在set中的位置。

inset(first,second);将定位器first到second之间的元素插入到set中,返回值是void.

演示样例代码:

#include <iostream>
#include <set> using namespace std; int main()
{
int a[] = {1,2,3};
set<int> s;
set<int>::iterator iter;
s.insert(a,a+3);
for(iter = s.begin() ; iter != s.end() ; ++iter)
{
cout<<*iter<<" ";
}
cout<<endl;
pair<set<int>::iterator,bool> pr;
pr = s.insert(5);
if(pr.second)
{
cout<<*pr.first<<endl;
}
return 0;
}

执行结果:

lower_bound(key_value) ,返回第一个大于等于key_value的定位器

upper_bound(key_value)。返回最后一个大于等于key_value的定位器

演示样例代码:

#include <iostream>
#include <set> using namespace std; int main()
{
set<int> s;
s.insert(1);
s.insert(3);
s.insert(4);
cout<<*s.lower_bound(2)<<endl;
cout<<*s.lower_bound(3)<<endl;
cout<<*s.upper_bound(3)<<endl;
return 0;
}

执行结果:

本文转自它处。我认为我们可以。。。

版权声明:本文博客原创文章,博客,未经同意,不得转载。

STL中间set具体用法!!!!的更多相关文章

  1. STL中mem_fun, mem_fun_ref用法

    1.引言 先看一个STL中for_each的用法: #include <iostream> #include <vector> #include <algorithm&g ...

  2. STL之sstream的用法

    STL之sstream的用法 说在前面: 库定义了三种类:istringstream.ostringstream和stringstream,分别用来进行流的输入.输出和输入输出操作.另外,每个类都有一 ...

  3. STL中map的用法

    map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候 ...

  4. STL——map/unordered_map基础用法

    map /multimap map是STL里重要容器之一. 它的特性总结来讲就是:所有元素都会根据元素的键值key自动排序(也可根据自定义的仿函数进行自定义排序),其中的每个元素都是<key,  ...

  5. STL中erase()的用法

    erase()是STL提供的容器中比较常用的方法之一,它的功能是删除容器中的某些元素,其中它的函数原型如下: 1.有两个参数,且参数类型都是size_t型: string& erase ( s ...

  6. STL 之 map的用法

    Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候 ...

  7. STL源代码学习--vector用法汇总

    一.容器vector 使用vector你必须包含头文件<vector>: #include<vector> 型别vector是一个定义于namespace std内的templ ...

  8. STL中bitset的用法

    终于又来写博客了 == bitset存储的是二进数位,就和一个bool性数组差不多.用法上和数组的操作方式也差不多. 每位只占一个字节,大大优化了空间,可以通过数组形式访问. bitset定义 可以用 ...

  9. STL之list容器用法

    List 容器 list是C++标准模版库(STL,Standard Template Library)中的部分内容.实际上,list容器就是一个双向链表,可以高效地进行插入删除元素. 使用list容 ...

随机推荐

  1. hdu1159 LCS模板题

    题目分析 pid=1159">原题地址 最简单的最长公共子序列(LCS)问题的模板题了.不解释. ------------------------------------------- ...

  2. Ubuntu--有关VMware Tools安装问题

    虚拟机中找不到VMware Tools选项 在虚拟机上安装了ubuntu系统后,是不可以进行系统间数据共享的,也就是说我win7系统里的文件,不能拷贝到虚拟机的ubuntu系统. 解决方案:我们需要安 ...

  3. Codeforces Round #277.5 (Div. 2)---B. BerSU Ball (贪心)

    BerSU Ball time limit per test 1 second memory limit per test 256 megabytes input standard input out ...

  4. VMware vSphere 服务器虚拟化之二十六 桌面虚拟化之View Persona Management

    VMware vSphere 服务器虚拟化之二十六 桌面虚拟化之View Persona Management 实验失败告终,启动VMware View Persona Management服务报10 ...

  5. WPF弹性模拟动画

    原文:WPF弹性模拟动画 我们此次将要制作模拟物理中的弹性现象的交互动画,我们让一个小球向鼠标点击位置移动,这个移动的轨迹不是简单的位移,而是根据胡克定律计算得出的. 胡克定律:F=-kd F代表弹性 ...

  6. asp.net Login控件基本属性及事件说明

    原文:asp.net Login控件基本属性及事件说明 Login系列控件是微软为了简化我们的开发过程,为我们进行常规的安全开发提供块捷途径. Login系列控件包含下列控件: Login 登录控件 ...

  7. PHP类中的七种语法说明

    类中的七种语法说明 -属性 -静态属性 -方法 -静态方法 -类常量 -构造函数 -析构函数 <?php class Student { // 类里的属性.方法和函数的訪问权限有 (函数和方法是 ...

  8. lightoj1030(期望dp)

    有n个格子,初始的时候pos=1,然后丢骰子,然后新的pos为pos+骰子的点数,走到新的pos,可以捡走该pos上的黄金. 特殊的是,如果新的pos超过了n,那么是不会走的,要重新丢骰子. 所以要分 ...

  9. uIP中国的协议文件:Ch01

    uIP0.9 参考 by Doxygen 1.3.3 Tue Oct 7 15:51:00 2003 译: fishOnFly(鱼在飞) uIP-refman中文pdf下载 第1章  uIP TCP/ ...

  10. Windows Phone开发(27):隔离存储A

    原文:Windows Phone开发(27):隔离存储A 在很多资料或书籍上都翻译为"独立存储",不过,我想了一下,决定将IsolatedStorage翻译为"隔离存储& ...