You are on page 1of 132

COMPUTER LABORATORY MANUAL

Data Structure and Algorithms


Version 1.3

DEPARTMENT OF SOFTWARE ENGINEERING (DSE)


FOUNDATION UNIVERSITY RAWALPINDI CAMPUS (FURC)
www.fui.edu.pk
http://www.fui.edu.pk/FURC/

1 Data Structure and Algorithms Lab Manual


PREFACE
To learn a subject such as computer science, you need to immerse yourself in it - learning by doing
rather than by simply observing. Through the study of several classic data structures and algorithms,
you will become a better informed and more knowledgeable computer science student and
programmer. To be able to professionally choose the best algorithm and data structure for a
particular set of resource constraints takes practice.
An emphasis on learning by doing is used throughout Data Structures through Java: a laboratory
manual. In each laboratory, you explore a particular data structure by implementing it. As you create
an implementation, you learn how the data structure works and how it can be applied. The resulting
implementation is a working piece of software that you can use in later laboratories and
programming projects.
One cannot learn to program just by reading a book. It is a skill that must be developed by practice.
Nevertheless, the best practitioners study the works of others and incorporate their observations into
their own practice. I firmly believe that after learning the fundamentals of program writing, students
should be exposed to examples of complex, yet well-designed program objects so that they can learn
about the designing good software.
This laboratory manual includes the programs relating to Overview of Java and Data Structures.

PREPARED BY
Lab manual is prepared by Mr. Aqib Rehman under the supervision of Head of Department, Dr.
Muhammad Shaheen.

GENERAL INSTRUCTIONS
a. Students are required to maintain the lab manual with them till the end of the semester.
b. All readings, answers to questions and illustrations must be solved on the place provided. If more
space is required then additional sheets may be attached.
c. It is the responsibility of the student to have the manual graded before deadlines as given by the
instructor.
d. Loss of manual will result in re-submission of the complete manual.
e. Students are required to go through the experiment before coming to the lab session.
f. Students must bring the manual in each lab.
g. Keep the manual neat clean and presentable.
h. Plagiarism is strictly forbidden. No credit will be given if a lab session is plagiarised and no re-
submission will be entertained.
i. Marks will be deducted for late submission.
j. You need to submit the report even if you have demonstrated the exercises to the lab instructor or
shown them the lab report during the lab session.

VERSION HISTORY
Date Update By Details
Fall 2019 Version 1.0
Sep 2019 Aqib Rehman Version 1.1. Designed in Java language
Sep 2019 Aqib Rehman Version 1.2. Formating, Experiments are added,
Exercises are added
Fall 2019 Ms. Aania Majeed Version 1.3. Complex Problems added
Dr. Muhammad Asif

2 Data Structure and Algorithms Lab Manual


MARKS

LAB Date Lab Title Max. Marks Instructor


# Conducted Marks Obtained Sign
1 Overview of Java Language and 10
Measuring Execution Time of Java
Program
2 Arrays (Static, Dynamic and Multi- 10
dimensional)
3 Array based Stack implementation 10

4 Array based Queues 10


implementation
5 Circular and Priority Queues 10

6 Singly Link List 10

7 Doubly Link List 10

8 Semester Project Proposal 10

9 Binary Trees, Binary Tree Traversals 10


and Level Order Traversal
10 Binary Search Trees 10

11 Balanced Trees 10

12 Dictionary using Hashing 10

13 Dictionary using Hashing and 10


HashTable
14 Heap 10

15 Graphs, Graph Traversals and Memory 10


Management
16 Semester Project Final

Grand Total

3 Data Structure and Algorithms Lab Manual


LIST OF LAB TASKS

LAB TASK 1 – Overview of Java Language and Measuring Execution Time of Java Program ... 5
LAB TASK 3 – Array based Stack implementation ..................................................................... 23
LAB TASK 4 – Array based Queue implementation ................................................................... 31
LAB TASK 5 – Circular Queue and Implementation of Deque using circular array ................... 40
LAB TASK 6 – Singly Link List .................................................................................................. 52
LAB TASK 7 – Doubly Link List................................................................................................. 63
LAB TASK 8 – SEMESTER PROJECT GUIDELINES ............................................................. 74
LAB TASK 9 – Binary Trees, Binary Tree Traversals and Level Order Traversal ...................... 77
LAB TASK 10 – Binary Search Trees .......................................................................................... 90
LAB TASK 11 – Balanced Trees .................................................................................................. 96
LAB TASK 13 – Dictionary using Hashing and HashTable ...................................................... 104
LAB TASK 14 – Heap ................................................................................................................ 113
LAB TASK 15 – Graphs using Adjacency list and Adjacency Matrix and Memory Management118
LAB TASK 16 – SEMESTER PROJECT PRESENTATION ................................................... 128

4 Data Structure and Algorithms Lab Manual


LAB TASK 1 – Overview of Java Language and Measuring Execution Time of Java
Program

Name / Group ID: Reg. No:

Class / Section: Date: _

Time Required : 3 hrs


Programming Language : Java
Software Required : Netbeans
Hardware Required : Computer System

Overview of Java
This section introduces the students to elementary Java. Java is a vast computer language and
programming environment, it is not possible to touch upon all Java-related issues. This section
introduces only those aspects of Java that are necessary for understanding the Java code offered
in this book. Java program examples presented in this section give you to implement data
structures.

What is an Algorithm?
An algorithm is a technique for solving a problem or performing an analysis. Algorithms act as
an accurate list of instructions that execute specified actions step by step in either hardware or
software-based practices. Algorithms are widely used throughout all regions of IT.

Overview of data structures


There are certain types of containers that are used to store data. These containers are nothing but
data structures. These containers have different properties associated with them, which are used
to store, organize, and manipulate the data stored in them.
There can be two types of data structures based on how they allocate the data. Linear data
structures like arrays and linked lists and dynamic data structures like trees and graphs.

Difference between Linear and Non-linear data structures


In linear data structures, each element is linearly connected to each other having reference to the
next and previous elements whereas in non-linear data structures, data is connected in a non-
linear or hierarchical manner.
Implementing a linear data structure is much easier than a non-linear data structure since it
involves only a single level. If we see memory-wise then the non-linear data structures are better
than their counterpart since they consume memory wisely and do not waste it.

Types of Data Structure


 Arrays
 Linked Lists
 Stacks
 Queues
 Trees
 Hash tables
 Graphs

5 Data Structure and Algorithms Lab Manual


Quadratic equation
Write a Java program that prints all real solutions to the quadratic equation ax2 + bx + c = 0. Read in
a, b, c and use the quadratic formula. If the discriminant (b2– 4ac) is negative; display a message
stating that there are no real solutions.
The roots of the quadratic equation, ax2 + bx + c = 0 are given by:
x = [–b ± √(b2 – 4ac) ]/2a
The discriminant, d = (b2 – 4ac)
Case (1): When d is greater than zero, the two roots are real.
x1 = (–b + √d )/2a and x2 = (–b – √d )/2a
Case (2): When d is equal to zero, the two roots are equal.
x1 = x2 = – b /2a
Case (3): When d is less than zero, the two roots are imaginary. Each of the two roots has two
parts: real-part-1, imaginary-part-1 and real-part-2, imaginary-part-2.
real-part-1, xr1 = –b/2a imaginary-part-1, xi1 = +√d /2a
real-part-2, xr2 = –b/2a imaginary-part-2, xi2 = –√d /2a

Program: Roots of a quadratic equation

import java.lang.Math;
import java.util.Scanner;
class QuadraticEquation
{
double a, b, c; // coefficients
QuadraticEquation( double a, double b, double c)

6 Data Structure and Algorithms Lab Manual


{
this.a = a;
this.b = b;
this.c = c;
}
public void roots()
{
if( a == 0.0 )
{ System.out.println("One root = " + (-c/b));
return;
}
double d = b*b - 4.0*a*c;
if(d < 0) // Roots are imaginary
{
System.out.println("There are no real solutions."); return;
}
if(d == 0)
{
// Roots are equal
System.out.println("Two roots are equal: " + (-b /(2.0*a))); return;
}
// Roots are real
double x1 = (-b + Math.sqrt(d))/(2.0*a);
double x2 = (-b - Math.sqrt(d))/(2.0*a);
System.out.println("Roots are: " + x1 + ", " + x2);
}
}
//////////////////// QuadraticEquationDemo.java /////////////////
class QuadraticEquationDemo
{
public static void main(String[] args)
{
Scanner scr = new Scanner(System.in);
System.out.print(" a = ");
double a = scr.nextDouble();
System.out.print(" b = ");
double b = scr.nextDouble();
System.out.print(" c = ");
double c = scr.nextDouble();
QuadraticEquation qe = new QuadraticEquation(a, b, c);

qe.roots();
}
}

Output:

7 Data Structure and Algorithms Lab Manual


a=0
b=4
c=1
One root = -0.25
a=1
b=4
c=4
Two roots are equal: -2.0
a=1
b=4
c=8
There are no real solutions
a=1
b=4
c=3

Roots are: -1.0, -3.0

Prime numbers
A prime number is a positive integer that is exactly divisible only by 1 and itself. The first few
prime numbers are:

2 3 5 7 11 13 17 23 29 31 37…

All primes apart from 2 are odd.


As a starting point in developing the prime number generator let us explore how we can establish
whether or not a particular number is a prime. To do this, let us consider a number 13. The definition
of prime number suggests that to determine whether or not 13 is prime, we need to divide it in turn
by the set of numbers 2, 3, 4, 5 …12. If any of these numbers divide into 13 without remainder we
will know it cannot be prime number. Therefore, to test an integer n for prime, n-2 calls to the mod
operation are required. As our n is 13, we need 11 calls. As n grows, the cost of making these
divisions and tests is going to get very expensive. We must therefore look for ways of improving the
efficiency of the algorithm. Firstly, we can try to keep to a minimum the number of numbers that we
have to test for primes, and secondly we can try to improve the efficiency of testing a number for
prime.

Following up these suggestions, we know that apart from 2, we do not need to examine any of the
even numbers, and only first half of the numbers is enough for testing prime. That is, we can test for
mod operation with numbers, from 3 to n/2. Hence, the following set of numbers is sufficient to test
13 for prime.
3 4 5 6

8 Data Structure and Algorithms Lab Manual


Program : Prime numbers

import java.io.*;
class PrimeNumber
{
public void primes(int n)
{
int k, m;
System.out.print("Prime numbers up to " + n + ": 2 3");
for(m=3; m <= n; m = m+2)
{
boolean isPrime = false;
for(k=2; k <= m/2; k++)
{
if(m % k == 0) { isPrime = false; break; }
else isPrime = true;
}
if(isPrime) System.out.print(" " + m);
}
}
}
////////////////////////// PrimeNumberDemo.java /////////////////
class PrimeNumberDemo
{
public static void main(String[] args) throws IOException {
PrimeNumber pn = new PrimeNumber();
BufferedReader kb = new
BufferedReader(new InputStreamReader(System.in));
System.out.print("Enter n: ");
int n = Integer.parseInt(kb.readLine());
pn.primes(n);
}
}
Output:
Enter n: 50
Prime numbers up to 50: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47

Palindrome

“MADAM” is a palindrome.
A string is an array of characters. For example, the string “MADAM” is stored as follows:

[0] [1] [2] [3] [4]


M A D A M

9 Data Structure and Algorithms Lab Manual


Java supports the manipulation of character data through the primitive data type char and the
associated operations for the input, output, assignment, and comparison of characters. Most
applications of character data require character sequences - or strings - rather than individual
characters. In Java a string is represented by the built-in class String. However, manipulating a
String data type in Java is quite different from manipulating a set (or array) of characters. In the
Java, strings are objects. The Java platform provides the String class to create and manipulate
strings. The most direct way to create a string is to write:
String str = "MADAM";

In this case, "MADAM" is a string literal - a series of characters that is enclosed in double quotes.
The String class provides the method length(), which returns as an int value the number of characters
in the String object. The method of the String class
char charAt(int n)

returns the nth character in a string (where n must be less than string length);

If the first character is equal to the last character of the string, second character is equal to the second
one from the last character of the string, and so on, then the string is a palindrome.

Program 4: Palindrome

class Palindrome
{
public boolean isPalindrome(String str)
{
System.out.print("Given string: " + str);
int n = str.length();
boolean flag = true;
for( int i=0; i < n/2; i++ )
if( str.charAt(i) != str.charAt(n-i-1) ) flag = false; return flag;

}
}
////////////////////////// PalindromeDemo.java ////////////////////
class PalindromeDemo
{
public static void main(String[] args)
{

Palindrome pal = new Palindrome();

String str = "MADAM";


if( pal.isPalindrome(str))
System.out.print(" is a palindrome.");
else
System.out.print(" is not a palindrome.");

10 Data Structure and Algorithms Lab Manual


}
}

Output:
Given string: MADAM is a palindrome.

Execution Time in Java

class TimeTest1 {
public static void main(String[] args) {

long startTime = System.currentTimeMillis();

long total = 0;
for (int i = 0; i < 10000000; i++) {
total += i;
}

long stopTime = System.currentTimeMillis();


long elapsedTime = stopTime - startTime;
System.out.println(elapsedTime);
}
}
Difference Between Linear Search and Binary Search
The major difference between linear search and binary search is that binary search takes less time to
search an element from the sorted list of elements. So it is inferred that efficiency of binary search
method is greater than linear search. Another difference between the two is that there is a prerequisite
for the binary search, i.e., the elements must be sorted while in linear search there is no such
prerequisite. Although both the searching methods use different techniques which are discussed below.

1. Linear search is iterative in nature and uses sequential approach. On the other hand, Binary
search implements divide and conquer approach.
2. The time complexity of linear search is O(N) while binary search has O(log2N).
3. The best case time in linear search is for the first element i.e., O(1). As against, in binary
search, it is for the middle element, i.e., O(1).
4. In the linear search, worst case for searching an element is N number of comparison. In
contrast, it is log2N number of comparison for binary search.
5. Linear search can be implemented in an array as well as in linked list whereas binary search
can not be implemented directly on linked list.
6. As we know Binary search requires the sorted array that is reason It requires processing to
insert at its proper place to maintain a sorted list. On the contrary linear search does not require
sorted elements, so elements are easily inserted at the end of the list.
7. Linear search is easy to use, and there is no need for any ordered elements. On the other
hand, Binary search algorithm is however tricky, and elements are necessarily arranged in order.

11 Data Structure and Algorithms Lab Manual


Conclusion

Both linear and binary search algorithms can be useful depending on the application. When an array is
the data structure and elements are arranged in sorted order, then binary search is preferred
for quick searching. If linked list is the data structure regardless how the elements are arranged, linear
search is adopted due to unavailability of direct implementation of binary search algorithm.

