简体   繁体   English

二叉树的分段错误

[英]Segmentation fault on binary tree

I'm working on a program that searches through a program and outputs the number of times it comes across a number greater than or equal to the value specified in the parameter of the function.我正在开发一个程序,该程序搜索程序并输出它遇到大于或等于函数参数中指定的值的数字的次数。 I have attached my code below, I see it traverses two of the values before a segmentation fault occurs.我在下面附上了我的代码,我看到它在发生分段错误之前遍历了两个值。 The segmentation fault error points to return count + count_values(value, here) + count_values(value, current);分段错误错误指向return count + count_values(value, here) + count_values(value, current);

typedef struct BinaryTree {
    int val;
    struct BinaryTree *left;
    struct BinaryTree *right;
} BinaryTree;

BinaryTree *build_tree(int value, BinaryTree *leftnode, BinaryTree *rightnode) {
    BinaryTree *out = calloc(1, sizeof(BinaryTree));
    out->val = value;
    out->leftnode = leftnode;
    out->rightnode = rightnode;

    return out;
}

int count_values(int value, BinaryTree *tree) {
  
    BinaryTree *current = tree;
    BinaryTree *here = current;
    int count = 0;

    if (current != NULL) {
        printf("Value in tree is not NULL\n");

        if (current->val < value) {
            printf("%d < %d\n", current->val, value);
            printf("Count value: %d\n", count);
            here = current->leftnode;
            count_values(value, here);
            current = current->rightnode;
            count_values(value, current);

        } else if (current->val == value) {
            printf("%d = %d\n", current->val, value);
            count++;
            printf("Count value: %d\n", count);
            here = current->leftnode;
            count_values(value, here);
            current = current->rightnode;
            count_values(value, current);
        } else {
            printf("%d > %d\n", current->val, value);
            count++;
            printf("Count value: %d\n", count);
            here = current->leftnode;
            count_values(value, here);
            current = current->rightnode;
            count_values(value, current);
        }
    }
        
    return count + count_values(value, here) + count_values(value, current);
}

int main(void) {
    BinaryTree *tree =
        build_tree(14, build_tree(3, NULL, NULL),
                   build_tree(15, NULL, build_tree(42, NULL, NULL)));

    //path is 14->15->42
    int count = count_values(42, tree);
    printf("should have a count of 1, got %d\n", count);

    count = count_values(14, tree);
    printf("should have a count of 3, got %d\n", count);

    return 0;
}

For starters there are typos in the both functions as for example对于初学者来说,这两个功能都有拼写错误,例如

out->leftnode = leftnode;
out->rightnode = rightnode;

and

here = current->leftnode;
current = current->rightnode;

You have to write你必须写

out->left = leftnode;
out->right = rightnode;

and

here = current->left;
current = current->right;

Within the function count_values already this if statement在函数count_values已经有这个 if 语句

if (current->val != NULL) {

invokes undefined behavior.调用未定义的行为。

First of all it does not make a sense.首先,它没有任何意义。 And secondly before accessing data members of a node you need to check whether the pointer current (more precisely the pointer tree ) is a null pointer or not.其次,在访问节点的数据成员之前,您需要检查指针current (更准确地说是指针tree )是否为空指针。

Pay attention to that such statements like these注意像这样的陈述

count_values(value, here);
count_values(value, current);

in fact have no effect.实际上没有任何效果。

The recursive function could be defined the following way递归函数可以通过以下方式定义

size_t count_values( const BinaryTree *tree, int value ) 
{
    return tree == NULL 
        ? 0 
        : ( tree->val >= value ) + count_values( tree->left, value ) + count_values( tree->right, value );
}    

The pointer to the tree should be the first function parameter and declared with the qualifier const because the function does not change the tree.指向树的指针应该是第一个函数参数并使用限定符const声明,因为该函数不会更改树。 And the function should return an object of an unsigned integer type because the counter can not be a negative value.并且该函数应该返回一个无符号整数类型的对象,因为计数器不能是负值。 Instead of the return type size_t you may use for example the type unsigned int .您可以使用例如unsigned int类型而不是返回类型size_t

Here is a demonstration program.这是一个演示程序。

#include <stdio.h>
#include <stdlib.h>

typedef struct BinaryTree {
    int val;
    struct BinaryTree *left;
    struct BinaryTree *right;
} BinaryTree;

BinaryTree *build_tree(int value, BinaryTree *leftnode, BinaryTree *rightnode) {
    BinaryTree *out = calloc(1, sizeof(BinaryTree));
    out->val = value;
    out->left = leftnode;
    out->right = rightnode;

    return out;
}

size_t count_values( const BinaryTree *tree, int value ) 
{
    return tree == NULL 
        ? 0 
        : ( tree->val >= value ) + count_values( tree->left, value ) + count_values( tree->right, value );
} 

int main(void) {
    BinaryTree *tree =
        build_tree(14, build_tree(3, NULL, NULL),
                   build_tree(15, NULL, build_tree(42, NULL, NULL)));

    //path is 14->15->42
    size_t count = count_values( tree, 42);
    printf("should have a count of 1, got %zu\n", count);

    count = count_values(tree, 14 );
    printf("should have a count of 3, got %zu\n", count);

    return 0;
}

Its output is它的输出是

should have a count of 1, got 1
should have a count of 3, got 3

You're making this way harder than it needs to be.你让这种方式变得比它需要的更难。

First test for the base case by testing whether tree is NULL .首先通过测试tree是否为NULL来测试基本情况。

If not, recurse on the left and right nodes, and add these counts to the count for the current node.如果不是,则在左右节点上递归,并将这些计数添加到当前节点的计数中。

int count_values(int value, BinaryTree *tree) {
    if (tree == NULL) {
        return 0;
    }

    int count = tree->val >= value;
    count += count_values(value, tree->left);
    count += count_values(value, tree->right);

    return count;
}
  1. In if (current->val != NULL) { current->value can never be NULL pointer as value isn't pointer.if (current->val != NULL) { current->value 永远不能是 NULL 指针,因为值不是指针。 It is just int.它只是整数。 You probably should check current instead of current->val您可能应该检查current而不是current->val
  2. Even if you corrected that line your's program would segfault cause to stack overflow (hehe) because you unconditionally call your function from itself in return count + count_values(value, here) + count_values(value, current);即使您更正了该行,您的程序也会出现段错误导致堆栈溢出(呵呵),因为您在return count + count_values(value, here) + count_values(value, current); line线

PS the code you posted needed some adjustments to build. PS您发布的代码需要一些调整才能构建。 Fix it if you can可以的话修一下

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM