John
John

Reputation: 105

How to free linked list which is within another linked list?

I have a School struct that holds a linked list of Student structs and each of those Student structs hold a linked list of Courses structs. I am a bit puzzled about how I would be able to free both linked lists. I am particularly unsure about how I would free the Courses linked list since it is within another linked list.

struct Courses {
    char *courseName;
    int creditValue;
    Courses *next;
} Courses;

struct Student {
    char *studentName;
    int studentAge;
    Courses *coursesList;  //First course (node)
    Student *next; 
} Student;

struct School {
     char *schoolName;
     int schoolAge;
     Student *studentList;  //First student (node)
} School;

If someone could show me an example on how I would be able to free both the linked lists that would be great!

Upvotes: 0

Views: 87

Answers (1)

chqrlie
chqrlie

Reputation: 144695

You should think in terms of ownership: when you free an item, you must free everything it owns, that is everything his has a pointer to that is not owned by something else.

Along these lines, each list item owns the next item, every School owns its list of Students, every Student owns its list of Courses.

Your type definitions seem incorrect as you use the same identifier for types and variables. You should rewrite them this way:

typedef struct Course Course;
typedef struct Student Student;
typedef struct School School;

struct Course {
    char *courseName;
    int creditValue;
    Course *next;
};

struct Student {
    char *studentName;
    int studentAge;
    Course *courseList;  //First course (node)
    Student *next; 
};

struct School {
    char *schoolName;
    int schoolAge;
    Student *studentList;  //First course (node)
};

The function to free everything:

void freeSchool(School *school) {
    Student *student = school->studentList;
    while (student) {
        Course *course = student->courseList;
        while (course) {
            free(course->courseName); // if it was allocated
            Course *nextCourse = course->next;
            free(course);
            course = nextCourse;
        }
        free(student->studentName); // if it was allocated
        Student *nextStudent = student->next;
        free(student);
        student = nextStudent;
    }
    free(school->schoolName); // if it was allocated
    free(school);
}

Note the similarity between the different levels. You can also split this function into separate freeSchool, freeStudent and freeCourse functions that you can use to handle individual object deletion in the program.

An elegant way to handle element deletion is for the freeXXX function to return the next element and free the node:

Courses *freeCourse(Course *course) {
    Course *next = course->next;
    free(course->courseName); // if it was allocated
    free(course);
    return next;
}

Student *freeStudent(Student* student) {
    Student *next = student->next;
    while (student->courseList) {
        student->courseList = freeCourse(student->courseList);
    }
    free(student->studentName); // if it was allocated
    free(student);
    return next;
}

School *freeSchool(School *school) {
    while (school->studentList) {
        school->studentList = freeStudent(school->studentList);
    }
    free(school->schoolName); // if it was allocated
    free(school);
    return NULL;
}

Upvotes: 3

Related Questions