码迷,mamicode.com
首页 > 编程语言 > 详细

C++知识

时间:2015-09-26 17:17:43      阅读:482      评论:0      收藏:0      [点我收藏+]

标签:

获取本机所有ip

  1. #include <net/if.h>

  2. #include <netinet/in.h>

  3. #include <sys/socket.h>

  4. #include <linux/sockios.h>

  5. #include <sys/ioctl.h>

  6. #include <arpa/inet.h>

  7. ///获取主机的所有网卡的IP列表。0:成功;-1:失败

  8. static int getHostIpAddr(list<string>& ips){

  9.    int s;

  10.    struct ifconf conf;

  11.    struct ifreq *ifr;

  12.    char buff[BUFSIZ];

  13.    int num;

  14.    int i;

  15.    string ip;

  16.    s = socket(PF_INET, SOCK_DGRAM, 0);

  17.    conf.ifc_len = BUFSIZ;

  18.    conf.ifc_buf = buff;

  19.    ::ioctl(s, SIOCGIFCONF, &conf);

  20.    num = conf.ifc_len / sizeof(struct ifreq);

  21.    ifr = conf.ifc_req;

  22.    for(i=0;i < num;i++){

  23.        struct sockaddr_in *sin = (struct sockaddr_in *)(&ifr->ifr_addr);

  24.        ::ioctl(s, SIOCGIFFLAGS, ifr);

  25.        ip = inet_ntoa(sin->sin_addr);

  26.        ips.push_back(ip);

  27.        ifr++;

  28.    }

  29.    return 0;

  30. }


获得Unix/Linux系统中的IP、MAC地址等信息

实际环境和特殊需求往往会将简单问题复杂化,比如计算机IP地址,对于一个连接中socket,可以直接获得本端和对端的IP、端口信息。但在一些特殊场合 我们可能需要更多的信息,比如系统中有几块网卡,他们的Mac地址是多少,每块网卡分配了几个IP(一个网卡对应多个IP)等等。

这些信息往往需要通过ifconfig指令来获得,对于程序员来说,在代码中调用外部的shell指令可不是个最佳方案,因为没人能保障不同平台、不同版本的ifconfig指令输出的格式是一致的。本篇文章中将介绍通过ioctl函数实现上述需求。

 

  1. #include <sys/ioctl.h>
  2. int ioctl(int fd, int request, /* void *arg */);

返回:成功返回0,失败返回-1

ioctl函数的参数只有3个,但却是Unix中少有的几个“家族类”复杂函数,这里摘录一段《Unix网络编程》一书中对ioctl函数的描述:

在传统上ioctl函数是用于那些普遍使用、但不适合归入其他类别的任何特殊的系统接口……网络程序(一般是服务器程序)中ioctl常用于在程序启动时获得主机上所有接口的信息:接口的地址、接口是否支持广播、是否支持多播,等等。

ioctl 函数的第一个参数fd,可以表示一个打开的文件(文件句柄)或网络套接字,第二个和第三个参数体现了函数的家族特色,参数二request根据函数功能分 类定义了多组宏,而参数三总是一个指针,指针的类型依赖于参数二request。因为ioctl的种类实在太多,这里只列出和本文相关的几个参数定义:


分类参数二(宏)参数三描述
接口SIOCGIFCONFstruct ifconf获得所有接口列表
接口SIOCGIFADDRstruct ifreq获得接口地址
接口SIOCGIFFLAGSstruct ifreq获得接口标志
接口SIOCGIFBRDADDRstruct ifreq获得广播地址
接口SIOCGIFNETMASKstruct ifreq获得子网掩码

  1. // ioctl函数中的struct ifconf 和 struct ifreq结构关系
  2. // 通常运用ioctl函数的第一步是从内核获取系统的所有接口,然后再针对每个接口获取其地址信息。获取所有接口通过SIOCGIFCONF请求来实现:
  3. struct ifconf ifc;  /* ifconf结构 */
  4. struct ifreq ifrs[16];  /* ifreq结构数组(这里估计了接口的最大数量16) */
  5. /* 初始化ifconf结构 */
  6. ifc.ifc_len = sizeof(ifrs);
  7. ifc.ifc_buf = (caddr_t) ifrs;
  8. /* 获得接口列表 */
  9. ioctl(fd, SIOCGIFCONF, (char *) &ifc);
  10. // 获得了接口列表,就可以通过struct ifconf结构中*ifcu_req的指针得到struct ifreq结构数组的地址,通过遍历获得每隔接口的详细地址信息:
  11. printf("接口名称:%s/n", ifrs[n].ifr_name); /* 接口名称 */
  12. /* 获得IP地址 */
  13. ioctl(fd, SIOCGIFADDR, (char *) &ifrs[n]);
  14. printf("IP地址:%s/n",
  15.    (char*)inet_ntoa(((struct sockaddr_in*) (&ifrs[n].ifr_addr))->sin_addr));
  16. /* 获得子网掩码 */
  17. ioctl(fd, SIOCGIFNETMASK, (char *) &ifrs[n]);
  18. printf("子网掩码:%s/n",
  19.    (char*)inet_ntoa(((struct sockaddr_in*) (&ifrs[n].ifr_addr))->sin_addr));
  20. /* 获得广播地址 */
  21. ioctl(fd, SIOCGIFBRDADDR, (char *) &ifrs[n]);
  22. printf("广播地址:%s/n",
  23.    (char*)inet_ntoa(((struct sockaddr_in*) (&ifrs[n].ifr_addr))->sin_addr));
  24. /* 获得MAC地址 */
  25. ioctl(fd, SIOCGIFHWADDR, (char *) &ifrs[n]);
  26. printf("MAC地址:%02x:%02x:%02x:%02x:%02x:%02x/n",
  27.    (unsigned char) ifrs[n].ifr_hwaddr.sa_data[0],
  28.    (unsigned char) ifrs[n].ifr_hwaddr.sa_data[1],
  29.    (unsigned char) ifrs[n].ifr_hwaddr.sa_data[2],
  30.    (unsigned char) ifrs[n].ifr_hwaddr.sa_data[3],
  31.    (unsigned char) ifrs[n].ifr_hwaddr.sa_data[4],
  32.    (unsigned char) ifrs[n].ifr_hwaddr.sa_data[5]);
第一节 STL  算法
1. 算法头文件

算法的头文件共有三个,分别在<algorithm>,<numeric>,<funtional>

所有的算法均被定义在头文件algorithm中,关于数值运算的需要包含 numeric,而使用function object 和 function adapter  则必须包含funtional头文件。


算法注意事项

  1. 算法一般被设计用于处理一个区间,调用者需要提供 起点  和   终点。

  2. 调用者必须保证这个区间的有效性

  3. STL算法一般采用overwrite覆盖模式而非insert安插模式,所以,调用者必须保证有足够的空间。

  4. 如果需要使用插入模式,则需要手动使用insert iterator。

  5. 一些STL允许传入自定义操作;这些操作可以是普通函数,也可以是function object

  6. 当自定义操作返回boolean类型;被称作判断式predicate;可用于 查找,排序。

  7. 自定义操作还可以传递一个 unary predicate 作为准则,用于对某项元素实施某项操作。

  8. predicate不应该改变自身的状态。

  9. 后缀_if用来表示算法要求传入一个function object来作为判断准则;如果算法以额外参数的形式接受函数或函数对象,则没有后缀。

  10. 后缀_copy表示算法中不止对元素进行操作,还会复制到目标区间。


STL 算法分类

  • 非更易型算法   17

  • 更易型算法        7

  • 移除型算法        4

  • 变序型算法      12 

  • 排序算法           4

  • 已排序区间算法 9

  • 数值算法           4