Exercise 1: (5)
Calculate the elapsed time of Linear search and Binary Search.

Exercise 2: (5)
Write down the menu driven program for addition and subtraction and perform respective functions.

12 Data Structure and Algorithms Lab Manual


13 Data Structure and Algorithms Lab Manual
LAB TASK 2 – Arrays (Static, Dynamic and Multi dimensional)

Name / Group ID: Reg. No:

Class / Section: Date: _

Time Required : 3 hrs


Programming Language : Java
Software Required : Netbeans
Hardware Required : Computer System

Arrays in Java
An array is a group of like-typed variables that are referred to by a common name.Arrays in Java work
differently than they do in C/C++. Following are some important point about Java arrays.
• In Java all arrays are dynamically allocated. (discussed below)
• Since arrays are objects in Java, we can find their length using member length. This is different
from C/C++ where we find length using sizeof.
• A Java array variable can also be declared like other variables with [] after the data type.
• The variables in the array are ordered and each have an index beginning from 0.
• Java array can be also be used as a static field, a local variable or a method parameter.
• The size of an array must be specified by an int value and not long or short.
• The direct superclass of an array type is Object.
• Every array type implements the interfaces Cloneable and java.io.Serializable.
Array can contains primitives data types as well as objects of a class depending on the definition of
array. In case of primitives data types, the actual values are stored in contiguous memory locations. In
case of objects of a class, the actual objects are stored in heap segment.

Figure 1 Creating, Initializing, and Accessing an Array


One-Dimensional Arrays :
The general form of a one-dimensional array declaration is

type var-name[];
OR
type[] var-name;

An array declaration has two components: the type and the name. type declares the element type of the
array. The element type determines the data type of each element that comprises the array. Like array of
int type, we can also create an array of other primitive data types like char, float, double.etc or user
defined data type (objects of a class). Thus, the element type for the array d etermines what type of data
the array will hold.

14 Data Structure and Algorithms Lab Manual


Example:
// both are valid declarations
int intArray[];
or int[] intArray;

byte byteArray[];
short shortsArray[];
boolean booleanArray[];
long longArray[];
float floatArray[];
double doubleArray[];
char charArray[];

// an array of references to objects of


// the class MyClass (a class created by
// user)
MyClass myClassArray[];

Object[] ao, // array of Object


Collection[] ca; // array of Collection
// of unknown type

Although the above first declaration establishes the fact that intArray is an array variable, no array
actually exists. It simply tells to the compiler that this (intArray) variable will hold an array of the
integer type. To link intArray with an actual, physical array of integers, you must allocate one
using new and assign it to intArray.
Instantiating an Array in Java
When an array is declared, only a reference of array is created. To actually create or give memory to
array, you create an array like this:The general form of new as it applies to one-dimensional arrays
appears as follows:
var-name = new type [size];
Here, type specifies the type of data being allocated, size specifies the number of elements in the
array, and var-name is the name of array variable that is linked to the array. That is, to use new to
allocate an array, you must specify the type and number of elements to allocate.
Example:
int intArray[]; //declaring array
intArray = new int[20]; // allocating memory to array
OR
int[] intArray = new int[20]; // combining both statements in one
Note :
1. The elements in the array allocated by new will automatically be initialized to zero (for
numeric types), false (for boolean), or null (for reference types).
2. Obtaining an array is a two-step process. First, you must declare a variable of the
desired array type. Second, you must allocate the memory that will hold the array, using
new, andassign it to the array variable. Thus, in Java all arrays are dynamically allocated.
Array Literal
In a situation, where the size of the array and variables of array are already known, array literals can
be used.
int[] intArray = new int[]{ 1,2,3,4,5,6,7,8,9,10 };
// Declaring array literal

15 Data Structure and Algorithms Lab Manual


• The length of this array determines the length of the created array.
• There is no need to write the new int[] part in the latest versions of Java
Accessing Java Array Elements using for Loop
Each element in the array is accessed via its index. The index begins with 0 and ends at (total array
size)-1. All the elements of array can be accessed using Java for Loop.

// accessing the elements of the specified array


for (int i = 0; i < arr.length; i++)
System.out.println("Element at index " + i + " : "+ arr[i]);
Implementation:
// Java program to illustrate creating an array
// of integers, puts some values in the array,
// and prints each value to standard output.

class GFG
{
public static void main (String[] args)
{
// declares an Array of integers.
int[] arr;

// allocating memory for 5 integers.


arr = new int[5];

// initialize the first elements of the array


arr[0] = 10;

// initialize the second elements of the array


arr[1] = 20;

//so on...
arr[2] = 30;
arr[3] = 40;
arr[4] = 50;

// accessing the elements of the specified array


for (int i = 0; i < arr.length; i++)
System.out.println("Element at index " + i +
" : "+ arr[i]);
}
}
Output:
Element at index 0 : 10
Element at index 1 : 20
Element at index 2 : 30
Element at index 3 : 40
Element at index 4 : 50

16 Data Structure and Algorithms Lab Manual


Figure 2 1-D Array Visualization

Example2

class SortNames
{
public void sort(String[] a)
{
int i, pass, n = a.length;
String tmp;
for( pass = 0; pass < n; pass++ )
{
for( i = 0; i < n-pass-1; i++ )
if( ((Comparable)a[i]).compareTo(a[i+1]) > 0)
{
tmp = a[i]; // Swap a[i], a[i+1]
a[i] = a[i+1];
a[i+1] = tmp;
}
}
}
}
////////////////////////// SortNamesDemo.java ////////////////////
class SortNamesDemo
{
public static void main(String[] args)
{
SortNames sn = new SortNames();
String[] names =
{"Ramu", "John", "Anu", "Priya", "Basha", "Prem"};
int i;
System.out.println("Unsorted names:");

for(i=0; i < names.length; i++)


System.out.println(names[i]);
sn.sort(names);

System.out.println("Sorted names:");

17 Data Structure and Algorithms Lab Manual


for(i=0; i < names.length; i++)
System.out.println(names[i]);
}
}

Output:
Unsorted names:
Ramu
John
Anu
Priya
Basha
Prem
Sorted names:
Anu
Basha
John
Prem
Priya
Ramu

Multidimensional Arrays
Multidimensional arrays are arrays of arrays with each element of the array holding the reference of
other array. These are also known as Jagged Arrays. A multidimensional array is created by
appending one set of square brackets ([]) per dimension.
Examples:
int[][] intArray = new int[10][20]; //a 2D array or matrix
int[][][] intArray = new int[10][20][10]; //a 3D array
Implementation
class multiDimensional
{
public static void main(String args[])
{
// declaring and initializing 2D array
int arr[][] = { {2,7,9},{3,6,1},{7,4,2} };

// printing 2D array
for (int i=0; i< 3 ; i++)
{
for (int j=0; j < 3 ; j++)
System.out.print(arr[i][j] + " ");

System.out.println();
}
}
}

18 Data Structure and Algorithms Lab Manual


Output:
279
361
742

Figure 3 Multidimensional Array Visualization

Passing Arrays to Methods


