Data Structures
Data Structures
can be defined as a way to store and organize data so that it can be used efficiently. Data
structures play a very important role in any software development as they help us to store and retrieve data as
fast as possible.
Large amounts of data is processed by different systems and if this is not stored properly, it will lead to
data loss.
It is easier to search for a particular data if it is organized in a proper format.
Data Structures help a program to minimize the usage of resources such as memory and space.
There are different types of data structures like list, stack, queue, etc. Each of them are suitable for specific
type of tasks.
A linear data structure is the one in which elements are arranged in a sequential manner and each element is
connected to its previous and next element.
A non-linear data structure is the one in which elements are not arranged in a sequential manner and each
element is connected to other elements through multiple paths.
You have already seen and worked with Array. Array is a linear data structure used to store similar type of
data. It is very easy to access any member of an array by using index.
You will now see how to insert and delete elements in an array.
To insert an element at a specific position, you first need to shift all the elements from that position by one to
the right.
Consider the array [A, B, C, D, E, F]. Let's say you want to insert 'J' at the third position.
First, all the elements from the third position to the last position are shifted.
For deleting an element from an array, the elements need to be shifted towards the position from which the
element has to be deleted.
Consider the array [A, B, C, D, E, F] and let's say you want to delete the element at the third position.
Some of the limitations are:
An array can contain data of only similar type. Heterogeneous elements cannot be stored in an array.
Array is of fixed size. Once declared, the size cannot be changed. Let us consider an example of a
school which uses an array to store names of all the students in a class. Initially based on the number
of students, an array is created and the information is stored. Suppose a student joins after few
days, storing the information of this student now becomes very difficult.
You have seen the insertion and deletion operations in an array. Those operations are expensive in
terms of memory as they require shifting of elements. This shifting may also sometime lead to loss of
data if we try to exceed the capacity of the array. Let us take the example of a car having 5 seats. 5
people are seated and another person comes and wants to sit at the second seat. In order to
accommodate this person, the person sitting at the second seat shifts to the third seat and so on. At
the end, the person who was sitting at the last has no place to sit.
The elements of an array are stored in continuous memory locations. If the required number of blocks
are not present together in the memory, then the array will not be created.
Linked list
Let us consider that a person named Noah is travelling to Europe for a holiday. He plans to travel to different
cities by train. The trip will cover most of the major cities like Milan, Venice, Paris, Amsterdam, etc.
He wants to store the information as to what cities he will be covering and in which order. The duration of the
trip is not fixed and also the number of cities that Noah wants to cover are not finalized and may change on the
way.
The trip details need to be stored in some data structure. Since the number of cities is not fixed, it is not a good
idea to use an array for storing the information.
This kind of information can be stored using another data structure called Linked list. Linked list eliminates the
disadvantages of an array that we had discussed previously.
A Linked List is a linear data structure used to store collections of objects. A Linked List is made up of
individual nodes which may be present at different memory locations, i.e., they need not be contiguous unlike
arrays. These nodes are connected or linked to each other. A node is made up of two parts - one to store the
data and a link to connect to the next node.
String data;
Node next;
Here, the data to be stored is of type String since city names have to be stored.
The data member variable can be of any primitive type or even objects of any class based on the requirement.
this.data=data;
this.data = data;
this.next = node;
return this.data;
return this.next;
}
Note:- "next" attribute of the Node class will be set to null by the constructor implicitly hence, it’s not explicitly
set to null. This can also be done by adding "next=null;" in the constructor of Node class.
The node referred by head marks the beginning of the list and the node referred by tail, marks the end of the
list.
Node head;
Node tail;
return this.head;
return this.tail;
Noah decides that the next city he will go to after Munich is Vienna. He wants to add this to his list.
Currently, Munich is the tail node of the list. So, it means that Vienna should be added after Munich and
should be made as the tail node.
Adding a node at the end of a linked list is very simple if the tail is known. The new node is simply linked to the
tail node and the position of the tail is changed as shown below.
add(data)
2.If the linked list is empty, then make this new node the head and the tail node
3.Else,
a.Make the link of the tail node refer to the new node
class Node {
this.data=data;
}
this.data = data;
this.next = node;
return this.data;
return this.next;
class LinkedList {
return this.head;
return this.tail;
}
//if yes, make the node as the head and the tail
if(this.head == null)
this.head=this.tail=node;
else{
//If the list is not empty, add the element at the end
this.tail.setNext(node);
this.tail=node;
class Tester{
list.addAtEnd("Milan");
list.addAtEnd("Venice");
list.addAtEnd("Munich");
list.addAtEnd("Vienna");
Problem Statement
Implement the method addAtBeginning(String data) to add a new element at the
beginning of a linked list.
You can make use of the below steps to implement the method.
2. If the linked list is empty, make the new node as the head and the tail node.
3. If the linked list is not empty, add the new node at the beginning, i.e., before
the current head node and make the new node as the head.
class Node {
this.data=data;
this.data = data;
this.next = node;
}
public String getData(){
return this.data;
return this.next;
class LinkedList {
return this.head;
return this.tail;
//if yes, make the node as the head and the tail
if(this.head == null)
this.head=this.tail=node;
else{
//If the list is not empty, add the element at the end
this.tail.setNext(node);
this.tail=node;
class Tester{
list.addAtEnd("Milan");
list.addAtEnd("Venice");
list.addAtEnd("Munich");
list.addAtBeginning("Nice");
To display the elements of a linked list from head to tail, you need to traverse the list using a temporary
reference and print the data at each point.
display()
class Node {
this.data = data;
}
public void setData(String data) {
this.data = data;
this.next = node;
return this.data;
return this.next;
class LinkedList {
return this.head;
}
public Node getTail() {
return this.tail;
if (this.head == null)
else {
this.tail.setNext(node);
this.tail = node;
else {
node.setNext(this.head);
this.head = node;
System.out.println(temp.getData());
temp = temp.getNext();
list.addAtEnd("Milan");
list.addAtEnd("Venice");
list.addAtEnd("Munich");
list.addAtEnd("Vienna");
list.display();
Searching in linked list is similar to display operation. To find an element in a linked list, you need to traverse
the list using a temporary reference. If the data is found, the respective node is returned.
The algorithm for searching an element in a linked list is given below.
find(data)
a.If the data at temp is equal to the data being searched for then, return temp
class Node {
this.data = data;
this.data = data;
this.next = node;
return this.data;
}
public Node getNext() {
return this.next;
class LinkedList {
return this.head;
return this.tail;
if (this.head == null)
this.head = this.tail = node;
else {
this.tail.setNext(node);
this.tail = node;
if (this.head == null)
else {
node.setNext(this.head);
this.head = node;
}
public void display() {
System.out.println(temp.getData());
temp = temp.getNext();
if (temp.getData().equals(data))
return temp;
temp = temp.getNext();
return null;
list.addAtEnd("Milan");
list.addAtEnd("Venice");
list.addAtEnd("Munich");
list.addAtEnd("Vienna");
list.display();
if (list.find("Munich") != null)
System.out.println("Node found");
else
Noah needs to change his list and insert Prague after Munich.
To insert an element in a linked list, you first need to find the node after which the new node has to be inserted.
The new node should then be placed after the specific node.
The algorithm to insert an element in a linked list is given below.
insert(data,dataBefore)
b.Make the link of the new node refer to the link of nodeBefore
d.If link of the new node is null, make it as the tail node
class Node {
this.data = data;
this.data = data;
this.next = node;
return this.data;
return this.next;
}
class LinkedList {
return this.head;
return this.tail;
else {
this.tail.setNext(node);
this.tail = node;
if (this.head == null)
else {
// If the list is not empty, add the element at the
beginning
node.setNext(this.head);
this.head = node;
System.out.println(temp.getData());
temp = temp.getNext();
if (temp.getData().equals(data))
return temp;
temp = temp.getNext();
return null;
if (this.head == null)
else {
if (nodeBefore != null) {
node.setNext(nodeBefore.getNext());
nodeBefore.setNext(node);
if (nodeBefore == this.tail)
this.tail = node;
} else
list.addAtEnd("Milan");
list.addAtEnd("Venice");
list.addAtEnd("Munich");
list.addAtEnd("Vienna");
list.insert("Prague", "Munich");
list.display();
To delete an element from a linked list, you first need to find the element and then connect the previous node to
the next node of the node to be deleted.
delete(data):
b. Otherwise,
iii. If the node to be deleted is the tail node, call the nodeBefore as
tail node
class Node {
this.data = data;
}
this.data = data;
this.next = node;
return this.data;
return this.next;
class LinkedList {
private Node head;
return this.head;
return this.tail;
if (this.head == null)
this.tail.setNext(node);
this.tail = node;
if (this.head == null)
else {
this.head = node;
System.out.println(temp.getData());
temp = temp.getNext();
if (temp.getData().equals(data))
return temp;
temp = temp.getNext();
return null;
if (this.head == null)
else {
if (nodeBefore != null) {
// Insert the new node after nodeBefore
node.setNext(nodeBefore.getNext());
nodeBefore.setNext(node);
if (nodeBefore == this.tail)
this.tail = node;
} else
if (this.head == null)
System.out.println("List is empty");
else {
this.head = this.head.getNext();
node.setNext(null);
if (node == this.tail)
tail = null;
} else {
if (temp.getNext() == node) {
nodeBefore = temp;
break;
temp = temp.getNext();
}
nodeBefore.setNext(node.getNext());
if (node == this.tail)
this.tail = nodeBefore;
node.setNext(null);
list.addAtEnd("Milan");
list.addAtEnd("Venice");
list.addAtEnd("Munich");
list.addAtEnd("Prague");
list.addAtEnd("Vienna");
list.display();
System.out.println("--------------------------");
list.delete("Venice");
list.display();
/*
* if(list.find("Munich")!=null) System.out.println("Node
found"); else
*/
}
Stack
class Stack {
private int top; // top represents the index position of the top most element in the stack
private int maxSize; // maxSize represents the maximum number of elements that can be stored
in the stack
Stack(int maxSize) {
this.maxSize = maxSize;
return true;
return false;
}
if (isFull()) {
return false;
} else {
arr[++top] = data;
return true;
class Tester {
System.out.println("Stack created.\n");
if (stack.push(1))
else
System.out.println("Stack is full!\n");
if (stack.push(2))
else
System.out.println("Stack is full!\n");
if (stack.push(3))
System.out.println("Stack is full!\n");
if (stack.push(4))
else
System.out.println("Stack is full!\n");
if (stack.push(5))
else
System.out.println("Stack is full!\n");
Problem Statement
The code given below has the isFull, push, display and peek methods implemented.
Tester class is provided to push the elements. Play around with it and observe the
output.
class Stack {
private int top; // represents the index position of the top most element in the stack
private int maxSize; // represents the maximum number of elements that can be stored in the
stack
Stack(int maxSize) {
this.top = -1; // top is -1 when the stack is created
this.maxSize = maxSize;
return true;
return false;
if (isFull()) {
return false;
} else {
arr[++top] = data;
return true;
return Integer.MIN_VALUE;
else
return arr[top];
class Tester {
System.out.println("Stack created.\n");
if (stack.push(1))
else
System.out.println("Stack is full!\n");
if (stack.push(2))
else
System.out.println("Stack is full!\n");
if (stack.push(3))
else
System.out.println("Stack is full!\n");
if (stack.push(4))
else
System.out.println("Stack is full!\n");
if (stack.push(5))
else
System.out.println("Stack is full!\n");
stack.display();
if (stack.push(6))
System.out.println("The element is pushed to the stack!\n");
else
System.out.println("Stack is full!\n");
A1 a2 a3 a4
} 0 1 2 3 4
ham
Food adress
*ptr Add(food)
address
x=&food