08 Lists
08 Lists
1. Linear Lists
2. List Operations
3. Arrays versus Linked Lists
4. Nodes
5. Sentinel (dummy) nodes
6. Types of Linked Lists
• Singly-Linked Lists
• Doubly-Linked Lists // CIS 22C
• Multi-Linked Lists // CIS 22C
7. Linked List Applications
1
A linear list is a sequence of n >= 0 elements:
2
A linear list is a sequence of n >= 0 elements:
3
Non-linear data structures:
4
Linear List Operations:
5
A linear list is a list in which each element has a
unique successor and a unique predecessor, except
the last node with no successor, and the first node
with no predecessor.
6
list A linked list of integers
20 70 10 50
data next
NULL
70
7
Operations
Arrays vs Linked Lists
1. Direct Access: list[i] 1. “Walk” to the node
3. Insert: 3. Insert:
• shift elements to make room • create a new node
• update pointers
4. Delete: 4. Delete:
• shift elements to eliminate gap • update pointers
• release memory
8
Operations
Arrays vs Linked Lists
1. Direct Access: list[i] // + 1. “Walk” to the node // -
9
Memory Usage
Arrays vs Linked Lists
1. Needs memory for data 1. Needs memory for both
data and pointers
10
Node
data next
70
In the following examples we assume that the linked list node is a struct.
11
A linked list of City nodes.
city
state year_incorporated name next
city
state year_incorporated name next Node
City
UML – diagram
- A LinkedList has Nodes.
- Each Node has a City object.
- is used to show “aggregation”
13
A linked list of City nodes.
list
14
What is one advantage and one disadvantage of using B instead of A?
( A ) ( B )
city
state year_incorporated name next
15
UML Diagram for the Singly Linked List Class
SList
- head
- length
+ SList()
+ insertNode()
+ deleteNode()
+ searchList()
+ traverse()
+ getLength()
+ isEmpty()
+ ~SList()
The head of the list could be the only data member of a linked list class .
The length of the list is convenient to have: when needed, we can get it
without traversing the entire list.
16
Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
NULL
17
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
NULL
18
list Data Structure Diagram of a Singly Linked List.
head
0
// constructor
SList::SList()
{
head = NULL;
length = 0;
} SList
- head
- length
+ SList()
+ insertNode()
+ deleteNode()
+ searchList()
+ traverse()
+ getLength()
+ isEmpty()
+ ~SList()
19
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
// getter NULL
int SList::getLength()
{ SList
return length; - head
} - length
+ SList()
+ insertNode()
+ deleteNode()
+ searchList()
+ traverse()
+ getLength()
+ isEmpty()
+ ~SList()
The getLength() member function of the SList class returns the number of
nodes in the list.
20
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
NULL
int SList::isEmpty()
{ SList
return (length == 0); - head
} - length
+ SList()
The isEmpty() member function of the SList class returns true if the + insertNode()
+ deleteNode()
list is empty, false otherwise. + searchList()
+ traverse()
We could always use getLength() instead of isEmpty(). + getLength()
Why do we need this function? + isEmpty()
+ ~SList()
Convenience: it enhances the readability of the code.
40 90 50 30 80
NULL
SList
- head
- length
+ SList()
Traversing a linked list: visit every node once.
+ insertNode()
There are many algorithms based on traversal: + deleteNode()
- Printing a list + searchList()
- Calculating a sum/average + traverse()
+ getLength()
- Finding smallest/largest + isEmpty()
- Any/all type of inquires such as: + ~SList()
- Are all elements positive?
- Is there at least one odd value?
- Updating data in each node
22
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
NULL
SList
- head
- length
+ SList()
+ insertNode()
+ deleteNode()
+ searchList()
+ traverse()
+ getLength()
+ isEmpty()
+ ~SList()
Traversing an array can be done using either an index or a pointer.
To traverse a linked list we have only one option: use a pointer!
23
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
NULL
40 90 50 30 80
NULL
Since we have the length of the list, we can easily write a for loop to traverse it. 25
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
NULL
40 90 50 30 80
NULL
How do we make pCurr point to the next node? (assign pCurr->next to pCurr) 27
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
NULL
28
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
NULL
29
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
NULL
40 90 50 30 80
NULL
31
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
NULL
32
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
NULL
Output: 40
33
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
NULL
Output: 40
34
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
NULL
Output: 40
35
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
NULL
Output: 40 90
36
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
NULL
Output: 40 90
37
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
NULL
40 90 50 30 80
NULL
Output: 40 90 50 30 80
39
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
pCurr NULL
SList
- head
- length
+ SList()
Let’s say we want to delete the node that contains 50 and that we
+ insertNode()
already have a pointer, pCur, pointing to this node. To remove 50 + deleteNode()
from the list, we have to make “node 90” to point to “node 30”, and + searchList()
this cannot be done with only one pointer! + traverse()
+ getLength()
+ isEmpty()
+ ~SList()
40
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
SList
- head
- length
+ SList()
Let’s say we want to delete the node that contains 50 and that we
+ insertNode()
already have a pointer, pCur, pointing to this node. To remove 50 + deleteNode()
from the list, we have to make “node 90” to point to “node 30”, and + searchList()
this cannot be done with only one pointer! + traverse()
+ getLength()
+ isEmpty()
Let’s add another pointer, pPre, to point to the current’s node + ~SList()
predecessor.
41
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
SList
pPre->next = pCur->next;
- head
- length
+ SList()
Let’s say we want to delete the node that contains 50 and that we
+ insertNode()
already have a pointer, pCur, pointing to this node. To remove 50 + deleteNode()
from the list, we have to make “node 90” to point to “node 30”, and + searchList()
this cannot be done with only one pointer! + traverse()
+ getLength()
+ isEmpty()
Let’s add another pointer, pPre, to point to the current’s node + ~SList()
predecessor.
40 90 30 80
SList
pPre->next = pCur->next;
delete pCur; - head
- length
+ SList()
Let’s say we want to delete the node that contains 50 and that we
+ insertNode()
already have a pointer, pCur, pointing to this node. To remove 50 + deleteNode()
from the list, we have to make “node 90” to point to “node 30”, and + searchList()
this cannot be done with only one pointer! + traverse()
+ getLength()
+ isEmpty()
Let’s add another pointer, pPre, to point to the current’s node + ~SList()
predecessor.
40 90 50 30 80
SList
pPre->next = pCur->next;
- head
delete pCur; - length
+ SList()
Does this code work if we remove the last node in the list? + insertNode()
+ deleteNode()
+ searchList()
+ traverse()
+ getLength()
+ isEmpty()
+ ~SList()
44
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
SList
pPre->next = pCur->next; // NULL
// pPre->next = NULL; - head
delete pCur; - length
+ SList()
Does this code work if we remove the last node in the list? + insertNode()
+ deleteNode()
Since pCurr is the last node in the list, after removing it, pPre will + searchList()
+ traverse()
be the last node in the list:
+ getLength()
+ isEmpty()
+ ~SList()
45
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30
SList
pPre->next = pCur->next; // NULL
// pPre->next = NULL; - head
delete pCur; - length
+ SList()
Does this code work if we remove the last node in the list? + insertNode()
+ deleteNode()
Since pCurr is the last node in the list, after removing it, pPre will + searchList()
+ traverse()
be the last node in the list: it works!
+ getLength()
+ isEmpty()
+ ~SList()
46
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
SList
pPre->next = pCur->next;
delete pCur; - head
- length
+ SList()
Does this code work if we remove the first node in the list? + insertNode()
+ deleteNode()
+ searchList()
+ traverse()
+ getLength()
+ isEmpty()
+ ~SList()
47
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
SList
pPre->next = pCur->next;
delete pCur; - head
- length
+ SList()
Does this code work if we remove the first node in the list? + insertNode()
+ deleteNode()
The first node does not have a predecessor (pPre is NULL) + searchList()
+ traverse()
Dereferencing a NULL pointer is not possible: it does NOT work!
+ getLength()
+ isEmpty()
+ ~SList()
48
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
SList
head = pCur->next;
delete pCur; - head
- length
+ SList()
Does this code work if we remove the first node in the list? + insertNode()
+ deleteNode()
The first node does not have a predecessor (pPre is NULL) + searchList()
+ traverse()
Dereferencing a NULL pointer is not possible: it does not work!
+ getLength()
+ isEmpty()
When we remove the first node in the list, the head of the list must + ~SList()
be updated to point to the second node.
49
list Data Structure Diagram of a Singly Linked List.
head
5
90 50 30 80
SList
head = pCur->next;
delete pCur; - head
- length
+ SList()
Does this code work if we remove the first node in the list? + insertNode()
+ deleteNode()
The first node does not have a predecessor (pPre is NULL) + searchList()
+ traverse()
Dereferencing a NULL pointer is not possible: it does not work!
+ getLength()
+ isEmpty()
When we remove the first node in the list, the head of the list must + ~SList()
be updated to point to the second node.
50
list Data Structure Diagram of a Singly Linked List.
head
5
40 90 50 30 80
SList
- head
- length
+ SList()
To summarize, when we remove a node from a list we have to
+ insertNode()
consider two cases: + deleteNode()
1. removing the first node (must update head) + searchList()
2. removing any other node (head does not change) + traverse()
+ getLength()
+ isEmpty()
We can make delete simpler if we add a predecessor for the first + ~SList()
node, an “empty” data node: it does not carry any data, and it is
known as a “dummy node” or a “sentinel node”.
51
head
5
/////// 40 90 50 30 80
NULL
A sentinel node, also known as dummy or header node, is an extra node added
before the first data record.
This convention simplifies and accelerates some list-manipulation algorithms,
by making sure that all links can be safely dereferenced and that every list
(even one that contains no data elements) always has a "first" node.
52
head
5
/////// 40 90 50 30 80
NULL
A sentinel node, also known as dummy or header node, is an extra node added
before the first data record.
This convention simplifies and accelerates some list-manipulation algorithms,
by making sure that all links can be safely dereferenced and that every list
(even one that contains no data elements) always has a "first" node.
Should we change the counter to 6, to include the sentinel node? No, the
counter represents the number of data items we store in the list.
When/where should we create the sentinel node? This is the constructor’s job!
53
head
5
/////// 10 20 50 60 80
NULL
/////// 10 20 50 60 80
55
head
5
/////// 10 20 50 60 80
pPre pCurr
NULL
SList
- head
- length
+ SList()
When we insert a new element into a sorted list, the list + insertNode()
will be sorted after the insertion of the new element. + deleteNode()
+ searchList()
For instance, if we insert 25, + traverse()
- first we find the insertion point (between 20 and 50), + getLength()
+ isEmpty()
+ ~SList()
56
head pNew
5
25
/////// 10 20 50 60 80
pPre pCurr
NULL
SList
- head
- length
+ SList()
When we insert a new element into a sorted list, the list + insertNode()
will be sorted after the insertion of the new element. + deleteNode()
+ searchList()
For instance, if we insert 25, + traverse()
- first we find the insertion point between 20 and 50, + getLength()
- then we create a new node, + isEmpty()
+ ~SList()
- copy 25 into the new node,
57
head pNew
6
25
/////// 10 20 50 60 80
pPre pCurr
NULL
SList
pPre->next = pNew;
pNew->next = pCurr; - head
length++; - length
+ SList()
When we insert a new element into a sorted list, the list + insertNode()
will be sorted after the insertion of the new element. + deleteNode()
+ searchList()
For instance, if we insert 25, + traverse()
- first we find the insertion point between 20 and 50, + getLength()
- then we create a new node, + isEmpty()
+ ~SList()
- copy 25 into the new node,
- update the links and
- update the counter.
58
head pNew
6
25
/////// 10 20 50 60 80
pPre pCurr
NULL
void SList::insertNode(int target)
{
SList
ListNode *pCur; // To traverse the list - head
ListNode *pPre; // To point to the previous node
- length
ListNode *pNew; // To point to the new node
+ SList()
pPre = head; // Initialize pointers
pCur = head->next;
+ insertNode()
// Find location: Skip all nodes whose data element is less than the target + deleteNode()
while (pCur != NULL && pCur->data < target){ + searchList()
pPre = pCur; + traverse()
pCur = pCur->next; + getLength()
} + isEmpty()
// Insert new node between pPre and pCur
pPre->next = pNew;
+ ~SList()
pNew->next = pCur;
length++;
}
59
Linked List Applications
60
1. Linked list in an array (no pointers)
data next
0
data next
1 70 4
data next
2
data next
3 10 6
data next
4 80 -1
data next
5
data next
6 20 1
data next
7
61
2. Operations on big numbers (tens of digits) 2019783 +
8905269
========
10925052
3 8 7 9 1 0 2
num_1
9 6 2 5 0 9 8
num_2
2 5 0 5 2 9 0 1
sum
62
3. Operations on polynomials
P: 3x4 + 2x + 5
Q: 7x3 + 5x2 + 4x + 6
P + Q?
P: 3x4 + 2x + 5
Q: 7x3 + 5x2 + 4x + 6
================================
P + Q: 3x4 + 7x3 + 5x2 + 6x + 11
63
4. Collections of linked lists
• array of linked lists (CIS 22C – Hashing)
• linked list of linked lists (CIS 22C – Graphs)
64
5. Text processing
text
The third
The fourth
65
6. Storage of files on a disk
There are different ways of allocating disk blocks for files, such as:
- contiguous
- linked allocation
- indexed allocation
66
7. Heap management
Operating Systems keep track of storage that is not in use: “free list”,
often implemented as a linked list.
67
Linked List
ü 1. Linear Lists
ü 2. List Operations
ü 3. Arrays versus Linked Lists
ü 4. Nodes
ü 5. Sentinel (dummy) nodes
ü 6. Types of Linked Lists
• Singly-Linked Lists
• Doubly-Linked Lists // CIS 22C
• Multi-Linked Lists // CIS 22C
ü 7. Linked List Applications
68