Двоичное дерево в бинарном дереве поиска

голоса
0

У меня есть домашние задания, которые просят у меня, чтобы создать из-структуры бинарного дерева поиска, где его узел бинарного дерева поиска является еще одним бинарным деревом поиска. Первый BST имеет фамилии студентов, а другие имеют имена и идентификатор. Кроме того, если кто-то имеет такую ​​же фамилию с другим студентом, я не должен создавать другую «фамилию» узел, но я должен создать внутри существующего узла «фамилия» другое «имя и Id» узла. Чтобы быть более конкретным:

typedef struct nameANDid{ //name and id nodes
    char first[20];
    int ID;
    struct nameANDid *nleft;
    struct nameANDid *nright;
}yohoho;
typedef struct node{  //surname nodes
   char last[20];  
   struct nameANDid yohoho;  
   struct node *left;
   struct node *right;
}node;

Моя главная проблема заключается в том, чтобы создать другой узел nameANDid для каждого FirstName я нашел, потому что с помощью следующего кода создать 2 BST один для фамилий, а другие для имен, но я хотел бы быть, как, например: Если у меня есть эти студенты

 Stallone Sylvester 11111111
 Stallone Noah      22222222
 Norris   Chuck     33333333
 Hogan    Hulk      44444444
 Hogan    Daniel    55555555

Я хочу, чтобы хранить их, как это: .........

 Stallone Sylvester 11111111
          Noah      22222222
 Norris   Chuck     33333333
 Hogan    Hulk      44444444
          Daniel    55555555

Вместо этого я беру что-то вроде: ...........

 Stallone  Sylvester 11111111.
           Noah      22222222 
           Chuck     33333333
           Hulk      44444444 
           Daniel    55555555

 Norris  Sylvester 11111111.
           Noah      22222222 
           Chuck     33333333
           Hulk      44444444 
           Daniel    55555555
 Hogan    Sylvester 11111111.
           Noah      22222222 
           Chuck     33333333
           Hulk      44444444 
           Daniel    55555555

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

Функция загрузки загружает имена из текстового документа.

void loadData(struct node *temp){      
int i;
FILE *fp;
fp=fopen(FILENAME,r);
if (fp == NULL) printf(File does not exist\n);
for (i=0; i<5; i++){                
    fscanf(fp,%s,&temp->last);
    fscanf(fp,%s,&temp->yohoho.first);
    fscanf(fp,%d,&temp->yohoho.ID);                 
    top=add_node(top,temp);  //this function create a surname node        
    }        
fclose(fp);     
    printf(\n\nFile loaded\n);  
}

где

        struct node temp;//just  a node pointer
        struct node *top=NULL; //shows the top of the tree

Функция ADDNODE является: ...

      struct node * add_node (struct node *top, struct node *temp){  
           struct node *newNode;  
           if (top == NULL){    
           newNode=(struct node *)malloc(sizeof(struct node));
           temp->left=NULL;
           temp->right=NULL;     
           if (memcpy(newNode,temp,sizeof(struct node)) == NULL){
               printf(Node addition failed\n);
               return NULL;}
           else {             
               topname=add_node_nameANDid(topname,&temp->yohoho); //Call the add_node_nameANDid to create a new name node in the other tree                           
               return newNode;}
            }
           else {   
               if (stricmp(temp->last,top->last) < 0){ //Insert node surname left
                     top->left=add_node(top->left,temp);}
               else if (stricmp(temp->last,top->last) == 0){         
                     topname=add_node_nameANDid(topname,&temp->yohoho);  //Call the add_node_nameANDid to create a new name node in the other tree   if i have the same surname        
               }
               else {
                     top->right=add_node(top->right,temp);           
               }
               return top;
             } 
             return NULL;
         }

И add_node_nameANDid () функция, как и предыдущая функция, но она имеет некоторые переменные изменились:

      struct nameANDid * add_node_nameANDid (struct nameANDid *topname, struct nameANDid *temp2){
        struct nameANDid *newNode_nameANDid;     
        if (topname == NULL){ 
            newNode_nameANDid=(struct nameANDid *)malloc(sizeof(struct nameANDid));
            temp2->nleft=NULL;
            temp2->nright=NULL;
            if (memcpy(newNode_nameANDid,temp2,sizeof(struct nameANDid)) == NULL){
                   printf(Node addition failed\n);
                   return NULL;}
            else {                 
                   return newNode_nameANDid;}
            }
        else {   
             if (stricmp(temp2->first,topname->first) <= 0){       
                  topname->nleft=add_node_nameANDid(topname->nleft,temp2);}
        else {         
                  topname->nright=add_node_nameANDid(topname->nright,temp2);}  
        return topname;
        } 
     return NULL;
    }