Like variables, we can also pass arrays to methods. For example, below program pass array to
method sum for calculating sum of array’s values.
// Java program to demonstrate
// passing of array to method
Example
class Test
{
// Driver method
public static void main(String args[])
{
int arr[] = {3, 1, 2, 5, 4};

// passing array to method m1


sum(arr);

public static void sum(int[] arr)


{
// getting sum of array values
int sum = 0;

for (int i = 0; i < arr.length; i++)


sum+=arr[i];

System.out.println("sum of array values : " + sum);


}
}

19 Data Structure and Algorithms Lab Manual


Output:
sum of array values : 15
Returning Arrays from Methods
As usual, a method can also return an array. For example, below program returns an array from
method m1.
Example
// Java program to demonstrate
// return of array from method

class Test
{
// Driver method
public static void main(String args[])
{
int arr[] = m1();

for (int i = 0; i < arr.length; i++)


System.out.print(arr[i]+" ");

public static int[] m1()


{
// returning array
return new int[]{1,2,3};
}
}
Output:
1 2 3

Exercises
Exercise 1: (2)
Write the program to store the students in the array having size 5. Consider the below data members for
student. Populate the array by user values.
// Java program to illustrate creating an array of
// objects
class Student
{
public int roll_no;
public String name;
Student(int roll_no, String name)
{
this.roll_no = roll_no;
this.name = name;
}
}

20 Data Structure and Algorithms Lab Manual


Exercise 2: (2)
Consider the below code for interative binary search. Run the code and write down the output. And also
explain its working.

class BinarySearchDemo
{
static Object[] a = { "AP", "KA", "MH", "MP", "OR", "TN", "UP", "WB"}; static
Object key = "UP";
public static void main(String args[])
{
if( binarySearch() )
System.out.println(key + " found in the list"); else
System.out.println(key + " not found in the list");
}
static boolean binarySearch()
{
int c, mid, low = 0, high = a.length-1;
while( low <= high)
{
mid = (low + high)/2;
c = ((Comparable)key).compareTo(a[mid]);
if( c < 0) high = mid-1;
else if( c > 0) low = mid+1;
else return true;
}
return false;
}
}

21 Data Structure and Algorithms Lab Manual


22 Data Structure and Algorithms Lab Manual
Exercise 3: (1)
Write a Java program to sort a numeric array and a string array.

Exercise 4: (1)
Write a Java program to sum values of an array.

Exercise 5: (1)
Write a Java program to calculate the average value of array elements.

23 Data Structure and Algorithms Lab Manual


Exercise 6: (1)
Write a Java program to test if an array contains a specific value.

Exercise 7: (2)
Write a Java program that returns the missing letter from an array of increasing letters (upper or lower). Assume there will always
be one omission from the array.
Sample Data:
{"A", "B", "D", "E"} -> “C”
{"a", "b", "c", "e"} -> “d”
{"p", "r", "s", "t"} -> “q”

24 Data Structure and Algorithms Lab Manual


LAB TASK 3 – Array based Stack implementation

Name / Group ID: Reg. No:

Class / Section: Date: _

Time Required : 3 hrs


Programming Language : Java
Software Required : Netbeans
Hardware Required : Computer System

Stack ADT
A Stack is an Abstract Data Type (ADT) used for storing the elements. The elements are stored
based on the principle of LIFO (Last In, First Out). In stack insertion and deletion of elements
take place at the same end (Top). The last element inserted will be the first to be retrieved.
• This end is called Top
• The other end is called Bottom

Stack supports the following methods:


Top(): The stack top operation gets the data from the top-most position and returns it to the user
without deleting it. The underflow state can also occur in stack top operation if stack is empty.

push(obj): Add object obj at the top of the stack.


Input: Object; Output: None.

obj pop(): Delete an item from the top of the stack and returns object obj; an error occurs if
the stack is empty.
Input: None; Output: Object.

obj peek(): Returns the top object obj on the stack , without removing it; an error occurs if
the stack is empty.
Input: None; Output: Object.

boolean isEmpty(): Returns a boolean indicating if the stack is empty.


Input: None; Output: boolean (true or false).

int size(): Returns the number of items on the stack.


Input: None; Output: integer.

boolean isUnderflow(): When stack contains equal number of elements as per its capacity and no
more elements can be added, the status of stack is known as overflow.
Input: None; Output: boolean (true or false).

Type Object may be any type that can be stored in the stack. The actual type of the object
will be provided by the user.

25 Data Structure and Algorithms Lab Manual


Data4 Top

Data3

Data2

Data1 Bottom

Figure 4 Stack Visualization 1

Figure 5 Stack Visualization 2

Stack Implementation:

/* Java program to implement basic stack


operations */
class Stack {
static final int MAX = 1000;
int top;
int a[] = new int[MAX]; // Maximum size of Stack

boolean isEmpty()
{
return (top < 0);
}
Stack()
{
top = -1;
}

boolean push(int x)
{

26 Data Structure and Algorithms Lab Manual


if (top >= (MAX - 1)) {
System.out.println("Stack Overflow");
return false;
}
else {
a[++top] = x;
System.out.println(x + " pushed into stack");
return true;
}
}

int pop()
{
if (top < 0) {
System.out.println("Stack Underflow");
return 0;
}
else {
int x = a[top--];
return x;
}
}

int peek()
{
if (top < 0) {
System.out.println("Stack Underflow");
return 0;
}
else {
int x = a[top];
return x;
}
}
}

// Driver code
class Main {
public static void main(String args[])
{
Stack s = new Stack();
s.push(10);
s.push(20);
s.push(30);
System.out.println(s.pop() + " Popped from stack");
}
}

27 Data Structure and Algorithms Lab Manual


Applications of stack:

• Balancing of symbols
• Infix to Postfix /Prefix conversion
• Redo-undo features at many places like editors, photoshop.
• Forward and backward feature in web browsers
• Used in many algorithms like Tower of Hanoi, tree traversals, stock span problem, histogram
problem.
• Other applications can be Backtracking, Knight tour problem, rat in a maze, N queen
problem and sudoku solver
• In Graph Algorithms like Topological Sorting and Strongly Connected Components

Exercices:

Exercise 1: Display ( ) Function test in main function (2)


Write this function to display the elements of stack e.g.
void display( )
{
}

Exercise 2: Implement using stacks. (3)


Write a program using stack operations, which accepts a non-negative base 10 integer as a parameter,
and display binary representation of number.
Description: To convert a number from decimal to binary, you simply divide by two and push reminder
to stack until quotient is reached to zero, then use pop operation to display the binary representation of
number. For example, to convert (35)10 to binary, you perform the following computation.
35/2 = 1
17/2 = 1
8/2 = 0
4/2 = 0

28 Data Structure and Algorithms Lab Manual


2/2 = 0
1
If you examine the remainders from the last division to the first one, writing them down as you go, you
will get the following sequence: 100011. i.e. (100011)2=(35)10

29 Data Structure and Algorithms Lab Manual


30 Data Structure and Algorithms Lab Manual
Exercise 3: (5)

Write a program to compare opening and closing brackets in expression. This program takes an
expression in the form of string and scan it character by character. Finally the output of the program is
the valid or invalid expression.

Algorithm: To do this comparison a stack ADT can be used to keep track of the scope delimiters
encountered while scanning the expression.
• Whenever a scope “opener” is encountered, it can be “pushed” onto a stack
• Whenever a scope “ender” is encountered, the stack is examined:
– If the stack is “empty”, there is no matching scope “opener” and the expression is invalid.
– If the stack is not empty, we pop the stack and check if the “popped” item corresponds to the
scope ender
– If match occurs, we continue scanning the expression
• When end of the expression string is reached, the stack must be empty, otherwise one or more
opened scopes have not been closed and the expression is invalid

29 Data Structure and Algorithms Lab Manual


30 Data Structure and Algorithms Lab Manual
LAB TASK 4 – Array based Queue implementation

Name / Group ID: Reg. No:

Class / Section: Date: _

Time Required : 3 hrs


Programming Language : Java
Software Required : Netbeans
Hardware Required : Computer System

Queue ADT

In queue, insertion and deletion happen at the opposite ends, so implementation is not as simple
as stack.
To implement a queue using array, create an array arr of size n and take two
variables front and rear both of which will be initialized to 0 which means the queue is currently
empty. Element rear is the index upto which the elements are stored in the array and front is the
index of the first element of the array.

Some of the implementation of queue operations are as follows:


Enqueue: Addition of an element to the queue. Adding an element will be performed after
checking whether the queue is full or not. If rear < n which indicates that the array is not full then
store the element at arr[rear] and increment rear by 1 but if rear == n then it is said to be an
Overflow condition as the array is full.

Dequeue: Removal of an element from the queue. An element can only be deleted when there is
at least an element to delete i.e. rear > 0. Now, element at arr[front] can be deleted but all the
remaining elements have to shifted to the left by one position in order for the dequeue operation
to delete the second element from the left on another dequeue operation.

Front: Get the front element from the queue i.e. arr[front] if queue is not empty.

Display: Print all element of the queue. If the queue is non-empty, traverse
and print all the elements from index front to rear.

31 Data Structure and Algorithms Lab Manual


Figure 6 Queue Visualization

Queue Implementation:

// Java program to implement a queue using an array


class Queue {
private static int front, rear, capacity;
private static int queue[];

Queue(int c)
{
front = rear = 0;
capacity = c;
queue = new int[capacity];
}

// function to insert an element

32 Data Structure and Algorithms Lab Manual


// at the rear of the queue
static void queueEnqueue(int data)
{
// check queue is full or not
if (capacity == rear) {
System.out.printf("\nQueue is full\n");
return;
}

// insert element at the rear


else {
queue[rear] = data;
rear++;
}
return;
}

// function to delete an element


// from the front of the queue
static void queueDequeue()
{
// if queue is empty
if (front == rear) {
System.out.printf("\nQueue is empty\n");
return;
}

// shift all the elements from index 2 till rear


// to the right by one
else {
for (int i = 0; i < rear - 1; i++) {
queue[i] = queue[i + 1];
}

// store 0 at rear indicating there's no element


if (rear < capacity)
queue[rear] = 0;

// decrement rear
rear--;
}
return;
}

33 Data Structure and Algorithms Lab Manual


// print queue elements
static void queueDisplay()
{
int i;
if (front == rear) {
System.out.printf("\nQueue is Empty\n");
return;
}

// traverse front to rear and print elements


for (i = front; i < rear; i++) {
System.out.printf(" %d <-- ", queue[i]);
}
return;
}

// print front of queue


static void queueFront()
{
if (front == rear) {
System.out.printf("\nQueue is Empty\n");
return;
}
System.out.printf("\nFront Element is: %d", queue[front]);
return;
}
}

public class StaticQueueinjava {

// Driver code
public static void main(String[] args)
{
// Create a queue of capacity 4
Queue q = new Queue(4);

// print Queue elements


q.queueDisplay();

// inserting elements in the queue


q.queueEnqueue(20);
q.queueEnqueue(30);
q.queueEnqueue(40);
q.queueEnqueue(50);

// print Queue elements


q.queueDisplay();

// insert element in the queue


q.queueEnqueue(60);

34 Data Structure and Algorithms Lab Manual


// print Queue elements
q.queueDisplay();

q.queueDequeue();
q.queueDequeue();
System.out.printf("\n\nafter two node deletion\n\n");
// print Queue elements
q.queueDisplay();

// print front of the queue


q.queueFront();
}
}

Output:

Queue is Empty
20 <-- 30 <-- 40 <-- 50 <--
Queue is full
20 <-- 30 <-- 40 <-- 50 <--

after two node deletion

40 <-- 50 <--
Front Element is: 40

Applications of Queue

• Queue is useful in CPU scheduling, Disk Scheduling. When multiple processes require
CPU at the same time, various CPU scheduling algorithms are used which are implemented
using Queue data structure.
• When data is transferred asynchronously between two processes.Queue is used for
synchronization. Examples : IO Buffers, pipes, file IO, etc.
• In print spooling, documents are loaded into a buffer and then the printer pulls them off
the buffer at its own rate. Spooling also lets you place a number of print jobs on a queue
instead ofwaiting for each one to finish before specifying the next one.
• Breadth First search in a Graph .It is an algorithm for traversing or searching graph
data structures. It starts at some arbitrary node of a graph and explores the neighbor nodes
first, before moving to the next level neighbors.This Algorithm uses Queue data structure.

35 Data Structure and Algorithms Lab Manual


Exercices

Exercise 1: (4)
Write a menu driven program to perform different operations with queue such a Enqueue ( ),
Dequeue( ) and DisplayQueue( ).

36 Data Structure and Algorithms Lab Manual


Exercise 2: (6)
In this Exercise, you have to take a single string as input. Using this input string, you have to create multiple
queues in which each queue will comprise of separate word appeared in input string. At the end, you will again
concatenate all queues to a single queue.
Example:
String = “Data Structure and Algo”
Q1 = D → a → t → a
Q2 = S → t → r → u → c → t → u → r → e
Q3 = a → n → d
Q4 = A → l → g → o
At the end concatenate all queues and display them.
Q1 → Q2 → Q3 → Q4

37 Data Structure and Algorithms Lab Manual


LAB TASK 5 – Circular Queue and Implementation of Deque using circular array

Name / Group ID: Reg. No:

Class / Section: Date: _

Time Required : 3 hrs


Programming Language : Java
Software Required : Netbeans
Hardware Required : Computer System

Circular Queue ADT

Circular Queue is a linear data structure in which the operations are performed based on FIFO
(First In First Out) principle and the last position is connected back to the first position to make a
circle. It is also called ‘Ring Buffer’.

Figure 7 Cicular Queue Visulaization

In a normal Queue, we can insert elements until queue becomes full. But once queue becomes full, we
can not insert the next element even if there is a space in front of queue.

38 Data Structure and Algorithms Lab Manual


Figure 8 Visulaization of Circular Queue through its operations

Operations on Circular Queue:


Front: Get the front item from queue.

Rear: Get the last item from queue.

enQueue(value) This function is used to insert an element into the circular queue. In a circular queue,
the new element is always inserted at Rear position.
Steps:
1. Check whether queue is Full – Check ((rear == SIZE-1 && front == 0) || (rear == front-1)).
2. If it is full then display Queue is full. If queue is not full then, check if (rear == SIZE – 1
&& front != 0) if it is true then set rear=0 and insert element.

deQueue() This function is used to delete an element from the circular queue. In a circular queue, the
element is always deleted from front position.
Steps:
3. Check whether queue is Empty means check (front==-1).
4. If it is empty then display Queue is empty. If queue is not empty then step 3
5. Check if (front==rear) if it is true then set front=rear= -1 else check if (front==size-1), if
it is true then set front=0 and return the element.

39 Data Structure and Algorithms Lab Manual


Deque
Deque or Double Ended Queue is a generalized version of Queue data structure that allows insert and
delete at both ends.In previous post we had discussed introduction of deque. Now in this post we see
how we implement deque Using circular array.

Operations on Deque:

Mainly the following four basic operations are performed on queue:

insetFront(): Adds an item at the front of Deque.

insertRear(): Adds an item at the rear of Deque.

deleteFront(): Deletes an item from front of Deque.

deleteRear(): Deletes an item from rear of Deque.

In addition to above operations, following operations are also supported

getFront(): Gets the front item from queue.

getRear(): Gets the last item from queue.

isEmpty(): Checks whether Deque is empty or not.

isFull(): Checks whether Deque is full or not.

Figure 9 Deque visualization

40 Data Structure and Algorithms Lab Manual


Circular array implementation deque

For implementing deque, we need to keep track of two indices, front and rear. We enqueue(push) an
item at the rear or the front end of qedue and dequeue(pop) an item from both rear and front end.
Working
1. Create an empty array ‘arr’ of size ‘n’
initialize front = -1 , rear = 0
Inserting First element in deque, at either front or rear will lead to the same result.

After insert Front Points = 0 and Rear points = 0

Insert Elements at Rear end

a). First we check deque if Full or Not


b). IF Rear == Size-1
then reinitialize Rear = 0 ;
Else increment Rear by '1'
and push current key into Arr[ rear ] = key
Front remain same.
Insert Elements at Front end

a). First we check deque if Full or Not


b). IF Front == 0 || initial position, move Front
to points last index of array
front = size - 1
Else decremented front by '1' and push
current key into Arr[ Front] = key
Rear remain same.

41 Data Structure and Algorithms Lab Manual


Delete Element From Rear end

a). first Check deque is Empty or Not


b). If deque has only one element
front = -1 ; rear =-1 ;
Else IF Rear points to the first index of array
it's means we have to move rear to points
last index [ now first inserted element at
front end become rear end ]
rear = size-1 ;
Else || decrease rear by '1'
rear = rear-1;
Delete Element From Front end

a). first Check deque is Empty or Not


b). If deque has only one element
front = -1 ; rear =-1 ;
Else IF front points to the last index of the array
it's means we have no more elements in array so
we move front to points first index of array
front = 0 ;
Else || increment Front by '1'
front = front+1;

42 Data Structure and Algorithms Lab Manual


Program

// Java implementation of De-queue using circular


// array

// A structure to represent a Deque


class Deque
{
static final int MAX = 100;
int arr[];
int front;
int rear;
int size;

public Deque(int size)


{
arr = new int[MAX];
front = -1;
rear = 0;
this.size = size;
}

/*// Operations on Deque:


void insertfront(int key);
void insertrear(int key);
void deletefront();
void deleterear();
bool isFull();
bool isEmpty();
int getFront();
int getRear();*/

// Checks whether Deque is full or not.


boolean isFull()
{
return ((front == 0 && rear == size-1)||
front == rear+1);
}

43 Data Structure and Algorithms Lab Manual


// Checks whether Deque is empty or not.
boolean isEmpty ()
{
return (front == -1);
}

// Inserts an element at front


void insertfront(int key)
{
// check whether Deque if full or not
if (isFull())
{
System.out.println("Overflow");
return;
}

// If queue is initially empty


if (front == -1)
{
front = 0;
rear = 0;
}

// front is at first position of queue


else if (front == 0)
front = size - 1 ;

else // decrement front end by '1'


front = front-1;

// insert current element into Deque


arr[front] = key ;
}

// function to inset element at rear end


// of Deque.
void insertrear(int key)
{
if (isFull())
{
System.out.println(" Overflow ");
return;
}

// If queue is initially empty


if (front == -1)
{
front = 0;
rear = 0;
}

44 Data Structure and Algorithms Lab Manual


// rear is at last position of queue
else if (rear == size-1)
rear = 0;

// increment rear end by '1'


else
rear = rear+1;

// insert current element into Deque


arr[rear] = key ;
}

// Deletes element at front end of Deque


void deletefront()
{
// check whether Deque is empty or not
if (isEmpty())
{
System.out.println("Queue Underflow\n");
return ;
}

// Deque has only one element


if (front == rear)
{
front = -1;
rear = -1;
}
else
// back to initial position
if (front == size -1)
front = 0;

else // increment front by '1' to remove current


// front value from Deque
front = front+1;
}

// Delete element at rear end of Deque


void deleterear()
{
if (isEmpty())
{
System.out.println(" Underflow");
return ;
}

// Deque has only one element


if (front == rear)
{
front = -1;
45 Data Structure and Algorithms Lab Manual
rear = -1;
}
else if (rear == 0)
rear = size-1;
else
rear = rear-1;
}

// Returns front element of Deque


int getFront()
{
// check whether Deque is empty or not
if (isEmpty())
{
System.out.println(" Underflow");
return -1 ;
}
return arr[front];
}

// function return rear element of Deque


int getRear()
{
// check whether Deque is empty or not
if(isEmpty() || rear < 0)
{
System.out.println(" Underflow\n");
return -1 ;
}
return arr[rear];
}

// Driver program to test above function


public static void main(String[] args)
{

Deque dq = new Deque(5);

System.out.println("Insert element at rear end : 5 ");


dq.insertrear(5);

System.out.println("insert element at rear end : 10 ");


dq.insertrear(10);

System.out.println("get rear element : "+ dq.getRear());

dq.deleterear();
System.out.println("After delete rear element new rear become : " +
dq.getRear());

System.out.println("inserting element at front end");


46 Data Structure and Algorithms Lab Manual
dq.insertfront(15);

System.out.println("get front element: " +dq.getFront());

dq.deletefront();

System.out.println("After delete front element new front become : " +


+ dq.getFront());

}
}

Output:
insert element at rear end : 5
insert element at rear end : 10
get rear element : 10
After delete rear element new rear become : 5
inserting element at front end
get front element : 15
After delete front element new front become : 5

Exercise: (10)
Run the given program and write down the output and explain the steps.
//Java program to find circular tour for a truck

public class Petrol


{
// A petrol pump has petrol and distance to next petrol pump
static class petrolPump
{
int petrol;
int distance;

// constructor
public petrolPump(int petrol, int distance)

47 Data Structure and Algorithms Lab Manual


{
this.petrol = petrol;
this.distance = distance;
}
}

// The function returns starting point if there is a possible solution,


// otherwise returns -1
static int printTour(petrolPump arr[], int n)
{
int start = 0;
int end = 1;
int curr_petrol = arr[start].petrol - arr[start].distance;

// If current amount of petrol in truck becomes less than 0, then


// remove the starting petrol pump from tour
while(end != start || curr_petrol < 0)
{

// If current amount of petrol in truck becomes less than 0, then


// remove the starting petrol pump from tour
while(curr_petrol < 0 && start != end)
{
// Remove starting petrol pump. Change start
curr_petrol -= arr[start].petrol - arr[start].distance;
start = (start + 1) % n;

// If 0 is being considered as start again, then there is no


// possible solution
if(start == 0)
return -1;
}
// Add a petrol pump to current tour
curr_petrol += arr[end].petrol - arr[end].distance;

48 Data Structure and Algorithms Lab Manual


end = (end + 1)%n;
}

// Return starting point


return start;
}

// Driver program to test above functions


public static void main(String[] args)
{

petrolPump[] arr = {new petrolPump(6, 4),


new petrolPump(3, 6),
new petrolPump(7, 3)};

int start = printTour(arr, arr.length);

System.out.println(start == -1 ? "No Solution" : "Start = " + start);

}
}
Output

