STL算法和迭代器

目錄

一、算法

(1)簡介

(2)STL常見算法

非可變序列算法

可變序列算法

排序算法

二、迭代器

(1)簡介

(2)迭代器操作

(3)STL使用自定義對象

三、類中成員函數聲明後面接 const


一、算法

(1)簡介

算法由頭文件<algorithm><numeric><functional>組成

  • <algorithm> 是頭文件中最大的,包含的功能有比較、交換、查找、遍歷、複製、修改、反轉、排序、合併等
  • <numeric> 只包括在序列上進行簡單數學運算的模板函數,包括加法和乘法在序列上的一些操作
  • <functional> 定義了一些模板類,用來聲明函數對象

(2)STL常見算法

  • 非可變序列算法

不直接修改所操作容器內容的算法

find()                    查找容器元素

find_if()                條件查找容器元素

#include <algorithm>                  
//for_each函數的頭文件

//find()
vector<int> v1;             
for(int i=0;i<10;i++)
{
    v1.push_back(2*i);
}
for_each(v1.begin(),v1.end(),MyPrint);                          //MyPrint爲之前定義的函數
vector<int>::iterator it1 = find(v1.begin(),v1.end(),5);        //查找成功返回迭代器,失敗返回v1.end()

//find_if()
bool DivBy5(int x)
{
    return x%5? 0:1;
}
vector<int>::iterator it2 = find_if(v1.begin(),v1.end(),DivBy5);   //返回第一個能被5整除的元素

count()                 統計元素的個數

count_if()             條件統計元素的個數

//count()
int num1 = count(v1.begin(),v1.end(),3);

//count_if()
int num2 = count(v1.begin(),v1.end(),DivBy5);          //第3個參數是條件函數

search()              子序列搜索,返回子序列在父序列中起始位置

search_n()           重複元素的子序列搜索

//search()
vector<int> v2;                //子序列
for(int i=0;i<2;i++)
{
    v2.push_back(i+8);
}
vector<int>::iterator it3 = search(v1.begin(),v1.end(),v2.begin(),v2.end());    
//前2個參數是搜索序列的範圍,後2個參數是子序列範圍

//search_n()
vector<int>::iterator it4 = search(v1.begin(),v1.end(),3,8);
                                          //在v1中搜索子序列 8 8 8 
  • 可變序列算法

修改所操作容器內容的算法

copy()                   元素複製

transform()           元素變換,也是複製,按照某種方案複製

//copy()
vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(5);

list<int> l;
l.push_back(2);
l.push_back(4);
l.push_back(6);
l.push_back(8);

copy(v.begin(),v.end(),l.begin());    //把v拷貝到l的頭部,會覆蓋l的數據

//transform(),按照規則拷貝
int square(int x)
{
    return x*x;
}

transform(v.begin(),v.end(),l.begin(),square);    //把v的平方拷貝到l的頭部,會覆蓋l的數據

replace()              替換元素

replace_if()          條件替換

//replace()
replace(v.begin(),v.end(),5,100);    //將所有5替換成100

//replace_if()
bool odd(int x)
{
    return x%2;
}
replace_if(v.begin(),v.end(),odd,100);   //將奇數替換成100

remove()              刪除元素

remove_if()          條件刪除

//remove()           
remove(v.begin(),v.end(),5);        //刪除值爲5的元素,但數組大小不變
                                    //刪除前 1  3  5  7
                                    //刪除後 1  3  7  7

//remove_if()
bool even(int x)
{
    return x%2?0:1;
}
remove_if(v.begin(),v.end(),even)   //刪除奇數
                                    //刪除前 1  2  3  4  5  6  7  8  9  10
                                    //刪除後 1  3  5  7  9  6  7  8  9  10

 

  • 排序算法

sort()                    普通排序

make_heap()       將一個區間轉換成堆

sort_heap()          對堆進行排序,排序後就不是堆了

//sort()                    
sort(v.begin(),v.end());              //參數爲要排序的區間,默認升序排列  

//make_heap()
make_heap(v.begin(),v.end());         //將區間轉換成大根堆

//sort_heap()         
sort_heap(v.begin(),v.end());         //對堆進行排序,默認升序排列

 

二、迭代器

(1)簡介

迭代器用於指向容器中的一個元素,有const非const兩種

通過迭代器可以讀取它指向的元素,通過非const迭代器可以修改它指向的元素

不同容器支持的迭代器功能強弱不同,迭代器功能強弱決定了該容器是否支持STL中的某種算法


定義迭代器:

容器類名:: iterator  變量名 ,如 vector<int>::iterator  v;

容器類名:: const_iterator  變量名 ,如 vector<int>::const_iterator  v;

