返回递归三元怪胎

Dav*_*nco 5 c++ recursion binary-tree

假设以下功能:

int binaryTree::findHeight(node *n) {
    if (n == NULL) {
        return 0;
    } else {
        return 1 + max(findHeight(n->left), findHeight(n->right));
    }
}
Run Code Online (Sandbox Code Playgroud)

treeHeight对于给定的二叉搜索树,相当标准的递归函数binaryTree.现在,我正在帮助一个朋友(他正在学习算法课程),我遇到了一个奇怪的问题,我无法100%向他解释这个功能.

将max定义为max(a,b) ((a)>(b)?(a):(b))(恰好是最大定义windef.h),递归函数变得怪异(它运行的n^n时间就像n树高一样).这显然使得检查具有3000个元素的树的高度非常非常长.

但是,如果max是通过模板定义的,就像std它一样,一切都很好.所以使用std::max修复他的问题.我只想知道原因.

另外,为什么countLeaves函数工作正常,使用相同的程序递归?

int binaryTree::countLeaves(node *n) {
    if (n == NULL) {
        return 0;
    } else if (n->left == NULL && n->right == NULL) {
        return 1;
    } else {
        return countLeaves(n->left) + countLeaves(n->right);
    }
}
Run Code Online (Sandbox Code Playgroud)

是因为在返回三元函数时,值a => countLeaves(n->left)b => countLeaves(n->right)递归双重调用只是因为它们是结果?

谢谢!

下面回答了这个问题

我只想链接一些有关该主题的文献以供将来参考:
http://www.boostpro.com/tmpbook/preprocessor.html
http://msdn.microsoft.com/en-us/library/z3f89ch8.aspx

这两种实现的主要区别在于:

#define max(i, j) (((i) > (j)) ? (i) : (j))
Run Code Online (Sandbox Code Playgroud)

VS

template<class T> T max (T i, T j) { return ((i > j) ? i : j) }
Run Code Online (Sandbox Code Playgroud)

谢谢你们!

GMa*_*ckG 11

在编译器查看代码之前,宏由预处理器进行扩展.这意味着,例如,宏参数可能会被多次评估.

使用你的宏,你最终会得到类似于:

int binaryTree::findHeight(node *n) {
    if (n == NULL) {
        return 0;
    } else {
        return 1 + (findHeight(n->left) > findHeight(n->right)) ? // call once...
                    findHeight(n->left) : findHeight(n->right); // and ouch
    }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,它将评估两个函数,然后再评估一个额外的时间.这就是为什么宏可能是邪恶的.

您可以通过NOMINMAX在包含Windows标头之前定义来禁用宏.然后使用该函数<algorithm>.

如果他必须使用宏,他必须将计算存储在一个变量中:

int binaryTree::findHeight(node *n) {
    if (n == NULL) {
        return 0;
    } else {
        const int leftHeight = findHeight(n->left);
        const int rightHeight = findHeight(n->right);
        return 1 + max(leftHeight, rightHeight);
    }
}
Run Code Online (Sandbox Code Playgroud)

使用函数,将调用函数之前评估每个调用.也就是说,它有点像以前的代码块.它评估函数的参数,获取结果,然后将它们传递给std::max函数.没有重复的评估.

  • 和该死的.当电源在我家闪烁时,我把这一切写进了所有内容.FUUUU- (2认同)