49 Data Structure and Algorithms Lab Manual


LAB TASK 6 – Singly Link List

Name / Group ID: Reg. No:

Class / Section: Date: _

Time Required : 3 hrs


Programming Language : Java
Software Required : Netbeans
Hardware Required : Computer System

Linked List
Like arrays, Linked List is a linear data structure. Unlike arrays, linked list elements are not stored at a
contiguous location; the elements are linked using pointers.

Figure 10 Linked List Visualization

In Java or C#, LinkedList can be represented as a class and a Node as a separate class. The LinkedList
class contains a reference of Node class type.

class LinkedList {
Node head; // head of the list

/* Linked list Node*/


class Node {
int data;
Node next;

// Constructor to create a new node


// Next is by default initialized
// as null
Node(int d) { data = d; }
}
}

50 Data Structure and Algorithms Lab Manual


First Simple Linked List in Java
Let us create a simple linked list with 3 nodes.

// A simple Java program to introduce a linked list


class LinkedList {
Node head; // head of list

/* Linked list Node. This inner class is made static so that


main() can access it */
static class Node {
int data;
Node next;
Node(int d)
{
data = d;
next = null;
} // Constructor
}

/* method to create a simple linked list with 3 nodes*/


public static void main(String[] args)
{
/* Start with the empty list. */
LinkedList llist = new LinkedList();

llist.head = new Node(1);


Node second = new Node(2);
Node third = new Node(3);

/* Three nodes have been allocated dynamically.


We have references to these three blocks as head,
second and third

llist.head second third


| | |
| | |
+ + + + + + + + +
| 1 | null | | 2 | null | | 3 | null |
+ + + + + + + + + */

llist.head.next = second; // Link first node with the second node

/* Now next of the first Node refers to the second. So they


both are linked.

51 Data Structure and Algorithms Lab Manual


llist.head second third
| | |
| | |
+ + + + + + + + +
| 1 | o ------- >| 2 | null | | 3 | null |
+----+------+ +----+------+ +----+------+ */

second.next = third; // Link second node with the third node

/* Now next of the second Node refers to third. So all three


nodes are linked.

llist.head second third


| | |
| | |
+ + + + + + + + +
| 1 | o-------->| 2 | o-------- >| 3 | null |
+ + + + + + + + + */
}
}

Linked List Traversal


In the previous program, we have created a simple linked list with three nodes. Let us traverse the
created list and print the data of each node. For traversal, let us write a general-purpose function
printList() that prints any given list.

// A simple Java program for traversal of a linked list


class LinkedList {
Node head; // head of list

/* Linked list Node. This inner class is made static so that


main() can access it */
static class Node {
int data;
Node next;
Node(int d)
{
data = d;
next = null;
} // Constructor
}

/* This function prints contents of linked list starting from head */


public void printList()
{
Node n = head;
while (n != null) {
System.out.print(n.data + " ");
n = n.next;
}
52 Data Structure and Algorithms Lab Manual
}

/* method to create a simple linked list with 3 nodes*/


public static void main(String[] args)
{
/* Start with the empty list. */
LinkedList llist = new LinkedList();

llist.head = new Node(1);


Node second = new Node(2);
Node third = new Node(3);

llist.head.next = second; // Link first node with the second node


second.next = third; // Link first node with the second node

llist.printList();
}
}

Linked List (Inserting a node)


A node can be added in three ways
1) At the front of the linked list
2) After a given node.
3) At the end of the linked list.

// A complete working Java program to demonstrate all insertion methods


// on linked list
class LinkedList
{
Node head; // head of list

/* Linked list Node*/


class Node
{
int data;
Node next;
Node(int d) {data = d; next = null; }
}

/* Inserts a new Node at front of the list. */


public void push(int new_data)
{
/* 1 & 2: Allocate the Node &
Put in the data*/
Node new_node = new Node(new_data);

/* 3. Make next of new Node as head */


new_node.next = head;

53 Data Structure and Algorithms Lab Manual


/* 4. Move the head to point to new Node */
head = new_node;
}

/* Inserts a new node after the given prev_node. */


public void insertAfter(Node prev_node, int new_data)
{
/* 1. Check if the given Node is null */
if (prev_node == null)
{
System.out.println("The given previous node cannot be null");
return;
}

/* 2 & 3: Allocate the Node &


Put in the data*/
Node new_node = new Node(new_data);

/* 4. Make next of new Node as next of prev_node */


new_node.next = prev_node.next;

/* 5. make next of prev_node as new_node */


prev_node.next = new_node;
}

/* Appends a new node at the end. This method is


defined inside LinkedList class shown above */
public void append(int new_data)
{
/* 1. Allocate the Node &
2. Put in the data
3. Set next as null */
Node new_node = new Node(new_data);

/* 4. If the Linked List is empty, then make the


new node as head */
if (head == null)
{
head = new Node(new_data);
return;
}

/* 4. This new node is going to be the last node, so


make next of it as null */
new_node.next = null;

/* 5. Else traverse till the last node */


Node last = head;
while (last.next != null)
last = last.next;

54 Data Structure and Algorithms Lab Manual


/* 6. Change the next of last node */
last.next = new_node;
return;
}

/* This function prints contents of linked list starting from


the given node */
public void printList()
{
Node tnode = head;
while (tnode != null)
{
System.out.print(tnode.data+" ");
tnode = tnode.next;
}
}

/* Driver program to test above functions. Ideally this function


should be in a separate user class. It is kept here to keep
code compact */
public static void main(String[] args)
{
/* Start with the empty list */
LinkedList llist = new LinkedList();

// Insert 6. So linked list becomes 6->NUllist


llist.append(6);

// Insert 7 at the beginning. So linked list becomes


// 7->6->NUllist
llist.push(7);

// Insert 1 at the beginning. So linked list becomes


// 1->7->6->NUllist
llist.push(1);

// Insert 4 at the end. So linked list becomes


// 1->7->6->4->NUllist
llist.append(4);

// Insert 8, after 7. So linked list becomes


// 1->7->8->6->4->NUllist
llist.insertAfter(llist.head.next, 8);

System.out.println("\nCreated Linked list is: ");


llist.printList();
}
}

55 Data Structure and Algorithms Lab Manual


Output

Created Linked list is: 1 7 8 6 4

Linked List (Deleting a node)


Let us formulate the problem statement to understand the deletion process. Given a ‘key’, delete the first
occurrence of this key in linked list.
To delete a node from linked list, we need to do following steps.
1) Find previous node of the node to be deleted.
2) Change the next of previous node.
3) Free memory for the node to be deleted.

// A complete working Java program to demonstrate deletion in singly


// linked list
class LinkedList
{
Node head; // head of list

/* Linked list Node*/


class Node
{
int data;
Node next;
Node(int d)
{
data = d;
next = null;
}
}

/* Given a key, deletes the first occurrence of key in linked list */


void deleteNode(int key)
{
// Store head node
Node temp = head, prev = null;

// If head node itself holds the key to be deleted

56 Data Structure and Algorithms Lab Manual


if (temp != null && temp.data == key)
{
head = temp.next; // Changed head
return;
}

// Search for the key to be deleted, keep track of the


// previous node as we need to change temp.next
while (temp != null && temp.data != key)
{
prev = temp;
temp = temp.next;
}

// If key was not present in linked list


if (temp == null) return;

// Unlink the node from linked list


prev.next = temp.next;
}

/* Inserts a new Node at front of the list. */


public void push(int new_data)
{
Node new_node = new Node(new_data);
new_node.next = head;
head = new_node;
}

/* This function prints contents of linked list starting from


the given node */
public void printList()
{
Node tnode = head;
while (tnode != null)
{
System.out.print(tnode.data+" ");
tnode = tnode.next;
}
}

/* Drier program to test above functions. Ideally this function


should be in a separate user class. It is kept here to keep
code compact */
public static void main(String[] args)
{
LinkedList llist = new LinkedList();

llist.push(7);
llist.push(1);
llist.push(3);
57 Data Structure and Algorithms Lab Manual
llist.push(2);

System.out.println("\nCreated Linked list is:");


llist.printList();

llist.deleteNode(1); // Delete node at position 4

System.out.println("\nLinked List after Deletion at position 4:");


llist.printList();
}
}

Output

Created Linked List:


23 1 7
Linked List after Deletion of 1:
23 7

Exercises

Exercise 1: (2)
Write a function to get Nth node in a Linked List

58 Data Structure and Algorithms Lab Manual


Exercise 2: (2)
Write a function that counts the number of times a given int occurs in a Linked List

Exercise 3: (2)
Swap nodes in a linked list without swapping data

59 Data Structure and Algorithms Lab Manual


Exercise 4: (4)
Snakes Game (Arrays)
 The snake game is one of the most popular games on Nokia phones, released in 1998
 Today there are over 300 snake-like games just for ios.
 We can also build a snake game using the Linked List concept of Data Structures.
 A linked list is a linear data structure in which elements are not stored in contiguous memory locations.
 This game is very similar to singly-linked lists, assuming that the snake head is the linked list tail and the snake tail
is the linked list head.
 Whenever the snake eats the pay, an extra node is added to its tail, i.e., an extra node is added to the linked list
head. The same process continues until the snake hits the boundary or itself.

60 Data Structure and Algorithms Lab Manual


LAB TASK 7 – Doubly Link List

Name / Group ID: Reg. No:

Class / Section: Date: _

Time Required : 3 hrs


Programming Language : Java
Software Required : Netbeans
Hardware Required : Computer System

Doubly Linked List


A Doubly Linked List (DLL) contains an extra pointer, typically called previous pointer, together with
next pointer and data which are there in singly linked list.

Following is representation of a DLL node in Java language.

// Class for Doubly Linked List


public class DLL {
Node head; // head of list

/* Doubly Linked list Node*/


class Node {
int data;
Node prev;
Node next;

// Constructor to create a new node


// next and prev is by default initialized as null
Node(int d) { data = d; }
}
}

A node can be added in four ways


1) At the front of the DLL
2) After a given node.
3) At the end of the DLL
4) Before a given node.

// A complete working Java program to demonstrate all

// Class for Doubly Linked List


public class DLL {
Node head; // head of list

/* Doubly Linked list Node*/


class Node {
int data;
Node prev;

61 Data Structure and Algorithms Lab Manual


Node next;

// Constructor to create a new node


// next and prev is by default initialized as null
Node(int d) { data = d; }
}

// Adding a node at the front of the list


public void push(int new_data)
{
/* 1. allocate node
* 2. put in the data */
Node new_Node = new Node(new_data);

/* 3. Make next of new node as head and previous as NULL */


new_Node.next = head;
new_Node.prev = null;

/* 4. change prev of head node to new node */


if (head != null)
head.prev = new_Node;

/* 5. move the head to point to the new node */


head = new_Node;
}

/* Given a node as prev_node, insert a new node after the given node */
public void InsertAfter(Node prev_Node, int new_data)
{

/*1. check if the given prev_node is NULL */


if (prev_Node == null) {
System.out.println("The given previous node cannot be NULL ");
return;
}

/* 2. allocate node
* 3. put in the data */
Node new_node = new Node(new_data);

/* 4. Make next of new node as next of prev_node */


new_node.next = prev_Node.next;

/* 5. Make the next of prev_node as new_node */


prev_Node.next = new_node;

/* 6. Make prev_node as previous of new_node */


new_node.prev = prev_Node;

/* 7. Change previous of new_node's next node */


if (new_node.next != null)
62 Data Structure and Algorithms Lab Manual
new_node.next.prev = new_node;
}

// Add a node at the end of the list


void append(int new_data)
{
/* 1. allocate node
* 2. put in the data */
Node new_node = new Node(new_data);

Node last = head; /* used in step 5*/

/* 3. This new node is going to be the last node, so


* make next of it as NULL*/
new_node.next = null;

/* 4. If the Linked List is empty, then make the new


* node as head */
if (head == null) {
new_node.prev = null;
head = new_node;
return;
}

/* 5. Else traverse till the last node */


while (last.next != null)
last = last.next;

/* 6. Change the next of last node */


last.next = new_node;

/* 7. Make last node as previous of new node */


new_node.prev = last;
}

// This function prints contents of linked list starting from the given node
public void printlist(Node node)
{
Node last = null;
System.out.println("Traversal in forward Direction");
while (node != null) {
System.out.print(node.data + " ");
last = node;
node = node.next;
}
System.out.println();
System.out.println("Traversal in reverse direction");
while (last != null) {
System.out.print(last.data + " ");
last = last.prev;
}
63 Data Structure and Algorithms Lab Manual
}

/* Drier program to test above functions*/


public static void main(String[] args)
{
/* Start with the empty list */
DLL dll = new DLL();

// Insert 6. So linked list becomes 6->NULL


dll.append(6);

// Insert 7 at the beginning. So linked list becomes 7->6->NULL


dll.push(7);

// Insert 1 at the beginning. So linked list becomes 1->7->6->NULL


dll.push(1);

// Insert 4 at the end. So linked list becomes 1->7->6->4->NULL


dll.append(4);

// Insert 8, after 7. So linked list becomes 1->7->8->6->4->NULL


dll.InsertAfter(dll.head.next, 8);

System.out.println("Created DLL is: ");


dll.printlist(dll.head);
}
}

Output:

Created DLL is:


Traversal in forward direction
17864
Traversal in reverse direction
46871

64 Data Structure and Algorithms Lab Manual


Delete a node in a Doubly Linked List

Original Doubly Linked List

After deletion of head node

After deletion of middle node

After deletion of last node

65 Data Structure and Algorithms Lab Manual


