c++ 特定容器算法(sort,merge,reverse,remove,unique)
下面內容都是特定容器算法,也就是c++,list和forward_list特有的算法。
第一部分:成員函數算法merge(forward_list和list專用)
1.c++ primer 5th p369頁上說,lst.merge(lst2) 必須lst 和lst2都是有序的,但是我自己編寫程序,lst和lst2都沒有順序也是可以的,why?
#include <iostream> #include <string> #include <sstream> #include <fstream> #include <forward_list> #include <stack> #include <vector> #include <forward_list> #include <deque> #include <array> #include <list> #include <algorithm> #include <numeric> using namespace std; bool compare(const int ,const int); int main() { forward_list<int> f1{1,2223,3,4,5,6}; forward_list<int> l1{7,8,9}; //f1.sort();這里根本就沒有運行 //l1.sort();這里也根本沒有運行 //下面merge算法添加第二個參數用于比較,但是結果卻不給從小到大排列? f1.merge(l1,compare); //這里我才開始排序 f1.sort(); for(auto i : f1)cout << i << endl;return 0; } bool compare(const int a,const int b) { return a < b; }上述代碼在ubuntu20.04運行結果如下:
r@r:~/coml_/c++/chapter10/10.6$ g++ 2.cc -o 123 r@r:~/coml_/c++/chapter10/10.6$ ./123 1 3 4 5 6 7 8 9 2223疑問:這個算法對于不不同類型的容器不成立?也就是說,一個forward_list,另一個是list,就不能合并。我自己的編譯器是如此的。
高手如果知道也告訴我下?難道只能合并相同類型的容器???
還有為何我程序里面加了compare,運行結果卻不給排序?為了,擺設?有高手就給我解釋下?拜托。小弟初學者。
第二部分:算法remove
#include <iostream> #include <string> #include <sstream> #include <fstream> #include <forward_list> #include <stack> #include <vector> #include <forward_list> #include <deque> #include <array> #include <list> #include <algorithm> using namespace std; bool is_odd(const int ); int main() { //have not function parameter forward_list<int> fint{1,2,3,45,5,32}; fint.remove(32); for(auto i : fint)cout << i << endl;//have function parameter forward_list<int> fint2{1,2,3,4,5,6,7}; fint2.remove_if([](const int i){return (i % 2 == 0);}); //fint2.remove_if(is_odd); cout << endl; for(auto i : fint2)cout << i << endl; return 0; } bool is_odd(const int i) { return (i % 2); }注意一下幾個問題:
1.如果使用算法remove那么參數一定是一個元素類型的值,如果使用算法remove_if,那么參數是一個函數或者是lambda表達式,總之是一個一元謂詞
2.以前非成員函數版本的remove是不會刪除這個元素的,因為返回位置后,刪除這個元素很容的。但是現在成員函數版本remove或者remove_if會直接刪除這個元素。因為你自己刪除這個元素很難。多么是人性化。
下面再加幾行代碼,同時復習一下bind函數(用于參數綁定的),要使用它必須先添加頭文件 functional,和名字空間? using namespace std::placeholders,廢話不多說,直接上代碼:
#include <iostream> #include <string> #include <sstream> #include <fstream> #include <forward_list> #include <stack> #include <vector> #include <forward_list> #include <deque> #include <array> #include <list> #include <algorithm> #include <functional> using namespace std::placeholders; using namespace std; bool is_odd(const int ); bool divide(const int ,const int); int main() { //have not function parameter forward_list<int> fint{1,2,3,45,5,32}; fint.remove(32); for(auto i : fint)cout << i << endl;//have function parameter forward_list<int> fint2{1,2,3,4,5,6,7}; fint2.remove_if([](const int i){return (i % 2 == 0);}); //fint2.remove_if(is_odd); cout << endl; for(auto i : fint2)cout << i << endl; //下面再作死一下,再編寫一個bind函數調用算法remove_if //順便復習一下bind函數,當你編寫的函數要求很苛刻的時候,bind可能越有用 //刪除能被5整除且大于給定整數的數 forward_list<int> fint3{10,11,12,13,14,15,16,5,0}; //define given integer number int key; cout << "Enter given number:"<< endl; cin >> key; fint3.remove_if(bind(divide,_1,key)); for(auto i : fint3)cout << i << endl;return 0; } bool is_odd(const int i) { return (i % 2); } //定義這個函數純粹是為了作死,調用bind bool divide(const int i,const int key) {return (i % 5== 0 && i > key);}第三部分:reverse,下面的代碼包含了很多不必要的頭文件。
#include <iostream> #include <string> #include <sstream> #include <fstream> #include <forward_list> #include <stack> #include <vector> #include <forward_list> #include <deque> #include <array> #include <list> #include <algorithm> using namespace std; int main() { forward_list<int> f1{1,2,3,4}; f1.reverse(); for(auto i : f1)cout << i << endl; return 0; }總結:還好,這個函數簡單,沒有遇到前面那么多麻煩。
第四部分:sort,本來打算不解釋了。仔細一看,sort帶參數版本竟然不加if,自己必須編寫程序運行一下:
?
#include <iostream> #include <string> #include <sstream> #include <fstream> #include <forward_list> #include <stack> #include <vector> #include <forward_list> #include <deque> #include <array> #include <list> #include <algorithm> using namespace std; int main() { //have no parameter forward_list<int> f1{1,2,3,4}; f1.reverse(); for(auto i : f1)cout << i << " "; cout << endl;//have parameter forward_list<int> f2{1,2,3,4,5,6,7,8,9,10}; //按照除以5的余數大小進行排序 f2.sort([](const int i,const int j){return (i % 5 < j % 5);});for(auto i : f2)cout << i << " ";cout << endl;return 0; }sort帶二元謂詞版本后面不加if,真尼瑪牛B。
第五部分:unique,簡單不介紹了。
這兩個函數都是重載函數,難道尼瑪的有參數和無參數后面不加個if區別下?
#include <iostream> #include <string> #include <sstream> #include <fstream> #include <forward_list> #include <stack> #include <vector> #include <forward_list> #include <deque> #include <array> #include <list> #include <algorithm> using namespace std; int main() { forward_list<int> f{1,2,3,4,5,4,5,1,2}; //sort the number by the remainder divided by 5 f.sort([](const int i,const int j){return (i%5 < j%5);}); //if remainder devided by 5 is the same,then equal f.unique([](int i,int j){return (i %5 == j %5);}); for(auto i : f)cout << i << endl;return 0; }總結:unique的二元謂詞參數,函數也是不加if。牛
第三部分:list的splice算法,forward_list的splice_after算法
#include <iostream> #include <string> #include <sstream> #include <fstream> #include <forward_list> #include <stack> #include <vector> #include <forward_list> #include <deque> #include <array> #include <list> #include <algorithm> using namespace std; int main() { /*forward_list*/ //member function 1:flst.splice_after(p,flst2),insert flst2 after p forward_list<int> f1{1,2,3,4,5,6}; forward_list<int> f2{11,22,33}; f1.splice_after(f1.begin(),f2); for(auto i : f1)cout << i << endl;//f2 has no elements for(auto j : f2)cout << j << endl;//member function 2:flst.splice_after(p,lst2,p2),move elements which pointed by p2's next interator //把p2位置之后的元素插入到p之后 forward_list<int> f21{21,23,24,35}; forward_list<int> f22{33,34,54,54}; f21.splice_after(f21.begin(),f22,++f22.begin()); for(auto i : f21)cout << i << " "; cout << endl; //member function3:flst.splice_after(p,lst2,b,e):把lst2中(b,e)中的元素移動到flst中p之后,注意(b,e)是兩邊開區間。 //把lst2的第二個到第五個元素移動到lst中 forward_list<int> lst{1,2,3,4}; forward_list<int> lst2{11,22,33,44,55,66,77,88}; int i = 0; forward_list<int>::iterator p1 = lst2.begin(),p2 =lst2.begin(); while(i !=5) { ++ p2; ++ i; } //now p2 point to 6th element of lst2,p1 point to 1th element of lst2 //注意這里(p1,p2)是兩邊開區間,因為forward_list本身的特性,是把p1后面且p2前面的元素移動到lst中 lst.splice_after(lst.before_begin(),lst2,p1,p2); cout << "lst is:" << endl; for(auto i : lst)cout << i << " ";cout << endl; /*list*/ list<int> l1{1,2,3,4,5}; list<int> l2{11,22,33}; list<int> l3{1024,1025,1026}; l1.splice(l1.begin(),l2); for(auto i : l1)cout << i << " "; cout << endl; cout << "list"<< " " << endl; //member function 2: insert element which pointed by l3.begin() into l1(before ++ l1.begin()) l1.splice(++l1.begin(),l3,l3.begin()); for(auto i : l1)cout << i << " "; cout << endl; //member function 3:lst.splice(p,lst2,b,e):把lst2中的[b,e)中的元素移動到lst中的p之前,注意[b,e)是前面閉區間,后面開區間.//把lst_new中第3-6個元素移動到lst2_new中 list<int> lst_new{20,21,22,23,24,25}; list<int> lst2_new{30,31,32,33,34,35,36,37,38}; int ii = 0,jj = 0; list<int>::iterator it1 = lst2_new.begin(); list<int>::iterator it2 = lst2_new.begin(); while(ii != 2) { it1 ++; ii ++; } while(jj != 6) { it2 ++; ++ jj; } lst_new.splice(lst_new.begin(),lst2_new,it1,it2); cout << "print:" << endl; for(auto i : lst_new)cout << i << " ";cout << endl; return 0; }總結:splice和splice_after算法的異同點:
1.splice是往給定迭代器前面插入,而splice_after是往給定的迭代器位置的后面插入,例如
lst.splice(p,lst2)在p的前面插入lst2,flst.splice_after(p,flst2)
lst.splice(p,lst2,p2)在p的前面插入lst2中p2所指元素,flst.splice(p,flst2,p2),把p2后面的一個元素插入到p的后面
lst.splice(p,lst2,b,e)在p的前面插入lst2中[b,e)的元素,flst.splice(p,flst2,b,e)? 把flst2中(b,e)的元素插入到p的后面
2.總結
lst.splice()插入的是【b,e)區間或者是某個迭代器p2所指的元素,往p的前面插入
lst.splice_after插入的是(b,e)區間的元素,或者是某個迭代器p2后面的一個元素,插入的范圍和插入的位置均不一樣,splice_after插入位置均位于某個迭代器之后,splice插入的位置是某個迭代器之前。
splice插入的元素正好是傳統上的p2所指的或者前開后9閉區間。而splice_after插入的元素是某個元素后面的元素或者是兩邊開區間范圍的元素。
相同點:都要插入和被插入的兩個鏈表(容器)的類型相同.要么都是list,要么都是forward_list
順便把那個課后習題也弄了把。下面就是自己編寫的答案:
10.6節習題自己編寫的答案
#include <iostream> #include <string> #include <sstream> #include <fstream> #include <forward_list> #include <stack> #include <vector> #include <forward_list> #include <deque> #include <array> #include <list> #include <algorithm> using namespace std;void print(const list<string> &);int main(int argc,char *argv[]) { //be careful:out must be specified to fstream::out or ofstream::out or //fstream::app,etc.. //注意,這里fstream 流的 out必須指明文件模式是 out模式或者app模式才能自動創建文件。否則打開文件會失敗。 fstream in,out(argv[2],ofstream::out); in.open(argv[1]); if(!out)cout << "open file failure" << endl;list<string> lstr; string str; while(in >> str) { lstr.push_back(str); } lstr.sort(); lstr.sort([](const string &s1,const string &s2){return (s1.size() < s2.size());}); lstr.unique(); print(lstr); cout << argv[1] << endl; cout << argv[2] << endl;for(auto i : lstr)out << i << endl;return 0; }void print(const list<string> &s) {for(auto i : s)cout << i << " ";}注意一點:c++輸出文件流要么指明是ofstream對象,如果是fstream對象必須指明out模式或者app模式才能自動創建文件。
也就是說,fstream文件流對象在不指名任何模式的情況下,編譯器不負責創建文件。
splice算法再舉個例子
//以下例子都運行過全部通過 #include <iostream> #include <string> #include <sstream> #include <fstream> #include <forward_list> #include <stack> #include <vector> #include <forward_list> #include <deque> #include <array> #include <list> #include <algorithm> using namespace std; int main() {forward_list<int> l1 {1,2,3,4,5},l2{6,7,8};//insert all elements of l2 to l1//l1.splice_after(l1.begin(),l2);//insert some element of l2 to l1//l1.splice_after(l1.before_begin(),l2,++l2.begin());//insert elements from a scope of l2 to l2,note that the scope is (),rather than [),becouse forward_listl1.splice_after(l1.before_begin(),l2,l2.begin(),l2.end());for(auto i : l1)cout << i << endl; return 0; }?
總結
以上是生活随笔為你收集整理的c++ 特定容器算法(sort,merge,reverse,remove,unique)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python3 测试函数的一个例子
- 下一篇: Ubuntu : 未找到 ‘nm-too