日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++ Primer 第11章 泛型算法 学习总结

發布時間:2024/7/5 c/c++ 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ Primer 第11章 泛型算法 学习总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 11.2 算法
    • 11.2.1 只讀算法
      • **1.find函數**
      • **2.accumulate函數**
      • **3.find_first_of 函數**
    • 11.2.2 寫容器元素算法
      • 1.fill函數
      • 2.fill_n函數
      • 3.back_inserter插入迭代器
      • 4.copy函數
      • 5.算法的 _copy 版本
    • 11.2.3 排序算法
      • sort(起始,結束);
      • unique(起始,結束)--刪除相鄰重復元素,返回迭代器(無重復范圍的下一位)
      • stable_sort(起始,結束)--穩定排序,相等情況下,保持原始順序
      • sort(起始,結束,謂詞函數<寫函數名即可>)--按照謂詞函數規則排序
  • 11.3 迭代器
    • 11.3.1 插入迭代器
      • a. back_inserter--使用push_back實現的插入迭代器
      • b.front_inserter--使用push_front實現插入,若容器不支持push_front,不可用
      • c.inserter(容器對象,插入起始位置迭代器)總是在該迭代器---前面---位置插入
    • 11.3.2 iostream迭代器
      • istream_iterator迭代器
      • ostream_iterator迭代器
      • 在類類型上使用istream_iterator
      • 流迭代器限制
        • a. 不能從 ostream_iterator 對象讀入,也不能寫到istream_iterator 對象中
        • b. 一旦給 ostream_iterator 對象賦了一個值,寫入就提交了。賦值后,沒有辦法再改變這個值。此外,ostream_iterator 對象中每個不同的值都只能正好輸出一次
        • c. ostream_iterator 沒有 -> 操作符
      • 與算法一起使用流迭代器
    • 11.3.3 反向迭代器
    • 11.3.4 const迭代器
    • 11.3.5 五種迭代器
  • 11.4泛型算法的結構
    • 11.4.1 算法的形參模式
      • a. 帶有單個目標迭代器的算法
      • b. 帶第二個輸入序列的算法
    • 11.4.2 算法命名規范
      • a. 區別帶有一個值或一個謂詞函數參數的算法版本
      • b. 區別是否實現復制的算法版本
  • 11.5容器特有的算法

標準容器定義的操作比較少,我們需要其他的一些函數來操作容器,比如查找,排序,這些算法不依賴容器類型。

11.2 算法

11.2.1 只讀算法

1.find函數

find(起始迭代器,終止迭代器,搜索值)
搜索范圍不包含終止迭代器位置,函數返回迭代器類型

#include<iostream> #include<algorithm> int main() {int ia[7] = {52,13,14,100,66,10,66};int search = 66;int *position = std::find(ia,ia+7,search);std::cout << "the value you want is " << search << (position==ia+7 ? " not found" : " found")<< std::endl;std::cout << "ia address is " << ia << " address of found value is " << position << std::endl; }


find 找到了第一個出現的搜索值,并返回迭代器(指針)
注意:不加 using namespace std; 則需要寫 std::find

2.accumulate函數

需要包含頭文件,accumulate(起始迭代器,終止迭代器,初始value);
返回范圍內的值和初始value的總和;也可以連接字符串;

#include<iostream> #include<numeric> int main() {int ia1[] = {1,2,3,4};int sum = std::accumulate(ia1,ia1+3,100);std::cout << "sum is " << sum << std::endl; }

string str[] = {"abc","def","ghi","jkl"};string strsum = accumulate(str,str+4,string("ok!!!"));cout << strsum << endl;

3.find_first_of 函數

find_first_of(a.起始迭代器,a.終止迭代器,b.起始迭代器,b.終止迭代器)
返回值:迭代器(指向第一個a中的元素,該元素也在b中存在)

string str[] = {"abc","def","ghi","jkl"};string str1[] = {"jkl","haha","abc"};string *strp = find_first_of(str,str+4,str1,str1+3);cout << *strp << " " << str << " " << strp << endl;

11.2.2 寫容器元素算法

1.fill函數

fill(起始迭代器,終止迭代器,填充值)
使得范圍內存在的元素進行寫入(填充值)

#include<algorithm> #include<iostream> using namespace std; int main() {int ia[] = {1,2,3,4,5,6};fill(ia,ia+5,9);for(int i = 0; i != 6;++i){cout << ia[i] << " ";}cout << endl;return 0; }

