NOIP--数据结构C++算法实现 - 合并两序列

 1 、数据结构算法

 

 

先讲一下本文主要要用到的稍微高级一点而重要的一些C++基础:

1. C++模板:

    模板简单的来说就是可以让你定义一个通用的类型,模板的关键字为typename和class,这两个关键字用在模板中基本上是一样的作用。class是旧的关键字,现在都建议用typename,这样是为了避免和类关键字class混淆。

template<typename T>
void mergeList(vector<T> &t, vector<T> &t1, vector<T> &t2);

这样你就可以定义你的函数的时候把T当做比如int,double,vector,甚至是你自己定义的类来使用了。模板很多书都把它放到书本的后面介绍了,好像很高级似的,其实用多几次就一点都不神秘。

2.Function Objects 函数对象

(下面内容翻译引用 The C++ Programming Language 这本书的部分内容,部分自己写)

又叫functor;其实就是一个类,不过这种类可以当做函数一样来调用。 也可以说表面上是一个类,不过用法确实像函数一样来使用。

如:

[cpp]

  1. template<typename T>  

  2. class Less_than {  

  3. const T val; // value to compare against  

  4. public:  

  5. Less_than(const T& v) :val(v) { }  

  6. bool operator()(const T& x) const { return x<val; } // call operator  

  7. };  

函数调用operator()执行函数调用,调用操作符();

初始化:

[cpp]

  1. Less_than<int> lti {42}; // lti(i) will compare i to 42 using < (i<42)  

  2. Less_than<string> lts {"Backus"}; // lts(s) will compare s to "Backus" using < (s<"Backus")  

然后我们就可以调用这样的对象,就好像我们调用函数一样:

[cpp]

  1. void fct(int n, const string & s)  

  2. {  

  3. bool b1 = lti(n); // true if n<42  

  4. bool b2 = lts(s); // true if s<"Backus"  

  5. // ...  

  6. }  

如果用好STL就知道其实这样的函数对象是很常用的。
而且大家不要以为这样定义一个类,执行效率会下降,其实恰恰相反,这样的函数对象可以内置(inline),函数对象调用实际上比直接调用函数更加快。而且函数对象可以自带数据,把数据和操作结合起来(正是类的优点),我们不用再去定义更多的变量,这也是它的美丽之处。函数对象自带数据和高效性使得函数对象在作为算法参数的时候特别有用。

下面是合并两序列的算法程序:

[cpp]

  1. /***** 

  2. 已知两线性表中的数据元素按值非递减排列,归并两线性表到新的线性表,是的数据元素也按值非递减排列 

  3. *****/  

  4. #include<iostream>  

  5. #include<vector>  

  6. using namespace std;  

  7.   

  8. template<typename T>  

  9. void mergeList(vector<T> &t, vector<T> &t1, vector<T> &t2)  

  10. {  

  11.     auto iter1=t1.begin(), iter2=t2.begin();  

  12.     while(iter1!=t1.end() && iter2!=t2.end())  

  13.     {  

  14.         if(*iter1<=*iter2)  

  15.         {  

  16.             t.push_back(*iter1);  

  17.             ++iter1;  

  18.         }  

  19.         else  

  20.         {  

  21.             t.push_back(*iter2);  

  22.             ++iter2;  

  23.         }  

  24.     }  

  25.     while(iter1!=t1.end())  

  26.     {  

  27.         t.push_back(*iter1);  

  28.         iter1++;  

  29.     }  

  30.     while(iter2!=t2.end())  

  31.     {  

  32.         t.push_back(*iter2);  

  33.         iter2++;  

  34.     }  

  35. }  

  36.   

  37. template<class C, class Oper>  

  38. void for_all(C &c, Oper op)  

  39. {  

  40.     for(auto x:c)   //C++新特性,记住其实就是一种方便循环遍历数据的写法  

  41.         op(x);  

  42. }/*写一个通用的函数,增加其可重用性,配合下面的Print函数就可以打印各种不同的数据到屏幕,非常方便。*/  

  43.   

  44. template<typename T>  

  45. class Print  

  46. {  

  47. public:  

  48.     Print(){}  

  49.     void operator()(const T& x) const{cout<<x<<" ";}  

  50. };//这就是函数对象,这里并没有带数据,只是一个简单的输出操作。  

  51.   

  52. int main()  

  53. {  

  54.     int a[4]={1,2,5,8};   

  55.     vector<int> vecI1(a,a+4);  

  56.     //vecI1={1,2,5,8};这个写法是C++11的新标准,可惜的是VS2012还不支持,只能用就的初始化了  

  57.     int b[7]={2,4,5,7,9,10,30};  

  58.     vector<int> vecI2(b,b+7);  

  59.     vector<int> vecI;  

  60.     mergeList(vecI, vecI1, vecI2);//不局限是vector<int>类型  

  61.     for_all(vecI,Print<int>());  

  62.     cout<<endl;  

  63.     return 0;  

  64. }  

总结:

主要的算法函数就是mergeList,本算法并不难,拿本程序,左改改,右改改,就很快可以掌握这个算法了,也可以同时学学C++一举两得。也可以换一换排序的数据类型,其实本程序还支持一般的数组排序。

 

NOIP信息学视频地址

视频地址

链接:https://pan.baidu.com/s/1tHo1DFMaDuMZAemNH60dmw 
提取码:7jgr

posted @ 2020-10-26 15:02  tianli3151  阅读(218)  评论(0编辑  收藏  举报