2017-01-22 3 views
0

연습의 일부로 프로그래밍을 배우려고 노력하면서 을 사용하는 프로그램을 만들도록 요청되었습니다. 1. 구조체 2. 두 배로 연결된 목록 3. 이진 검색 트리이진 검색 트리 문제

고객의 데이터베이스를 만들려면 .. 노드를 목록에 추가하고 검색하는 것이 좋습니다. 그러나 고객을 삭제하려고 할 때 프로그램이 작동하지 않아 충돌이 발생합니다. 문제점을 추적하여 BST_delete 함수이 86 행부터 시작됩니다. 왜냐하면이 함수를 실행하지 않으면 프로그램이 훨씬 효과적입니다. 구체적으로 내가이 날 미치게됩니다

내가 이진 트리의 가장 최근의 노드 수 있어야 올바르게 기능 BST_email_root을 .. 업데이트하고 있지 않다라고 생각! 나는 그것이 가장 우아한 코드는 아니지만 나는 여전히 배우려고 노력하고 있다는 것을 압니다! 감사합니다

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

#define MAX_STRING 250 

void myflush(); 

// Defining a customer structure. 
struct customer { 
    char *name; 
    char *address; 
    char *email; 
}; 

// A double linked list. The data field points to a customer struct. 
struct double_linked_list { 
    struct customer *data; 
    struct double_linked_list *previous; 
    struct double_linked_list *next; 
}; 

// Defining a pointer for the first one of the customers in the double linked list. 

struct double_linked_list *customers_head=0; 

// A node for a Binary Search Tree (BST). 

struct BST_node { 
    struct double_linked_list *data; 
    struct BST_node *left; 
    struct BST_node *right; 
}; 

// Defining a variable for the root of the BST that is indexed by the email. 
struct BST_node *BST_email_root = 0; 

// Looking for a node with a specific email in the BST. 

struct BST_node *BST_find_customer(struct BST_node *root, char *email) { 
if (root==NULL) 
    return NULL; 
if (strcmp(email,root->data->data->email)==0) 
    return root; 
else 
    { 
    if (strcmp(email,root->data->data->email)==-1) 
    return BST_find_customer(root->left,email); 
    else 
     return BST_find_customer(root->right,email); 
    } 
} 

// A procedure to finding a customer according to his email. 

void find_customer() { 
    char email[MAX_STRING]; 
    struct double_linked_list *l; 
    struct BST_node *b; 
    printf("Give the email of the customer (up to %d characters) : ", MAX_STRING-1); 
    gets(email); 

    b = BST_find_customer(BST_email_root, email); 
    if (b==0) 
     printf("There is no customer with this email.\n"); 
    else 
    { 
     l = b->data; 
     printf("Customer found! \n"); 
     printf("Name : %s\n", l->data->name); 
     printf("Address : %s\n", l->data->address); 
     printf("Email : %s\n", l->data->email); 
    } 
} 

struct BST_node *findMaxNode(struct BST_node *root) 
      { 
       if(root->right == NULL) return root; 
       findMaxNode(root->right); 
      } 

// Deleting a node in the BST, according to a given email. 

// The function returns the (new?) root of the BST, which might have been changed or not. 
struct BST_node *BST_delete(struct BST_node *root, char *email) 
{ 

if (root==NULL) 
    return root; 
struct BST_node *father=NULL; 
char which_son; 
while (strcmp(email,root->data->data->email)!=0){ //first, finding root and remembering who's root father 
if(root==NULL) { 
    return root; 
} else if (strcmp(email,root->data->data->email) <0){ 
    father = root; 
    root = root->left; 
    if(root==NULL) 
     return; 
    else which_son = 'l'; 
} else { 
    father = root; 
    root = root->right; 
    if(root==NULL) 
     return; 
    else which_son = 'r'; 
} 
} 
// now you have both the root node, and its father 
if ((root->right == NULL) && (root->left == NULL)){ //case 1, if it's a leaf 
free(root); 

} else if (root->left == NULL) { //case 2 
    if (which_son == 'l') { 
     father->left = root->right; 
    } else { 
     father->right = root->right; 
    } 

} else { //case 3 : here i get the "rightest" son of root's left son 
    struct BST_node *replacing_node = root->left; 
    while (replacing_node->right != NULL) { 
     replacing_node = replacing_node->right; 
    } //now replacing_node is a leaf, and can replace root 
    if (which_son == 'l') { 
     father->left = replacing_node; 
     replacing_node->left = root->left; 
     replacing_node->right = root->right; 
    } else { 
     father->right = replacing_node; 
     replacing_node->left = root->left; 
     replacing_node->right = root->right; 
    } 
    } 
    return root; 
} 