2. 非更易型算法

1)for_each    用来对每个元素执行某操作

  1. for_each(InputIterator beg, InputIterator end, UnaryProc op)

    区 间:  [beg, end) 中的每个元素

    返回值:  op的一个拷贝

    复杂度:  线性

    注 意: for_each忽略op返回的任何值

  1. vecotr<int> col;

  2. INSERT_ELEMENTS(col 1,9);

  3. for_each(col.begin(), col.end(),

  4.     [](int& i){ i += 10; });


2)transform

  1. transform(InputIterator beg, InputIterator end, UnaryProc op);

    区 间:  [beg, end) 中的每个元素

    返回值:  op的一个拷贝

    复杂度:  线性, 较for_each 效率较低,因为要处理返回值

  1. vecotr<int> col;

  2. INSERT_ELEMENTS(col 1,9);

  3. transform(col.begin(), col.end(),

  4.     [](int i){  return i + 10; });

3)count, count_if


  1. difference_type count(InputIterator beg, InputIterator end, T& value);

  2. difference_type count_if(InputIterator beg, InputIterator end, UnaryProc op);

    区 间:  [beg, end) 中的每个元素

    作 用:  count 返回 和 value 相等的元素的元素个数,count_if 返回了令‘UnaryProc’ 为true的元素个数

    返回值:  difference_type 用来表现iterator间距的类型

    复杂度:  线性, 较for_each 效率较低,因为要处理返回值

    注 意: op不应该做任何改变元素值的动作。

  1. int num;

  2. vector<int> col;

  3. INSERT_ELEMENTS(col, 1, 9);

  4. num = count(col.begin(), col.end(), 4);

  5. cout << "count of elements equal to 4: " << num << endl;

  6. num = count(col.begin(), col.end(), [](int a){ return a > 4});

  7. cout << "count of elements great than 4: " << num << endl;

4)最大值与最小值

  1. ForwardIterator

  2. min_element(ForwardIterator beg, ForwardIterator end);

  3. ForwardIterator

  4. min_element(ForwardIterator beg, ForwardIterator end, CompFunc op);

  5. ForwardIterator

  6. max_element(ForwardIterator beg, ForwardIterator end);

  7. ForwardIterator

  8. max_element(ForwardIterator beg, ForwardIterator end, CompFunc op);

  9. std::pair<ForwardIterator, ForwardIterator>

  10. minmax_element(ForwardIterator beg, ForwardIterator end);

  11. std::pair<ForwardIterator, ForwardIterator>

  12. minmax_element(ForwardIterator beg, ForwardIterator end, CompFunc op);

    区 间:  [beg, end) 中的每个元素

    作 用:  所有上述算法分别返回区间中的最小元素位置,最大元素位置 或 最小和最大元素所在位置组成的pair

    返回值:  ForwardIterator 和 pair<ForwardIterator, ForwardIterator> 

    复杂度:  线性

    注 意: op不应该做任何改变元素值的动作。当存在多个最小值和最大值时,min_ 和 max_ 返回第一个,而minmax_ 返回第一个最小 值和最后一个最大值,所以 max_ 和 minmax_ 对于最大值的返回可能不同。

  1. std::vector<int> v;

  2. v.push_back(1);

  3. v.push_back(2);

  4. v.push_back(1);

  5. v.push_back(6);

  6. v.push_back(5);

  7. v.push_back(6);

  8. std::vector<int>::const_iterator min = min_element(v.cbegin(), v.cend());

  9. cout << *min << endl;

  10. std::vector<int>::const_iterator max = max_element(v.cbegin(), v.cend());

  11. std::vector<int>::const_iterator minmax = minmax_element(v.cbegin(), v.cend()).second;

  12. cout << distance(minmax, max) << endl;


5)查找元素

  1. InputIterator

  2. find(InputIterator beg, InputIterator end, const T& value)

  3. InputIterator

  4. find_if(InputIterator beg, InputIterator end, UnaryPredicate op)

  5. InputIterator

  6. find_if_not(InputIterator beg, InputIterator end, UnaryPredicate op)


    区 间:  [beg, end) 中的每个元素; find_if_not 始自 C++11

    作 用:  第一形式返回元素值等于value的元素位置,第二形式返回令op为true的元素位置,第三形式返回令op为false的元素的位置;没有找到,则返回end

    返回值:  InputIterator    

    复杂度:  线性

    注 意: op不应该做任何改变元素值的动作


6)查找前n个连续匹配的值

  1. ForwardIterator

  2. search_n(ForwardIterator beg, ForwardIterator end, Size count, const T& value);

  3. ForwardIterator

  4. search_n(ForwardIterator beg, ForwardIterator end, Size count, BinaryPredicate op);

    区 间:  [beg, end) 中的每个元素

    作 用:  第一形式返回"连续count个元素都等于value"中的第一个元素的位置,第二形式返回"连续count个元素都令op等于true"中的第一个元素的位置;没有则返回end

    返回值:  ForwardIterator    

    复杂度:  线性

    注 意: op不应该做任何改变元素值的动作

  1. std::vector<int> v;

  2. v.push_back(1);

  3. v.push_back(2);

  4. v.push_back(1);

  5. v.push_back(1);

  6. v.push_back(1);

  7. v.push_back(6);

  8. vector<int>::const_iterator ci = search_n(v.cbegin(), v.cend(), 3, 1);

  9. if(ci != v.cend())

  10. cout << distance(v.cbegin(), ci) << endl;


7)查找第一个子区间

  1. ForwardIterator1

  2. search(ForwardIterator1, beg, ForwardIterator1 end, ForwardIterator2 searchBeg, ForwardIterator2 searchEnd);

  3. ForwardIterator1

  4. search(ForwardIterator1, beg, ForwardIterator1 end, ForwardIterator2 searchBeg, ForwardIterator2 searchEnd, BinaryPredicate op);

    区 间:  [beg, end) 中的每个元素

    作 用:  第一形式返回"与[searchBeg, searchEnd)完全吻合的"的第一个子区间的第一个元素的位置,第二形式返回"元素与[searchBeg, searchEnd)中元素令op为true"的第一个子区间的第一个元素的位置;没有则返回end

    返回值:  ForwardIterator1    

    复杂度:  线性

    注 意: op不应该做任何改变元素值的动作

  1. std::vector<int> v{1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5};

  2. std::vector<int> sub{2, 3, 4};

  3. vector<int>::const_iterator pos = v.cbegin();

  4. pos = search(pos, v.cend(), sub.cbegin(), sub.cend());

  5. while(pos != v.end()){

  6. cout << "sub quare is at " << distance(v.cbegin(), pos) << endl;

  7. ++pos;

  8. pos = search(pos, v.cend(), sub.cbegin(), sub.cend());

  9. }

8)查找最后一个子区间

  1. ForwardIterator1

  2. find_end(ForwardIterator1 beg, ForwardIterator1 end, ForwardIterator2 searchBeg, ForwardIterator2 searchEnd);

  3. ForwardIterator1

  4. find_end(ForwardIterator1 beg, ForwardIterator1 end, ForwardIterator2 searchBeg, ForwardIterator2 searchEnd, BinaryPredicate op);

    区 间:  [beg, end) 中的每个元素

    作 用:  第一形式返回"与[searchBeg, searchEnd)完全吻合的"的最后一个子区间的第一个元素的位置,第二形式返回"元素与[searchBeg, searchEnd)中元素令op为true"的最后一个子区间的第一个元素的位置;没有则返回end

    返回值:  ForwardIterator1    

    复杂度:  线性

    注 意: op不应该做任何改变元素值的动作