2.fill_n函數

fill_n(起始迭代器,計數器n,value)
需要保證要寫入的元素存在!!!不然,可能導致嚴重的錯誤

int ib[] = {1,2,3,4,5,6};fill_n(ib,5,9);for(int i = 0; i != 6;++i){cout << ib[i] << " ";}

3.back_inserter插入迭代器

需要iterator頭文件
back_inserter(容器對象)在容器尾部添加元素,返回的是一個迭代器

vector<int> ivec;ivec.push_back(1);ivec.push_back(2);fill_n(back_inserter(ivec),5,3);for(vector<int>::iterator it = ivec.begin();it != ivec.end();++it){cout << *it << " ";}cout << endl;

4.copy函數

copy(a.起始迭代器,a.終止迭代器,b.迭代器)

#include<iostream> #include<algorithm> #include<vector> #include<list> using namespace std; int main() {vector<int> ivec;ivec.push_back(9);list<int> ilist;ilist.push_back(1);ilist.push_back(2);ilist.push_back(3);copy(ilist.begin(),ilist.end(),back_inserter(ivec));for(vector<int>::iterator it = ivec.begin();it != ivec.end();++it){cout << *it << " ";}cout << endl; }

#include<iostream> #include<algorithm> #include<vector> #include<list> using namespace std; int main() {list<int> ilist;ilist.push_back(1);ilist.push_back(2);ilist.push_back(3);copy(ilist.begin(),ilist.end(),back_inserter(ilist));for(list<int>::iterator it = ilist.begin();it != ilist.end();++it){cout << *it << " ";}cout << endl; }

以上代碼無結果,內存撐爆!

int main() {vector<int> ivec;ivec.push_back(9);copy(ivec.begin(),ivec.end(),back_inserter(ivec));for(vector<int>::iterator it = ivec.begin();it != ivec.end();++it){cout << *it << " ";}cout << endl; }

int main() {vector<int> ivec;ivec.push_back(9);ivec.push_back(9);ivec.push_back(9);list<int> ilist;ilist.push_back(1);ilist.push_back(2);ilist.push_back(3);vector<int>::iterator it = ivec.begin();copy(ilist.begin(),ilist.end(),it+1);for(vector<int>::iterator it = ivec.begin();it != ivec.end();++it){cout << *it << " ";}cout << endl; }


copy函數沒有添加元素個數,只是改寫了元素。

5.算法的 _copy 版本

_copy版本不改變輸入元素,會創建新序列存儲處理的結果

list<int> ilist;ilist.push_back(1);ilist.push_back(2);ilist.push_back(2);ilist.push_back(3);replace(ilist.begin(),ilist.end(),2,6);for(list<int>::iterator it = ilist.begin();it != ilist.end();++it){cout << *it << " ";}cout << endl;


原輸入改變了

vector<int> ivec;ivec.push_back(9);list<int> ilist;ilist.push_back(1);ilist.push_back(2);ilist.push_back(2);ilist.push_back(3);replace_copy(ilist.begin(),ilist.end(),back_inserter(ivec),2,6);for(list<int>::iterator it = ilist.begin();it != ilist.end();++it){cout << *it << " ";}cout << endl;for(vector<int>::iterator it = ivec.begin();it != ivec.end();++it){cout << *it << " ";}cout << endl;


原輸入list沒有改變,把處理后的list追加到vector中了

11.2.3 排序算法

sort(起始,結束);

unique(起始,結束)–刪除相鄰重復元素,返回迭代器(無重復范圍的下一位)

stable_sort(起始,結束)–穩定排序,相等情況下,保持原始順序

sort(起始,結束,謂詞函數<寫函數名即可>)–按照謂詞函數規則排序

編寫程序統計一個文檔中長度不小于 4 的單詞,并輸出輸入序列中不重復的單詞。

