0% found this document useful (0 votes)
31 views92 pages

Unit 3 - Linked Lists

The document discusses linked lists including definitions, operations, and implementations. Linked lists allow dynamic memory allocation and can store infinite data. Common operations on linked lists include insertion, deletion, searching, and traversal.

Uploaded by

anmolbansal1969
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
31 views92 pages

Unit 3 - Linked Lists

The document discusses linked lists including definitions, operations, and implementations. Linked lists allow dynamic memory allocation and can store infinite data. Common operations on linked lists include insertion, deletion, searching, and traversal.

Uploaded by

anmolbansal1969
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 92

CS1301: DATA STRUCTURES

UNIT-3: LINKED LISTS

Singly linked lists, linked stacks and queues, doubly linked lists and
dynamic storage management, circular linked list, Applications of
Stacks, Queues and Linked lists.
Abstract Data Type (ADT)
• An Abstract Data Type is:
• Set of values
• Set of operations which can be uniformly applied to these values
• Set of Axioms
What is List?
• Countable number of ordered values
• Each occurrence of a value is a distinct item
• Implemented differently in different programming
languages
• Linked list is an implementation of list
List Abstract Data Type
• List ADT has:
• Values based on what type of data list stores
• Main operations:
• new() : creates a new list
• prepend(L, key): add element key to front of list L
• append(L, key): add element key to end of list L
• remove(L, key): removes element key from list L
• search(L, key): find location of element key in L
• head(L): returns the first object in L
• isEmpty(L): checks whether list L is empty or not
• Axioms:
• Based on implementation
Drawbacks with Array
• Is array also a list?
Drawbacks with Array
• Is array also a list?
• Yes, certainly.

• Problem: An array has a limited number of elements


• Routines inserting a new value have to check that there is room

• Solution: Multiple solutions exist


• Increase the size of array with some constant each time array is full
• Double the size of array each time array is full
• Use Linked List data structure
Linked List(LL)
• Nodes stores the data/values
• Sequence of nodes; each node points to next node in list
• Add node dynamically when required
• Can store infinite data until memory of system is
exhausted
• The address of first node is stored in separate location
called as head or first
• Last node contains a null link
head

a b c d
Dynamic Memory Allocation(1)
• Allocate memory to elements one at a time as needed,
have each element keep track of the next element
• Result is referred to as linked list of elements, track next
element with a pointer

Array of Elements in Memory


Jane Bob Anne

Linked List
Jane Anne Bob
More Terminology
• A node’s successor is the next node in the sequence
• The last node has no successor
• A node’s predecessor is the previous node in the
sequence
• The first node has no predecessor
• A list’s length is the number of elements in it
• A list may be empty (contain no elements)
• Linked list in context of C are sometime referred as List
• Until not specified, linked list refers to Singly-Linked List
LL with 3 nodes (dynamic)
void main() { /*assume data is int */
LinekedList ListStart = NULL; /*safe to give a legal
value*/
Pictorially In Memory
ListStart ListStart
0
100

ListStart = (Eptr)malloc(sizeof(Estruct));
/* ListStart points to memory allocated at location 108 */
ListStart ListStart Data Next
? ? 108 ? ?
Data Next 100 108
}
Declaration of LL
• Because the node of linked list contains 2 components it
should be declared as class or struct
struct nodeType
{
int info;
nodeType *link;
};
Properties of LL

VALUE EXPLANATION
head 2000
Because head is 2000 and the info of
head -> info 17
the node at location 2000 is 17
head -> link 2800
Because head -> link is 2800 and the
head -> link -> info 92
info of the node at location 2800 is 92
• Suppose that current is a pointer which has type as
pointer head. Then, the statement : current=head copies
the value of head into current

value

current 2000
current -> info 17
current -> link 2800
current -> link -> info 92
Insertion in Linked List
• Involves two step:
• Finding the correct position
• Doing the work to add the node

• Three possible positions:


• Front
• End
• Somewhere in the middle
Insertion in Linked List (Front)
• Finding the correct location
• No work required as already known
• Irrespective of list is empty or not, header will always point to
correct location
Insertion in Linked List (Front)
• Add new node to list
• Save element in data field of new node

ListStart New Node


5 9 6 X 3
Insertion in Linked List (Front)
• Add new node to list
• Save element in data field of new node
• Make new node’s next pointer to point start of existing list

ListStart New Node


5 9 6 X 3
Insertion in Linked List (Front)
• Add new node to list
• Save element in data field of new node
• Make new node’s next pointer to point start of existing list

ListStart New Node


5 9 6 X 3

• Make start of list point to new node in main


Insertion in Linked List (End)
• Find last of list