9)查找某元素第一次出现地点

  1. InputIterator

  2. find_first_of(InputIterator beg, InputIterator end, ForwardIterator searchBeg, ForwardIterator searchEnd);

  3. InputIterator

  4. find_first_of(InputIterator beg, InputIterator end, ForwardIterator searchBeg, ForwardIterator searchEnd, BinaryPredicate op);

    区 间:  [beg, end) 中的每个元素

    作 用:  第一形式返回"即出现在[beg,end)又出现在[searchBeg,searchEnd)的"第一个元素的位置,第二形式返回"在[beg,end)中和在[searchBeg,searchEnd)的op动作均为true"第一个元素的位置;没有则返回end

    返回值:  InputIterator    

    复杂度:  线性

    注 意: op不应该做任何改变元素值的动作

10)查找两个连续且相等的元素

  1. ForwardIterator

  2. adjancet_find(ForwardIterator beg, ForwardIterator end);

  3. ForwardIterator

  4. adjancet_find(ForwardIterator beg, ForwardIterator end, BinaryPredicate op);

    区 间:  [beg, end) 中的每个元素

    作 用:  第一形式返回"第一对两个连续相等的元素"第一个元素的位置,第二形式返回"第一对两个连续元素都使op为true"第一个元素的位置;没有则返回end

    返回值:  ForwardIterator   

    复杂度:  线性

    注 意: op不应该做任何改变元素值的动作


11)查找第一处不同

  1. pair<InputIterator1, InputIterator2>

  2. mismatch(InputIterator1 beg, InputIterator1 end, InputIterator2 Cmpbeg);

  3. pair<InputIterator1, InputIterator2>

  4. mismatch(InputIterator1 beg, InputIterator1 end, InputIterator2 Cmpbeg, BinaryPredicate op);

    区 间:  [beg, end) 中的每个元素

    作 用:  忽略顺序,第一形式判断[beg,end)内元素和Cmpbeg开头的区间中第一组相异的元素,第二形式判断[beg,end)内元素和Cmpbeg开头的区间中第一组令op为false的元素

    返回值:  pair<InputIterator1, InputIterator2>;没有则返回InputIterator1的 end 和 Cmpbeg 对应元素组成的pair  

    复杂度:  最坏情况是 O(n2)

    注 意: op不应该做任何改变元素值的动作




12)检验相等

  1. bool

  2. equal(InputIterator1 beg, InputIterator1 end, InputIterator2 cmpBeg);

  3. bool

  4. equal(InputIterator1 beg, InputIterator1 end, InputIterator2 cmpBeg, BinaryPredicate op);

    区 间:  [beg, end) 中的每个元素

    作 用:  第一形式判断[beg,end)内元素和cmpBeg开头的区间中是否相等,第二形式判断[beg,end)内元素和cmpBeg开头的区间中是否都能令op为true;没有则返回end

    返回值:  ForwardIterator   

    复杂度:  线性

    注 意: op不应该做任何改变元素值的动作


13)测试不定序之相等

  1. bool

  2. is_permutation(ForwardIterator1 beg1, ForwardIterator1 end1, ForwardIterator2 beg2);

  3. bool

  4. is_permutation(ForwardIterator1 beg1, ForwardIterator1 end1, ForwardIterator2 beg2, CompFunc op);

    区 间:  [beg, end) 中的每个元素; 始自 C++11

    作 用:  忽略顺序,第一形式判断[beg1,end1)内元素和beg2开头的区间中是否相等,第二形式判断[beg1,end1)内元素和beg2开头的区间中是否都能令op为true;没有则返回end

    返回值:  ForwardIterator   

    复杂度:  最坏情况是 O(n2)

    注 意: op不应该做任何改变元素值的动作


14)检验小于

  1. bool

  2. lexicographical_compare(InputIterator1 beg1, InputIterator1 end, InputIterator2 beg2, InputIterator2 end2);

  3. bool

  4. lexicographical_compare(InputIterator1 beg1, InputIterator1 end, InputIterator2 beg2, InputIterator2 end2, CompFunc op);

    区 间:  [beg, end) 中的每个元素

    作 用:  两个形式都用来判断[beg1, end1)区间内的元素是否小于[beg2,end2)的元素;所谓小于,指‘字典次序’。字典比较:两序列元素一一比较,直到出现下面的情况:1.如果两元素不相等,则两元素的结果就是整个序列比较结果。2.如果两序列元素数量不同则较少元素序列小于另一序列。3.如果没有更多元素相比较,则两序列相等,返回false。

    返回值:  bool   

    复杂度:  线性

    注 意: op不应该做任何改变元素值的动作


14)检验是否排序

  1. bool

  2. is_sorted(ForwardIterator beg, ForwardIterator end);

  3. bool

  4. is_sorted(ForwardIterator beg, ForwardIterator end, BinaryPredicate op);

  5. ForwardIterator

  6. is_sorted_until(ForwardIterator beg, ForwardIterator end);

  7. ForwardIterator

  8. is_sorted_until(ForwardIterator beg, ForwardIterator end, BinryPredicate op);

    区 间:  [beg, end) 中的每个元素;始自C++11

    作 用:  is_sorted 检验区间内元素是否已经排序,或两相邻元素令op为true;is_sorted_until 检查第一个破坏排序元素的的位置,如果没有返回end。

    返回值:  bool  或 ForwardIterator

    复杂度:  线性

    注 意: op不应该做任何改变元素值的动作


15)检验是否分割

  1. bool

  2. is_partitioned(InputIterator beg, InputIterator end, UnaryPredicate op);

  3. ForwardIterator

  4. partition_point(ForwardIterator beg, ForwardIterator end, BinaryPredicate op);

    区 间:  [beg, end) 中的每个元素; 始自C++11

    作 用:  is_partitioned 判断区间内的元素是否被分割,即所有令op为true 的元素均在令op为false的元素之前;partition_point 返回分割点元素的位置。

    返回值:  bool  或 ForwardIterator

    复杂度:  is_partitioned 为线性;partition_point 至多为 O(logn) 否则为线性

    注 意: op不应该做任何改变元素值的动作


16)检验是否形成了Heap(最大堆)

  1. bool

  2. is_heap(RandomAccessIterator beg, RandomAccessIterator end);

  3. bool

  4. is_heap(RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op);

  5. RandomAccessIterator

  6. is_heap_until(RandomAccessIterator beg, RandomAccessIterator end);

  7. RandomAccessIterator

  8. is_heap_until(RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op);

    区 间:  [beg, end) 中的每个元素; 始自C++11

    作 用:  is_heap 检验区间内元素是否形成了一个heap。is_heap_until 检验第一个破坏heap的元素位置。第一和第三形式使用 '<'进行比较,第二和第四形式使用op进行比较。

    返回值:  bool  或 RandomAccessIterator

    复杂度:  线性

    注 意: op不应该做任何改变元素值的动作


17)检验All,Any 或 None

  1. bool

  2. all_of(InputIterator beg, InputIterator end, UnaryPredicate op);

  3. bool

  4. any_of(InputIterator beg, InputIterator end, UnaryPredicate op);

  5. bool

  6. none_of(InputIterator beg, InputIterator end, UnaryPredicate op);

    区 间:  [beg, end) 中的每个元素; 始自C++11

    作 用:  三个算法分别检查了区间中元素 全部 或 任何一个  或 没有  满足令op为true 的元素。

    返回值:  bool  或 RandomAccessIterator

    复杂度:  线性

    注 意: op不应该做任何改变元素值的动作


3)更易性算法

