【问题标题】:Segmentation fault when trying to create an avl tree of strings尝试创建字符串的 avl 树时出现分段错误
【发布时间】:2014-08-07 14:01:08
【问题描述】:

我来自Java背景,我认为学习c会很好,因为我决定阅读一本数据结构书籍并在阅读时学习语言语法,但现在我遇到了一个问题,我'我试图创建一个 avl 树,其中它的键值将是一个字符串,但是当我尝试将我书中使用 int 的示例中的示例转换为 char* 时,编译器只会显示分段错误错误:( 这是我的代码:

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

// An AVL tree node
struct node {
    char *key;
    struct node *left;
    struct node *right;
    int height;
};

// A utility function to get maximum of two integers
int max(int a, int b);

// A utility function to get height of the tree
int height(struct node *N) {
    if (N == NULL)
        return 0;
    return N->height;
}

// A utility function to get maximum of two integers
int max(int a, int b) {
    return (a > b) ? a : b;
}

/* Helper function that allocates a new node with the given key and
 NULL left and right pointers. */
struct node* newNode(char *key) {
    struct node* node = (struct node*) malloc(sizeof(struct node));
    node->key = strdup(key);
    node->left = NULL;
    node->right = NULL;
    node->height = 1;  // new node is initially added at leaf
    return (node);
}

// A utility function to right rotate subtree rooted with y
// See the diagram given above.
struct node *rightRotate(struct node *y) {
    struct node *x = y->left;
    struct node *T2 = x->right;

    // Perform rotation
    x->right = y;
    y->left = T2;

    // Update heights
    y->height = max(height(y->left), height(y->right)) + 1;
    x->height = max(height(x->left), height(x->right)) + 1;

    // Return new root
    return x;
}

// A utility function to left rotate subtree rooted with x
// See the diagram given above.
struct node *leftRotate(struct node *x) {
    struct node *y = x->right;
    struct node *T2 = y->left;

    // Perform rotation
    y->left = x;
    x->right = T2;

    //  Update heights
    x->height = max(height(x->left), height(x->right)) + 1;
    y->height = max(height(y->left), height(y->right)) + 1;

    // Return new root
    return y;
}

// Get Balance factor of node N
int getBalance(struct node *N) {
    if (N == NULL)
        return 0;
    return height(N->left) - height(N->right);
}

struct node* insert(struct node* node, char *key) {
    /* 1.  Perform the normal BST rotation */
    if (node == NULL)
        return (newNode(key));

    if (strcmp(key, node->key) < 0)
        node->left = insert(node->left, key);
    else
        node->right = insert(node->right, key);

    /* 2. Update height of this ancestor node */
    node->height = max(height(node->left), height(node->right)) + 1;

    /* 3. Get the balance factor of this ancestor node to check whether
     this node became unbalanced */
    int balance = getBalance(node);

    // If this node becomes unbalanced, then there are 4 cases

    // Left Left Case
    if (balance > 1 && key < node->left->key)
        return rightRotate(node);

    // Right Right Case
    if (balance < -1 && key > node->right->key)
        return leftRotate(node);

    // Left Right Case
    if (balance > 1 && key > node->left->key) {
        node->left = leftRotate(node->left);
        return rightRotate(node);
    }

    // Right Left Case
    if (balance < -1 && key < node->right->key) {
        node->right = rightRotate(node->right);
        return leftRotate(node);
    }

    /* return the (unchanged) node pointer */
    return node;
}

// A utility function to print preorder traversal of the tree.
// The function also prints height of every node
void preOrder(struct node *root) {
    if (root != NULL) {
        printf("%d ", root->key);
        preOrder(root->left);
        preOrder(root->right);
    }
}

/* Drier program to test above function*/
int main() {
    struct node *root = NULL;

    /* Constructing tree given in the above figure */
    root = insert(root, "10");
    root = insert(root, "20");
    root = insert(root, "30");
    root = insert(root, "40");
    root = insert(root, "50");
    root = insert(root, "25");

    /* The constructed AVL Tree would be
     30
     /  \
         20   40
     /  \     \
       10  25    50
     */

    printf("Pre order traversal of the constructed AVL tree is \n");
    preOrder(root);

    return 0;
}

【问题讨论】:

  • printf("%d ", root-&gt;key); 应该是%s,因为root-&gt;keychar *
  • rightRotate 不检查 nullptr,y->left 可能是 nullptr。
  • @bezzi I come from a Java background and I thought it'd be nice to learn c 但您也将您的问题标记为C++。在 C++ 中,您应该使用 std::string 代替 char *。此外,在 C++ 中不需要 typedef struct 并在整个位置(除了类型的定义)指定关键字 struct。此外,动态分配通常最好使用newdelete 完成(还提到您未能释放您分配的任何内存。那么您是学习C 还是学习C++?
  • 是的,那个标签是错误的,我会删除它,谢谢你的提示:D
  • 实际上在 C 中做 #include &lt;string&gt; 是行不通的...

标签: c data-structures binary-tree avl-tree


【解决方案1】:

你需要使用strcmp,因为你正在从int转换为char,你可以学到更多关于这个主题阅读有关伟大的 c 编程语言的标准书籍

【讨论】:

    【解决方案2】:

    当您将键类型从int 更改为char * 时,您正确地将插入步骤更改为使用strcmp,但重新平衡步骤仍对字符串使用&lt; 运算符。这打破了代码关于某些节点为非 NULL 的假设。通过更新 left-left/left-right/etc 案例的条件以也使用strcmp,代码可以按预期工作。

    另外,正如我在 cmets 中提到的,您应该将 printf 更改为使用 %s 而不是 %d

    【讨论】:

    • 在不赞成票的同时发表评论会很好 - 我用我建议的更改测试了代码,它运行良好。
    【解决方案3】:

    rightRotate() 中,如果x-&gt;rightNULL,则需要先调用newNode() 来创建节点,然后再分配给T2。我怀疑整个代码中还有其他类似的地方。

    【讨论】:

    • 这并不能解决问题的根源。
    猜你喜欢
    • 2016-06-16
    • 2011-09-03
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-18
    • 2020-06-24
    • 1970-01-01
    相关资源
    最近更新 更多