訪問迭代器指向的元素:

* 迭代器變量名


迭代器功能由弱到強分爲5種

1.輸入:Input iterators 提供對數據的只讀訪問

1.輸出:Output iterators 提供對數據的寫訪問

2.正向:Forward iterators 提供讀寫操作,並能向前推進迭代器

3.雙向:Bidirectional iterators 提供讀寫操作,並能向前和向後操作

4.隨機:Random access iterators 提供讀寫操作,並能在數據種隨機移動(能使用[ ]操作符)

編號大的迭代器擁有編號小的迭代器的功能,能當編號小的迭代器使用


不同迭代器能進行的操作

所有迭代器: ++p,p++

輸入迭代器:*p,p=p1,p==p1,p!=p1

輸出迭代器:*p,p=p1

正向迭代器:上面全部

雙向迭代器:上面全部,--p,p--

隨機訪問迭代器:上面全部,

                             p+=i,p-=i, p+i,p-i,p[i],

                             p<p1,p<=p1,p>p1,p>=p1  (迭代器比較操作)


容器所支持的迭代器類別
容器 迭代器類別
vector 隨機
deque 隨機
list 雙向
set / multiset 雙向
map / multimap 雙向
stack 不支持
queue 不支持
priority_queue 不支持

(2)迭代器操作

//p<p1,p<=p1,p>p1,p>=p1

int arr[] = {11,12,13,14,15,16,17,18,19,20};
vector<int> v(arr,arr+9);
vector<int>::const_iterator it1 = v.begin();        //常量迭代器,指向第一個元素11
vector<int>::const_iterator it2 = v.cbegin();       //常量迭代器,指向第一個元素11
                                                    //cbegin()和cend()方法,返回一個const的迭代器,不能用於修改元素
vector<int>::iterator it3 = v.begin();
*it3 = 10;                                          //修改第一個元素值爲10
it3++;                     //指向第二個元素

//迭代器的比較是按照迭代器指向的值來進行比較                                          

(3)STL使用自定義對象

向vector,deque,list,stack,queue添加自定義對象,實際是將對象複製到容器中,要調用對象的拷貝函數;

如果定義了拷貝函數就調用定義的拷貝函數,否則就調用默認的拷貝函數;

向set和map容器添加自定義對象也是將對象複製到容器中,不同的是set和map容器要實現比較器函數

  • vector容器
class member
{
private:
   string m_str;
   int m_id;
public:
   member(const string str,const int id):m_str(str),m_id(id){};    //構造函數
   void MyPrint()
   {
      cout<< m_str << ":" << m_id;
   }
};

vector<member> v1;
v1.push_back(member("123",1));
v1.push_back(member("456",2));

vector<member> v2(v1);        //用v1初始化v2
vector<member>::iterator it = v2.begin();
it-> MyPrint();               //打印結果爲123:1
  •  set容器
class student
{
private:
   int s_str; string s_id;
public:
   student(const int id,const string str)
   {
      s_id= id; s_str = str;
   }
   void MyPrint()const             //const成員函數
   {
      cout<< s_str << ":" << s_id;
   }
};

//小於比較器
struct stuFun         
{
   bool operator()(const student& stu1,const student& stu2)
   {
      return(stu1.s_id < stu2.s_id)
   }
};

set<student,stuFun> s1;
s1.insert(student(7,"小A"));
s1.insert(student(5,"小B"));
s1.insert(student(3,"小C"));
s1.insert(student(1,"小D"));      //按id進行升序排列

set<student,stuFun> s2(s1);
set<student,stuFun>::iterator it = s2.begin();
it-> MyPrint();                   //打印結果爲 小D:1

 

 

三、類中成員函數聲明後面接 const

  • const 表示對類中成員函數屬性的聲明
  • 表示不會修改類中的數據成員;
  • 在編寫const成員函數時,若不慎修改了數據成員,或者調用了非const成員函數,編譯器報錯;
class S
{
private:
    int num;
    int data[100];
public:
    void Push(int elem);
    int Pop(void);
    int GetCount(void) const;     //const成員函數
};

//注意:在實現的時候需要帶有const修飾
int S::GetCount(void)const                 
{
    ++num;          //編譯錯誤,企圖修改數據成員num
    Pop();          //編譯錯誤,企圖調用非const函數
    return num;
}

類中被const聲明的成員函數只能訪問const成員函數,而非const函數可以訪問任意的成員函數,包括const成員函數

類中被const聲明的成員函數不可以修改對象的數據,不管對象是否具有const性質,它在編譯時,會檢查是否修改成員數據

加上mutable修飾符的數據成員,對於任何情況下通過任何手段都可修改,自然此時的const成員函數是可以修改它的

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章