DSA Using Java Quick Guide
DSA Using Java Quick Guide
• Interface − Each data strucure has an interface. Interface represents the set of operations that a datastructure supports.An interface
only provides the list of supported operations, type of parameters they can accept and return type of these operations.
• Implementation − Implementation provides the internal representation of a data structure. Implementation also provides the defination
of the alogrithms used in the opreations of the data structure.
• Data Search − Consider an inventory of 1 million(10 6) items of a store. If application is to search an item. It has to search item in 1
million(106) items every time slowing down the search. As data grows, search will become slower.
• Processor speed − Processor speed although being very high, falls limited if data grows to billon records.
• Multiple requests − As thousands of users can search data simultaneously on a web server,even very fast server fails while
searching the data.
To solve above problems, data structures come to rescue. Data can be organized in a data structure in such a way that all items may not be
required to be search and required data can be searched almost instantly.
• Worst Case − This is the scenario where a particular data structure operation takes maximum time it can take. If a operation's worst
case time is ƒ(n) then this operation will not take time more than ƒ(n) time where ƒ(n) represents function of n.
• Average Case − This is the scenario depicting the average execution time of an operation of a data structure. If a operation takes ƒ(n)
time in execution then m operations will take mƒ(n) time.
• Best Case − This is the scenario depicting the least possible execution time of an operation of a data structure. If a operation takes
ƒ(n) time in execution then actual operation may take time as random number which would be maximum as ƒ(n).
Java SE is freely available from the link Download Java. So you download a version based on your operating system.
Follow the instructions to download java and run the .exe to install Java on your machine. Once you installed Java on your machine, you
would need to set environment variables to point to correct installation directories:
Example, if you use bash as your shell, then you would add the following line to the end of your '.bashrc: export PATH=/path/to/java:$PATH'
• Notepad − On Windows machine you can use any simple text editor like Notepad (Recommended for this tutorial), TextPad.
• Netbeans −is a Java IDE that is open source and free which can be downloaded from https://www.netbeans.org/index.html.
• Eclipse − is also a java IDE developed by the eclipse open source community and can be downloaded from https://www.eclipse.org/.
What is Next ?
Next chapter will teach you how to write and run your first java program and some of the important basic syntaxes in java needed for
developing applications.
Algorithm analysis
Algorithm analysis deals with the execution time or running time of various operations of a data structure. Running time of an operation can
be defined as no. of computer instructions executed per operation. As exact running time of any operation varies from one computer to
another computer, we usually analyze the running time of any operation as some function of n, where n is the no. of items processed in that
operation in a datastructure.
Asymptotic analysis
Asymptotic analysis refers to computing the running time of any operation in mathematical units of computation. For example, running time of
one operation is computed as f(n) and of another operation as g(n2). Which means first operation running time will increase linearly with the
increase in n and running time of second operation will increase exponentially when n increases. Similarly the running time of both
operations will be nearly same if n is significantly small.
Asymptotic Notations
Following are commonly used asymptotic notations used in calculating running time complexity of an algorithm.
• Ο Notation
• Ω Notation
• θ Notation
Big Oh Notation, Ο
The Ο(n) is the formal way to express the upper bound of an algorithm's running time. It measures the worst case time complex ity or longest amount of
time an algorithm can possibly take to complete. For example, for a function f(n)
Ο(f(n)) = { g(n) : there exists c > 0 and n 0 such that g(n) ≤ c.f(n) for all n > n0. }
Big Oh notation is used to simplify functions. For example, we can replace a specific functional equation 7nlogn + n - 1 with Ο(f(nlogn)).
Consider the scenario as follows:
7nlogn +n - 1 ≤ 7nlogn + n
7nlogn +n - 1 ≤ 8nlogn
It demonstrates that f(n) = 7nlogn + n - 1 is within the range of outout of O(nlogn) using constants c = 8 and n0 = 2.
Omega Notation, Ω
The Ω(n) is the formal way to express the lower bound of an algorithm's running time. It measures the best case time complexity or best
amount of time an algorithm can possibly take to complete.
Ω(f(n)) ≥ { g(n) : there exists c > 0 and n 0 such that g(n) ≤ c.f(n) for all n > n0. }
Theta Notation, θ
The θ(n) is the formal way to express both the lower bound and upper bound of an algorithm's running time. It is represented as following.
θ(f(n)) = { g(n) if and only if g(n) = Ο(f(n)) and g(n) = Ω(f(n)) for all n > n 0. }
Data Definition
Data Definition defines a particular data with following characteristics.
Data Object
Data Object represents an object having a data.
Data Type
Data type is way to classify various types of data such as integer, string etc. which determines the values that can be used with the
corresponding type of data, the type of operations that can be performed on the corresponding type of data. Data type of two types −
• Integers
• Boolean (true, false)
• Floating (Decimal numbers)
• Character and Strings
Derived Data Type
Those data types which are implementation independent as they can be implemented in one or other way are known as derived data types.
These data types are normally built by combination of primary or built-in data types and associated operations on them. For example −
• List
• Array
• Stack
• Queue
DSA using Java - Arrays
Array Basics
Array is a container which can hold fix number of items and these items should be of same type. Most of the datastructure make use of array
to implement their algorithms. Following are important terms to understand the concepts of Array
Array Representation
As per above shown illustration, following are the important points to be considered.
Basic Operations
Following are the basic operations supported by an array.
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d
char '\u0000'
boolean false
Object null
Demo
package com.tutorialspoint.array;
// Declare an array
int intArray[];
// Operation : Insertion
// Add elements in the array
for(int i = 0; i< intArray.length; i++)
{
// place value of i at index i.
System.out.println("Adding "+i+" at index "+i);
intArray[i] = i;
}
System.out.println();
// Operation : Insertion
// Element at any location can be updated directly
int index = 5;
intArray[index] = 10;
Adding 0 at index 0
Adding 1 at index 1
Adding 2 at index 2
Adding 3 at index 3
Adding 4 at index 4
Adding 5 at index 5
Adding 6 at index 6
Adding 7 at index 7
Data at index 5: 10
4 Found at index: 4
• Link − Each Link of a linked list can store a data called an element.
• Next − Each Link of a linked list contain a link to next link called Next.
• LinkedList − A LinkedList contains the connection link to the first Link called First.
As per above shown illustration, following are the important points to be considered.
Basic Operations
Following are the basic operations supported by a list.
• Insertion − add an element at the beginning of the list.
• Deletion − delete an element at the beginning of the list.
• Display − displaying complete list.
• Search − search an element using given key.
• Delete − delete an element using given key.
Insertion Operation
Insertion is a three step process:
Navigation Operation
Navigation is a recursive step process and is basis of many operations like search, delete etc.:
3. Point Current Link to Next Link of Current Link and move to above step.
Note
Advanced Operations
Following are the advanced operations specified for a list.
Sort Operation
We've used bubble sort to sort a list.
tempKey = current.key;
current.key = next.key;
next.key = tempKey;
}
current = current.next;
next = next.next;
}
}
}
Reverse Operation
Following code demonstrate reversing a single linked list.
Concatenate Operation
Following code demonstrate reversing a single linked list.
Demo
Link.java
package com.tutorialspoint.list;
package com.tutorialspoint.list;
tempKey = current.key;
current.key = next.key;
next.key = tempKey;
}
current = current.next;
next = next.next;
}
}
}
while(temp.next !=null) {
temp = temp.next;
}
temp.next = list.first;
}
}
LinkedListDemo.java
package com.tutorialspoint.list;
list.insertFirst(1, 10);
list.insertFirst(2, 20);
list.insertFirst(3, 30);
list.insertFirst(4, 1);
list.insertFirst(5, 40);
list.insertFirst(6, 56);
list.delete(4);
System.out.print("List after deleting an item: ");
list.display();
System.out.println("");
foundLink = list.find(4);
if(foundLink != null){
System.out.print("Element found: ");
foundLink.display();
System.out.println("");
}else{
System.out.print("Element not found. {4,1}");
}
System.out.println("");
list.sort();
System.out.print("List after sorting the data: ");
list.display();
System.out.println("");
System.out.print("Reverse of the list: ");
LinkedList list1 = list.reverse();
list1.display();
System.out.println("");
list2.insertFirst(9, 50);
list2.insertFirst(8, 40);
list2.insertFirst(7, 20);
list.concatenate(list2);
System.out.print("List after concatenation: ");
list.display();
System.out.println("");
}
}
If we compile and run the above program then it would produce following result:
• Link − Each Link of a linked list can store a data called an element.
• Next − Each Link of a linked list contain a link to next link called Next.
• Prev − Each Link of a linked list contain a link to previous link called Prev.
• LinkedList − A LinkedList contains the connection link to the first Link called First and to the last link called Last.
Doubly Linked List Representation
As per above shown illustration, following are the important points to be considered.
Basic Operations
Following are the basic operations supported by an list.
Insertion Operation
Following code demonstrate insertion operation at beginning in a doubly linked list.
if(isEmpty()){
//make it the last link
last = link;
}else {
//update first prev link
first.prev = link;
}
if(isEmpty()){
//make it the last link
last = link;
}else {
//make link a new last link
last.next = link;
//mark old last node as prev of new link
link.prev = last;
}
Demo
Link.java
package com.tutorialspoint.list;
DoublyLinkedList.java
package com.tutorialspoint.list;
if(isEmpty()){
//make it the last link
last = link;
}else {
//update first prev link
first.prev = link;
}
if(isEmpty()){
//make it the last link
last = link;
}else {
//make link a new last link
last.next = link;
//mark old last node as prev of new link
link.prev = last;
}
if(current == last){
//change last to point to prev link
last = current.prev;
}else {
current.next.prev = current.prev;
}
return current;
}
DoublyLinkedListDemo.java
package com.tutorialspoint.list;
list.insertFirst(1, 10);
list.insertFirst(2, 20);
list.insertFirst(3, 30);
list.insertLast(4, 1);
list.insertLast(5, 40);
list.insertLast(6, 56);
}
}
If we compile and run the above program then it would produce following result −
As per above shown illustrations, following are the important points to be considered.
• Last Link'next points to first link of the list in both cases of singly as well as doubly linked list.
• First Link's prev points to the last of the list in case of doubly linked list.
Basic Operations
Following are the important operations supported by a circular list.
length Operation
Following code demonstrate insertion operation at in a circular linked list based on single linked list.
Deletion Operation
Following code demonstrate deletion operation at in a circular linked list based on single linked list.
Demo
Link.java
package com.tutorialspoint.list;
while(current != first){
length++;
current = current.next;
}
return length;
}
DoublyLinkedListDemo.java
package com.tutorialspoint.list;
list.insertFirst(1, 10);
list.insertFirst(2, 20);
list.insertFirst(3, 30);
list.insertFirst(4, 1);
list.insertFirst(5, 40);
list.insertFirst(6, 56);
If we compile and run the above program then it would produce following result −
Stack Representation
Basic Operations
Following are two primary operations of a stack which are following.
Push Operation
Whenever an element is pushed into stack, stack stores that element at the top of the storage and increments the top index for later use. If
storage is full then an error message is usually shown.
if(!isFull()){
// increment top by 1 and insert data
intArray[++top] = data;
}else{
System.out.println("Cannot add data. Stack is full.");
}
}
Pop Operation
Whenever an element is to be popped from stack, stack retrives the element from the top of the storage and decrements the top index for
later use.
// pop item from the top of the stack
public int pop() {
// retrieve data and decrement the top by 1
return intArray[top--];
}
Stack Implementation
Stack.java
package com.tutorialspoint.datastructure;
// Constructor
public Stack(int size){
this.size = size;
intArray = new int[size]; //initialize array
top = -1; //stack is initially empty
}
// Operation : Push
// push item on the top of the stack
public void push(int data) {
if(!isFull()){
// increment top by 1 and insert data
intArray[++top] = data;
}else{
System.out.println("Cannot add data. Stack is full.");
}
}
// Operation : Pop
// pop item from the top of the stack
public int pop() {
//retrieve data and decrement the top by 1
return intArray[top--];
}
// Operation : Peek
// view the data at top of the stack
public int peek() {
//retrieve data from the top
return intArray[top];
}
// Operation : isFull
// return true if stack is full
public boolean isFull(){
return (top == size-1);
}
// Operation : isEmpty
// return true if stack is empty
public boolean isEmpty(){
return (top == -1);
}
}
Demo Program
StackDemo.java
package com.tutorialspoint.datastructure;
If we compile and run the above program then it would produce following result −
Infix Notation
Normal airthmetic expression follows Infix Notation in which operator is in between the operands. For example A+B here A is first operand, B
is second operand and + is the operator acting on the two operands.
Postfix Notation
Postfix notation varies from normal arithmetic expression or infix notation in a way that the operator follows the operands. For example,
consider the following examples
1 A+B AB+
2 (A+B)*C AB+C*
3 A*(B+C) ABC+*
4 A/B+C/D AB/CD/+
5 (A+B)*(C+D) AB+CD+*
6 ((A+B)*C)-D AB+C*D-
1 A A A
2 + A+ A
3 B A+B AB
5 C A+B*C ABC
Now let us transform the above infix expression A+B*C into a postfix expression using stack.
1 A A A
2 + A+ A + push +
operator in
a stack.
3 B A+B AB +
4 * A+B* AB +* Precedence
of operator
* is higher
than +.
push *
operator in
the stack.
Otherwise,
+ would
pop up.
5 C A+B*C ABC +*
Now let us see another example, by transforming infix expression A*(B+C) into a postfix expression using stack.
1 A A A
2 * A* A * push *
operator in
a stack.
3 ( A*( A *( push ( in
the stack.
4 B A*(B AB *(
Demo program
Now we'll demonstrate the use of stack to convert infix expression to postfix expression and then evaluate the postfix expression.
Stack.java
package com.tutorialspoint.expression;
//Constructor
public Stack(int size){
this.size = size;
intArray = new int[size];
top = -1;
}
InfixToPostFix.java
package com.tutorialspoint.expression;
while(!stack.isEmpty()){
output = output + (char)stack.pop();
}
return output;
}
PostFixParser.java
package com.tutorialspoint.expression;
for(int i=0;i<input.length();i++){
ch = input.charAt(i);
PostFixDemo.java
package com.tutorialspoint.expression;
If we compile and run the above program then it would produce following result −
Queue Representation
Basic Operations
• insert / enqueue − add an item to the rear of the queue.
• remove / dequeue − remove an item from the front of the queue.
We're going to implement Queue using array in this article. There is few more operations supported by queue which are following.
intArray[++rear] = data;
itemCount++;
}
}
Queue Implementation
Queue.java
package com.tutorialspoint.datastructure;
intArray[++rear] = data;
itemCount++;
}
}
Demo Program
QueueDemo.java
package com.tutorialspoint.datastructure;
//insert 5 items
queue.insert(3);
queue.insert(5);
queue.insert(9);
queue.insert(1);
queue.insert(12);
// front : 0
// rear : 4
// ------------------
// index : 0 1 2 3 4
// ------------------
// queue : 3 5 9 1 12
queue.insert(15);
// front : 0
// rear : 5
// ---------------------
// index : 0 1 2 3 4 5
// ---------------------
// queue : 3 5 9 1 12 15
if(queue.isFull()){
System.out.println("Queue is full!");
}
// front : 1
// rear : -1
// ----------------------
// index : 0 1 2 3 4 5
// ----------------------
// queue : 16 5 9 1 12 15
// ----------------------
// index : 0 1 2 3 4 5
// ----------------------
// queue : 16 5 9 1 12 15
System.out.println("Element at front: "+queue.peek());
System.out.println("----------------------");
System.out.println("index : 5 4 3 2 1 0");
System.out.println("----------------------");
System.out.print("Queue: ");
while(!queue.isEmpty()){
int n = queue.remove();
System.out.print(n +" ");
}
}
}
If we compile and run the above program then it would produce following result −
Queue is full!
Element removed: 3
Element at front: 5
----------------------
index : 5 4 3 2 1 0
----------------------
Queue: 5 9 1 12 15 16
Basic Operations
• insert / enqueue − add an item to the rear of the queue.
• remove / dequeue − remove an item from the front of the queue.
Priority Queue Representation
We're going to implement Queue using array in this article. There is few more operations supported by queue which are following.
if(!isFull()){
// if queue is empty, insert the data
if(itemCount == 0){
intArray[itemCount++] = data;
}else{
// start from the right end of the queue
for(i = itemCount - 1; i >= 0; i-- ){
// if data is larger, shift existing item to right end
if(data > intArray[i]){
intArray[i+1] = intArray[i];
}else{
break;
}
}
// insert the data
intArray[i+1] = data;
itemCount++;
}
}
}
package com.tutorialspoint.datastructure;
if(!isFull()){
// if queue is empty, insert the data
if(itemCount == 0){
intArray[itemCount++] = data;
}else{
// start from the right end of the queue
for(i = itemCount - 1; i >= 0; i-- ){
// if data is larger, shift existing item to right end
if(data > intArray[i]){
intArray[i+1] = intArray[i];
}else{
break;
}
}
// insert the data
intArray[i+1] = data;
itemCount++;
}
}
}
public int remove(){
return intArray[--itemCount];
}
Demo Program
PriorityQueueDemo.java
package com.tutorialspoint.datastructure;
//insert 5 items
queue.insert(3);
queue.insert(5);
queue.insert(9);
queue.insert(1);
queue.insert(12);
// ------------------
// index : 0 1 2 3 4
// ------------------
// queue : 12 9 5 3 1
queue.insert(15);
// ---------------------
// index : 0 1 2 3 4 5
// ---------------------
// queue : 15 12 9 5 3 1
if(queue.isFull()){
System.out.println("Queue is full!");
}
// ----------------------
// index : 0 1 2 3 4 5
// ----------------------
// queue : 16 15 12 9 5 3
// ----------------------
// index : 0 1 2 3 4 5
// ----------------------
// queue : 16 15 12 9 5 3
System.out.println("Element at front: "+queue.peek());
System.out.println("----------------------");
System.out.println("index : 5 4 3 2 1 0");
System.out.println("----------------------");
System.out.print("Queue: ");
while(!queue.isEmpty()){
int n = queue.remove();
System.out.print(n +" ");
}
}
}
If we compile and run the above program then it would produce following result −
Queue is full!
Element removed: 1
Element at front: 3
----------------------
index : 5 4 3 2 1 0
----------------------
Queue: 3 5 9 12 15 16
Binary Tree is a special datastructure used for data storage purposes. A binary tree has a special condition that each node can have two
children at maximum. A binary tree have benefits of both an ordered array and a linked list as search is as quick as in sorted array and
insertion or deletion operation are as fast as in linked list.
Terms
Following are important terms with respect to tree.
Basic Operations
Following are basic primary operations of a tree which are following.
Node
Define a node having some data, references to its left and right child nodes.
public class Node {
public int data;
public Node leftChild;
public Node rightChild;
public Node(){}
Search Operation
Whenever an element is to be search. Start search from root node then if data is less than key value, search element in left subtree
otherwise search element in right subtree. Follow the same algorithm for each node.
Insert Operation
Whenever an element is to be inserted. First locate its proper location. Start search from root node then if data is less than key value, search
empty location in left subtree and insert the data. Otherwise search empty location in right subtree and insert the data.
while(true){
parent = current;
//go to left of the tree
if(data < parent.data){
current = current.leftChild;
//insert to the left
if(current == null){
parent.leftChild = tempNode;
return;
}
}//go to right of the tree
else{
current = current.rightChild;
//insert to the right
if(current == null){
parent.rightChild = tempNode;
return;
}
}
}
}
}
Preorder Traversal
It is a simple three step process.
Inorder Traversal
It is a simple three step process.
Postorder Traversal
It is a simple three step process.
Tree Implementation
Node.java
package com.tutorialspoint.datastructure;
public Node(){}
Tree.java
package com.tutorialspoint.datastructure;
public Tree(){
root = null;
}
while(true){
parent = current;
//go to left of the tree
if(data < parent.data){
current = current.leftChild;
//insert to the left
if(current == null){
parent.leftChild = tempNode;
return;
}
}//go to right of the tree
else{
current = current.rightChild;
//insert to the right
if(current == null){
parent.rightChild = tempNode;
return;
}
}
}
}
}
Demo Program
TreeDemo.java
package com.tutorialspoint.datastructure;
/* 11 //Level 0
*/
tree.insert(11);
/* 11 //Level 0
* |
* |---20 //Level 1
*/
tree.insert(20);
/* 11 //Level 0
* |
* 3---|---20 //Level 1
*/
tree.insert(3);
/* 11 //Level 0
* |
* 3---|---20 //Level 1
* |
* |--42 //Level 2
*/
tree.insert(42);
/* 11 //Level 0
* |
* 3---|---20 //Level 1
* |
* |--42 //Level 2
* |
* |--54 //Level 3
*/
tree.insert(54);
/* 11 //Level 0
* |
* 3---|---20 //Level 1
* |
* 16--|--42 //Level 2
* |
* |--54 //Level 3
*/
tree.insert(16);
/* 11 //Level 0
* |
* 3---|---20 //Level 1
* |
* 16--|--42 //Level 2
* |
* 32--|--54 //Level 3
*/
tree.insert(32);
/* 11 //Level 0
* |
* 3---|---20 //Level 1
* | |
* |--9 16--|--42 //Level 2
* |
* 32--|--54 //Level 3
*/
tree.insert(9);
/* 11 //Level 0
* |
* 3---|---20 //Level 1
* | |
* |--9 16--|--42 //Level 2
* | |
* 4--| 32--|--54 //Level 3
*/
tree.insert(4);
/* 11 //Level 0
* |
* 3---|---20 //Level 1
* | |
* |--9 16--|--42 //Level 2
* | |
* 4--|--10 32--|--54 //Level 3
*/
tree.insert(10);
Node node = tree.search(32);
if(node!=null){
System.out.print("Element found.");
node.display();
System.out.println();
}else{
System.out.println("Element not found.");
}
//pre-order traversal
//root, left ,right
tree.traverse(1);
//in-order traversal
//left, root ,right
tree.traverse(2);
//post order traversal
//left, right, root
tree.traverse(3);
}
}
If we compile and run the above program then it would produce following result −
Preorder traversal: 11 3 9 4 10 20 16 42 32 54
Inorder traversal: 3 4 9 10 11 16 20 32 42 54
Postorder traversal: 4 10 9 3 16 32 54 42 20 11
Hashing
Hashing is a technique to convert a range of key values into a range of indexes of an array. We're going to use modulo operator to get a
range of key values. Consider an example of hashtable of size 20, and following items are to be stored. Item are in (key,value) format.
• (1,20)
• (2,70)
• (42,80)
• (4,25)
• (12,44)
• (14,32)
• (17,11)
• (13,78)
• (37,98)
Sr.No. Key Hash Array Index
1 1 1 % 20 = 1 1
2 2 2 % 20 = 2 2
3 42 42 % 20 = 2 2
4 4 4 % 20 = 4 4
5 12 12 % 20 = 12 12
6 14 14 % 20 = 14 14
7 17 17 % 20 = 17 17
8 13 13 % 20 = 13 13
9 37 37 % 20 = 17 17
Linear Probing
As we can see, it may happen that the hashing technique used create already used index of the array. In such case, we can search the next
empty location in the array by looking into the next cell until we found an empty cell. This technique is called linear probing.
Sr.No. Key Hash Array Index After Linear Probing, Array Index
1 1 1 % 20 = 1 1 1
2 2 2 % 20 = 2 2 2
3 42 42 % 20 = 2 2 3
4 4 4 % 20 = 4 4 4
5 12 12 % 20 = 12 12 12
6 14 14 % 20 = 14 14 14
7 17 17 % 20 = 17 17 17
8 13 13 % 20 = 13 13 13
9 37 37 % 20 = 17 17 18
Basic Operations
Following are basic primary operations of a hashtable which are following.
DataItem
Define a data item having some data, and key based on which search is to be conducted in hashtable.
Hash Method
Define a hashing method to compute the hash code of the key of the data item.
Search Operation
Whenever an element is to be searched. Compute the hash code of the key passed and locate the element using that hashcode as index in
the array. Use linear probing to get element ahead if element not found at computed hash code.
Insert Operation
Whenever an element is to be inserted. Compute the hash code of the key passed and locate the index using that hashcode as index in the
array. Use linear probing for empty location if an element is found at computed hash code.
public void insert(DataItem item){
int key = item.getKey();
hashArray[hashIndex] = item;
}
Delete Operation
Whenever an element is to be deleted. Compute the hash code of the key passed and locate the index using that hashcode as index in the
array. Use linear probing to get element ahead if an element is not found at computed hash code. When found, store a dummy item there to
keep performance of hashtable intact.
HashTable Implementation
DataItem.java
package com.tutorialspoint.datastructure;
HashTable.java
package com.tutorialspoint.datastructure;
hashArray[hashIndex] = item;
}
package com.tutorialspoint.datastructure;
hashTable.display();
if(item != null){
System.out.println("Element found: "+ item.getData());
}else{
System.out.println("Element not found");
}
hashTable.delete(item);
item = hashTable.search(37);
if(item != null){
System.out.println("Element found: "+ item.getData());
}else{
System.out.println("Element not found");
}
}
}
If we compile and run the above program then it would produce following result −
Binary heap tree can be classified as a binary tree with two constraints −
• Completeness − Binary heap tree is a complete binary tree except the last level which may not have all elements but elements from
left to right should be filled in.
• Heapness − All parent nodes should be greater or smaller to their children. If parent node is to be greater than its child then it is called
Max heap otherwise it is called Min heap. Max heap is used for heap sort and Min heap is used for priority queue. We're consi dering
Min Heap and will use array implementation for the same.
Basic Operations
Following are basic primary operations of a Min heap which are following.
Insert Operation
• Whenever an element is to be inserted. Insert element at the end of the array. Increase the size of heap by 1.
• Heap up the element while heap property is broken. Compare element with parent's value and swap them if required.
public void insert(int value) {
size++;
intArray[size - 1] = value;
heapUp(size - 1);
}
Get Minimum
Get the first element of the array implementing the heap being root.
Remove Minimum
• Whenever an element is to be removed. Get the last element of the array and reduce size of heap by 1.
• Heap down the element while heap property is broken. Compare element with children's value and swap them if required.
public void removeMin() {
intArray[0] = intArray[size - 1];
size--;
if (size > 0)
heapDown(0);
}
Heap Implementation
Heap.java
package com.tutorialspoint.datastructure;
/**
* Heap up the new element,until heap property is broken.
* Steps:
* 1. Compare node's value with parent's value.
* 2. Swap them, If they are in wrong order.
* */
private void heapUp(int nodeIndex){
int parentIndex, tmp;
if (nodeIndex != 0) {
parentIndex = getParentIndex(nodeIndex);
if (intArray[parentIndex] > intArray[nodeIndex]) {
tmp = intArray[parentIndex];
intArray[parentIndex] = intArray[nodeIndex];
intArray[nodeIndex] = tmp;
heapUp(parentIndex);
}
}
}
/**
* Heap down the root element being least in value,until heap property is broken.
* Steps:
* 1.If current node has no children, done.
* 2.If current node has one children and heap property is broken,
* 3.Swap the current node and child node and heap down.
* 4.If current node has one children and heap property is broken, find smaller one
* 5.Swap the current node and child node and heap down.
* */
private void heapDown(int nodeIndex){
int leftChildIndex, rightChildIndex, minIndex, tmp;
leftChildIndex = getLeftChildIndex(nodeIndex);
rightChildIndex = getRightChildIndex(nodeIndex);
if (rightChildIndex >= size) {
if (leftChildIndex >= size)
return;
else
minIndex = leftChildIndex;
} else {
if (intArray[leftChildIndex] <= intArray[rightChildIndex])
minIndex = leftChildIndex;
else
minIndex = rightChildIndex;
}
if (intArray[nodeIndex] > intArray[minIndex]) {
tmp = intArray[minIndex];
intArray[minIndex] = intArray[nodeIndex];
intArray[nodeIndex] = tmp;
heapDown(minIndex);
}
}
}
Demo Program
HeapDemo.java
package com.tutorialspoint.datastructure;
System.out.println(heap.getMinimum());
heap.removeMin();
/* 2 //Level 0
* |
* 5---|---3 //Level 1
* | |
* 8--|--9 6--| //Level 2
*/
System.out.println(heap.getMinimum());
}
}
If we compile and run the above program then it would produce following result −
1
2
DSA using Java - Graph
Overview
Graph is a datastructure to model the mathematical graphs. It consists of a set of connected pairs called edges of vertices. We can represent
a graph using an array of vertices and a two dimentional array of edges.
Important terms
• Vertex − Each node of the graph is represented as a vertex. In example given below, labeled circle represents vertices. So A to G are
vertices. We can represent them using an array as shown in image below. Here A can be identified by index 0. B can be identified
using index 1 and so on.
• Edge − Edge represents a path between two vertices or a line between two vertices. In example given below, lines from A to B, B to C
and so on represents edges. We can use a two dimentional array to represent array as shown in image below. Here AB can be
represented as 1 at row 0, column 1, BC as 1 at row 1, column 2 and so on, keeping other combinations as 0.
• Adjacency − Two node or vertices are adjacent if they are connected to each other through an edge. In example given below, B is
adjacent to A, C is adjacent to B and so on.
• Path − Path represents a sequence of edges betweeen two vertices. In example given below, ABCD represents a path from A to D.
Basic Operations
Following are basic primary operations of a Graph which are following.
Traversal Algorithms
Following are important traversal algorithms on a Graph.
As in example given above, DFS algorithm traverses from A to B to C to D first then to E, then to F and lastly to G. It employs following rules.
• Rule 1 − Visit adjacent unvisited vertex. Mark it visited. Display it. Push it in a stack.
• Rule 2 − If no adjacent vertex found, pop up a vertex from stack. (It will pop up all the vertices from the stack which do not have
adjacent vertices.)
• Rule 3 − Repeat Rule 1 and Rule 2 until stack is empty.
public void depthFirstSearch(){
//mark first node as visited
lstVertices[0].visited = true;
//display the vertex
displayVertex(0);
//push vertex index in stack
stack.push(0);
while(!stack.isEmpty()){
//get the unvisited vertex of vertex which is at top of the stack
int unvisitedVertex = getAdjUnvisitedVertex(stack.peek());
//no adjacent vertex found
if(unvisitedVertex == -1){
stack.pop();
}else{
lstVertices[unvisitedVertex].visited = true;
displayVertex(unvisitedVertex);
stack.push(unvisitedVertex);
}
}
As in example given above, BFS algorithm traverses from A to B to E to F first then to C and G lastly to D. It employs following rules.
• Rule 1 − Visit adjacent unvisited vertex. Mark it visited. Display it. Insert it in a queue.
• Rule 2 − If no adjacent vertex found, remove the first vertex from queue.
• Rule 3 − Repeat Rule 1 and Rule 2 until queue is empty.
public void breadthFirstSearch(){
//mark first node as visited
lstVertices[0].visited = true;
//display the vertex
displayVertex(0);
//insert vertex index in queue
queue.insert(0);
int unvisitedVertex;
while(!queue.isEmpty()){
//get the unvisited vertex of vertex which is at front of the queue
int tempVertex = queue.remove();
//no adjacent vertex found
while((unvisitedVertex=getAdjUnvisitedVertex(tempVertex)) != -1){
lstVertices[unvisitedVertex].visited = true;
displayVertex(unvisitedVertex);
queue.insert(unvisitedVertex);
}
}
Graph Implementation
Stack.java
package com.tutorialspoint.datastructure;
// Constructor
public Stack(int size){
this.size = size;
intArray = new int[size]; //initialize array
top = -1; //stack is initially empty
}
// Operation : Push
// push item on the top of the stack
public void push(int data) {
if(!isFull()){
// increment top by 1 and insert data
intArray[++top] = data;
}else{
System.out.println("Cannot add data. Stack is full.");
}
}
// Operation : Pop
// pop item from the top of the stack
public int pop() {
//retrieve data and decrement the top by 1
return intArray[top--];
}
// Operation : Peek
// view the data at top of the stack
public int peek() {
//retrieve data from the top
return intArray[top];
}
// Operation : isFull
// return true if stack is full
public boolean isFull(){
return (top == size-1);
}
// Operation : isEmpty
// return true if stack is empty
public boolean isEmpty(){
return (top == -1);
}
}
Queue.java
package com.tutorialspoint.datastructure;
intArray[++rear] = data;
itemCount++;
}
}
Vertex.java
package com.tutorialspoint.datastructure;
Graph.java
package com.tutorialspoint.datastructure;
public Graph(){
lstVertices = new Vertex[MAX];
adjMatrix = new int[MAX][MAX];
vertexCount = 0;
stack = new Stack(MAX);
queue = new Queue(MAX);
for(int j=0; j<MAX; j++) // set adjacency
for(int k=0; k<MAX; k++) // matrix to 0
adjMatrix[j][k] = 0;
}
while(!stack.isEmpty()){
//get the unvisited vertex of vertex which is at top of the stack
int unvisitedVertex = getAdjUnvisitedVertex(stack.peek());
//no adjacent vertex found
if(unvisitedVertex == -1){
stack.pop();
}else{
lstVertices[unvisitedVertex].visited = true;
displayVertex(unvisitedVertex);
stack.push(unvisitedVertex);
}
}
Demo Program
GraphDemo.java
package com.tutorialspoint.datastructure;
graph.addVertex('A'); //0
graph.addVertex('B'); //1
graph.addVertex('C'); //2
graph.addVertex('D'); //3
graph.addVertex('E'); //4
graph.addVertex('F'); //5
graph.addVertex('G'); //6
/* 1 2 3
* 0 |--B--C--D
* A--|
*|
*| 4
* |-----E
*| 5 6
* | |--F--G
* |--|
*/
graph.addEdge(0, 1); //AB
graph.addEdge(1, 2); //BC
graph.addEdge(2, 3); //CD
graph.addEdge(0, 4); //AC
graph.addEdge(0, 5); //AF
graph.addEdge(5, 6); //FG
System.out.print("Depth First Search: ");
//A B C D E F G
graph.depthFirstSearch();
System.out.println("");
System.out.print("Breadth First Search: ");
//A B E F C G D
graph.breadthFirstSearch();
}
}
If we compile and run the above program then it would produce following result −
1 Linear Search
Linear search searches all items and its worst execution time is n where n is the
number of items.
2 Binary Search
Binary search requires items to be in sorted order but its worst execution time is
constant and is much faster than linear search.
3 Interpolation Search
Interpolation search requires items to be in sorted order but its worst execution
time is O(n) where n is the number of items and it is much faster than linear
search.
Sorting refers to arranging data in a particular format. Sorting algorithm specifies the way to arrange data in a particular order. Most common
orders are numerical or lexicographical order.
Importance of sorting lies in the fact that data searching can be optimized to a very high level if data is stored in a sorte d manner. Sorting is
also used to represent data in more readable formats. Some of the examples of sorting in real life scenarios are following.
• Telephone Directory − Telephone directory keeps telephone no. of people sorted on their names. So that names can be searched.
• Dictionary − Dictionary keeps words in alphabetical order so that searching of any work becomes easy.
Types of Sorting
Following is the list of popular sorting algorithms and their comparison.
Bubble sort is simple to understand and implement algorithm but is very poor in
performance.
2 Selection Sort
Selection sort as name specifies use the technique to select the required item and
prepare sorted array accordingly.
3 Insertion Sort
4 Shell Sort
5 Quick Sort
6 Sorting Objects
Characteristics
A recursive function must posses the following two characteristics
• Base Case(s)
• Set of rules which leads to base case after reducing the cases.
Recursive Factorial
Factorial is one of the classical example of recursion. Factorial is a non-negative number satisfying following conditions.
1. 0! = 1
2. 1! = 1
3. n! = n * n-1!
Factorial is represented by "!". Here Rule 1 and Rule 2 are base cases and Rule 3 are factorial rules.
As an example, 3! = 3 x 2 x 1 = 6
1. F0 = 0
2. F1 = 1
3. Fn = Fn-1 + Fn-2
Fibonacci is represented by "F". Here Rule 1 and Rule 2 are base cases and Rule 3 are fibonnacci rules.
As an example, F5 = 0 1 1 2 3
Demo Program
RecursionDemo.java
package com.tutorialspoint.algorithm;
If we compile and run the above program then it would produce following result −
Factorial of 5: 120
Fibbonacci of 5: 0 1 1 2 3