// This function adds a new node in the Binary Search Tree (BST) rooted by *root, 

struct BST_node *new_BST_node(struct BST_node *root, struct double_linked_list *l) 
    { 
    if (root==NULL) 
     { 
     root= (struct BST_node *)malloc(sizeof(struct BST_node)); 
     if (root==NULL) 
      { 
      printf("Out of Memory!"); 
      exit(1); 
      } 

     root->data=l; 
     root->left=NULL; 
     root->right=NULL; 
     return root; 
     } 

    if ((strcmp(l->data->email,root->data->data->email))<0) 
       root->left =new_BST_node(root->left,l); 
    else 
     root->right =new_BST_node(root->right,l); 


    }; 


// A procedure to modify the data concerning an existing customer 
void modify_customer() { 
    char old_email[MAX_STRING]; 
    char new_email[MAX_STRING]; 
    char new_name[MAX_STRING]; 
    char new_address[MAX_STRING]; 
    char ans; 

    struct BST_node *ind; 
    struct double_linked_list *l; 

    printf("Give the email of the customer you want to modify: "); 
    gets(old_email); 
    ind = BST_find_customer(BST_email_root, old_email); 
    if (ind == 0) 
    { 
     printf("There is no customer with this email.\n"); 
     return; 
    } 

    l = ind->data; // The node in the double linked list for the customer 
    printf("Old name: %s\n", l->data->name); 
    printf("Give the new name (up to %d characters, <Enter> if it does not change): ", MAX_STRING - 1); 
    gets(new_name); 
    if (new_name[0] == 0) 
     strcpy(new_name, l->data->name); 

    printf("Old address: %s\n", l->data->address); 
    printf("Give the new address (up to %d characters, <Enter> if it does not change): ", MAX_STRING - 1); 
    gets(new_address); 
    if (new_address[0] == 0) 
     strcpy(new_address, l->data->address); 

    printf("Old email: %s\n", l->data->email); 
    printf("Give the new email (up to %d characters, <Enter> if it does not change): ", MAX_STRING-1); 
    gets(new_email); 
    if (new_email[0] == 0) 
     strcpy(new_email, l->data->email); 

    if (strcmp(l->data->email, new_email)) 
    { 
     if (BST_find_customer(BST_email_root, new_email)) 
     { 
      printf("New email already exists. Modification aborted.\n"); 
      return; 
     } 
    } 

    printf("\n\n"); 
    printf("REPLACE:\n"); 
    printf("Name : %s\n", l->data->name); 
    printf("Address : %s\n", l->data->address); 
    printf("Email : %s\n", l->data->email); 
    printf("WITH:\n"); 
    printf("Name : %s\n", new_name); 
    printf("Address : %s\n", new_address); 
    printf("Email : %s\n\n", new_email); 

    printf("Are you sure? (Y)es/(N)o\n"); 
    scanf(" %c", &ans); 
    myflush(); 
    if (ans == 'Y' || ans == 'y') 
    { 
     free(l->data->name); 
     l->data->name = strdup(new_name); 
     free(l->data->address); 
     l->data->address = strdup(new_address); 

     if (strcmp(l->data->email, new_email) != 0) 
      // Only in case the email has been changed, we have to maintain the BST 
     { 
      BST_email_root=BST_delete(BST_email_root, l->data->email); 
      free(l->data->email); 
      l->data->email = strdup(new_email); 
      BST_email_root=new_BST_node(BST_email_root, l); 
     } 
    } 
} 