1)复制元素

  1. OutputIterator

  2. copy(InputIterator sourceBeg, InputIterator end,  OutputIterator destBeg);

  3. OutputIterator

  4. copy_if(InputIterator sourceBeg, InputIterator end,  OutputIterator destBeg, UnaryPredicate op);

  5. OutputIterator

  6. copy(InputIterator sourceBeg, Size num,  OutputIterator destBeg);

  7. BidrectionalIterator2

  8. copy_bakward(BidrectionalIterator1 soureBeg, BidrectionalIterator1 sourceEnd, BidrectionalIterator2 destEnd);

    区 间:  [beg, end) 中的每个元素; copy_n() 和 copy_if()始自C++11

    作 用:  四个算法均将区间内的元素拷贝到目标区,copy()正向遍历,copy_backward() 反向遍历。copy_n拷贝区间内的num个元素。copy_if()拷贝令op为true 的元素

    返回值:  OutputIterator 或 BidrectionalIterator2 均返回最后一个被拷贝元素的下一个元素的位置

    复杂度:  线性

    注 意: op不应该做任何改变元素值的动作;调用者需要保证dest有足够空间,否则请使用InsertIterator;目标区域不可以和源区域重合;自C++11起,如果源端元素不再被使用,请将copy用move替代;如果想在拷贝中反转元素次序,请使用reverse_copy() 会快些;partition_copy可以将复制到两个目标区间中。


2)搬移元素

  1. OutputIterator

  2. move(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg);

  3. BidirectionalIterator2

  4. move_backward(BidirectionalIterator1 sourceBeg, BidirectionalIterator1 sourceEnd, BidirectionalIterator2 destEnd);


    区 间:  [beg, end) 中的每个元素; 始自C++11

    作 用:  两个算法将源区间中所有的元素移动到目标区间,第一个正向拷贝,第二个反向拷贝

    返回值:  OutputIterator 或 BidrectionalIterator2 均返回最后一个被拷贝元素的下一个元素的位置

    复杂度:  线性

    注 意: 调用者需要保证dest有足够空间,否则请使用InsertIterator;目标区域不可以和源区域重合;算法对每个元素调用 *destElem = std::move(*sourceElem),如果源端元素提供移动语义,则它们从此不再明确,也不应该再被使用。如果没有提供移动语义,则使用copy,行为类似 copy() 和 copy_backward()。

  1. std::vector<string> v{"123","456","wangxiao"};

  2. array<string, 5> arr;

  3. move(v.begin(), v.end(), arr.begin());

  4. cout << "after v size " << v.size() << endl;

  5. for(auto a : arr){

  6. cout << a << endl;

  7. }

  8. for(auto a : v){

  9. cout << a << endl;

  10. }


3)互换元素

  1. ForwardIterator2

  2. swap_ranges(ForwardIterator1 beg1, ForwardIterator1 end1, ForwardIterator2 beg2);


    区 间:  [beg1, end1) 中的每个元素;

    作 用:  算法将区间内的元素和beg2开头的区间对应元素进行交换

    返回值:  OutputIterator 或 BidrectionalIterator2 均返回最后一个被拷贝元素的下一个元素的位置

    复杂度:  线性

    注 意: 调用者需要保证dest有足够空间,目标区域不可以和源区域重合;如果两个相同的容器互换元素,请使用swap()成员函数,它有O(1)的复杂度。


4)赋予相同的数值

  1. void

  2. fill(ForwardIterator beg, ForwardIterator end, const T& newValue);

  3. void

  4. fill_n(ForwardIterator beg,  Size num, const T& newValue);


    区 间:  [beg, end) 中的每个元素;   fill_n() 始自C++11

    作 用:  给区间的每一个元素都赋予新值newValue

    返回值:  void

    复杂度:  线性

    注 意: 如果想要赋予不同的值,使用 generate() 


4)赋予新生值

  1. void

  2. generate(ForwardIterator beg, ForwardIterator end, Func op);

  3. void

  4. generate_n(ForwardIterator beg, Size num, Func op);


    区 间:  [beg, end) 中的每个元素;   generate_n() 始自C++11

    作 用:  算法调用op产生新值赋给区间内的元素

    返回值:  void

    复杂度:  线性

    注 意: 确保目标区间有足够的元素

  1. std::vector<int> v;

  2. cout << "vector's cap: " << v.capacity() <<endl;

  3. int cap  = v.capacity() + 10;

  4. back_insert_iterator<vector<int>> iter(v);

  5. int aa = 0;

  6. generate_n(iter, cap, [&](){return ++aa;});

  7. cout << "vector's cap: " << v.capacity() <<endl;

  8. for( auto i : v){

  9. cout << i << endl;

  10. }


5)赋予递增的值

  1. void

  2. iota(ForwardIterator beg, ForwardIterator end, T startValue);


    区 间:  [beg, end) 中的每个元素;   始自C++11

    作 用:  赋予递增的值  startValue+1, startValue+2 ...

    返回值:  void

    复杂度:  线性

    注 意: 确保目标区间有足够的元素


6)替换元素

  1. void

  2. replace(ForwardIterator beg, ForwardIterator end, const T& oldValue, T& newValue);

  3. void

  4. replace_if(ForwardIterator beg, ForwardIterator end, UnaryPredicate op, T& newValue);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  第一形式替换每个与oldValue相等的元素到newValue;第二形式替换每个令op为true 的元素到newValue

    返回值:  void

    复杂度:  线性

    注 意: op不应该改变元素的值


7)复制并替换元素

  1. OutputIerator

  2. replace_copy(InputIterator srouceBeg, InputIterator sourceEnd, OutputIterator destBeg, const T& oldValue, const T& newValue);

  3. OutputIerator

  4. replace_copy(InputIterator srouceBeg, InputIterator sourceEnd, OutputIterator destBeg, UnaryPredicate op, const T& newValue);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  此函数是 replace 和copy 的结合体,将区间中的元素copy到destBeg开始的区间中,并将其值替换为newValue。第二形式则是将满足op为true 的元素copy,并替换为newValue.

    返回值:  OutputIterator

    复杂度:  线性

    注 意: op不应该改变元素的值;调用者需要保证有足够的空间


4. 移除型算法

1)移除某些元素

  1. ForwardIterator

  2. remove(ForwardIterator beg, ForwardIterator end, const T& value);

  3. ForwardIterator

  4. remove_if(ForwardIterator beg, ForwardIterator end, UnaryPredicate op);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  移除区间中和value相等的元素或 令op为true 的元素。

    返回值:  ForwardIterator  两个算法都返回区间的新逻辑终点

    复杂度:  线性

    注 意: op不应该改变元素的值;List提供了成员函数remove(),效率更高; associative 或 unordered 容器不适合使用,可以使用成员函数erase()。


2)复制时一并移除元素

  1. OutputIterator

  2. remove_copy(InputIterator soureBeg, InputIterator sourceEnd, OutputIterator destBeg, const T& value);

  3. OutputIterator

  4. remove_copy_if(InputIterator soureBeg, InputIterator sourceEnd, OutputIterator destBeg, UnaryPredicate op);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  移除区间中和value相等的元素或 令op为true 的元素,并将其拷贝到destBeg开始的区间中。

    返回值:  OutputIterator

    复杂度:  线性

    注 意: op不应该改变元素的值;List提供了成员函数remove(),效率更高; associative 或 unordered 容器不适合使用,可以使用成员函数erase()


3)移除重复的元素

  1. ForwardIterator

  2. unique(ForwardIterator beg, ForwardIterator end);

  3. ForwardIterator

  4. unique(ForwardIterator beg, ForwardIterator end, BinaryPredicate op);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  移除区间中连续重复的元素中多余的元素, 或 没有被处理掉的两个元素令op为true的元素。

    返回值:  ForwardIterator

    复杂度:  线性

    注 意: op不应该改变元素的值;List提供了成员函数unique(),效率更高; associative 或 unordered 容器不适合使用。


