昨天晚上有点兴奋,睡不着,哪知道又来惦记起了本主题,突然又想多说几句。
原来的代码中有这个遍历自然数,执行单元测试的类:
template< size_t N >
struct test_nature:public test_nature< N-1 >
{
test_nature():test_nature< N-1 >(){test(N);}
};
template<>
struct test_nature< 1 >
{
test_nature(){test(1);}
};
就模板的嵌套深度而言,深度达到N.多一点编译器就会报错了,现在我们就来优化它。
(哥现在并没有写代码,正边写边想哦)
首先的思路是在构造函数中多执行一次测试用例,深度立即减少到N/2.
template< size_t N >
struct test_nature:public test_nature< N-2 >
{
test_nature():test_nature< N-2 >(){test(N);test(N-1);}
};
再对N=2,N=1进行特化就可以了。复杂度可谓线性下降。
不过继承关系图是一个树形结构图,我们还可以把复杂度设法转化为对数复杂度。
思路:继承关系图中的树我们需要进行遍历整棵树,我们设法构造一棵树。复杂度立即下降到log2N。
算法一:设根节点为N,执行先序构造和后序遍历(先构造出继承关系,再让构造函数去遍历。注意这里的“构造”和“遍历”2词的含义)。然后如何构造子树呢?这是一个问题,规定策略如下:左节点是根节点左节点和当前最大的已构造节点的平均数,右节点是N-1(如果N-1已经在左树中有了,就不构造右节点)。
用几个图来说明。字体有点怪哈,不好意思。
这个构造法用模板实现有一定难度。用树结构来遍历则意味着需要用多继承,注意在生成右子树时要告诉她当前新的最大的已构造节点。
上面这个是个不支持vc6的版本,编译速度大幅度提高,codepad.org在线编译器可以支持300的输出,大约超过300后不再报嵌套过深而是编译时间超时错误。
首先定一个空节点标记static const size_t stop_tag = size_t (-1);
支持vc6的版本:
因为有不定多个空节点,我们不得不使用虚继承来重复继承空节点。其实不用继承,用组合是完全可以的.从数据结构讲到设计模式了,呵呵.
有机会我再来生成一棵满树,一棵avl树,一棵红黑树,呵呵.今天说到这里了.
哦对了,今天生成的树就是avl树,我最喜欢的一种树。我甚至在毫无意识的情况下就构造出了它,直到我输出结果我才看见我其实构造的是avl树,留给大家优化的空间已经不多了。改日还是做红黑树吧。