Programming Linked Lists. Collections Store collection of data Online store - Items University ...

Post on 18-Jan-2018

220 views 0 download

description

Array Recap Allocated as one block in memory Convenient to declare  int arr[100]; Easy access to a single element  arr[i] Size is fixed  Wasting memory because of “large enough” allocation Adding / Deleting elements  need to shift large parts of the array

Transcript of Programming Linked Lists. Collections Store collection of data Online store - Items University ...

Programming

Linked Lists

Collections

Store collection of data Online store - Items University – Students Library – books

Until now we used arrays

Array Recap Allocated as one block in memory Convenient to declare

int arr[100]; Easy access to a single element

arr[i] Size is fixed

Wasting memory because of “large enough” allocation Adding / Deleting elements

need to shift large parts of the array

Linked Lists

Dynamic Efficient use of memory

Allocate just as much as needed Easy insertion in front Local deletion Hard to get to any particular element

Graphic Description

Array

Linked List

Each link (node) contains data and a pointer to the next link

Linked Lists

A list is a chain of nodes.typedef struct node_type{ <data> struct node_type* next;} Node;

NULL

Data

Next

Data

Next

Data

Next

head

Linked Lists Operation

Insert front, back, middle

Remove Find Size

Insertion (front)

Data

Next

head

1 .create the new node

2. have it point to the first element

3 .change the head of the list

Data

Next

Data

Next

NULL

Data

Next

Insertion (back)

Data

Next

head

1 .create the new node

2. locate the last element in the list

3 .have the last element point to the new one

Data

Next

Data

Next

NULL

last

NULL

Data

Next

Insertion (middle)

Data

Next

head

NULL

1. create the new node

2. locate the insertion point

3. new_item->next = curr->next

4. curr->next = new_item

Data

Next

Data

Next

curr

new_item

NULL

Data

Next

Delete Node

Data

Next

head

1 .find node to remove

2. have the previous node point to the one after the node to be removed

3 .remove the node

Data

Next

Data

Next

Data

Next

NULL

remove

Iterating

Data

Next

head

Data

Next

Data

Next

Data

Next

1 .start at the beginning

2. advance your iterator one node at a time iter = iter->next

3 .unti the end is reached

iter iter iter iter

NULL

iter

Length Count the number of nodes in a list

int length(Node *head){ int count = 0; while (head != NULL) { count++; head = head->next; } return count;}

Length (recursive)

Count the number of nodes in a list

int length(Node *head){ if (head == NULL) return 0;

return length(head->next) + 1;}

Using Lengthint main(void){ Node *head = build_list(); int length = length(head);

printf("The length of the list is: %d\n", length);

free_list(head);

return 0;}

Course Management System

Maintain a list of studentsKeep their ID, name, grade etc.

Allow for adding / removing a student Find a student in the list Produce Reports

Average grade

Storing a Collection of Students Use an array of student structures There are problems with this –

we must allocate a big-enough array before accepting students (how do we know what’s big enough?)

How shall we remove students from the list without creating “holes”?

How can we maintain the list sorted by grade? Insertion and deletion may be problematic

Linking Students Use a linked list Define a student node

typedef struct student { char id[ID_LENGTH]; char name[NAME_LENGTH]; int grade;

/* A pointer to the next node in the list */ struct student *next;

} Student;

Exercise Download find_student_ex.c from the tirgul home

page Implement Student* find_student(const Student *head, const char* id)

find_student searches for a student with a given id. It returns a pointer to the student if found, otherwise it returns NULL.

Solution/* find a student whose id matches the given id */Student* find_student(Student *head, char *id){ while (head != NULL) /* go over all the list */ { if (strcmp(head->id, id) == 0) /* same id */ return head; head = head->next; }

/* If we're here, we didn't find it */ return NULL;}

Adding students

Usually when using linked lists we don’t know how many elements will be in the list

Therefore we would like to be able to dynamically allocate new elements when the need arises

A possible implementation follows…

Creating a New StudentStudent* new_student(char* name, char* id, int grade){ Student *std =(Student*)malloc(sizeof(Student));

if (std != NULL) { strcpy(std->name, name); strcpy(std->id, id); std->grade = grade; std->next = NULL; } return std;}