#include<iostream> #include<vector> #include<fstream> #include<algorithm> #include<string> using namespace std; bool isshorter(const string &s1, const string &s2) {return s1.size() < s2.size(); } bool gt4(const string &s) {return s.size() >= 4; } string make_end_s(size_t ctr, const string &word, const string &ending) {return (ctr == 1)?word:word+ending; //多個單詞,后綴加s } int main(int argc, char **argv) {if(argc < 2){cerr << "No input file!" << endl;return EXIT_FAILURE;}ifstream infile;infile.open(argv[1]);if(!infile){cerr << "can not open input file!" << endl;return EXIT_FAILURE;}vector<string> words;string word;while(infile >> word)words.push_back(word);sort(words.begin(),words.end());//sort按照字典順序排序words.erase(unique(words.begin(),words.end()),words.end());//unique指向無重復的末端的下一位,erase刪除重復的stable_sort(words.begin(),words.end(),isshorter);//按照isshorter規則,長度從小到大排序,stable排序,長度一樣的話不改變之前的字典序vector<string>::size_type wc = count_if(words.begin(),words.end(),gt4);//count_if if判斷每個元素是否滿足gt4函數,true則wc+1cout << wc << " " << make_end_s(wc,"word","s")<< " 4 characters or longer!" << endl;cout << "unique words:" << endl;for(vector<string>::iterator iter = words.begin();iter != words.end();++iter)cout << *iter << endl;cout << endl;return 0; }


調試過程如下:

11.3 迭代器

11.3.1 插入迭代器

a. back_inserter–使用push_back實現的插入迭代器

b.front_inserter–使用push_front實現插入,若容器不支持push_front,不可用

在vector或其他沒有push_front運算的容器上,不可以使用,將產生錯誤

c.inserter(容器對象,插入起始位置迭代器)總是在該迭代器—前面—位置插入

#include<list> #include<vector> #include<iostream> #include<algorithm> using namespace std; int main() {list<int> ilist;ilist.push_back(1);ilist.push_back(2);vector<int> ivec;ivec.push_back(6);ivec.push_back(7);list<int>::iterator it = find(ilist.begin(),ilist.end(),2);replace_copy(ivec.begin(),ivec.end(),inserter(ilist,it),6,5);for(it = ilist.begin(); it != ilist.end(); ++it){cout << *it << " ";}cout << endl;return 0; }


!!!在容器begin首位置inserter,不能跟front_inserter一樣產生反序,看下面例子

list<int> ilist,ilist2,ilist3;ilist.push_back(1);ilist.push_back(2);ilist.push_back(3);copy(ilist.begin(),ilist.end(),front_inserter(ilist2));for(list<int>::iterator it = ilist2.begin(); it != ilist2.end(); ++it){cout << *it << " ";}cout << endl;copy(ilist.begin(),ilist.end(),inserter(ilist3,ilist3.begin()));for(list<int>::iterator it = ilist3.begin(); it != ilist3.end(); ++it){cout << *it << " ";}

11.3.2 iostream迭代器

istream_iterator in(strm);創建從輸入流 strm 中讀取 T 類型對象的istream_iterator 對象
istream_iterator in;istream_iterator 對象的超出末端迭代器
ostream_iterator in(strm);創建將 T 類型的對象寫到輸出流 strm 的ostream_iterator 對象
ostream_iterator in(strm, delim);創建將 T 類型的對象寫到輸出流 strm 的ostream_iterator 對象,在寫入過程中使用 delim作為元素的分隔符。delim 是以空字符結束的字符數組

istream_iterator迭代器

#include<vector> #include<iterator> #include<iostream> #include<fstream> #include<exception> using namespace std; int main(int argc, char** argv) {vector<int> ivec;ifstream openfile;openfile.open(argv[1]);if(!openfile)throw runtime_error("open file failure!");istream_iterator<int> int_iter(openfile);istream_iterator<int> end;while(int_iter != end){ivec.push_back(*int_iter++);openfile.clear();}for(vector<int>::iterator it = ivec.begin(); it != ivec.end(); ++it){cout << *it << " ";}cout << endl;return 0; }


以下代碼與上面效果相同,用一對迭代器指向的內容初始化vector

istream_iterator<int> int_iter(openfile);istream_iterator<int> end;vector<int> ivec(int_iter,end);

ostream_iterator迭代器

int main(int argc, char** argv) {ifstream openfile;openfile.open(argv[1]);if(!openfile)throw runtime_error("open file failure!");ostream_iterator<string> out_iter(cout,"\n");istream_iterator<string> int_iter(openfile),end;while(int_iter != end){*out_iter++ = *int_iter++;}return 0; }

在類類型上使用istream_iterator

提供了>>操作的任何類類型都可以使用istream_iterator

#include<vector> #include<iterator> #include<iostream> #include<fstream> #include<exception> #include<Sales_item.h> using namespace std; int main(int argc, char** argv) {ifstream openfile;openfile.open(argv[1]);if(!openfile)throw runtime_error("open file failure!");istream_iterator<Sales_item> item_iter(openfile),end;Sales_item sum;sum = *item_iter++;while(item_iter != end){if(item_iter->same_isbn(sum))sum += *item_iter;else{cout << sum << endl;sum = *item_iter;}++item_iter;}cout << sum << endl;return 0; }