4)复制区间并移除重复元素

  1. OutputIterator

  2. unique_copy(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg);

  3. OutputIterator

  4. unique_copy(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg, BinaryPredicate op);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  复制区间并移除区间中连续重复的元素中多余的元素, 或 没有被处理掉的两个元素令op为true的元素。

    返回值:  OutputIterator

    复杂度:  线性

    注 意: op不应该改变元素的值;List提供了成员函数unique(),效率更高; associative 或 unordered 容器不适合使用。


5. 变序型算法

1)反转元素次序

  1. void

  2. reverse(BidrectionalIterator beg, BidirectionalIterator end);

  3. OutputIterator

  4. reverse_copy((BidrectionalIterator beg, BidirectionalIterator end, OutputIterator destBeg);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  reverse()会将区间中的元素反转,而reverse_copy()会倒序复制到destBeg中。

    返回值:  void 或 OutputIterator

    复杂度:  线性

    注 意: 调用者必须保证有足够的空间;List提供了成员函数reverse(),效率更高; associative 或 unordered 容器不适合使用。


2)旋转序列中的元素

  1. ForwardIterator

  2. rotate(ForwardIterator beg, ForwardIterator newBegin, ForwardIterator end);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  旋转区间中的元素,执行后 *newBegin 将成为第一元素。

    返回值:  ForwardIterator

    复杂度:  线性

    注 意:  C++11 之前返回 void。


3)复制并旋转序列中的元素

  1. OutputIterator

  2. rotate_copy(ForwardIterator sourceBeg, ForwardIterator newBeg, ForwardIterator sourceEnd, OutputIterator destBeg);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  将区间复制到destBeg开始的区间中,并旋转区间中的元素,执行后 *newBegin 将成为第一元素。

    返回值:  ForwardIterator

    复杂度:  线性

    注 意:  必须保证newBeg是区间中的一个,否则引发不确定行为;调用者必须确保有足够的空间,否则使用InsertIterator。


4)排列元素

  1. bool

  2. next_permutation(BidirectionalIterator beg, BidirectionalIterator end);

  3. bool

  4. next_permutation(BidirectionalIterator beg, BidirectionalIterator end, BinaryPredicate op);

  5. bool

  6. prev_permutation(BidirectionalIterator beg, BidirectionalIterator end);

  7. bool

  8. prev_permutation(BidirectionalIterator beg, BidirectionalIterator end, BinaryPredicate op);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  将区间内的元素排列为“下一次排列次序” 或 “上一次排列次序”;第一形式通过operator < 来比较,第二形式通过 op中如果 elem1 < elem2 ,它应返回true。

    返回值:  bool;当序列为升序时,next_permutation返回false;当序列为降序时,prev_permutation返回false

    复杂度:  线性

    注 意:  

  1. int main(){

  2. std::vector<int> v{3,2,1};

  3. while(next_permutation(v.begin(), v.end())){

  4. for(auto a : v){

  5. cout << a << " ";

  6. }

  7. cout << endl;

  8. }

  9. cout << "-------------" << endl;

  10. for(auto a : v){

  11. cout << a << " ";

  12. }

  13. }


5)使用随机数对元素进行洗牌

  1. void

  2. shuffle(RandomAccessItertor beg, RandomAccessItertor end, UniformRandomNumberGenerator&& eng);

  3. void

  4. random_shuffle(RandomAccessItertor beg, RandomAccessItertor end);

  5. void

  6. random_shuffle(RandomAccessItertor beg, RandomAccessItertor end, RandomFunc&& eng)


    区 间:  [beg, end) 中的每个元素;   第一形式 始自C++11

    作 用:  三种形式均打乱区间中的元素;第一种使用调用者指定的随机数引擎(具体请看《C++标准库之Engine》);第二形式使用一个均匀分布随机数产生出;第三种形式使用op提供的随机数,算法调用op(max),op应该返回一个 0 < x < max 的随机数 x。

    返回值:  bool;当序列为升序时,next_permutation返回false;当序列为降序时,prev_permutation返回false

    复杂度:  线性

    注 意:  shuffle() 最好不要传入一个临时创建的引擎;C++11之前 op声明为RandomFunc,所以不能传输一个临时对象或普通函数;旧式C全局函数的局部状态使用static存储,这对于多线程来说是不安全的,且不能创建两个独立的随机数流,建议使用FunctionObject可以有效解决。


6)将元素向前搬

  1. ForwardIterator

  2. partition(ForwardIterator beg, ForwardIterator end, UnaryPredicate op);

  3. BidirectionalIterator

  4. stable_partition(BidirectionalIterator beg, BidirectionalIterator end, UnaryPredicate op);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  两个函数均将令op为true 的元素向前移动,区别是无论元素是否满足给定条件,stable_partition()都会保持元素的相对顺序。

    返回值:  ForwardIterator 或 BidirectionalIterator;均返回 令op为false的第一个元素的位置。

    复杂度:  partition() 线性;stable_partition() 如果内存足够则为线性,否则为O(nlogn)

    注 意:  op不应改变元素的值


7)划分为两个子区间

  1. Pair<OutputIterator1, OutputIterator2>

  2. partition_copy(InputIterator sourebeg, InputIterator sourceEnd, OutputIterator1 destTrueBeg, OutputIterator2 destFalseBeg, UnaryPreidcate op);


    区 间:  [sourceBeg, sourceEnd) 中的每个元素;   

    作 用:  将区间中的元素令op为true的copy到destTrueBeg开始的区间中,令op为false的copy到destFalseBeg开始的区间中。

    返回值:  返回一个Pair,first是destTrueBeg,second是destFalseBeg。

    复杂度:  线性

    注 意:  op不应改变元素的值;调用者需要保证有足够的空间


8)对所有的元素排序

  1. void

  2. sort(RandomAccessIterator beg, RandomAccessIterator end);

  3. void

  4. sort(RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op);

  5. void

  6. stable_sort(RandomAccessIterator beg, RandomAccessIterator end);

  7. void

  8. stable_sort(RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  将区间中的元素进行排序,第一第三形式使用 operator < 进行排序;第二第四形式使用op,op(elem1, elem2)应返回elem1<emel2;sort和stable_sort的区别在于后者对相等的元素会在排序之后保持其相对位置。

    返回值:  void

    复杂度:  sort() 平均 O(nlogn); stable_sort() 如果内存足够为O(nlogn) 否则为 O(nlogn x logn)

    注 意:  op不应改变元素的值;


9)局部排序

  1. void

  2. partial_sort(RandomAccessIterator beg, RandomAcessIterator sortEnd, RandomAccessIterator end);

  3. void

  4. partial_sort(RandomAccessIterator beg, RandomAcessIterator sortEnd, RandomAccessIterator end, BinaryPredicate op);


    区 间:  [beg, sortEnd) 中的每个元素;   

    作 用:  将区间中的元素进行排序,第一形式使用 operator < 进行排序;第二形式使用op,op(elem1, elem2)应返回elem1<emel2;

    返回值:  void

    复杂度:  在线性 到  O(nlogn) 

    注 意:  op不应改变元素的值;


10)复制并局部排序

  1. RandomAccessIterator

  2. partial_sort_copy(InputIterator sourceBeg, InputIterator sourceEnd, RandomAccessIterator destBeg, RandomAccessIterator destEnd);

  3. RandomAccessIterator

  4. partial_sort_copy(InputIterator sourceBeg, InputIterator sourceEnd, RandomAccessIterator destBeg, RandomAccessIterator destEnd, BinaryPredicate op);


    区 间:  [beg, sortEnd) 中的每个元素;   

    作 用:  将区间中的元素copy到目标区间,然后进行对目标区间排序,第一形式使用 operator < 进行排序;第二形式使用op,op(elem1, elem2)应返回elem1<emel2;

    返回值:  RandomAccessIterator 最后一个被复制元素的下一位置

    复杂度:  在线性 到  O(nlogn) 

    注 意:  op不应改变元素的值;


