This document discusses linked lists and their implementation in C. It begins by describing the differences between array-based and linked list implementations. Specifically, it notes that linked lists use dynamic memory allocation and pointers to connect nodes rather than contiguous memory blocks. The document then covers creating and traversing linked lists using nodes with data fields and next pointers. It provides code examples for inserting, finding, deleting and destroying nodes in a singly linked list. Finally, it briefly lists some other common linked list operations like sorting, reversing and finding min/max elements.
3. Array Implementation...
Requires an estimate of the maximum size of the
list
waste space
Print all element and find an specific number:
Linear – Traverse whole array
Print i’th Element:
Constant time - (Example: printf(“%d”,a[i]);
insert and delete: slow
e.g. insert at position 0 (making a new element)
requires first pushing the entire array down one spot to
make room
e.g. delete at position 0
requires shifting all the elements in the list up one
4. Pointer Implementation (Linked List)
Ensure that the list is not stored contiguously
use a linked list
a series of structures that are not necessarily adjacent in
memory
Each node contains the element and a pointer to a
structure containing its successor
the last cell’s next link points to NULL
Compared to the array implementation,
the pointer implementation uses only as much space as is needed for the
elements currently on the list
but requires space for the pointers in each cell
5. Nodes and Linked Lists
A linked list is a list that can grow and shrink while
the program is running
A linked list is constructed using pointers
A linked list often consists of structs that
contain a pointer variable connecting them to other
dynamic variables
A linked list can be visualized as items, drawn as
boxes, connected to other items by arrows
10 12 14 end
head
6. Linked Lists
A linked list is a series of connected nodes
Each node contains at least
A piece of data (any type)
Pointer to the next node in the list
Head: pointer to the first node
The last node points to NULL
10 ∅
Head
20 30
10
data pointer
node
7. Implementing Nodes
Nodes are implemented in C as “struct”
Example: A structure to store two data items and
a pointer to another node of the same type,
along with a type definition might be:
struct Node
{
int item;
struct Node *next;
};
8. Self-Referential Structures
A structure may not contain an object of its own type.
struct Node {
int item;
struct Node n; /* Invalid */
};
However, a structure may contain a pointer to the same
type.
struct Node {
int item;
struct Node *pn; /* Valid */
};
9. The head of a List
The box labeled head, is not a node, but a pointer
variable that points to a node.
Pointer variable head is declared as:
struct Node *head;
10 ∅
head
20 30
10. Accessing Items in a Node
One way to change the number in the first node from
10 to 12:
head->item = 12;
12 ∅
head
20 30
11. NULL
The defined constant NULL is used as…
An end marker for a linked list
A program can step through a list of nodes by following
the pointers, but when it finds a node containing NULL,
it knows it has come to the end of the list
The value of a pointer that has nothing to point to
The value of NULL is 0
Any pointer can be assigned the value NULL:
double* there = NULL;
12. Linked Lists
A linked list is a list of nodes in which each node
has a member variable that is a pointer that
points to the next node in the list
The first node is called the head
The pointer variable head, points to the first node
The pointer named head is not the head of the list…it
points to the head of the list
The last node contains a pointer set to NULL
13. Building a Linked List:
Declaring Pointer Variable head
With the node defined and a type definition to
make or code easier to understand, we can
declare the pointer variable head:
struct Node *head;
head is a pointer variable that will point to the head node
when the node is created
14. Building a Linked List:
Creating the First Node
To create the first node, the operator new is used
to create a new dynamic variable:
head = (struct Node *)malloc(sizeof(struct Node));
Now head points to the first, and only, node in the
list
15. Building a Linked List:
Initializing the Node
Now that head points to a node, we need to
give values to the member variables of the node:
head->item = 10;
head->next = NULL;
Since this node is the last node, the link is set to NULL
10 ∅
head
16. Traversing Singly Linked List
void Traverse(struct Node *head)
Print the data of all the elements
Print the number of the nodes in the list
From “main()” function call “Traverse(head)”.
void Traverse(struct Node *head)
{
int num = 0;
struct Node *currNode;
currNode = head;
while (currNode != NULL){
printf(“%d “,currNode->item);
currNode = currNode->next;
num++;
}
printf("Number of nodes in the list: %dn”,num);
}
20. Traversing Singly Linked List (2)
Output: 12 20 30
Num: 3
currnode = NULL at this moment. So function
terminates.
12 ∅
head
20 30
currnode
21. Inserting a new node
Node* InsertNode(int index, double x)
Insert a node with data equal to x after the index’th elements. (i.e.,
when index = 0, insert the node as the first element;
when index = 1, insert the node after the first element, and so
on)
If the insertion is successful, return the inserted node.
Otherwise, return NULL.
(If index is < 0 or > length of the list, the insertion will fail.)
Steps
Locate index’th element
Allocate memory for the new node
Point the new node to its successor
Point the new node’s predecessor to the new node newNode
index’th
element
22. Inserting a new node
Possible cases of InsertNode
Insert into an empty list
Insert in front
Insert at back
Insert in middle
But, in fact, only need to handle two cases
Insert as the first node (Case 1 and Case 2)
Insert in the middle or at the end of the list (Case 3 and Case 4)
23. Inserting a new node
struct Node* InsertNode(int index, double x) {
if (index < 0) return NULL;
int currIndex = 1;
struct Node* currNode = head;
while (currNode!=NULL && index > currIndex) {
currNode = currNode->next;
currIndex++;
}
if (index > 0 && currNode == NULL) return NULL;
Node* newNode = (struct Node *)malloc(sizeof(struct Node));
newNode->data = x;
if (index == 0) {
newNode->next = head;
head = newNode;
}
else {
newNode->next = currNode->next;
currNode->next = newNode;
}
return newNode;
}
Try to locate index’th
node. If it doesn’t exist,
return NULL.
24. Inserting a new node
struct Node* InsertNode(int index, double x) {
if (index < 0) return NULL;
int currIndex = 1;
struct Node* currNode = head;
while (currNode!=NULL && index > currIndex) {
currNode = currNode->next;
currIndex++;
}
if (index > 0 && currNode == NULL) return NULL;
Node* newNode = (struct Node *)malloc(sizeof(struct Node));
newNode->data = x;
if (index == 0) {
newNode->next = head;
head = newNode;
}
else {
newNode->next = currNode->next;
currNode->next = newNode;
}
return newNode;
}
Create a new node
25. Inserting a new node
struct Node* InsertNode(int index, double x) {
if (index < 0) return NULL;
int currIndex = 1;
struct Node* currNode = head;
while (currNode!=NULL && index > currIndex) {
currNode = currNode->next;
currIndex++;
}
if (index > 0 && currNode == NULL) return NULL;
Node* newNode = (struct Node *)malloc(sizeof(struct Node));
newNode->data = x;
if (index == 0) {
newNode->next = head;
head = newNode;
}
else {
newNode->next = currNode->next;
currNode->next = newNode;
}
return newNode;
}
Insert as first element
head
newNode
26. Inserting a new node
struct Node* InsertNode(int index, double x) {
if (index < 0) return NULL;
int currIndex = 1;
struct Node* currNode = head;
while (currNode!=NULL && index > currIndex) {
currNode = currNode->next;
currIndex++;
}
if (index > 0 && currNode == NULL) return NULL;
Node* newNode = (struct Node *)malloc(sizeof(struct Node));
newNode->data = x;
if (index == 0) {
newNode->next = head;
head = newNode;
}
else {
newNode->next = currNode->next;
currNode->next = newNode;
}
return newNode;
}
Insert after currNode
newNode
currNode
27. Finding a node
int FindNode(double x, struct Node *head)
Search for a node with the value equal to x in the list.
If such a node is found, return its position. Otherwise, return
0.
int FindNode(double x, struct Node *head) {
struct Node* currNode = head;
int currIndex = 1;
while (currNode!=NULL && currNode->data != x) {
currNode = currNode->next;
currIndex++;
}
if (currNode!=NULL) return currIndex;
else return 0;
}
28. Deleting a node
int DeleteNode(double x)
Delete a node with the value equal to x from the list.
If such a node is found, return its position. Otherwise, return
0.
Steps
Find the desirable node (similar to FindNode)
Release the memory occupied by the found node
Set the pointer of the predecessor of the found node to the
successor of the found node
Like InsertNode, there are two special cases
Delete first node
Delete the node in middle or at the end of the list
29. Deleting a node
int DeleteNode(double x) {
struct Node* prevNode = NULL;
struct Node* currNode = head;
int currIndex = 1;
while (currNode!=NULL && currNode->data != x) {
prevNode = currNode;
currNode = currNode->next;
currIndex++;
}
if (currNode!=NULL) {
if (prevNode) {
prevNode->next = currNode->next;
delete currNode;
}
else {
head = currNode->next;
delete currNode;
}
return currIndex;
}
return 0;
}
Try to find the node with its
value equal to x
30. Deleting a node
int DeleteNode(double x) {
struct Node* prevNode = NULL;
struct Node* currNode = head;
int currIndex = 1;
while (currNode!=NULL && currNode->data != x) {
prevNode = currNode;
currNode = currNode->next;
currIndex++;
}
if (currNode!=NULL) {
if (prevNode!=NULL) {
prevNode->next = currNode->next;
free (currNode);
}
else {
head = currNode->next;
delete currNode;
}
return currIndex;
}
return 0;
}
currNodeprevNode
31. Deleting a node
int DeleteNode(double x) {
struct Node* prevNode = NULL;
struct Node* currNode = head;
int currIndex = 1;
while (currNode!=NULL && currNode->data != x) {
prevNode = currNode;
currNode = currNode->next;
currIndex++;
}
if (currNode!=NULL) {
if (prevNode!=NULL) {
prevNode->next = currNode->next;
free (currNode);
}
else {
head = currNode->next;
free( currNode);
}
return currIndex;
}
return 0;
}
currNodehead
32. Destroying the list
void DeleteList(struct Node *head)
Use the DeleteList() function to release all the memory used by
the list.
Step through the list and delete each node one by one.
void DelteList(struct Node *head) {
struct Node* currNode = head, *nextNode = NULL;
while (currNode != NULL)
{
nextNode = currNode->next;
// destroy the current node
free (currNode);
currNode = nextNode;
}
}
33. Linked List (Other Operaions)
Find the highest and lowest element from a linked list.
Sort the linked list
Insert a node before (and after) a given number of a linked
list
Reverse the linked list
Print the linked list in reverse order (using (and without
using)recursion)
Delete the last element of a linked list (where you are given
the head of the linked list only)
Find the middle element of a linked list.