Program
// Class for Doubly Linked List
public class DLL {
Node head; // head of list

/* Doubly Linked list Node*/


class Node {
int data;
Node prev;
Node next;

// Constructor to create a new node


// next and prev is by default initialized
// as null
Node(int d) { data = d; }
}

// Adding a node at the front of the list


public void push(int new_data)
{
// 1. allocate node
// 2. put in the data
Node new_Node = new Node(new_data);

// 3. Make next of new node as head


// and previous as NULL
new_Node.next = head;
new_Node.prev = null;

// 4. change prev of head node to new node


if (head != null)
head.prev = new_Node;

// 5. move the head to point to the new node


head = new_Node;
}

// This function prints contents of linked list


// starting from the given node
public void printlist(Node node)
{
Node last = null;

while (node != null) {


System.out.print(node.data + " ");
last = node;
node = node.next;
}
System.out.println();
}
66 Data Structure and Algorithms Lab Manual
// Function to delete a node in a Doubly Linked List.
// head_ref --> pointer to head node pointer.
// del --> data of node to be deleted.
void deleteNode(Node head_ref, Node del)
{

// Base case
if (head == null || del == null) {
return;
}

// If node to be deleted is head node


if (head == del) {
head = del.next;
}

// Change next only if node to be deleted


// is NOT the last node
if (del.next != null) {
del.next.prev = del.prev;
}

// Change prev only if node to be deleted


// is NOT the first node
if (del.prev != null) {
del.prev.next = del.next;
}

// Finally, free the memory occupied by del


return;
}

// Driver Code
public static void main(String[] args)
{
// Start with the empty list
DLL dll = new DLL();

// Insert 2. So linked list becomes 2->NULL


dll.push(2);

// Insert 4. So linked list becomes 4->2->NULL


dll.push(4);

// Insert 8. So linked list becomes 8->4->2->NULL


dll.push(8);

// Insert 10. So linked list becomes 10->8->4->2->NULL


dll.push(10);

67 Data Structure and Algorithms Lab Manual


System.out.print("Created DLL is: ");
dll.printlist(dll.head);

// Deleting first node


dll.deleteNode(dll.head, dll.head);

// List after deleting first node


// 8->4->2
System.out.print("\nList after deleting first node: ");
dll.printlist(dll.head);

// Deleting middle node from 8->4->2


dll.deleteNode(dll.head, dll.head.next);

System.out.print("\nList after Deleting middle node: ");


dll.printlist(dll.head);
}
}

Output:
Original Linked list 10 8 4 2
Modified Linked list 8

Exercises

Exercise 1: (2)
Delete all the nodes from a doubly linked list that are smaller than a given value

68 Data Structure and Algorithms Lab Manual


Exercise 2: (2)
Find the largest node in Doubly linked list

Exercise 3: (2)
Delete a Node from linked list without head pointer

69 Data Structure and Algorithms Lab Manual


Exercise 4: (3)
Convert the LinkedList into Circular LinkedList

70 Data Structure and Algorithms Lab Manual


Practical Application of Doubly-linked lists
Phone directory application using doubly-linked lists

This project can demonstrate the working of contact book applications and also teach you about data structures like
arrays, linked lists, stacks, and queues. Typically, phone book management encompasses searching, sorting, and
deleting operations. A distinctive feature of the search queries here is that the user sees suggestions from the contact
list after entering each character. You can read the source-code of freely available projects and replicate the same to
develop your skills.

This project demonstrates how to address the book programs’ function. It also teaches you about queuing, stacking,
linking lists, and arrays. Usually, this project’s directory includes certain actions like categorising, scanning, and
removing. Subsequently, the client shows recommendations from the address book after typing each character. This
is the web searches’ unique facet. You can inspect the code of extensively used DSA projects in C++ and applications
and ultimately duplicate them. This helps you to advance your data science career.

71 Data Structure and Algorithms Lab Manual


LAB TASK 8 – SEMESTER PROJECT GUIDELINES

Name / Group ID: Reg. No:

Class / Section: Date: _

Time Required : 3 hrs


Programming Language : Nill
Software Required : Web Browser
Hardware Required : Computer System
[5]
Form a group for this course’s semester project.

Select a system that you want to implement using Java, submit a project proposal with the following
sections: [5]

Date
Group Members: List of Roll number and Names
System introduction: what is the system about?
Problem Statement: what is the possible problem area that you will attempt to implement?

*Semester Project Report Template is attached with this lab. Please format your report
accordingly.

72 Data Structure and Algorithms Lab Manual


Data Structure

SEMESTER PROJECT REPORT


[TEMPLATE]

GROUP ID:
PROJECT TITLE:

GROUP MEMBERS:
NAME/ROLL NO. :
NAME/ROLL NO. :
NAME/ROLL NO. :
NAME/ROLL NO. :

SUBMITTED TO:

INSTRUCTOR: Aqib Rehman

DATED:

73 Data Structure and Algorithms Lab Manual


*Up to +5 bonus to those who implement the system on GUI.

For every group project, evaluation will be done on the following criteria:

Evaluation Criteria Group Marks %age

Project Idea

Code Demonstration
(Is it consistent with the proposed design?)

Interface Bonus
Project Report
(is compiling, formatting, correctness and
completeness in accordance with the given project
report template?)*

Slideshow Presentation

Group Total Sum of all of the above

Individual Effort in project

74 Data Structure and Algorithms Lab Manual


LAB TASK 9 – Binary Trees, Binary Tree Traversals and Level Order Traversal

Name / Group ID: Reg. No:

Class / Section: Date: _

Time Required : 3 hrs


Programming Language : Java
Software Required : Netbeans
Hardware Required : Computer System

Binary Tree Data Structure


A tree whose elements have at most 2 children is called a binary tree. Since each element in a binary tree
can have only 2 children, we typically name them the left and right child.

A Binary Tree node contains following parts.


1. Data
2. Pointer to left child
3. Pointer to right child

Node Code
/* Class containing left and right child of current
node and key value*/
class Node
{
int key;
Node left, right;
public Node(int item)
{
key = item;
left = right = null;

75 Data Structure and Algorithms Lab Manual


}
}

Binary Trees Code


/* Class containing left and right child of current
node and key value*/
class Node
{
int key;
Node left, right;
public Node(int item)
{
key = item;
left = right = null;
}
}
// A Java program to introduce Binary Tree
class BinaryTree
{
// Root of Binary Tree
Node root;

// Constructors
BinaryTree(int key)
{
root = new Node(key);
}
BinaryTree()
{
root = null;
}
public static void main(String[] args)
{
BinaryTree tree = new BinaryTree();
/*create root*/
tree.root = new Node(1);
tree.root.left = new Node(2);
tree.root.right = new Node(3);
tree.root.left.left = new Node(4);
}
}

76 Data Structure and Algorithms Lab Manual


Complete Program

// Java program to insert element in binary tree


import java.util.LinkedList;
import java.util.Queue;
static class Node {
int key;
Node left, right;

// constructor
Node(int key){
this.key = key;
left = null;
right = null;
}
}
public class GFG {
/* A binary tree node has key, pointer to
left child and a pointer to right child */
static Node root;
static Node temp = root;
/* Inorder traversal of a binary tree*/
static void inorder(Node temp)
{
if (temp == null)
return;

inorder(temp.left);
System.out.print(temp.key+" ");
inorder(temp.right);
}

/*function to insert element in binary tree */


static void insert(Node temp, int key)
{
Queue<Node> q = new LinkedList<Node>();
q.add(temp);

// Do level order traversal until we find


// an empty place.
while (!q.isEmpty()) {
temp = q.peek();
q.remove();

77 Data Structure and Algorithms Lab Manual


if (temp.left == null) {
temp.left = new Node(key);
break;
} else
q.add(temp.left);

if (temp.right == null) {
temp.right = new Node(key);
break;
} else
q.add(temp.right);
}
}

// Driver code
public static void main(String args[])
{
root = new Node(10);
root.left = new Node(11);
root.left.left = new Node(7);
root.right = new Node(9);
root.right.left = new Node(15);
root.right.right = new Node(8);

System.out.print( "Inorder traversal before insertion:");


inorder(root);

int key = 12;


insert(root, key);

System.out.print("\nInorder traversal after insertion:");


inorder(root);
}
}

Output:
Inorder traversal before insertion: 7 11 10 15 9 8
Inorder traversal after insertion: 7 11 12 10 15 9 8

Binary Tree Traversals


(a) Preorder
(b) Inorder, and
(c) Postorder.

78 Data Structure and Algorithms Lab Manual


Program

class Node
{ Object data;
Node left;
Node right;
Node( Object d ) // constructor
{ data = d; }
}
class BinaryTree
{
Object tree[];
int maxSize;
java.util.Stack<Node> stk = new java.util.Stack<Node>();

BinaryTree( Object a[], int n ) // constructor


{ maxSize = n;
tree = new Object[maxSize]; for( int i=0;
i<maxSize; i++ )
tree[i] = a[i];
}
public Node buildTree( int index )
{ Node p = null;
if( tree[index] != null )
{ p = new Node(tree[index]);

p.left = buildTree(2*index+1);
p.right = buildTree(2*index+2);
}
return p;
}
/* Recursive methods - Binary tree traversals */ public void
inorder(Node p) {

if( p != null )
{
inorder(p.left);
System.out.print(p.data + " ");
inorder(p.right);
}
}
public void preorder(Node p)
{
if( p != null )
{
System.out.print(p.data + " ");

79 Data Structure and Algorithms Lab Manual


preorder(p.left);
preorder(p.right);
}
}
public void postorder(Node p)
{
if( p != null )
{
postorder(p.left);
postorder(p.right);
System.out.print(p.data + " ");
}
}
/* Non-recursive methods - Binary tree traversals */ public void
preorderIterative(Node p) {

if(p == null )
{ System.out.println("Tree is empty");
return;
}
stk.push(p);
while( !stk.isEmpty() )
{
p = stk.pop();
if( p != null )
{
System.out.print(p.data + " ");
stk.push(p.right);
stk.push(p.left);
}
}
}
public void inorderIterative(Node p)
{
if(p == null )
{ System.out.println("Tree is empty"); return;
}
while( !stk.isEmpty() || p != null )
{
if( p != null )
{ stk.push(p); // push left-most path onto stack p =
p.left;
}
else
{
p = stk.pop(); // assign popped node to p System.out.print(p.data
+ " "); // print node data p = p.right; // move p to right subtree
}
}
}
80 Data Structure and Algorithms Lab Manual
public void postorderIterative(Node p)
{
if(p == null )
{ System.out.println("Tree is empty"); return;
}
Node tmp = p;
while( p != null )
{
while( p.left != null )
{ stk.push(p); p = p.left;
}
while( p != null && (p.right == null || p.right == tmp ))
{ System.out.print(p.data + " "); // print node data tmp = p;
if( stk.isEmpty() )
return;
p = stk.pop();
}
stk.push(p);
p = p.right;
}
}
} // end of BinaryTree class
//////////////////////// BinaryTreeDemo.java //////////////////////
class BinaryTreeDemo
{
public static void main(String args[])
{
Object arr[] = {'E', 'C', 'G', 'A', 'D', 'F', 'H', null,'B', null, null,
null, null, null, null, null, null, null, null};
BinaryTree t = new BinaryTree( arr, arr.length );

Node root = t.buildTree(0); // buildTree() returns reference to root


System.out.print("\n Recursive Binary Tree Traversals:");
System.out.print("\n inorder: "); t.inorder(root);

System.out.print("\n preorder: ");


t.preorder(root);
System.out.print("\n postorder: ");
t.postorder(root);
System.out.print("\n Non-recursive Binary Tree Traversals:");
System.out.print("\n inorder: "); t.inorderIterative(root);
System.out.print("\n preorder: ");
t.preorderIterative(root);
System.out.print("\n postorder: ");
t.postorderIterative(root);
}
81 Data Structure and Algorithms Lab Manual
}

Output:
Recursive Binary Tree Traversals:
inorder: A B C D E F G H
preorder: E C A B D G F H
postorder: B A D C F H G E
Non-recursive Binary Tree Traversals:
inorder: A B C D E F G H
preorder: E C A B D G F H
postorder: B A D C F H G E

Level Order Traversal

Traverse a binary tree level by level. That is, the root is visited first, then the immediate
children of the root (from left to right), then grandchildren of the root (from left to right), and
so on. The algorithm uses a queue to keep track of the children of a node until it is time to
visit them. This algorithm is also known as breadth-first traversal.
1. Initialize a queue.
2. Insert the root into the queue.
3. Repeat steps 4 to 7 until the queue is empty.
4. Delete the node from the queue.
5. Process the node being deleted.
6. If the left child of node exists (is not null), insert it into the queue.
7. If the right child of node exists (is not null), insert it into the queue

82 Data Structure and Algorithms Lab Manual


Program
class Node
{
Object data;
Node left;
Node right;
Node( Object d ) // constructor
{ data = d; }
}
class BinaryTree
{ Object tree[]; int maxSize;
java.util.LinkedList<Node> que =

new java.util.LinkedList<Node>(); BinaryTree(


Object a[], int n ) // constructor { maxSize = n;
tree = new Object[maxSize];
for( int i=0; i<maxSize; i++ )
tree[i] = a[i];
}
public Node buildTree( int index )
{ Node p = null;
if( tree[index] != null )
{ p = new Node(tree[index]);
p.left = buildTree(2*index+1);
p.right = buildTree(2*index+2);
}
return p;
}

public void levelorder(Node p)


{
que.addLast(p);
while( !que.isEmpty() )
{
p = que.removeFirst();
System.out.print(p.data + " ");
if(p.left != null)
que.addLast(p.left);
if(p.right != null)
que.addLast(p.right);
}
}
} // end of BinaryTree class
//////////////////////// LevelOrderTraversal.java //////////////////////
class LevelOrderTraversal
{

83 Data Structure and Algorithms Lab Manual


public static void main(String args[])
{
Object arr[] = {'E', 'C', 'G', 'A', 'D', 'F', 'H', null,'B', null, null,
null, null, null, null, null, null, null, null};
BinaryTree t = new BinaryTree( arr, arr.length );
Node root = t.buildTree(0); // buildTree() returns reference to root

System.out.print("\n Level Order Tree Traversal: ");

t.levelorder(root);
}
}

Output:
Level Order Tree Traversal: E C G A D F H B
Exersises

Exercise 1: (10)
Write a program which should implement a binary tree using a static array of size 10. Elements of this
array of integer type, user will provide values as input for elements of this array. Your program should
allow searching of a value specified by user in tree and it will also provide deletion of a value specified
by user.

84 Data Structure and Algorithms Lab Manual


85 Data Structure and Algorithms Lab Manual
Exercise 2: (10)
Write a program which should implement a binary tree using array. Elements of array are objects of
“student” class. “student” class contains attributes (privately defined) reg_no(int), st_name (string) and
cgpa (float). “student” class should also contain member functions (publicly defined); constructor,
input and output functions. User will insert objects of class “student” array of binary tree, values of
attributes of objects will be provided by user. Program should insert the values using level order
insertion technique.

86 Data Structure and Algorithms Lab Manual


87 Data Structure and Algorithms Lab Manual
LAB TASK 10 – Binary Search Trees

Name / Group ID: Reg. No:

Class / Section: Date: _

Time Required : 3 hrs


Programming Language : Java
Software Required : Netbeans
Hardware Required : Computer System

Binary Search Tree


A binary search tree is a binary tree that is either empty or in which every node contains a key
and satisfies the conditions:
The key in the left child of a node (if it exists) is less than the key in its parent node.
The key in the right child of a node (if it exists) is greater than the key in its parent node.
The left and right subtrees of the root are again binary search trees.
The first two properties describe the ordering relative to the key in the root node, and that the third
property extends them to all nodes in the tree; hence we can continue to use the recursive structure
of the binary tree. After we examine the root of the tree, we shall move to either its left or right
subtree, and this subtree is again a binary search tree. Thus we can use the same method again on
this smaller tree. This definition assumes that no duplicate keys are permitted.