// add a new customer 
struct double_linked_list *new_customer() 
{ 
    char name[MAX_STRING], address[MAX_STRING], email[MAX_STRING]; 
    struct BST_node *b; 
    struct double_linked_list *l; 
    struct customer *c; 

    printf("\nADDING A CUSTOMER\n\n\n"); 
    printf("Give the name (up to %d characters): ", MAX_STRING-1); 
    gets(name); 

    printf("Give the address (up to %d characters): ", MAX_STRING - 1); 
    gets(address); 

    printf("Give the email (up to %d characters): ", MAX_STRING - 1); 
    gets(email); 

     // check for duplicate email 
    b = BST_find_customer(BST_email_root, email); 
    if (b) 
    { 
     printf("Duplicate email. Customer aborted.\n"); 
     return 0; 
    } 

    c = (struct customer *) malloc(sizeof(struct customer)); 
    if (c == 0) 
    { 
     printf("Not enough memory.\n"); 
     return 0; 
    } 

    c->name = strdup(name); // check for memory allocation problem 
    if (c->name == 0) return 0; 
    c->address = strdup(address); // check for memory allocation problem 
    if (c->address == 0) return 0; 
    c->email = strdup(email); // check for memory allocation problem 
    if (c->email == 0) return 0; 

    l = (struct double_linked_list*) malloc(sizeof(struct double_linked_list)); 
    if (l == 0) 
    { 
     printf("Not enough memory.\n"); 
     free(c->name); 
     free(c->address); 
     free(c->email); 
     free(c); 
     return 0; 
    } 

    l->data = c; 
    l->previous = 0; 
    l->next = customers_head; 

    if (customers_head) 
     customers_head->previous = l; 

    customers_head = l; 

    BST_email_root = new_BST_node(BST_email_root, l); 

    return l; 
} 

// This function deletes a customer, based on its email 
void delete_customer() { 
    char email[MAX_STRING]; 
    struct BST_node *n_del; 
    printf("Give the email of the customer you want to delete(up to %d characters) : ", MAX_STRING-1); 
    gets(email); 

    n_del = BST_find_customer(BST_email_root, email); 
    if (n_del==0) 
     printf("There is no customer with this email.\n"); 

    else 
    { 
    struct double_linked_list *current = n_del->data; 
    //struct double_linked_list *temp; 
    //struct double_linked_list *prev = customers_head; 

    if (current->next==NULL &&current->previous==NULL) 
     { 
     free(current); 
     customers_head=0; 
     } 

    else if (current->next==NULL) //TA EXOUN ANAPODA??i oxi..Den exw katalaveiNEXT=0 EINAI GIA TO PROTO STOIXEIO pou vazw. An exw mono ena stoixeio ti ginete? prepei na to dw.. 
     { 
     printf("1"); 
     current->previous->next=NULL; 
     free(current); 
     } 

    else if (current->previous==NULL) 
     { printf("2"); 
      current->next->previous=NULL; //Apla kane to previous tou proigoumenou apo ton teleytaio pou thes na kaneis na mi deixnei pouthena.. 
     customers_head=current->next; 
     free(current); 
     } 
    else 
     { 
     printf("3"); 
     current->next->previous = current->previous; //vle ton proigoumeno komvo na deixnei ston epomeno kai ton epomeno ston proigoumeno 
     current->previous->next = current->next;  //Ftiakse to customer's head na deixnei sto proigoumeno pou einai pleon to pio prosfato sti lista 
     } 
    } 

    BST_email_root=BST_delete(BST_email_root, email); 
} 


void displaymenu() { 
    printf("\n\n"); 
    printf("1. New customer\n"); 
    printf("2. Find customer using email\n"); 
    printf("3. Modify customer\n"); 
    printf("4. Delete customer\n"); 
    printf("0. Exit\n\n"); 
    printf("Give a choice (0-6) : "); 
} 

// This function empties the buffer of the standard input (stdin), that is, of the keyboard 
void myflush() 
{ 
    char ch; 
    while ((ch = getchar()) != '\n' && ch != EOF); 
} 


