Data Structures and Algorithms (Using C++)
Data Structures and Algorithms (Using C++)
CODE: CS 2201
Students will learn about fundamental computing algorithms, including searching and
sorting; elementary abstract data types including linked lists, stacks, queues and trees; and
elementary algorithm analysis.
COURSE CONTENT
• Sequential representations: arrays and lists, stacks, queues and de-queues, strings,
applications; Link representation: Linear linked lists, Circularly linked lists, Doubly
linked lists, applications.
Recursion
• Design of recursive algorithms, Tail Recursion, when not to use recursion, Removal
of recursion.
• Trees, Binary Trees, Traversals and Threads, Binary Search Trees, Insertion and
Deletion algorithms, Height-balanced and weight-balanced trees, B-trees, B+ -trees,
Applications of trees
Hashing
• Bubble Sort, Selection Sort, Insertion Sort, Quick Sort, Merge Sort, Heap Sort and
Radix Sort.
File Structures
• Sequential and Direct Access; Relative Files; Indexed Files: B+ tree as index; Multi-
indexed Files, Inverted Files, Hashed Files
MODE OF DELIVERY
• Lectures
• Reading assignments
• Practical assignments
• Field trips
• Documentaries
• Flip Charts
• LCD Projectors
COURSE ASSESSMENT
Total 100%
1. Hanley, Koffman (1999). Problem Solving & Program Design in C, 3rd ed., Addison-
Wesley, USA
3. Savitch (2001). Problem Solving with C++: The Object of Programming, 3 rd ed.,
Addison Wesley Longman Inc., USA
Data structure
A data structure is a specialized format for organizing and storing data. General data
structure types include the array, the file, the record, the table, the tree, and so on.
Any data structure is designed to organize data to suit a specific purpose so that it can be
accessed and worked with in appropriate ways.
2.Time Complexity − Running time or the execution time of operations of data structure
must be as small as possible.
As applications are getting complex and data rich, there are three common problems that
applications face now-a-days.
ALGORITHM
Features/properties/characteristics of algorithms.
Not all procedures can be called an algorithm. An algorithm should have the following
characteristics –
1.Unambiguous −Each of its steps (or phases), and their inputs/outputs should be clear and
must lead to only one meaning.
3.Output − An algorithm should have 1 or more well-defined outputs, and should match the
desired output.
Generality: Algorithm is generalized one. It works on all set of inputs and provides the
required output. In other words it is not restricted to a single input value.
(v) Backtracking
3) Testing Phase: After writing an algorithm, it is necessary to check that the algorithm gives
correct result for every valid input.
4) Analyzing Phase: Suppose for a problem P, ten correct algorithms are designed. Now
which one is to be chosen that depends on the performance of them. Mainly this performance
is judged based on how much time and space the algorithm takes. That is after testing phase
of an algorithm it is required to analyze the time complexity and space complexity of it. In
section 2.5 this is discussed in details.
The two approaches which are used to measure the performance of the program are:
a)Space Complexity.
b) Time Complexity
a) SPACE COMPLEXITY
The space complexity can be measured using experimental method, which is done by running
the program and then measuring the actual space occupied by the program during execution.
The program which is written by the user is the source program. When this program is
compiled, a compiled version of the program is generated. For executing the program an
executable version of the program is generated. The space occupied by these three when the
program is under execution, will account for the instruction space.
The space needed by the constants, simple variables, arrays, structures and other data
structures will account for the data space.
• Structure size – It is the sum of the size of component variables of the structure.
• Array size – Total size of the array is the product of the size of the data type and the
number of array locations.
The Environment stack space is used for saving information needed to resume execution of
partially completed functions. That is whenever the control of the program is transferred
from one function to another during a function call, then the values of the local variable of
that function and return address are stored in the environment stack. This information is
retrieved when the control comes back to the same function.
• Return address
b) TIME COMPLEXITY
Time complexity: Time complexity of the program is defined as the amount of computer
time it needs to run to completion
a)Compiler used – some compilers produce optimized code which consumes less time to get
executed. b)Compiler options – The optimization options can be set in the options of the
compiler.
c)Target computer – The speed of the computer or the number of instructions executed per
second differs from one computer to another.
The total time taken for the execution of the program is the sum of the compilation time
and the execution time.
(i) Compile time – The time taken for the compilation of the program to produce the
intermediate object code or the compiler version of the program. The compilation time is
taken only once as it is enough if the program is compiled once. If optimized code is to be
generated, then the compilation time will be higher.
(ii) Run time or Execution time - The time taken for the execution of the program. The
optimized code will take less time to get executed.
c -Compile time
We will be interested in estimating only the execution time as this is the one which varies
according to the user input.
ASYMPTOTIC NOTATIONS
Asymptotic notations are the notations used to describe the behavior of the time or space
complexity.
Let us represent the time complexity and the space complexity using the common function
f(n).
Asymptotic analysis refers to computing the running time of any operation in mathematical
units of computation. For example, the running time of one operation is computed as f(n) and
may be for another operation it is computed as g(n2). This means the first operation running
time will increase linearly with the increase in n and the running time of the second operation
will increase exponentially when n increases. Similarly, the running time of both operations
will be nearly the same if n is significantly small.
O – Big Oh notation
The big Oh notation provides an upper bound for the function f(n).
The function f(n) = O(g(n)) if and only if there exists positive constants c and n 0 such that
f(n) ≤ cg(n) for all n ≥ n 0.
Examples:
1. f(n) = 3n + 2
c = 4
n0 =2
3n + 1 ≤ 4n for all n ≥ 2
2. f(n) = 10n2 + 4n + 2
c = 11
n0 = 6
- Omega notationΩ
The notation gives the lower bound for the function f(n). Ω
The function f(n) = (g(n)) if and only if there exists positive constants Ω c and n 0 such that
f(n) ≥ cg(n) for all n ≥ n 0.
Examples:
1. f(n) = 3n + 2
c = 3
n0 = 0
3n + 1 ≥ 3n for all n ≥ 0
2. f(n) = 10n 2 + 4n + 2
c = 10 n0 = 0
– Theta notationθ
The theta notation is used when the function f(n) can be bounded by both from above and
below the same function g(n).
f(n) = (g(n)) if and only if there exists some positive constants c 1 and c2 and n 0, such that
c1g(n) ≤ f(n) c 2g(n) for all n n ≥ 0.
o - Little Oh notation
For example,
3n + 2 = O(n 2) but 3n + 2 (n ≠ Ω 2)
DATA STRUCTURES
A data structure is said to be linear if its elements form a sequence or a linear list. In a linear
data structure, every data element has a unique successor and predecessor. There are two
basic ways of representing linear structures in memory. One way is to have the relationship
between the elements by means of pointers (links), called linked lists. The other way is using
sequential organization, that is, arrays
Non-linear data structures are used to represent the data containing hierarchical or network
relationship among the elements. Trees and graphs are examples of non-linear data structures.
In non-linear data structures, every data element may have more than one predecessor as well
as successor. Elements do not form any particular linear sequence.
ARRAYS
• The elements of the array can be of any valid type- integers, characters, floating point types
or user-defined types
Types of Array:
Following are some valid array declarations: int age[15]; float weight[50];
int weight[]={55,6,77,5,45,88,96,11,44,32};
float a[]={2,3.5,7.9,-5.9,-8};
char section[4]={‘A’,’B’,’C’,’D’};
char name[10]=”Bhupendra”;
A program to read n numbers and to find the sum and average of those numbers.
#include <iostream>
int main()
int n, i;
cin >> n;
sum += num[i];
average = sum / n;
return 0;
• Creating of an array
• Traversing of an array
• Merging of arrays
Suppose we want to insert 20 in array a, at location with index 4, it means the elements 22
and 90 must shift 1 position downwards as follows.
int i;
n++;
// insert x at pos
arr[pos - 1] = x;
return arr;
int arr[100] = { 0 };
arr[i] = i + 1;
// element to be inserted
pos = 5;
// Insert x at pos
return 0;
Suppose we want to delete the element a[5]=90, then the elements following it were moved
upward by one location as shown in fig. below:
int main()
cout << "Enter the values in an array \n"; // Take an input array
a[i] = a[i+1];
cout<<" "<<a[i];
return 0;
#include<iostream>
int main()
cin>>size;
cin>>arr[i];
j=i-1;//j points to the last element and i points to the first element
i=0;
while(i<j)
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
i++;
j--;
cout<<arr[i]<<"\t";
return 0;
Traversing of an array:
Traversing means to access all the elements of the array, starting from first element upto the
last element in the array one-by-one.
NOTE
Merging means combining elements of two arrays to form a new array. Simplest way of
merging two arrays is the first copy all elements of one array into a third empty array, and
then copy all the elements of other array into third array. Suppose we want to merge two
arrays a[6] and b[4]. The new array says c will be having (6+4) =10 elements as shown in
figure below.
EXAMPLE
#include<iostream>
int main()
cin>>array1;
cin>>arrOne[i];
arrMerge[i] = arrOne[i];
k = i;
cin>>array2;
cin>>arrTwo[i];
arrMerge[k] = arrTwo[i];
k++;
cout<<arrMerge[i]<<" ";
cout<<endl;
return 0;
#include<iostream>
int main()
cin>>n;
cout<<" ";
cin>>arr[i];
cin>>num;
if(arr[i]==num)
cnt=1;
pos=i+1;
break;
if(cnt==0)
else
return 0;
#include <iostream>
#include<conio.h>
#define ARRAY_SIZE 5
int main()
// Read Input
temp = numbers[i];
numbers[i] = numbers[j];
numbers[j] = temp;
cout<<numbers[i]<<endl;
getch();
return 0;
#include<iostream>
int main ()
int num[10];
int i, j, desc;
cout<<" ";
cin>>num[i];
for (i = 0; i < 10; ++i)// 'for' loop is used for sorting the numbers in descending order
desc = num[i];
num[i] = num[j];
num[j] = desc;
cout<<" ";
cout<<num[i];
cout<<"\n";
Two-Dimensional array:
When we declare two dimensional array, the first subscript written is for the number of rows
and the second one is for the column.
int this first example, 3 represents number of rows and 4 represents number of columns.
• Use first subscript to specify row no and the second subscript to specify column no.
• Row-major implementation
• Column-major implementation
EXAMPLE
#include<iostream>
int main()
cout<<" ";
cin>>m1[i][j];
cout<<" ";
cin>>m2[i][j];
m3[i][j]=m1[i][j]+m2[i][j];
cout<<" ";
cout<<m3[i][j]<<" ";
cout<<"\n";
return 0;
• one way is we can store the elements in sequential memory locations. That
means we can store the list in arrays.
• The other way is we can use pointers or links to associate elements sequentially. This
is known as linked list.
LINKED LISTS
The linked list is very flexible dynamic data structure : items may be added to it or deleted
from it at will. A programmer need not worry about how many items a program will have to
accommodate in advance. This allows us to write robust programs which require much less
maintenance.
A singly linked list, or simply a linked list, is a linear collection of data items. The linear
order is given by means of POINTERS. These types of lists are often referred to as linear
linked list.
2. Next address- contains the address of the next item in the list.
The last node in the list contains NULL pointer to indicate that it is the end of the list
2. Within the structure body declare the variable(s) of each node that will contain information
and the pointer of each node.
3. Declare the external pointer and the node(s) of that structure type. A node may contain any
number of information fields.
Declaration syntax
struct node {
int data;
struct node *next;
}
example
Struct slinklist
int data;
};
• Creation
• Insertion of a node
• Deletions of a node
• Traversing the list
Creating a singly linked list starts with creating a node. Sufficient memory has to be allocated
for creating a node. The information is stored in the memory, allocated by using the new ()
function. The function getnode(), is used for creating a node, after allocating memory for the
node, the Information for the node at a path as to be read from the user and set next field to
NULL and finally return the node.
node* getnode()
node* newnode;
return newnode;
Void createlist(int n)
{
int i;
node *newnode;
node *temp;
for(i = 0; i< n ; i++)
{
newnode = getnode();
if(start = = NULL)
{
start = newnode;
}
else
{
temp = start;
while(temp -> next != NULL)
temp = temp -> next;
temp -> next = newnode;
}
}
}
1. Get the new node using getnode() then new node = getnode();
head = newnode;
head is the pointer variable which contains address of the first node and temp
contains address of new node to be inserted then sample code is
node *newnode;
newnode = getnode();
if(start == NULL)
start = newnode;
else
start = newnode;
newNode->data = num;
/* Next pointer of new node will point to head node of linked list */
newNode->next = head;
head = newNode;
cout<<"Inserted Element"<<num;
head is the pointer variable which contains address of the first node and temp
contains address of new node to be inserted then sample code is
Void insert_at_end()
{
node *newnode, *temp;
newnode = getnode();
if(start == NULL)
{
start = newnode;
}
else
{
temp = start;
while(temp -> next != NULL)
temp = temp -> next;
temp -> next = newnode;
}
}
example
Void insert_at_mid()
{
node *newnode, *temp, *prev;
int pos, nodectr, ctr = 1;
newnode = getnode();
cout<< Enter the position;
cin>>pos;
Include <iostream>
using namespace std;
void initialize(){
head = NULL;
}
Inserts a node in front of a singly linked list.
*/
void insertAtFront(int num) {
/* Create a new Linked List node */
struct node* newNode =new node;
newNode->data = num;
/* Next pointer of new node will point to head node of linked list */
newNode->next = head;
/* make new node as new head of linked list */
head = newNode;
cout<<"Inserted Element"<<num;
}
the list:
2.If the list is not empty, follow the steps given below:
temp = start;
delete temp;
EXAMPLE
void delete_at_beg()
node *temp;
if(start == NULL)
return ;
else
temp = start;
delete temp;
cout<<Node deleted;
The following steps are followed to delete a node at the end of the list:
prev = temp;
delete temp;
EXAMPLE
Void delete_at_last()
if(start == NULL)
cout<<Empty List;
return ;
else
temp = start;
prev = start;
prev = temp;
delete temp;
cout<<Node deleted;
The following steps are followed, to delete node from the specified
if(pos> 1 &&pos<nodectr) {
ctr = 1;
while(ctr<pos) {
prev = temp;
ctr++;
delete temp;
cout<<node deleted;
EXAMPLE
Void delete_at_mid()
if(start == NULL)
cout<<Empty List;
return ;
else
cin>>pos;
nodectr = countnode(start);
if(pos>nodectr)
if(pos> 1 &&pos<nodectr) {
prev = temp;
ctr ++;
delete temp;
cout<<Node deleted;
else
cout<<Invalid position;
node by node from the first node, until the end of the list is reached.
EXAMPLE
void traverse()
node *temp;
temp = start;
if(start == NULL )
cout<<Empty List;
else
cout<<X;
The main advantage of a doubly linked list is that, they permit traversing or searching of the
list in both directions.
Before writing the code to build the list, we need to create a start node, used to create and
access other nodes in the linked list.
• Creating a structure with one data item and a right pointer, which will
be pointing to next node of the list and left pointer pointing to the previous node. This is
called as self-referential structure.
Struct dlinklist
int data;
};
The different operations performed on the doubly linked list are listed as follows.
• Creation
• Insertion
• Deletion
• Traversing
• Display
Creating a doubly linked list starts with creating a node. Sufficient memory has to be
allocated for creating a node. The information is stored in the memory, allocated by using the
new() function.
The function getnode(),is used for creating a node, after allocating memory for the node, the
information for the node data part has to be read from the user and set left and right field to
NULL and finally return the node.
node* getnode()
node* newnode;
cin>>newnode-> data
newnode = getnode();
start = newnode;
• The left field of the new node is made to point the previous node.
• The previous nodes right field must be assigned with address of the new node.
5. Repeat the above steps „n‟ times.
void createlist(int n)
int i;
node *newnode;
node *temp;
newnode = getnode();
if(start = = NULL)
start = newnode;
else
temp = start;
INSERTION OF A NODE
One of the most important operations that can be done in a doubly linked list is the insertion
of a node . Memory is to be allocated for the new node before reading the data .The new node
will contain empty data field and empty next field. The data field of the new node is then
stored with the information read from the user .The left and right fields of the new node are
set to NULL. The new node can then be inserted at three different places
namely:
The following steps are to be followed to insert a newnode at the beginning of the list:
newnode = getnode();
EXAMPLE
void insertion_beginning()
int item;
if(ptr == NULL)
cout<<"\nOVERFLOW";
else
cin>>item;
if(head==NULL)
ptr->next = NULL;
ptr->prev=NULL;
ptr->data=item;
head=ptr;
else
ptr->data=item;
ptr->prev=NULL;
head->prev=ptr;
head=ptr;
cout<<"\nNode inserted\n";
The following steps are followed to insert a newnode at the end of the
list:
temp = start;
void insertion_last()
int item;
if(ptr == NULL)
else
cout<<"\nEnter value";
cin>>item;
ptr->data=item;
if(head == NULL)
ptr->next = NULL;
ptr->prev = NULL;
head = ptr;
else
temp = head;
while(temp->next!=NULL)
temp = temp->next;
temp->next = ptr;
ptr ->prev=temp;
ptr->next = NULL;
cout<<"\nnode inserted\n";
EXAMPLE
2.Ensure that the specified position is in between first node and last node. If
3.Store the starting address (which is in start pointer)in temp and prev
pointers. Then traverse the temp pointer up to the specified position followed
by prev pointer.
4. After reaching the specified position, follow the steps given below:
EXAMPLE
void insertion_specified()
int item,loc,i;
if(ptr == NULL)
cout<<"\n OVERFLOW";
else
temp=head;
cin>>loc;
for(i=0;i<loc;i++)
temp = temp->next;
if(temp == NULL)
return;
cout<<"Enter value";
cin>>item;
ptr->data = item;
ptr->next = temp->next;
temp->next = ptr;
temp->next->prev=ptr;
cout<<"\nnode inserted\n";
Another operation that can be done in a doubly linked list is the deletion of a node. Memory
is to be released for the node to be deleted. A node can be deleted from the list from three
different places.
The following steps are followed ,to delete a node at the beginning of
the list:
2.If the list is not empty, follow the steps given below:
temp = start;
delete temp;
EXAMPLE
void deletion_beginning()
if(head == NULL)
head = NULL;
delete head;
cout<<"\nnode deleted\n";
else
ptr = head;
delete ptr;
cout<<"\nnode deleted\n";
The following steps are followed to delete a node at the end of the list:
temp = start;
delete temp;
void deletion_last()
if(head == NULL)
cout<<"\n UNDERFLOW";
head = NULL;
delete head;
cout<<"\nnode deleted\n";
else
ptr = head;
if(ptr->next != NULL)
delete ptr;
cout<<"\nnode deleted\n";
The following steps are followed,to delete a node from the specified position in
the list.
if(pos> 1 &&pos<nodectr) {
temp = start;ctr= 1;
while(ctr<pos) {
ctr++;
delete temp;
EXAMPLE
void deletion_specified()
int val;
cout<<"\n Enter the data after which the node is to be deleted : ";
cin>>val;
ptr = head;
else
delete temp;
cout<<"\nnode deleted\n";
To display the information, you have to traverse the list, node by node from the first node
,until the end of the list is reached .The function traverse_left_right() is used for traversing
and displaying the information stored in the list from left to right. The following steps are
followed, to traverse a list from left to right:
temp = start;
while(temp != NULL)
void display()
ptr = head;
while(ptr != NULL)
cout<<ptr->data;
ptr=ptr->next;
To display the information from right to left, you have to traverse the list, node by node from
the first node, until the end of the list is reached. The function traverse_right_left() is used for
traversing and displaying the information stored in the list from right to left .The following
steps are followed, to traverse a list from right to left:
temp = start;
while(temp != NULL)
#include<iostream>
struct node
int data;
};
void insertion_beginning();
void insertion_last();
void insertion_specified();
void deletion_beginning();
void deletion_last();
void deletion_specified();
void display();
void search();
int main ()
while(choice != 9)
cout<<"\n*********Main Menu*********\n";
cout<<"\n===============================================\n";
cin>>choice;
switch(choice)
case 1:
insertion_beginning();
break;
case 2:
insertion_last();
break;
case 3:
insertion_specified();
break;
case 4:
deletion_beginning();
break;
case 5:
deletion_last();
break;
case 6:
deletion_specified();
break;
search();
break;
case 8:
display();
break;
case 9:
exit(0);
break;
default:
void insertion_beginning()
int item;
if(ptr == NULL)
cout<<"\nOVERFLOW";
else
cin>>item;
ptr->next = NULL;
ptr->prev=NULL;
ptr->data=item;
head=ptr;
else
ptr->data=item;
ptr->prev=NULL;
ptr->next = head;
head->prev=ptr;
head=ptr;
cout<<"\nNode inserted\n";
void insertion_last()
int item;
if(ptr == NULL)
else
cout<<"\nEnter value";
cin>>item;
ptr->data=item;
if(head == NULL)
ptr->next = NULL;
ptr->prev = NULL;
head = ptr;
else
temp = head;
while(temp->next!=NULL)
temp = temp->next;
temp->next = ptr;
ptr ->prev=temp;
ptr->next = NULL;
cout<<"\nnode inserted\n";
void insertion_specified()
int item,loc,i;
if(ptr == NULL)
cout<<"\n OVERFLOW";
else
temp=head;
cin>>loc;
for(i=0;i<loc;i++)
temp = temp->next;
if(temp == NULL)
return;
cout<<"Enter value";
cin>>item;
ptr->data = item;
temp->next = ptr;
temp->next->prev=ptr;
cout<<"\nnode inserted\n";
void deletion_beginning()
if(head == NULL)
head = NULL;
delete head;
cout<<"\nnode deleted\n";
else
ptr = head;
delete ptr;
cout<<"\nnode deleted\n";
void deletion_last()
if(head == NULL)
cout<<"\n UNDERFLOW";
head = NULL;
delete head;
cout<<"\nnode deleted\n";
else
ptr = head;
if(ptr->next != NULL)
delete ptr;
cout<<"\nnode deleted\n";
void deletion_specified()
int val;
cout<<"\n Enter the data after which the node is to be deleted : ";
cin>>val;
ptr = head;
cout<<"\nCan't delete\n";
else
delete temp;
cout<<"\nnode deleted\n";
ptr = head;
while(ptr != NULL)
cout<<ptr->data;
ptr=ptr->next;
void search()
int item,i=0,flag;
ptr = head;
if(ptr == NULL)
cout<<"\nEmpty List\n";
else
cin>>item;
while (ptr!=NULL)
if(ptr->data == item)
flag=0;
break;
else
flag=1;
i++;
if(flag==1)
c) CIRCULAR LISTS
Circular linked list is a linked list which consists of collection of nodes each of which has two
parts, namely the data part and the next part. The data part holds the value of the element and
the next part has the address of the next node. The last node of list has the next pointing to the
first node thus making the circular traversal possible in the list.
It is just a single linked list in which the next field of the last node points back to the address
of the first node. A circular linked list has no beginning and no end. In circular linked list no
null pointers are used, hence all pointers contain valid address.
Creating a circular linked list starts with creating a node. Sufficient memory has to be
allocated for creating a node. The information is stored in the memory, allocated by using the
new() function. The function getnode(),is used for creating a node, after allocating memory
for the node, the information for the node data part has to be read from the user and set next
field to NULL and finally return the node.
node* getnode()
node* newnode;
cin>>newnode-> data
return newnode;
newnode = getnode();
start = newnode;
temp = start;
EXAMPLE
Void createlist(int n)
inti;
node *newnode;
node *temp;
newnode = getnode();
if(start = = NULL)
start = newnode;
temp = start;
newnode = getnode();
start = newnode;
last = start;
start = newnode;
The following steps are followed to insert a new node at the end of the
list:
newnode = getnode();
start = newnode;
temp = start;
#include<iostream>
struct node
int data;
};
void randominsert();
void begin_delete();
void last_delete();
void random_delete();
void display();
void search();
int main ()
while(choice != 7)
cout<<"\n*********Main Menu*********\n";
cout<<"\n===============================================\n";
cin>>choice;
switch(choice)
case 1:
beginsert();
break;
case 2:
lastinsert();
break;
case 3:
begin_delete();
break;
case 4:
last_delete();
break;
case 5:
search();
break;
case 6:
display();
break;
case 7:
exit(0);
break;
void beginsert()
int item;
if(ptr == NULL)
cout<<"\nOVERFLOW";
else
cin>>item;
if(head == NULL)
head = ptr;
else
temp = head;
temp = temp->next;
ptr->next = head;
head = ptr;
cout<<"\nnode inserted\n";
void lastinsert()
int item;
if(ptr == NULL)
cout<<"\nOVERFLOW\n";
else
cout<<"\nEnter Data?";
cin>>item;
ptr->data = item;
if(head == NULL)
head = ptr;
temp = head;
cout<<"\nnode inserted\n";
void begin_delete()
if(head == NULL)
cout<<"\nUNDERFLOW";
head = NULL;
delete head;
cout<<"\nnode deleted\n";
else
ptr->next = head->next;
delete head;
head = ptr->next;
cout<<"\nnode deleted\n";
void last_delete()
if(head==NULL)
cout<<"\nUNDERFLOW";
head = NULL;
delete head;
cout<<"\nnode deleted\n";
else
ptr = head;
ptr = ptr->next;
delete ptr;
cout<<"\nnode deleted\n";
void search()
int item,i=0,flag=1;
ptr = head;
if(ptr == NULL)
cout<<"\nEmpty List\n";
else
cin>>item;
flag=0;
else
if(ptr->data == item)
flag=0;
break;
else
flag=1;
i++;
if(flag != 0)
void display()
ptr=head;
cout<<"\nnothing to print";
else
A stack is an ordered collection of items into which new items may be inserted and from which items
may be deleted at one end, called the top of the stack. The deletion and insertion in a stack is done
from top of the stack. The following fig shows the stack containing items
This end is often known as top of stack. When an item is added to a stack, the operation is called
push, and when an item is removed from the stack the operation is called pop. Stack is also called as
Last- InFirst- Out (LIFO) list.
Operations on Stack:
PUSH operation:
The push operation is used to add (or push or insert) elements in a stack.
When we add an item to a stack, we say that we push it onto the stack .
I.e. top=Max
The pop operation is used to remove or delete the top element from the stack.
We may notice that the last item pushed onto a stack is always the first that will be popped from the
stack. That is why stack is called last in, first out or LIFO in short.
Since a stack usually holds a bunch of items with the same type, we could implement a stack as an
array. Consider how we could have an array of characters, contents, to hold the contents of the
stack, and an integer top that holds the index of the element at the top of the stack.
We choose the array to be of size 4 for now. Starting with an empty stack, we have:
void push()
int x;
if(top == max-1)
else
cin>>x;
item[ ++top]=x;
I.e. top=-1
void pop()
int x;
if(top ==-1)
else
x = item[ top--];
Peep ():or peek() Peep is nothing but display the elements at the top of stack
I.e. top=-1
int peek()
int i;
if(top ==-1)
else
item[top];
#include<iostream>
#define max 5
int top=-1;
int item[max];
int main( )
void push();
void pop();
int peek();
void display();
int n;
top=-1;
cout<<"\n 1. push";
cout<<"\n 2. pop";
cout<<"\n 3. peek";
cout<<"\n 4. display";
cout<<"\n 5. exit";
cout<<endl<<"choice :";
cin>>n;
switch(n)
case 1: push();
break;
case 2: pop();
break;
case 3: peek();
break;
void push()
int x;
if(top == max-1)
else
cin>>x;
item[ ++top]=x;
void pop()
int x;
if(top ==-1)
else
x = item[ top--];
void display()
int i;
if(top>=0)
cout<<item[i]<<"";
cout<<"\n";
else
cout<<"stack is empty";
int peek()
int i;
if(top ==-1)
else
item[top];
The linked-list implementation is equally simple and straightforward. In fact, a stack linked-list is
much simpler than most linked-list implementations: it requires that we implement a linked-list
where only the head node or element can be removed, or popped, and a node can only be inserted
by becoming the new head node.
Unlike the array implementation, our structure typedef corresponds not to the entire stack
structure, but to a single node:
struct stack
int data;
stack
Using a linked list is one way to implement a stack so that it can handle essentially any number of
elements.
Push (): operation both initializes an empty stack, and adds a new node to a non-empty one. It works
by receiving a data value to push onto the stack, along with a target stack, creating a new node by
allocating memory for it, and then inserting it into a linked list as the new head.
Here is what a linked list implementing a stack with 3 elements might look like:
Pop (): operation removes the head from the linked list, and assigns the pointer to the head to the
previous second node. It check whether the list is empty before popping from it:
#include<iostream>
struct node
int info;
*top,*top1,*temp;
int topelement();
void pop();
void empty();
void display();
void destroy();
void stack_count();
void create();
int count = 0;
int main()
cout<<"\n 1 - Push";
cout<<"\n 2 - Pop";
cout<<"\n 3 - Top";
cout<<"\n 4 - Empty";
cout<<"\n 5 - Exit";
create();
while (1)
cin>>ch;
switch (ch)
case 1:
cin>>no;
push(no);
break;
case 2:
pop();
break;
case 3:
if (top == NULL)
else
e = topelement();
case 4:
empty();
break;
case 5:
exit(0);
case 6:
display();
break;
case 7:
stack_count();
break;
case 8:
destroy();
break;
default :
break;
void create()
top = NULL;
void stack_count()
if (top == NULL)
top->ptr = NULL;
top->info = data;
else
temp->ptr = top;
temp->info = data;
top = temp;
count++;
top1 = top;
if (top1 == NULL)
cout<<"Stack is empty";
return;
cout<<top1->info<<endl;
top1 = top1->ptr;
void pop()
top1 = top;
if (top1 == NULL)
return;
top1 = top1->ptr;
delete top;
top = top1;
count--;
int topelement()
return(top->info);
void empty()
if (top == NULL)
else
void destroy()
top1 = top;
top1 = top->ptr;
delete top;
top = top1;
top1 = top1->ptr;
delete top1;
top = NULL;
count = 0;
Applications of Stack:
void recurse()
... .. ...
recurse();
... .. ...
int main()
... .. ...
recurse();
... .. ...
#include <iostream>
int main() {
cin>>number;
result = sum(number);
cout<<result;
return 0;
int sum(int n) {
if (n != 0)
return n + sum(n-1);
else
return n;
Initially, the sum() is called from the main() function with number passed as an argument.
Suppose, the value of n inside sum() is 3 initially. During the next function call, 2 is passed to
the sum() function. This process continues until n is equal to 0.
When n is equal to 0, the if condition fails and the else part is executed returning the sum of integers
ultimately to the main() function.
EXAMPLE 2
#include<iostream>
int main()
cin>>number;
int x=1;
return(1);
else
x = a * fact(a-1); /* Function Call Recursively as the fact() calls itself in the program */
return(x);
The output generated here from the code mentioned above would be: Please enter a non-
negative number here: 5
5! = 120
EXAMPLE 3
#include <iostream>
int fib(int n)
// Stop condition
if (n == 0)
return 0;
// Stop condition
if (n == 1 || n == 2)
return 1;
else
int main()
// Initialize variable n.
int n = 8;
cout<<fib(i)<<endl;
return 0;
Recursion makes program elegant. However, if performance is vital, use loops instead as recursion is
usually much slower.
That being said, recursion is an important concept. It is frequently used in data structure and
algorithms For example, it is common to use recursion in problems such as tree traversal.
A Queue is an ordered collection of items from which items may be deleted at one end
(called the front of the queue and into which items may be inserted at the other end (the
rear of the queue.
To understand a queue, think of a cafeteria line: the person at the front is served first, and
people are added to the line at the back. Thus, the first person in line is served first, and the
last person is served last.
This can be abbreviated to First In, First Out (FIFO).
The cafeteria line is one type of queue. Queues are often used in programming networks,
operating systems, and other situations in which many different processes must share
resources such as CPU time.
When inserting for the very first time, we need to adjust in position of front from zero to 1
Queue operations may involve initializing or defining the queue, utilizing it, and then completely
erasing it from the memory. Here we shall try to understand the basic operations associated with
queues −
Few more functions are required to make the above-mentioned queue operation efficient. These are
−
peek() − Gets the element at the front of the queue without removing it.
1. Two pointers called FRONT and REAR are used to keep track of the first and last elements in the
queue.
2. When initializing the queue, we set the value of FRONT and REAR to 0.
3. On enqueing an element, we increase the value of REAR index and place the new element in the
position pointed to by REAR.
4. On dequeueing an element, we return the value pointed to by FRONT and increase the FRONT
index.
8. When dequeing the last element, we reset the values of FRONT and REAR to 0.
One of the most common way to implement a queue is using array. An easy way to do so is to define
an array Queue, and two additional variables front and rear.
Elements are always removed from the front. After removing the element, front is incremented by
one. Fig. 11.1 f shows status of front and rear after two deletions from Fig. 11.1d. Observe that
positions vacated by front marked as * are unusable by queue any further.
This is one of the major draw back of linear queue array representation. In Fig. 11.1 g, we have
carried out three deletions for 25,35,and 45. after deleting 45, we find queue is empty and the
condition for this queue state is q.rear is less than q.front. At this stage, we can reinitialize the queue
by setting q.front=0 and q.rear = -1 and thus reclaim the unused positions marked with *.
void insertion() {
if(rear==max-1)
else {
cin>>queue[rear++];
void deletion() {
if(front>rear-1) {
else
x++;