You are on page 1of 34

UNIT-3 DATA STRUCTURES

UNIT – III
Data Structures –Definition, Linear Data Structures, Non-Linear Data Structures,
Stacks - Overview of Stack, Implementation of Stack (List), Applications of Stack
Queues: Overview of Queue, Implementation of Queue (List), Applications of Queues, Priority Queues
Linked Lists – Implementation of Singly Linked Lists, Doubly Linked Lists, Circular Linked Lists.
Implementation of Stack and Queue using Linked list.

What is Data Structure?


A data structure is a particular way of organizing data in a computer so that it can be used effectively.
The idea is to reduce the space and time complexities of different tasks.
The choice of a good data structure makes it possible to perform a variety of critical operations
effectively. An efficient data structure also uses minimum memory space and execution time to
process the structure. A data structure is not only used for organizing the data. It is also used for
processing, retrieving, and storing data. There are different basic and advanced types of data
structures that are used in almost every program or software system that has been developed. So we
must have good knowledge of data structures.

Need Of Data Structure:


The structure of the data and the synthesis of the algorithm are relative to each other. Data
presentation must be easy to understand so the developer, as well as the user, can make an efficient
implementation of the operation.
Data structures provide an easy way of organizing, retrieving, managing, and storing data.
Here is a list of the needs for data.
 Data structure modification is easy.
 It requires less time.
 Save storage memory space.
 Data representation is easy.
 Easy access to the large database

Classification of Data Structures

A Data Structure delivers a structured set of variables related to each other in various ways. It forms
the basis of a programming tool that signifies the relationship between the data elements and allows
programmers to process the data efficiently.

We can classify Data Structures into two categories:

1. Primitive Data Structure


2. Non-Primitive Data Structure

B SARITHA, CSE pg. 1


UNIT-3 DATA STRUCTURES

The following figure shows the different classifications of Data Structures.

Primitive Data Structures


1. Primitive Data Structures are the data structures consisting of the numbers and the characters
that come in-built into programs.
2. These data structures can be manipulated or operated directly by machine-level instructions.
3. Basic data types like Integer, Float, Character, and Boolean come under the Primitive Data
Structures.
4. These data types are also called Simple data types, as they contain characters that can't be
divided further

Non-Primitive Data Structures


1. Non-Primitive Data Structures are those data structures derived from Primitive Data
Structures.
2. These data structures can't be manipulated or operated directly by machine-level instructions.
3. The focus of these data structures is on forming a set of data elements that is
either homogeneous (same data type) or heterogeneous (different data types).
4. Based on the structure and arrangement of data, we can divide these data structures into two
sub-categories -
a. Linear Data Structures
b. Non-Linear Data Structures

B SARITHA, CSE pg. 2


UNIT-3 DATA STRUCTURES

Linear Data Structures

A data structure that preserves a linear connection among its data elements is known as a Linear Data
Structure. The arrangement of the data is done linearly, where each element consists of the successors
and predecessors except the first and the last data element. However, it is not necessarily true in the
case of memory, as the arrangement may not be sequential.

Based on memory allocation, the Linear Data Structures are further classified into two types:

1. Static Data Structures: The data structures having a fixed size are known as Static Data
Structures. The memory for these data structures is allocated at the compiler time, and their size
cannot be changed by the user after being compiled; however, the data stored in them can be
altered.
The Array is the best example of the Static Data Structure as they have a fixed size, and its data
can be modified later.
2. Dynamic Data Structures: The data structures having a dynamic size are known as Dynamic
Data Structures. The memory of these data structures is allocated at the run time, and their size
varies during the run time of the code. Moreover, the user can change the size as well as the
data elements stored in these data structures at the run time of the code.
Linked Lists, Stacks, and Queues are common examples of dynamic data structures

Types of Linear Data Structures

The following is the list of Linear Data Structures that we generally use:

1. Arrays

An Array is a data structure used to collect multiple data elements of the same data type into one
variable. Instead of storing multiple values of the same data types in separate variable names, we could
store all of them together into one variable. This statement doesn't imply that we will have to unite all
the values of the same data type in any program into one array of that data type. But there will often be
times when some specific variables of the same data types are all related to one another in a way
appropriate for an array.

An Array is a list of elements where each element has a unique place in the list. The data elements of
the array share the same variable name; however, each carries a different index number called a
subscript. We can access any data element from the list with the help of its location in the list. Thus,
the key feature of the arrays to understand is that the data is stored in contiguous memory locations,
making it possible for the users to traverse through the data elements of the array using their respective
indexes.

B SARITHA, CSE pg. 3


UNIT-3 DATA STRUCTURES

Figure 3. An Array

Arrays can be classified into different types:

a) One-Dimensional Array: An Array with only one row of data elements is known as a One-
Dimensional Array. It is stored in ascending storage location.
b) Two-Dimensional Array: An Array consisting of multiple rows and columns of data elements
is called a Two-Dimensional Array. It is also known as a Matrix.
c) Multidimensional Array: We can define Multidimensional Array as an Array of Arrays.
Multidimensional Arrays are not bounded to two indices or two dimensions as they can include
as many indices are per the need.

Some Applications of Array:

a) We can store a list of data elements belonging to the same data type.
b) Array acts as an auxiliary storage for other data structures.
c) The array also helps store data elements of a binary tree of the fixed count.
d) Array also acts as a storage of matrices.

2. Linked Lists

A Linked List is another example of a linear data structure used to store a collection of data elements
dynamically. Data elements in this data structure are represented by the Nodes, connected using links
or pointers. Each node contains two fields, the information field consists of the actual data, and the
pointer field consists of the address of the subsequent nodes in the list. The pointer of the last node of
the linked list consists of a null pointer, as it points to nothing. Unlike the Arrays, the user can
dynamically adjust the size of a Linked List as per the requirements.

B SARITHA, CSE pg. 4


UNIT-3 DATA STRUCTURES

Figure 4. A Linked List

Linked Lists can be classified into different types:

a) Singly Linked List: A Singly Linked List is the most common type of Linked List. Each node
has data and a pointer field containing an address to the next node.
b) Doubly Linked List: A Doubly Linked List consists of an information field and two pointer
fields. The information field contains the data. The first pointer field contains an address of the
previous node, whereas another pointer field contains a reference to the next node. Thus, we
can go in both directions (backward as well as forward).
c) Circular Linked List: The Circular Linked List is similar to the Singly Linked List. The only
key difference is that the last node contains the address of the first node, forming a circular loop
in the Circular Linked List.

Some Applications of Linked Lists:

a) The Linked Lists help us implement stacks, queues, binary trees, and graphs of predefined size.
b) We can also implement Operating System's function for dynamic memory management.
c) Linked Lists also allow polynomial implementation for mathematical operations.
d) We can use Circular Linked List to implement Operating Systems or application functions that
Round Robin execution of tasks.
e) Circular Linked List is also helpful in a Slide Show where a user requires to go back to the first
slide after the last slide is presented.
f) Doubly Linked List is utilized to implement forward and backward buttons in a browser to
move forward and backward in the opened pages of a website.

B SARITHA, CSE pg. 5


UNIT-3 DATA STRUCTURES

Types of Non-primitive data structures

Difference between Linear and Non-linear Data Structures:

S.NO Linear Data Structure Non-linear Data Structure

In a linear data structure, data elements are


arranged in a linear order where each and In a non-linear data structure, data elements
1.
every element is attached to its previous and are attached in hierarchically manner.
next adjacent.

In linear data structure, single level is Whereas in non-linear data structure,


2.
involved. multiple levels are involved.

Its implementation is easy in comparison to While its implementation is complex in


3.
non-linear data structure. comparison to linear data structure.

While in non-linear data structure, data


In linear data structure, data elements can be
4. elements can’t be traversed in a single run
traversed in a single run only.
only.

While in a non-linear data structure,


In a linear data structure, memory is not
5. memory is utilized in an efficient way.
utilized in an efficient way.

Its examples are: array, stack, queue, linked


6. While its examples are: trees and graphs.
list, etc.

B SARITHA, CSE pg. 6


UNIT-3 DATA STRUCTURES

S.NO Linear Data Structure Non-linear Data Structure

Applications of non-linear data structures


