c++ specific container algorithm (sort, merge, reverse, remove, unique)

The following are all specific container algorithms, which are specific algorithms for c++, list and forward_list.

Part 1: Member function algorithm merge (for forward_list and list only)

1. On the page of c++ primer 5th p369, lst.merge(lst2) must have both lst and lst2 in order, but I write my own program. It is okay to have both lst and lst2 in order, 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;
}

The results of the above code running on ubuntu20.04 are as follows:

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

Question: This algorithm is not valid for different types of containers? In other words, one forward_list and the other a list cannot be merged. My own compiler is so.

If the master knows, tell me? Is it only possible to merge containers of the same type? ? ?

And why I added compare in the program, but the running results are not sorted? For, furnishings? Explain to me if you have a master? Please. Little beginner beginner.

Part 2: Algorithm 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);
}

Pay attention to a few issues:

1. If you use the algorithm remove, the parameter must be an element type value. If you use the algorithm remove_if, then the parameter is a function or lambda expression, in short, it is a unary predicate

2. The previous non-member function version of remove will not delete this element, because it is easy to delete this element after returning the position. But now the member function version remove or remove_if will directly delete this element. Because it is difficult to delete this element yourself. How humane.

Add a few more lines of code below, and review the bind function (used for parameter binding). To use it, you must first add the header file functional, and the namespace using namespace std::placeholders, not much nonsense, just go to the code:

#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);

}

The third part: reverse, the following code contains a lot of unnecessary header files.

#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;
}

Summary: Fortunately, this function is simple and did not encounter as much trouble as before.

The fourth part: sort, originally planned not to explain. Take a closer look, the version of sort with parameters does not add if, and you must write a program to run it:

 



#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;
}



The version of sort with binary predicate does not add if after it, really Nima Niu B.

Part 5: Unique, I won't introduce it briefly.

These two functions are overloaded functions. Is there an if difference between Nima's parameters and no parameters?

#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;
}

Summary: For unique binary predicate parameters, the function does not add if. Cattle

Part 3: Splice algorithm of list, splice_after algorithm of forward_list

#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;
}

Summary: The similarities and differences between splice and splice_after algorithms:

1. splice is inserted before the given iterator, and splice_after is inserted after the given iterator position, for example

lst.splice(p,lst2) insert lst2 before p, flst.splice_after(p,flst2)

lst.splice(p,lst2,p2) inserts the element pointed to by p2 in lst2 before p, flst.splice(p,flst2,p2), inserts an element after p2 into the back of p

lst.splice(p,lst2,b,e) inserts the element of [b,e) in lst2 before p , flst.splice(p,flst2,b,e) inserts the element of (b,e) in flst2 To the back of p

2. Summary

lst.splice() inserts the interval [b, e) or the element pointed to by an iterator p2, and inserts it in front of p

lst.splice_after inserts an element in the (b,e) interval, or an element after a certain iterator p2 , the inserted range and the inserted position are not the same, the splice_after insertion positions are all located after a certain iterator, splice The insertion position is before a certain iterator.

The element inserted by splice is exactly what the traditional p2 refers to or the 9-closed interval before opening. The element inserted by splice_after is an element behind an element or an element with a range of two sides.

Similarities: The types of the two linked lists (containers) that must be inserted and inserted are the same. Either both are list or forward_list

By the way, I also got rid of the exercises after class. Here is the answer I wrote:

10.6 self-written answers to exercises

#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 << " ";


}

Note: C++ output file stream must be specified as ofstream object, if it is fstream object, out mode or app mode must be specified to automatically create file.

In other words, the compiler is not responsible for creating files when the fstream file stream object does not name any mode.

Another example of splice algorithm

//以下例子都运行过全部通过
#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_list
 l1.splice_after(l1.before_begin(),l2,l2.begin(),l2.end());
 for(auto i : l1)
         cout << i << endl;
return 0;
}


 

Guess you like

Origin blog.csdn.net/digitalkee/article/details/112594071