45

25 65
15 30 55 75

10 20 50 60 80

Binary search tree operations

class BSTNode
{
int data;
BSTNode left;
BSTNode right;
BSTNode( int d ) { data = d; }// constructor

88 Data Structure and Algorithms Lab Manual


}
class BinarySearchTree{

public BSTNode insertTree(BSTNode p, int key) // create BST {


if( p == null )
p = new BSTNode(key);
else if( key < p.data)
p.left = insertTree( p.left, key);
else p.right = insertTree( p.right, key);
return p; // return root
}
public BSTNode search(BSTNode root, int key)
{
BSTNode p = root; while(
p != null )
{ if( key == p.data ) return p; else if( key < p.data
) p = p.left; else p = p.right;
}
return null;
}
public int leafNodes(BSTNode p)
{
int count = 0;
if( p != null)
{ if((p.left == null) && (p.right == null))
count = 1;
else
count = count + leafNodes(p.left)
+ leafNodes(p.right);
}
return count;
}
public BSTNode deleteTree(BSTNode root, int key)
{
BSTNode p; // refer to node to be deleted
BSTNode parent = root; // refer to parent of node to be deleted
BSTNode inorderSucc; //refer to inorder succ. of node to be deleted
if(root == null)
{ System.out.println("Tree is empty");
return null;
}
p = root; // initialize p with root
/* find node being deleted & its parent */
while( p != null && p.data != key)
{ parent = p;
if( key < p.data) p = p.left; else p =
p.right;
89 Data Structure and Algorithms Lab Manual
}
if( p == null )
{ System.out.println("\n Node " + key + " not found for deletion"); return null;
}
/* find inorder successor of the node being deleted and its parent */

if(p.left != null && p.right != null) // case-3


{ parent = p; inorderSucc = p.right;
while(inorderSucc.left != null)

{
parent = inorderSucc; inorderSucc =
inorderSucc.left;
}
p.data = inorderSucc.data;
p = inorderSucc;
} // case-
if(p.left == null && p.right == null) 1
{
if( parent.left == p ) parent.left = null;
else parent.right = null;
}
if(p.left == null && p.right != null) // case-2(a)
{
if(parent.left == p) parent.left = p.right;
else parent.right = p.right;
} // case-
if(p.left != null && p.right == null) 2(b)
{
if(parent.left == p) parent.left = p.left;
else parent.right = p.left;
}
return root;
}
// 'p' starts with
public void inorder(BSTNode p) root
{ if( p != null )
{ inorder(p.left);
System.out.print(p.data + " ");
inorder(p.right);
}
}
public void preorder(BSTNode p)
{ if( p != null )
{ System.out.print(p.data + " ");
preorder(p.left);
preorder(p.right);
}
}
public void postorder(BSTNode p)
90 Data Structure and Algorithms Lab Manual
{ if( p != null )
{ postorder(p.left); postorder(p.right);
System.out.print(p.data + " ");
}
}
} // end of BinarySearchTree class
////////////////////// BinarySearchTreeDemo.java //////////////////// class
BinarySearchTreeDemo
{ public static void main(String args[])
{
int arr[] = { 45, 25, 15, 10, 20, 30, 65, 55, 50, 60, 75, 80 };
BinarySearchTree bst = new BinarySearchTree();

BSTNode root = null;


// build tree by repeated insertions
for( int i = 0; i < arr.length; i++ )
root = bst.insertTree( root, arr[i]);
BSTNode root2 = root; // copy BST

int key = 66;


BSTNode item = bst.search(root2, key);
if( item != null )
System.out.print("\n item found: " + item.data);
else System.out.print("\n Node " + key + " not found");
System.out.print("\n Number of leaf nodes: " + bst.leafNodes(root));

System.out.print("\n Inorder: ");


bst.inorder(root);
System.out.print("\n Preorder: ");
bst.preorder(root);
System.out.print("\n Postorder: ");
bst.postorder(root);
key = 55; // delete 55
bst.deleteTree(root, key);
System.out.print("\n Inorder, after deletion of " + key + ": "); bst.inorder(root);
key = 44; // insert 44
bst.insertTree(root, key);
System.out.print("\n Inorder, after insertion of " + key + ": "); bst.inorder(root);
}
}

Output:

Node 66 not found


Number of leaf nodes: 6
Inorder: 10 15 20 25 30 45 50 55 60 65 75 80

91 Data Structure and Algorithms Lab Manual


Preorder: 45 25 15 10 20 30 65 55 50 60 75 80
Postorder: 10 20 15 30 25 50 60 55 80 75 65 45
Inorder, after deletion of 55: 10 15 20 25 30 45 50 60 65 75 80
Inorder, after insertion of 44: 10 15 20 25 30 44 45 50 60 65 75 80
Exercises:

Exersise 1 [5]
Write a program which should implement a binary search tree containing floating point values as its
elements. Program should allow user to insert a value in tree and program should also perform pre
order, post order and in order traversal of this tree. Program should also count the number of nodes
present in the tree.
2.3

2.1 3.4

1.9 5.6

1.5

92 Data Structure and Algorithms Lab Manual


93 Data Structure and Algorithms Lab Manual
Exersise 2 [5]
Write a program which should implement a binary serach tree using linked list. Elements of tree are
objects of “student” class. “student” class contains attributes (privately defined) reg_no(int), st_name
(string) and cgpa (float). “student” class should also contain member functions (publicly defined);
constructor, input and output functions. User will insert objects of class “student” in binary tree, values
of attributes of objects will be provided by user. Program should display the objects of student class in
pre order, post order and in order traversal formats. Program should also search an object from tree
which is provided by user as input.

94 Data Structure and Algorithms Lab Manual


Practical Application of Binary Search Trees
Obscure binary search trees
Items, such as names, numbers, etc. can be stored in memory in a sorted order called binary search
trees or BSTs. And some of these data structures can automatically balance their height when arbitrary
items are inserted or deleted. Therefore, they are known as self-balancing BSTs. Further, there can be
different implementations of this type, like the BTrees, AVL trees, and red-black trees. But there are
many other lesser-known executions that you can learn about. Some examples include AA trees, 2-3
trees, splay trees, scapegoat trees, and treaps.

You can base your project on these alternatives and explore how they can outperform other widely-
used BSTs in different scenarios. For instance, splay trees can prove faster than red-black trees under
the conditions of serious temporal locality.

BSTs following the memoization algorithm


Memoization related to dynamic programming. In reduction-memoizing BSTs, each node can memoize
a function of its subtrees. Consider the example of a BST of persons ordered by their ages. Now, let the
child nodes store the maximum income of each individual. With this structure, you can answer queries
like, “What is the maximum income of people aged between 18.3 and 25.3?” It can also handle
updates in logarithmic time.

Moreover, such data structures are easy to accomplish in C language. You can also attempt to bind it
with Ruby and a convenient API. Go for an interface that allows you to specify ‘lambda’ as your
ordering function and your subtree memoizing function. All in all, you can expect reduction-memoizing
BSTs to be self-balancing BSTs with a dash of additional book-keeping.

Dynamic coding will need cognitive memorisation for its implementation. Each vertex in a reducing BST
can memorise its sub–trees’ functionality. For example, a BST of persons is categorised by their age.

This DSA topics based project idea allows the kid node to store every individual’s maximum salary. This
framework can be used to answer the questions like “what’s the income limit of persons aged 25 to
30?”

95 Data Structure and Algorithms Lab Manual


LAB TASK 11 – Balanced Trees

Name / Group ID: Reg. No:

Class / Section: Date: _

Time Required : 3 hrs


Programming Language : Java
Software Required : Netbeans
Hardware Required : Computer System

Balanaced Tree
A B-tree of order m is an m-way tree in which
All leaf nodes are on the same level.
All nodes, except the root and the leaves, have between [m/2] and m children.
The nonleaf nodes store up to m-1 keys to guide the searching; and these keys partition the keys in
the children in the fashion of a search tree.
The root is either a leaf or has between two and m children.
If a node has ‘d’ number of children, then it must have d-1 number of keys.

Program B-Tree

class BTree
{
final int MAX = 4;
final int MIN = 2;

class BTNode // B-Tree node


{
int count;
int key[] = new int[MAX+1];
BTNode child[] = new BTNode[MAX+1];
}
BTNode root = new BTNode();
class Ref // This class creates an object reference
{ int m; } // and is used to retain/save index values
// of current node between method calls.
/*
* New key is inserted into an appropriate node.
* No node has key equal to new key (duplicate keys are not allowed.

96 Data Structure and Algorithms Lab Manual


*/
void insertTree( int val )
{
Ref i = new Ref();
BTNode c = new BTNode();
BTNode node = new BTNode();
boolean pushup;
pushup = pushDown( val, root, i, c );

if ( pushup )
{
node.count = 1;
node.key[1] = i.m;
node.child[0] = root;
node.child[1] = c;
root = node;
}
}
/*
* New key is inserted into subtree to which current node points.
* If pushup becomes true, then height of the tree grows.
*/
boolean pushDown( int val, BTNode node, Ref p, BTNode c )
{
Ref k = new Ref();
if ( node == null )
{
p.m = val;
c = null;
return true;
}
else
{
if ( searchNode( val, node, k ) ) System.out.println("Key
already exists.");
if ( pushDown( val, node.child[k.m], p, c ) )
{

if ( node.count < MAX )


{

97 Data Structure and Algorithms Lab Manual


pushIn( p.m, c, node, k.m );
return false;
}
else
{
split( p.m, c, node, k.m, p, c );
return true;
}
}
return false;
}
}
/*
* Search through a B-Tree for a target key in the node: val
* Outputs target node and its position (pos) in the node
*/
BTNode searchTree( int val, BTNode root, Ref pos )
{
if ( root == null )
return null ;
else
{
if ( searchNode( val, root, pos ) )
return root;
else
return searchTree( val, root.child[pos.m], pos );
}
}
/*
* This method determines if the target key is present in
* the current node, or not. Seraches keys in the current node;
* returns position of the target, or child on which to continue search.
*/
boolean searchNode( int val, BTNode node, Ref pos )
{
if ( val < node.key[1] )
{
pos.m = 0 ; return false
;
}
else
{
pos.m = node.count ;
while ( ( val < node.key[pos.m] ) && pos.m > 1 ) (pos.m)--;
if ( val == node.key[pos.m] ) return
true;
else
return false;
}
}
100 Data Structure and Algorithms Lab Manual
/*
* Inserts the key into a node, if there is room

* for the insertion


*/
void pushIn( int val, BTNode c, BTNode node, int k )
{
int i ;
for ( i = node.count; i > k ; i-- )
{
node.key[i + 1] = node.key[i]; node.child[i +
1] = node.child[i];
}
node.key[k + 1] = val ;
node.child[k + 1] = c ; node.count++ ;
}
/*
* Splits a full node into current node and new right child
* with median.
*/
void split( int val, BTNode c, BTNode node,
int k, Ref y, BTNode newnode )
{
int i, mid; // mid is median
if ( k <= MIN )
mid = MIN;
else
mid = MIN + 1;
newnode = new BTNode();
for ( i = mid+1; i <= MAX; i++ )
{
newnode.key[i-mid] = node.key[i];
newnode.child[i-mid] = node.child[i];
}
newnode.count = MAX - mid;
node.count = mid;
if ( k <= MIN )
pushIn ( val, c, node, k );
else
pushIn ( val, c, newnode, k-mid ) ;
y.m = node.key[node.count];
newnode.child[0] = node.child[node.count] ;
node.count-- ;
}

101 Data Structure and Algorithms Lab Manual


// calls display( ) void
displayTree()
{
display( root );
}
// displays the B-Tree
void display( BTNode root )
{

int i;

if ( root != null )
{
for ( i = 0; i < root.count; i++ )
{
display( root.child[i] );
System.out.print( root.key[i+1] + " " );
}
display( root.child[i] );
}
}
} // end of BTree class
////////////////////////// BTreeDemo.java /////////////////////////////
class BTreeDemo
{
public static void main( String[] args )
{
BTree bt = new BTree();
/*
* Refer Textbook, the section 13.3 B-Trees,
* inserting into a B-Tree
* Figure 13.30: Building a B-tree of order 5
*/
int[] arr = { 11, 23, 21, 12, 31, 18, 25, 35, 29, 20, 45, 27, 42, 55, 15, 33,
36, 47, 50, 39 };
for ( int i = 0; i < arr.length; i++ )
bt.insertTree( arr[i] );
System.out.println("B-Tree of order 5:");
bt.displayTree();
}
}

102 Data Structure and Algorithms Lab Manual


Output:
B-Tree of order 5:
11 12 15 18 20 21 23 25 27 29 31 33 35 36 39 42 45 47 50 55

Exersise [1o]
Write a deletion method

103 Data Structure and Algorithms Lab Manual


LAB TASK 13 – Dictionary using Hashing and HashTable

Name / Group ID: Reg. No:

Class / Section: Date: _

Time Required : 3 hrs


Programming Language : Java
Software Required : Netbeans
Hardware Required : Computer System

Dictionary
An ADT that supports the operations insert, delete, and search is called a dictionary. Dictionaries are
found applications in the design of numerous algorithms. A dictionary is a collection of pairs of key and
element. No two pairs in a dictionary have the same key.
Consider a database of books maintained in a library system. When a user wants to check whether a
particular book is available, a search operation is called for. If the book is available and is issued to the
user, a delete operation can be performed to remove this book from the set of available books. When the
user returns the book, it can be inserted back into the set.
It is essential that we are able to support the above-mentioned operations as efficiently as possible since
these operations are performed quite frequently. A number of data structures have been developed to
realize a dictionary. These can be broadly divided into comparison methods and direct access methods.
Hashing is an example of the latter. Comparison methods fit into binary search trees.
Program Dictionary operations using Hash tables

class Entry
{ public String key; // word
public String element; // word meaning
public Entry(String k, String e) // constructor
{
key = k;
element = e;
}
}
class HashTable
{
Entry[] hashArray; // array holds hash table
int size; // table size
// current number of items in the
int count; table
public HashTable(int s) // constructor
{
size = s;
count = 0;
hashArray = new Entry[size];

104 Data Structure and Algorithms Lab Manual


}
int hashFunc( String theKey ) // convert the string into a numeric key
{
int hashVal=0;

// convert the string into a numeric key


for(int i = 0; i < theKey.length(); i++)
hashVal = 37*hashVal + (int)theKey.charAt(i);
hashVal = hashVal % size;

if(hashVal < 0 )
hashVal = hashVal + size;
return hashVal;
}
public void insert(String theKey, String str) // insert a record {
if( !isFull() )
{
int hashVal = hashFunc(theKey); // hash the key
// until empty cell or null,
while(hashArray[hashVal] != null )
++hashVal; // go to next cell
hashVal
%= size; // wraparound if necessary
}
hashArray[hashVal] = new Entry(theKey, str);

count++; // update count


}
else
System.out.println("Table is full");
}
public Entry delete(String theKey) // delete a record with the key {
if( !isEmpty() )
{
int hashVal = hashFunc(theKey); // hash the key
while(hashArray[hashVal] != null) // until empty cell, {
if(hashArray[hashVal].key == theKey) // found the key?
{ Entry tmp = hashArray[hashVal]; // save item
hashArray[hashVal] = null; // delete item count--;
return tmp; // return item
}
++hashVal; // go to next cell
hashVal %= size; // wraparound if necessary
}

