c++泛型算法


1.定義

  泛型算法是STL庫里面定義的一些算法,這些算法可以用一個接口操作各種數據類型,因此成為泛型算法。大多算法定義在頭文件algorithm和numeric中。意思就是可以用一個接口操作各種類型的算法就是泛型算法。

  記住一些泛型算法,還是很必要的,有時候自己寫的超長函數功能,其實調用一個庫里面自帶的函數就解決了。

2.一些泛型算法

  [1]find(begin,end,value) :查找算法。begin到end是查找范圍的迭代器,value是要找的值,返回值是第一個等於給定值的迭代器,如果沒找到,則返回第二個參數表示找到了結尾。例如:

    int target = 1;
    vector<int> vec;
  int array[4] = {1,2,3,4}; vec.push_back(1); vec.push_back(2); vec.push_back(3);
  //查找一個vector
    if(find(vec.begin(), vec.end(), target) == vec.end())
        printf("not find\n");
    else
        printf("find\n");

    //查找一個數組
    if(find(&array[0], &array[3], target) == &ar[3])
        printf("not find\n");
    else
        printf("find\n");

    find_if(begin, end, pred):查找算法。帶自定義查找函數。意思就是對begin到end上面每一個元素判斷pred(*iter) == true,則表示找到返回當前迭代器,找不到則返回end。例如:

bool isequal6(const int &v1)
{
    return (v1 == 6);
}

class isequal5{  
public:   
    bool operator () (int& target) {  
        return (target == 5);  
    }  
}; 

class isequal{  
public:   
    isequal(int value):m_value(value){}
    bool operator () (int& target) {  
        return (target == m_value);  
    }  

    int m_value;
}; 

int main()
{
    vector<int> vec1;

    vec1.push_back(1);
    vec1.push_back(5);
    vec1.push_back(6);

    if(find_if(vec1.begin(), vec1.end(), isequal6) != vec1.end())      //使用自定義函數
        printf("find\n");
    else
        printf("not find.\n");
    
    if(find_if(vec1.begin(), vec1.end(), isequal5()) != vec1.end())    //使用仿函數
        printf("find\n");
    else
        printf("not find.\n");

    if(find_if(vec1.begin(), vec1.end(), isequal(7)) != vec1.end())    //使用帶參數的構造函數仿函數
        printf("find\n");
    else
        printf("not find.\n");

    return 0;
}

      另外說一下這個仿函數,仿函數就是讓對象擁有和函數名一樣的調用方式。上面的仿函數代碼解釋如下:

class isequal5{  
public:   
    bool operator () (int& target) {  
        return (target == 5);  
    }  
}; 

class isequal{  
public:   
    isequal(int value):m_value(value){}
    bool operator () (int& target) {  
        return (target == m_value);  
    }  

    int m_value;
}; 

