programming linked lists. collections store collection of data online store - items university ...
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 arrayTRANSCRIPT
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);}