在這裏總結下可替代循環的區間成員函數和區間算法;java
相比單元素遍歷操做,使用區間成員函數的優點在於:
1)更少的函數調用
2)更少的元素移動
3)更少的內存分配python
在區間成員函數不適用的狀況下也應該使用區間算法,至少,相比手寫循環而言,它更加簡單,有效,而且不容易出錯;c++
標準容器都支持區間構造函數:程序員
container::container(InputIterator begin, // 區間的起點 InputIterator end); // 區間的終點
例如:算法
int myints[] = { 10, 20, 30, 30, 20, 10, 10, 20 }; std::vector<int> myvector (myints, myints+8);
以上是c++98中經常使用法,在C++11中,vector能夠直接初始化了:數組
std::vector<int> second ={10, 20, 30, 30, 20, 10, 10, 20}; 或者: std::vector<int> second ({10, 20, 30, 30, 20, 10, 10, 20});
標準序列容器提供這種形式的insert:函數
void container::insert(iterator position, // 區間插入的位置 InputIterator begin, // 插入區間的起點 InputIterator end); // 插入區間的終點
例如:性能
int myints[] = { 10, 20, 30, 30, 20, 10, 10, 20 }; std::vector<int> myvector; myvector.push_back(100); myvector.insert(myvector.begin(),myints,myints+8); //10 20 30 30 20 10 10 20 100
關聯容器也支持區間插入,但因爲其插入後的位置由其比較函數來決定,因此沒有區間插入的位置這個參數;c++11
標準序列容器提供的erase:code
iterator container::erase(iterator begin, iterator end);
c++98的標準關聯容器提供的erase爲:
void container::erase(iterator begin, iterator end);
序列容器調用erase以後,返回一個迭代器(被刪除的那個元素的下一個),
而關聯容器的erase刪除以後並不返回迭代器.【官方解釋說若是實現成序列容器那樣返回指向下一個迭代器,會致使沒法接收的性能降低】;
這一區別在c++11中終於統一了;c++11中,對關聯容器調用erase以後會返回一個迭代器(指向被刪除元素的下一個);
iterator container::erase(const_iterator first, const_iterator last);
全部標準容器提供了區間賦值的成員函數:
void container::assign(InputIterator begin, InputIterator end);
這個函數用於給容器賦值,會替代現有值,並根據須要分配空間;
與copy()算法的區別在於它不須要預先分配空間,並有更高的性能;
int myints[]={10,20,30,40,50,60,70}; std::vector<int> myvector; myvector.assign(myints,myints+7);
for_each:遍歷,對每一個元素都執行一個動做;
C++98只支持最原始的for循環,不少語言(java、python等)都實現了foreach區間迭代語法,這讓C++程序員眼饞了好久;
在沒有foreach區間迭代的時代,咱們能夠用for_each()算法來代替:
例:對每一個元素都加5:
void myfunction (int& i) { i += 5; } std::vector<int> myvector; myvector.push_back(10); myvector.push_back(20); myvector.push_back(30); for_each(myvector.begin(),myvector.end(),myfunction); //15 25 35
c++11中新增了區間迭代,使得咱們對for_each的依賴下降了,使用也更加方便:
for(auto &i : myvector ) { i+=5; }
對區間中每一個元素執行操做後,將修改後的值寫入到新區間中;
能夠認爲這個是for_each()算法不修改原區間的版本;
仍是for_each中的例子:
int addfunction(int i ){ return i+5; } void output (int i) { // output function std::cout << ' ' << i; } std::vector<int> myvector; myvector.push_back(10); myvector.push_back(20); myvector.push_back(30); std::vector<int> bvector; bvector.resize(myvector.size()); transform(myvector.begin(),myvector.end(),bvector.begin(),addfunction); //輸出 for_each(bvector.begin(),bvector.end(),output); //bvector: 15 25 35
區間複製,通常用於多個容器間的數據傳值;
這個算法被用的很廣泛,其實,不少使用copy的場景,均可以使用區間成員函數來替代(也建議這麼作);
例:複製數組到vector:
int myints[]={10,20,30,40,50,60,70}; std::vector<int> myvector (7); std::copy ( myints, myints+7, myvector.begin() );
用一個元素來重複填充區間;
這個算法使用頻率較低;
例:用5填充vector前4個元素:
std::vector<int> myvector (8); // myvector: 0 0 0 0 0 0 0 0 std::fill (myvector.begin(),myvector.begin()+4,5); // myvector: 5 5 5 5 0 0 0 0
遍歷區間,進行值替換:
例:將如下區間中全部20替換爲99:
int myints[] = { 10, 20, 30, 30, 20, 10, 10, 20 }; std::vector<int> myvector (myints, myints+8); // 10 20 30 30 20 10 10 20 std::replace (myvector.begin(), myvector.end(), 20, 99); // 10 99 30 30 99 10 10 99
更復雜的版本(使用仿函數)replace_if
例:將如下區間中全部大於20替換爲99:
bool bigerThen20 (int i) { return i > 20; } int myints[] = { 10, 20, 30, 30, 20, 10, 10, 20 }; std::vector<int> myvector (myints, myints+8); // 10 20 30 30 20 10 10 20 std::replace_if (myvector.begin(), myvector.end(), bigerThen20, 99); //10 20 99 99 20 10 10 20
因爲用到了仿函數,經過replace_if實現的,用for_each()也很容易實現;
從區間中刪除指定元素;
int myints[] = { 10, 20, 30, 30, 20, 10, 10, 20 }; std::vector<int> myvector (myints, myints+8); // 10 20 30 30 20 10 10 20 std::remove(myvector.begin(), myvector.end(), 20); // 10 30 30 10 10 ? ? ?
注意,remove並不會真正刪除元素,而只是將須要刪除的元素放到到最後,同時返回一個新的尾部迭代器,
好比,上述例子中,調用完remove後,vector中的值通常爲 //10 30 30 10 10 10 10 20
而若是但願真的刪除元素,須要加上成員函數erase()來實現刪除 【remove-erase慣用法】:
myvector.erase(std::remove(myvector.begin(), myvector.end(), 20),myvector.end()); // 10 30 30 10 10
從區間中刪除相鄰相同的元素,一樣,這個算法也不會真正的刪除元素,而是將待刪除的元素移到區間尾部;
使用【unique-erase慣用法】:
int myints[] = {10,20,20,20,30,30,20,20,10}; // 10 20 20 20 30 30 20 20 10 std::vector<int> myvector (myints,myints+9); std::vector<int>::iterator it; it = std::unique (myvector.begin(), myvector.end()); // 10 20 30 20 10 ? ? ? ? myvector.erase(it,myvector.end());
Posted by: 大CC | 28JUN,2015
博客:blog.me115.com [訂閱]
微博:新浪微博