int main()
{
    vector<int> vec1;

    vec1.push_back(1);
    vec1.push_back(5);
    vec1.push_back(6);

    /*
        此處創建了一個對象i5,之后就可以把對象i5當成函數來使用了,例如i5(6)
        因為重寫的()運算符需要傳入一個參數,所以這個i5仿函數也是需要傳入一個參數
        因此下面的find_if在查找的時候對每個iter執行了i5(*iter)操作。
    
也可以用上面的例子直接創建對象:
find_if(vec1.begin(), vec1.end(), isequal5()),這里是為了解釋,所以顯式創建了一個i5
*/
    isequal5 i5; 
    if(find_if(vec1.begin(), vec1.end(), i5) != vec1.end())
        printf("find\n");
    else
        printf("not find.\n");

    /*
        此處創建了一個對象is,之后就可以把對象is當成函數來使用了,例如is(6)
        因此下面的find_if在查找的時候對每個iter執行了is(*iter)操作。
    */
    isequal is(7);
    if(find_if(vec1.begin(), vec1.end(), is) != vec1.end())
        printf("find\n");
    else
        printf("not find.\n");

    return 0;
}

  [2]accumulate(begin,end,init_value) :求和算法。begin到end是求和范圍的迭代器,init_value是求和的初值。意思就是求前面范圍的和,最后加上init_value。

    int total;
    vector<int> vec;

    vec.push_back(1);
    vec.push_back(2);
    vec.push_back(3);

    total = accumulate(vec.begin(), vec.end(), 0);
    printf("total:%d\n", total);

  [3]equal(v1.begin,v1.end,v2.begin) :比較算法。v1.begin到v1.end是比較的范圍,v2.begin是一個迭代器的起始。如果相同則返回true,否則返回false。因為這個函數比較的時候是從范圍的開始一直比較到范圍的最后,所以第三個參數的長度應該至少等於比較的范圍的長度,否則會比較到越界。這意思就是會從vec1.begin()取值和vec2.begin()開始比較,如果vec1有8個元素,則也會從vec2的迭代器一直加8次,所以vec2至少要有8個元素。

    vector<int> vec1;
    vector<int> vec2;

    vec1.push_back(1);
    vec1.push_back(2);

    vec2.push_back(1);
    vec2.push_back(2);

    if(equal(vec1.begin(), vec1.end(), vec2.begin()))  //比較vec1是否和vec2的每個元素是否相等(如果vec1的長度是n,則是比較vec2中的前n個)
        printf("equal.\n");
    else
        printf("not equal.\n");

  [4]fill(begin,end,value):填充算法。begin到end是填充的范圍,value是要填充的值。類似memset()函數。

      fill_n(begin,size,value):也是填充算法。begin是迭代器起始位置,size是填充的長度,value是填充的值。這個就是memset()函數。

    vector<int> vec1(10);
    vector<int>::iterator it;
    
    fill(vec1.begin(), vec1.end(), 100);      //把vec1每個元素填充為100
    for(it=vec1.begin(); it!=vec1.end(); it++)
        printf("%d\n", *it);

  fill_n(vec1.begin(), vec1.size(), 200);    //把vec1每個元素填充為200

  [5]back_inserter():插入迭代器。這個意思就是這是一個迭代器,並且可以插入值。給back_inserter賦值,其實就是push_back()。例如vector是空的時候,給it賦值是會core掉的(it=vec.begin();)。

    vector<int> vec1;
    vector<int>::iterator it;

    //第一種賦值方式
    back_inserter(vec1) = 1;
    back_inserter(vec1) = 2;

    //另外一種賦值方式
    back_insert_iterator<vector<int> > backiter = back_inserter(vec1);  
    *backiter = 10;  
    backiter++;  
    *backiter = 20;  

    for(it=vec1.begin(); it!=vec1.end(); it++)
        printf("%d\n", *it);

    //調用fill_n賦值
    fill_n(back_inserter(vec1), 10, 100);
    for(it=vec1.begin(); it!=vec1.end(); it++)
        printf("%d\n", *it);

  [6]copy(v1.begin,v1.end,v2.begin):拷貝算法。v1.begin和v1.end是拷貝源的范圍,v2.begin是拷貝目的迭代器的起始。所以v2的長度至少要等於v1的長度。這個函數的返回值是目的迭代器的尾部。為了順序化寫代碼。

    vector<int> vec1(5);
    vector<int> vec2(5);
    vector<int>::iterator it;

    fill_n(vec1.begin(), 5, 10);
    copy(vec1.begin(), vec1.end(), vec2.begin());  //把vec1的元素拷貝到vec2中

    for(it=vec2.begin(); it!=vec2.end(); it++)
        printf("%d\n", *it);

  [7]replace(begin,end,old_value,new_vlaue):替換算法。begin和end是查找的范圍,old_value要搜索的值,new_value替換的值。意思就是把begin到end范圍內的old_value替換為new_value。

    vector<int> vec1;
    vector<int>::iterator it;
    
    vec1.push_back(1);
    vec1.push_back(2);
    vec1.push_back(3);

    replace(vec1.begin(),vec1.end(), 2, 10);  //把vec1中的2的替換為10

    for(it=vec1.begin(); it!=vec1.end(); it++)
        printf("%d\n", *it);

  [8]sort(begin,end):排序算法。這個就是排序,另外可以有第三個參數,傳入自定義的比較函數,另外也可以傳入stl自帶的比較函數模板。

      stable_sort():穩定排序算法。這個用法和上面的是一樣的。只不過這個函數對相同的元素可以在排序好后保持之前的相對位置,這個意思就是比如排序之前的序列中a等於b,並且a在b前面,則排序好后a還在b的前面,但是用sort排序就不一定是這樣了。

bool islittle(const int &v1, const int &v2)
{
    return (v1 < v2);
}

int main()
{
    vector<int> vec1;
    vector<int>::iterator it, unique_end;
    
    vec1.push_back(1);
    vec1.push_back(2);
    vec1.push_back(6);
    vec1.push_back(3);
    vec1.push_back(2);

    sort(vec1.begin(),vec1.end());                          //默認是升序排序
    sort(vec1.begin(),vec1.end(), less<int>());             //升序排序
    sort(vec1.begin(),vec1.end(), greater<int>());          //降序排序
    
    sort(vec1.begin(),vec1.end(), islittle);                //自定義比較函數
    
    for(it=vec1.begin(); it!=vec1.end(); it++)
        printf("%d\n", *it);

    return 0;
}

 

  [9]unique(begin,end):去重算法。這個把begin到end之間重復的元素放到最后,返回最后一個不重復的迭代器。這個的意思就是把不重復的元素放到前面,最后的元素是什么已經無所謂了,刪除就可以了。

    vector<int> vec1;
    vector<int>::iterator it, unique_end;
    
    vec1.push_back(1);
    vec1.push_back(2);
    vec1.push_back(6);
    vec1.push_back(3);
    vec1.push_back(2);

    sort(vec1.begin(),vec1.end());                        //sort之后是{1,2,2,3,6}
    unique_end = unique(vec1.begin(),vec1.end());         //unique之后是{1,2,3,6,6},unique_end指向最后的6
    vec1.erase(unique_end, vec1.end());                   //erase之后是{1,2,3,6}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM