2016-04-24 3 views
0

Итак, у меня есть код для двоичного дерева поиска в C, который отлично подходит для меня. Однако, когда я добавляю код для удаления BST, моя программа выйдет из строя во время этого удаления.AVL Tree Deletion вызывает программу для сбоя

Это дает мне сообщение об ошибке Доступ к чтению с недоверием 0x00000000.

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

В любом случае, вот мой код для моего удаления AVL. Если бы вы могли помочь мне в работе моей программы и помочь мне понять, что я сделал не так, я был бы очень благодарен. Я также включу свою функцию для поиска минимального узла, потому что я чувствую, что это может быть преступником.

AVL min_node(AVL self) 
{ 
    /* A AVL node to keep track of the current node. */ 
    AVL current = self; 


    /* This loop finds the minimum node, by traversing the tree until the leftmost node is discovered. */ 
    while (!empty_tree(current)) 
    { 
     current = current->left; 
    } 

    /* Returns the tree. */ 
    return current; 
} 



AVL delete(AVL self, long id) 
{ 

    if (self != NULL) 
    { 
     if (id == self->student_id) 
     { 
      if (self->left != NULL) 
      { 
       AVL successor = min_node(self->right); 
       self->student_id = successor->student_id; 
       self->right = delete(self->right, self->student_id); 
      } 
      else 
      { 
       AVL to_free = self; 
       if (self->left) 
       { 
        self = self->left; 
       } 
       else 
       { 
        self = self->right; 
       } 
       free(to_free); 
      } 
     } 
     else if (id < self->student_id) 
     { 
      self->left = delete(self->left, id); 
     } 
     else 
     { 
      self->right = delete(self->right, id); 
     } 
    } 

    /*NEW SHIT*/ 
    int balance = getBalance(self); 

    //Left Left Case 
    if (balance > 1 && getBalance(self->left) >= 0) 
    { 
     return rotateRight(self); 
    } 
    //Left Right Case 
    if (balance > 1 && getBalance(self->left) < 0) 
    { 
     self->left = leftRotate(self->left); 
     return rotateRight(self); 
    } 
    //Right Right Case 
    if (balance < -1 && getBalance(self->right) <= 0) 
    { 
     return leftRotate(self); 
    } 
    //Right Left Case 
    if (balance < -1 && getBalance(self->right) > 0) 
    { 
     self->right = rotateRight(self->right); 
     return leftRotate(self); 
    } 

    return self; 
} 

UPDATE: Так что, похоже, сбой на одной из двух линий в функции удаления:

self->student_id = successor->student_id; 

ИЛИ

AVL successor = min_node(self->right); 

EDIT 2: По желанию, я Я включил весь файл avl.c.

#include <stdlib.h> 
#include <stdbool.h> 
#include "avl.h" 

bool names_match(char* name_one, char* name_two) 
{ 
    if (strcmp(name_one, name_two) == 0) 
    { 
     return true; 
    } 
    else 
    { 
     return false; 
    } 
} 

bool empty_tree(AVL self) 
{ 
    if (self == NULL) 
    { 
     return true; 
    } 
    else 
    { 
     return false; 
    } 
} 


AVL leftRotate(AVL self) 
{ 
    AVL y = self->right; 
    AVL T2 = y->left; 

    y->left = self; 
    self->right = T2; 

    return y; 
} 

AVL rotateRight(AVL self) 
{ 
    AVL x = self->left; 
    AVL T2 = x->right; 

    x->right = self; 
    self->left = T2; 

    return x; 
} 

int getBalance(AVL node) 
{ 
    if (node == NULL) 
    { 
     return 0; 
    } 
    return height(node->left) - height(node->right); 
} 


AVL insert(AVL self, long id) 
{ 
    if (self == NULL) 
    { 
     self = (AVL)malloc(sizeof(struct avlNode)); 
     self->student_id = id; 
     self->left = self->right = NULL; 
    } 
    else if (id < self->student_id) 
    { 
     self->left = insert(self->left, id); 
    } 
    else if (id > self->student_id) 
    { 
     self->right = insert(self->right, id); 
    } 


    /*NEW SHIT*/ 
    int balance = getBalance(self); 

    //Left Left Case 
    if (balance > 1 && id < self->left->student_id) 
    { 
     return rotateRight(self); 
    } 
    //Right Right Case 
    if (balance < -1 && id > self->right->student_id) 
    { 
     return leftRotate(self); 
    } 
    //Left Right Case 
    if (balance > 1 && id > self->left->student_id) 
    { 
     self->left = leftRotate(self->left); 
     return rotateRight(self); 
    } 
    //Right Left Case 
    if (balance < -1 && id < self->right->student_id) 
    { 
     self->right = rotateRight(self->right); 
     return leftRotate(self); 
    } 

    //Return unchanged pointer (i dunno why. could probably be void) 
    return self; 
} 

/* === AVL MINIMUM NODE === 
Finds the minimum node in a AVL. 
*/ 
AVL min_node(AVL self) 
{ 
    /* A AVL node to keep track of the current node. */ 
    AVL current = self; 

    /* This loop finds the minimum node, by traversing the tree until the leftmost node is discovered. */ 
    while (!empty_tree(current->left)) 
    { 
     current = current->left; 
    } 

    /* Returns the tree. */ 
    return current; 
} 