105 Data Structure and Algorithms Lab Manual


return null; // cannot find item
}
else
System.out.println("Table is empty");
return null;
}
public Entry search(String theKey) // find item with key {
int hashVal = hashFunc(theKey); // hash the key
while(hashArray[hashVal] != null) // until empty cell, {
if(hashArray[hashVal].key == theKey) // found the key?

return hashArray[hashVal]; // yes, return item

++hashVal; // go to next cell

hashVal %= size; // wraparound if necessary


}
return null; // cannot find item
}
public void displayTable()
{
System.out.println("<< Dictionary Table >>\n");
for(int i=0; i<size; i++)
{
if(hashArray[i] != null ) System.out.println( hashArray[i].key
+ "\t" +
hashArray[i].element );

}
}
public boolean isEmpty() // returns true, if table is empty {
return count == 0;
}
public boolean isFull() // returns true, if table is full {

return count == size;


}
public int currentSize()
{
return count;
}
}
///////////////////////// Dictionary.java ////////////////////////////
class Dictionary
106 Data Structure and Algorithms Lab Manual
{
public static void main(String[] args)
{
HashTable ht = new HashTable(19); // create hash table of size, 19
// Insert the following items into hash table
ht.insert("man", "gentleman"); ht.insert("watch",
"observe"); ht.insert("hope", "expect");
ht.insert("arrange", "put together"); ht.insert("run",
"sprint"); ht.insert("wish", "desire");
ht.insert("help", "lend a hand"); ht.insert("insert",
"put in"); ht.insert("count", "add up");
ht.insert("format", "arrangement");
ht.displayTable(); // Display the table items

// Search an item
String word = "wish";
Entry item = ht.search(word);
if( item != null )
System.out.println("found: " + item.key + "\t" + item.element); else
System.out.println(word + " not found");
// Delete an item word =
"hope";
item = ht.delete(word); if( item !=
null )
System.out.println("deleted: " + item.key + "\t" + item.element); else
System.out.println(word + " not found - no deletion");
// Current number of items in the table
System.out.println("size: " + ht.currentSize());
}

}
Output:
<< Dictionary Table >>
insert put in
help lend a hand
man gentleman
watch observe
format arrangement
run sprint
wish desire
arrange put together
hope expect
count add up

108 Data Structure and Algorithms Lab Manual


found: wish desire
107 Data Structure and Algorithms Lab Manual
deleted: hope expect
size: 9

Program Dictionary operations using java.util.Hashtable

import java.util.*;
class HashtableDemo
{ public static void main(String[] args)
{
Hashtable<String, String> htab = new Hashtable<String, String>();
// Insert the following items
htab.put("man", "gentleman");
htab.put("watch", "observe");
htab.put("hope", "expect");
htab.put("arrange", "put together");
htab.put("run", "sprint");
htab.put("wish", "desire");
htab.put("help", "lend a hand");
htab.put("insert", "put in");
htab.put("count", "add up");
htab.put("format", "arrangement");
System.out.println(htab); // Display the table items

System.out.println("get(hope): " + htab.get("hope"));

System.out.println("remove(arrange): " + htab.remove("arrange"));


System.out.println("remove(help): " + htab.remove("help"));
// returns a set containing all the pairs (key, value).
System.out.println(htab.entrySet());
}
}

Output:
{ arrange=put together, man=gentleman, wish=desire, run=sprint, help=lend a hand, count=add
up, watch=observe, hope=expect, format=arrangement, insert=put in }
get(hope): expect
remove(arrange): put together
remove(help): lend a hand
[ man=gentleman, wish=desire, run=sprint, count=add up, watch=observe, hope=expect,
format=arrangement, insert=put in ]
Exercises

109 Data Structure and Algorithms Lab Manual


Exersise 1 [5]
Given an array of n integers. The task is to find the first element that occurs k number of times. If
no element occurs k times the print -1. The distribution of integer elements could be in any
range.

110 Data Structure and Algorithms Lab Manual


111 Data Structure and Algorithms Lab Manual
Exersise 2 [5]
Given an array of size N with repeated numbers, You Have to Find the top three repeated
numbers.
Note : If Number comes same number of times then our output is one who comes first in array

112 Data Structure and Algorithms Lab Manual


113 Data Structure and Algorithms Lab Manual
LAB TASK 14 – Heap

Name / Group ID: Reg. No: _

Class / Section: Date: _

Time Required : 3 hrs


Programming Language : Java
Software Required : Netbeans
Hardware Required : Computer System

Heap ADT

Linked structures are not the only way in which you can represent trees. If you take the binary tree
shown below and copy its contents into an array in level order, you produce the following array.

Index Entry
93
0 93
1 82
2 64
82 64
3 27
4 75
5 39
27 75 39 18 6 18

Examining the relationship between positions in the tree and entries in the array, you see that if an
element is stored in entry N in the array, then the elementÕs left child is stored in entry 2N + 1, its right
child is stored in entry 2N + 2, and its parent is stored in entry (N 1) / 2. These mappings make it easy to
move through the tree stepping from parent to child (or vice versa).
You could use these mappings to support an array-based implementation of the Binary Search Tree
ADT. However, the result would be a tree representation in which large areas of the array are left unused
(as indicated by the dashes in the following array).

114 Data Structure and Algorithms Lab Manual


Index Enty
43
0 43
1 20
2 72
20 72
3 16
4 31
5 65
16 31 65 86 6 86
7 Ñ
8 Ñ

92
13 Ñ
14 92

A heap is a binary tree that meets the following conditions.


The tree is complete. That is, every level in the tree is Þlled, except possibly the bottom level. If the
bottom level is not Þlled, then all the missing elements occur on the right.
Each element in the tree has a corresponding value. For each element E, all of EÕs descen-dants have
values that are less than or equal to EÕs value. Therefore, the root stores the maxi-mum of all values in
the tree. (Note: In this laboratory we are using a max-heap. There is another heap variant called a min-
heap. In a min-heap, all of EÕs descendants have values that are greater than or equal to EÕs value.)
The tree shown at the beginning of this laboratory is a heap, as is the tree shown below.

72

72 34

26 66 9

The fact that the tree is complete means that a heap can be stored in level order in an array without
introducing gaps (unused areas) in the middle. The result is a compact representation in which you can
easily move up and down the branches in a heap.

115 Data Structure and Algorithms Lab Manual


Clearly, the relationship between the priorities (or values) of the various elements in a heap is not
strong enough to support an efÞcient search process. Because the relationship is simple, however,
you can quickly restructure a heap after removing the highest priority (root) element or after
inserting a new element. As a result, you can rapidly process the elements in a heap in descending
order based on priority. This property combined with the compact array represen-tation forms the
basis for an efÞcient sorting algorithm called heap sort (In-lab Exercise 2) and makes a heap an ideal
representation for a priority queue (In-lab Exercise 3).

Heap ADT Elements


The elements in a heap are of generic type HeapData deÞned in the Þle HeapData.java. Each element
has a priority that is used to determine the relative position of the element within the heap. Elements
usually include additional data. Note that priorities are not uniqueÑit is quite likely that several
elements have the same priority. These objects must support the six basic relational operators, as
well as a method called pty( ) that returns an elementÕs priority.

Structure
The elements form a complete binary tree. This is a max-heap. For each element E in the tree, all of
EÕs descendants have priorities that are less than or equal to EÕs priority.

Constructors and Methods


Heap ( )
Precondition:
None.
Postcondition:
Default Constructor. Calls setup, which creates an empty heap. Allocates enough memory for a
heap containing DEF_MAX_HEAP_SIZE (a constant value) elements.
Heap ( int maxNumber )
Precondition:
maxNumber > 0.
Postcondition:
Constructor. Calls setup, which creates an empty heap. Allocates enough memory for a heap
containing maxNumber elements.
void setup ( int maxNumber )
Precondition:
maxNumber > 0. A helper method for the constructors. Is declared private since only heap
constructors should call this method.
Postcondition:
Creates an empty heap. Allocates enough memory for a heap containing maxNumber ele-
ments.
void insert ( HeapData newElement )
Precondition:
Heap is not full.

116 Data Structure and Algorithms Lab Manual


Postcondition:
Inserts newElement into a heap. Inserts this element as the bottom rightmost element in the heap
and moves it upward until the properties that deÞne a heap are restored. Note that repeatedly
swapping array elements is not an efÞcient way of positioning the newElement in the heap.

HeapData removeMax ( )
Precondition:
Heap is not empty.
Postcondition:
Removes the element with the highest priority (the root) from a heap and returns it. Replaces the
root element with the bottom rightmost element and moves this element downward until the
properties that deÞne a heap are restored. Note that (as in insert above) repeatedly swapping array
elements is not an efÞcient method for restoring the heap.

void clear ( )
Precondition:
None.
Postcondition:
Removes all the elements in a heap.

boolean isEmpty ( )
Precondition:
None.
Postcondition:
Returns true if a heap is empty. Otherwise, returns false.

boolean isFull ( )
Precondition:
None.
Postcondition:
Returns true if a heap is full. Otherwise, returns false.

void showStructure ( )
Precondition:
None.
Postcondition:
Outputs the priorities of the elements in a heap in both array and tree form. The tree is out-put
with its branches oriented from left (root) to right (leaves)Ñthat is, the tree is output rotated
counterclockwise 90 degrees from its conventional orientation. If the heap is empty, outputs
ÒEmpty heapÓ. Note that this operation is intended for testing/debugging purposes only.

Exersise 01 [4]
Write a program which should implement a max heap tree containing floating point values as its
elements. Program should allow user to insert a value in tree and program should perform search a value
input by user to check whether it exists in tree or not?

117 Data Structure and Algorithms Lab Manual


Exersise 02 [6]
Cash Flow Minimiser (Graphs/Multisets/Heaps)
 Cash flow is the net balance of cash moving into or out of business at a specific time.
 An application cash flow minimizer can be built using Graphs concepts to minimize this cash flow.
 For example, Assume three friends: friend one, friend two, and friend three. Friend one has to give 4k
to friend three and 2k to friend one.
 And friend two has to give 3k to friend three. Now minimize the flow between friend one and friend
two by direct payment to friend three by friend one.
 An application can be created with the same mechanism for translation
118 Data Structure and Algorithms Lab Manual
Practical Application of Heaps

Heap insertion time (average case insertion time for binary heap data
structures )
119 Data Structure and Algorithms Lab Manual
According to some online sources, it is constant time, while others imply that it is log(n) time. But
Bollobas and Simon give a numerically-backed answer in their paper entitled, “Repeated random
insertion into a priority queue.” First, they assume a scenario where you want to insert n elements into
an empty heap. There can be ‘n!’ possible orders for the same. Then, they adopt the average cost
approach to prove that the insertion time is bound by a constant of 1.7645.

When looking for Data Structures tasks in this project idea, you will face challenges that are addressed
using novel methods. One of the interesting research subjects is the mean response insertion time for the
sequential heap DS.

Inserting ‘n’ components into an empty heap will yield ‘n!’ arrangements which you can use in suitable
DSA projects in C++. Subsequently, you can implement the estimated cost approach to specify that the
inserting period is limited by a fixed constant.
Optimal treaps with priority-changing parameters
Treaps are a combination of BSTs and heaps. These randomized data structures involve assigning
specific priorities to the nodes. You can go for a project that optimizes a set of parameters under
different settings. For instance, you can set higher preferences for nodes that are accessed more
frequently than others. Here, each access will set off a two-fold process:
 Choosing a random number
 Replacing the node’s priority with that number if it is found to be higher than the previous priority

As a result of this modification, the tree will lose its random shape. It is likely that the frequently-
accessed nodes would now be near the tree’s root, hence delivering faster searches. So, experiment with
this data structure and try to base your argument on evidence.

At the end of the project, you can either make an original discovery or even conclude that changing the
priority of the node does not deliver much speed. It will be a relevant and useful exercise, nevertheless.

Constructing a heap involves building an ordered binary tree and letting it fulfill the “heap” property.
But if it is done using a single element, it would appear like a line. This is because in the BST, the right
child should be greater or equal to its parent, and the left child should be less than its parent. However,
for a heap, every parent must either be all larger or all smaller than its children.

The numbers show the data structure’s heap arrangement (organized in max-heap order). The alphabets
show the tree portion. Now comes the time to use the unique property of treap data structure in DSA
projects in C++. This treap has only one arrangement irrespective of the order by which the elements
were chosen to build the tree.

You can use a random heap weight to make the second key more useful. Hence, now the tree’s structure
will completely depend on the randomized weight offered to the heap values. In the file structure mini
project topics, we obtain randomized heap priorities by ascertaining that you assign these randomly.

120 Data Structure and Algorithms Lab Manual


LAB TASK 15 – Graphs using Adjacency list and Adjacency Matrix and Memory
Management

Name / Group ID: Reg. No:

Class / Section: Date: _

Time Required : 3 hrs


Programming Language : Java
Software Required : Netbeans
Hardware Required : Computer System

Graph Traversals
A primary problem concerning the graphs is the reachability. A number of graph problems involve
traversal of a graph. Traversal of a graph means visiting each of its nodes exactly once. This is
accomplished by visiting the nodes in a systematic manner. Two commonly used techniques of
graph traversal are depth-first search (DFS) and breadth-first search (BFS). These algorithms work
for both directed and undirected graphs.

Depth-First Search
Depth-first search is a generalization of the preorder traversal of a tree. DFS can serve as a structure
around which many other efficient graph algorithms can be built.
As an example of dfs, suppose in the graph of the following figure, we start at node A. A complete
program listing is given in Program 31(a).

A A B D E X A B C D E

A 0 1 0 1 1
B A C D X

B 1 0 1 1 0