11)根据第n个元素排序

  1. void

  2. nth_element(RandomAccessIterator beg, RandomAccessIterator nth, RandomAccessIterator end);

  3. void

  4. nth_element(RandomAccessIterator beg, RandomAccessIterator nth, RandomAccessIterator end, BinaryPredicate op);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  将区间中的元素将大于*nth的放在其后面,小于*nth的放在其前面;第一形式使用 operator < 进行排序;第二形式使用op,op(elem1, elem2)应返回elem1<emel2;

    返回值:  void

    复杂度:  平均为线性 

    注 意:  op不应改变元素的值;与partition()的区别请查看


12)Heap相关算法

  1. void

  2. make_heap(RandomAccessIterator beg, RandomAccessIterator end);

  3. void

  4. make_heap(RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op);

  5. void

  6. push_heap(RandomAccessIterator beg, RandomAccessIterator end);

  7. void

  8. push_heap(RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op);

  9. void

  10. pop_heap(RandomAccessIterator beg, RandomAccessIterator end);

  11. void

  12. pop_heap(RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op);

  13. void

  14. sort_heap(RandomAccessIterator beg, RandomAccessIterator end);

  15. void

  16. sort_heap(RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  Heap的第一个元素总是最大;

  • make_heap() 将区间内的元素转化为heap;

  • push_heap() 将end之前的最后一个元素加入原本就是heap的[beg, end -1)区间内,是整个区间重新变成一个heap;

  • pop_heap() 将最高元素移到最后的位置,并将剩余[beg,end-1)元素组成一个新的heap

  • sort_heap() 将区间内已经为heap的元素转换成一个已排序的序列

    返回值:  void

    复杂度:  make_heap() 线性;push_heap()对数;sort_heap()对数;

    注 意:  op不应改变元素的值;使用push_heap()必须保证区间已经是一个heap,pop_heap()与sort_heap()同理;


5. 已排序区间算法

1)查找元素

  1. bool

  2. binary_serarch(ForwardIterator beg, ForwardIterator end, const T& value);

  3. bool

  4. binary_serarch(ForwardIterator beg, ForwardIterator end, BinaryPredicate op);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  两个算法均用来判断是否包含和value等值的元素。op是可选的,视为排序准则,op(elem1, elem2)。

    返回值:   bool

    复杂度:  若搭配RandomAccessIterator则为logn,否则为线性 

    注 意:  op不应改变元素的值;若要获取元素的位置,请使用 lower_bound(),upper_bound() 或 equal_range();调用者必须保证区间已排序。


2)检查数个元素是否存在

  1. bool

  2. inlcudes(InputIterator1 beg, InputIterator1 end, InputIterator2 searchBeg, InputIterator2 searchEnd);

  3. bool

  4. inlcudes(InputIterator1 beg, InputIterator1 end, InputIterator2 searchBeg, InputIterator2 searchEnd, BinaryPredicate op);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  区间中是否包含另一排序区间[searchBeg,searchEnd)中的每个元素,即是否为其子集。

    返回值:   bool

    复杂度:  若搭配RandomAccessIterator则为logn,否则为线性 

    注 意:  op不应改变元素的值;若要获取元素的位置,请使用 lower_bound(),upper_bound() 或 equal_range();调用者必须保证区间已排序。


3)查找第一个或最后一个可能的位置

  1. ForwardIterator

  2. lower_bound(ForwardIterator beg, ForwardIterator end, const T&value);

  3. ForwardIterator

  4. lower_bound(ForwardIterator beg, ForwardIterator end, const T&value, BinaryPredicate op);

  5. ForwardIterator

  6. upper_bound(ForwardIterator beg, ForwardIterator end, const T&value);

  7. ForwardIterator

  8. upper_bound(ForwardIterator beg, ForwardIterator end, const T&value, BinaryPredicate op);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  lower_bound()返回了第一个“大于等于value”的元素的位置。这是可插入“元素值为value”且“不破坏区间已排序性”的第一个位置; upper_bound()返回了第一个“大于value”的元素的位置。这是可插入“元素值为value”且“不破坏区间已排序性”的最后一个位置。

    返回值:   如果不存在则都返回end。

    复杂度:  若搭配RandomAccessIterator则为logn,否则为线性 

    注 意:  op不应改变元素的值;若要获取lower_bound(),upper_bound() 两个函数的结果,请使用equal_range();调用者必须保证区间已排序;op可选作为排序基准。


4)查找第一个和最后一个可能的位置

  1. pair<ForwardIterator, ForwardIterator>

  2. equal_range(ForwardIterator beg, ForwardIterator end, const T& value);

  3. pair<ForwardIterator, ForwardIterator>

  4. equal_range(ForwardIterator beg, ForwardIterator end, const T& value, BinaryPredicate op);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  得到第一个“大于等于value”的元素的位置和第一个“大于value值”的位置,和下式等效“make_pair(lower_bound(...), upper_bound(...))”。

    返回值:  pair<ForwardIterator, ForwardIterator>

    复杂度:  若搭配RandomAccessIterator则为logn,否则为线性 

    注 意:  op不应改变元素的值;调用者必须保证区间已排序;op可选作为排序基准


5)合并两个已排序的集合

  1. OutputIterator

  2. merge(InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg);

  3. OutputIterator

  4. merge(InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg, BinaryPredicate op);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  将两个源区间的已排序序列合并到destBeg开始的目的区间中;目标区间所有的元素都处于排序下。
                   假设:

                        1 2 2 4 7 9

                        和

                        2 3 3 5 6

                    调用merge

                        1 2 2 2 3 3 4 5 6 7 9

    返回值:  OutputIterator 最后一个被复制元素 的下一个位置。

    复杂度:  线性 

    注 意:  op不应改变元素的值;调用者必须保证区间已排序;op可选作为排序基准;两个源区间不可重叠;调用者需要保证有足够的空间,否则使用InsertIterator;如果想要两个区间都有的元素只出现一次请使用 set_union()


6)两个已排序集合的并集

  1. OutputIterator

  2. set_union(InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg);

  3. OutputIterator

  4. set_union(InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg, BinaryPredicate op);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  将两个源区间的已排序序列合并到destBeg开始的目的区间中;目标区间所有的元素都处于排序下;目标区间的元素或是来自第一区间或是来自第二区间或是来自两者。
                   假设:

                        1 2 2 4 6 7 7 9

                        和

                        2 2 2 3 6 6 8 9

                    调用算法

                        1 2 2 2 3 4 6 6 7 7 8 9 

    返回值:  OutputIterator 最后一个被复制元素 的下一个位置。

    复杂度:  线性 

    注 意:  op不应改变元素的值;调用者必须保证区间已排序;op可选作为排序基准;两个源区间不可重叠;调用者需要保证有足够的空间,否则使用InsertIterator;


7)两个已排序集合的交集

  1. OutputIterator

  2. set_intersection(InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg);

  3. OutputIterator

  4. set_intersection(InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg, BinaryPrediate op);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  将两个源区间的已排序序列合并到destBeg开始的目的区间中;目标区间所有的元素都处于排序下;目标区间的元素同时存在于两个源区间中。
                   假设:

                        1 2 2 4 6 7 7 9

                        和

                        2 2 2 3 6 6 8 9

                    调用算法

                        2 2 6 9

    返回值:  OutputIterator 最后一个被复制元素 的下一个位置。

    复杂度:  线性 

    注 意:  op不应改变元素的值;调用者必须保证区间已排序;op可选作为排序基准;两个源区间不可重叠;调用者需要保证有足够的空间,否则使用InsertIterator;