AVL delete(AVL self, long id) 
{ 
    if (self != NULL) 
    { 
     if (id == self->student_id) 
     { 
      if (self->left != NULL) 
      { 
       AVL successor = min_node(self->right); 
       self->student_id = successor->student_id; 
       self->right = delete(self->right, self->student_id); 
      } 
      else 
      { 
       AVL to_free = self; 
       if (self->left) 
       { 
        self = self->left; 
       } 
       else 
       { 
        self = self->right; 
       } 
       free(to_free); 
      } 
     } 
     else if (id < self->student_id) 
     { 
      self->left = delete(self->left, id); 
     } 
     else 
     { 
      self->right = delete(self->right, id); 
     } 
    } 

    /*NEW SHIT*/ 
    if (self == NULL) 
    { 
     return self; //ADDED TODAY 
    } 

    int balance = getBalance(self); 

    //Left Left Case 
    if (balance > 1 && getBalance(self->left) >= 0) 
    { 
     return rotateRight(self); 
    } 
    //Left Right Case 
    if (balance > 1 && getBalance(self->left) < 0) 
    { 
     self->left = leftRotate(self->left); 
     return rotateRight(self); 
    } 
    //Right Right Case 
    if (balance < -1 && getBalance(self->right) <= 0) 
    { 
     return leftRotate(self); 
    } 
    //Right Left Case 
    if (balance < -1 && getBalance(self->right) > 0) 
    { 
     self->right = rotateRight(self->right); 
     return leftRotate(self); 
    } 

    return self; 
} 

/* === AVL NODE COUNT === 
Counts the number of nodes in the AVL. 
*/ 
int number_of_nodes(AVL self) 
{ 
    /* If the tree is empty, return a count of 0 nodes. */ 
    if (empty_tree(self)) 
    { 
     return(0); 
    } 
    /* If the tree is not empty, but its left and right nodes are, return a count of 1 node. */ 
    else if (empty_tree(self->left) && empty_tree(self->right)) 
    { 
     return(1); 
    } 

    /* If the tree is not empty, and its left and right nodes are also not empty, run this function recursively in the left and right nodes. */ 
    else 
    { 
     return(1 + (number_of_nodes(self->left) + number_of_nodes(self->right))); 
    } 

} 

/* === AVL HEIGHT === 
Returns the total height of a AVL. 
*/ 
int height(AVL self) 
{ 
    /* If the tree is empty, return a count of 0 nodes. */ 
    if (empty_tree(self)) 
    { 
     return 0; 
    } 
    /* If the tree is not empty, run this fucntion recursively on the left and right branches, returning the max of the two. */ 
    else 
    { 
     return 1 + max(height(self->left), height(self->right)); 
    } 
} 



/* === PRINT AVL === 
Prints a AVL in pre-order. 
*/ 
void print_pre_order(AVL self) 
{ 

    /* If the tree isn't empty, print the node's ID and then run this function recursively on the left and then the right nodes, 
    to print pre order. */ 
    if (!empty_tree(self)) 
    { 
     printf("%d", self->student_id); 
     printf("\n"); 
     print_pre_order(self->left); 
     print_pre_order(self->right); 

    } 
} 

/* === SEARCH AVL === 
Searches a AVL for a particular node. 
*/ 
bool searchTree(AVL self, long id) 
{ 
    if (!empty_tree(self)) 
    { 
     /* If the node's ID matches the input ID, return true. */ 
     if (self->student_id == id) 
     { 
      return true; 
     } 

     /* If the node's ID doesn't match the input ID, run this function recurseively on the appropriate node. */ 
     else 
     { 
      if (self->student_id > id) 
      { 
       return searchTree(self->left, id); 
      } 
      else if (self->student_id < id) 
      { 
       return searchTree(self->right, id); 
      } 
     } 
    } 
    return false; 
} 

void destroy_tree(AVL self) 
{ 
    /* If the tree is not empty, free each node in the tree by running this function recursively on the left and right branches. */ 
    if (!empty_tree(self)) 
    { 
     destroy_tree(self->left); 
     destroy_tree(self->right); 
     free(self); 
    } 
} 

EDIT 3: Интересное развитие. Используемое дерево AVL на самом деле находится в связанном списке, причем каждый узел содержит дерево AVL. Теперь я понял (через множество тестов), что узел на дереве AVL можно удалить, IF его первый, который был построен. Очень интересно и даже более раздражает.

+2

Это ** идеальная ** возможность использовать отладчик;) – Idos

+0

Я использую отладчик. Вот как я знаю, что моя программа сталкивается с проблемой при удалении и минимальной функцией узла. – user3414510

+0

Тогда что мешает вам сузить вашу проблему до определенной команды и посмотреть, что произойдет? – Idos

ответ

0

Я думаю, что проблема заключается в том, что вы переходите к функции. Если «я» - это указатель, который я предполагаю, то, на мой взгляд, вы должны передать «адрес» «я», например, так: «& (self-> right)», а текущему нужно присвоить значение '& self' like so 'current = * self'. Тогда я думаю, что это может сработать. Я думаю, что могу исправить то, что я говорю, если мне предоставлен весь код, но я думаю, что вы получаете суть

+0

Попробовал ваше предложение. Не работает, к сожалению. Меня раздражает то, что все работает отлично с моим двоичным деревом поиска.Я просто не могу понять, почему он падает с дополнительным AVL-кодом. – user3414510

+0

Не могли бы вы показать мне весь код? – Vivek

+0

Конечно, я добавил его на главный пост. – user3414510

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

  • Нет связанных вопросов^_^