// The main function 
int main() { 
    int choice; 
    do { 
     displaymenu(); 
     scanf("%d", &choice); 
     myflush(); 
     switch (choice) { 
     case 1: 
      new_customer(); 
      break; 
     case 2: 
      find_customer(); 
      break; 
     case 3: 
      modify_customer(); 
      break; 
     case 4: 
      delete_customer(); 
      break; 

     default: 
      printf("Wrong selection.\n\n"); 
     } 
    } while (choice != 0); 

    return 0; 
} 
+2

세상에 나! 당신은리스트와 트리를 연결했고 데이터는 할당 된 메모리 포인터로 구조화되어 있습니다. 대답은 한 가지 문제를 발견했습니다. 그 동안 디버거로 바쁘다. BTW는 프로그램 단계를 작은 단계로 구성했는지 확인하고 스트레칭을 진행하거나 거대한 밤새 코딩 작업을 수행 한 후에 넘어 졌습니까? –

+1

대답은 아니지만 가능한 버그 관찰 :'BST_delete'에서 두번째'if (root == NULL)'체크는'return;'으로 이어진다. 그것은 일종의'struct BST_node *'를 반환해야합니다. 포인터가 'NULL'일지라도 명시 적으로 말해야합니다. (들여 쓰기도 그 줄에서 이상하게 보입니다 ... 잘라 내기 및 붙여 넣기 오류, 아마도?) –

+0

하나의 오류가 발견되었습니다 ... 디버거를 사용 중입니다! 'while (strcmp (email, root-> data-> data-> email)! = 0)'루핑 할 때'BST_delete()'함수에서'if (root == NULL)'을 체크하지 않는다. 'root = root-> left; 또는'root = root-> right; 그리고'root-> data'는 실패했습니다 !!! –

답변

2

코드에 깊이 빠져 들지 않으면 즉시 보았던 것이 있습니다. 귀하의 문

