Sum Tree问题中递归solve函数无return语句却运行正常?求解疑问
关于Sum Tree问题中递归函数无return分支的行为疑问
我正在解决GeeksforGeeks上的Sum Tree问题,题目要求:给定一棵二叉树,若除叶子节点外的每个节点X的值等于其左子树和右子树的节点值之和,则返回true,否则返回false;空树和叶子节点也视为Sum Tree。
我的代码通过了多个测试用例,但发现递归函数solve在部分分支未执行return语句却能正常运行,似乎存在可依赖的默认返回值,想请教这一现象的原因。
GeeksforGeeks驱动代码
#include <bits/stdc++.h> using namespace std; struct Node { int data; struct Node *left; struct Node *right; }; // Utility function to create a new Tree Node Node* newNode(int val) { Node* temp = new Node; temp->data = val; temp->left = NULL; temp->right = NULL; return temp; } // Function to Build Tree Node* buildTree(string str) { // Corner Case if(str.length() == 0 || str[0] == 'N') return NULL; // Creating vector of strings from input // string after spliting by space vector<string> ip; istringstream iss(str); for(string str; iss >> str; ) ip.push_back(str); // Create the root of the tree Node* root = newNode(stoi(ip[0])); // Push the root to the queue queue<Node*> queue; queue.push(root); // Starting from the second element int i = 1; while(!queue.empty() && i < ip.size()) { // Get and remove the front of the queue Node* currNode = queue.front(); queue.pop(); // Get the current node's value from the string string currVal = ip[i]; // If the left child is not null if(currVal != "N") { // Create the left child for the current node currNode->left = newNode(stoi(currVal)); // Push it to the queue queue.push(currNode->left); } // For the right child i++; if(i >= ip.size()) break; currVal = ip[i]; // If the right child is not null if(currVal != "N") { // Create the right child for the current node currNode->right = newNode(stoi(currVal)); // Push it to the queue queue.push(currNode->right); } i++; } return root; } // } Driver Code Ends // Solution class comes here // ... see my code in next code block ... // //{ Driver Code Starts. int main() { int t; scanf("%d ",&t); while(t--) { string s; getline(cin,s); Node* root = buildTree(s); Solution ob; cout <<ob.isSumTree(root) << endl; } return 1; } // } Driver Code Ends
我的实现代码
class Solution { public: // int returnSum=0; // Should return true if tree is Sum Tree, else false int solve(Node* root, int& sumofSubtree){ if(root==NULL){ return 0; } int l = solve(root->left, sumofSubtree); int r = solve(root->right, sumofSubtree); // int sum = l+r; sumofSubtree = l+r+root->data; if(sumofSubtree-root->data == root->data){ return sumofSubtree; } } bool isSumTree(Node* root) { //Main Function int sumofSubtree = 0; solve(root, sumofSubtree); cout<<"sumofSubtree"<<" : "<<sumofSubtree<<endl; // if(sumofSubtree-root->data==root->data || sumofSubtree == root->data){ return true; } else{ return false; } } };
问题解答
核心原因:未定义行为
在C++中,非void类型的函数必须在所有代码路径中显式返回值,否则属于未定义行为。编译器不会强制报错,但程序运行时会返回栈上的随机残留值,这不是什么“默认返回值”,完全不可靠。
你的代码能“正常运行”只是巧合:
- 你的
isSumTree函数并没有使用solve的返回值,只用到了引用参数sumofSubtree,所以即使solve返回随机值,也没影响主逻辑; - 当
solve的if条件不满足时,栈中刚好有某个值被当作返回值返回,但这完全是运气,换编译器、编译选项或测试用例,程序可能直接崩溃或输出错误结果。
额外问题:代码逻辑缺陷
你的代码只检查了根节点是否符合Sum Tree条件,没有递归验证所有子节点,这也是为什么部分测试用例能过,但本质逻辑错误。比如如果根节点符合条件,但某个子节点不符合,你的代码会错误返回true。
修复后的代码
正确的实现需要递归检查每个节点,同时计算子树和:
class Solution { public: // 返回值:pair<子树节点值总和, 该子树是否为Sum Tree> pair<int, bool> checkSumTree(Node* root) { if (!root) { return {0, true}; } // 叶子节点直接符合条件 if (!root->left && !root->right) { return {root->data, true}; } auto leftRes = checkSumTree(root->left); auto rightRes = checkSumTree(root->right); // 当前节点值等于左右子树和,且左右子树都是Sum Tree bool isValid = (root->data == leftRes.first + rightRes.first) && leftRes.second && rightRes.second; // 当前子树的总和是自身值加左右子树总和 int totalSum = root->data + leftRes.first + rightRes.first; return {totalSum, isValid}; } bool isSumTree(Node* root) { return checkSumTree(root).second; } };
内容的提问来源于stack exchange,提问作者Baljit Singh
相关产品推荐
相关产品推荐