ListStart
5 9 6 X

Last
Insertion in Linked List (End)
• Find last of list
• Add new node to list
• Save element in data field of new node
• Save NULL in next field of new node
• Make last node’s next pointer to point new node

ListStart New Node


5 9 6 3 X

Last
Insertion in Linked List (Between)
• Find the node you want to insert after

ListStart
5 9 6 X

After
Insertion in Linked List (Between)
• Find the node you want to insert after
• Add new node to list
• Save element in data field of new node
• Save address of following node in next field of new node
• Save address of new node in “after” node

ListStart New Node


5 9 6 X 3

After
Item insertion to LL
• Consider linked list before insertion

• variable declaration
nodeType *head, *p, *q, *newnode;
• Suppose that p points to the node with info 65, and a new
node with info 50 is to be created and inserted after p
newNode = new nodeType;//create newNode
newNode -> info = 50;//store 50 in the new node
newNode -> link = p -> link;
p -> link = newNode;
p -> link = newNode;
newNode -> link = p -> link;

• newNode points back to itself and the remainder of the list is lost
• by using to pointers insertion code can be simplified
• suppose q points to the node with info 34
newNode -> link = q;
p -> link = newNode;
Above statements insert newNode between p and q
Print a Linked List
• Use a “walker” to examine list from start to end

void printList() {
node *temp = start; /*temp is walker variable*/
while (temp != NULL) {
cout<<temp->data;
temp = temp->next;
}
}

• Why we need “walker” when we already have “start”?


• Try to avoid start, could be required later in the function
Operations on LL

Print the LL Destroy the LL


current = first; while (first != NULL)
//set current so that it points to //while there are nodes in the list
{
//the first node temp = first;
while (current != NULL) //set temp to the current node
//while more data to print first = first->link;
{ //advance first to the next node
cout << current->info << " "; delete temp;
//deallocate the memory occupied by temp
current = current->link; }
} last = NULL;
}//end print //initialize last to NULL; first has already
//been set to NULL by the while loop
Search in Linked List
• Compare every element in list; return pointer to node if
found else return NULL

• Can we perform binary search given elements are sorted?


• Yes, but the performance will be similar to linear search
Search in Linked List
• Search 9
ListStart
5 9 6 X

findP

• Search 4
ListStart
5 9 6 X

findP
Deletion in Linked List
• Involves two steps:
• Find the node to be deleted
• Change its predecessor to point its successor

• Deletion from front


• Change header to point to second node

• Deletion from elsewhere


• Change predecessor to point successor
Deletion in Linked List (Front)
• Change the header to point to second node.
• Set first node free

• Set start to returned pointer after deletion


Deletion in Linked List (Except Front)
• Change the predecessor to point to successor
• Set deleted node free
Deletion
• We have LL shown below

• How to delete node with info 34


• p->link = p->link->link;

• the node with info 34 is removed from the list. However, the
memory is still occupied by this node, and this memory is
inaccessible; that
• is, this node is dangling. To deallocate the memory, we need a
pointer to this node.
Deallocate deleted node
• The following statements delete the node from the list and deallocate the memory
occupied by this node.
q = p->link;
p->link = q->link;
delete q;
Building LL
• Suppose that the nodes are in the usual info-link form,
and info is of type int.
• Assume to process the following data: 2, 15, 8, 24, 34
• Will be needed:
• three pointers to build the list: one to point to the first node in the
list, which cannot be moved;
• one to point to the last node in the list;
• and one to create the new node.
nodeType *first, *last, *newNode;
int num;
Building LL…

nodeType *first, *last, *newNode; newNode->link = NULL;


