You are on page 1of 24

CT-159 DATA STRUCTURES ALGORITHMS

AND APPLICATIONS

LECTURE 3

HUMA TABASSUM
LECTURER
DEPT. OF COMPUTER SCIENCE & INFORMATION TECHNOLOGY
NED UNIVERSITY OF ENGINEERING & TECHNOLOGY
INTRODUCTION
• An array is a very useful data structure provided in programming languages.
• However, it has at least two limitations:
• its size has to be known at compilation time, and
• the data in the array are separated in computer memory by the same distance, which
means that inserting an item inside the array requires shifting other data in this array.
• This limitation can be overcome by using linked structures.
• A linked structure is a collection of nodes storing data and links to other
nodes.
• In this way, nodes can be located anywhere in memory, and passing from one node of
the linked structure to another is accomplished by storing the addresses of other
nodes in the linked structure.
• Although linked structures can be implemented in a variety of ways, the
most flexible implementation is by using pointers.
LINKED LIST
• If a node contains a data member that is a pointer to another node, then
many nodes can be strung together using only one variable to access the
entire sequence of nodes.
• Such a sequence of nodes is the most frequently used implementation of a
linked list, which is a data structure composed of nodes, each node holding
some information and a pointer to another node in the list.
• If a node has a link only to its successor in this sequence, the list is called a
singly linked list.
• An example of such a list is shown in Figure 3.1.
• Note that only one variable p is used to access any node in the list.
• The last node on the list can be recognized by the null pointer.
What does a linked list node contain?
• A node includes two data members: info and next.
• The info member is used to store information.
• The next member is used to link nodes to form a linked list.
• It is an auxiliary data member used to maintain the linked list.
• It is indispensable for implementation of the linked list.
• A linked list is the most sought-after data structure when it comes to
handling dynamic data elements.
• A linked list can grow and shrink its size, as per the requirement so it
does not waste memory space.
How to Define?

• Note that IntSLLNode is defined in terms of itself because one data


member, next, is a pointer to a node of the same type that is just being
defined.
• Objects that include such a data member are called self-referential objects.
• Now, let us create the linked list in Figure 3.1l.
Creation
• One way to create this three-node linked list is to first generate the
node for number 10, then the node for 8, and finally the node for 50.
• Each node has to be initialized properly and incorporated into the list.
• To see this, each step is illustrated in Figure 3.1 separately.

• First, we execute the declaration and assignment


IntSLLNode *p = new IntSLLNode(10);
which creates the first node on the list and makes the variable p a
pointer to this node.
Creation (continued)
• This is done in four steps.
• In the first step, a new IntSLLNode is created (Figure 3.1a), in the second step,
the info member of this node is set to 10 (Figure 3.1b), and in the third step,
the node’s next member is set to null (Figure 3.1c).
• The null pointer is marked with a slash in the pointer data member.

• The second and third steps—initialization of data members of the new


IntSLLNode—are performed by invoking the constructor.

• The fourth step is making p a pointer to the newly created node (Figure 3.1d).
• This pointer is the address of the node, and it is shown as an arrow from the variable p to
the new node.
• The second node is created with the assignment
p->next = new IntSLLNode(8);
where p->next is the next member of the node pointed to by p (Figure 3.1d).
• As before, four steps are executed.
• A new node is created (Figure 3.1e), the constructor assigns the info and next members of
this node (Figure 3.1f,g), and the new node is included in the list by making the next member
of the first node a pointer to the new node (Figure 3.1h).
• Note that the data members of nodes pointed to by p are accessed using the
arrow notation.
• The linked list is now extended by adding a third node with the assignment
p->next->next = new IntSLLNode(50);
where p->next->next is the next member of the second node.

• And the process repeats.