... if (strcmp(email,root->data->data->email) == -1) { 

은 하나가 다른 것보다 작은 경우, 반환 값은 정확히 -1 있다고 가정합니다. 그러나이 경우 strcmp의 반환 값은 < 0이 아니고 정확히 -1이 아닙니다 (참조 : strcmp reference 참조).

따라서, "아버지"를 검색하는 동안, 당신은 당신이 찾고있는 노드 ...

+0

시도해보고 돌아올 것입니다! 고마워요! – ritgeo

+0

@ritgeo 왜 이전 질문에서 배울 수 있습니까? – BLUEPIXY

+0

이것은 코드였습니다. 왜냐하면 삭제 기능에 집중되어 있었기 때문에 내가 찾지 못했던 것이고, 찾기 기능에 집중되어 있지 않았기 때문에 그것을 발견하지 못했습니다! 미안해서 더 조심해야 했어! – ritgeo

1

가 여기 내 수정 된 버전입니다 찾을 수없는, 가능성이 높습니다. double_linked_list는 필요 없다고 생각합니다. BST_node.data에 대해 고객을 직접 사용할 수 있습니다. 나는 새로운 고객을 추가하고, 고객을 찾고, 고객을 삭제하고, 모두 예상대로 작동하는지 테스트했다. 그러나 나는 생각보다 오히려 솔직하게 고객을 수정하지 않았습니다. 제공된 소스 코드를 테스트하고 @StephanLechner의 발언을 삽입 한 후

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

#define MAX_STRING 250 

void myflush(); 

// Defining a customer structure. 
struct customer { 
    char *name; 
    char *address; 
    char *email; 
}; 

// A double linked list. The data field points to a customer struct. 
struct double_linked_list { 
    struct customer *data; 
    struct double_linked_list *previous; 
    struct double_linked_list *next; 
}; 

// Defining a pointer for the first one of the customers in the double linked list. 

struct double_linked_list *customers_head=0; 

// A node for a Binary Search Tree (BST). 

struct BST_node { 
    struct double_linked_list *data; 
    struct BST_node *top; 
    struct BST_node *left; 
    struct BST_node *right; 
}; 

// Defining a variable for the root of the BST that is indexed by the email. 
struct BST_node *BST_email_root = 0; 

// Looking for a node with a specific email in the BST. 

struct BST_node *BST_find_customer(struct BST_node *root, char *email) { 
if (root==NULL) 
    return NULL; 

int rv = strcmp(email,root->data->data->email); 

if (rv==0) 
    return root; 
else 
    { 
    if (rv<0) 
    return BST_find_customer(root->left,email); 
    else 
     return BST_find_customer(root->right,email); 
    } 
} 

// A procedure to finding a customer according to his email. 

void find_customer() { 
    char email[MAX_STRING]; 
    struct double_linked_list *l; 
    struct BST_node *b; 
    printf("Give the email of the customer (up to %d characters) : ", MAX_STRING-1); 
    gets(email); 

    b = BST_find_customer(BST_email_root, email); 
    if (b==0) 
     printf("There is no customer with this email.\n"); 
    else 
    { 
     l = b->data; 
     printf("Customer found! \n"); 
     printf("Name : %s\n", l->data->name); 
     printf("Address : %s\n", l->data->address); 
     printf("Email : %s\n", l->data->email); 
    } 
} 

struct BST_node *findMaxNode(struct BST_node *root) 
      { 
       if(root->right == NULL) return root; 
       findMaxNode(root->right); 
       return NULL; 
      } 

// Deleting a node in the BST, according to a given email. 

// The function returns the (new?) root of the BST, which might have been changed or not. 
struct BST_node *BST_delete(struct BST_node *root, char *email) 
    { 

    if (root==NULL) 
     return root; 
    struct BST_node *father=NULL; 
    char which_son; 
    while (strcmp(email,root->data->data->email)!=0){ //first, finding root and remembering who's root father 
    if(root==NULL) { 
     return NULL; 
    } else if (strcmp(email,root->data->data->email) < 0){ 
     father = root; 
     root = root->left; 
     which_son = 'l'; 
    } else { 
     father = root; 
     root = root->right; 
     which_son = 'r'; 
    } 
} 
    // now you have both the root node, and its father 
    if ((root->right == NULL) && (root->left == NULL)){ //case 1, if it's a leaf 
    free(root); 

    } else if (root->left == NULL) { //case 2 
     if (which_son == 'l') { 
      father->left = root->right; 
     } else { 
      father->right = root->right; 
     } 

    } else { //case 3 : here i get the "rightest" son of root's left son 
     struct BST_node *replacing_node = root->left; 
     while (replacing_node->right != NULL) { 
      replacing_node = replacing_node->right; 
     } //now replacing_node is a leaf, and can replace root 
     if (which_son == 'l') { 
      father->left = replacing_node; 
      replacing_node->left = root->left; 
      replacing_node->right = root->right; 
     } else { 
      father->right = replacing_node; 
      replacing_node->left = root->left; 
      replacing_node->right = root->right; 
     } 
     } 
     return root; 
    } 


// This function adds a new node in the Binary Search Tree (BST) rooted by *root, 

void new_BST_node(struct BST_node *root, struct double_linked_list *l) 
{ 
    if ((strcmp(l->data->email,root->data->data->email))<0) 
    { 
     if(root->left == NULL) 
     { 
      root->left = (struct BST_node *)malloc(sizeof(struct BST_node)); 
      root->left->data = l; 
      root->left->top = root; 
      root->left->left = NULL; 
      root->left->right = NULL; 
     } 
     else 
     { 
      new_BST_node(root->left,l); 
     } 
    } 
    else 
    { 
     if(root->right == NULL) 
     { 
      root->right = (struct BST_node *)malloc(sizeof(struct BST_node)); 
      root->right->data = l; 
      root->right->top = root; 
      root->right->left = NULL; 
      root->right->right = NULL; 
     } 
     else 
     { 
      new_BST_node(root->right,l); 
     } 
    } 
} 


// A procedure to modify the data concerning an existing customer 
void modify_customer() { 
    char old_email[MAX_STRING]; 
    char new_email[MAX_STRING]; 
    char new_name[MAX_STRING]; 
    char new_address[MAX_STRING]; 
    char ans; 

    struct BST_node *ind; 
    struct double_linked_list *l; 

    printf("Give the email of the customer you want to modify: "); 
    gets(old_email); 
    ind = BST_find_customer(BST_email_root, old_email); 
    if (ind == 0) 
    { 
     printf("There is no customer with this email.\n"); 
     return; 
    } 

    l = ind->data; // The node in the double linked list for the customer 
    printf("Old name: %s\n", l->data->name); 
    printf("Give the new name (up to %d characters, <Enter> if it does not change): ", MAX_STRING - 1); 
    gets(new_name); 
    if (new_name[0] == 0) 
     strcpy(new_name, l->data->name); 

    printf("Old address: %s\n", l->data->address); 
    printf("Give the new address (up to %d characters, <Enter> if it does not change): ", MAX_STRING - 1); 
    gets(new_address); 
    if (new_address[0] == 0) 
     strcpy(new_address, l->data->address); 

    printf("Old email: %s\n", l->data->email); 
    printf("Give the new email (up to %d characters, <Enter> if it does not change): ", MAX_STRING-1); 
    gets(new_email); 
    if (new_email[0] == 0) 
     strcpy(new_email, l->data->email); 

    if (strcmp(l->data->email, new_email)) 
    { 
     if (BST_find_customer(BST_email_root, new_email)) 
     { 
      printf("New email already exists. Modification aborted.\n"); 
      return; 
     } 
    } 

    printf("\n\n"); 
    printf("REPLACE:\n"); 
    printf("Name : %s\n", l->data->name); 
    printf("Address : %s\n", l->data->address); 
    printf("Email : %s\n", l->data->email); 
    printf("WITH:\n"); 
    printf("Name : %s\n", new_name); 
    printf("Address : %s\n", new_address); 
    printf("Email : %s\n\n", new_email); 

    printf("Are you sure? (Y)es/(N)o\n"); 
    scanf(" %c", &ans); 
    myflush(); 
    if (ans == 'Y' || ans == 'y') 
    { 
     free(l->data->name); 
     l->data->name = strdup(new_name); 
     free(l->data->address); 
     l->data->address = strdup(new_address); 

     if (strcmp(l->data->email, new_email) != 0) 
      // Only in case the email has been changed, we have to maintain the BST 
     { 
      BST_email_root=BST_delete(BST_email_root, l->data->email); 
      free(l->data->email); 
      l->data->email = strdup(new_email); 
      new_BST_node(BST_email_root, l); 
     } 
    } 
} 

// add a new customer 
struct double_linked_list *new_customer() 
{ 
    char name[MAX_STRING], address[MAX_STRING], email[MAX_STRING]; 
    struct BST_node *b; 
    struct double_linked_list *l; 
    struct customer *c; 

    printf("\nADDING A CUSTOMER\n\n\n"); 
    printf("Give the name (up to %d characters): ", MAX_STRING-1); 
    gets(name); 

    printf("Give the address (up to %d characters): ", MAX_STRING - 1); 
    gets(address); 

    printf("Give the email (up to %d characters): ", MAX_STRING - 1); 
    gets(email); 

     // check for duplicate email 
    b = BST_find_customer(BST_email_root, email); 
    if (b) 
    { 
     printf("Duplicate email. Customer aborted.\n"); 
     return 0; 
    } 

    c = (struct customer *) malloc(sizeof(struct customer)); 
    if (c == 0) 
    { 
     printf("Not enough memory.\n"); 
     return 0; 
    } 

    c->name = strdup(name); // check for memory allocation problem 
    if (c->name == 0) return 0; 
    c->address = strdup(address); // check for memory allocation problem 
    if (c->address == 0) return 0; 
    c->email = strdup(email); // check for memory allocation problem 
    if (c->email == 0) return 0; 

    l = (struct double_linked_list*) malloc(sizeof(struct double_linked_list)); 
    if (l == 0) 
    { 
     printf("Not enough memory.\n"); 
     free(c->name); 
     free(c->address); 
     free(c->email); 
     free(c); 
     return 0; 
    } 

    l->data = c; 
    l->previous = 0; 
    l->next = customers_head; 

    if (customers_head) 
     customers_head->previous = l; 

    customers_head = l; 

    if (BST_email_root==NULL) 
    { 
     BST_email_root = (struct BST_node *)malloc(sizeof(struct BST_node)); 

     BST_email_root->data = l; 
     BST_email_root->top = NULL; 
     BST_email_root->left = NULL; 
     BST_email_root->right = NULL; 
    } 
    else 
    { 
     new_BST_node(BST_email_root, l); 
    } 

    return l; 
} 

void print_customers(struct BST_node *node) 
{ 
    if(node == NULL) 
    { 
     printf("No customers yet\n"); 
    } 
    else if(node->left) 
    { 
     print_customers(node->left); 
     printf("%s %s %s\n", node->data->data->name, 
          node->data->data->address, 
          node->data->data->email); 
     if(node->right) 
     { 
      print_customers(node->right); 
     } 
    } 
    else if(node->right) 
    { 
     printf("%s %s %s\n", node->data->data->name, 
          node->data->data->address, 
          node->data->data->email); 
     print_customers(node->right); 
    } 
    else 
    { 
     printf("%s %s %s\n", node->data->data->name, 
          node->data->data->address, 
          node->data->data->email); 
    } 
} 

// This function deletes a customer, based on its email 
void delete_customer() { 
    char email[MAX_STRING]; 
    struct BST_node *n_del; 
    printf("Give the email of the customer you want to delete(up to %d characters) : ", MAX_STRING-1); 
    gets(email); 

    n_del = BST_find_customer(BST_email_root, email); 
    if (n_del==0) 
     printf("There is no customer with this email.\n"); 

    else 
    { 
     if(n_del->left && n_del->right) 
     { 
      if(n_del->top->left == n_del) 
      { 
       n_del->top->left = n_del->left; 
      } 
      else 
      { 
       n_del->top->right = n_del->left; 
      } 

      struct BST_node *node = n_del->left; 
      while(node->right) 
      { 
       node = node->right; 
      } 
      node->right = n_del->right; 
     } 
     else if(n_del->left) 
     { 
      if(n_del->top->left == n_del) 
      { 
       n_del->top->left = n_del->left; 
      } 
      else // must be right node 
      { 
       n_del->top->right = n_del->left; 
      } 
     } 
     else if(n_del->right) 
     { 
      if(n_del->top->left == n_del) 
      { 
       n_del->top->left = n_del->right; 
      } 
      else // must be right node 
      { 
       n_del->top->right = n_del->right; 
      } 
     } 
     else { /* a leaf */ 
      if(n_del->top->left == n_del) 
      { 
       n_del->top->left = NULL; 
      } 
      else // must be right node 
      { 
       n_del->top->right = NULL; 
      } 
     } 

     free(n_del->data->data->name); 
     free(n_del->data->data->email); 
     free(n_del->data->data->address); 
     free(n_del->data->data); 
     free(n_del->data); 
     free(n_del); 
    } 

} 


void displaymenu() { 
    printf("\n\n"); 
    printf("1. New customer\n"); 
    printf("2. Find customer using email\n"); 
    printf("3. Modify customer\n"); 
    printf("4. Delete customer\n"); 
    printf("5. List customers\n"); 
    printf("0. Exit\n\n"); 
    printf("Give a choice (0-5) : "); 
} 

// This function empties the buffer of the standard input (stdin), that is, of the keyboard 
void myflush() 
{ 
    char ch; 
    while ((ch = getchar()) != '\n' && ch != EOF); 
} 


// The main function 
int main() { 
    int choice; 
    do { 
     displaymenu(); 
     scanf("%d", &choice); 
     myflush(); 
     switch (choice) { 
     case 1: 
      new_customer(); 
      break; 
     case 2: 
      find_customer(); 
      break; 
     case 3: 
      modify_customer(); 
      break; 
     case 4: 
      delete_customer(); 
      break; 
     case 5: 
      print_customers(BST_email_root); 
      break; 

     default: 
      printf("Wrong selection.\n\n"); 
     } 
    } while (choice != 0); 

    return 0; 
} 
+0

또한 현재 고객을 나열하는 기능이 추가되어 각 작업 후에 결과를 확인할 수 있습니다. 다른 사람들이 지적했듯이, strcmp 결과를 -1과 비교하는 것은 올바르지 않습니다. 결과를 == 0, < 0 or >으로 비교해야합니다. – Shiping

+0

이유는 double_linked_list가 필요하지 않다는 것입니다. 왜냐하면 BST_node가 이미 이중 연결 목록이기 때문에, 연습의 이중 연결 목록 요구 사항이 이미 충족되어 있기 때문입니다. – Shiping

+0

해결책을 확인하려고합니다!좋은 작품에 감사드립니다! 대부분의 경우에는 작동하지만 모든 경우에는 작동하지 않는 것 같습니다. 삽입 된 첫 번째 고객을 삭제하면 프로그램이 중단됩니다. 나는 이것을 파고 있습니다! – ritgeo

1

은 주요 문제는 BST_find_customer()BST_find_customer() 알고리즘과 new_BST_node()에서 사용하는 사이의 간격으로 인해 어떤 노드를 찾을 수없는 것입니다.

오류 1 - BST_find_customer() 기능에, 왼쪽 또는 오른쪽 노드를 찾고 전에 root->data (A struct double_linked_list *)을 탐구한다.

// explore the list from root->data; 
struct double_linked_list *ldata = root->data; 
while (ldata!=NULL) { 
    if (strcmp(email,ldata->data->email)==0) { 
     return (root); 
    } 
    ldata=ldata->next; 
} 
if (strcmp(email,root->data->data->email)<0) { // ERROR ==-1) { 
    return BST_find_customer(root->left,email); 
} 
else { 
    return BST_find_customer(root->right,email); 
} 

대신 :

if (strcmp(email,root->data->data->email)==0) 
    return root; 
else { 
    if (strcmp(email,root->data->data->email)==-1) 
     return BST_find_customer(root->left,email); 
    else 
     return BST_find_customer(root->right,email); 
} 

오류 2 - BST_delete() 함수에서의 data을 탐험하기 전에 root의 유효성을 확인합니다.

while-loop에 if-condition (root!=NULL)을 추가하여 트리 끝을 방지하십시오.

이 함수는 return; 대신 값 return (NULL);을 반환해야합니다. 그렇지 않으면 정의되지 않은 동작입니다.

while ((root!=NULL) && (strcmp(email,root->data->data->email)!=0)){ 
    if (strcmp(email,root->data->data->email) < 0){ 
     father = root; 
     root = root->left; 
     which_son = 'l'; 
    } else { 
     father = root; 
     root = root->right; 
     which_son = 'r'; 
    } 
} 
if(root==NULL) { 
    return (root); 
} 

대신 :

while (strcmp(email,root->data->data->email)!=0) { //first, finding root and remembering who's root father 
    if(root==NULL) { 
     return root; 
    } else if (strcmp(email,root->data->data->email) <0){ 
     father = root; 
     root = root->left; 
     if(root==NULL) 
      return; 
     else which_son = 'l'; 
    } else { 
     father = root; 
     root = root->right; 
     if(root==NULL) 
      return; 
     else which_son = 'r'; 
    } 
} 

오류 3 - 어떤 고객이 입력 한 이메일이없는 경우 delete_customer()에서 삭제를 중단합니다.

n_del = BST_find_customer(BST_email_root, email); 
if (n_del==0) { 
    printf("There is no customer with this email.\n"); 
    return; 
} 
else 

대신 :

n_del = BST_find_customer(BST_email_root, email); 
if (n_del==0) 
    printf("There is no customer with this email.\n"); 
    // ABORT HERE 
else 
+0

버그 수정에 감사드립니다! 내 코드에서이 문제를 해결했습니다! 그래도 나는 같은 충돌을 얻는다! 나는 무언가가 내 뿌리 가치에 문제가 있다고 믿는다. 나는 그것을 알아 내려고 노력 중이다! – ritgeo