8)两个已排序集合的差集

  1. OutputIterator

  2. set_difference(InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg);

  3. OutputIterator

  4. set_difference(InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg, BinaryPrediate op);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  将两个源区间的已排序序列合并到destBeg开始的目的区间中;目标区间所有的元素都处于排序下;目标区间的元素只存在于第一区间,不存在于第二区间。
                   假设:

                        1 2 2 4 6 7 7 9

                        和

                        2 2 2 3 6 6 8 9

                    调用算法

                        1 4 7 7 

    返回值:  OutputIterator 最后一个被复制元素 的下一个位置。

    复杂度:  线性 

    注 意:  op不应改变元素的值;调用者必须保证区间已排序;op可选作为排序基准;两个源区间不可重叠;调用者需要保证有足够的空间,否则使用InsertIterator;


  1. OutputIterator

  2. set_symmetric_difference(InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg);

  3. OutputIterator

  4. set_symmetric_difference(InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg, BinaryPrediate op);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  将两个源区间的已排序序列合并到destBeg开始的目的区间中;目标区间所有的元素都处于排序下;目标区间的元素或存在于第一区间,或存在于第二区间,没有两个区间都存在的元素。
                   假设:

                        1 2 2 4 6 7 7 9

                        和

                        2 2 2 3 6 6 8 9

                    调用算法

                        1 2 3 4 6 7 7 8

    返回值:  OutputIterator 最后一个被复制元素 的下一个位置。

    复杂度:  线性 

    注 意:  op不应改变元素的值;调用者必须保证区间已排序;op可选作为排序基准;两个源区间不可重叠;调用者需要保证有足够的空间,否则使用InsertIterator;


9)合并连贯值两个已排序区间

  1. void

  2. inplace_merge(BidirectionalIterator beg1, BidirectionalIterator end1beg2, BidirectionalIterator end2);

  3. void

  4. inplace_merge(BidirectionalIterator beg1, BidirectionalIterator end1beg2, BidirectionalIterator end2, BinaryPredicate op);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  将两个已排序区间[beg1, end1beg2), [end1beg2, end2) 合并成一个。

    返回值:   void

    复杂度:  内存足够为线性,否则为 nlogn 

    注 意:  op不应改变元素的值;调用者必须保证区间已排序;op可选作为排序基准;两个源区间不可重叠。



6. 数值算法


1)对数列进行某种运算

  1. T

  2. accumulate(InputIterator beg, InputIterator end, T initValue);

  3. T

  4. accumulate(InputIterator beg, InputIterator end, T initValue, BinaryFunc op);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  

  • 对于第一形式,相当于对于每个元素调用 initValue = initValue + elem;

  • 对于第二种形式,相当于对每个元素调用 initValue = op(initValue, elem);

    返回值:   T ;如果数列为空则返回 initValue

    复杂度:  线性  

    注 意:  op不应改变元素的值;


2)计算两数列的内积

  1. T

  2. inner_product(InputIterator1 beg1, InputIterator1 end1, InputIterator2 beg2, T initValue);

  3. T

  4. inner_product(InputIterator1 beg1, InputIterator1 end1, InputIterator2 beg2, T initValue, BinaryFunc op1, BinaryFunc op2);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  

  • 对于第一形式,相当于对于两个数列每个元素调用 initValue = initValue + elem1 * elem2;

  • 对于第二种形式,相当于对每个元素调用 initValue = op1(initValue, op2(elem1, elem2));

    返回值:   T ;如果数列为空则返回 initValue

    复杂度:  线性  

    注 意:  op不应改变元素的值;调用者确保beg2开始的区间中有足够的元素。


3)将相对值转换为绝对值

  1. OutputIterator
  2. partial_sum(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg);
  3. OutputIterator
  4. partial_sum(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg, BinaryFunc op);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  

  • 对于第一形式,计算每个元素的部分和,然后将结果写入以destBeg为起点的目标区间

  • 对于第二种形式,对每个元素和其先前所有的元素进行op运算

    返回值:   OutputIterator

    复杂度:  线性  

    注 意:  op不应改变元素的值;调用者确保区间中有足够的空间;源区间可以和目标区间重合


4)将绝对值转换为相对值

  1. OutputIterator
  2. adjacent_difference(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg);
  3. OutputIterator
  4. adjacent_difference(InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg, BinaryFunc op);


    区 间:  [beg, end) 中的每个元素;   

    作 用:  正与partial_sum作用相反

  • 对于第一形式,计算每个元素的部分差,相当于分别计算, a1 , a2 - a1, a3 - a2 .....

  • 对于第二种形式,对每个元素和其前一元素的op值,相当于分别计算  a1 , a2  op a1, a3 op a2 .....

    返回值:   OutputIterator

    复杂度:  线性  

    注 意:  op不应改变元素的值;调用者确保区间中有足够的空间;源区间可以和目标区间重合


STL迭代器


一、头文件: 

  1. 各容器自带

  2. <iterator>


二、迭代器种类

技术分享

迭代器种类能力提供者
Output 迭代器向前写入Ostream, inserter

Input 迭代器

向前读取一次Istream
Forward 迭代器向前读取Forward list、Unordered containers
Bidirectional 迭代器向前和向后读取

List, Set, Multiset, Map, multimap

Random-access 迭代器以随机访问方式读取Array, Vector, Deque, String, C-style array



注意:在对迭代器的递增和递减时有个奇怪的问题。

请看以下代码:

  1. std::vector<int> coll;

  2. ...

  3. std::sort(++coll.begin(), coll.end());


编译这个可能会失败,因为在有些实现版本上,vector、array、string通常被时限为普通pointer,而C++不允许你修改任何基础类型的临时值,对于struct 和 class 则允许;如果被时限为class则编译可以成功。

为了避免这个问题 c++提供了 next() 和 prev()。


三、编译器辅助函数

1. advance()
  1. void

  2. advance(InputIterator& pos, Dist n);


    作 用:  令pos的InputIterator前进或者后退n个元素。n为负值时,为后退

    返回值:  void

    注 意: 函数不检查迭代器的边界,调用者需保证前进或后退的迭代器有效。

2. next() 和 prev()
  1. ForwardIterator

  2. next(ForwardIterator pos);

  3. ForwardIterator

  4. next(ForwardIterator pos, Dist n);

  5. BidirectionalIterator

  6. prev(BidirectionalIterator pos);

  7. BidirectionalIterator

  8. prev(BidirectionalIterator pos, Dist n);


    作 用:  第一和第三形式分别 将pos迭代器 向前或向后移动一步;第二和第四形式分别将pos迭代器向前或向后移动n步。

    返回值:  void

    注 意: 函数不检查迭代器的边界,调用者需保证前进或后退的迭代器有效。


3. iter_swap()
  1. void

  2. iter_swap(ForwardIterator1 pos1, ForwardIterator2 pos2);


    作 用:  交换两个迭代器所指的值;迭代器类型不必相同,但其元素必须可以相互赋值。

    返回值:  void

    注 意: 。。。


四、迭代器适配器

1. Reverse 反向迭代器


Reverse迭代器重新定义了递增运算符和递减运算符,使其行为正好电脑,因此,使用这种迭代器可以反向处理数据。

生成方法:

  • 容器的成员函数rbegin() 和 rend() 各自返回一个reverse迭代器

  • 使用T::reverse_iterator 创造一个反向迭代器,或将一个Iterator 转换为 reverse_iterator

