2016-07-16 2 views
-1

Я закодировал двоичное дерево поиска. Каждая функция работает нормально, но «делетод». Этот метод должен удалить узел, на который указывает * p.Двоичное дерево поиска, сбой удаления узла

Однако, если узел является листом, он печатает дерево без узла и сбой. Если узел не является листом, он даже не печатает дерево и не падает.

Я не вижу возможного способа воссоздать проблему в меньшем количестве кода, потому что я не знаю, где должна быть проблема. Извините.

Возможно, кто-то может загрузить его и посмотреть, где проблема, потому что им действительно отчаянно.

#include <stdio.h> 

void *malloc(size_t size); 
void free(void *ptr); 

struct tnode { 
    int content; 
    struct tnode *left; /* left subtree */ 
    struct tnode *right; /* right subtree */ 
}; 


struct tnode *talloc(void) /* reserves memory*/ 
{ 
    return (struct tnode *) malloc(sizeof(struct tnode)); 
} 

struct tnode *addelement(struct tnode *p, int i) /* addelement: adds new node */ 
{ 
    int cond; 
    if(p == NULL) { 
     p = talloc(); /* make a new node */ p->content = i; 
     p->left = p->right = NULL; 
    } else if(p->content == i) { 
     return p; 
    } else if(i < p->content) /* goes to the left side */ p->left = addelement(p->left, i); 
    else /* goes to the right side */ p->right = addelement(p->right, i); 
    return p; 
} 

struct tnode *addtree(struct tnode *top, struct tnode *p) /* adds subtree to main tree*/ 
{ 
    if(p == NULL) 
     return top; 
    else 
     return addtree(addtree(addelement(top, p->content), p->right), p->left); 
} 

int printtree_preorder(struct tnode *p) /* prints tree in preorder*/ 
{ 
    if(p != NULL) { 
     printf("%d \n", p->content); 
     printtree_preorder(p->left); 
     printtree_preorder(p->right); 
    } 
    return 0; 
} 

int printtree_inorder(struct tnode *p) /* prints tree in inorder*/ 
{ 
    if(p != NULL) { 
     printtree_inorder(p->left); 
     printf("%d \n", p->content); 
     printtree_inorder(p->right); 
    } 
    return 0; 
} 

int printtree_postorder(struct tnode *p) /* prints tree in postorder*/ 
{ 
    if(p != NULL) { 
     printtree_postorder(p->left); 
     printtree_postorder(p->right); 
     printf("%d \n", p->content); 
    } 
    return 0; 
} 

struct tnode *searchnode(struct tnode *p, int nodtodelete) /* pointer is set on the node which is supposed to be deleted */ 
{ 
    if(p == NULL) { 
     printf("Baum ist leer oder Element nicht vorhanden \n"); 
     return 0; 
    } 
    if(p->content == nodtodelete) { 
     return p; 
    } 
    if(p->content < nodtodelete) { 
     return searchnode(p->right, nodtodelete); 
    } 
    if(p->content > nodtodelete) { 
     return searchnode(p->left, nodtodelete); 
    } 
} 

struct tnode *deletenode(struct tnode *p, struct tnode *pBaum) /* Is supposed to delete the node which the *p is pointing at */ 
{ 
    if((p->left == NULL) && (p->right == NULL)) { 
     free(p); 
     printf("Ist Blatt \n"); 
     return pBaum; 
    } 
    if((p->left == NULL) && (p->right != NULL)) { 
     struct tnode *rechterTeilbaum = p->right; 
     free(p); 
     pBaum = addtree(pBaum, rechterTeilbaum); 
     return pBaum; 

    } 
    if((p->right == NULL) && (p->left != NULL)) { 
     struct tnode *linkerTeilbaum = p->left; 
     free(p); 
     pBaum = addtree(pBaum, linkerTeilbaum); 
     return pBaum; 
    } 
    if((p->left != NULL) && (p->right != NULL)) { 
     struct tnode *rechterTeilbaum = p->right; 
     struct tnode *linkerTeilbaum = p->left; 
     free(p); 
     pBaum = addtree(pBaum, rechterTeilbaum); 
     pBaum = addtree(pBaum, linkerTeilbaum); 
     return pBaum; 
    } 
} 

int main() { 
    struct tnode *Baum = NULL; 
    struct tnode *tmpPos = NULL; 

    Baum = addelement(Baum, 10); 
    Baum = addelement(Baum, 30); 
    Baum = addelement(Baum, 20); 
    Baum = addelement(Baum, 35); 

    tmpPos = searchnode(Baum, 35); 

    if(tmpPos != 0) { 
     printf("Zu loeschendes Element: %d \n", tmpPos->content); 
     Baum = deletenode(tmpPos, Baum); 
    } 

    printf("Inorder Ausgabe\n"); 
    printtree_inorder(Baum); 

    printf("Postorder Ausgabe\n"); 
    printtree_postorder(Baum); 

    printf("Preorder Ausgabe\n"); 
    printtree_preorder(Baum); 
} 
+0

Задайте себе вопрос: как получить внутренний узел, если один из его детей будет удален? То есть как он будет знать, если его «правильные» или «левые» указатели остаются действительными после того, как вы назвали 'deletenode'? Ваша программа выйдет из строя, потому что во время печати в какой-то момент вы пытаетесь разыменовать висячий указатель. – BeyelerStudios

+0

@BeyelerStudios, если я называю «deletenode», память, в которой указывается «p», очищается в каждом случае. Поэтому, если im correct, это также удалит указатель «left» и «right», который приведет к их недействительности. Если я ошибаюсь, не стесняйтесь сказать мне, как я могу решить свою проблему. –

+0

Вы ошибаетесь. Пожалуйста, прочитайте учебное пособие по указателям, то есть посмотрите на * болтающийся указатель *: необработанные указатели не обновляются магически (это простые адреса памяти), вам необходимо самостоятельно аннулировать «левый» и «правый» родителя удаленного узла. – BeyelerStudios

ответ

1

В функции deletenode, вы не проверять, если р NULL, прежде чем пытаться разыменования его. Вы преувеличиваете?

+0

Да, забыл добавить NULL чек, но im не segfault. –

+0

Итак, что же такое ошибка? –

+0

Im компилируя все с CodeBlocks, я не получаю никакие ошибки или предупреждения. Это просто говорит мне, что .exe перестает работать и падает. Если вы скомпилируете его самостоятельно, вы, скорее всего, увидите то же самое. –

Смежные вопросы