B D C B D E X

E C 0 1 0 1 1
D A B C X D 1 1 1 0 0

C E A C X E 1 0 1 0 0
Undirected Adjacency
Graph Adjacency list matrix

121 Data Structure and Algorithms Lab Manual


Program
class Node
{ int label; // vertex label
// next node in
Node next; list
Node( int b ) // constructor
{ label = b; }
}
class Graph
{ int size; Node adjList[];
int mark[];
Graph(int n) // constructor

{ size = n;

adjList = new Node[size];


mark = new int[size]; // elements of mark are initialized to 0
}
public void createAdjList(int a[][]) // create adjacent lists
{
Node p; int i, k;
for( i = 0; i < size; i++ )
{ p = adjList[i] = new Node(i); //create first node of ith adj. list for( k
= 0; k < size; k++ )
{ if( a[i][k] == 1 )
{ p.next = new Node(k); // create next node of ith adj. list
p = p.next;
}
}
}
}
public void dfs(int head) // recursive depth-first search
{ Node w; int v; mark[head] = 1;
System.out.print( head + " "); w =
adjList[head];

while( w != null)
{ v = w.label;
if( mark[v] == 0 ) dfs(v); w =
w.next;
}
}
}

///////////////////////// DfsDemo.java ////////////////////////


class DfsDemo
{ public static void main(String[] args)

122 Data Structure and Algorithms Lab Manual


{ Graph g = new Graph(5); // graph is created with 5 nodes
int a[][] = { {0,1,0,1,1}, {1,0,1,1,0}, {0,1,0,1,1},
{1,1,1,0,0}, {1,0,1,0,0}};
g.createAdjList(a);
g.dfs(0); // starting node to dfs (i.e., A)
is 0
}
}
Output:

123 Data Structure and Algorithms Lab Manual


Here, 0 is for A, 1 is for B, 2 is for C, 3 is for D, and 4 is for E

Breadth-First Search
Another systematic way of visiting the nodes is called breadth- first search (bfs). The approach is
called “breadth-first” because from each node v that we visit we search as broadly as possible by
next visiting all nodes adjacent to v.
The breadthFirstSearch algorithm inserts a node into a queue, which we assume is initially empty.
Every entry in the array mark is assumed to be initialized to the value unvisited. If the graph is not
connected, bfs must be called on a node of each connected component. Note that in bfs we must
mark a node visited before inserting it into the queue, to avoid placing it on the queue more than
once. The algorithm terminates when the queue becomes empty.

We assume the graph is represented by an adjacency list and is globally available. The algorithm
depends on the availability of an implementation of a queue of integers (here, a simple queue is
assumed; not circular queue). Three methods relating to queue: qinsert(), qdelete(), and isEmpty() are to
be properly defined before the method for bfs is defined.

Program
class Node
{ int label; // vertex label
// next node in
Node next; list
Node( int b ) // constructor
{ label = b; }
}
class Graph
{ int size; Node adjList[];
int mark[];
Graph(int n) // constructor
{ size = n;
adjList = new Node[size];
mark = new int[size];
}
public void createAdjList(int a[][]) // create adjacent lists
{ Node p; int i, k;
for( i = 0; i < size; i++ )
{ p = adjList[i] = new Node(i); for( k = 0; k
< size; k++ ) { if( a[i][k] == 1 )
{ p.next = new Node(k);
p = p.next;
}
} // end of inner for-loop
} // end of outer for-loop
} // end of createAdjList()
public void bfs(int head)
{ int v; Node adj;
Queue q = new Queue(size);
124 Data Structure and Algorithms Lab Manual
v = head;
mark[v] = 1;
System.out.print(v + " ");
q.qinsert(v); // while(queue not
while( !q.IsEmpty() ) empty)
{

125 Data Structure and Algorithms Lab Manual


v = q.qdelete();
adj = adjList[v];
while( adj != null )
{ v = adj.label;
if( mark[v] == 0 )
{ q.qinsert(v); mark[v] =
1;
System.out.print(v + " ");
}

adj = adj.next;
}
}
}
} // end of Graph class
class Queue
{ private int maxSize; // max queue size
// que is an array of
private int[] que; integers
private int front;
private int rear; // count of items in
private int count; queue
public Queue(int s) // constructor
{ maxSize = s;
que = new int[maxSize]; front =
rear = -1;
}
public void qinsert(int item)
{ if( rear == maxSize-1 ) System.out.println("Queue is
Full");
else { rear = rear + 1;
que[rear] = item;
if( front == -1 ) front = 0;
}
}
public int qdelete()
{ int item;
if( IsEmpty() )
{ System.out.println("\n Queue is Empty");
return(-1);
}
item = que[front];
if( front == rear ) front = rear = -1;
else front = front+1;
return(item);
126 Data Structure and Algorithms Lab Manual
}
public boolean IsEmpty()
{ return( front == -1 ); }
} // end of Queue class
//////////////////////////////////////////////////////////
class BfsDemo
{ public static void main(String[] args) { Graph g =
new Graph(5);
int a[][] = { {0,1,0,1,1}, {1,0,1,1,0}, {0,1,0,1,1}, {1,1,1,0,0},
{1,0,1,0,0}};
g.createAdjList(a);
g.bfs(0);
}
}

Output
01342

Practical Application of BFS and DFS


Knight’s travails
This problem, utilizes two algorithms in action – BFS and DFS. BFS stands for Breadth-First Search and utilizes the
Queue data structure to find the shortest path. Whereas, DFS refers to Depth-First Search and traverses Stack data
structures.

For starters, you will need a data structure similar to binary trees. Now, suppose that you have a standard 8 X 8
chessboard, and you want to show the knight’s movements in a game. As you may know, a knight’s basic move in
chess is two forward steps and one sidestep. Facing in any direction and given enough turns, it can move from any
square on the board to any other square.

If you want to know the simplest way your knight can move from one square (or node) to another in a two-
dimensional setup, you will first have to build a function like the one below.

knight_plays([0,0], [1,2]) == [[0,0], [1,2]]


knight_plays([0,0], [3,3]) == [[0,0], [1,2], [3,3]]
knight_plays([3,3], [0,0]) == [[3,3], [1,2], [0,0]]

Furthermore, this project would require the following tasks:


 Creating a script for a board game and a night
 Treating all possible moves of the knight as children in the tree structure
 Ensuring that any move does not go off the board
 Choosing a search algorithm for finding the shortest path in this case
 Applying the appropriate search algorithm to find the best possible move from the starting square to the ending
square.

127 Data Structure and Algorithms Lab Manual


Exersise [1o]
Map Navigator(Dijkstra's Algorithm)
 Everyone is well-known for Google Maps. Google map is an efficient application showing the shortest path from
source to destination.
 Google Maps application is built using Dijkstra's algorithm.
 We can build the same application for the metro using Dijkstra's algorithm
 Dijkstra's algorithm efficiently finds the minimum distance between nodes using the edge values.
 We can consider the stations as nodes and distance as edges; by using Dijkstra's algorithm, we can find the shortest
time path and shortest cost path.

128 Data Structure and Algorithms Lab Manual


Memory Management

Most data structures are designed to store and access objects of uniform size. A typical example would
be an integer stored in a list or a queue. Some applications require the ability to store variable-length
records, such as a string of arbitrary length. One solution is to store in list or queue a bunch of pointers
to strings, where each pointer is pointing to space of whatever size is necessary to old that string. This is
fine for data structures stored in main memory. But if the collection of strings is meant to be stored on
disk, then we might need to worry about how exactly these strings are stored. And even when stored in
main memory, something has to figure out where there are available bytes to hold the string. In a
language like C++ or Java, programmers can allocate space as necessary (either explicitly with new or
implicitly with a variable declaration). Where does this space come from? This section discusses
memory management techniques for the general problem of handling space requests of variable size.

The basic model for memory management is that we have a (large) block of contiguous memory
locations, which we will call the memory pool. Periodically, memory requests are issued for some
amount of space in the pool. A memory manager has the job of finding a contiguous block of locations
of at least the requested size from somewhere within the memory pool. Honoring such a request is
called memory allocation. The memory manager will typically return some piece of information that the
requestor can hold on to so that later it can recover the data that were just stored by the memory
manager. This piece of information is called a handle. At some point, space that has been requested
might no longer be needed, and this space can be returned to the memory manager so that it can be
reused. This is called a memory deallocation. We can define an ADT for a simple memory manager for
storing variable length arrays of integers as follows.

// Memory Manager abstract class


public interface MemManager {
// Store a record and return a handle to it
public MemHandle insert(byte[] info);

// Release the space associated with a record


public void release(MemHandle h);

// Get back a copy of a stored record


public byte[] getRecord(MemHandle h);
}

The user of the MemManager ADT provides a pointer (in parameter info) to space that holds some
message to be stored or retrieved. This is similar to the C++ basic file read/write methods. The
fundamental idea is that the client gives messages to the memory manager for safe keeping. The
memory manager returns a receipt for the message in the form of a MemHandleobject. The client holds
the MemHandle until it wishes to get the message back.

Method insert lets the client tell the memory manager the length and contents of the message to be
stored. This ADT assumes that the memory manager will remember the length of the message associated

129 Data Structure and Algorithms Lab Manual


with a given handle, thus method getRecord does not include a length parameter but instead returns the
message actually stored. Method release allows the client to tell the memory manager to release the
space that stores a given message.

When all inserts and releases follow a simple pattern, such as last requested, first released (stack order),
or first requested, first released (queue order), memory management is fairly easy. We are concerned
here with the general case where blocks of any size might be requested and released in any order. This is
known as dynamic memory allocation. One example of dynamic memory allocation is managing free
store for a compiler's runtime environment, such as the system-level new and delete operations in C++.
Another example is managing main memory in a multitasking operating system. Here, a program might
require a certain amount of space, and the memory manager must keep track of which programs are
using which parts of the main memory. Yet another example is the file manager for a disk drive. When a
disk file is created, expanded, or deleted, the file manager must allocate or deallocate disk space.

A block of memory or disk space managed in this way is sometimes referred to as a heap. The term
"heap" is being used here in a different way than the heap data structure typically used to implement a
priority queue. Here "heap" refers to the memory controlled by a dynamic memory management
scheme.

Exersises

Exersise [1o]
Given two four digit prime numbers, suppose 1033 and 8179, we need to find the shortest path from
1033 to 8179 by altering only single digit at a time such that every number that we get after changing a
digit is prime. For example a solution is 1033, 1733, 3733, 3739, 3779, 8779, 8179
Examples:
Input : 1033 8179
Output :6

Input : 1373 8017


Output : 7

Input : 1033 1033


Output : 0

130 Data Structure and Algorithms Lab Manual


LAB TASK 16 – SEMESTER PROJECT PRESENTATION

Name / Group ID: Reg.


No:
Class / Section: Date:

Objectives
• Learn to implement the real problem using Java.

Time Required : 3 hrs


Programming Language : NIL
Software Required : Web browser.
Hardware Required : computer system

Introduction: Present your semester project on a projector in class for final evaluation.
Submit the project report to the instructor.

For every group project, evaluation will be done on the following criteria:

Evaluation Criteria Group Marks %age

Project Idea

Code Demonstration
(Is it consistent with the proposed design?)

Interface Bonus
Project Report
(is compiling, formatting, correctness and
completeness in accordance with the given project
report template?)*

Slideshow Presentation

Group Total Sum of all of the above

Individual Effort in project

131 Data Structure and Algorithms Lab Manual


Important Concepts
1. STACK: The operations like push, pop, top of the stack, is empty, is full are performed on the stack.
2. QUEUE: The operations like insertion, deletion, rear of the queue, front of the queue, is empty, is full are
performed on the queue.
3. CIRCULAR QUEUE: The operations like insertion, deletion, rear of the queue, front of the queue, is empty,
is full are performed on the circular queue.
4. SINGLY LINKED LIST: The operations like insertion, deletion and search operations are performed on the
singly linked list.
5. DOUBLY LINKED LIST: The operations like insertion, deletion and search operations are performed on the
doubly linked list.
6. BUBBLE SORT: Various numbers are sorted in ascending order according to the bubble sort technique.
7. INSERTION SORT: Various numbers are sorted in ascending order according to the insertion sort technique.
8. SELECTION SORT: Various numbers are sorted in ascending order according to the selection sort technique.
9. LINEAR SEARCH: A list of elements are created and the required value is searched in the list based on the
linear search strategy.
10. BINARY SEARCH: A list of elements are created and the required value is searched in the list based on the
binary search strategy.
11. BINARY SEARCH TREE: Operations insertion, deletion are performed on the binary search tree. Also the
search operation is performed on the tree.
12. TREE TRAVERSAL: A tree is created and the operations infix, prefix, postfix are performed on the tree.
13. GRAPH TRAVERSAL: A graph is created and the operations BFS,DFS are performed on the graph.
14. DIJKSTRA’S ALGORITHM: A graph is created and the shortest path from start node to each node in the
graph is determined.
15. PRIM’S ALGORITHM: A graph is created and the minimum spanning tree is determined according to the
prim’s algorithm.
16. KRUSKAL’S ALGORITHM: A graph is created and the minimum spanning tree is determined according to
the kruskal’s algorithm.
17. AVL TREE: Operations insertion, deletion are performed on the AVL tree. Also the search operation is
performed on the tree.
18. NQUEENS PROBLEM: A board of n*n dimension is created and the solution to the nqueens board is
displayed. Also the solution is animated at each step.
19. DFA: The required graph is created, and we check whether the given input string is accepted or rejected by the
DFA.
20. NFA: The required graph is created, and we check whether the given input string is accepted or rejected by the
NFA.
21. BINARY ADDITION: Two decimal numbers are accepted as input and are automatically converted into
binary numbers and are added. At each step, the results are displayed.
22. PROCESS SCHEDULING: Various processes and their execution times are taken as input, and they are
scheduled according to the selected strategy(FCFS,SJF,ROUND-ROBIN).
23. TRAVELLING SALES PERSON PROBLEM: The number of cities to be traversed are taken as input and
the path through which the traveler need to traverse is determined both at a time and step by step.
24. LINEAR HASHING: The hash table is created for required number of elements and insertion, deletion and
search operations are performed on it.

132 Data Structure and Algorithms Lab Manual


“I insist you to strive. Work, Work
and only work for satisfaction with
patience, humbleness and serve thy
nation”.
Muhammad Ali Jinnah

“A scientist in his laboratory is not


a mere technician: he is also a
child confronting natural
phenomena that impress him as
though they were fairy tales”.
Marie Curie

“I have not failed. I've just found


10,000 ways that won't work”.
Thomas Alva Edison

133 Data Structure and Algorithms Lab Manual

You might also like