转回正常:

  • 可以运用base()成员函数转回正常迭代器, list<int>::const_iterator = rpos.base();


2. Insert 迭代器


也成为Inserter,用来将“赋予新值”动作转换为“安插新值”动作。

所有的Insert迭代器都隶属于Output迭代器种类。

Insert迭代器实现时候使用了两个技巧

  1. Operator * 被实现一个无用的no-op,仅仅返回*this。所以对于insert迭代器来说 pos 和 *pos等价,即 pos = value 和 *pos = value等价。但推荐使用第二个,语法规范。

  2. 赋值动作被转化为安插动作。实际上,在迭代器内部会调用push_back(),  push_front() 或 insert() 成员函数。


注意:递增也被实现为 no-op,你不可以改变此迭代器的位置


Insert迭代器的种类

C++标准库实现了三种Insert迭代器,区别在于安插的位置。事实上他们各自调用不同的成员函数。所以初始化的时候一定要指明是哪种迭代器。

名称Class名称其所调用的函数生成函数
Back Inserterback_insert_iteratorpush_back(value)back_inserter(cont)

Front Inserter

front_insert_iteratorpush_front(value)front_inserter(cont)
General Inserterinsert_iteratorinsert(pos, value)inserter(cont, pos)


Back Inserter     只支持 vector、deque、list 和 string。

Front Insert       只支持 deque、list、forward list

General Insert    除 array 和 forward list 都支持


所有Insert迭代器示例

  1. #include <iostream>

  2. #include <algorithm>

  3. #include <list>

  4. #include <array>

  5. #include <string>

  6. #include <iterator>

  7. using namespace std;

  8. template<typename T>

  9. void print_elem(T& con){

  10. for(auto n : con){

  11. cout << n << " ";

  12. }

  13. cout << endl << "-------------------" << endl;

  14. }

  15. int main(){

  16. std::list<int> v;

  17. back_insert_iterator<list<int>> biter(v);

  18. biter = 1;

  19. biter = 2;

  20. print_elem(v);

  21. back_inserter(v) = 3;

  22. back_inserter(v) = 4;

  23. print_elem(v);

  24. front_insert_iterator<list<int>> fiter(v);

  25. fiter = 9;

  26. fiter = 10;

  27. print_elem(v);

  28. front_inserter(v) = 11;

  29. front_inserter(v) = 12;

  30. print_elem(v);

  31. insert_iterator<list<int>> iter(v, v.begin());

  32. iter = 55;

  33. iter = 66;

  34. inserter(v, v.begin()) = 77;

  35. print_elem(v);

  36. }


3. Stream 串流迭代器


Stream迭代器是一个迭代器适配器,借由它,算法可以直接把stream座位来源段和目的端。例如:一个istream可以从input stream中读取元素,而ostream则可以用来对 outout steam 写入元素。


1)Ostream 迭代器


Ostream迭代器可以将 assigned value 写入 output stream。 其实现与 input stream的概念一致,唯一的区别是 Ostream 将赋值转化为output动作(通过 operator << )而input stream则相反。

表达式效果
ostream_iterator<T>(ostream)

为Ostream建立一个ostream迭代器

ostream_iterator<T>(ostream, delim)为Ostream建立一个ostream迭代器,各元素之间使用delim作为分隔符,其类型为 const char *
*iterop-op
iter = value将 value 写入到ostream
++iterno-op
iter++no-op


2)Istream 迭代器


表达式效果
istream_iterator<T>()建立一个 end-of-stream 迭代器
istream_iterator<T>(istream)为istream建立一个迭代器(可能会立即读取第一个值)
*iter返回此前读取的值,如果构造函数没有开始读,则本式执行读取动作
iter++读取下一个值,并返回其位置
++iter读取下一个值,但返回前一次的读取值
iter1 == iter2iter1和iter2是否相等(两者都是end-of-stream或都可以进行读取,且指向同一stream)
iter1 != iter2iter1 和 iter2 不等


代码示例:

  1. int main(){

  2. std::list<int> v;

  3. back_insert_iterator<list<int>> biter(v);

  4. istream_iterator<int> intReader(cin);

  5. istream_iterator<int> intEof;

  6. while(intReader != intEof){

  7. biter = *intReader;

  8. ++intReader;

  9. }

  10. copy(v.begin(), v.end(), ostream_iterator<int>(cout, " | "));

  11. cout << endl;

  12. return 0;

  13. }


4. Move 搬移迭代器


C++11中实现了一个新的迭代器适配器,可以将底层元素的处理转换为一个move操作。

代码示例:

  1. std::list<std::string> s;

  2. // 普通迭代器 复制 元素

  3. std::vector<string> v1(s.begin(), s.end());

  4. // 搬移迭代器迭代器 移动 元素

  5. std::vector<string> v1(make_move_iterator(s.begin()), make_move_iterator(s.end()));


注意:源区间的元素被move之后,再使用会引发未定义行为。调用者需保证只move一次。


5. Iterator Trait

迭代器可以区分为不同的类型(category)每个类型都代表特定的迭代器能力,如果能够根据不同的迭代器种类将操作行为进行重载,将会很有用。甚至很必要。通过迭代器标志(Iterator tag)和特性(trait 由<iterator>提供)可以重现这样的重载。

C++标准库为每个迭代器种类提供了一个迭代器标志,用来在位迭代器的标签:

  1. namespace std {
  2. struct output_iterator_tag {};
  3. struct iutput_iterator_tag {};
  4. struct forward_iterator_tag :
  5. public iutput_iterator_tag {
  6. };
  7. struct bidirectional_iterator_tag :
  8. public forward_iterator_tag {
  9. };
  10. struct random_access_iterator_tag :
  11. public bidirectional_iterator_tag {
  12. };
  13. }

在编写泛型代码时,你可能不只对迭代器的类型感兴趣,也会对元素的类型感兴趣。标准库提供了一个特殊的template结构来定义所谓的迭代器特性。该结构包含迭代器相关的所有信息,为迭代器应具备的类型定义提供了统一的接口:

  1. namespace std{
  2. template<typename T>
  3. struct iterator_trais {
  4. typedef typename T::iterator_caegory iterator_category;   //迭代器类型
  5. typedef typename T::value_type       value_type;    // 元素类型
  6. typedef typename T::difference_type  difference_type;
  7. typedef typename T::pointer          pointer;
  8. typedef typename T::reference        reference;
  9. };
  10. }

这个trait结构有两个优点:

  1. 确保每一个迭代器都提供了所有必要的类型定义

  2. 能够针对特定的迭代器实施特化

通过Iterator Trait 编写泛型代码(distance函数的实现)

  1. template <typename Iterator>
  2. typename std::iterator_traits<Iterator>::difference_type
  3. distance(Iterator pos1, Iterator pos2){
  4. return distance(pos1, pos2,
  5. std::iterator_traits<Iterator>::iterator_category());
  6. }
  7. template <typename RaIterator>
  8. typename std::iterator_traits<RaIterator>::difference_type
  9. distance(RaIterator pos1, RaIterator pos2,
  10. std::random_access_iterator_tag){
  11. return pos2 - pos1;
  12. }
  13. template <typename RaIterator>
  14. typename std::iterator_traits<RaIterator>::difference_type
  15. distance(RaIterator pos1, RaIterator pos2,
  16. std::input_iterator_tag){
  17. typename std::iterator_traits<RaIterator>::difference_type d;
  18. for(d = 0; pos1 != pos2; ++pos1; ++d){
  19. ;
  20. }
  21. return d;
  22. }











C++知识

标签:

原文地址:http://www.cnblogs.com/reposkeeper/p/4840960.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!