2017-09-22 115 views
2

正如标题所说,我试图从具有2例树中删除一个节点:麻烦试图消除从树中的节点(结构)

  • 的节点是没有连接到任何一个叶子
  • 节点连接到另一个节点

我能够做出第二种情况下工作的功能(对我来说最困难的),但第一个(似乎容易)引起分段错误没有不管我尝试什么。

这里是结构的定义:

struct node { 
    int value; 
    struct node *sx; 
    struct node *dx; 
}; 

typedef struct node *tree; 

这里是执行消除操作的模块:

void destroy_node(tree Y, int elem) { 
    if (Y->value < elem) 
     destroy_node(Y->dx, elem); 
    if (Y->value > elem) 
     destroy_node(Y->sx, elem); 
    else { // 
     if (Y->sx == NULL && Y->dx == NULL) { 
      free(Y); <-- seg fault 
      Y = NULL; <-- seg fault 
     } 
     if (Y->sx != NULL && Y->dx == NULL) { 
      Y->value = (Y->sx)->value; 
      free(Y->sx); 
      Y->sx = NULL; 
     } 
     if (Y->sx == NULL && Y->dx != NULL) { 
      Y->value = (Y->dx)->value; 
      free(Y->dx); 
      Y->dx = NULL; 
     } 
     if (Y->sx != NULL && Y->dx != NULL) 
      printf("Can't eliminate that!\n"); 
    } 
    print_everything(Y); 
} 

这里是main电话:

tree Y = T; 
printf("Which one you want to destroy? "); 
scanf("%d", &elem); 
destroy_node(Y, elem); 

要编译函数我使用命令

gcc -std=gnu99 -Wall -Wextra c.c 

我的环境是虚拟机的Ubuntu 17.04与股票GCC

是构建树

tree insert_node(tree T, int val) { 
    if (T == NULL) {  
     T = (tree)malloc(sizeof(struct node)); 
     T->value = val; 
     T->sx = NULL; 
     T->dx = NULL; 
    } else { 
     if ((T->value) < (val)) { 
      T->dx = insert_node(T->dx, val); 
     } 
     if ((T->value) > (val)) { 
      T->sx = insert_node(T->sx, val); 
     } 
    } 
    return T; 
} 

在这里有主的通话EDIT 1

模块此模块

printf("How many nodes your tree will have? "); 
scanf("%d", &tot); 
for (int i = 0; i < tot; i++) { 
    printf("What is the %d° node? ", (i + 1)); 
    scanf("%d", &val); 
    T = insert_node(T, val); 
} 

P.S.如果有关于节目我会复制粘贴整个文件

+0

你可以添加你建树的地方吗? – atru

+0

@atru插入了您请求的其他函数,希望它有帮助 – Allen

+0

您忘记检查'Y'是否为空。 –

回答

0

有你的功能缺件的可理解性问题:

  • 你不检查是否Y != NULL。你会在空树上有未定义的行为。
  • 第一个if声明后还有一个缺失。如果Y->value <= elem错误地删除节点。
  • 当您删除节点时,您不会更新父指针。

您应该更改API返回的指针参数更新值:

tree destroy_node(tree Y, int elem) { 
    tree res = Y; 
    if (Y != NULL) { 
     if (Y->value < elem) { 
      Y->dx = destroy_node(Y->dx, elem); 
     } else 
     if (Y->value > elem) { 
      Y->sx = destroy_node(Y->sx, elem); 
     } else { 
     if (Y->dx == NULL) { 
      res = Y->sx; 
      free(Y); 
     } else 
     if (Y->sx == NULL) { 
      res = Y->dx; 
      free(Y); 
     } else { 
      printf("Can't eliminate that!\n"); 
     } 
    } 
    return res; 
} 

呼叫从main为:

tree T; 
... 
printf("Which one you want to destroy? "); 
if (scanf("%d", &elem) == 1) 
    T = destroy_node(T, elem); 

当然,你必须找到一个解决方案,以删除节点有2个分支。

+0

立即使用我的代码。很明显,我会找到一个解决方案来删除具有2个分支的节点,但我通常尝试从一个小代码开始工作,然后添加新函数以避免太多混淆(和错误)。顺便说一句,谢谢 – Allen

+0

@艾伦:这是一个很好的方法。重新读取代码,我意识到'if(Y-> sx == NULL && Y-> dx == NULL)'测试是多余的。答复更新和简化。 – chqrlie