Applications of linear data structures are
7. are in Artificial Intelligence and image
mainly in application software development.
processing.

Non-linear data structures are useful for


Linear data structures are useful for simple representing complex relationships and data
8.
data storage and manipulation. hierarchies, such as in social networks, file
systems, or computer networks.

Performance is usually good for simple


Performance can vary depending on the
operations like adding or removing at the
9. structure and the operation, but can be
ends, but slower for operations like searching
optimized for specific operations.
or removing elements in the middle.

STACK:
A stack is a linear data structure that stores items in a Last-In/First-Out (LIFO) or First-In/Last-
Out (FILO) manner. In stack, a new element is added at one end and an element is removed from that
end only. The insert and delete operations are often called push and pop

 Push operation as demonstrated in below diagram will add an element at the top of stack. Refer
the below image for more understanding:

B SARITHA, CSE pg. 7


UNIT-3 DATA STRUCTURES

Pop operation as demonstrated in below diagram removes an element from the top of
the stack. Refer the below image for more understanding:

The functions associated with stack are:


 empty() – Returns whether the stack is empty – Time Complexity: O(1)
 size() – Returns the size of the stack – Time Complexity: O(1)
 top() / peek() – Returns a reference to the topmost element of the stack – Time Complexity:
O(1)
 push(a) – Inserts the element ‘a’ at the top of the stack – Time Complexity: O(1)
 pop() – Deletes the topmost element of the stack – Time Complexity: O(1)

B SARITHA, CSE pg. 8


UNIT-3 DATA STRUCTURES

Implementation of Stack in Python

class Stack:
top=-1 #class variable
def __init__(self,size):
self.MAX=size
self.list1=[]
print("stack is created ")
def push_ele(self,x):
if Stack.top== self.MAX-1:
print("stack is full")
else:
Stack.top=Stack.top+1
print(Stack.top)
self.list1.insert( Stack.top , x) #insert element into the stack.
def pop_ele(self):
if Stack.top== -1:
print("stack is empty")
else:
m=Stack.top
print(m)
k=self.list1.pop( m ) #// to remove an item from the stack
Stack.top=Stack.top-1
return k
def display(self):
if Stack.top== -1:
print("stack is empty")
else:
print("elements in the stack are ")
print(self.list1)

ob=Stack(5)
ob.push_ele(25)
ob.push_ele(45)
ob.push_ele(65)
ob.push_ele(85)
ob.push_ele(95)
ob.push_ele(105)
print(Stack.top)
ob.display()

B SARITHA, CSE pg. 9


UNIT-3 DATA STRUCTURES

ob.push_ele(16)
ob.push_ele(12)
ob.display()

print("popped element is ",ob.pop_ele())


print("popped element is ",ob.pop_ele())
print("after deleting or popping the 2 items stack is ")
ob.display()
print("popped element is ",ob.pop_ele())
print("popped element is ",ob.pop_ele())
print("popped element is ",ob.pop_ele())
print("popped element is ",ob.pop_ele())

Output:
stack is created
0
1
2
3
4
stack is full
4
elements in the stack are
[25, 45, 65, 85, 95]
stack is full
stack is full
elements in the stack are
[25, 45, 65, 85, 95]
4
popped element is 95
3
popped element is 85
after deleting or popping the 2 items stack is
elements in the stack are
[25, 45, 65]
2
popped element is 65
1
popped element is 45

B SARITHA, CSE pg. 10


UNIT-3 DATA STRUCTURES

0
popped element is 25
stack is empty
popped element is None

Some Applications of Stacks:


a. The Stack is used as a Temporary Storage Structure for recursive operations.
b. Stack is also utilized as Auxiliary Storage Structure for function calls, nested operations, and
deferred/postponed functions.
c. We can manage function calls using Stacks.
d. Stacks are also utilized to evaluate the arithmetic expressions in different programming
languages.
e. Stacks are also helpful in converting infix expressions to postfix expressions.
f. Stacks allow us to check the expression's syntax in the programming environment.
g. We can match parenthesis using Stacks.
h. Stacks can be used to reverse a String.
i. Stacks are helpful in solving problems based on backtracking.
j. We can use Stacks in depth-first search in graph and tree traversal.
k. Stacks are also used in Operating System functions.
l. Stacks are also used in UNDO and REDO functions in an edit.

