Linked Lists
Linked Lists
Head
A linked list is a linear collection of connected nodes
Each node contains at least
A piece of data (any type) node
Pointer to the next node in the list
A
Head: pointer to the first node
The last node points to NULL data pointer
a1 a2 a3 a4
Memory
Content a1 800 a2 712 a3 992 a4 0
Memory
1000 800 3 712 992
Address
Composition of a Linked List
D
A
B E
head
C
Just like any other data type, the information about the
node
has to be first be declared.
struct Node
{
int data;
struct Node *next;
};
head null
Creating a Linked List
Step 3) Allocate memory for the
node
?
Creating a Linked List
0
100
Sample Linked List Operations
void main() {
NODEPTR ListStart = NULL;
/* safest to give ListStart an initial legal
value -- NULL indicates empty list */
Pictorially In Memory
ListStart ListStart
0
100
ListStart->next = NULL;
ListStart ListStart
5 108 5 0
100
108
ListStart->next
5 ? ?
= (NODEPTR) 108
malloc(sizeof(struct
5 120 ? ?
node));
ListStart ListStart
100 108 120
ListStart->next->data = 9;
ListStart->next->next = NULL;
ListStart ListStart
5 9 108 5 120 9 0
100 108 120
Sample Linked List Ops (cont)
ListStart->next->next = (NODEPTR) malloc(sizeof(struct node));
ListStart ListStart
5 9 ? ? 108 5 120 9 132 ? ?
100 108 120 132
ListStart->next->next->data = 6;
ListStart->next->next->next = NULL;
ListStart ListStart
5 9 6 108 5 120 9 132 6 0
100
108
120
132
e NEXT
newNode
Inserting a Node at the Front
Inserting a Node at the Front
void insert_start(NODEPTR *head, int x);
10
7
13
null
entry
head
Inserting a Node at the Front
void insert_start(NODEPTR *head, int x);
variable temp_ptr.
15
10
7
13
null
entry
head
Inserting a Node at the Front
void insert_start(NODEPTR *head, int x);
temp_ptr = (NODEPTR)
malloc(sizeof(struct node)); temp_ptr
15
10
7
13
null
entry
head
Inserting a Node at the Front
void insert_start(NODEPTR *head, int x);
temp_ptr = (NODEPTR)
malloc(sizeof(struct node)); 13
temp_ptr
temp_ptr->data = 13;
10
7
13
null
entry
head
Inserting a Node at the Front
void insert_start(NODEPTR *head, int x);
temp_ptr = (NODEPTR)
malloc(sizeof(struct node)); temp_ptr
13
Place the data in the new node's
data_field.
15
Connect the new node to the front
of the list. 10
temp_ptr->next = *head;
7
13
null
entry
head
Inserting a Node at the Front
void insert_start(NODEPTR *head, int x);
temp_ptr = (NODEPTR)
malloc(sizeof(struct node)); temp_ptr
13
Make the old head pointer
point to the new node.
15
10
7
13
null
entry
head
Inserting a Node at the Front
void insert_start(NODEPTR *head, int x);
temp_ptr = (NODEPTR)
malloc(sizeof(struct node)); temp_ptr
13
*head = temp_ptr;
15
10
7
13
null
entry
head
Inserting a Node at the Front
void insert_start(NODEPTR *head, int x);
A0 A1 A2
head after_me
A0 A1 A2
head after_me
tmp_ptr
A0 A1 A2
head after_me x
tmp_ptr
temp_ptr->data
temp_ptr = x;
= (NODEPTR) malloc(sizeof(struct
node));
temp_ptr->next = after_me->next;
after_me->next = temp_ptr;
Inserting element in middle
A0 A1 A2
head after_me x
tmp_ptr
At any point, we can add a new item x by doing
this:
A0 A1 A2
head after_me x
tmp_ptr
At any point, we can add a new item x by doing this:
temp_ptr = (NODEPTR) malloc(sizeof(struct node));
temp_ptr->data = x;
temp_ptr->next = after_me->next;
after_me->next = temp_ptr;
void insert_after(NODEPTR after_me, int x)
{
NODEPTR temp_ptr = (NODEPTR) malloc(sizeof(struct node));
temp_ptr ->data = x;
temp_ptr ->next = after_me->next;
after_me->next = temp_ptr;
}
Adding a node to a sorted list
You are given a linked list in which the elements
are ordered. You want to add a node with a
new element, but you want to keep the list still
ordered.
To do so, you have to spot the place to insert the
new node by traversing the list. Here, there are
some cases to consider:
What if the list is empty?
What if I need to add a node before the beginning of the list?
What if I need to add a node somewhere inside the list?
Caution you cannot go back!
What if I need to add a node at the end of the list?
Adding a node to a sorted list
scanf("%d" ,&i);
insert_start(&head, i);
scanf("%d", &i);
while (i)
{
if(head->data>i) insert_start(&head,
i); else
{
for(p=head; p!=NULL; prev=p, p=p->next)
if(p->data > i) {insert_after(prev, i);
break;} if(p==NULL) insert_after(prev, i);
}
scanf("%d", &i);
}
}
Adding a node to a sorted list
(Program)
main()
{
NODEPTR head = NULL, p,
prev; int i;
scanf("%d", &i);
while (i)
{
for(prev = NULL, p= head; (p != NULL)&& > p->data);
(i prev = p, p = p->next);
if(prev==NULL)
insert_start(&head,
i);
else
insert_after(prev, i);
scanf("%d", &i);
}
}
A few questions on linked lists
Write a function to merge two ordered lists into a
third list.
void merge_sorted(NODEPTR head1,
NODEPTR head2, NODEPTR *head3)
void merge_sorted(NODEPTR head1, NODEPTR head2, NODEPTR *head3)
{
NODEPTR temp1=head1, temp2=head2, end1=NULL, end2;
*head3 = NULL;
while(temp1 && temp2){
if(temp1->data
< temp2->data)
{
if(*hea
d3==NUL
L)
{
i
n
s
e
r
t
_
s
t
a
r
t
(
&
e
n
else
{
insert_after(end1, temp2->data);
end1 = end1->next;
}
temp2 = temp2->next;
}
}
while(temp1)
{
insert_after(end1, temp1->data);
temp1 = temp1->next;
end1 = end1->next;
}
while(temp2)
{
insert_after(end1, temp2->data);
temp2 = temp2->next;
end1 = end1->next;
}
}
Interview Question
How can you find the value in mid of a linked
list in a single scan?
A few questions on linked lists
Write a function to split a linked list in middle into two. If
odd number of nodes are there then first list to have one
more node than second list.
void split_list(NODEPTR head, NODEPTR *head1)
A few questions on linked lists
Write a function to split a linked list in middle into two. If
odd number of nodes are there then first list to have one
more node than second list.
void split_list(NODEPTR head, NODEPTR *head1)
{
NODEPTR p1=head, p2=head;
while(p2)
{
if(p2)
p2=p2-
>next;
if(p2)
p2=p2-
>next;
if(p2)
p1=p1-
>next;
}
*head1 = p1->next;
A few questions on linked lists
Print a singly-linked list backwards with and without
recursion.
Write a C program to copy a linked list.
Reorder A->B->C->D->E as B->A->D->C->E in a singly
linked list
Write a function to return the Nth-to-Last element in a
singly linked list of unknown length. If N = 0, then your
function must return the last element.
Write a function to reverse a Linked-list
How would you find a loop in a singly-linked list?
Find the middle element in a singly linked list without
counting the number of elements.
A few questions on linked lists
Given an integer linked list of which both first half and
second half are sorted independently. Write a function to
merge the two parts to create one single sorted linked
list in place [do not use any extra space].
Sample test case:
Input 1 :1->2->3->4->5->1->2; Output: 1->1->2->2->3->4->5
Input 2: 1->5->7->9->11->2->4->6; Output 2: 1->2->4->5->6->7-
>9->11
Given two linked lists, return the intersection of the two
lists: i.e. return a list containing only the elements that
occur in both of the input lists.
A few questions on linked lists
Write a function that returns the intersection of the two
ordered lists: i.e. return a list containing only the
elements that occur in both of the input lists.
void intersect_list(NODEPTR head1, NODEPTR head2,
NODEPTR *head3)
void intersect_list(NODEPTR head1, NODEPTR head2, NODEPTR *head3)
{
NODEPTR temp1=head1, temp2=head2, end1=NULL, end2;
*head3 = NULL;
while(temp1 && temp2)
{
if(temp1-
>data ==
temp2->data)
{
if(*he
ad3==N
ULL)
{
i
n
s
e
r
t
_
s
t
a
r
t
(
&
A few questions on linked lists
Write a function that returns the intersection of the two
unordered lists: i.e. return a list containing only the
elements that occur in both of the input lists.
void intersect_list1(NODEPTR head1, NODEPTR head2, NODEPTR
*head3)
{
NODEPTR temp1=head1, temp2=head2, end1=NULL;
*head3 = NULL;
while(temp1)
{
if(sear
ch_list
(temp2,
temp1-
>data))
{
i
f
(
*
h
e
a
d
3
=
=
N
A few questions on linked lists
Write a function to reverse a Linked-list
Reversing linked list
NODEPTR reverse(NODEPTR head)
{
NODEPTR previous = NULL;
NODEPTR current = head;
NODEPTR forward;
pPre pCur
After:
pPre pCur
68
Deleting a Node from a Linked Li st – General
Case
Before: Code:
pPre -> next = -> next;
pCur
75 96 124
free(pCur);
pPre pCur
After:
Recycle
75 d 124
pPre pCur
Deleting a Node From Start of Linked List
struct Node{
int data;
struct Node
*next;
};
typedef
struct Node
*NODEPTR;
Circular Linked List
Operations
print(NODEPTR Rear)
//print the Circular Linked List
once
Rear
Insert Node
Insert into an empty list
NODEPTR p = new
Node;
p->data = 10;
Rear = p;
Rear->next = Rear; 10
New Rear
Insert to head of a Circular Linked List
p>next = Rear->next;
Rear->next = p;
10 20 40 55 70
New Head
Rear
Insert to end of a Circular Linked List
p->next = Rear->next;
Rear->next = p;
Rear = p;
10 20 40 55 70
Cur New
Rear
Insert to middle of a Circular Linked List
between Prev and Cur
p>next = Cur;
Prev->next = p;
10 20 55 70
40
Prev Cur Rear
New
Delete a node from a single-node Circular
Linked List
Rear = NULL;
delete Cur;
10
10 20 40 55 70
10 20 40 55 70
Prev Cur
Rear
Delete a middle node Cur from a
Circular Linked List
Prev->next = Cur->next;
Delete Cur;
10 20 40 55 70
single_to_circular(NODEPTR *list)
A few questions on linked lists
Write a function to convert singly linked list to
circular linked list.
push = insert_start(&list);
Pop = delete_start(&list);
Implementation of Queues
using linked lists
Enqueue = insert_end(&rear);
Dequeue = delete_start(&rear);
Polynomial Application
Many high level polynomials have many
terms with a 0 coefficient.
Would need to store them if using an
array.
Use a linked list to not take memory for items
with a 0 coefficient.
Polynomials
A( x ) am 1 xe am 2 x e
...a0 x e0
m 1 m 2
Representation
typedef struct poly_node *poly_pointer;
typedef struct poly_node
{ int coef;
int expon;
poly_pointer next;
};
poly_pointer a, b, c;
a 3x 1 4 2 x 8 1
a
3 14 2 8 1 0 null
b 8x 1 4 3x 1 0 1 0 x 6
b
8 14 -3 10 10 6 null
Adding Polynomials
3 14 2 8 1 0
a
8 14 -3 10 10 6
b
11 14 a->expon == b->expon
d
3 14 2 8 1 0
a
8 14 -3 10 10 6
b
11 14 -3 10 a->expon < b->expon
d
Adding Polynomials (cont’d)
3 14 2 8 1 0
a
8 14 -3 10 10 6
b
11 14 -3 10 2 8
d
a->expon > b->expon
About sparse arrays
A sparse array is simply an array most of whose entries
are zero (or null, or some other default value)
For example: Suppose you wanted a 2-dimensional
array of course grades, whose rows are students and
whose columns are courses
There are about 22,000 students
There are about 5000 courses
This array would have about 11,00,00,000 entries
Since most students take fewer than 5000 courses, there will
be
a lot of empty spaces in this array
This is a big array, even by modern standards
There are ways to represent sparse arrays efficiently
Sparse arrays as linked lists
We will start with sparse one-dimensional arrays, which
are simpler
We’ll do sparse two-dimensional arrays later
Here is an example of a sparse one-dimensional array:
0 1 2 3 4 5 6 7 8 9 10
0 0 0 110 17 0 0 23 14 0 0 0
ary
0 0 0 0
4 1 4 1 4 1 4 X
1
3 2 3 X
3 2 X 2
3 2
Round 3 Round 2
X X X
0 0
X
0 X 0
X
4 1 4 1 X4 1 4
1 X
3 2
X 3 2 X 3 2 X 3 2 X
while(list->next!=list)
{
for(i=0; i<count-1; i++)
list = list->next;
delete_after(list);
}
Array of linked lists
An array of linked list combines a static structure (an
array) and a dynamic structure (linked lists) to form
a useful data structure. This type of a structure is
appropriate for applications, where say for example,
number of categories is known in advance, but how
many nodes in each category is not known. For
example, we can use an array (of size 26) of linked
lists, where each list contains words starting with a
specific letter in the alphabet.
Variations of Linked Lists
Doubly linked lists
Each node points to not only successor but the
predecessor
There are two NULL: at the first and last nodes
in the list
Advantage: given a node, it is easy to visit its
predecessor. Convenient to traverse lists
backwA
ards B C
Head
Advantages of Doubly Linked
Lists
Solves the problem of traversing backwards in
an ordinary linked list.(Implementing big
numbers)
A link to the previous item as well as to the
next item is maintained.
The only disadvantage is that every time an
item is inserted or deleted, two links have to be
changed instead of one.
Doubly Linked List Definition
struct Node{
int data;
struct Node
*next,
*prev;
};
typedef
struct Node
*NODEPTR;
Inserting into a Doubly Linked List
a c
head tail
current
a c
head b tail
current
a c
head b tail
current
a c
head b tail
current
a c
head b tail
current
a c
head b tail
current
a c
head b tail
current
a c
head b
current
oldNode=current;
oldNode->prev->next = oldNode->next;
oldNode->next->prev = oldNode->prev;
current = oldNode->prev;
free(oldNode);
Deleting an element from a double
linked list
a c
head b
current
oldNode
oldNode=current;
oldNode->prev->next = oldNode->next;
oldNode->next->prev = oldNode->prev;
current = oldNode->prev;
free(oldNode);
Deleting an element from a double
linked list
a c
head b
current
oldNode
oldNode=current;
oldNode->prev->next = oldNode->next;
oldNode->next->prev = oldNode->prev;
current = oldNode->prev;
free(oldNode);
Deleting an element from a double
linked list
a c
head b
current
oldNode
oldNode=current;
oldNode->prev->next = oldNode->next;
oldNode->next->prev = oldNode->prev;
current = oldNode->prev;
free(oldNode);
Deleting an element from a double
linked list
a c
head b
current
oldNode
oldNode=current;
oldNode->prev->next = oldNode->next;
oldNode->next->prev = oldNode->prev;
current = oldNode->prev;
free(oldNode);
Deleting an element from a double
linked list
a c
head
current
oldNode=current;
oldNode->prev->next = oldNode->next;
oldNode->next->prev = oldNode->prev;
current = oldNode->prev;
free(oldNode);
Doubly Linked List Application
int a = 3, b = 5;
NULL
Double-Ended Queues
Front Rear
Input :
arr[] =
{8, 5,
10, 7,
9, 4,
15, 12,