2013-08-14 5 views
1

이 코드에서 소스 코드의 길이를 미리 사과드립니다. 내가 어디에서 잘못 될 지 모르겠습니다. 필자는 이진 트리 구현과 트리 탐색을위한 몇 가지 함수를 작성했습니다. 하나의 항목을 트리에 추가해도 작동하지만 여러 항목을 추가하면 세그멘테이션 오류가 발생합니다. DDD는 backtrace에서 isfull, addToTree 및 isEmpty의 여러 함수를 나열합니다.바이너리 트리 구현시 분할 오류

프로그램은 세 가지 소스 파일 (미안)에 걸쳐 있습니다.

/*----------------------------------Tree.h----------------------------------*/ 

#ifndef TREE 
#define TREE 

#define MAXHEIGHT 4 

typedef struct cat{ 
    char *name; 
    int age; 
}Item; 

typedef struct node{ 
    Item thing; 
}Node; 

typedef struct tree{ 
    Node *root; 
    struct tree *left, *right; 
    int leafcount; 
}Tree; 

void initializeTree(Tree *); 
void closeTree(Tree *); 
int isEmpty(const Tree *); 
int isFull(const Tree*); 
Tree *searchTree(Item *thing, Tree *t, int (*)(const Item *, const Item *)); 
int addToTree(Item *, Tree *, int (*)(const Item *, const Item *)); 
int removeFromTree(Item *, Tree *); 

int itemComp(const Item *, const Item *); 

#endif 

/*----------------------------------Tree.c----------------------------------*/ 

#include "Tree.h" 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <math.h> 

Node *copyToNode(Item *); 

/*Definition: Tree 
    Node *root; 
    int leafcount; */ 

Node *copyToNode(Item *thing){ 
    Node *tmp = malloc(sizeof(Node)); 
    if(tmp == NULL) 
     return tmp; 
    tmp->thing = *thing; 
    return tmp; 
} 

void initializeTree(Tree *t){ 
    t->root = NULL; 
    t->right = t->left = NULL; 
    t->leafcount = 0; 
} 

int isEmpty(const Tree *t){ 
    return t->root == NULL; 
} 

int isFull(const Tree *t){ 
    return t->leafcount == (int)pow(2,MAXHEIGHT) - 1; 
} 

int addToTree(Item *thing, Tree *t, int (*fp)(const Item *, const Item *)){ 
    if(isFull(t)) 
     return 0; 

    if(isEmpty(t)){ 
     Node *current = copyToNode(thing); 
     if(current == NULL){ 
      puts("Couldn't copy to tree!"); 
      return 0; 
     } 
     t->root = current; 
     t->leafcount++; 
     return 1; 
    } 

    if(fp(thing, &t->root->thing) <= 0) 
     return addToTree(thing, t->left, fp); 
    else 
     return addToTree(thing, t->right, fp); 
} 

Tree *searchTree(Item *thing, Tree *t, int (*fp)(const Item *, const Item *)){ 
    int temp; 

    if(t->root == NULL) 
     return NULL; 
    else if((temp = fp(&t->root->thing, thing)) == 0) 
     return t; 
    else if(temp = -1) 
     return searchTree(thing, t->left, fp); 
    else 
     return searchTree(thing, t->right, fp); 
} 


int removeFromTree(Item *thing, Tree *t){ 
    /*Tree *tmp = searchTree(thing, t); 
    Not finished*/ 
} 

void closeTree(Tree *t){ 
    return; 
} 

    /*------------------------------TreeDriver.c-------------------------------*/ 
#include "Tree.h" 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#define MAXNAME 30 
int promptUser(void); 
int itemComp(const Item *, const Item *); 
Item * createUserItem(); 

int main(){ 
    int userChoice; 
    Item * userItem = NULL; 
    Tree userTree; 

    initializeTree(&userTree); 

    do{ 
     userChoice = promptUser(); 
     switch(userChoice){ 
      case 1: 
       puts("Enter cat information to add"); 
       userItem = createUserItem(); 
       if(addToTree(userItem, &userTree, itemComp)) 
        puts("Cat successfully added!"); 
       else 
        puts("Could not add cat!"); 
       break; 
      case 2: 
       puts("Enter cat information to search for"); 
       userItem = createUserItem(); 
       if(searchTree(userItem, &userTree, itemComp)) 
        puts("Cat found!"); 
       else 
        puts("Cat not found!"); 
       break; 
      case 3: 
       if(isEmpty(&userTree)) 
        puts("Tree is empty!"); 
       else 
        puts("Tree is not empty!"); 
       break; 
      case 4: 
       if(isFull(&userTree)) 
        puts("Tree is full!"); 
       else 
        puts("Tree is not full!"); 
       break; 
      case 0: 
       break; 
      default: 
       puts("Not an option!"); 
       break; 
     } 

    }while(userChoice); 

} 