QUEUE
Like a stack, the queue is a linear data structure that stores items in a First In First Out (FIFO) manner.
With a queue, the least recently added item is removed first. A good example of a queue is any queue
of consumers for a resource where the consumer that came first is served first.

Operations associated with queue are:


 Enqueue: Adds an item to the queue. If the queue is full, then it is said to be an Overflow
condition – Time Complexity : O(1)

B SARITHA, CSE pg. 11


UNIT-3 DATA STRUCTURES

 Dequeue: Removes an item from the queue. The items are popped in the same order in
which they are pushed. If the queue is empty, then it is said to be an Underflow condition
– Time Complexity : O(1)
 Front: Get the front item from queue – Time Complexity : O(1)
 Rear: Get the last item from queue – Time Complexity : O(1)

Working of Queue

Queue operations work as follows:

 two pointers FRONT and REAR


 FRONT track the first element of the queue
 REAR track the last element of the queue
 initially, set value of FRONT and REAR to -1

Enqueue Operation

 check if the queue is full

 for the first element, set the value of FRONT to 0


 increase the REAR index by 1
 add the new element in the position pointed to by REAR

Dequeue Operation

 check if the queue is empty

 return the value pointed by FRONT


 increase the FRONT index by 1
 for the last element, reset the values of FRONT and REAR to -1

B SARITHA, CSE pg. 12


UNIT-3 DATA STRUCTURES

B SARITHA, CSE pg. 13


UNIT-3 DATA STRUCTURES

# Queue implementation in Python

class Queue:

def __init__(self):
self.queue = []

# Add an element
def enqueue(self, item):
self.queue.append(item)

# Remove an element
def dequeue(self):
if len(self.queue) < 1:
return None
return self.queue.pop(0)

# Display the queue


def display(self):
print(self.queue)

def size(self):
return len(self.queue)

q = Queue()
q.enqueue(10)
q.enqueue(20)
q.enqueue(30)
q.enqueue(40)
q.enqueue(50)
q.display()
q.dequeue()
print("After removing an element")
q.display()

OUTPUT:
Current Queue: [10, 20, 30, 40, 50]
Dequeued item: 10
Dequeued item: 20
Updated Queue: [30, 40, 50]

B SARITHA, CSE pg. 14


UNIT-3 DATA STRUCTURES

Some Applications of Queues:

a) Queues are generally used in the breadth search operation in Graphs.


b) Queues are also used in Job Scheduler Operations of Operating Systems, like a keyboard buffer
queue to store the keys pressed by users and a print buffer queue to store the documents printed
by the printer.
c) Queues are responsible for CPU scheduling, Job scheduling, and Disk Scheduling.
d) Priority Queues are utilized in file-downloading operations in a browser.
e) Queues are also used to transfer data between peripheral devices and the CPU.
f) Queues are also responsible for handling interrupts generated by the User Applications for the
CPU.

Types of Linked List

Before knowing about the types of a linked list, we should know what is linked list. So, to know about
the linked list, click on the link given below:

 Singly linked lists

 Doubly linked lists

 Circular linked lists

 Circular doubly linked lists

Singly Linked List

The singly linked list is a linear data structure in which each element of the list contains a pointer which
points to the next element in the list. Each element in the singly linked list is called a node. Each node
has two components: data and a pointer next which point to the next node in the list. The first node of
the list is called as head, and the last node of the list is called a tail. The last node of the list contains a

B SARITHA, CSE pg. 15


UNIT-3 DATA STRUCTURES

pointer to the null. Each node in the list can be accessed linearly by traversing through the list from
head to tail.

Consider the above example; node 1 is the head of the list and node 4 is the tail of the list. Each node
is connected in such a way that node 1 is pointing to node 2 which in turn pointing to node 3. Node 3
is again pointing to node 4. Node 4 is pointing to null as it is the last node of the list.

Insertion in Linked List


Given a Linked List, the task is to insert a new node in this given Linked List at the following
positions:
 At the front of the linked list
 After a given node.
 At the end of the linked list.