流迭代器限制

a. 不能從 ostream_iterator 對象讀入,也不能寫到istream_iterator 對象中

b. 一旦給 ostream_iterator 對象賦了一個值,寫入就提交了。賦值后,沒有辦法再改變這個值。此外,ostream_iterator 對象中每個不同的值都只能正好輸出一次

c. ostream_iterator 沒有 -> 操作符

與算法一起使用流迭代器

#include<vector> #include<iterator> #include<algorithm> #include<iostream> using namespace std; int main() {istream_iterator<int> cin_iter(cin),end;vector<int> ivec(cin_iter,end);sort(ivec.begin(),ivec.end());ostream_iterator<int> print(cout," ");unique_copy(ivec.begin(),ivec.end(),print);return 0; }

11.3.3 反向迭代器

反向遍歷容器的迭代器

#include<vector> #include<iostream> using namespace std; int main() {vector<int> ivec;for(vector<int>::size_type i = 0; i!= 10; ++i){ivec.push_back(i);}vector<int>::reverse_iterator r_iter;for(r_iter = ivec.rbegin(); r_iter != ivec.rend(); ++r_iter){cout << *r_iter << " ";}return 0; }


如果是字符串呢?反向迭代器有什么問題?

#include<cstring> #include<iterator> #include<iostream> #include<algorithm> using namespace std; int main() {string str("first,middle,last"),str1;string::reverse_iterator rcomma = find(str.rbegin(),str.rend(),',');cout << string(str.rbegin(),rcomma) << endl;cout << string(rcomma.base(),str.end()) << endl;return 0; }

11.3.4 const迭代器

find_first_of(it, roster1.end(),roster2.begin(), roster2.end())

如果該容器是 const 對象,則返回的迭代器是 const_iterator 類型;否則,就是普通的 iterator 類型。
roster1 不是 const 對象,因而 end 返回的只是一個普通的迭代器。
如果將 it 定義為 const_iterator,那么 find_first_of 的調用將無法編譯。
because 用來指定范圍的兩個迭代器的類型不相同。
it 是 const_iterator 類型的對象,而 rotser1.end() 返回的則是一個 iterator 對象。

11.3.5 五種迭代器

Input iterator(輸入迭代器)讀,不能寫;只支持自增運算
Output iterator(輸出迭代器)寫,不能讀;只支持自增運算
Forward iterator(前向迭代器)讀和寫;只支持自增運算
Bidirectional iterator(雙向迭代器)讀和寫;支持自增和自減運算
Random access iterator(隨機訪問迭代器)讀和寫;支持完整的迭代器算術運算

11.4泛型算法的結構

11.4.1 算法的形參模式

alg (beg, end, other parms);
alg (beg, end, dest, other parms);
alg (beg, end, beg2, other parms);
alg (beg, end, beg2, end2, other parms);

alg 是算法名稱;
beg,end 是算法的輸入范圍(操作的元素范圍);
dest,beg2,end2,都是迭代器;
other parms 是算法的特有其他參數。

a. 帶有單個目標迭代器的算法

dest 形參是一個迭代器,用于指定存儲輸出數據的目標對象。算法假定無論需要寫入多少個元素都是安全的。必須確保輸出容器有足夠大的容量存儲輸出數據

如果 dest 是容器上的迭代器,則算法將輸出內容寫到容器中已存在的元素上。
更普遍的用法是,將 dest 與某個插入迭代器(第 11.3.1 節)或者ostream_iterator 綁定在一起。插入迭代器在容器中添加元素,以確保容器有足夠的空間存儲輸出。ostream_iterator 則實現寫輸出流的功能,無需要考慮所寫的元素個數。

b. 帶第二個輸入序列的算法

算法同時使用 beg2 和 end2 時,這些迭代器用于標記完整的第二個范圍。
帶有 beg2 而不帶 end2 的算法將 beg2 視為第二個輸入范圍的首元素,但沒有指定該范圍的最后一個元素。這些算法假定以 beg2 開始的范圍至少與 beg和 end 指定的范圍一樣大。

11.4.2 算法命名規范

a. 區別帶有一個值或一個謂詞函數參數的算法版本