Add in FrontStudent* add_front(Student *head, Student *std){ std->next = head; return std;}

int main(void){ Student *std_list, *std; ... std = new_student(...); std_list = add_front(std_list, std); ... return 0;}

Sorted Add

Adding a student to a list can be done in such a way that the list remains sorted by grade

We will implement this in a separate function

Adding a student - begining

Head

Adding a student – mid/end

Head

Insert new item:

Previous

Next

Student *add_student(Student *head, Student *to_add){ Student *curr_std, *prev_std = NULL;

if (head == NULL) return to_add;

if (to_add->grade > head->grade) { to_add->next = head; return to_add; }

curr_std = head; while (curr_std != NULL && to_add->grade < curr_std->grade) { prev_std = curr_std; curr_std = curr_std->next; }

prev_std->next = to_add; to_add->next = curr_std;

return head;}

handle empty list

handle beginning

the rest

Adding a student – beginning

if (head == NULL) return to_add;

if (to_add->grade > head->grade){ to_add->next = head; return to_add;}

95 80 70 …

to_add

100

head

Adding a student – mid / endcurr_std = head;while (curr_std != NULL && to_add->grade < curr_std->grade){ prev_std = curr_std; curr_std = curr_std->next;}

prev_std->next = to_add;to_add->next = curr_std;return head;

95 80 70 60head

to_add

75

curr_std

Adding a student – mid / endcurr_std = head;while (curr_std != NULL && to_add->grade < curr_std->grade){ prev_std = curr_std; curr_std = curr_std->next;}

prev_std->next = to_add;to_add->next = curr_std;return head;

95 80 70 60head

to_add

75

curr_std

Adding a student – mid / endcurr_std = head;while (curr_std != NULL && to_add->grade < curr_std->grade){ prev_std = curr_std; curr_std = curr_std->next;}

prev_std->next = to_add;to_add->next = curr_std;return head;

95 80 70 60head

to_add

75

curr_std

prev_std

Adding a student – mid / endcurr_std = head;while (curr_std != NULL && to_add->grade < curr_std->grade){ prev_std = curr_std; curr_std = curr_std->next;}

prev_std->next = to_add;to_add->next = curr_std;return head;

95 80 70 60head

to_add

75

curr_std

prev_std

Adding a student – mid / endcurr_std = head;while (curr_std != NULL && to_add->grade < curr_std->grade){ prev_std = curr_std; curr_std = curr_std->next;}

prev_std->next = to_add;to_add->next = curr_std;return head;

95 80 70 60head

to_add

75

curr_std

prev_std

Adding a student – mid / endcurr_std = head;while (curr_std != NULL && to_add->grade < curr_std->grade){ prev_std = curr_std; curr_std = curr_std->next;}

prev_std->next = to_add;to_add->next = curr_std;return head;

95 80 70 60head

to_add

75

curr_std

prev_std

Adding a student – mid / endcurr_std = head;while (curr_std != NULL && to_add->grade < curr_std->grade){ prev_std = curr_std; curr_std = curr_std->next;}

prev_std->next = to_add;to_add->next = curr_std;return head;

95 80 70 60head

to_add

75

curr_std

prev_std

Adding a student – mid / endcurr_std = head;while (curr_std != NULL && to_add->grade < curr_std->grade){ prev_std = curr_std; curr_std = curr_std->next;}

prev_std->next = to_add;to_add->next = curr_std;return head;

95 80 70 60head

to_add

75

curr_std

prev_std

Adding a student – mid / endcurr_std = head;while (curr_std != NULL && to_add->grade < curr_std->grade){ prev_std = curr_std; curr_std = curr_std->next;}

prev_std->next = to_add;to_add->next = curr_std;return head;

95 80 70 60head

to_add

75

curr_std

prev_std

Adding a student – mid / endcurr_std = head;while (curr_std != NULL && to_add->grade < curr_std->grade){ prev_std = curr_std; curr_std = curr_std->next;}

prev_std->next = to_add;to_add->next = curr_std;return head;

95 80 70 60head

to_add

75

curr_std

prev_std

Removing a student

We would like to be able to remove a student by her/his ID.

The function that performs this is remove_student

HeadPrevious

Current

Removing a student - reminder