How to Insert a Node at the Front/Beginning of Linked List


Approach:
To insert a node at the start/beginning/front of a Linked List, we need to:
 Make the first node of Linked List linked to the new node
 Remove the head from the original first node of Linked List
 Make the new node as the Head of the Linked List.

B SARITHA, CSE pg. 16


UNIT-3 DATA STRUCTURES

How to Insert a Node after a Given Node in Linked List


Approach:
To insert a node after a given node in a Linked List, we need to:
 Check if the given node exists or not.
 If it do not exists,
 terminate the process.
 If the given node exists,
 Make the element to be inserted as a new node
 Change the next pointer of given node to the new node
 Now shift the original next pointer of given node to the next pointer
of new node

How to Insert a Node at the End of Linked List


To insert a node at the end of a Linked List, we need to:
 Go to the last node of the Linked List
 Change the next pointer of last node from NULL to the new node
 Make the next pointer of new node as NULL to show the end of Linked List

B SARITHA, CSE pg. 17


UNIT-3 DATA STRUCTURES

# A single node of a singly linked list


class Node:
# constructor
def __init__(self, data):
self.data = data
self.next = None

# A Linked List class with a single head node


class LinkedList:
def __init__(self):
self.head = None
def insert(self, data):
new_Node = Node(data)
if(self.head):
temp = self.head
while( temp.next):
temp = temp.next
temp.next = new_Node
else:
self.head = new_Node
def insert_position(self,pos,data):
new_node=Node(data)
temp=self.head
for i in range(1,pos-1):
temp=temp.next
new_node.next=temp.next
temp.next=new_node
def printLL(self):
temp = self.head
while(temp):
print(temp.data)
temp = temp.next
# Singly Linked List with insertion and print methods
LL = LinkedList()
LL.insert(30)
LL.insert(40)
LL.insert(50)
LL.insert(60)
LL.insert(70)
print("After creation the elents are")

B SARITHA, CSE pg. 18


UNIT-3 DATA STRUCTURES

LL.printLL()
print("After inserting node at position 2")
LL.insert_position(5,45)
LL.printLL()

Output:
After creation the elents are
30
40
50
60
70
After inserting node at position 2
30
40
50
60
45
70

# A single node of a singly linked list


class Node:
# constructor
def __init__(self, data):
self.data = data
self.next = None

# A Linked List class with a single head node


class LinkedList:
def __init__(self):
self.head = None
def insert(self, data):
new_Node = Node(data)
if(self.head):
temp = self.head
while( temp.next):
temp = temp.next

B SARITHA, CSE pg. 19


UNIT-3 DATA STRUCTURES

temp.next = new_Node
new_next=self.head
else:
self.head = new_Node
def remove_first_node(self):
if(self.head == None):
return
else:
temp=self.head
self.head = temp.next
self.temp=None
def remove_last_node(self):
prev=self.head
temp=self.head.next
while temp.next is not None:
temp=temp.next
prev=prev.next
prev.next=None
def remove_at_index(self, index):
if self.head == None:
return
temp = self.head
position = 0
if position == index:
self.remove_first_node()
else:
while(temp != None and position+1 != index):
position = position+1
temp = temp.next
if temp != None:
temp.next = temp.next.next
else:
print("Index not present")
# print method for the linked list
def printLL(self):
temp = self.head
while(temp):
print(temp.data)
temp = temp.next
# Singly Linked List with insertion and print methods

B SARITHA, CSE pg. 20


UNIT-3 DATA STRUCTURES

LL = LinkedList()
LL.insert(30)
LL.insert(40)
LL.insert(50)
LL.insert(60)
LL.insert(70)
print("After creation the elents are")
LL.printLL()
print("After deleting first element")
LL.remove_first_node()
LL.printLL()
#print("After deleting last element")
#LL.remove_last_node()
#LL.printLL()
print("After Deleting node at index 2")
LL.remove_at_index(2)
LL.printLL()

Output:
After creation the elents are
30
40
50
60
70
After deleting first element
40
50
60
70
After Deleting node at index 2
40
50
70

B SARITHA, CSE pg. 21


UNIT-3 DATA STRUCTURES

Doubly Linked List:

Doubly Linked List is a variation of the linked list. The linked list is a linear data structure which can
be described as the collection of nodes. Nodes are connected through pointers. Each node contains two
fields: data and pointer to the next field. The first node of the linked list is called the head, and the last
node of the list is called the tail of the list.

One of the limitations of the singly linked list is that it can be traversed in only one direction that is
forward. The doubly linked list has overcome this limitation by providing an additional pointer that
points to the previous node. With the help of the previous pointer, the doubly linked list can be traversed
in a backward direction thus making insertion and deletion operation easier to perform. So, a typical
node in the doubly linked list consists of three fields:

o Data represents the data value stored in the node.


o Previous represents a pointer that points to the previous node.
o Next represents a pointer that points to the next node in the list.

The above picture represents a doubly linked list in which each node has two pointers to point to
previous and next node respectively. Here, node 1 represents the head of the list. The previous pointer
of the head node will always point to NULL. Next pointer of node one will point to node 2. Node 5
represents the tail of the list whose previous pointer will point to node 4, and the next will point to
NULL

Insertion in a Doubly Linked List


Add a node at the front in a Doubly Linked List:
The new node is always added before the head of the given Linked List. The task can be performed
by using the following 5 steps:
1. Firstly, allocate a new node (say new_node).
2. Now put the required data in the new node.
3. Make the next of new_node point to the current head of the doubly linked list.
4. Make the previous of the current head point to new_node.
5. Lastly, point head to new_node.

B SARITHA, CSE pg. 22


UNIT-3 DATA STRUCTURES

Illustration:
See the below illustration where E is being inserted at the beginning of the doubly linked
list

Add a node in between two nodes:


It is further classified into the following two parts:
Add a node after a given node in a Doubly Linked List:
We are given a pointer to a node as prev_node, and the new node is inserted after the given node.
This can be done using the following 6 steps:
1. Firstly create a new node (say new_node).
2. Now insert the data in the new node.
3. Point the next of new_node to the next of prev_node.
4. Point the next of prev_node to new_node.
5. Point the previous of new_node to prev_node.
6. Change the pointer of the new node’s previous pointer to new_node.
Illustration:
See the below illustration where ‘E‘ is being inserted after ‘B‘.

Add a node at the end in a Doubly Linked List:


The new node is always added after the last node of the given Linked List. This can be done using
the following 7 steps:
1. Create a new node (say new_node).
2. Put the value in the new node.
3. Make the next pointer of new_node as null.

B SARITHA, CSE pg. 23


UNIT-3 DATA STRUCTURES

4. If the list is empty, make new_node as the head.


5. Otherwise, travel to the end of the linked list.
6. Now make the next pointer of last node point to new_node.
7. Change the previous pointer of new_node to the last node of the list.
Illustration:
See the below illustration where ‘D‘ is inserted at the end of the linked list.

#Implement Double linkedlist


class Node:
def __init__(self,data):
self.data = data;
self.previous = None;
self.next = None;

class DoublyLinkedList:
def __init__(self):
self.head = None;
self.tail = None;

def insert(self, data):


#Create a new node
newNode = Node(data)

#If list is empty


if(self.head == None):
self.head = self.tail = newNode
self.head.previous = None
self.tail.next = None
else:
self.tail.next = newNode
newNode.previous = self.tail
self.tail = newNode
self.tail.next = None

B SARITHA, CSE pg. 24


UNIT-3 DATA STRUCTURES

# Adding a node at the front of the list


def insertAtBeginning(self,data):
new_node = Node(data)
if self.head==None:
self.head = new_node
else:
new_node.next = self.head
self.head.previous = new_node
self.head = new_node
def insertAtEnd(self,data):
new_node = Node(data)
if self.head==None:
self.head = new_node
else:
temp = self.head
while temp.next is not None:
temp = temp.next
temp.next = new_node
new_node.previous = temp
def deleteFromBeginning(self):
if self.head is None:
print("Linked List is empty. Cannot delete elements.")
elif self.head.next is None:
self.head = None
else:
self.head = self.head.next
self.head.previous = None
def deleteFromLast(self):
if self.head is None:
print("Linked List is empty. Cannot delete elements.")
elif self.head.next is None:
self.head = None
else:
temp = self.head
while temp.next is not None:
temp = temp.next
temp.previous.next = None
temp.previous = None

