You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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类型的函数必须在所有代码路径中显式返回值,否则属于未定义行为。编译器不会强制报错,但程序运行时会返回栈上的随机残留值,这不是什么“默认返回值”,完全不可靠。

你的代码能“正常运行”只是巧合:

  1. 你的isSumTree函数并没有使用solve的返回值,只用到了引用参数sumofSubtree,所以即使solve返回随机值,也没影响主逻辑;
  2. 当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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 14:22:50