int itemComp(const Item *thing_one, const Item *thing_two){ 
    int comparison; 

    if(comparison = strcmp(thing_one->name, thing_two->name)) 
     return comparison; 

    return !(thing_one->age == thing_two->age); 
} 

int promptUser(){ 
    int tmp; 

    puts("--------MENU---------"); 
    puts("1. Create cat"); 
    puts("2. Search for cat"); 
    puts("3. Check empty"); 
    puts("4. Check full"); 
    puts("0. Quit"); 

    scanf("%d", &tmp); 
    while(getchar() != '\n') 
     ; 

    return tmp; 
} 

Item * createUserItem(){ 
    Item *tmp = malloc(sizeof(Item)); 
    static char namebuf[MAXNAME]; 

    printf("Enter cat name: "); 
    if(fgets(namebuf, MAXNAME, stdin) == NULL) 
     return NULL; 

    tmp->name = malloc(strlen(namebuf)); 
    strcpy(tmp->name, namebuf); 

    printf("Enter cat age:\t"); 
    scanf("%d", &tmp->age); 

    while(getchar() != '\n') 
     ; 

    return tmp; 
} 

어쨌든 디버거의 백 트레이스를 해석하는 방법을 정확히 모르겠습니다. 나는 어디로 잘못 갔는가? 드라이버 파일에서 사용자 입력을위한 더미 항목을 어떻게 처리했는지와 관련이 있습니까? 나는 그 문제 (또는 그 문제에 대한이 프로그램의 나머지 부분)를 잘 처리했다고 생각하지 않는다.

감사

+1

'addToTree' 함수가 작동하지 않아야합니다 ...'struct tree'에 대한 이중 포인터를 사용해야합니다. –

답변

3

면책 조항 : 당신이 오류가 나는 오류 (당신의 구조 정의가 아닌)에 대한 다른 곳에서는 보이지 않았다 당신의 addToTree 함수 내에서 거짓말을 생각하는 규정입니다.


addToTree 함수에 두 개의 오류가 있습니다. 첫 번째 문제는 leafcount을 올바르게 처리하지 못했기 때문입니다. 노드로 트리를 밀어 넣을 때 올바르지 않은 것을 발견 할 것입니다 (아래의 해결책으로 해결할 수 없습니다). 둘째, struct tree (또는 Tree)에 이중 포인터를 전달해야하며, 단일 포인터를 전달하면 NULL을 전달할 것이므로 빈 트리에 삽입 할 수 없습니다.

노드를 이미 만들었으므로 첫 번째 삽입이 작동하고 진행하지 않는 유일한 이유는 래퍼 구조를 사용하는 경우 NULL이어야합니다.

는 다음을 수행, 두 번째 오류를 수정하려면 다음을 제외하고

int addToTree(Item *thing, Tree **t, int (*fp)(const Item *, const Item *)) { 
    if(isFull(*t) == true) return 0; 

    if(isEmpty(*t) == true) { 
     Node *current = copyToNode(thing); 

     if(current == NULL) { 
      puts("Couldn't copy to tree!"); 

      return 0; 
     } 

     (*t) = current; 

     return 1; 
    } 

    if(fp(thing, t->root->thing) <= 0) 
     return addToTree(thing, &((*t)->left), fp); 
    else 
     return addToTree(thing, &((*t)->right), fp); 
} 

:은 또한 다르게 구조를 명명 고려할 것입니다. NodeTree 오해의 소지가있는 구조는 NodeItem이되어야하고 TreeBstNode을하게한다 (또는 그 라인을 따라 맞는 볼 어떤 명명 체계는) 다음과 같이 다음 정의 BstTree라는 래퍼 구조를 가지고 :

struct BstTree { 
    struct Tree *root; 
    int height; 
}; 

... root은 루트를 가리키며 Nodeheight은 이진 검색 트리의 높이입니다. 이렇게하면 의사 소통이 더 잘 이루어질뿐 아니라 구현이 훨씬 쉬워집니다.