def display(self):

B SARITHA, CSE pg. 25


UNIT-3 DATA STRUCTURES

#Node current will point to head


temp = self.head
if(self.head == None):
print("List is empty")
return
print("Nodes of doubly linked list: ")
while(temp!= None):
#Prints each node by incrementing pointer.
print(temp.data)
temp = temp.next
dList = DoublyLinkedList()
#Add nodes to the list
dList.insert(10)
dList.insert(20)
dList.insert(30)
dList.insert(40)
dList.insert(50)
#Displays the nodes present in the list
dList.display()
print("After insertion at begin")
dList.insertAtBeginning(5)
dList.display()
print("After insertion at end")
dList.insertAtEnd(60)
dList.display()
dList.deleteFromBeginning()
print("After deleting the first node")
dList.display()
dList.deleteFromLast()
print("After deleting the last node")
dList.display()

Output
Nodes of doubly linked list:
10
20
30
40
50

B SARITHA, CSE pg. 26


UNIT-3 DATA STRUCTURES

After insertion at begin


Nodes of doubly linked list:
5
10
20
30
40
50
After insertion at end
Nodes of doubly linked list:
5
10
20
30
40
50
60
After deleting the first node
Nodes of doubly linked list:
10
20
30
40
50
60
After deleting the last node
Nodes of doubly linked list:
10
20
30
40
50

Circular Linked List:

The circular linked list is a kind of linked list. First thing first, the node is an element of the list, and it
has two parts that are, data and next. Data represents the data stored in the node, and next is the pointer
that will point to the next node. Head will point to the first element of the list, and tail will point to the
last element in the list. In the simple linked list, all the nodes will point to their next element and tail
will point to null.

B SARITHA, CSE pg. 27


UNIT-3 DATA STRUCTURES

The circular linked list is the collection of nodes in which tail node also point back to head node. The
diagram shown below depicts a circular linked list. Node A represents head and node D represents tail.
So, in this list, A is pointing to B, B is pointing to C and C is pointing to D but what makes it circular
is that node D is pointing back to node A.

Algorithm:
1. Define a Node class which represents a node in the list. It has two properties data and next
which will point to the next node.
2. Define another class for creating the circular linked list, and it has two nodes: head and tail. It
has two methods: add() and display() .
3. add() will add the node to the list:
4. It first checks whether the head is null, then it will insert the node as the head.
5. Both head and tail will point to the newly added node.
6. If the head is not null, the new node will be the new tail, and the new tail will point to the head
as it is a circular linked list.

Program:
1. #Represents the node of list.
2. class Node:
3. def __init__(self,data):
4. self.data = data;
5. self.next = None;
6.
7. class CreateList:
8. #Declaring head and tail pointer as null.
9. def __init__(self):
10. self.head = Node(None);
11. self.tail = Node(None);

B SARITHA, CSE pg. 28


UNIT-3 DATA STRUCTURES

12. self.head.next = self.tail;


13. self.tail.next = self.head;
14.
15. #This function will add the new node at the end of the list.
16. def add(self,data):
17. newNode = Node(data);
18. #Checks if the list is empty.
19. if self.head.data is None:
20. #If list is empty, both head and tail would point to new node.
21. self.head = newNode;
22. self.tail = newNode;
23. newNode.next = self.head;
24. else:
25. #tail will point to new node.
26. self.tail.next = newNode;
27. #New node will become new tail.
28. self.tail = newNode;
29. #Since, it is circular linked list tail will point to head.
30. self.tail.next = self.head;
31.
32. #Displays all the nodes in the list
33. def display(self):
34. current = self.head;
35. if self.head is None:
36. print("List is empty");
37. return;
38. else:
39. print("Nodes of the circular linked list: ");
40. #Prints each node by incrementing pointer.
41. print(current.data),
42. while(current.next != self.head):
43. current = current.next;
44. print(current.data),
45.
46.
47. class CircularLinkedList:
48. cl = CreateList();
49. #Adds data to the list
50. cl.add(1);
51. cl.add(2);

