求1+2+3+...+N 不可以使用 * / 和循环 模板的偏特化和全特化

看到这个题,不考虑限定条件,我们可能会有两个方向
1.一个就是用等差数列公式m=n(n+1)/2直接就可以求出来了

2.用循环实现
但是上面都限定了。所以我们就要想办法了

我们知道,多数情况下,循环和递归是可以转换的
那么有这样一种最基本方法,我们用递归实现
#include <stdio.h>
#include <iostream>
using namespace std;

int Get_1_add_to_n(int n)
{
    if(n==1)
    {   
        return 1;
    }   
    return n+Get_1_add_to_n(n-1);
}
int main()
{
    int n=8;
    int ret=Get_1_add_to_n(n);
    cout<<ret<<endl;
    return 0;
}             

或者这样:

#include <stdio.h>                                                                                                                                         
  #include <iostream>
  using namespace std;
  
  
  class AA
  {
  public:
      AA()
      {   
          _sum=_sum+(++_count);
      }   
  
      static int _count;//定义静态数据成员
      static int _sum;
  };
  
  int AA::_count=0;//对静态数据成员进行初始化
  int AA::_sum=0;
  
  int main()
  {
      const int N=10;
      AA *p=new AA[N];
      cout<<AA::_sum<<endl;
      return 0;
  }

可是上面的两种方法都不是很优美的解法,因为这样的时间复杂度为O(N),我们是否有一种复杂度为O(1)的解法呢?

我们可以这样想,是否可以将一些操作放在代码编译的时候来做,这样代码运行起来的效率就高了呢。
有人很巧妙的利用到了这一点:

都是别人想的。我只是代码的搬运工:

#include <stdio.h>
#include <iostream>
using namespace std;

int main()
{
    const int N=10;
    char arr[N][N+1];
    char size=sizeof(arr)/sizeof(arr[0][0]);//N*(N+1)为数组的大小
    int ret=size>>1;//完美的利用了N(N+1)/2                                                                                               cout<<ret<<endl;
    return 0;
}

但是这种方法是不能运算比较大的数字的,栈上的空间是有限的,可以自己试一下
还有一种方法是这样的:

#include <stdio.h>
#include <iostream>
using namespace std;


template <int N>
class Sum
{
public:
    enum//这里是一个匿名枚举类型
    {
        RET=N+Sum<N-1>::RET,//递归的去计算N+(N-1)+...+1(不过是在编译时进行展开)
    };
};

//全特化
template <>
class Sum<1>//N为1时也是上面递归的出口
{
public:
    enum
    {
      RET=1,
    };
};

int main()
{
    const int N=10;
    cout<<Sum<N>::RET<<endl;
}

特化的概念是继模板提出来的
前面讲过,模板函数有其重载函数时,这时候就会调用重载函数,不会再去进行推演。

这里模板类中的 特化就是不管你调不调用都会生生成代码
template <typename T>
class SeqList
{
public :
SeqList();
~ SeqList();
private :
int _size ;
int _capacity ;
T* _data 
};

//必须有一个模板类的基础上才会有特化
template <>//全特化没有模板参数
class SeqList <int>//定义类时显示指定模板参数
{
public :
SeqList(int capacity);
~ SeqList();
private :
int _size ;
int _capacity ;
int* _data ;
};

 
 
上面举例的时 全特化,还有一种是 偏特化
看看下面的例子:

#include <stdio.h>
#include <iostream>
using namespace std;


template<class T1,class T2>
class Data
{
public:
    Data()
    {
        cout<<"<T1,T2>"<<endl;
    }
};


//*i*****************************全特化*************************
template<>
class Data<int ,int>
{
public:
    Data()
    {
        cout<<"<int,int>"<<endl;
    }
};

//*******************************偏特化**************************
template<class T2>
class Data<char,T2>//对T1进行偏特化
{
public:
    Data()
    {
        cout<<"<char,T2>"<<endl;
    }
};

template<class T1>
class Data<T1,char>//对T2进行偏特化
{
public:
    Data()
    {
        cout<<"<T1,char>"<<endl;
    }
};

template<class T1,class T2>
class Data<T1 *,T2 *>//对T1和T2进行偏特化,加限制条件
{
public:
    Data()
    {
        cout<<"<*T1,*T2>"<<endl;
    }
};

template<class T1,class T2>
class Data<T1 &,T2 &>//对T1和T2进行偏特化,加限制条件
{
public:
    Data()
    {
        cout<<"<int,T2>"<<endl;
    }
};

int main()
{
    Data<float,float> d0;
    Data<int ,int > d1;
    Data<int ,char> d2;
    Data<char,int>  d3;
    Data<int *,int *> d4;
    Data<int &,int &> d5;
    //Data<char,char> d6;
    return 0;
}
再结合上面的求1+2+3+...+N,中的模板中的枚举类型在编译时进行展开的例子来理解特化。

猜你喜欢

转载自blog.csdn.net/misszhoudandan/article/details/80340881