Removing a student – beginningif (head == NULL)

return head;

cur = head;

if (strcmp(cur->id, id) == 0){ head = head->next; free(cur); return head;}

74823 53621 25773head

cur

14525

ID

14525

Removing a student – mid list

14525 74823 53621 25773head

53621

ID

cur

while (cur != NULL && strcmp(cur->id, id) != 0){ prev = cur; cur = cur->next;}

if (cur != NULL){ prev->next = cur->next; free(cur);}

return head;

Removing a student – mid list

14525 74823 53621 25773head

53621

ID

prev cur

while (cur != NULL && strcmp(cur->id, id) != 0){ prev = cur; cur = cur->next;}

if (cur != NULL){ prev->next = cur->next; free(cur);}

return head;

Removing a student – mid list

14525 74823 53621 25773head

53621

ID

prev cur

while (cur != NULL && strcmp(cur->id, id) != 0){ prev = cur; cur = cur->next;}

if (cur != NULL){ prev->next = cur->next; free(cur);}

return head;

Removing a student – mid list

14525 74823 53621 25773head

53621

ID

prev cur

while (cur != NULL && strcmp(cur->id, id) != 0){ prev = cur; cur = cur->next;}

if (cur != NULL){ prev->next = cur->next; free(cur);}

return head;

Removing a student – mid listwhile (cur != NULL && strcmp(cur->id, id) != 0){ prev = cur; cur = cur->next;}

if (cur != NULL){ prev->next = cur->next; free(cur);}

return head;

14525 74823 25773head

53621

ID

prev cur

Deallocating all studentsvoid free_list(Student *head){ Student *temp = head;

while (head != NULL) { temp = head; head = head->next; free(temp); }}

Deallocating students

head

tempwhile (head != NULL) { temp = head; head = head->next; free(temp);}

Deallocating students

head

tempwhile (head != NULL) { temp = head; head = head->next; free(temp);}

Deallocating students

head

tempwhile (head != NULL) { temp = head; head = head->next; free(temp);}

Deallocating students

head

tempwhile (head != NULL) { temp = head; head = head->next; free(temp);}

Deallocating students

head

tempwhile (head != NULL) { temp = head; head = head->next; free(temp);}

Deallocating students

head

tempwhile (head != NULL) { temp = head; head = head->next; free(temp);}

Deallocating students

head

tempwhile (head != NULL) { temp = head; head = head->next; free(temp);}

Deallocating students

head

tempwhile (head != NULL) { temp = head; head = head->next; free(temp);}

Deallocating students

head

tempwhile (head != NULL) { temp = head; head = head->next; free(temp);}

Deallocating students

head

tempwhile (head != NULL) { temp = head; head = head->next; free(temp);}

Deallocating students

head

tempwhile (head != NULL) { temp = head; head = head->next; free(temp);}

Deallocating students

head

tempwhile (head != NULL) { temp = head; head = head->next; free(temp);}

Deallocating students

head

tempwhile (head != NULL) { temp = head; head = head->next; free(temp);}

Deallocating students

head

tempwhile (head != NULL) { temp = head; head = head->next; free(temp);}

Deallocating students

head

tempwhile (head != NULL) { temp = head; head = head->next; free(temp);}

Deallocating students

head

tempwhile (head != NULL) { temp = head; head = head->next; free(temp);}

Deallocating students

head

tempwhile (head != NULL) { temp = head; head = head->next; free(temp);}

Deallocating students

NULL

head

tempwhile (head != NULL) { temp = head; head = head->next; free(temp);}

Deallocating students

void free_list(Student *head){ if (head == NULL) return;

free_list(head->next); free(head);}

Exercise Use change_grade_ex.c and implement the

change_grade function. The function takes as input the head of the list,

the ID whose grade we’d like to change, and the new grade

Hint – Create a new student with the same name and ID as the old one, but with the new grade. Remove the old student from the list and add the new one using the existing functions

solutionStudent* find_student(Student* head, char* id){ while (head != NULL && strcmp(head->id, id) != 0) { head = head->next; }

return head;}

Student* change_grade(Student *head, char* id, int new_grade){ Student *std = find_student(head, id); std = new_student(std->name, id, new_grade);

head = remove_student(head, id); return add_student(head, std);}