簡體   English   中英

C語言中二叉樹的分割錯誤

[英]segmentation fault in binary tree in C

我正在嘗試實現我的代碼以C語言創建一個二進制樹。該代碼沒有給出任何錯誤,但在運行時會導致分段錯誤。無法確定原因。 請幫忙。

#include<stdio.h>
#include<malloc.h>

struct node{
    int value;
    struct node *left;
    struct node *right;
}*root = NULL;

struct node* create(int val)
{
    struct node *ptr;
    ptr = (struct node*)malloc(sizeof(struct node));
    ptr->value = val;
    ptr->left = NULL;
    ptr->right = NULL;
    return ptr;
}

void insert(int val)
{
    if(root == NULL)
    {
        root=create(val);
    }
    else if(val < (root)->value)
    {
        (root)->left = create(val);
    }
    else
    {
        (root)->right = create(val);
    }
}

void traverse(struct node** root)
{   
    if(*root==NULL)
        printf("TREE EMPTY");
        return 0;
    while((*root)!=NULL)
    {
        printf("%d",(*root)->value);
        traverse((*root)->left);
        traverse((*root)->right);
    }
}

int main()
{
    int val;
    char ch='y';
    while(ch=='y')
    {
        scanf("%d",&val);
        insert(val);
        printf("Want to insert more elements ?(y or n) =");
        scanf("%c",ch);
    }
    traverse(&root);
    free(root);
    return 0;
}

正如@BLUEPIXY描述的分段錯誤通過解析變量的值而引起ch代替的地址ch 除此之外,您的代碼似乎還存在一些邏輯錯誤。

  1. 您的insert實現僅查看根節點,並根據根值將新值添加到其左或右子級。 插入的理想行為是向下搜索樹結構,直到到達葉節點,然后在此處插入新值。

  2. 如@BLUEPIXY所示, traverse函數中的while ((*root)!=NULL)等於while (true) ,因為根元素從未更新。 這里,再次, traverse功能的期望行為是導航樹結構(通常從左到右)並遞歸訪問當前節點的子代。 下面的代碼通過簡單地在每個兒童上調用traverse而沒有while循環,從而實現了一種簡單的方法。

  3. 最后,正如@BLUEPIXY指出的那樣,以root為參數調用free不會釋放整個樹。 Free僅釋放其參數指向的內存塊。 它不會以遞歸方式跟隨該內存塊中的指針。 為了釋放樹結構所擁有的所有資源,您需要再次遍歷樹並在每個節點上free調用。

以下代碼基於您的代碼,實現了二叉樹。 請注意,樹長大后不太可能保持平衡。 為了獲得平衡的二叉樹,您需要在插入新節點時對樹進行重塑。

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

typedef struct node{
    int value;
    struct node *left;
    struct node *right;
} node;

node *root = NULL;

node* create(int val)
{

    node *ptr;
    ptr = (node*)malloc(sizeof(node));
    ptr->value = val;
    ptr->left = NULL;
    ptr->right = NULL;
    return ptr;
}

void insert_(node *root, int val)
{
  if (val < root->value)
  {
    if (root->left != NULL)
    {
        insert_(root->left, val);
        } else {
        root->left = create(val);
        }
    }
    else
    {
        if (root->right != NULL)
        {
            insert_(root->right, val);
        } else {
            root->right = create(val);
        }
    }
}

void insert(int val)
{
    if(root == NULL)
    {
        root = create(val);
    }
    else
    {
        insert_(root, val);
    }
}

void traverse(node *root)
{
    if(root == NULL)
    {
        printf("E");
        return;
    }
    printf("%d (", root->value);
    traverse(root->left);
    printf( ") (");
    traverse(root->right);
    printf( ")");
}

void free_tree(node *root)
{
      if (root == NULL) {
            return;
      }
      free_tree(root->left);
      free_tree(root->right);
      free(root);
}

int main()
{
      int val;
      char ch='y';
      while(ch=='y')
      {
            scanf("%d",&val);
            insert(val);
            printf("Want to insert more elements ?(y or n) =");
            scanf(" %s", &ch);
      }
      traverse(root);
      free_tree(root);
      return 0;
}

問題出在您的traverse()函數上。

  1. 當您檢查根是否為NULL時,您就錯過了包含printf()語句並return 0語句的括號;

如果您不這樣做,那么它將首先檢查(root是否為NULL)是否是->然后打印語句“ TREE EMPTY”並返回; 如果沒有->它直接從函數返回。

void traverse ( struct node **root )
{
    if ( *root == NULL )
    {
        printf ("TREE EMPTY");
        return 0;
    }
    while ((*root) != NULL )
    {
        printf ("%d", (*root) -> value);
        traverse ((*root) -> left);
        traverse ((*root) -> right);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM