Data Structures Lab Manual in Java
Data Structures Lab Manual in Java
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
4 Array based 10
Queues
implementation
5 Circular and Priority Queues 10
11 Balanced Trees 10
Grand Total
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 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 16 – SEMESTER PROJECT PRESENTATION......................................................128
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.
import java.lang.Math;
import java.util.Scanner;
class QuadraticEquation
{
double a, b, c; // coefficients
QuadraticEquation( double a, double b, double
c)
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
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…
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
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
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)
{
Output:
Given string: MADAM is a palindrome.
class TimeTest1 {
public static void main(String[] args) {
long startTime =
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.
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 rted 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.
import java.util.Arrays;
import java.util.Date;
if (arr[mid] == key) {
return mid;
} else if (arr[mid] < key) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return -1;
}
}
while (true) {
System.out.println("Menu:");
System.out.println("1. Addition");
System.out.println("2. Subtraction");
System.out.println("3. Exit");
System.out.print("Enter your choice: ");
switch (choice) {
case 1:
performAddition(scanner);
break;
case 2:
performSubtraction(scanner);
break;
case 3:
System.out.println("Exiting...");
return;
default:
System.out.println("Invalid choice. Please try again.");
}
}
}
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.
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.
16 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[];
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
17 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.
class GFG
{
public static void main (String[] args)
{
// declares an Array of
integers. int[] arr;
//so on...
arr[2] = 30;
arr[3] = 40;
arr[4] = 50;
Example
2
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:");
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();
}
}
}
class Test
{
// Driver method
public static void main(String args[])
{
int arr[] = m1();
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
import java.util.Scanner;
class Student {
String name;
int age;
double gpa;
System.out.println("\nStudent Details:");
for (int i = 0; i < students.length; i++) {
System.out.println((i + 1) + ". " + students[i].name + ", Age: " + students[i].age + ", GPA: " + students[i].gpa);
}
}
}
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;
}
}
Out put:
Working:
Main Method:
The main method is the entry point of the program. It calls the binarySearch method and prints the result to the console. If the
binarySearch method returns true, it means the key was found in the array, and the program prints "UP found in the list".
Otherwise, it prints "UP not found in the list".
25 Data Structure and Algorithms Lab Manual
Binary Search Method:
The binarySearch method performs the actual binary search on the array a. Here's how it works:
If key is less than the element at mid, update high to mid - 1 to search in the lower half of the range.
If key is greater than the element at mid, update low to mid + 1 to search in the upper half of the range.
If key is equal to the element at mid, return true to indicate that the key was found.
If the loop completes without finding the key, return false to indicate that the key was not found.
In this specific example, the key "UP" is present in the array, so the binarySearch method returns true, and the program prints "UP
found in the list"
import java.util.Arrays;
// String array
String[] stringArray = {"apple", "banana", "cherry", "date", "fig"};
Exercise 4: (1)
Write a Java program to sum values of an array.
// Iterate through the array and add each element to the sum
for (int i = 0; i < numbers.length; i++) {
sum += numbers[i];
}
Exercise 5: (1)
Write a Java program to calculate the average value of array elements.
// Iterate through the array and add each element to the sum
for (int i = 0; i < numbers.length; i++) {
sum += numbers[i];
}
// Array of integers
int[] numbers = {1789, 2035, 1899, 1456, 2013};
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
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 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.
Data3
Data2
Data1 Bottom
Stack Implementation:
boolean isEmpty()
{
return (top < 0);
}
Stack()
{
top = -1;
}
boolean push(int x){
}
}
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");
}
}
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:
import java.util.Stack;
public class DecimalToBinary {
public static void decimalToBinary(int decimalNumber) {
if (decimalNumber < 0) {
System.out.println("Invalid input. Please enter a non-negative integer.");
return;
}
while (!stack.isEmpty()) {
System.out.print(stack.pop());
}
System.out.println();
}
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
import java.util.Stack;
while (!stack.isEmpty()) {
System.out.print(stack.pop());
}
System.out.println();
}
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.
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.
Queue Implementation:
Queue(int c)
{
front = rear =
0; capacity = c;
queue = new int[capacity];
}
// decrement
rear rear--;
}
return;
}
// Driver code
public static void main(String[] args)
{
// Create a queue of capacity
4 Queue q = new Queue(4);
// print Queue
elements
q.queueDisplay();
// print Queue
elements
q.queueDisplay();
34 Data Structure and Algorithms Lab Manual
// insert element in the
queue q.queueEnqueue(60);
q.queueDequeue();
q.queueDequeue();
System.out.printf("\n\nafter two node deletion\n\n");
// print Queue
elements
q.queueDisplay();
Output:
Queue is Empty
20 <-- 30 <-- 40 <-- 50 <--
Queue is full
20 <-- 30 <-- 40 <-- 50 <--
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.
Exercise 1: (4)
Write a menu driven program to perform different operations with queue such a Enqueue ( ),
Dequeue( ) and DisplayQueue( ).
import java.util.Scanner;
class Queue {
private int maxSize;
private int[] queueArray;
private int front;
private int rear;
private int numberOfItems;
do {
System.out.println("\n1. Insert");
System.out.println("2. Remove");
System.out.println("3. Display");
System.out.println("4. Quit");
System.out.print("Enter your choice: ");
choice = input.nextInt();
switch (choice) {
case 1:
System.out.print("Enter the value to insert: ");
value = input.nextInt();
theQueue.insert(value);
break;
case 2:
value = theQueue.remove();
if (value != -1)
System.out.println("Removed: " + value);
else
System.out.println("Queue is empty");
break;
case 3:
theQueue.display();
break;
case 4:
System.out.println("Goodbye!");
break;
default:
System.out.println("Invalid choice");
}
} while (choice != 4);
}
}
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
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’.
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.
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.
Operations on Deque:
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.
// A structure to represent a
Deque class Deque
{
static final int MAX = 100;
int arr[];
int front;
int rear;
int size;
// Inserts an element at
front void insertfront(int
key)
{
// check whether Deque if full or
not if (isFull())
{
System.out.println("Overflow");
return;
}
dq.deleterear();
System.out.println("After delete rear element new rear become : " +
dq.getRear());
System.out.println("inserting element at front end");
+dq.getFront()); dq.deletefront();
}
}
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
import java.util.*;
if (start == 0) {
return -1;
}
}
curr_petrol += arr[end].petrol - arr[end].distance;
end = (end + 1) % n;
}
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;
// 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);
}
}
// 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);
}
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);
Output:
Inorder traversal before insertion: 7 11 10 15 9 8
Inorder traversal after insertion: 7 11 12 10 15 9 8
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>();
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 + " ");
54 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
}
}
55 Data Structure and Algorithms Lab Manual
}
}
56 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 );
}
57 Data Structure and Algorithms Lab Manual
System.out.print("\n postorder: ");
t.postorderIterative(root);
}
58 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
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
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;
}
"); 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.
import java.util.Scanner;
public BinaryTree() {
tree = new int[MAX_SIZE];
}
System.out.println("Enter values for the binary tree (type 'done' when finished):");
while (true) {
String input = scanner.nextLine();
if (input.equalsIgnoreCase("done")) {
break;
}
int value = Integer.parseInt(input);
bt.insert(value);
}
import java.util.Scanner;
class Student {
private int regNo;
private String stName;
private float cgpa;
public Student() {
this.regNo = 0;
this.stName = "";
this.cgpa = 0.0f;
}
public BinaryTree1() {
tree = new Student[MAX_SIZE];
for (int i = 0; i < MAX_SIZE; i++) {
tree[i] = new Student();
}
}
45
25 65
15 30 55 75
10 20 50 60 80
class BSTNode
{
int data;
BSTNode left;
BSTNode right;
BSTNode( int d ) { data = d; }// constructor
{
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 == 2(b)
null)
{
if(parent.left == p) parent.left =
p.left; else parent.right = p.left;
}
return root;
}
// 'p' starts
public void inorder(BSTNode with root
p)
{ 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);
72 Data Structure and Algorithms Lab Manual
}
}
public void postorder(BSTNode p)
Output:
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
import java.util.Scanner;
class Node {
double data;
Node left, right;
Node(double data) {
this.data = data;
left = right = null;
}
}
class BinarySearchTree {
Node root;
int nodeCount;
BinarySearchTree() {
root = null;
nodeCount = 0;
}
while (true) {
System.out.print("\nEnter your choice: ");
int choice = scanner.nextInt();
switch (choice) {
case 1:
System.out.print("Enter value to insert: ");
double data = scanner.nextDouble();
bst.insert(data);
break;
case 2:
System.out.print("Pre-order Traversal: ");
bst.preOrder(bst.root);
System.out.println();
break;
case 3:
77 Data Structure and Algorithms Lab Manual
System.out.print("In-order Traversal: ");
bst.inOrder(bst.root);
System.out.println();
break;
case 4:
System.out.print("Post-order Traversal: ");
bst.postOrder(bst.root);
System.out.println();
break;
case 5:
System.out.println("Number of nodes: " + bst.nodeCount);
break;
case 6:
System.exit(0);
default:
System.out.println("Invalid choice!");
}
}
}
}
import java.util.Scanner;
class Student {
private int reg_no;
private String st_name;
private float cgpa;
public Student() {}
class Node {
Student data;
Node left;
Node right;
94 Data Structure and Algorithms Lab Manual
Node(Student s) {
data = s;
left = right = null;
}
}
class BinarySearchTree {
Node root;
public BinarySearchTree() {
root = null;
}
while (true) {
System.out.print("\nEnter your choice: ");
int choice = scanner.nextInt();
switch (choice) {
case 1:
s.input();
bst.insert(s);
break;
case 2:
System.out.println("Pre-order Traversal:");
bst.preOrderTraversal();
break;
case 3:
System.out.println("In-order Traversal:");
bst.inOrderTraversal();
break;
case 4:
System.out.println("Post-order Traversal:");
bst.postOrderTraversal();
break;
case 5:
System.out.print("Enter registration number to search: ");
int regNo = scanner.nextInt();
94 Data Structure and Algorithms Lab Manual
bst.search(regNo);
break;
case 6:
System.exit(0);
default:
System.out.println("Invalid choice!");
}
}
}
}
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.
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?”
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;
); 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 ) )
{
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();
}
}
Exersise [1o]
Write a deletion method
Node deleteNode(Node root, int key) {
if (root == null)
return root;
if (temp == null) {
temp = root;
root = null;
} else
root = temp;
} else {
Node temp = minValueNode(root.right);
root.key = temp.key;
root.right = deleteNode(root.right, temp.key);
}
}
if (root == null)
return root;
return root;
}