B SARITHA, CSE pg. 29


UNIT-3 DATA STRUCTURES

52. cl.add(3);
53. cl.add(4);
54. #Displays all the nodes present in the list
55. cl.display();

Output:

Nodes of the circular linked list:


1234

Implementation Of Stack Using Linked List

# the node class is used to create an element holder and the respective reference pointers.
class Node:
def __init__(self, data=None, next=None):
self.data = data
self.next = next
class Stack:
def __init__(self):
self.top = None
def push(self, data):
if self.top is None:
self.top = Node(data, None)
return
self.top = Node(data, self.top)
def pop(self):
if self.top is None:
return
temp = self.top
if self.top is not None:
self.top = self.top.next
temp.next = None
return temp.data
def peek(self):
return self.top.data
def clearstack(self):
self.top = None
def emptystack(self):
if self.top is None:
return True

B SARITHA, CSE pg. 30


UNIT-3 DATA STRUCTURES

return False
def display(self):
itr = self.top
sstr = ' '
while itr:
sstr += str(itr.data) + '-->'
itr = itr.next
print(sstr)

if __name__ == "__main__":
stack = Stack()
stack.push(10)
stack.push(20)
stack.push(30)
stack.peek()
print("Display all the elements")
stack.display()
print("Delete top of the element")
stack.pop()
stack.display()
print("after iserting one element")
stack.push(40)
stack.display()
print("after clearstack")
stack.clearstack()
print("Stack is empty")
stack.display()

OUTPUT:
Display all the elements
30-->20-->10-->
Delete top of the element
20-->10-->
after iserting one element
40-->20-->10-->
after clearstack
Stack is empty

B SARITHA, CSE pg. 31


UNIT-3 DATA STRUCTURES

Code Implementation of queue using doubly linked list in PythonV

class Node:

def __init__(self, data):


self.data = data
self.next = None
self.prev = None

class Queue:

def __init__(self):
self.head = None
self.last=None

def enqueue(self, data):


if self.last is None:
self.head =Node(data)
self.last =self.head
else:
self.last.next = Node(data)
self.last.next.prev=self.last
self.last = self.last.next

def dequeue(self):

if self.head is None:
return None
else:
temp= self.head.data
self.head = self.head.next
self.head.prev=None
return temp

def first(self):

B SARITHA, CSE pg. 32


UNIT-3 DATA STRUCTURES

return self.head.data

def size(self):

temp=self.head
count=0
while temp is not None:
count=count+1
temp=temp.next
return count

def isEmpty(self):

if self.head is None:
return True
else:
return False

def printqueue(self):

print("queue elements are:")


temp=self.head
while temp is not None:
print(temp.data,end=" ")
temp=temp.next

if __name__=='__main__':
queue = Queue()

print("Queue operations using doubly linked list")

queue.enqueue(2)

queue.enqueue(4)

B SARITHA, CSE pg. 33


UNIT-3 DATA STRUCTURES

queue.enqueue(6)

queue.enqueue(8)

queue.printqueue()

print("\nfirst element is ",queue.first())

print("Size of the queue is ",queue.size())

queue.dequeue()

queue.dequeue()

print("After applying dequeue() two times")


queue.printqueue()

print("\nqueue is empty:",queue.isEmpty())

Some Applications of Data Structures


1. Data Structures help in the organization of data in a computer's memory.
2. Data Structures also help in representing the information in databases.
3. Data Structures allows the implementation of algorithms to search through data (For example,
search engine).
4. We can use the Data Structures to implement the algorithms to manipulate data (For example,
word processors).
5. We can also implement the algorithms to analyse data using Data Structures (For example, data
miners).
6. Data Structures support algorithms to generate the data (For example, a random number
generator).
7. Data Structures also support algorithms to compress and decompress the data (For example, a
zip utility).
8. We can also use Data Structures to implement algorithms to encrypt and decrypt the data (For
example, a security system).
9. With the help of Data Structures, we can build software that can manage files and directories
(For example, a file manager).
10. We can also develop software that can render graphics using Data Structures. (For example, a
web browser or 3D rendering software).

B SARITHA, CSE pg. 34

You might also like