Binární vyhledávací strom uvnitř Binární vyhledávací strom

hlasů
0

Mám úkol, který mě požádat vytvořit struct binárního vyhledávacího stromu, kde jeho uzel binárního vyhledávacího stromu je další binární vyhledávací strom. První BST má příjmení studentů a druhý má křestní jména a id. Také pokud někdo má stejné příjmení s jiným studentem Nesmím vytvořit další „příjmení“ uzel, ale musím vytvořit uvnitř stávajícího „příjmení“ uzel další „křestní jméno a ID“ uzel. Byt více specifický:

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;

Mým hlavním problémem je, jak vytvořit různé nameANDid uzel pro každou křestní jméno, protože jsem našel následující kód tvořím 2 BST jeden pro příjmení a jiný pro názvy, ale chtěl bych být jako například: Mám-li tyto studenty

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

Chci ukládat takto: .........

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

Namísto toho jsem si něco jako: ...........

 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

Vložím zde některé funkce, aby byl konkrétnější

Funkce load načte jména z TXT dokumentu.

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);  
}

kde

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

Funkce AddNode je: ...

      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;
         }

A add_node_nameANDid () funkce je podobně jako předchozí funkce, ale má některé proměnné změnilo:

      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;
    }

Omlouváme se za obrovské zdrojový kód, který jsem jen nahrát, ale to by bylo velmi obtížné vysvětlit, aniž by to.

Myslím, že mám dva problémy, ale nemám znalosti, aby jejich řešení.

PRVNÍ: Mám vytvořit jiný FIRSTNAME BST pro každý uzel příjmení a myslím, že nemám dělat to, ale nevím, jak to udělat ...

Nějaké návrhy?

Položena 29/05/2011 v 12:22
zdroj uživatelem
V jiných jazycích...                            


1 odpovědí

hlasů
2

Dal jsem implementaci příklad tohoto níže komentoval vysvětlit, jak jsem se blížil to. Měli byste být schopni používat své myšlenky změnit způsob, jakým váš kód funguje. Všimněte si, že to není ideální implementace, z vrcholu mé hlavě, vidím následující problémy.

  1. Jeho rekurzivní , což znamená, že hloubka stromu to zvládne je omezena velikostí zásobníku na cílovém počítači. Existují dva způsoby, jak můžete zaútočit to buď:
    1. Ať je to iterativní . To znamená, že použití for/ whilesmyčky namísto funkcí volat sebe - to by umožnilo co největšímu počtu uzlů podle pokynů svého stroje paměť zvládne (řeší problém).
    2. Aktualizace add_name_to_treezvládnout inzerce pro vyvážené binární strom (ale to jen pomůže tento problém vyřešit, limit stack je tam pořád).
  2. To nemůže zvládnout dva lidi s naprosto stejným názvem, ale jiným ID je - po prvním osoba je přidán do stromu, všechny následné lidé stejného jména jsou ignorovány.

Nechám to jako cvičení pro vás řešení těchto situací.


#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;
}
Odpovězeno 29/05/2011 v 23:46
zdroj uživatelem

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