Limitation of this Approach and Solution
• This example illustrates an issue: the longer the linked list, the longer
the chain of nexts to access the nodes at the end of the list.
• What if it were the 103rd or, worse, the 1,003rd node on the list?
• Typing 1,003 nexts, as in p->next->. . .->next, would be .
• If we missed one next in this chain, then a wrong assignment is made.
• Therefore, one way is to always keep two pointers to the linked list:
one to the first node (head) and one to the last (tail).

not part of the list;


allows for having
access to the list
Insertion (at the beginning)
• Adding a node at the beginning of a linked list is performed in four
steps.
• An empty node is created. It is empty in the sense that the program performing
insertion does not assign any values to the data members of the node (Figure
3.4a).
• The node’s info member is initialized to a particular integer (Figure 3.4b).
• Because the node is being included at the front of the list, the next member
becomes a pointer to the first node on the list; that is, the current value of head
(Figure 3.4c).
• The new node precedes all the nodes on the list, but this fact has to be reflected
in the value of head; otherwise, the new node is not accessible. Therefore, head
is updated to become the pointer to the new node (Figure 3.4d).
Insertion (at the end)
• The process of adding a new node to the end of the list has five steps.
• An empty node is created (Figure 3.5a).
• The node’s info member is initialized to an integer el (Figure 3.5b).
• Because the node is being included at the end of the list, the next member is
set to null (Figure 3.5c).
• The node is now included in the list by making the next member of the last
node of the list a pointer to the newly created node (Figure 3.5d).
• The new node follows all the nodes of the list, but this fact has to be reflected
in the value of tail, which now becomes the pointer to the new node (Figure
3.5e).
How will you insert a node between two nodes??
Deletion (from the beginning)
• One deletion operation consists of deleting a node at the beginning of
the list and returning the value stored in it.
Special Cases
• Unlike before, there are now two special cases to consider.
• One case is when we attempt to remove a node from an empty linked
list.
• If such an attempt is made, the program is very likely to crash, which we don’t
want to happen.
• There are several ways to approach this problem.
• One way is to use an assert statement:
• The assert statement checks the condition !isEmpty(), and if the condition is false, the
program is aborted.
• Another solution is to throw an exception and catch it.
• The second special case is when the list has only one node to be
removed.
• In this case, the list becomes empty, which requires setting tail and head to null.
Deletion (from the end)
• The problem is that after removing a node, tail should refer to the new tail
of the list; that is, tail has to be moved backward by one node.
• But moving backward is impossible because there is no direct link from the
last node to its predecessor.
• Hence, this predecessor has to be found by searching from the beginning
of the list and stopping right before tail.
• This is accomplished with a temporary variable tmp that scans the list
within the for loop.
• The variable tmp is initialized to the head of the list, and then in each
iteration of the loop it is advanced to the next node.
• In deletion from end, the two special cases are the same as deletion from
beginning.
Another Situation
• Suppose we want to delete a node that holds a particular integer
regardless of the position of this node in the list.
• It may be right at the beginning, at the end, or anywhere inside the
list.
• Briefly, a node has to be located first and then detached from the list
by linking the predecessor of this node directly to its successor.
• Because we do not know where the node may be, the process of
finding and deleting a node with a certain integer is much more
complex than the deletion operations discussed so far.
• A node is removed from inside a
list by linking its predecessor to
its successor.
• But because the list has only
forward links, the predecessor of
a node is not reachable from the
node.
• One way to accomplish the task
is to find the node to be
removed by first scanning the list
and then scanning it again to
find its predecessor.
• Another way is shown in figure.
Search
• The searching operation scans an existing list to learn whether a number is
in it.
• We implement this operation with the Boolean member function isInList().
• The function uses a temporary variable tmp to go through the list starting
from the head node.
• The number stored in each node is compared to the number being sought,
and if the two numbers are equal, the loop is exited; otherwise, tmp is
updated to tmp->next so that the next node can be investigated.
• After reaching the last node and executing the assignment tmp = tmp->next,
tmp becomes null, which is used as an indication that the number is not in
the list.
• That is, if tmp is not null, the search was discontinued somewhere inside the
list because the number was found.

You might also like