NigthWalker NigthWalker - 19 days ago 6
C Question

a linked list of linked lists in C

Hello i am currently trying to do a project and i am wondering if i can create a linked list that contais other linked lists.I want to create a new type person in C but in my new type(person) every person can have kids and kids are a list of people and also every person has parents who are also people.So i am thinking of doing that using structures and linked lists.

#include <stdio.h>

struct person {
unsigned int id;//identity,unique for every person
char* name;
struct person **father;
struct person **mother;
struct kids **kids;
}

struct kids {
struct person **kid;
struct kids **next_kid;
};


Thank you in advance for your time.

Answer

Yes, you can have lists of lists, one example of which is shown below, a list of children each with their own list of toys.

First, the relevant header files and structures for the two types of objects (children and toys):

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

typedef struct sToy {
    char name[50];
    struct sToy *next;
} tToy;

typedef struct sChild {
    char name[50];
    tToy *firstToy;
    struct sChild *next;
} tChild;

Then, a helper function for allocating memory so I don't have to pollute the sample with lots of error checking:

void *chkMalloc (size_t sz) {
    void *mem = malloc (sz);

    // Just fail immediately on error.

    if (mem == NULL) {
        printf ("Out of memory! Exiting.\n");
        exit (1);
    }

    // Otherwise we know it worked.

    return mem;
}

Next, helper functions to allocate the two types of object and insert them into the relevant list. Note that I'm inserting at the start of the list to simplify the code, so we don't have to worry about list traversal or storing the final item pointer as well.

That means everything will be printed in reverse order when dumping the details but that's a small price to pay for keeping things simple:

void addChild (tChild **first, char *name) {
    // Insert new item at start.

    tChild *newest = chkMalloc (sizeof (*newest));
    strcpy (newest->name, name);
    newest->next = *first;
    *first = newest;
}

void addToy (tChild *first, char *name) {
    // Insert at start of list.

    tToy *newest = chkMalloc (sizeof (*newest));
    strcpy (newest->name, name);
    newest->next = first->firstToy;
    first->firstToy = newest;
}

Next, the function for dumping the lists in readable format:

void dumpDetails (tChild *currChild) {
    // For every child.

    while (currChild != NULL) {
        printf ("%s has:\n", currChild->name);

        // For every toy that child has.

        tToy *currToy = currChild->firstToy;
        if (currToy == NULL) {
            printf ("   <<nothing>>\n");
        } else {
            while (currToy != NULL) {
                printf ("   %s\n", currToy->name);
                currToy = currToy->next;
            }
        }
        currChild = currChild->next;
    }
}

And, lastly, a main function for tying all the others together:

int main (void) {
    tChild *firstChild = NULL;

    addChild (&firstChild, "Anita");
        addToy (firstChild, "skipping rope");
    addChild (&firstChild, "Beth");
    addChild (&firstChild, "Carla");
        addToy (firstChild, "model car");
        addToy (firstChild, "trampoline");

    dumpDetails (firstChild);

    return 0;
}

When you enter, compile and run all that code, you can see that it quite easily handles lists of lists:

Carla has:
   trampoline
   model car
Beth has:
   <<nothing>>
Anita has:
   skipping rope