很多算法通過檢查其輸入范圍內的元素實現其功能。這些算法通常要用到標準關系操作符:== 或 <
sort (beg, end); -----默認升序排序 // use < operator to sort the elements
sort (beg, end, comp); -----用滿足comp函數的規則排序// use function named comp to sort theelements

檢查指定值的算法默認使用 == 操作符。系統為這類算法提供另外命名的(而非重載的)版本,帶有謂詞函數形參。帶有謂詞函數形參的算法,其名字帶有后綴 _if:
find(beg, end, val); // find first instance of val in the input range
------find 算法查找一個指定的值
find_if(beg, end, pred); // find first instance for which pred is true
------find_if 算法則用于查找一個使謂詞函數 pred 返回非零值True的元素

b. 區別是否實現復制的算法版本

_copy的版本,將元素寫到指定的輸出目標

reverse(beg, end); 將自己的輸入序列中的元素反向重排reverse_copy(beg, end, dest); 復制輸入序列的元素,并將它們逆序存儲到 dest 開始的序列中。

11.5容器特有的算法

list 容器上的迭代器是雙向的,而不是隨機訪問類型。
由于 list 容器不支持隨機訪問,因此,在此容器上不能使用需要隨機訪問迭代器的算法。
這些算法包括 sort 及其相關的算法。
還有一些其他的泛型算法,如 merge、remove、reverse 和 unique,雖然可以用在 list 上,但卻付出了性能上的代價。

lst.merge(lst2); lst.merge(lst2, comp)將 lst2 的元素合并到 lst 中。這兩個 list 容器對象都必須排序。lst2 中的元素將被刪除。合并后,lst2 為空。返回 void 類型。第一個版本使用 < 操作符,而第二個版本則使用 comp 指定的比較運算
lst.remove(val); lst.remove_if(unaryPred)調用 lst.erase 刪除所有等于指定值或使指定的謂詞函數返回非零值的元素。返回 void 類型
lst.reverse()反向排列 lst 中的元素
lst.sort對 lst 中的元素排序
lst.splice(iter, lst2)將 lst2 的元素移到 lst 中迭代器 iter 指向的元素前面。在 lst2 中刪除移出的元素;-------第一個版本將 lst2 的所有元素移到 lst 中;合并后,lst2 為空。lst 和 lst2 不能是同一個 list 對象
lst.splice(iter, lst2, iter2)第二版本只移動 iter2 所指向的元素,這個元素必須是 lst2 中的元素。在這種情況中,lst 和lst2 可以是同一個 list 對象。也就是說,可在一個 list對象中使用 splice 運算移動一個元素。
lst.splice(iter, beg, end)第三版本移動迭代器 beg 和 end 標記的范圍內的元素。beg 和 end 必須指定一個有效的范圍。這兩個迭代器可標記任意 list 對象內的范圍,包括 lst。當它們指定 lst 的一段范圍時,如果 iter 也指向這個范圍的一個元素,則該運算未定義(iter 應不屬于beg,end范圍內

與對應的泛型算法不同,list 容器特有的操作能添加和刪除元素。

list 容器特有的算法與其泛型算法版本之間有兩個至關重要的差別。

  • 一個差別是 remove 和 unique 的 list 版本修改了其關聯的基礎容器:真正刪除了指定的元素。
    例如,list::unique 將 list 中第二個和后續重復的元素刪除出該容器。

  • 另一個差別是 list 容器提供的 merge 和 splice 運算會破壞它們的實參。
    使用 merge 的泛型算法版本時,合并的序列將寫入目標迭代器指向的對象,而兩輸入序列保持不變。
    但是,使用 list 容器的 merge 成員函數時,則會破壞它的實參 list 對象------當實參對象的元素合并到調用 merge 函數的list 對象時,實參對象的元素被移出并刪除。

  • #include<iostream> #include<list> #include<string> #include<fstream> #include<algorithm> using namespace std; int main(int argc, char **argv) {if(argc<2){cerr << "no input file!" << endl;return EXIT_FAILURE;}ifstream infile;infile.open(argv[1]);if(!infile){cerr << "can not open input file!" << endl;return EXIT_FAILURE;}list<string> words;string word;while(infile >> word)words.push_back(word);words.sort();words.unique();cout << "unique words: " << endl;for(list<string>::iterator iter = words.begin();iter != words.end();++iter)cout << *iter << " ";cout << endl;return 0; }

    list.unique(); 直接刪除了重復的元素!

    總結

    以上是生活随笔為你收集整理的C++ Primer 第11章 泛型算法 学习总结的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。