stl algorithm -- sort ,unique

在写私信群聊代码的时候碰到怎么把一个vector<Int> 元素unique化的问题,基本上就是需要下面这么做,用<algorithm>中的,先sort再unique

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <vector>
 4 #include <stdio.h>
 5 using namespace std;
 6 void print(vector<int>& vec);
 7 int main(){
 8     int a[] = {1,3,4,4,6,3,2,5,6,2};
 9     vector<int> vec(a, a+10);
10     print(vec);
11     vector<int>::iterator it;
12     sort(vec.begin(), vec.end());
13     print(vec);
14     it = unique(vec.begin(), vec.end());
15 //    printf("%p\n", &vec);
16     vec.resize(it-vec.begin());
17 //    printf("%p\n", &vec);
18     print(vec);
19     printf("%p\n", &vec);
20     vec.resize(23, 22);
21     printf("%p\n", &vec);
22     print(vec);
23 
24 }
25 void print(vector<int>& vec){
26     for(vector<int>::iterator it = vec.begin(); it != vec.end(); it++){
27         cout << *it << "  ";
28     }
29     cout << endl;
30 }

运行结果 :

1 3 4 4 6 3 2 5 6 2
1 2 2 3 3 4 4 5 6 6
1 2 3 4 5 6
0x7fffa2daab30
0x7fffa2daab30
1 2 3 4 5 6 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22

 

注意20行的 resize,  resize是sequence containers(vector, list, deque)共有的一个方法,它把vector扩展或缩小到参数指定的那么大,从20行可以看到它可以带2个参数,第二个指定如果扩展的话要复制过去的对象, 可以看到resize之后vector的地址是不变的,即使是扩大,注意19行输出地址的方式, "%p"意味着要接一个void*型的参数

有些方法是某种container所特有的,比如list自己就有sort,它还自己定义了几种算法,unique,merge,reverse,只有list有,可能是它自身特性决定的吧,它自己来实现比一般性的algorithm来得好, vector所特有的是capacity, reserve   参考http://www.cplusplus.com/reference/stl/

 

2  试着写下上面unique的实现算法,sort的我没有写出来

 1 #include<iostream>
 2 #include<vector>
 3 #include<algorithm>
 4 using namespace std;
 5 void print(vector<int>& vec);
 6 template <class InputIterator>
 7 InputIterator unique_wy(InputIterator begin, InputIterator end){
typename iterator_traits<InputIterator>::value_type value = *begin;
cout << "in unique wy *begin = " << value << endl;
8 InputIterator last = begin; 9 while(++begin != end){ 10 if (*last != *begin){ 11 *++last = *begin; 12 } 13 } 14 return ++last; 15 } 16 int main(){ 17 int a[] = {1,1,2,2,4,6,7,7,4}; 18 vector<int> vec(a, a+9); 19 print(vec); 20 // sort_wy(vec.begin(), vec.end()); 21 // print(vec); 22 vector<int>::iterator it = unique_wy(vec.begin(), vec.end()); 23 vec.resize(it-vec.begin()); 24 print(vec); 25 return 0; 26 } 27 void print(vector<int>& vec){ 28 for(vector<int>::iterator it = vec.begin(); it != vec.end(); it++){ 29 cout << *it << " "; 30 } 31 cout << endl; 32 }

运行结果:

1 1 2 2 4 6 7 7 4
in unique_wy *begin = 1
1 2 4 6 7 4

本来我想把sort也写上去,算法不过关,没写出来。 去<stl_algo.h>的源码中看了点sort源码,sort有一系列的实现及辅助函数, 里面的参数都命名的是 RandomIterator.      这里引出了<algorithm>中算法的实现了,<algorithm>中都是function template,这是针对未知的iterator实现的算法,只要传进去的iterator满足相应的要求, 注意上面7,8行之间的代码,是如何使用iterator_traits<InputInterator>的,在<algorithm>中要使用iterator(通过模板参数传进来的类型)相关的几个type,都是这么用的

 

3 <iterator>

从上面的可以看出,自己定义的iterator若要被stl algorithm所使用,则必须按照iterator_traits中要求的定义那5个type, 当然也可以不自己定义,从 struct iterator{}派生,它会帮我们定义这些类型,<iterator>中还定义了5个空struct,有简单的派生关系input_iterator_tag, bidirectional_iterator_tag, random_access_iterator_tag   http://www.cplusplus.com/reference/std/iterator/ , 在从struct iterator{}派生的时候,必须给它传两个参数, 指向的type,和这五个之一的 catagory type,  从前述的那个文档中我们可以看到5个iterator catogory必须要支持哪些operator, 即必须重载了哪些operator. 虽然下面的例子是从iterator<>派生来提供5个预定义的类型,但我看c++/4.6实现的源码,stl_list.h中的 _List_iterator是直接在其中实现的,没有从iterator<>派生

1 class WyList;
2 class WyListIterator: public iterator<random_access_iterator_tag,  WYList> {
3     //一系列的operator overloading    bool operator==(WY&, WY&);
4    // WyListIterator&  operator++(){}  ; 
5    // WyListIterator  operator++(int){} ; 
6    //WyListIterator  operator+(int n){};
7    // typename iterator_traits::value_type operator[](int n) { };
8 }

以上写得很简单,本来想可以去模拟一下 std  list的实现,  注意2行中从iterator派生时的用法,传入的参数,自己定义的WyListIterator是一个类,并不是模板,这也就是container的实现者自己来实现自己的iterator的表现  另外注意4,5行重载实现 ++WyListIterator 和WyListIterator++时返回值的不同,体现了这前置和后置++的不同,一个对自己操作后返回自己,一个先copy自己,然后再把自己++,然后返回之前的自己

posted on 2012-06-11 19:37  小宇2  阅读(998)  评论(0编辑  收藏  举报

导航