Извините за огромный исходный код, который я только загрузить, но это было бы очень трудно объяснить без этого.

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

ПЕРВЫЙ: Я должен создавать различный ПгвЬЫат BST для каждого узла фамилии, и я думаю, что я не делаю это, но я не знаю, как это сделать ...

Какие-либо предложения?

Задан 29/05/2011 в 12:22
источник пользователем
На других языках...                            


1 ответов

голоса
2

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

  1. Его рекурсивные , что означает глубину дерева он может обрабатывать ограничен размером стека на целевом компьютере. Есть два способа вы можете атаковать это, либо:
    1. Сделать это итеративный . То есть, использование for/ whileпетли вместо функций , называющих себя - это позволило бы , как многие узлы , как ваши машины памяти может обрабатывать (исправляет проблему).
    2. Обновление add_name_to_treeдля обработки вставки для сбалансированного двоичного дерева (но это только помогает вопросу, предел стеки все еще есть).
  2. Он не может обрабатывать два человека с точно таким же именем, но разными идентификаторами - после того, как первый человек, добавляется к дереву, все последующие люди одного и того же имени, игнорируются.

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


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

/* a single struct type for storing all tree elements */
typedef struct _node
{
    char name[50];
    int id;
    struct _node *subname;
    struct _node *left;
    struct _node *right;
} node;

/* creates a new node structure for the specified name and id */
node *create_node(const char *name, int id)
{
    node *newNode = (node*)malloc(sizeof(node));
    memset(newNode, 0, sizeof(*newNode));

    newNode->id = id;
    strncpy(newNode->name, name, sizeof(newNode->name));

    return newNode;
}

/* inserts the name/id pair into the tree specified by root.
   note that root is passed as a pointer to a pointer, so that
   it can accept NULL if no tree exists yet, and return to the 
   caller the node the node that contains the name.  Note that
   id is ignored if "name" already exists, i'll leave it as an
   excersice for you to handle situations with the same name
   with multiple id's */
node *add_name_to_tree(node **root, const char *name, int id)
{
    if (*root == NULL)
    {
        *root = create_node(name, id);
        return *root;
    }

    const int cmp = strcmp(name, (*root)->name);

    if (cmp < 0)
    {
        return add_name_to_tree(&(*root)->left, name, id);
    }
    else if (cmp > 0)
    {
        return add_name_to_tree(&(*root)->right, name, id);
    }
    else
    {
        return *root;
    }
}

/* adds the specified first/last name and id combo to the tree
   specified by root */
node *add_name(node *root, const char *first, const char *last, int id)
{
    /* this call will return the node that holds the last name,
       we can then use its "subname" tree root to insert the first name */
    node *last_node = add_name_to_tree(&root, last, 0);

    /* use the "subname" of the node that stores the last name as the 
       root of the tree that stores first names */
    add_name_to_tree(&last_node->subname, first, id);
    return root;
}

/* just to demonstrate why I use the same node type for first/last names,
   its because it allows you to support any number of names, see
   below - an add function that adds people with a middle name to the tree
   */
node *add_with_middle_name(node *root, const char *first, 
                           const char *middle, const char *last, int id)
{
    node *last_node = add_name_to_tree(&root, last, 0);
    node *mid_node = add_name_to_tree(&last_node->subname, middle, 0);
    add_name_to_tree(&mid_node->subname, first, id);
    return root;
}

/* recursively traverse the name tree, printing out the names */
void print_names(node *names, int level)
{
    const int indent = 10;

    if (names == NULL)
    {
        printf("\n");
    }

    if (names->left)
    {
        print_names(names->left, level);
    }

    if (names->subname)
    {
        printf("%*c %s \n", (indent * level), ' ', names->name);
        print_names(names->subname, level + 1);
        printf("\n");
    }
    else
    {
        printf("%*c %-*s %d\n", 
               (indent * level), ' ', 
               indent, names->name, names->id);
    }

    if (names->right)
    {
        print_names(names->right, level);
    }
}

int main()
{
    node *names = NULL;

    names = add_name(names, "Sylvester", "Stallone", 11111111);
    names = add_name(names, "Noah", "Stallone", 22222222);
    names = add_name(names, "Chuck", "Norris", 33333333);
    names = add_name(names, "Hulk", "Hogan", 44444444);
    names = add_name(names, "Daniel", "Hogan", 55555555);

    names = add_with_middle_name(names, "Peter", "Michael", 
                                 "Zachson", 66666666);

    print_names(names, 0);

    return 0;
}
Ответил 29/05/2011 в 23:46
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more