int num; /*initialize the link field of newNode to NULL*/
if (first == NULL)
/*Suppose that first points to the first node in the //if first is NULL, the list is empty;
list. Initially, the list is empty, so both first and last //make first and last point to newNode
are NULL*/ {
first = NULL; first = newNode;
last = NULL; last = newNode;
}
cin >> num; //read a number in num else //list is not empty
{
newNode=new nodeType;
last->link = newNode;
/*allocate memory of type nodeType //insert newNode at the end of the list
and store the address of the last = newNode;
allocated memory in newNode*/ //set last so that it points to the
newNode->info = num; //actual last node in the list
/*copy the value of num into the }
info field of newNode*/
Building LL…
nodeType *first, *last, *newNode;
int num; 4 newNode->link = NULL;
/*initialize the link field of newNode to NULL*/
/*Suppose that first points to the first node in the 5 if (first == NULL)
list. Initially, the list is empty, so both first and last //if first is NULL, the list is empty;
are NULL*/ //make first and last point to newNode
first = NULL; {
last = NULL; 5a first = newNode;
5b last = newNode;
1 cin >> num; //read a number in num }
2 newNode=new nodeType;
6 else //list is not empty
/*allocate memory of type nodeType {
and store the address of the 6a last->link = newNode;
allocated memory in newNode*/ //insert newNode at the end of the list
3 newNode->info = num; 6b last = newNode;
/*copy the value of num into the //set last so that it points to the
//actual last node in the list
info field of newNode*/ }
• We now repeat statements 1 through 6b. After
• After statement 1 executes, num is 2. Statement
2 creates a node and stores the address of that statement 1 executes, num is 15. Statement 2
node in newNode. Statement 3 stores 2 in the creates a node and stores the address of this
info field of newNode, and statement 4 stores node in newNode. Statement 3 stores 15 in the
NULL in the link field of newNode info field of newNode, and statement 4 stores
NULL in the link field of newNode

• Because first is NULL, we execute statements


5a and 5b.

• Because first is not NULL, we execute


statements 6a and 6b.
Building LL Backward
• For the previously given data 2, 15, 8, 24, 34 the linked
list is as shown below as
Backward LL

Forward LL
Pseudo code of building Backward LL
• 1. Initialize first to NULL.
• 2. For each item in the list,
• Create the new node, newNode.
• Store the item in newNode.
• Insert newNode before first.
• Update the value of the pointer first.
C++ function to build Backward LL

nodeType* buildListBackward()
{
nodeType *first, *newNode;
int num;
cout<<"Enter a list of integers ending with -1."<<endl;
cin >> num;
first = NULL;
while (num != -1)
{
newNode = new nodeType; //create a node
newNode->info = num; //store the data in newNode
newNode->link = first; //put newNode at the beginning of the list
first = newNode; //update the head (first) pointer of the list
cin >> num; //read the next number
}
return first;
} //end buildListBackward
Linked List Variation: Dummy Head Node
Using "dummy" first (head) node:
Empty linked list
ListStart
?

Sample list:
ListStart
? 5 9 6

• Why?
• No special case for inserting/deleting at beginning
• Header (ListStart) does not change after it is initialized
• Disadvantage
• cost of one extra element
Linked List Variation: Sorted List
• Idea: Keep the items on the list in a sorted order
• sort based on data value in each node
• Advantages:
• already sorted
• operations such as delete, find, etc. need not search to the end of the
list if the item is not in list
• Disadvantages
• insert must search for the right place to add element (slower than simply
adding at beginning)
Doubly Linked List
• Each node contain data, link to its successor and a link to
its predecessor
• Two headers pointing to first and last node respectively or
pointing to NULL (if list is empty)

myDL
First L Last
a b c
Doubly Linked List
• Advantages:
• Can be traversed in either direction (may be essential for some
programs)
• Some operations, such as deletion and inserting before a node,
become easier

• Disadvantages:
• Requires more space
• List manipulations are slower (because more links must be
changed)
• Greater chance of having bugs (because more links must be
manipulated)
Insertion in DLL
• Change forward and backward pointers accordingly
• Insert element “d” after “a”

myDL
First L Last
a b c

New Node

d
Insertion in DLL
• Change forward and backward pointers accordingly
• Eg. Insert element “d” after “a”

myDL
First L Last
a b c

New Node

d
Deletion in DLL
• Change forward and backward pointers accordingly
• Insertion and Deletion in beginning and last are special
cases and should be handled differently
• Eg. Delete “b” from previous list

myDL
First L Last
a X b X c
X X
Deletion in DLL
• Change forward and backward pointers accordingly
• Insertion and Deletion in beginning and last are special
cases and should be handled differently
• Eg. Delete “b” from previous list

myDL
First L Last
a c
Stack using LL
• Since all the action happens at the top of a stack, a
singly-linked list (SLL) is a fine way to implement it
• The header of the list points to the top of the stack

myStack:

44 97 23 17

• Pushing is inserting an element at the front of the list


• Popping is removing an element from the front of the list
Stack using LL
• Initialize stack; set header to NULL

myStack:

NULL
Stack using LL
• Initialize stack; set header to NULL
• push(44)

myStack:

44 NULL
Stack using LL
• Initialize stack; set header to NULL
• push(44)
• push(97)

myStack:

97 44 NULL
Stack using LL
• Initialize stack; set header to NULL
• push(44)
• push(97)
• push(23)

myStack:

23 97 44 NULL
Stack using LL
• Initialize stack; set header to NULL
• push(44)
• push(97)
• push(23)
• pop()

myStack:

97 44 NULL
Stack using LL
• Initialize stack; set header to NULL
• push(44)
• push(97)
• push(23)
• pop()
• push(17)

myStack:

17 97 44 NULL
Stack using LL
• Initialize stack; set header to NULL
• push(44)
• push(97)
• push(23)
• pop()
• push(17)
• pop()

myStack:

97 44 NULL
Stack using LL details
• With a linked-list representation, overflow will not happen
(unless you exhaust memory, which is another kind of
problem)
• Underflow can happen, and should be handled the same
way as for an array implementation
• When a node is popped from a list, and the node
references an object, the reference (the pointer in the
node) does not need to be set to NULL
• Unlike an array implementation, it really is removed--you can no
longer get to it from the linked list
Queue using LL
• In a queue, insertions occur at one end, deletions at the
other end

• Operations at the front of a singly-linked list (SLL) are


O(1), but at the other end they are O(n)
• Because you have to find the last element each time

• In order to implement both insertions and deletions in


O(1) time in a SLL
• You always need a pointer to the first thing in the list
• You can keep an additional pointer to the last thing in the list
Queue using LL
• In an SLL you can easily find the successor of a node, but
not its predecessor
• Remember, pointers (references) are one-way

• If you know where the last node in a list is, it’s hard to
remove that node, but it’s easy to add a node after it

• Hence,
• Use the first element in an SLL as the front of the queue
• Use the last element in an SLL as the rear of the queue
• Keep pointers to both the front and the rear of the SLL
Enqueueing a Node
• Create a new node

last
first New Node
44 97 23 X 17 X
Enqueueing a Node
• Create a new node
• Change pointer of last node to point new node

last
first New Node
44 97 23 17 X
Enqueueing a Node
• Create a new node
• Change pointer of last node to point new node
• Change last pointer to point to new node

last
first New Node
44 97 23 17 X
Dequeueing a Node
• Change “first” to point to second node

last
first

44 97 23 17 X
Dequeueing a Node
• Change “first” to point to second node
• Optionally, set deleted node free

last
first

44 97 23 17 X
Queue using LL details
• With a linked-list representation, overflow will not happen
(unless you exhaust memory, which is another kind of
problem)
• Underflow can happen, and should be handled the same
way as for an array implementation
• When a node is dequeued from a list, and the node
references an object, the reference (the pointer in the
node) does not need to be set to NULL
• Unlike an array implementation, it really is removed--you can no
longer get to it from the linked list
Polynomial Representation in LL
• Represent polynomial expression using Linked List
• A node in linked list stores coefficient and exponent of
each term in polynomial expression

• Eg.

5 12 2 9 -1 3 NULL
Polynomial Addition
• Consider Two polynomial expressions

• Addition of above two expression is


Algo for Polynomial Addition
• Represent two polynomials in two linked lists L1 and L2
• Create a third empty linked list L3
• Compare the items in L1 with the items in L2
• If there is no item having the same exponent, append these items
to the third list.
• If there are two items with the same exponent exp and coefficient
coff1 and coff2, append an item with exponent exp and coefficient
coff1+coff2 to L3
Pseudocode for Polynomial Addition
Polyadd(list L1, list L2, list L3)
while (L1 != NULL and L2 != NULL) //While both list are not empty
if (L1->pow > L2->pow) //if power of L1 is greater than L2, append L1 to L3
L3->coff = L1->coff; L3->pow = L1->pow;
L1 = L1->next;
if (L1->pow < L2->pow) //if power of L2 is greater than L1, append L1 to L3
L3->coff = L2->coff; L3->pow = L2->pow;
L2 = L2->next;
if (L1->pow = L2->pow) //if power of L1 & L2 is equal, add coefficient
L3->coff = L1->coff + L2->coff; L3->pow = L1->pow;
L1 = L1->next; L2= L2->next;

while (L1 != NULL) //if L2 has reached end, append remaining terms of L1
L3->coff = L1->coff; L3->pow = L1->pow; L1 = L1->next;

while (L2 != NULL) //if L1 has reached end, append remaining terms of L2
L3->coff = L2->coff; L3->pow = L2->pow; L1 = L2->next;
Example Polynomial Addition
L1
5 12 2 9 -1 3 NULL

L2
5 11 -4 9 2 3 -1 1 NULL

L3
NULL
Example Polynomial Addition
L1
5 12 2 9 -1 3 NULL

L2
5 11 -4 9 2 3 -1 1 NULL

L3
5 12 NULL
Example Polynomial Addition
L1
5 12 2 9 -1 3 NULL

L2
5 11 -4 9 2 3 -1 1 NULL

L3
5 12 5 11 NULL
Example Polynomial Addition
L1
5 12 2 9 -1 3 NULL

L2
5 11 -4 9 2 3 -1 1 NULL

L3
5 12 5 11 -2 9 NULL
Example Polynomial Addition
L1
5 12 2 9 -1 3 NULL

L2
5 11 -4 9 2 3 -1 1 NULL

L3
5 12 5 11 -2 9 1 3 NULL
Example Polynomial Addition
L1
5 12 2 9 -1 3 NULL

L2
5 11 -4 9 2 3 -1 1 NULL

L3
5 12 5 11 -2 9 1 3

-1 1 NULL
Algo for Polynomial Subtraction
• Represent two polynomials in two linked lists L1 and L2
• Create a third linked list L3, with coefficient of L2 negated
• Perform the algo for addition of list L1 and L3
Sparse Matrices
• Sparse: Many elements are zero
• Dense: Many elements are non-zero

• A matrix is a collection of relation between two entities of


same of different groups
• Eg. Airline Flight Matrix between cities
city
0 0 3 0 4
0 0 5 7 0
0 0 0 0 0
0 2 6 0 0
4 1 0 3 0
Structured Sparse Matrices
• Has a proper structure of zero and non-zero elements
• Eg. Diagonal, tridiagonal, lower triangular

Diagonal Tridiagonal
a1 0 0 0 a1 b1 0 0
0 a2 0 0 c1 a2 b2 0
0 0 a3 0 0 c2 a3 b3
0 0 0 a4 0 0 c3 a4

• May be mapped into a 1D array so that a mapping


function can be used to locate an element.
Unstructured Sparse Matrices
• Airline flight matrix.
 airports are numbered 1 through n
 flight(i, j) = list of nonstop flights from airport i to airport j
 n = 1000 (say)
 n x n array of list references (assuming 4Bytes for one reference)
=> 4 million bytes
 total number of flights = 20,000 (say)
 need at most 20,000 list references => at most 80,000 bytes
Representation of
Unstructured Sparse Matrix(USM)
• Single linear list in row-major order.
• scan the nonzero elements of the sparse matrix in row-major
order
• each nonzero element is represented by a triple (row, column,
value)
• the list of triples may be an array list or a linked list (chain)

Example: 00304
00570
00000
02600
Array Representation of USM
Example: 00304
00570
00000
02600

Element 0 1 2 3 4 5
Row 1 1 2 2 4 4
Column 3 5 3 4 2 3
Value 3 4 5 7 2 6
LL Representation of USM
Example:0 0 3 0 4 Row 1 1 2 2 4 4
00570
LL = Column 3 5 3 4 2 3
00000
02600 Value 3 4 5 7 2 6

1 3 3 1 5 4 2 3 5 2 4 7

4 2 2 4 3 6 NULL
Array of LL Representation of USM
Example:0 0 3 0 4
00570
00000
02600

3 3 5 4 NULL

3 5 4 7 NULL

NULL

2 2 3 6 NULL

Row[]
Memory Requirements (Approx.)
• 500 x 500 matrix with 1994 nonzero elements

• 2D Array 500*500*4 = 106 Bytes


• Single Array List 3*1994*4 = 23,928 Bytes
• Array of LL 23,928 + 500*4 = 25,928 Bytes
Circular Linked List(CLL)
• Extension of Linear/Singly Linked List where last node
points to beginning of list
• Can be implemented in two ways
1. Header Pointer: An extra pointer pointing to start of list
2. Header Node: A special node in the beginning of list
• Header node stores some special value, like a negative number if
list contains only positive numbers
• We can use flag to specify header and non-header nodes
• CLL does not have any NULL pointer except for empty list
Circular Linked List (CLL)
• Empty CLL
ListStart
NULL

• Non-Empty CLL
ListStart
5 9 6

• Header Node

-1 5 9 6
Traversing in CLL
void print(Eptr ListStart) {
Eptr temp = ListStart;
print (temp->data);
while (temp->next != ListStart) {
print (temp->data);
temp = temp->next;
}
}
Advantages of CLL
• Some operations can be made efficient in CLL compare to
Singly LL like search multiple entries subsequently
• CLL are useful when element of lists are to be visited in
“Loop” fashion
Insertion in CLL
Insert in Empty CLL
• Change Header to point new node and new node to point
itself

Insert at Start
• Create new node; point to existing first node
• Change last node to point to new node; change header

Insert in middle
• Change new node to point successor of the node after
which node is inserted
• Change predecessor to point to new node
Deletion in CLL
Delete Last node
• If node points to itself, set header to point to null

Delete from Front


• Change last node to point second node in list
• Update header to point to second node

Delete from middle


• Change predecessor to point successor

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy