0% found this document useful (0 votes)
17 views

Java and Data Structures - Book - III Semester - BSC (CS) - TS

Uploaded by

Chengai Karthi
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views

Java and Data Structures - Book - III Semester - BSC (CS) - TS

Uploaded by

Chengai Karthi
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 426

CORE - III JAVA AND DATA STRUCTURES

II YEAR / III SEM


OBJECTIVES:
• To enable the students to learn the basic concepts of Java programming
• To use class and objects to create applications
• To have an overview of interfaces, packages, multithreading and exceptions.
• To familiarize students with basic data structures and their use in algorithms.

OUTCOMES:
• Students will be able to develop Java Standalone applications and Applets.
• Choose the appropriate data structure for modeling a given problem.

UNIT - I

History and Evolution of Java - Features of Java - Object Oriented Concepts - Bytecode - Lexical
Issues - Data Types – Variables - Type Conversion and Casting - Operators - Arithmetic Operators
- Bitwise - Relational Operators - Assignment Operator - The conditional Operator - Operator
Precedence - Control Statements - Arrays.

UNIT - II

Classes - Objects - Constructors - Overloading method - Static and fixed methods - Inner Classes -
String Class - Overriding methods - Using super - Abstract class - this keyword - finalize() method
- Garbage Collection.

UNIT - III

Packages - Access Protection - Importing Packages - Interfaces - Exception Handling - Throw


and Throws - The Java Thread Model - Creating a Thread and Multiple Threads - Thread Priorities
Synchronization - Inter thread Communication - Deadlock - Suspending, Resuming and Stopping
Threads – Multithreading - I/O Streams - File Streams - Applets .

UNIT - IV

Abstract Data Types(ADTs) - List ADT - Array based implementation - linked list implementation
- singly linked list - doubly linked list - circular linked list - Stack ADT operations – Applications -
Evaluating arithmetic expressions - Conversion of infix to postfix expression - Queue ADT-
operations - Applications of Queues.

UNIT - V

Trees - Binary Trees - representation - Operations on Binary Trees - Traversal of a Binary Tree -
Binary Search Trees, Graphs - Representation of Graphs - Traversal in Graph - Dijkstra’s Algorithm,
Depth-First vs Breadth-First Search.

1
TEXT BOOKS:

1. E.Balagurusamy,” Programming with Java: A Primer”, Tata McGraw Hill 2014, 5th Edition.
2. Mark Allen Weiss, “Data Structures and Algorithms Analysis in C++”, Person Education 2014,
4th Edition.

REFERENCES:

1. Herbert Schildt, “JAVA 2: The Complete Reference”, McGraw Hill 2018, 11th Edition.
2. Aho, Hopcroft and Ullman, “Data Structures and Algorithms “, Pearson Education 2003.
3. S. Sahni, “Data Structures, Algorithms and Applications in JAVA”, Universities Press 2005, 2nd
Edition

WEB REFERENCES:

➢ NPTEL & MOOC courses titled Java and Data Structures


➢ https://nptel.ac.in/courses/106106127/
➢ https://nptel.ac.in/courses/106105191/

2
JAVA AND DATA STRUCTURES

UNIT - I
*******************************************************************************
Chapter 1 The History and Evolution of Java
*******************************************************************************
1.1 Introduction
❖ Java is a General-Purpose, High-Level Object-Oriented Programming language developed by
Sun Microsystems of USA in 1991.
❖ It is a simple programming language. Java makes writing, compiling, and debugging
programming easy. It helps to create reusable code and modular programs.
❖ Java code can run on all platforms that support Java. Java applications are compiled to byte
code that can run on any Java Virtual Machine. The syntax of Java is similar to C/C++.
❖ Java is currently one of the most popular programming languages in use, particularly for client-
server web applications.
1.2 History of Java
❖ Java is invented by James Gosling, Patrick Naughton, Chris Warth, Ed Frank, and Mike
Sheridan at Sun Microsystems, Inc. in 1991. Java is related to C++, which is inherited from the
language C. The character of Java is inherited from C and C++ language. It took approx.
Eighteen months to develop the first working version. It was first named as “Oak” but was
renamed as “Java” in 1995.
❖ The basic idea behind creating this language is to create a platform-independent language that
is used to develop software for consumer electronic devices such as microwave ovens, remote
controls, etc. Initially, it was not designed for Internet applications.
❖ Java had an extreme effect on the Internet by the innovation of a new type of networked program
called the Applet. An Applet is a Java program that is designed to be transmitted over the
internet and executed by the web browser that is Java-compatible. Applets are the small program
that is used to display data provided by the server, handle user input, provide a simple function
such as calculator etc.
❖ Java solves the Security and the portability issue of the other language that is being used. The
key that allows doing so is the Bytecode. Bytecode is a highly optimized set of instruction that is
designed to be executed by the Java Virtual Machine (JVM). Java programs are executed by the
JVM also helps to make Java a secure programming g language because the JVM contains the
application and prevents it from affecting the external systems.

3
1.3 Evolution of Java

Version Release Date Features


JDK Beta 1995 —

JDK 1.0 January 1996 This is the first stable version.


In this version, added many new library elements,
redefined the way of handling events, and reconfigured
JDK 1.1 February 1997 most of the libraries of 1.0 and deprecated some features
defined by 1.0. Added inner class, JavaBeans, JDBC,
RMI, JIT (Just In time) compiler.

Added support for many features, such as Swing and


J2SE 1.2 December 1998 Collection Framework. The methods suspend(), resume()
and stop() of Thread class were deprecated.
A very small improvement, as it just improved the
J2SE 1.3 May 2000
development environment.
It added some upgrades such as the new keyword assert,
chained exception and a channel-based I/O subsystem.
J2SE 1.4 February 2002 Also added some feature to the collection framework and
the Networking classes.
The significant new features added to this version are –
Generics, Annotation, Autoboxing and Auto-unboxing,
J2SE 5.0 September 2004
Enumeration, for-each, variable-length argument, Static
import, Formatted I/O, Concurrency utilities.
In this version the API libraries and several new packages
Java SE 6 December 2006 got enhanced and offered improvements to the run time.
It supports JDBC 4.0.
Added JVM support for dynamic language, String in the
switch, Automatic resource management in try-
Java SE 7 July 2011
statement, support for underscore in integers, binary
integer literals etc.
Added Date and time API, Repeating annotation,
Java SE 8 March 2014
JavaFX.
Added Java platform module system update, jshell, XML
Java SE 9 September 2017
Catalog, jlink, and the JavaDB was removed from JDK
Added features are local variable type interface,
Java SE 10 March 2018 Application class data sharing, Garbage collector
interface, etc.
Feature added: Dynamic class file loader, HTTP client,
Java SE 11 September 2018 and Transport layer security. JavaFX, Java EE, and
CORBA modules have been removed from JDK.
Added Microbenchmark Suite, JVM Constant API, One
Java SE 12 March 2019
AArch64 Port, Default CDS Archives etc.
Z Garbage Collector enhancements, application class-
Java SE 13 September 2019 data sharing, and previews of switch expressions and text
blocks.
Includes new capabilities such as JDK Flight Recorder
Java SE 14 March 2020 event streaming, pattern matching, and switch
expressions.

4
Includes update to standard Java Features text blocks,
Java SE 15 September 2020 hidden classes, the Z Garbage Collector, and previews of
pattern matching and records.
Upgrade of standard Java include primitive classes,
Java SE 16 March 2021 sealed classes, records, a vector API, and ports for
Windows on ARM64 and Alpine Linux.

1.4 JavaApplets and Applications


❖ Java can be used to construct two kinds of programs: Applications and Applets.
❖ An Application is a program that runs on our computer, under the operating system of that
computer. That is, an application created by Java is more or less like one created using C or C++.
When used to create applications, Java is not much different from any other computer language.
❖ An applet is an application designed to be transmitted over the Internet and executed by a java-
compatible Web browser. An Applet is actually a tiny Java program, dynamically
downloaded across the network, just like an image, sound file, or video clip.
❖ The important difference is that an applet is an intelligent program, not just as an animation or
media file. In other words, an applet is a program that can react to user input and dynamically
change – not just run the same animation or sound over and over.
1.5 Features of Java
❖ Java is a truly object-oriented language.
❖ The features of Java are also known as Java buzzwords.
❖ The important features of Java are as follows:
1. Simple
2. Secure
3. Portable
4. Object-Oriented
5. Robust
6. Multithreaded
7. Architecture-Neutral
8. Interpreted
9. High Performance
10. Distributed
11. Dynamic
1. Simple
❖ Java is one of the simplest programming languages to learn.
❖ The Java programming language retains many of the features of C++ and removes the
unnecessary complexities like Pointers, Operator Overloading and Multiple Inheritance of C++.
❖ Syntax of Java is very similar to C and C++ that enables C/C++ programmers to migrate easily
5
to Java platform.
2. Secure
❖ Java is highly secure. The Java interpreter verifies the byte code before executing it.
❖ If the byte code runs out to be invalid, it will not be executed at all. Java does not allow
programmers to interact with the memory of the system. I.e. one cannot write a Java code that
accesses the memory of the system.
3. Portable
❖ The ability of software to run on different processors is referred to as portability. The Java system
was built to be portable.
❖ Java programs are the same on every platform. The feature Write-Sonce-run-anywhere (WORA)
makes the Java language portable provided that the system must have interpreter for the JVM.
4. Object-Oriented
❖ Java is an Object-Oriented Programming language. It has all OOP features such
as Abstraction, Encapsulation, Inheritance and Polymorphism.
❖ Object-Oriented Programming (OOPs) is a methodology that simplifies software development
and maintenance by providing some rules.
5. Robust
❖ Robust simply means strong. Java is robust because:
• It uses strong memory management.
• There is automatic garbage collection in java which runs on the Java Virtual Machine to get
rid of objects which are not being used by a Java application anymore.
• There are exception handling and the type checking mechanism in Java. All these points
make Java robust.
6. Multithreaded
❖ Multithreaded means handling multiple tasks simultaneously.
❖ Java supports multithreaded programs. This means that we need not wait for the application to
finish one task before beginning another.
❖ Multithreading works the similar way as multiple processes run on one computer.
7. Architecture-Neutral
❖ Java is architecture neutral because there are no implementation dependent features, for example,
the size of primitive types is fixed.
❖ In C programming, int data type occupies 2 bytes of memory for 32-bit architecture and 4 bytes
of memory for 64-bit architecture. However, it occupies 4 bytes of memory for both 32 and 64-
bit architectures in Java.
8. Interpreted

6
❖ Java is an interpreted language.
❖ Java programs can be executed directly on any machine, which has the Java interpreter known
as the Java Virtual Machine and where the run-time environment has been ported.
9. High Performance
❖ Java provides high performance with the use of “JIT – Just In Time compiler”, in which the
compiler compiles the code on-demand basis, that is, it compiles only that method which is being
called. This saves time and makes it more efficient.
❖ Bytecodes generated by the Java compiler are highly optimized, so Java Virtual Machine can
execute them much faster.

10. Distributed

❖ Java is distributed because it encourages users to create distributed applications.


❖ RMI (Remote Method Invocation) and EJB (Enterprise Java Beans) are used for creating
distributed applications.
❖ This enables multiple programmers at multiple remote locations to collaborate and work
together on a single project.
11. Dynamic
❖ Java programs are dynamic.
❖ A Java program consists of many modules and when they undergo any changes, the dynamism
of Java avoids problems caused by change of code used in a program.
1.6 Java and C++

❖ Java is a true object-oriented language while C++ is basically C with object-oriented extension.
❖ Some major C++ features that were intentionally omitted from Java or significantly modified
are:
• Java does not support Operator Overloading.
• Java does not have template classes as in C++.
• Java does not support multiple inheritance of classes. This is accomplished using a new
feature called “interface”.
• Java does not support global variables. Every variable and method is declared within a class
and forms part of that class.
• Java does not use Pointers.
• Java has replaced the destructor function with a finalize() function.
• There are no header files in Java.

1.7 Java and Internet

❖ Java is strongly associated with the Internet because of the fact that the first application program

7
written in Java was HotJava, a Web browser to run applets on Internet.
❖ Internet users can use Java to create applet programs and run them locally using a “Java-enabled
browser” such as HotJava.
❖ They can also use a Java-enabled browser to download an applet located on a computer
anywhere in the Internet and run it on his local computer.
1.8 Java and World Wide Web
❖ World Wide Web (WWW) is an open-ended information retrieval system designed to be used
in the Internet’s distributed environment. This system contains what are known as Web pages
that provide both information and controls.
❖ Java was meant to be used in distributed environments such as Internet. Since, both the Web
and Java share the same philosophy, Java could be easily incorporated into the Web system.
❖ With the support of Java, the Web has become more interactive and dynamic. Java
communicates with a Web page through a special tag called <APPLET>.
Exercises:

1. What is Java?
2. Write short notes on History of Java.
3. Discuss briefly about the Evolution of Java.
4. What do you mean by Java “Applets” and “Applications”?
5. Explain the Features of Java.
6. Distinguish between Java and C++.
7. Write short notes on Java and Internet.
8. Write a brief note on Java and WWW.
**************************

*******************************************************************************
Chapter 2 An Overview of Java
*******************************************************************************
2.1 Definition of OOP
❖ Object-Oriented Programming is an approach that provides a way of modularizing
programs by creating partitioned memory area for both data and functions that can be
used as templates for creating copies of such modules on demand.

8
2.2 Object-Oriented Paradigm

❖ OOP allows us to decompose a problem into a number of smaller entities called Objects and
then build dataand functions (known as methods in Java) around these entities.
❖ The combination of data and functions make up an object.The data of an object can be accessed
only by the methods associated with that object. However, methods of one object can access
the methods of other objects.
2.3 Basic Concepts of Object-Oriented Programming
❖ Object Oriented Programming is a method of implementation in which programs are
organized as cooperative collection of objects, each of which represents an instance of a class,
and whose classes are all members of a hierarchy of classes united via inheritance relationships.
❖ The general concepts of OOP are as follows:
1. Classes
❖ Collection of objects is called class. It is a logical entity.
❖ A class can also be defined as a blueprint from which we can create an individual object. Class
doesn't consume any space.
2. Objects
❖ An Object can be defined as an instance of a class. An object contains an address and takes up
some space in memory.
❖ Any entity that has state and behavior is known as an object. For example, a chair, pen, table,
keyboard, bike, etc.
❖ In other terms, objects are the runtime entities of a class. For example, the object for Student
class can be created as follows:
Student st1;

st1 is the runtime entity of Student and it will have the data members Name, DOB and marks
and the functions Total, Average and Display can be used by st1 to calculate.
3. Abstraction
❖ Abstraction refers to the act of representing essential features without including the
explanations. Since the classes use the concept of data abstraction, they are known as Abstract
Data Types.
4. Encapsulation
❖ The wrapping up of data and functions into a single unit is called as encapsulation.
❖ A java class is the example of encapsulation.
5. Inheritance

❖ Inheritance is the process by which objects of one class acquire the properties of another class.

9
❖ For example, a student as well as a staff is a Person. Both have some common properties.
Inheritance allows the programmer to reuse defined properties.
6. Polymorphism
❖ Polymorphism means the ability to take more than one form. For example, consider the
operation of addition.
• For two numbers, the operation will generate a sum.
• If the operands are strings, then the operation would produce a third string by concatenation.
7. Dynamic Binding

❖ Binding refers to the linking of a procedure call to the code to be executed.


❖ Dynamic Binding means that the code associated with a given procedure call is not known
until the time of the call at run-time.
8. Message Passing
❖ Objects communicate with one another by sending and receiving information. A message for
an object is a request for execution of a procedure.
❖ Message Passing involves specifying the name of the object, the name of the function
(message) and the information to be sent.
2.4 Benefits of OOP
❖ OOP offers several benefits to both the program designer and the user. The principal
advantages are:
• Through inheritance, we can eliminate redundant code and extend the use of existing classes.
• We can build programs from the standard working modules that communicate with one
another, rather than having to start writing the code from scratch. This leads to saving of
development time and higher productivity.
• The principle of data hiding helps the programmer to build secure programs that cannot be
invaded by code in other parts of the program.
• It is possible to have multiple objects to coexist without any interference.
• It is possible to map objects in the problem domain to those objects in the program.
• It is easy to partition the work in a project based on objects.
• The data-centered design approach enables us to compare more details of a model in an
implementable form.
• Object-oriented systems can be easily upgraded from small to large systems.
2.5 Applications of OOP
❖ Applications of OOP are beginning to gain importance in many areas. The most popular
application of Object-Oriented Programming, has been in the area of user interface design such
as windows. There are hundreds of windowing systems developed using OOP techniques.
10
❖ The promising areas for applications of OOP include:

• Real-time Systems
• Simulation and Modeling
• Object-Oriented Databases
• Hypertext, Hypermedia and Expertext
• AI and Expert Systems
• Neural Networks and Parallel Programming
• Decision Support and Office Automation Systems
• CIM/CAD/CAM Systems
2.6 The Bytecode
❖ The output of a Java compiler is called a bytecode.
❖ Bytecode is a highly optimized set of instructions designed to be executed by the Java run-time
system, which is called the Java Virtual Machine (JVM). That is, in its standard form, the JVM
is an interpreter for bytecode.
❖ Translating a Java program into bytecode helps makes it much easier to run a program in a wide
variety of environments. The interpretation of bytecode is the easiest way to create truly portable
programs.
2.7 Java Environment
❖ Java environment includes a large number of development tools and hundreds of classes and
methods. The development tools are part of the system known as Java Development Kit (JDK)
and the classes and methods are part of the Java Standard Library (JSL), also known as the
Application Programming Interface (API).
Java Development Kit
❖ The Java Development Kit comes with a collection of tools that are used for developing and
running Java programs. They include:
• appletviewer (for viewing Java applets)
• javac (Java compiler)
• java (Java Interpreter)
• javap (Java disassemble)
• javah (for C header files)
• javadoc (for creating HTML documents)
• jdb (Java debugger)
❖ Table 1.1 lists these tools and their descriptions.

Tool Description
appletviewer Enables us to run Java applets (without actually using a Java-compatible
11
browser).
Java interpreter, which runs applets and applications by reading and
java interpreting bytecode files.
The Java compiler, which translates Java source code to bytecode files that
javac
the interpreter can understand.
javadoc Creates HTML format documentation from Java source code files.
javah Produces header for use with native methods.
Java disassembler, which enables us to convert bytecode files into a
javap
program description.
jdb Java debugger, which helps us to find errors in our programs.
Table 1.1: Java Development Tools
Application Programming Interface
❖ The Java Standard Library (or API) includes hundreds of classes and methods grouped into
several functional packages.
• Language Support Package: A collection of classes and methods required for
implementing basic features of Java.
• Utilities Package: A collection of classes to provide utility functions such as date and time
functions.
• Input / Output Package: A collection of classes required for input / output manipulation.
• Networking Package: A collection of classes for communicating with other computers via
Internet.
• AWT package: The Abstract Window Tool Kit package contains classes that implements
platform-independent graphical user interface.
• Applet Package: This includes a set of classes that allows us to create Java applets.
2.8 Structure of a Java Program
❖ Every Java program is written as a collection of one or more classes. Each class contains data
members and methods that act upon data members.
❖ The methods contain executable statements. Even though a Java program contain many classes,
only one of them should contain the main() method.
❖ The execution of a Java program starts with the main() method.
❖ A Java program can contain one or more sections as shown below.

Documentation Section
Package Statement
Import Statements
Interface Statements
Class Definitions

Main Method Class


12
{ <---------- Suggested
Main Method Definition
<---------- Optional
}
<---------- Optional
<---------- Optional
<---------- Optional

<---------- Essential

Documentation Section
❖ The documentation section contains a set of comment lines. Java supports three types of
comments.
1. Single-line Comment
2. Multiline Comment
3. Documentation Comment
❖ A single line comment starts with // and ends in the single line.
Example:
// The following program will calculate the bonus
❖ A multiline comment spreads over several lines. Such a comment begins with /* and ends with
*/

Example:

/* This program receives the salary of an employee


and computes the incentive
*/
❖ The documentation comment is used to produce an HTML file that documents our program. The
documentation comment begins with a /** and ends with a */.
Package Statement
❖ The package statement is optional. If a package program involves the package statement, it
should be written as the first statement of that program.
Import Statements
❖ The import statement is placed next to the package statement in a Java program. Suppose that
in a Java program we refer to a class which is within the predefined package named io, which in
turn is within another predefined package named java. We have to write the following import
statement in such a Java program.
import java.io.*;
This statement instructs the Java interpreter to load the classes in the io package, which is within
the java package. Each predefined package in Java, such as io and Java, will contain several
classes. The import statement in Java is similar to the #include statement in C++.
13
Interface Statements
❖ An interface is like a class but include a group of method declarations. This is also an optional
section and is used only when we wish to implement the multiple inheritance feature in the
program.
Class Definitions
❖ A Java program may contain multiple class definitions. A Java class is made up of data members
and methods that act upon these data members. Each method shall contain one or more executable
statements. Each Java program shall have one or more classes. The number of classes used
depends on the complexity of the problem.
Main Method Class
❖ The main method class is the essential part of a Java program. A simple Java program may
contain only this part. The main method creates objects of various classes and establishes
communications between them. On reaching the end of main, the program terminates and the
control passes back to the operating system.
2.9 Simple Java Program
//Example.java
class Example
{
public static void main(String args[])
{
System.out.println(“Welcome to Java Programming.”);
}
}
Class declaration
The first line
class Example
declares a class, which is an object-oriented concept. Java is a true object-oriented language and
therefore, everything must be placed inside a class. class is a keyword and declares that a new class
definition follows. Example is a Java identifier that specifies the name of the class to be defined.
Opening brace
Every class definition in Java begins with an opening brace “{“ and ends with a matching closing
brace “}”, appearing in the last line in the example.
The main line
public static void main(String args[])
declares a method named main. Conceptually, this is similar to the main() function in C / C++. Every
Java application program must include the main() method. This is the starting point for the interpreter
to begin the execution of the program. A Java application can have any number of classes but only

14
one of them must include a main method to initiate the execution.
This line contains a number of keywords, public, static and void.
-----------------------------------------------------------------------------------------------------------------------
public The keyword public is an access specifier that declares the main method as unprotected
and therefore making it accessible to all other classes. This is similar to the C++ public
modifier.
Static Next appears the keyword static, which declares this method as one that belongs to the
entire class and not a part of any object of the class. The main must always be declared
as static since the interpreter uses this method before any objects are created.
void The type modifier void states that the main method does not return any value.
-----------------------------------------------------------------------------------------------------------------------
All parameters to a method are declared inside a pair of parentheses. Hence, String args[] declares
a parameter named args, which contains an array of objects of the class type String.
The Output Line
The only executable statement in the program is
System.out.println(“Welcome to Java Programming.”);
This is similar to the printf() statement of C or cout<<construct of C++. Since Java is a true object
oriented language, every method must be part of an object. The println method is a member of the
out object, which is a static data member of System class This line prints the string
Welcome to Java Programming.

on the screen. The method always appends a newline character to the end of the string. This means
that any subsequent output will start on a new line. Every Java statement must end with a semicolon.
2.10 Java Character Set
❖ The set of characters allowed in Java constitutes its character set. All the constituents of a
Java program, such as identifiers, literals, keywords, expression and statements are written only
by using the characters in the following character set:
Numerals : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Alphabets : a, b, c, d, e, f, g, h, I, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z

: A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z

Special Characters : +, -, *, /, %, =, <, >, (, ), ‘, ,, :, ?, #, $, !, ^, ~, [, ], {, }


❖ Java uses the uniform 16-bit coding scheme called UNICODE to represent characters internally.
The Unicode can incorporate 65000 characters.
2.11 Lexical Issues
❖ Java programs are a collection of whitespace, identifiers, literals, comments, operators,
separators, and keywords.

15
Whitespace
❖ A space, tab, or newline is called a whitespace in Java.
❖ Java is a free-form language. This means that we do not follow any special indentation rules.
There must be at least one whitespace character between each token that was not already
delineated by an operator or separator.
Identifiers

❖ Identifiers are names given to classes, methods, variables, objects, arrays, packages and
interfaces in a program. These are user defined names.
Rules:
• Identifiers are formed with alphabets, digits, underscore and dollar sign characters.
• The first character must be an alphabet.
• Uppercase and lowercase letters are distinct.
• They can be of any length.
• They are case sensitive.
Literals

❖ A sequence of valid characters that represent a constant value is called a literal.


❖ Literals are also known as constants. Java language specifies five major types of literals. They
are:
• Integer literals
• Floating-point literals
• Character literals
• String literals
• Boolean literals
Comments
❖ There are three types of comments defined by Java: Single-line Comment, Multline Comment
and Documentation Comment. This type of comment is used to produce an HTML filethat
documents our program. The documentation comment begins with a /**and ends with a */.

Operators
❖ An operator is a symbol which represents some operation that can be performed on data. There
are eight operators in Java. They are Arithmetic operators, Relational operators, Logical
operators, Shorthand assignment operators, Increment and decrement operators, Conditional
operator, Bitwise operators, Special operators.
Separators
❖ A symbol that is used to separate one group from another group is called a separator.
16
❖ The most commonly used separator in Java is the semicolon.It is used to terminate statements.
❖ The separators are shown in the following table:

Symbol Name Purpose


() Parentheses Used to contain lists of parentheses in method definition and
invocation. Also used for defining precedence in expressions,
containing expressions in control statements, and surrounding
cast types.
{} Braces Used to contain the values of automatically initialized arrays.
Also, used to define a block of code for classes, methods, and
local scopes.
[] Brackets Used to declare array types. Also used when dereferencing array
values.
: Semicolon Used to separate statements.
, Comma Used to separate consecutive identifiers in a variable declaration,
also used to chain statements together inside a ‘for’ statement.
. Period Used to separate package names from sub-packages and
classes.Also, used to separate a variable or method from a
reference variable.
:: Colons Used to create a method or constructor reference.
… Ellipsis Indicates a variable-arity parameter.
@ Ampersand Begins an annotation.

Java Keywords
❖ Java Keywords are also known as as reserved words.
❖ Java Keywords are predefined in JAVA and they are used to represent some predefined actions.
❖ We cannot use them as names for variables, classes, methods and so on.
❖ All keywords are to be written in lower-case letters.
❖ In addition to the keywords, Java reserves the following: true, false, and null. These are values
defined by Java.
❖ There are 61 keywords currently defined in the Java language (Table 2.1)

abstract assert boolean break byte case


catch char class const continue default
do double else enum exports extends
final finally float for goto if
implements import instanceof int interface long
module native new open opens package
private protected provides public requires return
short static strictfp super switch synchronized

17
this throw throws to transient transitive
try uses void volatile while with
Table 2.1: Java Keywords
2.12 Java Statements
❖ A statement is an executable combination of tokens ending with a semicolon (;) mark. Java
statements are instructions that tell the programming language what to do. Java implements
several types of statements described in table below.

Summary of Java Statements


Statement Description Remarks
Empty Statement These do nothing and are used Same as C and C++
during program development as a
place holder.
Labeled Statement Any statement may begin with a Identical to C and C++
label. Such labels must not used as except their use with
keywords,. jump statements
Expression Statement Java has several types of Expression Same as C++
statements: Assignment, pre-
Increment/decrement, Post-
Increment/decrement, Method Call
and Allocation Expression.
Selection Statement There are three types of selection Same as C and C++
statements in Java: if, if-else, and
switch.
Iteration Statement There are three types of iteration Same as C and C++
statements: while, do and for. except for jumps and
labels
Jump Statement Jump statements pass control to the C and C++ do not use
labeled statement. The four types of labels with jump
Jump statement are: break, continue, statements
return and throw.
Synchronization Statement These are used for handling issues Not available in C and
with multi-threading. C++
Guarding Statement These are used to handle exceptions. Same as in C++ except
Thestatements use the keywords try, finally statement
catch, and finally.

18
Figure 2.1: Classification of Java Statements
2.13 Implementing a Java Program
❖ Implementation of a Java application program involves a series of steps. They include:
• Creating the program
• Compiling the program
• Running the program
Creating the Program
❖ To enter the program, we can use any word processor, such as MS-Word or the Windows
Notepad editor or the DOS editor. Assume that we have entered the following program:

//Simple Java Program


class Example
{
public static void main(String args[])
{
System.out.println(“Welcome to Java programming.”);
}
}
❖ Save this program in a file called Example.java ensuring that the file name contains the class
name properly. This file is called the source file.

Note: All Java source files will have the extension java. If a program contains multiple classes,
the file name must be the classname of the class containing the main method.

Compiling the Program

❖ To compile the Example program, execute the compiler, javac, specifying the name of the source
file on the command line as shown here:
C:\JDK1.6.0_01\BIN>javac Example.java
19
❖ The javac compiler creates a file called Example.class that contains the bytecode version of the
program. The Java bytecode is the intermediate representation of our program that contains the
instructions the Java interpreter will execute. Thus, the output of javac is not code that can be
directly executed.
Running the Program
❖ To actually run the program, we must use the Java interpreter called java. To do so, pass the
class name Example as a command-line argument as shown here:
C:\JDK1.6.0_01\BIN>java Example
When the program is run, the following output is displayed:
Welcome to Java Programming.
❖ When Java source code is compiled, each individual class is put into its own output file named
after the class and using the .class extension.
2.14 Java Virtual Machine
❖ The JVM (Java Virtual Machine) is the environment in which Java programs execute.
❖ It is software that is implemented on top of real hardware and operating system.
❖ JVM is Write Once-Run Anywhere (WORA) software.
❖ JVM forms part of large system JRE.
❖ JVM's main job is interpreting java byte code and translating this into actions or OS calls.
❖ JVM is OS dependent which makes java source code as machine independent.
2.15 Command Line Arguments
❖ Command line arguments are parameters that are supplied to the application program at
the time of invoking it for execution.
❖ We can write Java programs that can receive and use the arguments provided in the command
line. The signature of the main() method used in our earlier programs:
public static void main(String args[])
args is declared as an array of strings. Any arguments provided in the command line (at the
time of execution) are passed to the array args as its elements. We can simply access the array
elements and use them in the program as we wish.
The individual elements of an array are accessed by using an index or subscript like args[i].
The value of i denotes the position of the elements inside the array.
Example:

//Java program that uses command line arguments as input


class CmdLineTest
{
public static void main(String args[])
{
int count,i=0;
20
String str;
count=args.length;
System.out.println("Number of arguments = "+count);
while(i<count)
{
str=args[i];
i=i+1;
System.out.println(i +" : "+"Java is "+str+"!");
}
}
}
Compile and run the program with the command line as follows:
Java CmdLineTest Simple Object-Oriented Distributed Robust Secure Portable Multithreaded Dynamic
Upon execution, the command line arguments Simple, Object-Oriented, etc. are passed to the
program through the array args. That is the element args[0] contains Simple, args[1] contains Object-
Oriented and so on.
The output of the program would be s follows:
Number of arguments = 8
1: Java is Simple!
2: Java is Object-Oriented!
3: Java is Distributed!
4: Java is Robust!
5: Java is Secure!
6: Java is Portable!
7: Java is Multithreaded!
8: Java is Dynamic!
Exercises:
1. Define OOP.
2. Define Class.
3. What is an Object?
4. Write the benefits of OOP.
5. List out few applications of OOP.
6. Define Bytecode.
7. What is JDK in Java?
8. Define API.
9. Explain briefly about the Strucutre of a Java Program.
10. Explain the various access specifiers used in Java.
11. Discuss in detail about Java Character Set.
12. What are Java Keywords?
13. Explain the various kinds of Java statements.
14. Define JVM.
15. What are Command Line Arguments in Java?
**************************

21
*******************************************************************
Chapter 3 Data Types and Variables
*******************************************************************
3.1 Data Types
❖ Data Types specify the size and type of values that can be stored.
❖ Java language is rich in its data types. Java has four main primitive data types built into the
language.
• Integers: This group includes byte, short, int, and long, which are for whole-valued signed
numbers.
• Floating Point numbers: This group includes float and double, which represent numbers with
fractional precision.
• Characters: This group includes char, which represents symbols in a character set, like letters
and numbers.
• Boolean: This group includes boolean, which is a special type for representing true/false values.
❖ Data Types in Java under various categories are shown in Figure 3.1

Figure 3.1: Data Types in Java

Integer Types

❖ Java defines four integer types: byte, short, int, and long. All of these are signed, positive and
negative values. Java does not support unsigned, positive-only integers.
❖ The width and ranges of these integer types vary widely, as shown in this table:
------------------------------------------------------------------------------------------------------
Type Size Range
------------------------------------------------------------------------------------------------------
byte 1 byte -128 to 127
short 2 bytes -32,768 to 32,767
int 4 bytes -2,147,483,648 to 2,147,483,647
long 8 bytes -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
-----------------------------------------------------------------------------------------------------------

22
Figure 3.2: Integer Data Types
byte
❖ The smallest integer type is byte. This is a signed 8-bit type that has a range from -128 to 127.
❖ Variables of type byte are especially useful when we are working with a stream of data from a
network or file.
❖ Byte variables are declared by use of the byte keyword.
Example:
byte b,c;
short
❖ short is a signed 16-bit type. It has a range from -32,768 to 32,767.
❖ It is probably the least-used Java type. This type is mostly applicable to 16-bit computers.
Example:
short S;
short t;
int
❖ The most commonly used integer type is int. It is a signed 32-bit type that has a range from -
2,147,483,648 to 2,147,483,647.
❖ In addition to other uses, variables of type int are commonly employed to control loops and to
index arrays.
Example:
int a,b,c;
long
❖ long is a signed 64-bit type and is useful for those occasions where an int type is not large
enough to hold the desired value.
❖ The range of a long is quite large. This makes it useful when big, whole numbers are needed.
Example:
long distance;
Floating-Point Types
❖ Floating-point numbers, also known as real numbers, are used when evaluating expressions that
require fractional precision.
❖ Floating point types are used to hold numbers containing fractional parts such as 27.59 and -

23
1.375.
❖ There are two kinds of floating-point types, float and double, which represent single- and
double-precision numbers, respectively.

Figure 3.3: Floating Point Data Types


The following table gives the size and range of these two types:
--------------------------------------------------------------
Type Size Range
--------------------------------------------------------------
float 4 bytes 3.4e-038 to 3.4e+038
double 8 bytes 1.7e-308 to 1.7e+308
--------------------------------------------------------------
float
❖ The type float specifies a single-precision value that uses 32 bits of storage.
❖ Variable of type float are useful when we need a fractional component, but don’t require a large
degree of precision.
❖ For example, float can be useful when representing dollars and cents.
Example:
float hightemp, lowtemp;
double
❖ Double precision, as denoted by the double keyword, uses 64 bits to store a value.
❖ Double precision is actually faster than single precision on some modern processors that have
been optimized for high-speed mathematical calculations. All transcendental math functions,
such as sin(), cos(), sqrt(), return double values.
❖ When we need to maintain accuracy over many iterative calculations, or are manipulating large-
valued numbers, double is the best choice.
Example:
double pi;
Character Type
❖ Character Data Types are used to store character constants in memory.
❖ In Java, the character data type is denoted by the keyword char.
❖ The char type assumes a size of 2 bytes but, basically, it can hold only a single character. The
range of a char is 0 to 65,536.

24
Example:
char ch;
ch=’X’;
Boolean Type
❖ Boolean type is used when we want to test a particular condition during the execution of the
program.
❖ There are only two values that a Boolean type can take: true or false. Boolean type is denoted by
the keyword boolean and uses only one bit of storage.
❖ Boolean values are often used in selection and iteration statements.
Example:
boolean flag;
flag=true;
3.2 Constants (Literals)
❖ Constant refers tofixed values that do not change during the execution of a program.
❖ Constants are declared using the final keyword.
❖ Java support several types of constants as follows:
Integer Constants
❖ An integer constant refers to a sequence of digits. There are three types of integers, namely,
decimal integer, octal integer, and hexadecimal integer.
❖ Decimal integers consist of a set of digits, 0 through 9, preceded by an optional minus sign.
❖ Valid examples of decimal integer constants are:
123 -321 0 654321
❖ Embedded spaces, commas, and non-digit character are not permitted between digits. For
example,
15 750 20,000 $1000
are illegal numbers.
❖ An octal integer constant consists of any combination of digits from the set 0 through 7,
with a leading 0.
❖ Some examples of octal integer are:
037 0 0435 0551
❖ A sequence of digits preceded by 0x or 0X is considered as hexadecimal integer. They may
also include alphabets A through F or a through f. A letter A through F represents the numbers
10 through 15.
❖ Following are the examples of valid hex integers.
0x2 0x9F 0xbcd 0x

25
Real Constants
❖ A number with a decimal point is called a real constant or a floating point constant.
❖ Some examples of real constants are:
0.0083 -0.75 435.36
❖ A real number may also be expressed in exponential (or scientific) notation.
❖ For example, the value 215.65 may be written as 2.1565e2 in exponential notation.e2 means
multiply by 102. The general form is:
mantissa e exponent

❖ The mantissa is either a real number expressed in decimal notation or an integer.


❖ The exponent is an integer with an optional plus or minus sign. The letter e separating the
mantissa and the exponent can be written in either lowercase or uppercase.
❖ Since the exponent causes the decimal point to “float”, this notation is said to represent a real
number in floating point form.
❖ Examples of legal floating point constants are:
0.65e4 12e-2 1.5 e+5 3.18E3 -1.2 E-1
❖ A floating point constant may thus comprise four parts:
• a whole number
• a decimal point
• a fractional part
• an exponent
Single Character Constants
❖ A Single Character Constant (or simply character constant) contains a single character
enclosed within a pair of single quote marks.
❖ Examples of character constants are:
'5' 'X' ';' 'a'

Note: Character Constant '5' is not the same as the number 5.


String Constants
❖ A String Constant is a sequence of character enclosed between double quotes.
❖ The characters may be alphabets, digits, special characters and blank spaces. Examples are:
"Hello Java" "1997" "WELLDONE” “?...!” “5+3" "X"
Backslash Character Constants
❖ Java supports some special backslash character constants that are used in output methods.
❖ For example, the symbol ‘\n’ stands for newline character.
❖ A list of such backslash character constants is given in table below. These character
combinations are known as escape sequences.
26
Constant Meaning
'\b' back space
'\f' form feed
'\n' new line
'\t' horizontal tab
'\r' carriage return
'\'' single quote
'\"' double quote
'\\' Backslash

3.3 Variables
❖ A variable is an identifier that denotes a storage location used to store a data value.
❖ A variable may take different values at different times during the execution of the program.
❖ A variable name can be chosen by the programmer in a meaningful way so as to reflect what it
represents in the program.
❖ Some examples of variable names are:
i) average
ii) height
iii) total_height
iv) classStrength
Rules:
• A variable name may consist of alphabets, digits, the underscore (_) and the dollar character.

• The first character in a variable name should not be a digit.


• Uppercase and lowercase are distinct. This means that the variable Total is not the same as total
or TOTAL.
• A keyword should not be used as a variable name.
• White spaces are not allowed within a variable name.
• A variable name can be of any length.
Declaration of Variables
❖ In Java, all variables must be declared before they can be used. The basic form of a variable
declaration is shown here:
Datatype identifier [=value][,identifier [=value]…];
Examples:
int a,b,c;
int d=3,e,f=5;
byte age=22;
double pi=3.14159;
char x=’x’;

27
3.4 Giving Values to Variables
❖ A variable must be given a value after it has been declared before it is used in an expression.
❖ This can be declared in two ways:
• By using an assignment statement
The assignment statement is used to assign a value to a variable.
variableName=value;
type variableName=value;
• By using a read Statement
The readLine() method is used to read a line of text from the keyboard.
int n=Integer.parseInt(br.readLine());
3.5 Scope of Variables
❖ The area of the program where the variable is accessible (i.e., usable) is called its scope.
❖ Java allows variables to be declared within any block. A block defines the scope.
❖ Java variables are classified into three parts:
• Instance Variables
❖ A variable declared outside the method/block/constructor but inside the body is called an
instance variable.
❖ When an object of the class is created then the object also creates one copy of the instance
variable and destroyed when the object is destroyed.
❖ We can specify the access specifier for instance variables. By default, the default access
specifier will be used.
❖ Initialization of Instance Variable is not Mandatory. Its default value is depending on the data
type of variable.
❖ These variables can be accessed by creating objects.
• Class Variables
❖ Class Variables are declared inside a class.
❖ Class variables are global to a class and belong to the entire set of objects that class creates.
❖ Only one memory location is created for each class variable.
• Local Variables
❖ A variable declared inside the body of a method or block or constructor is called a local
variable.
❖ We can’t access these variable outside the method. These variables are created in memory
when the function/block/constructor is called. After completing the execution of
function/block/constructor these variables are destroyed by JVM.
❖ We can access these variables only within that block because the scope of these variables exists
only within the block.
28
❖ The initialization of the local variables is mandatory. If we don’t initialize the variable compiler
will throw run time exception.
3.6 Symbolic Constants
❖ Memory locations whose values cannot be changed within a program are called Constants
or Symbolic Constants.
❖ A constant is declared as follows:
final type symbolic-name=value;
Examples:
final int PASS_MARK=50;
final float PI=3.14159;
Note:
• Symbolic names take the same form as variable names. But, they are written in CAPITALS
because they are distinguished them from normal variable names.
• After declaration, they should not be assigned any other value within the program.
• They can't be declared inside of a class. They should be declared as beginning of the class.
3.7 Type Conversion and Type Casting
❖ The two terms Type Conversion and the Type Casting are used in a program to convert one
data type to another data type.
Type Conversion
❖ Type Conversion allows a compiler to convert one data type to another data type at the
compile time of a program or code.
❖ Converting a lower data type to a higher data type is known as widening.
❖ In this case the conversion is done automatically therefore, it is known as implicit type
casting.
❖ In this case both data types should be compatible with each other.

Example 1:

int x = 20;
long y = x; // Automatic Conversion

Example 2:

//Java Program to implement Type Conversion


public class TypeConversionExample
{
public static void main(String args[])
{
29
char ch = 'C';
int i = ch;
System.out.println("Integer value of the given character: "+i);
}
}
Output:
Integer value of the given character: 67
Type Casting
❖ Type Casting is a mechanism in which one data type is converted to another
data type by a programmer.
❖ Converting a higher data type to a lower data type is known as narrowing.
❖ In this case the casting is not done automatically, we need to convert explicitly using the cast
operator “( )” explicitly. Therefore, it is known as explicit type casting.
❖ In this case both data types need not be compatible with each other.

❖ The syntax is:


type variable1=(type) variable2;
Example 1:
int m=50;
byte n=(byte)m;
long count=(long)m;
Example 2:
//Java Program to implement Type Casting
import java.util.*;
public class TypeCastingExample
{
public static void main(String args[])
{
Scanner sc = new Scanner(System.in);
System.out.println("Enter an integer value: ");
int i = sc.nextInt();
char ch = (char) i;
System.out.println("Character value of the given integer: "+ch);
}
}
Output:

Enter an integer value:


67
Character value of the given integer: C

30
Differences Between Type Casting and Type Conversion
Sl. No. Type Casting Type Conversion
1 Type Casting is a mechanism in which Type Conversion allows a compiler to
one data type is converted to another data convert one data type to another data type at
type by a programmer. the compile time of a program or code.
2 It can be used both compatible data type Type Conversion is only used with
and incompatible data type. compatible data types.
3 It requires a programmer to manually The compiler automatically converts it at the
casting one data into another type. run time of a program.
4 It is used while designing a program by the It is used or take place at the compile time of
programmer. a program.
5 When casting one data type to another, the When converting one data type to another,
destination data type must be smaller than the destination type should be greater than
the source data. the source data type.
6 It is also known as narrowing conversion It is also known as widening conversion
because one larger data type converts to a because one smaller data type converts to a
smaller data type. larger data type.
7 It is more reliable and efficient. It is less efficient and less reliable.
8 There is a possibility of data loss in type Possibility of data loss is very less
casting.
9 float b = 3.0; int x = 5, y = 2, c;
int a = (int) b float q = 12.5, p;
p = q/x;

Exercises:
1. Define Data Type.
2. Explain the various Data Types available in Java.
3. What are Constants?
4. Explain the various Constants available in Java.
5. Define Variable.
6. How will you declare a Variable?
7. Discuss briefly about the Scope of Variables.
8. Define Symbolic Constants.
9. Define Type Conversion.
10. What is Type Casting?
11. Distinguish between Type Casting and Type Conversion.
**************************

31
*******************************************************************************
Chapter 4 Operators
*******************************************************************************
4.1 Java Operators
❖ Operators are used to perform operations on variables and values.
❖ Java provides a rich set of operators to manipulate variables.
❖ Java Operators can be classified into a number of related categories as below:
• Arithmetic Operators
• Relational Operators
• Logical Operators
• Assignment Operators
• Conditional Operators
• Bitwise Operators
• Special Operators
Arithmetic Operators
❖ Arithmetic Operators are used to perform common mathematical operations.
❖ The following table lists the Arithmetic Operators:
Operator Meaning
+ Addition or Unary Plus
- Subtraction or Unary Minus
* Multiplication
/ Division
% Modulus
++ Increment
-- Decrement

Relational Operators
❖ Relational Operators in Java are used to compare two or more objects.
❖ Java supports six relational operators.
❖ The following table lists the relational operators:
Operator Meaning
== Equal to
!= Not Equal to
> Greater than
< Less than
>= Greater than or equal to
32
<= Less than or equal to
Logical Operators

❖ Logical Operators return a true or false value based on the state of the variables.
❖ Java has three Logical or Boolean Operators.
❖ The following table lists the logical operators:
Operator Meaning

&& Logical AND


|| Logical OR
! Logical NOT
Assignment Operators
❖ Assignment Operators are used to assign values to variables.
❖ The simplest assignment operator is =.
❖ In addition, Java has a set of ‘shorthand’ assignment operators which are used in the form
v op= exp;
where v is a variable, exp is an expression and op is a Java binary operator. The operator op= is
known as the shorthand assignment operator.
Operator Meaning
= Simple assignment operator
+= Add AND assignment operator
-= Subtract AND assignment operator
*= Multiply AND assignment operator
/= Divide AND assignment operator
%= Modulus and assignment operator
The Conditional Operator
❖ Conditional Operator is also known as the ternary operator.
❖ The character pair ? : is a ternary operator available in Java. This operator consists of three
operands and is used to evaluate Boolean expressions.
❖ This operator is used to evaluate conditional expression of the form
expression1 ? expression2 : expression3
Here, expression1 can be any expression that evaluates to a boolean value. If expression1 is
true, then expression2 is evaluated; otherwise, expression3 is evaluated. Both expression2 and
expression3 are required to return the same type, which can’t be void.
Example:
a=10;
b=15;
33
x=(a>b)?a:b;
In this example, x will be assigned the value of b.
Bitwise Operators
❖ Java defines several bitwise operators that can be applied to the integer types: long, int, short,
char, and byte.
❖ These operators act upon the individual bits of their operands.
❖ The following table lists the bitwise operators:
Operator Meaning

& Bitwise AND


| Bitwise OR
^ Bitwise exclusive OR
~ One’s complement
<< Shift left
>> Shift right
>>> Shift right with zero fill
&= Bitwise AND assignment
!= Bitwise OR assignment
^= Bitwise exclusive OR assignment
<<= Shift left assignment
>>= Shift right assignment
>>>= Shift right with zero fill assignment
Special Operators
❖ Java supports some special operators of interest such as instanceof operator and member
selection operator (.).
instanceOf Operator
❖ The instanceOf is an object reference operator and return true if the object on the left-hand side
is an instance of the class given on the right-hand side.
❖ This operator allows us to determine whether the object belongs to a particular class or not.
❖ The instanceOf operator is written as:

( Object reference variable ) instanceOf (class/interface type)


Example:
person instanceOf student
is true if the object person belongs to the class student; otherwise it is false.
Dot Operator
❖ The dot operator (.) is used to access the instance variables and methods of class objects.
34
Examples:
person1.age //Reference to the variable age
person1.salary() //Reference to the method salary()
❖ It is also used to access classes and sub-packages from a package.
4.2 Arithmetic Expressions
❖ An arithmetic expression is a combination, variables, constants, and operators arranged as per
the syntax of the language.
❖ Java can handle any complex mathematical expressions.
4.3 Evaluation of Expressions
❖ Expressions are evaluated using an assignment statement of the form
variable=expression;
variable is any valid Java variable name. When the statement is encountered, the expression
is evaluated first and the result then replaces the previous value of the variable on the left-
hand side. All variables used in the expression must be assigned values before evaluation is
attempted.
Examples:
x=a*b-c;
y=b/c*a;
z=a-b/c+d;
When these statements are used in program, the variables a, b, c and d must be defined before
they are used in the expressions.
4.4 Precedence of Arithmetic Operators
❖ An arithmetic expression without any parentheses will be evaluated form left to right using
the rules of precedence of operators.
❖ There are two distinct priority levels of arithmetic operators in Java:
High priority */%
Low priority +-
❖ The basic evaluation procedure includes two left-to-right passes through the expression.
During the first pass, the high priority operators (if any) are applied as they are encountered.
During the second pass, the low priority operators (if any) are applied as they are
encountered.
Consider the following evaluation statement:
x = a-b/3+c*2-1
When a = 9, b = 12, and c = 3, the statement becomes
x = 9-12/3+3*2-1
35
and is evaluated as follows:
First Pass
Step1: x = 9-4+3*2-1 (12/3 evaluated)
Step2: x = 9-4+6-1 (3*2 evaluated)
Second Pass
Step3: x = 5+6-1 (9-4 evaluated)
Step4: x = 11-1 (5+6 evaluated)
Step5: x = 10 (11-1 evaluated)
However, the order of evaluation can be changed by introducing parentheses into an expression.
Consider the same expression with parentheses as shown below:
9-12/(3+3)*(2-1)
Whenever the parentheses are used, the expressions within parentheses assume highest priority. If
two or more sets of parentheses appear one after another, the expression contained in the left-most
set is evaluated first and the right-most in the last.
Given below are the new steps.
First Pass
Step1: 9-12/6*(2-1)
Step2: 9-12/6*1
Second Pass
Step3: 9-2*1
Step4: 9-2
Third Pass
Step5: 7
Parentheses may be nested, and in such cases, evaluation of the expression will proceed
outward from the innermost set of parentheses.
4.5 Operator Precedence in Java
❖ Operator Precedence determines the order in which the operators in an expression are
evaluated.
❖ The operators at the highest level of precedence are evaluated first.
❖ The operators of the same precedence are evaluated either from left to right or right to left,
depending on the level. This is known as the associativity property of an operator.

36
❖ Table 4.1 shows the order of precedence for Java operators, from highest to lowest.

Table 4.1: The Precedence of the Java Operators


4.6 Mathematical Functions
❖ Java supports the basic math functions through the Math class defined in the java.lang package.
❖ These functions should be used as follows:
Math.function_name()
Example:
double y=Math.sqrt(x);
Functions Action
sin(x) Returns the sine of an angle x in radians.
cos(x) Returns the cosine of an angle x in radians.
tan(x) Returns the tangent of an angle x in radians.
asin(y) Returns the angle whose sine is y
acos(y) Returns the angle whose cosine is y.
atan(y) Returns the angle whose tangent is y.
atan2(x,y) Returns the angle whose tangent is x/y.
pow(x,y) Returns x raised to y (xy).
exp(x) Returns e raised to x (ex).
log(x) Returns the natural logarithm of x.
sqrt(x) Returns the square root of x.
ceil(x) Returns the smallest whole number greater than or equal to x. (Rounding up)
floor(x) Returns the largest whole number less than or equal to x. (Rounding down)
rint(x) Returns the truncated value of x.
abs(a) Returns tha absolute value of a.

37
max(a,b) Returns the maximum of a and b.
min(a,b) Returns the minimum of a and b.
Note: x and y are double type parameters, a and b may be ints, longs, floats and doubles.
Simple Java Programs
//Java program to find the Area of the Circle
//area.java
import java.io.*;
class area
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
float r,a;
final float pi=3.14f;
System.out.println("Enter the radius");
r=Float.parseFloat(br.readLine());
a=pi*r*r;
System.out.println("Area of the Circle="+a);
}
}

Output:
Enter the radius
10
Area of the Circle=314
-----------------------------------------------------------------------------------------------------------------------
//Java program to add two numbers
//addnos.java
import java.io.*;
class addnos
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int a,b,c;
System.out.println("Enter the first number");
a=Integer.parseInt(br.readLine());
System.out.println("Enter the second number");
b=Integer.parseInt(br.readLine());
c=a+b;
System.out.println("Sum="+c);
}
}
Output:

38
Enter the first number
25
Enter the second number
35
Sum=60
Exercises:
1. Explain the various Operators available in Java.
2. Define Conditional Operator.
3. What are Logical Operators?
4. What is an instanceOf operator?
5. List out the Bitwise Operators.
6. Discuss briefly about operator precedence in Java.
7. Explain the various methods of the Math class with suitable example.
8. Write a Java program to perform arithmetic operations.
**************************

39
************************************************************
Chapter 5 Control Statements
*********************************************************
5.1 Introduction
❖ The Control Statements are used for controlling the execution of the program.
❖ There are three main categories of control statements;
• Selection Statements: if and switch.
• Looping Statements: while, do-while and for.
• Transfer Statements: break, continue and return.
5.2 Selection Statements
❖ Java supports two selection statements - if and switch. These statements allow us to control the
flow of the program.
❖ Depending upon the expressions or values, the corresponding blocks/statements of code will be
executed or by passed.
❖ The two statements are
• if statement is a conditional branch statement. This is a two way branch statement.
Depending upon the whether a condition is true or false, the corresponding code is executed.
• switch statement is a multiway branch statement. Depending upon the value used for
switching, the corresponding code is executed.
❖ These two statements are very powerful and are used widely across any application. They
provide effective solutions for branching problems.
1. The if Statement
❖ The if statement is a powerful decision making statement and is used to control the flow of
execution of statements.
❖ It is basically a two-way decision statement and is used in conjunction with an expression.
❖ The if statement may be implemented in different forms depending on the complexity of
conditions to be tested.
i) Simple if statement
ii) if…else statement
iii) Nested if…else statement
iv) if-else-if Ladder
i) Simple if Statement
❖ The if statement executes a block of code only if the specified condition is true.
❖ If the condition is false, then the if block is skipped and execution continues with the rest of the
program.
Syntax:

40
if (Condition)
{
//Statements;
}

Here, Condition is a boolean expression. It returns either true or false.


If a user doesn’t provide curly braces (‘{‘ ‘}’ ) then by default only one statement will be considered
inside the if block.
Example:
// Java program to demonstrate Simple if Statement
import java.io.*;
public class IfStatementDemo
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int a, b;
System.out.println("Enter the first number");
a=Integer.parseInt(br.readLine());
System.out.println("Enter the second number");
b=Integer.parseInt(br.readLine());
if (a > b)
{
System.out.println("Biggest="+a);
}
System.out.println("Biggest="+b);
}
}
Output:
Enter the first number
10
Enter the second number
20
Biggest=20
ii) The if…else Statement
❖ The if…else Statement is used to execute a block of code if the condition is true and
another block of code if the condition is false.
❖ We can either have a single statement or a block of code within if…else blocks.
Syntax:
if (Condition)
{
//Statements;
}
else

41
{
//Statements;
}
Here, Condition is a boolean expression. It returns either true or false.
Example :
//Java program to check whether the given number is odd or even
//oddeven.java
import java.io.*;
class oddeven
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int n,r;
System.out.println("Enter the number");
n=Integer.parseInt(br.readLine());
r=n%2;
if (r==0)
System.out.println("The given number is even");
else
System.out.println("The given number is odd");
}
}
Output:
Enter the number
5
The given number is odd
iii) Nested if…else Statement
❖ An if…else statement within another if…else statement is called nested if…else statement.
❖ When a series of decisions are involved, we may have to use more than one if…else statement
in nested form as follows:
if (Condition-1)
{
if (Condition-2)
{
//Statement-1;
}
else
{
//Statement-2;
}
}
else
{
//Statement-3;

42
}
//Statement-x;

❖ If the Condition-1 is false, Statement-3 will be executed; otherwise, it continues to perform the
second test. If the condition-2 is true, the Statement-1 will be evaluated; otherwise the
Statement-2 will be evaluated and then the control is transferred to the Statement-x.

Example:

//Java program to find the biggest among three numbers using nested if statement
//big3.java
import java.io.*;
class big3
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int a,b,c;
System.out.println("Enter the first number");
a=Integer.parseInt(br.readLine());
System.out.println("Enter the second number");
b=Integer.parseInt(br.readLine());
System.out.println("Enter the third number");
c=Integer.parseInt(br.readLine());
if ((a>b) && (a>c))
{
System.out.println("Biggest="+a);
}
if ((b>a) && (b>c))
{
System.out.println("Biggest="+b);
}
else
{
System.out.println("Biggest="+c);
}
}
}

Output:
Enter the first number
50
Enter the second number
40
Enter the third number

43
30
Biggest=50
iv) if…else…if Ladder
❖ An if...else...if ladder can be used to execute one block of code among multiple blocks.
Syntax:
if(Condition1)
{
//Statements
}
else if(Condition2)
{
//Statements
}
.
.
.
else
{
//Statements
}
❖ This construct is known as the else if ladder.
❖ The conditions are evaluated from top (of the ladder) to bottom.
❖ When the test condition is true, code inside the body of that if block is executed. And,
program control jumps outside the if...else...if ladder.
❖ If all test expressions are false, code inside the body of else are executed.
Example:

//Java Program to implement if-else-if ladder


//PrintStudentGrade.java
import java.io.*;
class PrintStudentGrade
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int marks;
System.out.println("Enter the marks");
marks=Integer.parseInt(br.readLine());
if( marks >= 75 )
{
System.out.println("Distinction");
}
else if( marks >= 60 )
{
System.out.println("First Class");
44
}
else if( marks >= 50 )
{
System.out.println("Second Class");
}
else
{
System.out.println("Fail");
}
}
}
Output:
Enter the marks
75
Distinction
2. The switch Statement
❖ The switch statement is a multiway branch statement. It provides an easy way to
dispatch execution to different parts of code based on the value of the expression.
❖ It often provides a better alternative than a large series of if-else-if statements.
Syntax:
switch(expression)
{
case value1:
// Statements
break;
case value2:
//Statements
break;
.
.
.
default:
//Default Statement
}

❖ The value of the expression is evaluated and compared with each of the values in the case
statements.
❖ If a match is found, the code sequence following that case statement is executed. If none of the
constants matches the value of the expression, then the default statement is executed. However,
the default statement is optional.
❖ The break statement is used inside the switch to terminate a statement sequence.
Example:
//Java program to print the days of the week using switch statement
45
//days_of_week.java
import java.io.*;
class days_of_week
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int d;
System.out.println("Enter the day code");
d=Integer.parseInt(br.readLine());
switch(d)
{
case 1 : System.out.println("Sunday");
break;
case 2 : System.out.println("Monday");
break;
case 3 : System.out.println("Tuesday");
break;
case 4 : System.out.println("Wednesday");
break;
case 5 : System.out.println("Thursday");
break;
case 6 : System.out.println("Friday");
break;
case 7 : System.out.println("Saturday");
break;
default : System.out.println("Wrong day code");
}
}
}
Output:
Enter the day code
2
Monday
Nested switch Statement
❖ A switch statement inside another switch statement is known as nested switch statement.
❖ The inner switch statement will be part of any case of an outer switch.
❖ The inner switch statement will be executed only if the outer switch statement condition is true.
Example:
//Java Program to implement Nested Switch Statement
import java.io.*;
public class ExampleOfNestedSwitch
{
public static void main(String args[]) throws IOException
{
int year, marks;
BufferedReader br=new BufferedReader(New InputStreamReader(System.in));

46
System.out.println(“Enter the year”);
year=Integer.parseInt(br.readLine());
System.out.println(“Enter the marks”);
marks=Integer.parseInt(br.readLine());
switch(year)
{
case 1:
System.out.println("First year students are not eligible for scholarship ");
break;
case 2:
System.out.println("Second year students are not eligible for scholarship");
break;
case 3:
switch(marks)
{
case 50:
System.out.println("You are not eligible for scholarship");
break;
case 80:
System.out.println("Congrats! You are eligible for scholarship");
break;
}
break;
default:
System.out.println("Please enter valid year");
}
}
}
Output:
Enter the year
3
Enter the marks
80
Congrats! You are eligible for scholarship

Differences Between if..else and switch Statements

if…else switch
If statement is used to select among two The switch statement is used to select among
alternatives multiple alternatives.
It contains either logical or equality It contains a single expression which can be either a
expression. character or integer variable.
It evaluates all types of data, such as integer, It evaluates either an integer, or character.
floating-point, character or Boolean.
First, the condition is checked. If the condition It executes one case after another till the break
is true then 'if' block is executed otherwise keyword is not found, or the default statement is
'else' block executed.
47
If the condition is not true, then by default, else If the value does not match with any case, then by
block will be executed. default, default statement is executed.
It is difficult to edit the if-else statement, if the It is easy to edit switch cases as, they are recognized
nested if-else statement is used. easily.
If there are multiple choices implemented If we have multiple choices then the switch
through 'if-else', then the speed of the statement is the best option as the speed of the
execution will be slow. execution will be much higher than 'if-else'.

5.3 Looping Statements


❖ The process of repeatedly executing a block of statements is known as looping.
❖ The Java language provides three constructs for performing loop operations. They are:
1. The while Statement
2. The do…while Statement
3. The for Statement

1. The while Statement

❖ The while loop executes a block of code as long as a specified condition is true.
❖ If the number of iterations is not fixed, it is recommended to use a while loop.
❖ It is also known as an Entry-Controlled loop.
Syntax:
while(Condition)
{
//Body of while loop
}
❖ The Condition can be any Boolean expression.
❖ The body of while loop will be executed as long as the conditionl expression is true.
❖ When the Condition becomes false, control passes to the next line of code immediately
following the while loop.
Example:

//Java program to add individual digits of an n digit number


//add_digt.java
import java.io.*;
class add_digt
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int n,r,s=0;
System.out.println("Enter the number");
n=Integer.parseInt(br.readLine());

48
while(n>0)
{
r=n%10;
s=s+r;
n=n/10;
}
System.out.println("Sum of all digits="+s);
}
}
Output:
Enter the number
125
Sum of all digits=8
2. The do…while Statement

❖ The do...while loop executes a block of code repeatedly until the specified condition is true.

❖ It is also known as an Exit-Controlled Loop.

❖ The do…while loop is executed at least once because the condition is checked after the loop
body.

❖ The do…while loop is similar to the while loop, however there is a difference between them.
In while loop, the condition is evaluated before the execution of loop’s body but in do…while
loop the condition is evaluated after the execution of loop’s body.

Syntax:
do
{
//Body of the loop
}
while(Condition);
❖ The Condition can be any Boolean expression.
❖ Each iteration of the do…while loop first executes the body of the loop and then evaluates the
conditional expression. If this expression is true, the loop will repeat. Otherwise, the loop
terminates.
Example:
//Java program to print the positive integers from 1 to n
//print_digits.java
import java.io.*;
class print_digits
{
public static void main(String args[]) throws IOException
{

49
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int n,i=1;
System.out.println("Enter the number");
n=Integer.parseInt(br.readLine());
do
{
System.out.println(i);
i++;
}
while(i<=n);
}
}
Output:
Enter the number
5
1
2
3
4
5
3. The for Statement
❖ The for loop is used to execute a set of statements repeatedly for a specified number of
times.
❖ It is commonly used for simple iteration.
Syntax:
for (initialization; condition; increment/decrement)
{
//Body of for loop
}

If only one statement is being repeated, there is no need for the curly braces.
1. Initialization: The initialization portion of the loop is executed first. Generally, this is an
expression that sets the value of the loop control variable, which acts as a counter that controls
the loop. The initialization expression is executed only once.
2. Condition: The condition must be a Boolean expression. If this expression is true, then the
body of the loop is executed. If it is false, the loop terminates.
3. Body of for loop: It contains a block of code that executes each time after evaluating the
condition true.
4. Increment/decrement: This is usually an expression that increments or decrements the loop
control variable.
Example:
//Java program to find the factorial value of a given number
50
//fact.java
import java.io.*;
class fact
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int n;
long f=1;
System.out.println("Enter the number");
n=Integer.parseInt(br.readLine());
for(int i=1;i<=n;i++)
{
f=f*i;
}
System.out.println("Factorial Value="+f);
}
}
Output:
Enter the number
5
Factorial Value=120
5.4 Jump (Transfer) Statements
❖ Java supports three jump statements: break, continue, and return. These statements transfer
control to another part of the program.
1. The break statement
❖ The break statement is used to terminate the loop.
❖ When a break statement is encountered inside a loop, the loop is immediately terminated and the
program control resumes at the next statement following the loop.
❖ The break statement can be used in all types of loops such as for loop, while loop and do-while
loop.
Syntax:
break; // The unlabeled form
break label; // The labeled form
❖ In Java, the break statement has three uses. First, as we have seen, it terminates a statement
sequence in a switch statement. Second, it can be used to exit a loop. Third, it can be used as a
“civilized” form of goto.
i) Using break to Exit a Loop
❖ By using break, we can force immediate termination of a loop, bypassing the conditional
expression and any remaining code in the body of the loop.
51
Example:
//Java program to illustrate the break statement
//BreakExample.java
class BreakExample
{
public static void main(String args[])
{
System.out.println("Numbers 1 - 10");
for (int i = 1;i<=100;i++)
{
if (i == 5) break; // Terminate loop if i is 5
System.out.println(i);
}
}
}
Output:
Numbers 1 - 10
1
2
3
4
ii) Using break as a Form of goto
❖ The break statement can also be employed by itself to provide a “civilized” form of the goto
statement.
❖ Java does not have a goto statement. By using this form of break, we can break out of one or
more blocks of code.
Syntax:

break label;
Here, label is the name of the label that identifies a block of code. When this form of break
executes, control is transferred out of the named block of code.
To name a block, put a label at the start of it. A label is any valid Java identifier followed by
a colon. Once we have labeled the block, we can then use this label as the target of a break
statement.
Example:
//Java program to find the sum of 1 to n numbers using the break label statement
//BreakLoop.java
import java.io.*;
class BreakLoop
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int n,i,s=0;
System.out.println("Enter the number");
52
n=Integer.parseInt(br.readLine());
s=s+i;
i++;
start:
if (i<=n) break start;
System.out.println(“Sum=”+s);
}
}
Output:
Enter the number
5
Sum=15
2. The continue Statement
❖ The continue statement is used to continue the loop.
❖ When a continue statement is encountered the control directly jumps to the beginning of the
loop for the next iteration instead of executing the statements of the current iteration.
❖ The continue statement is used when we do not want to execute the remaining statements in the
loop, but we do not want to exit the loop itself.
Syntax:
continue; // The unlabeled form
continue label; // The labeled form
The label name is optional, and is usually only used when we wish to return to the outermost
loop in a series of nested loops.
Example 1:
//Java program to print the odd numbers between 1 to 10
//ContinueExample.java
class ContinueExample
{
public static void main(String args[])
{
System.out.println("Odd Numbers");
for (int i = 1; i <= 10; ++i)
{
if (i % 2 == 0)
continue;
// Rest of loop body skipped when i is even
System.out.println(i);
}
}
}
Output:
Odd Numbers
1
53
3
5
7
9

Example 2:
//Using continue with a label
//ContinueLabel.java
class ContinueLabel
{
public static void main(String args[])
{
outer: for (int i=0;i<5;i++)
{
for (int j=0;j<5;j++)
{
if (j>i)
{
System.out.println();
continue outer;
}
System.out.print(“ “+(i*j));
}
}
System.out.println();
}
}
Output:
0
01
02 4
03 6 9
0 4 8 12 16
Differences Between break and continue Statements

break Statement continue Statement


1. It is used to jump out of the loop. 1. It is used to break a single iteration.
2. The loop gets terminated or halted 2. The loop gets halted only for a single iteration
permanently when the break statement when the continue Java statement condition
condition matches. matches.
3. It is very commonly used with the “switch 3. It is not compatible with the “switch
statements”. statements”.

3. The return statement


❖ The return statement can be used to return a value from a method.
❖ The return statement causes the program control to transfer back to the caller of a method.
❖ The general form of return statement is
return;

54
return expression;
Example:
//Java Program to demonstrate continue statement
import java.io.*;
public class Test
{
int square(int s)
{
return s * s; // Return a square value.
}
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
Test t = new Test();
int n;
System.out.println(“Enter the value of n”);
n = Integer.parseInt(br.readLine());
int sq = t.square(n);
// Displaying the result.
System.out.println("Square of “ + n +”= " +sq);
}
}
Output:
Enter the value of n
10
Square of 10 = 100
Nested Loops
❖ Nested loop means a loop statement inside another loop statement.
❖ When we "nest" two loops, the outer loop takes control of the number of complete repetitions
of the inner loop.
1. Nested for loop
❖ Placing one for loop within the body of another for is called nested for loop.
Syntax:
for ( initialization; condition; increment/decrement )
{
for ( initialization; condition; increment/decrement )
{
// Statement of inner loop
}
// Statement of outer loop
}
Example:
//Demonstrate Nested for loop
55
//NestedForLoop.java
public class NestedForLoop
{
public static void main(String[] args)
{
for(int i=1;i<=5;i++)
{
for(int j=1;j<=i;j++)
{
System.out.print(i);
}
System.out.println();
}
}
}
Output:
1
22
333
4444
55555
2. Nested while loop
❖ A nested while loop is a while statement inside another while statement
Syntax:
while(condition)
{
while(condition)
{
// Statement of inner loop
}
// Statement of outer loop
}
Example:
//Java program to demonstrate nested while loop
class NestedWhileExample
{
public static void main(String args[])
{
int outer = 1;
while(outer < 3)
{
int inner = 5;
while(inner < 8)
{
System.out.println(outer + " " + inner);
56
inner++;
}
outer++;
}
}
}

Output:
15

16

17

25

26

27

3. Nested do-while loop


❖ A do-while within another do-while loop is called nested do-while loop.
Syntax:
do
{
do
{
// Statement of inside loop
}
while(condition);
// Statement of outer loop
}
while(condition);
Example:
//Java program to implement nested do-while loop
import java.io.*;
class NestedDoWhileExample
{
public static void main(String args[])
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int n, i, j;
System.out.println(“Enter the number of rows”);
n=Integer.parseInt(br.readLine());
System.out.println("Triangle number pattern\n");
i=1;
do
{
j=1;
do
{
System.out.println(j + “ “);
j++;
57
}
while(j<=i);
System.out.println("\n");
i++;
}
while(i<=n);
}
}
Output:
Enter the number of rows
5
Triangle number pattern
1
12
123
1234
12345
Exercises:
1. What are Control Statements?
2. List our any two types of Java decision making statements with an example.
3. Explain the ‘if’ control statement with an example.
4. Explain briefly about nested if else statement.
5. Explain switch case statement with suitable example.
6. Differentiate between if..else and switch statements.
7. Explain the various looping structure in Java with example.
8. What are nested loops?
9. Discuss about the iteration statements in Java.
10. Define break statement.
11. Define continue statement.
12. Distinguish between break and continue statements.
13. List out the uses of return statement.

**************************

58
************************************************************
Chapter 6 Arrays
************************************************************
6.1 Definition
❖ An Array is a group of contiguous or related data items that share a common name.
❖ Arrays are used to store multiple values in a single variable.
❖ The individual items in an array are called elements.
❖ Array in Java is index based, first element of the array is stored at 0 index.
Advantages of Arrays in Java
• Java arrays enable us to access any element randomly with the help of indexes.
• It is easy to store and manipulate large data sets.
Disadvantages of Arrays in Java
• The size of the array cannot be increased or decreased once it is declared—arrays have a fixed
size.
• Java cannot store heterogeneous data. It can only store a single type of primitives.
6.2 Types of Arrays
❖ There are two types of arrays.
1. One-Dimensional Arrays
2. Multidimensional Arrays
1. One-Dimensional Arrays
❖ A list of items can be given one variable name using only one subscript and such a variable
is called a single-subscripted variable or a one-dimensional array.
❖ For example, if we want to represent a set of five numbers, say (35, 40, 20, 57, 19), by an array
variable number, then we may create the variable number as follows:
int number[]=new int[3];
❖ The values to the array elements can be assigned as follows:
number[0]=35;
number[1]=40;
number[2]=20;
❖ These elements may be used in programs just like any other Java variable.
❖ The subscript of an array can be integer constants, integer variables like i, or expressions that
yield integers.
Creating an Array
❖ Creation of an array involves three steps:
1. Declare the array.
2. Create memory locations.

59
3. Put values into the memory locations.
Declaration of Arrays
❖ One-Dimensional Arrays in Java can be declared as follows:
DataType[]ArrayName;
DataType ArrayName[];
DataType []ArrayName;
Here,
• DataType can be a primitive data type (int, char, Double, byte etc.) or Non-primitive

data (Objects).
• ArrayName is the name of an array
• [ ] is called subscript.
Examples:
int number[];
int[] number;
int []number;
float average[];
float[] average;
float []average;
Creation of Arrays
❖ Java allows us to create arrays using the new operator only, as shown below:
ArrayName = new DataType[Size];
where:
ArrayName is the name of the array to be created.
Size Specifies the size of the array. The size should be an integer value or a variable that contains
an integer value.
Examples:
number=new int[5];
average=new float[10];
These lines create necessary memory locations and designate them as int and float respectively.
Now, the variable number refers to an array of 5 integers and average refers to an array of 10
floating point values.
❖ It is also possible to combine the two steps – declaration and creation into one as shown below:
int number[]=new int[5];
Initialization of Arrays
❖ To initialize the Array we have to put the values at each index of array.
❖ This is done using the array subscripts as shown below:
arrayname[subscript]=value;

60
Example:

number[0]=35;
number[1]=40;
number[2]=20;
number[3]=57;
number[4]=19;

❖ Java creates arrays starting with a subscript of 0 and ends with a value one less than the size
specified.
❖ We can also initialize arrays automatically in the same way as ordinary variables when they are
declared, as shown below:
datatype arrayName[] = {value1, value2, …valueN}
• If we choose datatype of an array is int then values should be int type. It means a type of
value is totally dependent on datatype of an array.
• Value1 will be store at 0 indexes, value2 in 1 index and so on.
• The size of the array depends upon how many values we are providing at the time of
initialization.\
Example:
int number[]={35,40,20,57,19};
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.
Example:
for (int i=0;i<10;i++)
{
sum=sum+a[i];
}
Array Length
❖ The length property is used to find the length of the array.
Example:
int size=a.length;
Example:

// Java program to sort the array elements in ascending order


// arr_sort.java
import java.io.*;
class arr_sort
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
61
int n,i,j,t;
int a[]=new int[100];
System.out.println("How many numbers?");
n=Integer.parseInt(br.readLine());
System.out.println("Enter "+n+" numbers");
for(i=0;i<n;i++)
{
a[i]=Integer.parseInt(br.readLine());
}
//Sorting begins
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
{
if (a[i]>a[j])
{
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
System.out.println("The array in ascending order is");
for(i=0;i<n;i++)
{
System.out.println(a[i]);
}
}
}
Output:
How many numbers?
5
Enter 5 numbers
34
20
15
40
10
The array in ascending order is
10
15
20
34
40

2. Multidimensional Arrays
❖ Multidimensional Arrays are actually arrays of arrays.
❖ Each element of a multidimensional array is an array itself.
❖ Data in multidimensional arrays are stored in tabular form.
❖ The representation of the elements is in rows and columns. Thus, we can get a total number of
elements in a Multidimensional array by multiplying row size with column size.

62
❖ The simplest of the multidimensional array is a two-dimensional array. A simple definition of
2D arrays is: A 2D array is an array of one-dimensional arrays.
❖ In Java, a two-dimensional array is stored in the form of rows and columns and is represented
in the form of a matrix.
❖ The general declaration of a two-dimensional array is,
DataType [][] ArrayName;
Here,
DataType = Data Type of elements that will be stored in an array.
ArrayName = Name of the two-dimensional array.
❖ We can create a 2D array using new as follows:
DataType [] [] ArrayName = new DataType[Row_Size][Column_Size];
Here,

Row_Size = number of rows an array will contain.


Column_Size = number of columns array will contain.
So if we have an array of 3×3, this means it will have 3 rows and 3 columns.
Example:
int[ ][ ] a = new int[3][3];
Here, we have created a 2-dimensional array named a. It is a 2-dimensional array, that can hold
a maximum of 9 elements.

Figure 6.1: Two-Dimensional Array

Initializing a 2D Array
❖ There are various ways of initializing the 2d array with values. The first method is the
traditional method of assigning values to each element.

❖ The general syntax for initialization is:

ArrayName[Row_Index][Column_Index] = Value;
Example:
int[][] MyArray = new int[2][2];
MyArray[0][0] = 1;
MyArray[0][1] = MyArray[1][0] = 0;
MyArray[1][1] = 1;

63
The above statements initialize all the elements of the given 2d array.
Example:
//Java Program to add two matrices
import java.util.*;
public class Add_Matrix
{
public static void main(String args[]) throws IOException
{
int m, n;
Scanner sc = new Scanner(System.in);
System.out.print("Enter the number of rows:");
m = sc.nextInt();
System.out.print("Enter the number of columns:");
n = sc.nextInt();
int a[][] = new int[m][n];
int b[][] = new int[m][n];
int c[][] = new int[m][n];
System.out.println("Enter the elements of first matrix:");
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
a[i][j] = sc.nextInt();
}
}
System.out.println("Enter the elements of second matrix:");
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
b[i][j] = sc.nextInt();
}
}
System.out.println("First Matrix:");
for (int i = 0; i < m; i++)
{
for (int j = 0; j <n; j++)
{
System.out.print(a[i][j]+" ");
}
System.out.println("");
}
System.out.println("Second Matrix:");
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
64
{
System.out.print(b[i][j]+" ");
}
System.out.println("");
}
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
c[i][j] = a[i][j] + b[i][j];
}
}
System.out.println("Matrix after addition:");
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
System.out.print(c[i][j]+" ");
}
System.out.println("");
}
}
}
Output:
Enter the number of rows: 2
Enter the number of columns: 3
Enter the elements of first matrix:
1
2
3
4
5
6
Enter the elements of second matrix:
7
8
9
4
3
2
First Matrix:
123
456

Second Matrix:
789
65
432
Matrix after addition:
8 10 12
8 8 8
Exercises:

1. Define Array.
2. How to create an Array?
3. Write the syntax for declaring one dimensional array.
4. How will you initialize the array elements?
5. Discuss in detail about Multidimensional Array.
6. Write a Java program to implement Two Dimensional Arrays.
**************************

66
UNIT- II
*******************************************************************************
7. Classes, Objects and Methods
*******************************************************************************
7.1 Introduction
❖ The class is the logical construct upon which the entire Java language is built because it defines
the shape and nature of the object. The class forms the basis for object-oriented programming
in Java. Any concept we wish to implement in a Java program must be encapsulated in a class.
❖ Classes provide a convenient method for packing together a group of logically related data
items and functions that work on them. In Java, the data items are called fields and the
functions are called methods. Classes create objects and objects use methods to communicate
between them.
❖ The most important thing to know about a class is that it defines a new data type. Once defined,
this new type can be used to create objects of that type. Thus, a class is a template for an object,
and an object is an instance of a class.
7.2 Defining a Class
❖ A class is a user-defined data type which has data members and member functions.
❖ A class is a template or blueprint from which objects are created.
❖ A class is declared by using the class keyword.
❖ The general form of a class definition is:
class classname
{
type variable1;
type variable2;
............
type variableN;
type methodname1(parameter-list)
{
// body of method
}
type methodname2(parameter-list)
{
// body of method
}
….
type methodnameN(parameter-list)
{
// body of method
}
}
❖ The data, or variables, defined within a class are called instance variables. The code is
contained within methods. Collectively, the methods and variables defined within a class are
called members of the class.
67
❖ Variables defined within a class are called instance variables because each instance of the class
(i.e. each object of the class) contains its own copy of these variables. Thus, the data for one
object is separate and unique from the data for another.
Example:

class Rectangle
{
int length;
int width;
void getData(int x, int y)
{
length=x;
width=y;
}
}
The class Rectangle contains two integer type instance variables. These variables are only declared
and therefore no storage space has been created in the memory. Instance variables are also known
as member variables.
The method has a return type of void because it does not return any value. We pass two integer
values to the method, which are then assigned to the instance variables length and width. The
getData() method is basically added to provide values to the instance variables.
7.3 Creating Objects
❖ An Object is an instance of a Class. When a class is defined, no memory is allocated but
when it is instantiated (i.e. an object is created) memory is allocated.
❖ Objects in Java are created using the new operator. The new operator is used to allocate
memory at runtime.
❖ It has this general form:
classname class-var=new classname();
Here, class-var is a variable of the class type being created. The classname is the name of the
class that is being instantiated. The class name followed by parentheses specifies the
constructor for the class. A constructor defines what occurs when an object of a class is created.
Example:
Rectangle rect1=new rectangle();
7.4 Distinction between a class and an object
❖ A class creates a new data type that can be used to create objects. That is, a class creates a
logical framework that defines the relationship between its members.
❖ When we declare an object of a class, we are creating an instance of that class.
❖ Thus, a class is a logical construct. An object has physical reality. That is, an object occupies
space in memory.
68
7.5 Accessing Class Members
❖ The instance variables and methods are accessed using the dot (.) operator.
❖ The syntax for accessing a class member is:
objectname.variablename
objectname.methodname(parameter-list);
Here objectnme is the name of the object, variablename is the name of the instance variable
inside the object we wish to access, methodname is the method that we wish to call, and
parameter-list is a comma separated list of “actual values” (or expressions) that must match in
type and number with the parameter list of the methodname declared in the class.
Example:
Rectangle rect1=new Rectangle();
rect1.length=15;
rect1.width=10;
We can call the getData() method on any Rectangle object to set the values of both length and
width.
Example:
Rectangle rect1=new Rectangle(); // Creating an object
rect1.getData(15,10); // Calling the method using the object
This code creates rect1 object and then passes the values 15 and 10 for the x and y parameters
of the method getData(). This method then assigns these values to length and width variables
respectively.
7.6 Assigning Object Reference Variables
❖ Object reference variables act differently than we might expect when an assignment takes place.
Example:
Rectangle r1=new Rectangle();
Rectangle r2=r1;
We might think that r2 is being assigned a reference to a copy of the object referred to by r1.
After this fragment executes, r1 and r2 will both refer to the same object. The assignment of r1
to r2 did not allocate any memory or copy any part of the original object. It simply makes r2
refer to the same object as does r1. Thus, any changes made to the object through r2 will affect
the object r1 is referring, since they are the same object.
7.7 Methods
❖ Methods are the functions that operate on instances of classes in which they are defined.
❖ Objects can communicate with each other using methods and can call methods in other classes.
❖ Classes usually consist of two things: instance variables and methods.
❖ Methods are declared inside the body of the class but immediately after the declaration of
69
instance variables.
❖ The general form of method declaration is
type methodname(parameter-list)
{
// Body of method
}
Here, type specifies the type of data returned by the method. This can be any valid type,
including class types that we create. If the method does not return a value, its return type must
be void.
The methodname can be any valid identifier that specifies the name of the method.
The parameter-list is a sequence of type and identifier pairs separated by commas. Parameters
are essentially variables that receive the value of the arguments passed to the method when it is
called. If the method has no parameters, then the parameter list will be empty.
The body actually describes the operations to be performed on the data.
❖ A method may be instructed to return a value after its execution is over. The following form of
the return statement is used.
return value;
Here, value is the value returned.
7.8 Calling Methods
❖ Calling a method is similar to calling or referring to an instance variable. The methods are
accessed using the dot notation.
Example:
// Java Application using classes and objects
// RectArea.java
import java.io.*;
class Rectangle
{
int length, width; // Declaration of variables
void getData(int x,int y) // Definition of method
{
length=x;
width=y;
}

int rectArea() // Definition of another method


{
int area=length*width;
return(area);
}
}
70
class RectArea // Class with main method
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int l,b,area1;
Rectangle rect1=new Rectangle(); // Creating an object
System.out.println("Enter the length");
l=Integer.parseInt(br.readLine());
System.out.println("Enter the breadth");
b=Integer.parseInt(br.readLine());
rect1.getData(l,b);
area1=rect1.rectArea();
System.out.println("Area of the rectangle="+area1);
}
}
Output:
Enter the length
10
Enter the breadth
15
Area of the rectangle=150
7.9 Constructors
❖ A Constructor is a special member function whose task is to initialize the objects of its class.

❖ Constructors have the same name as the class name.


❖ Constructors are automatically called when an object is created.
❖ It is called constructor because it constructs the values of data members of the class.
❖ Constructors do not have a return type; not even void.
❖ A constructor can be overloaded.
Types of Constructors
❖ There are two types of constructors. They are:
1. Default Constructor (Constructor with no argument)
2. Parameterized Constructor.

1. Default Constructor
❖ A constructor that has no parameter is known as the default constructor.
❖ The default constructor automatically initializes all instance variables to zero.
71
❖ The general form is
constructorname() // Constructor with no argument
{
// Give initial values to data members
}
Where, constructorname is the name of the class.
Example:
// Java Application using default constructor
// RectangleArea.java
class Rectangle
{
int length, width; // Declaration of variables
Rectangle() // Default Constructor
{
length=10;
width=15;
}
int rectArea()
{
return(length*width);
}
}
class RectangleArea // Class with main method
{
public static void main(String args[])
{
Rectangle rect1=new Rectangle(); // Calling constructor
int area1=rect1.rectArea();
System.out.println("Area of the rectangle="+area1);
}
}
Output:
Area of the rectangle=150
2. Parameterized Constructors
❖ A constructor that has parameters is known as parameterized constructor
❖ The parameterized constructor is used to provide different values to distinct objects.
❖ The general format of the parameterized constructor is as follows:
constructorname(datatype arg1, datatype arg2,…datatype argN)
{
// Give initial values to data members
}
where, constructorname is the name of the class.
datatype arg1, datatype arg2,… are the list of parameters
Example:

72
// Java Application using Parameterized Constructors
// RectangleArea.java
import java.io.*;
class Rectangle
{
int length, width; // Declaration of variables
Rectangle(int x, int y) // Defining parameterized constructor
{
length=x;
width=y;
}
int rectArea()
{
return(length*width);
}
}
class RectangleArea // Class with main method
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int l, b;
System.out.println("Enter the length");
l=Integer.parseInt(br.readLine());
System.out.println("Enter the breadth");
b=Integer.parseInt(br.readLine());
Rectangle rect1=new Rectangle(l,b); // Calling constructor
int area1=rect1.rectArea();
System.out.println("Area of the rectangle="+area1);
}
}
7.10 The this keyword
❖ The this keyword is used to refer to the current object.
❖ It can be used inside the method or constructor of a class.
❖ The most common use of this keyword is to eliminate the confusion between class attributes
and the parameters with the same name.
❖ Methods declared with the keyword static (class methods) cannot use this.
Example:
// Java program that illustrates the usage of the keyword this
// ThisDemo.java
import java.io.*;
class Sample
{
int x,y;
void GetData(int x, int y)
{
this.x=x;
this.y=y;
}

73
void Display()
{
System.out.println("x="+x);
System.out.println("y="+y);
}
}
class ThisDemo
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int a,b;
System.out.println("Enter the values of a & b");
a=Integer.parseInt(br.readLine());
b=Integer.parseInt(br.readLine());
Sample obj=new Sample();
obj.GetData(a,b);
obj.Display();
}
}
Output:
Enter the values of a & b
30
40
x=30
y=40

7.11 Method Overloading

❖ Method Overloading allows a class to define multiple methods with the same name, but
different parameters.

Benefits of using Method Overloading


❖ Method overloading increases the readability of the program.
❖ This provides flexibility to programmers so that they can call the same method for different
types of data.
❖ This reduces the execution time because the binding is done in compilation time itself.
❖ Method overloading minimizes the complexity of the code.
❖ With this, we can use the code again, which saves memory.

Example:

// Java program to demonstrate Method Overloading


import java.io.*;
public class Sum_Nos
{
public int sum(int x, int y)

74
{
return (x + y);
}
public int sum(int x, int y, int z)
{
return (x + y + z);
}
public double sum(double x, double y)
{
return (x + y);
}
// Main Program
public static void main(String args[])
{
Sum_Nos S = new Sum_Nos();
System.out.println(S.sum(10, 20));
System.out.println(S.sum(10, 20, 30));
System.out.println(S.sum(10.5, 20.5));
}
}

Output:

30
60
31.0

7.12 Overloading Constructors


❖ The technique of having two or more constructors in a class is known as constructor
overloading.
❖ A class can have multiple constructors that differ in the number and/or type of their parameters.
Example:
// Java program to implement Constructor Overloading
// Student.java
import java.io.*;
class Student
{
int id;
String name;
int age;
Student(int i, String n)
{
id = i;
name = n;
}
Student(int i, String n,int a)
{

75
id = i;
name = n;
age=a;
}
void display()
{
System.out.println(id+" "+name+" "+age);
}
public static void main(String args[])
{
Student s1 = new Student(111,"Sun");
Student s2 = new Student(222,"Chandra",16);
s1.display();
s2.display();
}
}
Output:
111 Sun 0
222 Chandra 16
7.13 Objects as Parameters

❖ Objects can also be passed to methods.


❖ Objects are implicitly passed by use of call-by-reference.
Example:
// Passing Object as Parameter in Function
// Add_Nos.java
import java.io.*;
class Add
{
int a;
int b;
Add(int x, int y) // Parametrized Constructor
{
a=x;
b=y;
}
void sum(Add A1) // Object 'A1' passed as parameter in function 'sum'
{
int c=A.a+A.b;
System.out.println("Sum of a and b: "+c);
}
}
public class Add_Nos
{
public static void main(String args[]) throws IOException
{
76
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int m, n
System.out.println(“Enter the first number”);
m=Integer.parseInt(br.readLine());
System.out.println(“Enter the second number”);
n=Integer.parseInt(br.readLine());
Add A=new Add(m, n);
A.sum(A);
}
}
Output:
Enter the first number
10
Enter the second number
20
Sum of a and b: 30

7.14 Passing arguments to methods


❖ There are two ways of passing arguments to methods. They are:
1. Call by Value
2. Call by Reference
1. Call by Value
❖ In Call by Value approach, the values of the actual parameters are copied into the formal
parameter list of a method.
❖ The actual and the formal parameters are stored in different memory locations.
❖ Therefore, any changes made inside formal parameters of the method are not reflected in the
actual parameters of the caller.
❖ It is also known as Pass by Value.
2. Call by Reference
❖ In Call By Reference approach, the address of an argument is copied into the formal parameter
of the method.
❖ The actual and the formal parameters are stored in same memory locations.
❖ It means that changes made in the parameter alter the passing argument.
❖ It is also known as Pass by Reference.
Example 1:
// Java program that demonstrates Call By Value
// CallByValue.java
import java.io.*;
class Test
{
77
void meth(int i, int j)
{
i*=2;
j/=2;
}
}
class CallByValue
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int a,b;
Test ob=new Test();
System.out.println("Enter the values of a & b");
a=Integer.parseInt(br.readLine());
b=Integer.parseInt(br.readLine());
System.out.println(" a and b before call : "+a+" "+b);
ob.meth(a,b);
System.out.println(" a and b after call : "+a+" "+b);
}
}
Output:
Enter the values of a & b
15
20
a and b before call : 15 20
a and b after call : 15 20
Example 2:
// Objects are passed by reference
// CallByRef.java
import java.io.*;
class Test
{
int a,b;
Test(int i, int j)
{
a=i;
b=j;
}
void meth(Test o)
{
o.a*=2;
o.b/= 2;
}
}
class CallByRef
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int a,b;
78
System.out.println("Enter the values of a & b");
a=Integer.parseInt(br.readLine());
b=Integer.parseInt(br.readLine());
Test ob=new Test(a,b);
System.out.println(" a and b before call : "+ob.a+" "+ob.b);
ob.meth(ob);
System.out.println(" a and b after call : "+ob.a+" "+ob.b);
}
}
Output:
Enter the values of a & b
15
20
a and b before call : 15 20
a and b after call : 30 10
7.15 Returning Objects
❖ A method can return any type of data, including class types that we create.
Example:
// Returning an object
// RetOb.java
import java.io.*;
class Test
{
int a;
Test(int i)
{
a=i;
}

Test incrByTen()
{
Test temp=new Test(a+10);
return temp;
}
}
class RetOb
{
public static void main(String args[])
{
Test ob1=new Test(2);
Test ob2;
ob2= ob1.incrByTen();
System.out.println(" ob1.a : "+ob1.a);
System.out.println(" ob2.a : "+ob2.a);
ob2= ob2.incrByTen();
System.out.println(" ob2.a after second increase : "+ob2.a);
}
}
Output:
79
ob1.a : 2
ob2.a : 12
ob2.a after second increase : 22
7.16 Recursion
❖ Recursion is a process by which a function calls itself.
❖ A method in Java that calls itself is called recursive method.
❖ This technique provides a way to break complicated problems down into simple problems which
are easier to solve.
Example:

// Java program to find the factorial of a number using recursion


// Recursion.java
import java.io.*;
class Factorial
{
int fact(int n)
{
if (n==1)
return 1;
else
return(n*fact(n-1));
}
}
class Recursion
{
public static void main(String args[]) throws IOException
{
Factorial f=new Factorial();
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int m;
System.out.println("Enter the value of m");
m=Integer.parseInt(br.readLine());
System.out.println("Factorial of "+m +" is "+f.fact(m));
}
}
Output:
Enter the value of m
5
Factorial of 5 is 120
7.17 Inheritance
Definition
❖ The mechanism of deriving a new class from an old one is called inheritance. The old class
is known as the base class or super class or parent class and the new one is called the subclass
80
or derived class or child class.
Defining a Subclass
❖ A subclass is defined as follows:
class subclass-name extends superclass-name
{
Variables declaration;
Methods declaration;
}
❖ The keyword extends signifies that the properties of the superclass-name are extended to the
subclass-name.
❖ The subclass will now contain its own variables and methods as well those of the superclass.
❖ This kind of situation occurs when we want to add some more properties to an existing class
without actually it.
Types of Inheritance
❖ There are various types of Inheritance in Java.
1. Single Inheritance (only one super class)
2. Multiple Inheritance (several super classes)
3. Hierarchical Inheritance (one super class, many sub classes)
4. Multilevel Inheritance (Derived from a derived class)
❖ These forms of inheritance are shown in Figure 7.1.
❖ Java does not implement multiple inheritance. However, this concept is implemented using a
secondary inheritance path in the form of interfaces.

Figure 7.1: Forms of Inheritance


1. Single Inheritance
❖ Single Inheritance is defined as the inheritance in which a derived class is inherited from
only one base class.
❖ It allows a derived class to inherit the properties and behavior of a base class, thus enabling
code reusability as well as adding new features to the existing code.

81
Syntax:
class Sub-classname extends Super-classname
{
// Variables and Methods
}
❖ The extends keyword indicates that we are creating a new class that derives from an existing
class.
❖ A class which is inherited is called a parent or superclass, and the new class is called child or
subclass.
Example:
// Java Application using Single Inheritance
//SingleInheritance.java
import java.io.*;
class Room
{
int length;
int breadth;
int area()
{
return (length*breadth);
}
}
class BedRoom extends Room
{
int height;
BedRoom(int x, int y, int z)
{
length= x;
breadth=y;
height=z;
}
int volume()
{
return (length*breadth*height);
}
}
class SingleInheritance
{

82
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int l,b,h;
System.out.println("Enter the length");
l=Integer.parseInt(br.readLine());
System.out.println("Enter the breadth");
b=Integer.parseInt(br.readLine());
System.out.println("Enter the height");
h=Integer.parseInt(br.readLine());
BedRoom room1=new BedRoom(l,b,h);
int area1= room1.area();
int volume1=room1.volume();
System.out.println("Area = "+area1);
System.out.println("Volume = "+volume1);
}
}
Output:
Enter the length
10
Enter the breadth
20
Enter the height
30
Area = 200
Volume = 600
The super keyword
❖ The super keyword in Java is used in subclasses to access superclass members.
❖ The most common use of the super keyword is to eliminate the confusion between superclasses
and subclasses that have methods with the same name.
❖ Super has two general forms. The first calls the superclass constructor. The second is used to
access a member of the superclass that has been hidden by a member of a subclass.
i) Using super to Call Superclass Constructors
❖ A subclass can call a constructor method defined by its superclass by use of the following form
of super:
super(parameter-list);
Here, parameter-list specifies any parameter needed by the constructor in the superclass.
super() must always be the first statement executed inside a subclass constructor.
ii) A Second Use for super
❖ The second form of super acts somewhat like this, except that it always refers to the superclass
of the sublass in which it is used.
❖ This usage has the following general form:
83
super.member
Here, member can be either a method or an instance variable.
❖ This second form of super is most applicable to situations in which member names of a subclass
hide members by the same name in the superclass.
Example:
// Java program using super to overcome name hiding.
//SuperDemo.java
import java.io.*;
class A
{
int i;
}
// Create a subclass by extending class A.
class B extends A
{
int i; // this i hides the i in A
B(int a, int b)
{
super.i=a; // i in A
i=b; // i in B
}
void show()
{
System.out.println("i in superclass: "+super.i);
System.out.println("i in subclass : "+i);
}
}

class SuperDemo
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int x,y;
System.out.println("Enter the values of x & y");
x=Integer.parseInt(br.readLine());
y=Integer.parseInt(br.readLine());
B subOb=new B(x,y);
subOb.show();
}
}
Output:
Enter the values of x & y
4
84
6
i in superclass: 4
i in subclass : 6
2. Multiple Inheritance
❖ The mechanism of inheriting the features of more than one base class into a single class is known
as multiple inheritance.
❖ Java does not support multiple inheritance but the multiple inheritance can be achieved by
using the interface.
3. Multilevel Inheritance
❖ The mechanism of deriving a class from another derived class is called multilevel
inheritance.
❖ This concept allows us to build a chain of classes as shown in Figure 7.2

Figure 7.2: Multilevel Inheritance


Syntax:
class A
{
// Variables and Methods
}
class B extends A
{
// Variables and Methods
}
class C extends B
{
// Variables and Methods
}
The class A serves as a base class for the derived class B, which in turn serves as a base class for the
derived class C. The class B is known as intermediate base class since it provides a link for the
inheritance between A and C.
Example:
// Java program to implement multilevel inheritance
import java.io.*;
class Car
{
public Car()
{
System.out.println("Class Car");
}
85
public void vehicleType()
{
System.out.println("Vehicle Type: Car");
}
}
class Maruti extends Car
{
public Maruti()
{
System.out.println("Class Maruti");
}
public void brand()
{
System.out.println("Brand: Maruti");
}
public void speed()
{
System.out.println("Max: 90Kmph");
}
}
public class Maruti800 extends Maruti
{
public Maruti800()
{
System.out.println("Maruti Model: 800");
}
public void speed()
{
System.out.println("Max: 80Kmph");
}
public static void main(String args[])
{
Maruti800 obj=new Maruti800();
obj.vehicleType();
obj.brand();
obj.speed();
}
}
Output:
Class Car
Class Maruti
Maruti Model: 800
Vehicle Type: Car
Brand: Maruti
Max: 80Kmph

4. Hierarchical Inheritance
❖ Hierarchical Inheritance is a method of inheritance where one or more derived classes are
derived from a common base class. i.e there is one super class and multiple subclasses.
❖ This form of inheritance is commonly used in Java program design.
86
Syntax:
class Subclassname1 extends Superclassname
{
// Variables and Methods
}
class Subclassname2 extends Superclassname
{
// Variables and Methods
}
Example:
// Java program to implement Hierarchical Inheritance
//HierInheritanceDemo.java
class Employee
{
float salary = 40000;
void dispSalary()
{
System.out.println("The Employee salary is :" +salary);
}
}
class PermanentEmp extends Employee
{
double hike = 0.5;
void incrementSalary()
{
System.out.println("The Permanent Employee incremented salary is :" +(salary+(salary * hike)));
}
}
class TemporaryEmp extends Employee
{
double hike = 0.35;
void incrementSalary()
{
System.out.println("The Temporary Employee incremented salary is :" +(salary+(salary * hike)));
}
}
public class HierInheritanceDemo
{
public static void main(String args[])
{
PermanentEmp p = new PermanentEmp();
TemporaryEmp t = new TemporaryEmp();
p.dispSalary();
p.incrementSalary();
t.dispSalary();
t.incrementSalary();
}
}

87
Output:
The Employee salary is: 40000.0
The Permanent Employee incremented salary is : 60000.0
The Employee salary is: 40000.0
The Temporary Employee incremented salary is : 54000.0
7.18 Method Overriding
❖ Method Overriding is a feature that allows us to use the same method name in the child
class which is already present in the parent class.
❖ In other words, it is performed between two classes using inheritance relation.Method Overriding
is one of the way by which Java can achieve Run Time Polymorphism.
Rules for Method Overriding
1. Method name must be the same in both parent and child classes.
2. The method must have the same parameter as in the parent class.
3. There must be an IS-A relationship between classes (inheritance).
4. Private, final and static methods cannot be overridden.

Example:
// Java program to implement Method Overriding
// MethodOverriding.java
import java.io.*;
class Parent // Base Class
{
void show()
{
System.out.println("Parent's show method");
}
}
class Child extends Parent // Inherited Class
{
// This method overrides show() of Parent
void show()
{
System.out.println("Child's show method");
}
}
class MethodOverriding // Main class
{
public static void main(String args[])
{
Parent obj1 = new Parent();
obj1.show();
Parent obj2 = new Child();
obj2.show();
}
}
Output:
88
Parent's show method
Child's show method
7.19 Differences between Method Overloading and Method Overriding in Java
❖ There are many differences between method overloading and method overriding in java.
❖ A list of differences between method overloading and method overriding are given below:
Sl.
Method Overloading Method Overriding
No.
1) Method Overloading is used to increase Method Overriding is used to provide the
the readability of the program. specific implementation of the method that
is already provided by its super class.
2) Method Overloading is performed within Method Overriding occurs in two classes
class. that have IS-A (inheritance) relationship.
3) In case of method In case of method overriding, parameter
overloading, parameter must be must be same.
different.
4) Method Overloading is an example Method Overriding is an example for Run
for Compile Time Polymorphism. Time Polymorphism.
5) Return type can be same or different in Return type must be same in method
method overloading. But we must have overriding.
to change the parameter.

7.20 Final Variables and Methods


final Variables
❖ Variables that are declared with the final keyword are known as final variables.
❖ The value of a final variable cannot change after it has been initialized.
❖ Such variables are similar to constants in other programming languages.
❖ The general form is:
final type variablename=value;
Example 1:
final float PI=3.14159;
final int SIZE=100;
It is a common coding convention to choose all uppercase identifiers for final variables.
Variables declared as final do not occupy any memory on a per-instance basis. Thus, a final
variable is essentially a constant.
Example 2:
//Java Program to implement final variable
import java.io.*;
class Bike
{
final int SpeedLimit=90; //final variable
void run()
{
SpeedLimit=400;

89
}
public static void main(String args[])
{
Bike obj=new Bike();
obj.run();
}
}
Output:
Compile Time Error
final Methods
❖ The final keyword is used in a method declaration to indicate that the method cannot be
overridden by subclasses.
❖ Methods called from constructors should generally be declared final.
❖ A final method cannot be overriden or hidden by subclasses. This is used to prevent unexpected
behavior from a subclass altering a method that may be crucial to the function or consistency of
the class.
Example:
//Final Method Example
class Bike
{
final void run()
{
System.out.println("Running");
}
}
class Honda extends Bike
{
void run()
{
System.out.println("Running safely with 100kmph");
}
public static void main(String args[])
{
Honda honda= new Honda();
honda.run();
}
}
Output:
Compile Time Error
7.21 final classes
❖ A class that cannot be subclassed is called a final class.
❖ This is achieved in Java using the keyword final as follows:
final class A {………………}
final class B extends A {…………..}
90
❖ Any attempt to inherit these classes will cause an error and the compiler will not allow it.
❖ Declaring a class final prevents any unwanted extensions to the class
Example:

//Java Program to implement final classs


import java.io.*;
final class Bike
{
}
class Honda extends Bike
{
void run()
{
System.out.println("Running safely with 100kmph");
}
public static void main(String args[])
{
Honda honda= new Honda();
honda.run();
}
}
Output:
Compile Time Error
7.23 Garbage Collection
❖ Garbage Collection (GC) is a form of automatic memory management.
❖ Garbage Collection (GC) is the process of reclaiming the runtime unused memory
automatically. In other words, it is a way to destroy the unused objects.

Advantages of Garbage Collection


• It makes Java memory efficient because garbage collector removes the unreferenced objects
from heap memory.
• It is automatically done by the garbage collector (a part of JVM) so we don't need to make extra
efforts.
7.24 Finalizer Methods
finalize() method
❖ The finalize() method is called the finalizer.
❖ It is a protected method of java.lang.Object class.
❖ The finalize() method is invoked each time before the object is garbage collected.
❖ This method is used to perform some final operations or clean up operations on an object before
it is removed from the memory.
❖ We can override the finalize() method to keep those operations we want to perform before an
object is destroyed.
91
❖ The finalize() method has this general form:
protected void finalize()
{
// Finalization code here
}
Here, the keyword protected is a specifier that prevents access to finalize() by code defined
outside its class.

Example:

//Java program that implements the finalize() method


import java.util.*;
public class ObjectDemo extends GregorianCalendar
{
public static void main(String args[])
{
try
{
ObjectDemo cal = new ObjectDemo();
// Print current time
System.out.println("" + cal.getTime());
// finalize cal
System.out.println("Finalizing...");
cal.finalize();
System.out.println("Finalized.");
}
catch (Throwable ex)
{
ex.printStackTrace();
}
}
}

Output:
Finalizing…
Finalized.
7.24 Abstract Methods and Classes
Abstract Methods
❖ A method without body (no implementation) is known as abstract method.
❖ A method must always be declared in an abstract class, or in other words we can say that if a
class has an abstract method, it should be declared abstract as well.
❖ The general form is:
abstract type name(parameter-list);
Rules of Abstract Method
1. Abstract methods don’t have body, they just have method signature as shown above.

92
2. If a class has an abstract method it should be declared abstract, the vice versa is not true, which
means an abstract class doesn’t need to have an abstract method compulsory.
3. If a regular class extends an abstract class, then the class must have to implement all the abstract
methods of abstract parent class or it has to be declared abstract as well.
Example:
// Java program using abstract method in an abstract class
// Demo.java
import java.io.*;
abstract class Sum
{
public abstract int sumOfTwo(int n1, int n2);
public abstract int sumOfThree(int n1, int n2, int n3);
//Regular method
public void disp()
{
System.out.println("Method of class Sum");
}
}
//Regular class extends abstract class
class Demo extends Sum
{
public int sumOfTwo(int num1, int num2)
{
return num1+num2;
}
public int sumOfThree(int num1, int num2, int num3)
{
return num1+num2+num3;
}
public static void main(String args[])
{
Demo obj = new Demo();
System.out.println(obj.sumOfTwo(3, 7));
System.out.println(obj.sumOfThree(4, 3, 19));
obj.disp();
}
}
Output:
10
26
Method of class Sum
Abstract Class
❖ A class that is declared with an abstract keyword is known as abstract class.
❖ An abstract class cannot be instantiated, which means we are not allowed to create an object of
it. It can be used only as a super-class for those classes that extend the abstract class.
❖ The default functionality of the class still exists, with its fields, methods and constructors being
accessed in the same way as with the other classes.
93
❖ An abstract class may contain methods without any implementation, called abstract methods.
❖ A class that extends an abstract class must implement all its abstract methods (if any).
❖ The general form of an abstract class is:
abstract class Class_Name
{
………….
………….
abstract type name(parameter-list);
…………
}
Here,
abstract: It is a keyword that must be used at the time of declaration.
Class_Name: We can provide class names according to our functionality.
abstract method: Each abstract class has at least one abstract method.
Example:
// Java program to demonstrate abstract class
//AbstractDemo.java
import java.io.*;
abstract class Shape
{
abstract void draw();
}
class Rectangle extends Shape
{
void draw()
{
System.out.println("Drawing Rectangle");
}
}
class Circle extends Shape
{
void draw()
{
System.out.println("Drawing Circle");
}
}
class AbstractDemo
{
public static void main(String args[])
{
Circle c=new Circle();
c.draw();
}
}
94
Output:
Drawing Circle
7.25 Visibility Control (Access Control)
❖ Visibility Control is otherwise called access control or access specifiers or access modifiers.
❖ Access Control is used to restrict the access to certain variables and methods from outside
the class.
❖ Java provides a number of access modifiers to set access levels for classes, variables, methods,
and constructors. They are:
1. private
2. public
3. protected
❖ When no access specifier is used, then by default the member of a class is public within its own
package but cannot be accessed outside of its package.
private
❖ Methods, variables, and constructors that are declared private can only be accessed within
the declared class itself.
❖ Private access modifier is the most restrictive access level. Class and interfaces cannot be private.
❖ Using the private modifier is the main way that an object encapsulates itself and hides data from the
outside world.
Example:

private int rollno;


private String str;
private double NetSalary();
public
❖ A class, method, constructor, interface, etc. declared public can be accessed from any other
class.
❖ Therefore, fields, methods, blocks declared inside a public class can be accessed from any class
belonging to the Java Universe.

Example:

public int number;


public void sum(){…..}
public static void main(String args[])
{
// ...
}

95
The main() method of an application has to be public. Otherwise, it could not be called by a Java
interpreter (such as java) to run the class.
protected

❖ Variables, methods, and constructors, which are declared protected in a superclass can be
accessed only by the subclasses in other package or any class within the package of the
protected members' class.
❖ The protected access modifier cannot be applied to class and interfaces. Methods, fields can be
declared protected, however methods and fields in a interface cannot be declared protected.
❖ Protected access gives the subclass a chance to use the helper method or variable, while preventing
a nonrelated class from trying to use it.
Example:
protected int number;
protected int sum();
7.26 Static Members
❖ The members that are declared using the keyword static are called static members.
❖ Static members always remain the same, regardless of where and how they are used.
❖ Because static members are associated with the class, it is not necessary to create an instance of
that class to invoke them.
❖ Static members can be defined as follows:
static int count;
static int max(int x, int y);
❖ The most common example of a static member is main(). main() is declared as static because
it must be called before any objects exist.
❖ Instance variables declared as static are, essentially, global variables.
❖ We can call a static method from outside of the class as follows:
classname.staticmethodname(parameter);
❖ Methods declared as static have several restrictions:
▪ They can only call other static methods.
▪ They must access only static data.
▪ They cannot refer to this or super in any way.
Example:

// Java program to implement static members


// StaticDemo.java
import java.lang.*;
class StaticDemo
{
static int rollno=1001;
96
static String name="Vijay";
static void display()
{
System.out.println("RollNo :"+rollno);
System.out.println("Name : "+name);
}
public static void main(String args[])
{
display(); //Calling the static member function without any object.
}
}
Output:
RollNo : 1001
Name : Vijay
7.27 Nested and Inner Classes
❖ A class within another class is known as nested class.
❖ There are two types of nested classes: static and non-static. A static nested class is one which
has the static modifier applied. Because it is static, it must access the members of its enclosing
class through an object. That is, it cannot refer to members of its enclosing class directly.
Because of this restriction, static nested classes are seldom used.
❖ The most important type of nested class is the inner class. An inner class is a non-static nested
class. It has access to all of the variables and methods of its outer class and may refer to them
directly in the same way that other non-static members of the outer class do. Thus, an inner
class is fully within the scope of its enclosing class.

Example:
// Java program to demonstrate inner class
// InnerDemo.java
class Bank
{
private double bal, rate;
Bank(double b, double r)
{
bal = b;
rate = r;
}
void display()
{
Interest in=new Interest();
in.calculateInterest();
System.out.println("New Balance = "+bal);
}
private class Interest
97
{
void calculateInterest()
{
System.out.println("Balance = " +bal);
double interest=bal * rate/100;
System.out.println("Interest = "+interest);
bal+=interest;
}
}
}
class InnerDemo
{
public static void main(String args[])
{
Bank account=new Bank(20000,5);
account.display();
}
}
Output:
Balance = 20000.0
Interest = 1000.0
New Balance = 21000
7.28 Nesting of Methods
❖ A method can be called by using only its name by another method of the same class. This is
known as nesting of methods.

Example:
// Java program to illustrate nesting of method
// NestingTest.java
import java.io.*;
class Nesting
{
int m,n;
Nesting(int x, int y)
{
m=x;
n=y;
}
int largest()
{
if (m>=n)
return (m);
else
return(n);
}
98
void display()
{
int large = largest(); // Calling a method
System.out.println("Largest Value = "+large);
}
}
class NestingTest
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int a,b;
System.out.println("Enter the values of a & b");
a=Integer.parseInt(br.readLine());
b=Integer.parseInt(br.readLine());
Nesting nest=new Nesting(a,b);
nest.display();
}
}
Output:
Enter the values of a & b
30
40
Largest Value = 40

Exercises:
1. Define Class.
2. Define Instance Variable.
3. What is an Object? How to create Object for a class?
4. How do you access class members?
5. Define Methods.
6. What are Constructors?
7. Explain in Detail about Constructors with an example.
8. Define this keyword.
9. What is Method Overloading?
10. What is recursive function?
11. Discuss inheritance with an example.
12. Define extends keyword.
13. Define super keyword.
14. What is Method Overriding?
99
15. What are the differences between method overriding and overloading?
16. Define final keyword.
17. Explain briefly about Garbage Collection in Java.
18. What is finalize method?
19. Explain abstract method.
20. Discuss about visibility control in Java.
21. Explain static members.
22. Write a Java program to illustrate nested class.
**************************

100
******************************************************************************
Chapter 8 String Handling
******************************************************************************
8.1 Definition
❖ A string is a sequence of characters. Java implements strings as objects of type String.
❖ Java has methods to compare two strings, search for a substring, concatenate two strings, and
change the case of letters within a string. Also, String objects can be constructed a number of
ways, making it easy to obtain a string when needed.
❖ In Java, strings are class objects and implemented using two classes, namely, String and
StringBuffer. These classes are defined in the package java.lang.
8.2 String Class

❖ The String class represents character strings. A Java string is an instantiated object of the
String class. The Java platform provides the String class to create and manipulate strings.
❖ Strings are constant; their values cannot be changed after they are created. Java strings are
reliable and more predictable. A Java string is not a character array and is not NULL terminated.
❖ The class String includes methods for examining individual characters of the sequence, for
comparing strings, for searching strings, for extracting substrings, and for creating a copy of a
string with all characters translated to uppercase or to lowercase.
1. The String Constructors

❖ The String class supports several constructors.

String()
String(char chars[])
String(char chars[], int startIndex, int numChars)
String(String strObj)
String(byte asciiChars[])
String(byte asciiChars[], int startIndex, int numChars)
i) String()
❖ This is the default constructor. To create an empty string, we call the default constructor.
Example:
String S=new String();
will create an instance of String with no characters in it.
ii) String(char chars[])
❖ The String class provides a variety of constructors to create strings that have initial values. This
constructor is used to create a String initialized by an array of characters.
Example:

101
char chars[]={‘a’,’b’,’c’};

String S=new String(chars);

This constructor initializes S with the string “abc”.

iii) String(char chars[], int startIndex, int numChars)


❖ This constructor is used to specify a sub range of a character array as an initializer. Here,
startIndex specifies the index at which the sub range begins, and numChars specifies the
number of characters to use.
Example:

char chars[]={‘a’, ’b’, ’c’, ’d’, ‘e’, ‘f’};

String S=new String(chars,2,3);

This initializes S with the characters “cde”.

iv) String(String strObj)


❖ This constructor is used to construct a String object that contains the same character sequence
as another. Here, strObj is a String object.
Example:

String S1=new String(“Java”);

String S2=new String(S1);

Here, S1 and S2 contain the same string.

v) String(byte asciiChars[])
vi) String(byte asciiChars[], int startIndex, int numChars)
❖ The String class provides constructors that initialize a string when given a byte array. Here,
asciiChars specifies the array of bytes. The second form allows us to specify a sub range. In
each of these constructors, the byte-to-character conversion is done by using the default character
encoding of the platform.
Example:

byte ascii[] ={65, 66, 67, 68, 69, 70};


String S1=new String(ascii)
System.out.println(S1); // ABCDEF
String S2=new String(ascii,2,3);
System.out.println(S2); // CDE

2. String Methods

102
❖ The String class contains a number of methods that allow us to perform a string manipulation.
Some of the most commonly used string methods are as follows:
i) charAt()

❖ The charAt() method returns the character at the specified index in a string.
❖ The index of the first character is 0, the second character is 1, and so on.
❖ The general form is:
StringObject.charAt(int index)

Example:
//Java program to demonstrate charAt method
import java.io.*;
public class CharAtDemo
{
public static void main(String args[])
{
String Str = "Hello";
char result = Str.charAt(0);
System.out.println(result);
}
}
Output:
H
ii) compareTo()

❖ The compareTo() method is used to compare two stringslexicographically (in the dictionary
order).
❖ This method is returns negative if string1 is less than string2, positive if string1 is greater than
string2, and zero if string1 is equal to string2.
❖ The general form is:
StringObject.compareTo(string)
Example:
//Java program to compare strings
import java.io.*;
class CompareTo_Ex
{
public static void main(String args[])
{
String Str1 = "Learn Java";
String Str2 = "Learn Java";
String Str3 = "Learn Python";
int result;
// Comparing Str1 with Str2
103
result = Str1.compareTo(Str2);
System.out.println(result); // 0
// Comparing Str1 with Str3
result = Str1.compareTo(Str3);
System.out.println(result); // -1
// Comparing Str3 with Str1
result = Str3.compareTo(Str1);
System.out.println(result); // 1
}
}
Output:
0
-6
6
iii) concat()

❖ The concat() method concatenates multiple strings. This method appends the specified
string at the end of the given string and returns the combined string.
❖ The general form is:
StringObject.concat(string)
Example:
//Java program to demonstrate concat method
import java.io.*;
public class ConcatDemo
{
public static void main(String args[])
{
String FirstName = "Raja";
String LastName = "ram";
System.out.println(FirstName.concat(LastName));
}
}
Output:

Rajaram
iv) equals()

❖ The equals() method compares two strings, and returns true if the strings are equal, and false
if not.
❖ The general form is:
StringObject.equals(string)

Example:

104
//Java program to demonstrate equals method
import java.io.*;
public class EqualsDemo
{
public static void main(String args[])
{
String Str1 = "Java";
String Str2 = "Java";
StringStr3 = "Python";
System.out.println(Str1.equals(Str2));
System.out.println(Str1.equals(Str3));
}
}
Output:
true
false
v) equalsIgnoreCase()
❖ The equalsIgnoreCase() method compares two strings, ignoring lowercase and uppercase
differences.
❖ This method returns true if the strings are equal, and false if not.
❖ The general form is:
StringObject.equalsIgnoreCase(string)
Example:
//Java program to demonstrate equalsIgnoreCase method
import java.io.*;
public class EqualsIgnoreCaseDemo
{
public static void main(String args[])
{
String Str1 = "Java";
String Str2 = "JAVA";
StringStr3 = "Python";
System.out.println(Str1.equalsIgnoreCase(Str2));
System.out.println(Str1.equalsIgnoreCase(Str3));
}
}
Output:
true
false
vi) endsWith()

❖ The endsWith() method is used to check whether a given string ends with the specified string.
❖ The general form is:
StringObject.endsWith(String str)

105
Here, str is the String being tested. If the string matches, true is returned. Otherwise, false is
returned.

Example:

//Java program to demonstrate endsWith method


import java.io.*;
public class EndsWithExample
{
public static void main(String args[])
{
String Str="Welcome to Sindhi College";
System.out.println(Str.endsWith("College"));
System.out.println(Str.endsWith("Sindhi"));
}
}
Output:
true
false
vii) getChars()
❖ The getChars() method copies characters from the given string into the destination character
array.
❖ The general form is:
StringObject. getChars(int sourceStart, int sourceEnd, char target[], int targetStart)
Here, sourceStart specifies the index of the beginning of the substring. And sourceEnd
specifies an index that is one past the end of the desired substring. Thus, the substring contains
the characters from sourceStart through sourceEnd-1. The array that will receive the characters
is specified by target. The index within target at which the substring will be copied is passed
to targetStart.
Example:

//Java program to demonstrate getChars method


import java.io.*;
class Getchar_Demo
{
public static void main(String args[])
{
String str = "Welcome to Sindhi College";
char[] destArray = new char[14];
str.getChars(11, 25, destArray, 0);
System.out.println(destArray);
}
}

106
Output:
Sindhi College

viii) getBytes()

❖ The getBytes() method returns the byte array of the string. In other words, it returns sequence
of bytes.
❖ The general form is:
StringObject.getBytes()
Example:
//Java program to demonstrate getBytes method
import java.io.*;
public class GetBytesEx
{
public static void main(String args[])
{
String Str="ABCD";
byte[] arr=Str.getBytes();
for(int i=0;i<arr.length;i++)
{
System.out.println(arr[i]);
}
}
}
Output:
65
56
67
68

ix) indexOf()

❖ The indexOf() method Searches for the first occurrence of a character or substring in a given
String.
❖ There are 4 variations of this method in String class:
int indexOf(int ch): It returns the index of the first occurrence of character ch in a given String.

int indexOf(int ch, int fromIndex): It returns the index of first occurrence of character ch in
the given string after the specified index “fromIndex”.

int indexOf(String str): Returns the index of string str in a particular String.

int indexOf(String str, int fromIndex): Returns the index of string str in the given string after
the specified index “fromIndex”.

107
❖ All the above variations returns -1 if the specified char/substring is not found in the
particular String.
Example 1:

// Java program to demonstrate indexOf() method


import java.io.*;
class indexOfDemo
{
public static void main(String args[])
{
String S = "Now is the time for all good mento come to the aid of their country.";
System.out.println(S);
System.out.println("indexOf(t) = " + S.indexOf('t'));
System.out.println("indexOf(the) = " + S.indexOf("the"));
System.out.println("indexOf(t, 10) = " + S.indexOf('t', 10));
System.out.println("indexOf(the, 10) = " + S.indexOf("the", 10));
}
}
Output:

Now is the time for all good men to come to the aid of their country.

indexOf(t) = 7
indexOf(the) = 7
indexOf(t, 10) = 11
indexOf(the, 10) = 44

x) lastIndexOf()

❖ The lastIndexOf() method searches for the last occurrence of a character or substring in a given
string.
❖ It has the following 4 forms:
int lastIndexOf(int ch): It returns the last occurrence of character ch in the given String.

int lastIndexOf(int ch, int startIndex): It returns the last occurrence of ch, it starts looking
backwards from the specified index “startIndex”.

int lastIndexOf(String str): Returns the last occurrence of substring str in a String.

int lastIndexOf(String str, int startIndex): Returns the last occurrence of str, starts searching
backward from the specified index “startIndex”.

Example:
//Java program to demonstrate lastIndexOf().
import java.io.*;
class LastIndexOfDemo

108
{
public static void main(String args[])
{
String S = "Now is the time for all good men to come to the aid of their country.";
System.out.println(S);
System.out.println("lastIndexOf(t) = " + S.lastIndexOf('t'));
System.out.println("lastIndexOf(the) = " + S.lastIndexOf("the"));
System.out.println("lastIndexOf(t, 60) = " +S.lastIndexOf('t', 60));
System.out.println("lastIndexOf(the, 60) = " + S.lastIndexOf("the", 60));
}
}
Output:

Now is the time for all good men to come to the aid of their country.

lastIndexOf(t) = 65
lastIndexOf(the) = 55
lastIndexOf(t, 60) = 55
lastIndexOf(the, 60) = 55

xi) length()

❖ The length() method returns the number of characters in a string.


❖ The general form is:
StringObject.length()
Example:
//Java program to demonstrate length method
import java.io.*;
public class LengthExample
{
public static void main(String args[])
{
String Str="Sindhi College";
System.out.println("String length is: "+Str.length());
}
}
Output:
14
xii) replace(), replaceAll & replaceFirst() methods

❖ The Java String class has three types of replace methods:

1. replace()
2. replaceAll()
3. replaceFirst()

109
1. replace()
❖ The replace() method replaces every occurrence of a given character with a new character and
returns a new string.
❖ The general form is:
StringObject.replace(char original, char replacement)
Here, original specifies the string to be replaced by the string specified by replacement. The
resulting string is returned.
Example:

//Java program to demonstrate replace method


import java.io.*;
public class replace_Ex
{
public static void main(String args[])
{
String Str = new String("The quick fox jumped");
System.out.println("Original String is ': " + Str);
System.out.println("String after replacing 'fox' with 'dog': " + Str.replace("fox", "dog"));
}
}
Output:
Original String is ': The quick fox jumped
String after replacing 'fox' with 'dog': The quick dog jumped

2. replaceAll()
❖ The replaceAll() method returns a new string where each occurrence of the matching substring
is replaced with the replacement string.
❖ The general form is:
StringObject.replaceAll(String regex, String replacement)
Here,
regex - regular expression that is to be replaced
replacement -matching substrings are replaced with this string
Example:

//Java program to demonstrate replaceAll method


import java.io.*;
public class replaceAllExample
{
public static void main(String args[])
{
String Str="Sindhi College";
String replaceString=Str.replaceAll("i","a");//replaces all occurrences of "i" to "a"
System.out.println(replaceString);
110
}
}
Ouput:
Sandha College
3. replaceFirst()
❖ The replaceFirst() method replaces only the first substring which matches a given regular
expression.
❖ Matching of the string starts from the beginning of a string (left to right). The general form is:
StringObject.replaceFirst(String regex, String replacement)
Here,
regex − regular expression.
replacement − the string that replaces regular expression.
Example:
//Java program to demonstrate replaceFirst method
import java.io.*;
public class repFirst_Ex
{
public static void main(String args[])
{
String Str = new String("Welcome to SindhicollegeSindhi");
System.out.print("Original String : " );
System.out.println(Str);
System.out.print("After replacing 1st occurrence of regex with replacement : " );
System.out.println(Str.replaceFirst("Sindhi", "Alpha"));
}
}
Output:
Original String : Welcome to SindhicollegeSindhi
After replacing 1st occurrence of regex with replacement : Welcome to AlphacollegeSindhi

xiii) startsWith()
❖ The startsWith() method checks whether the given string begins with the specified string or
not.
❖ The general form is:
StringObject.startsWith(String str)
Here, str is the String being tested. If the string matches, true is returned. Otherwise, false is
returned.
Example:
//Java program to demonstrate startsWith method
import java.io.*;
class StartsWith_Ex
{
111
public static void main(String args[])
{
String str = "Java Programming";
System.out.println(str.startsWith("Java"));
System.out.println(str.startsWith("Program"));
}
}
Output:
true
false
xiv) substring()

❖ The substring() method is used to extract a substring.


❖ There are two types of substring methods in java

1. substring(jnt StartIndex)
❖ The substring() method is used to extract a part of the string.
❖ The general form is:
StringObject.substring(int StartIndex)
Here, StartIndex specifies the beginning index
Example:
//SubstrExample
import java.io.*;
public class Substr_Ex1
{
public static void main(String args[])
{
String Str = new String("Welcome to DataPoint");
System.out.print("The extracted substring is : ");
System.out.println(Str.substring(11));
}
}
Output:

The extracted substring is : DataPoint


2. substring(StartIndex, EndIndex)
❖ The substring() method extracts the characters from a string, between the specified starting
and ending positions and returns a new sub string.
❖ The general form is:
StringObject.substring(int startIndex, int endIndex)
Here, the startIndex specifies the beginning index, and endIndex specifies the stopping point.
The string returned contains all the characters from the beginning index, up to, but not including,
112
the ending index.
Example:
//Java program using substring
import java.io.*;
public class Substr2_Ex2
{
public static void main(String args[])
{
String Str = new String("Welcome to Java");
System.out.print("The extracted substring is : ");
System.out.println(Str.substring(11, 15));
}
}
Output:
The extracted substring is : Java
xv) toCharArray()

❖ The toCharArray() method converts the string to a character array.


❖ The returned array length is equal to the length of the string.
❖ The general form is:
StringObject. toCharArray()
Example:
//Java Program to implement toCharArray()
import java.io.*;
class ToCharArrayEx
{
public static void main(String args[])
{
String S = "Sindhi";
char[] Str = S.toCharArray();
for (int i = 0; i <Str.length; i++)
{
System.out.println(Str[i]);
}
}
}
Output:
S
i
n
d
h
i

113
xvi) toLowerCase()
❖ The toLowerCase() method is used to convert all the characters of a string to lowercase letters.
❖ The general form is:
StringObject.toLowerCase()

Example:

//Java program to demonstrate toLowerCase method


import java.io.*;
public class ToLowerCase_Ex
{
public static void main(String args[])
{
String Str = "SINDHI COLLEGE";
//Convert to LowerCase
System.out.println(Str.toLowerCase());
}
}
Output:
sindhi college
xvii) toString()
❖ The toString() method returns the string representation of the object.
❖ The general form is:
StringObject.toString()

Example:

//Java Program to implement toString()


import java.io.*;
public class Test
{
public static void main(String args[])
{
int x = 5;
System.out.println(x.toString());
}
}
Output:
5
xviii) toUpperCase()
❖ The toUpperCase() method is used to convert all the characters of a string to uppercase letters.
❖ The general form is:
StringObject.toUpperCase()

Example:
114
//Java program to demonstrate toUpperCase method
import java.io.*;
public class ToUpperCase_Ex
{
public static void main(String args[])
{
String Str = "Sindhi College";
//Convert to UpperCase
System.out.println(Str.toUpperCase());
}
}
Output:
SINDHI COLLEGE
xix) trim()
❖ The trim() method is used to remove leading and trailing whitespaces from a string.
❖ The general form is:
StringObject.trim()
Example:

//Java program to demonstrate trim() method


import java.io.*;
class Trim_Ex
{
public static void main(String args[])
{
String Str = " Learn Java Programming ";
System.out.println(Str.trim());
}
}

Output:

Learn Java Programming


xx) valueOf()
❖ The valueOf() method returns the string representation of the argument passed. This method has
the following variants:
• valueOf(boolean b) − Returns the string representation of the boolean argument.
• valueOf(char c) − Returns the string representation of the char argument.
• valueOf(char[] data) − Returns the string representation of the char array argument.
• valueOf(char[] data, int offset, int count) − Returns the string representation of a specific
subarray of the char array argument.
• valueOf(double d) − Returns the string representation of the double argument.
• valueOf(float f) − Returns the string representation of the float argument.

115
• valueOf(int i) − Returns the string representation of the int argument.
• valueOf(long l) − Returns the string representation of the long argument.
• valueOf(Object obj) − Returns the string representation of the Object argument.
❖ The general form is:
StringObject.valueOf()
Example:

//Java program to implement valueOf method


import java.io.*;
public class ValueOf_Ex
{
public static void main(String args[])
{
int i = 10;
float f = 10.10f;
double d = 102939939.939;
boolean b = true;
long l = 1232874;
char[] arr = {'a', 'b', 'c', 'd'};
System.out.println(String.valueOf(i));
System.out.println(String.valueOf(f));
System.out.println(String.valueOf(d));
System.out.println(String.valueOf(b));
System.out.println(String.valueOf(l));
System.out.println(String.valueOf(arr));
}
}
Output:
10
10.1
1.02939939939E8
true
1232874
abcd

8.3 StringBuffer Class


❖ StringBuffer class is used to create a mutable (modifiable) string.
❖ The StringBuffer class in Java is same as String class except it is mutable i.e. it can be changed.
❖ StringBufferclass is available in java.lang package.

1. StringBuffer Constructors

❖ StringBuffer defines these Four constructors:

116
(i) StringBuffer()
(ii) StringBuffer(int size)
(iii) StringBuffer(String str)
(iv) StringBuffer(charSequence []ch)
i) StringBuffer()
❖ This constructor creates an empty stringbuffer and reserves space for 16 characters.
❖ This is the default constructor.
❖ The general form is:
StringBuffer bufname=new StringBuffer();
Example:
StringBuffer str=new StringBuffer();

ii) StringBuffer(int size)


❖ This constructor creates an empty stringbuffer and takes an integer argument to set capacity of
the buffer.
❖ The general form is:
StringBuffer bufname=new StringBuffer(size);
Example:
StringBuffer str=new StringBuffer(15);
iii) StringBuffer(String str)
❖ This constructor creates a stringbuffer object from the specified string.
❖ The general form is:
StringBuffer bufname=new StringBuffer(str);
Example:
StringBuffer str=new StringBuffer(“Welcome”);
iv) StringBuffer(charSequence []ch)
❖ This Constructor creates a stringbuffer object from the charsequence array.
2. StringBuffer Methods
❖ The following methods are some of the most commonly used methods of StringBuffer
class.
i) append(String str)
❖ The append()method is used to add text at the end of the existing text.
❖ The general form is:

StringBufferObject.append(String str)
Example:
//Java program to demonstrate append method

117
import java.io.*;
public class StringBuffer_AppendEx
{
public static void main(String args[])
{
StringBuffer str = new StringBuffer("Sindhi");
str.append("College");
System.out.println(str);
}
}
Output:
SindhiCollege
ii) capacity()
❖ The capacity()method returns the allocated capacity of the StringBuffer object.
❖ The general form is:
StringBufferObject.capacity()
Example:
//Java program to demonstrate capacity() method
import java.io.*;
public class StrBuffer_CapacityEx
{
public static void main(String args[])
{
StringBuffer str = new StringBuffer();
System.out.println(str.capacity());
}
}
Output:
16

iii) charAt(int index)

❖ The chatAt()method is used to return the character at the specifiedposition.


❖ The general form is:
StringBufferObject.charAt(int index)
Example:
//Java program to demonstrate charAt method
import java.io.*;
public class StringBuffer_CharAtEx
{
public static void main(String args[])
{
StringBuffer sb = new StringBuffer("Stringbuffer");
System.out.println("Given String: "+sb);
118
// Printing character at index value 2
System.out.println("Character at index 2: "+sb.charAt(2));
}
}
Output:
Given String: Stringbuffer
Character at index 2: r

iv) delete(int startIndex, int endIndex)


❖ The delete()method is used to delete the string from the specified startIndex to endIndex.
❖ The general form is:
StringBufferObject.delete(int startIndex, int endIndex)
Here, startIndex specifies the index of the first character to remove, and endIndex specifies an
index of the last character to remove. Thus, the substring deleted runs from startIndex to
endIndex-1. The resulting StringBuffer object is returned.
Example:
//Java program to demonstrate delete method
import java.io.*;
public class StringBuffer_DeleteEx
{
public static void main(String args[])
{
StringBuffer sb = new StringBuffer("Java lang package");
System.out.println("Given String = " + sb);
// Deleting characters from index 4 to index 9
sb.delete(4, 9);
System.out.println("After deletion = " + sb);
}
}
Output:
Given String = Java lang package
After deletion = Java package

v) deleteCharAt(int index)

❖ The deleteCharAt()method is used to delete the character at the specified index.


❖ The general form is:
StringBufferObject.deleteCharAt(int index)

Example:

//Java program to demonstrate deleteCharAt method

119
import java.io.*;
public class StringBuffer_DeleteCharAtEx
{
public static void main(String args[])
{
StringBuffer sb = new StringBuffer("Raghav");
System.out.println("String buffer before deletion = " + sb);
// Deleting the character at index 5
sb.deleteCharAt(5);
System.out.println("String buffer after deletion = " + sb);
}
}

Output:

String buffer before deletion = Raghav


String buffer after deletion = Ragha

vi) ensureCapacity(int capacity)


❖ The ensureCapacity() is method is used to set the size of the buffer.
❖ The general form is:
StringBufferObject.ensureCapacity(int capacity)
Here, capacity specifies the size of the buffer.
Example:
//Java program to demonstrate ensureCapacity method
import java.io.*;
public class StringBuffer_ensureCapacityEx
{
public static void main(String args[])
{
StringBuffer str = new StringBuffer();
System.out.println(str.capacity());
str.ensureCapacity(30); //Greater than the existing capacity
System.out.println(str.capacity()); //Output: 34 (by following the rule –
// (oldcapacity*2) + 2.) i.e (16*2)+2 = 34.
}
}
Output:

16
34

vii) getChars()

120
❖ The getChars() method copies characters from the given string into the destination character
array.
❖ The general form is:
. StringBufferObject.getChars(int srcStartIndex,int srcEndIndex,char[]destArray,int

destStartIndex)

Here,
srcStartIndex: Index of the first character in the string to copy.
srcEndIndex: Index after the last character in the string to copy.
destArray: Destination array where chars wil get copied.
destStartIndex: Index in the array starting from where the charswill be pushed into the
array.

Example:

// Java program to demonstrate getChars() method


class GetChars_Ex
{
public static void main(String args[])
{
String str = "Welcome to Sindhi College";
char[] destArray = new char[14];
str.getChars(11, 25, destArray, 0);
System.out.println(destArray);
}
}

Output:

Sindhi College

viii) insert()

❖ The insert() method is used to insert the given string at the specified index.
❖ There are various overloaded insert() methods available in StringBuffer class.
❖ The few forms of the insert() method are:
StringBufferObject.insert(int index, String str)
StringBufferObject.insert(int index, char ch)
StringBufferObject.insert(int index, Object obj)

Here, index specifies the index at which point the string will be inserted into the invoking
StringBuffer object.

Example:
121
//Java program to demonstrate insert() method of StringBuffer class
import java.io.*;
class Insert_Example
{
public static void main(String args[])
{
StringBuffer sb=new StringBuffer("Hello ");
sb.insert(1,"Java");//Now original string is changed
System.out.println(sb);//prints HJavaello
}
}
Output:
HJavaello
ix) indexOf()
❖ The indexOf() method is used to return the index of the first occurrence of the specified
substring.
❖ In StringBuffer class, there are two types of indexOf() method depending upon the
parameters passed to it.
1. indexOf(String str)

❖ This method returns the position of the first occurrence of the specified substring within the
original string.
❖ If the substring str is not present, then -1 is returned.
❖ The general form is:
StringBufferObject.indexOf(String str)
Here, str is the string to be searched.
Example:

//Java program to demonstrate indexOf(String str) method


import java.io.*;
public class IndexOf_Ex1
{
public static void main(String args[])
{
StringBuffer sb = new StringBuffer("Programming language");
System.out.println("Given String = " + sb);
// Returns the index of the specified substring
System.out.println("Index of substring = " + sb.indexOf("age"));
// Returns -1 as substring is not found
System.out.println("Index of substring = " + sb.indexOf("k"));
}
}
Output:

122
Given String = Programming language
Index of substring = 17
Index of substring = -1
2. indexOf(String str, int startIndex)
❖ This method returns the index of the first occurrence of the substring starting at the specified
index.
❖ If the substring str is not present, then -1 is returned.
❖ The general form is:
StringBufferObject.indexOf(String str, int startIndex)
Here, str is the string to be searched. startIndex specifies the index of the first character
Example:
//Java program to demonstrate indexOf(String str, int startIndex) method
import java.io.*;
public class IndexOf_Ex2
{
public static void main(String args[])
{
StringBuffer sb = new StringBuffer("Let us go to JavaTpoint to learn Java");
System.out.println("String: " + sb);
// Returns the index of first occurrence substring after the given index
System.out.println("Index of substring Java: " + sb.indexOf("Java",20));
System.out.println("Index of substring to: " + sb.indexOf("to",8));
}
}
Output:
nt to learn java
String: Let us go to JavaTpoint to learn Java
Index of substring Java: 33
Index of substring to: 10
x) lastIndexOf()
❖ The lastIndexOf() method returns the index of the last occurrence of the specified substring.
❖ There are two overloaded lastIndexOf() methods available in StringBuffer class.
1. lastIndexOf(String str)

❖ This method returns the position of the last occurrence of the specified substring.
❖ The general form is:
StringBufferObject.lastIndexOf(String str)

Here, str is the string to be searched.


Example:

123
//Java program to implement lastindexOf
import java.io.*;
public class LastIndexOf_Ex1
{
public static void main(String args[])
{
StringBuffer Str = new StringBuffer("This is lastIndexOf example");
System.out.println("Given String: "+Str);
//Rreturns last index of example
System.out.println("Last index of example: " + Str..lastIndexOf("example"));
}
}
Output:
Given String: This is lastIndexOf example
Last index of example: 20
2. lastIndexOf(String str, int startIndex)
❖ This method returns the position of the last occurrence of the specified substring.
❖ The argument startIndex is the index to start the search from.
❖ The general form is:
StringBufferObject.lastIndexOf(String str, int startIndex)
Here, str is the string to be searched. startIndex specifies the index of the first character.
Example:
//Java program to implement lastIndexOf method
import java.io.*;
public class LastIndexOf_Ex2
{
public static void main(String args[])
{
StringBuffer Str = new StringBuffer("This is string it value is java");
System.out.println("Given String: " + Str);
//Returns last index of is, fromIndex 10
System.out.println("Last index of is: " + sb2.lastIndexOf("is",10));
}
}
Output:

Given String: This is string it value is java


Last index of is: 5
xi) length()

❖ The length()method is used to return the length of the string i.e. total number of characters.
❖ The general form is:
StringBufferObject.length()

124
Example:
//Java program to demonstrate length() method
import java.io.*;
public class Length_Ex
{
public static void main(String args[])
{
StringBuffer Str = new StringBuffer("Sindhi College");
// Printing the length of stringbuffer
System.out.println("Length = " + Str.length());
}
}
Output:
Length = 14
xii) replace()
❖ The replace() method is used to replace one string with another string.
❖ The substring being replaced is specified by the indexes startIndex and endIndex. Thus, the
substring at the startIndex through endIndex–1 is replaced.
❖ The general form is:
StringBufferObject.replace(int startIndex, int endIndex, String str)
Here,
StartIndex - It is the starting index of the substring
EndIndex - It is the end index (exclusive) of the substring.
Str - It is a string which replaces the substring from this sequence.
Example:
//Java program to demonstrate replace() method
import java.io.*;
public class Replace_Ex
{
public static void main(String args[])
{
StringBuffer sb = new StringBuffer("Program compile time");
System.out.println("Given String: "+sb);
System.out.println("After replace: "+sb.replace(8, 15, "run"));
}
}

Output:
Given String: Program compile time
After replace: Program run time
xiii) reverse()
125
❖ The reverse() method is used to reverse the given string.
❖ The general form is:
StringBufferObject.reverse()
Example:
//Java program using StringBuffer reverse()
import java.io.*;
public class Reverse_Ex
{
public static void main(String args[])
{
StringBuffer Str = new StringBuffer("Hello");
Str.reverse();
System.out.println(Str);
}
}
Output:
olleH
xiv) setCharAt()
❖ The setCharAt() method is used to set the specified character at the given index.
❖ The general form is:
StringBufferObject.setCharAt(int index, char ch)
where index specifies the position of the character being set and ch specifies the new value of the
character.
Example
//Java program to demonstrate setCharAt method
import java.io.*;
public class SetCharAt_Ex
{
public static void main(String args[])
{
StringBuffer sb = new StringBuffer("abc");
System.out.println("Given String: " + sb);
// Character at index 1
System.out.println("Character at index 1: " + sb.charAt(1));
// Set character at index 1
sb.setCharAt(1, 'x');
System.out.println("New String: " + sb);
// Character at index 1
System.out.println("Character at index 1: " + sb.charAt(1));
}
}

Output:
126
Given String: abc
Character at index 1: bc
New String: axc
Character at index 1: xharacter at index 1: b
xv) setLength()
❖ The setLength() method is used to set the new length of the string.
❖ The general form is:
StringBufferObject.setLength(int len)
Here, len specifies the length of the buffer. This value must be nonnegative. When we increase
the size of the buffer, null characters are added to the end of the existing buffer.
Example:
//Java program to implement setLength method
import java.io.*;
public classSetLength_Example
{
public static void main(String[] args)
{
StringBuffer sb = new StringBuffer("Sindhi College");
System.out.println("Given String: "+sb);
System.out.println("Length: "+sb.length());
//Set new length of character sequence
sb.setLength(7);
System.out.println("Set new length: "+sb.length());
System.out.println("New String: "+sb);
}
}
Output:
Given String: Sindhi College
Length: 14
Set new length: 7
New String: Sindhi
xvi) substring()

❖ The substring() method is used to extract a substring from the original string.
❖ There are two overloaded substring() methods available in StringBuffer class. These methods
are differentiated on the base of their parameters.
1. substring(int startIndex)
❖ This method is used to return the substring from the specified startIndex.
❖ The general form is:
StringBufferObject.substring(int startIndex)
This form will extract substring from startIndex till the end of the buffer.
127
Example:
//Java program to demonstrate substring(int startIndex) Method
import java.io.*;
public class SubString_Ex1
{
public static void main(String args[])
{
StringBuffer sb = new StringBuffer("StringBuffer");
System.out.println("Given String: "+sb);
String sub_str= sb.substring(6);
System.out.println("Sub String from start index 6= "+sub_str);
}
}
Output:
Given String: StringBuffer
Sub String from start index 6= Buffer
2. substring(int startIndex, int endIndex)
❖ This method is used to return the substring from the specified startIndex and endIndex.
❖ The general form is:
StringBufferObject.substring(int startIndex, int endIndex)
This will extract a substring from startIndex till the endIndex but won't include the character
at endIndex.
Example:
//Java program to demonstrate sunstring(int StartIndex, int endIndex) method
import java.io.*;
public class Substring_Ex2
{
public static void main(String args[])
{
StringBuffer sb = new StringBuffer("Java is a programming language");
System.out.println("Given String: "+sb);
String sub_str= sb.substring(10,20);
//Sub string from start index 10 and end index 20
System.out.println("Sub string from index 10 to 20: "+sub_str);
}
}
Output:
stva is a programming language
Given String: Java is a programming languageequence from index 10 to 22:
string from index 10 to 22: programming
xvii) toString()
❖ The toString() method can be used to convert a StringBuffer object to a String.
❖ The general form is:
StringBufferObject.toString()
128
Example:

//Java program to demonstate toString()


import java.io.*;
public class ToString_Ex
{
public static void main(String args[])
{
StringBuffer sb = new StringBuffer("Hello World!");
String str = sb.toString();
System.out.println("StringBuffer to String: " + str);
}
}
Output:
StringBuffer to String: Hello World!
8.8 Differences between String class and StringBuffer class

Sl. No. String StringBuffer


1) String objecct is immutable. StringBuffer object is mutable.
2) The length of the String object is fixed. The length of the StringBuffer can be
increased.
3) It is slower during concatenation. It is faster during concatenation.
4) Consumes more memory. Consumes less memory.
5) It overrides the equals() method of It doesn't override the equals() method of
Object class. Hence, the ‘equals’ Object class.
method can be used to compare two
strings.

Exercises:

1. Define String Class.


2. Define StringBuffer Class.
3. Explain briefly about String Constructors.
4. Discuss the various methods of the String class.
5. Explain the various methods of the StringBuffer class with suitable example.
6. Distinguish between String class and StringBuffer Class.
7. Write a Java program to illustrate the use of String methods.
**************************

UNIT - III

129
*******************************************************************************
Chapter 9 Packages
*******************************************************************************
9.1 Definition
❖ A package is a group of related classes and interfaces. The grouping is usually done
according to functionality. In fact, packages act as “containers” for classes.
❖ Java classes can be grouped together in packages. A package name is the same as the directory
(folder) name which contains the .java files.
9.2 Benefits of using packages
❖ The classes contained in the packages of another program can be easily reused.
❖ Packages also allow programmers to separate design from coding.
❖ In packages, classes can be declared uniquely compared with classes in other packages.
❖ Java Packages provide a way to ‘hide’ classes thus preventing other programs or packages from
accessing classes that are meant for internal use only.
❖ Packages provide access protection.
❖ Java package removes naming collision.
9.3 Different types of Packages
❖ Java packages are classified into two types. They are:
1. Java API Packages
2. User Defined Packages
Java API Packages
❖ Java API provides a large number of classes grouped into different packages according to
functionality. Most of the time we use the packages available with the Java API as shown in
Figure 10.1.

Figure 10.1: Frequently used API packages

❖ Table 10.1 shows the classes that belong to each package.

Package Name Contents

130
java.lang Language support classes. These are classes that Java compiler itself uses and
therefore they are automatically imported. They include classes for primitive
types, strings, math functions, threads and exceptions.
java.util Language utility classes such as vectors, hash tables, random numbers, date,
etc.
java.io Input / output support classes. They provide facilities for the input and output
of data.
java.awt Set of classes for implementing graphical user interface. They include
classes for
windows, buttons, lists, menus, and so on.
java.net Classes for networking. They include classes for communicating with local
computers as well as with Internet servers.
java.applet Classes for creating and implementing applets

Table 10.1: Java System Packages and Their Classes


User Defined Packages
❖ Programmers can define their own packages to bundle group of classes/interfaces etc.
❖ It is a good practice to group related classes implemented by us so that a programmers can easily
determine that the classes, interfaces, enumerations, annotations are related.
9.4 Naming Conventions
❖ Packages can be named using the standard Java naming rules.
❖ By convention, however, packages begin with lowercase letters. This makes it easy for users to
distinguish package names from class names when looking at an explicit reference to a class.
❖ We know that all class names, again by convention, begin with an uppercase letter. For example,

❖ This statement uses a fully qualified class name Math to invoke the method sqrt().
❖ The package names must be unique. Duplicate names will cause run-time errors.
❖ Naming a package is therefore a very important aspect of creating a package. Since multiple
users work on Internet, duplicate package names are unavoidable.
❖ Java designers have recognized this problem and therefore suggested a package naming
convention that ensures uniqueness.
❖ This suggests the use of domain names as prefix to the preferred package names. For example:
cbe.psg.mypackage
Here, cbe denotes city name and psg denotes the organization name.
9.5 Creating Packages
❖ The package statement is used to create a new package.
❖ The package statement should be the first line in the source file. There can be only one package
statement in each source file, and it applies to all types in the file.

131
❖ The general form of the package statement is:
package packagename;
where packagename is the name of the package.
Example:
package MyPackage; // package declaration
public class FirstClass // class definition
{
………………
……………… (body of class)
………………
}

❖ Creating our own package involves the following steps:


1. Declare the package at the beginning of the file using the form
package packagename;
2. Define the class that is to be put in the package and declare it public.
3. Create a subdirectory under the directory where the main source files are stored.
4. Store the listing as the classname.java file in the subdirectory created.
5. Compile the file. This creates .class file in the subdirectory.
❖ Java also supports the concept of package hierarchy. This is done by specifying multiple names
in a package statement, separated by dots.
Example:
package firstPackage.secondPackage;
This approach allows us to group related classes into a package and then group related packages
into a larger package.
❖ A Java package file can have more than one class definitions. In such cases, only one of the
classes may be declared public and that classname with .java extension is the source file name.
Set CLASSPATH System Variable
❖ To display the current CLASSPATH variable, use the following commands in Windows and
Unix (Bourne shell):
• In Windows -> C:\> set CLASSPATH
• In Unix -> % echo $CLASSPATH
❖ To delete the current contents of the CLASSPATH variable, use:
• In Windows -> C:\> set CLASSPATH=
• In Unix -> % unset CLASSPATH; export CLASSPATH
❖ To set the CLASSPATH variable:
• In Windows -> set CLASSPATH=C:\users\jack\java\classes
• In Unix -> % CLASSPATH=/home/jack/java/classes; export CLASSPATH
132
Example:
// Java Program to create a simple package
// Palindrome.java
package mypackage;
public class Palindrome
{
public String test(String str)
{
char givenstring[];
char reverse[] = new char[str.length()];
boolean flag = true;
int i = 0, j = 0,l;
givenstring = str.toCharArray();
l=str.length();
for(i=l-1;i>=0;i--)
{
reverse[j] = givenstring[i];
j++;
}
for(i=0;i<l;i++)
{
if(reverse[i]!= givenstring[i])
flag = false;
}
if (flag==false)
return "Not Palindrome";
else
return "Palindrome";
}
}
--------------------------------------------------------------------------------------------------------------
// Java program using packages to check whether the given string is Palindrome or not
// Program to use the package created
// Palintest.java
import mypackage.*;
import java.util.*;
import java.io.*;

class Palintest
{
public static void main(String args[]) throws IOException
{
Palindrome P=new Palindrome();
Scanner in=new Scanner(System.in);
String message;
System.out.println("\tJava Program using Package");
133
System.out.println("\t***********************");
System.out.println("Input");
System.out.println("-------");
System.out.println("Enter the String");
String str= in.nextLine();
message=P.test(str);
System.out.println("Output");
System.out.println("---------");
System.out.println("The given string is "+message);
}
}
C:\>md mypackage
C:\>cd mypackage
C:\mypackage>path="c:\program files\java\jdk1.6.0_01\bin";
C:\mypackage>javac Palindrome.java
C:\mypackage>cd\
C:\>path="c:\program files\java\jdk1.6.0_01\bin";
C:\>javac Palintest.java
C:\>java Palintest

Java Program using Package


***********************
Input
-------
Enter the String
malayalam

Output
---------
The given string is Palindrome

C:\>java Palintest
Java Program using Package
***********************
Input
-------
Enter the String
welcome

Output
---------
The given string is Not Palindrome
C:\>
9.6 Access Protection
❖ Java provides many levels of security that provides the visibility of members (variables and
methods) within the classes, subclasses, and packages.

134
❖ There are four types of access modifiers available in java:
1) Default – No keyword required
2) Private
3) Protected
4) Public
1) Default
❖ When no access modifier is specified for a class, method, or data member – It is said to be
having the default access modifier by default.
❖ The data members, class or methods which are not declared using any access modifiers i.e.
having default access modifier are accessible only within the same package.
2) private
❖ The private access modifier is specified using the keyword private.
❖ The scope of private modifier is limited to the class only.
❖ The methods or data members declared as private are accessible only within the class in
which they are declared.
3) protected
❖ The protected access modifier is specified using the keyword protected.
❖ The methods or data members declared as protected are accessible within the same package
or subclasses in different packages.
4) public
❖ The public access modifier is specified using the keyword public.
❖ The members, methods and classes that are declared public can be accessed
from anywhere.
❖ There is no restriction on the scope of public data members.
9.7 Accessing a Package
The import statement
❖ The import statement is used to access the package.
❖ The general form of import statement for searching a class is:
import package1 [.package2] [.package3].classname;

Here, package1 is the name of the top-level package. package2 is the name of the package that
is inside the 1st package i.e. package1 and so on. Programmers can use any number of packages
in the package hierarchy. At the end, the explicitly classname is specified.
❖ The import statement should appear before any class definitions in a source file. Multiple
import statements are allowed. The following is an example of importing a particular class:
import firstPackage.secondPackage.MyClass;
135
❖ After defining this statement, all members of the class MyClass can be directly accesses using
the class name or its objects directly without using the package name.
❖ We can also use another approach as follows:
import packagename.*;
Here, packagename may denote a single package or hierarchy of packages. The star (*) indicates
that the compiler should search this entire package hierarchy where it encounters a class name.
this implies that we can access all classes contained in the above package directly.
Exercises:
1. Define package.
2. List out few Java packages.
3. Explain Java API packages briefly.
4. What are the naming conventions for Java packages?
5. How will you create a user defined packages in Java?
6. Explain Access Protection in Java.
7. Define import keyword.
8. How will you access the Java package?

**************************

*******************************************************************************
Chapter 10 Interfaces
*******************************************************************************
10.1 Introduction
136
❖ An interface is similar to a class, but it contains abstract methods and static final variables
only.
❖ To access the interface methods, the interface must be "implemented" by another class with
the implements keyword.
❖ Like abstract classes, interfaces cannot be used to create objects.
❖ Interface methods do not have a body - the body is provided by the "implement" class.
❖ On implementation of an interface, we must override all of its methods.
❖ Interface methods are by default abstract and public..
❖ Interface attributes are by default public, static and final.
❖ An interface cannot contain a constructor.
10.2 Defining an Interface
❖ The syntax for defining an interface is very similar to that for defining a class.
❖ The general form of an interface definition is:
interface InterfaceName
{
//Variable declaration;
//Methods declaration;
}

Here, interface is the keyword and InterfaceName is any valid Java variable. Variables are
declared as follows:
static final type VariableName=value;
All variables are declared as constants. Methods declaration will contain only a list of methods
without any body statements. Methods are declared as follows:
return-type methodName(parameter_list);
Example 1:
interface Item
{
static final float code=1001;
static final String name=”Fan”;
void display();
}

Here, the code for the method is not included in the interface and the method declaration simply
ends with a semicolon. The class that implements this interface must define the code for the method.

Example 2:

interface Area
{
float static float pi=3,142F;

137
float compute(float x, float y);
void show();
}

10.3 Extending Interfaces


❖ An interface can extend another interface, similarly to the way that a class can extend another
class.
❖ The extends keyword is used to extend an interface, and the child interface inherits the methods
of the parent interface.
interface name2 entends name1
{
//Body of name2
}

Example:

interface ItemConstants
{
int code=1001;
String name=”Fan”;
}
interface Item extends ItemConstants
{
display();
}

The interface Item would inherit both the constants code and name into it. The variables name
and code are declared like simple variables. It is allowed because all the variables in an interface
are created as constants although the keywords final and static are not present.
❖ We can also combine several interfaces together into a single interface. Following declarations
are valid.
interface ItemConstants
{
int code=1001;
String name=”Fan”;
}

interface ItemMethods
{
display();
}

interface Item extends ItemConstants, ItemMethods


{
………..
………..
}

138
❖ While interfaces are allowed to extend to other interfaces, subinterfaces cannot define the
methods declared in the superinterfaces, Instead, it is the responsibility of any class that
implements the derived interface to define all the methods.
❖ An interface cannot extend classes.
10.4 Implementing Interfaces
❖ A class uses the implements keyword to implement an interface. The implements keyword
appears in the class declaration following the extends portion of the declaration.
❖ Interfaces are used as “superclasses” whose properties are inherited by classes. It is therefore
necessary to create a class that inherits the given interface. This is done as follows:
class classname implements Interfacename
{
//Body of classname
}

Here the class classname “implements” the interface interfacename. A more general form of
implementation may look like this:
class classname extends superclass implements Interfac1, Interface2, …
{
//Body of classname
}

This shows that a class can extend another class while implementing interfaces. When a class
implements more than one interface, they are separated by a comma.
Example:

// Java program for implementing interfaces.


// InterfaceTest.java
import java.io.*;
interface Area // Interface defined
{
final static float pi=3.14f;
float compute(float x, float y);
}
class Rectangle implements Area // Interface implemented
{
public float compute(float x, float y)
{
return (x*y) ;
}
}

class Circle implements Area // Another implementation


{
public float compute(float x, float y)
{
return (pi*x*x) ;
}
139
}
class InterfaceTest
{
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
Rectangle rect=new Rectangle();
Circle cir=new Circle();
int a,b;
System.out.println("Enter the values of a & b");
a=Integer.parseInt(br.readLine());
b=Integer.parseInt(br.readLine());
Area area; // Interface object
area=rect;
System.out.println("Area of Rectangle = "+area.compute(a,b));
area=cir;
System.out.println("Area of Circle = "+area.compute(a,0));
}
}
Output:
Enter the values of a & b
10
20
Area of Rectangle=200
Area of Circle = 314
10.5 Accessing Interface Variables
❖ Interfaces can be used to declare a set of constants that can be used in different classes. Since
such interfaces do not contain methods, there is no need to worry about implementing any
methods.
❖ The constant values will be available to any class that implements the interface.
❖ The values can be used in any method, as part of any variable declaration, or anywhere we can
use a final value.
interface A
{
int m=10;
int n=10;
}
class B implements A
{
int x=n;
void method B(int size)
{
…………
if (size<n)
………..
}
}

140
10.6 Differences between class and interface in Java
Class Interface
A class is declared by using a keyword called An interface is declared by using a keyword
class. interface.
A class can be instantiated. The keyword new An interface can never be instantiated. That is
can only create an instance of a class. an object of interface can never be created.
Variables in a class can be declared using any All variables in an interface are always public,
access modifiers such as public, protected, static, and final.
default, and private. They can also be static,
final, or neither.
Methods declared in a class are implemented. Methods declared in an interface cannot be
i.e, methods have a body. Methods that have a implemented. i.e, In an interface, methods have
body is called concrete method. no body. It contains only abstract method.
Note: Java 8 introduces default method, which
allows us to give the body of a method in an
interface.
The members of a class can be declared with The members of an interface are always public
any access modifiers such as private, default, by default.
protected, and public.
A class can have constructors to initialize An interface cannot have any constructors.
instance variables.
Class allows only single, multilevel and Interface supports all types of inheritance such
hierarchical inheritances but do not support as multilevel, hierarchical, and multiple
multiple inheritance. inheritance.
A class can implement any number of the Interface cannot implement any class.
interface.
A class can extend only one class at a time. An interface can extend multiple interfaces at a
time.
A class is used to define the attributes and Interface is used for defining behavior that can
behaviors of an object. be implemented by any class anywhere in the
class hierarchy.
A method in a class can be declared as final. The method in an interface cannot be final
because if we declare a method as final,the
method cannot be modified by its subclass.
A class may contain main() method. Interface cannot have main() method.

Exercises:
1. Define interface.
2. Define abstract class.
3. How interfaces are extended?
4. Explian in detail about implementing interfaces.
5. Write a Java program to create and implement an interface.
6. How will you access interface variables?
7. Distinguish between class and interface in Java.
**************************
*******************************************************************************
Chapter 11 Exception Handling
*******************************************************************************
11.1 Introduction

141
❖ Exception Handling is a construct in some programming languages to handle or deal with
errors automatically.
❖ Errors are the wrongs that can make a program go wrong. An error may produce an incorrect
output or may terminate the execution of the program abruptly or even may cause the system to
crash.
11.2 Types of Errors
❖ Errors may be broadly classified into two categories:
• Compile-time errors
• Run-time errors
Compile-Time Errors
❖ A compile-time error is an error that is detected by the compiler. Compile-time errors occur
while a program is being compiled.
❖ All syntax errors will be detected and displayed by the Java compiler and therefore these errors
are known as compile-time errors.
❖ Whenever the compiler displays an error, it will not create the .class file. It is therefore necessary
that we fix all the errors before we can successfully compile and run the program.
Example:

// Illustration of compile-time errors


/* This program contains an error */
// Error1.java
import java.io.*;
class Error1
{
public static void main(String args[])
{
System.out.println(“Welcome to Java Programming”) // Missing Semicolon
}
}

❖ Most of the compile-time errors are due to typing mistakes. Typographical errors are hard to
find. The most common problems are:
• Missing semicolon
• Missing brackets in classes and methods
• Misspelling of identifiers and keywords
• Missing double quotes in strings
• Use of undeclared variables
• Incompatible types in assignments / initialization
• Use of = in place of == operator

Run-Time Errors
❖ An error that occurs during the execution of a program is called a run-time error. For
example, running out of memory will often cause run-time error.
142
❖ Most common run-time errors are:
• Dividing an integer by zero
• Accessing an element that is out of the bounds of an array
• Trying to store a value into an array of an incompatible class or type
• Trying to cast an instance of a class to one of its subclasses
• Passing a parameter that is not in a valid range or value for a method
• Trying to illegally change the state of a thread
• Attempting to use a negative size for an array
• Using a null object reference as a legitimate object reference to access a method or a variable
• Converting invalid string to a number
• Accessing a character that is out of bounds of a string

Example:

// Illustration of run-time errors


class Error2
{
public static void main(String args[])
{
int a=10;
int b=5;
int c=5;
int x=a/(b-c); // Division by zero
System.out.println(“x= “+x);
int y=a/(b+c);
System.out.println(“y= “+y);
}
}

The above program is syntactically correct and therefore does not cause any problem during
compilation. However, while executing, it displays the following message and stops without
executing further statements.
Java.lang.ArithmeticException: / by zero
At Error2.main(Error2.java:10)

When Java run-time tries to execute a division by zero, it generates an error condition, which causes
the program to stop after displaying an appropriate message.
11.3 Exceptions

❖ An exception is an event that occurs during the execution of a program.

What is Exception Handling?

❖ Exception Handling is a mechanism to handle runtime errors such as ClassNotFoundException,


IOException, SQLException, RemoteException, etc.
❖ The purpose of exception handling mechanism is to provide a means to detect and report an

143
“exceptional circumstance“ so that appropriate action can be taken. The mechanism suggests
incorporation of a separate error handling code that performs the following tasks:
1. Find the problem (Hit the exception)
2. Inform that an error has occurred (Throw the exception)
3. Receive the error information (Catch the exception)
4. Take correction actions (Handle the exception)

❖ The error handling code basically consists of two segments, one to detect errors and to throw
exceptions and the other to catch exceptions and to take appropriate actions.
❖ All exception classes are subtypes of the java.lang.Exception class. The Exception class is a
subclass of the Throwable class.
11.4 Types of Exception in Java

❖ Java defines several types of exceptions that relate to its various class libraries.
❖ Java also allows users to define their own exceptions.

Built-in Exceptions
❖ Built-in exceptions are the exceptions which are available in Java libraries. These exceptions are
suitable to explain certain error situations. Below is the list of important built-in exceptions in
Java.
1. ArithmeticException
It is thrown when an exceptional condition has occurred in an arithmetic operation.
2. ArrayIndexOutOfBoundsException
It is thrown to indicate that an array has been accessed with an illegal index. The index
is either negative or greater than or equal to the size of the array.
3. ClassNotFoundException
This Exception is raised when we try to access a class whose definition is not found
4. FileNotFoundException
This Exception is raised when a file is not accessible or does not open.
5. IOException
It is thrown when an input-output operation failed or interrupted
6. InterruptedException
It is thrown when a thread is waiting, sleeping, or doing some processing, and it is
interrupted.
144
7. NoSuchFieldException
It is thrown when a class does not contain the field (or variable) specified
8. NoSuchMethodException
It is thrown when accessing a method which is not found.
9. NullPointerException
This exception is raised when referring to the members of a null object. Null represents
nothing
10. NumberFormatException
This exception is raised when a method could not convert a string into a numeric format.
11. RuntimeException
This represents any exception which occurs during runtime.
12. StringIndexOutOfBoundsException
It is thrown by String class methods to indicate that an index is either negative or greater
than the size of the string
Example:
//Java program to demonstrate Arithmetic Exception
import java.io.*;
class ArithmeticException_Demo
{
public static void main(String args[])
{
try
{
int a = 30, b = 0;
int c = a/b; // Cannot divide by zero
System.out.println ("Result = " + c);
}
catch(ArithmeticException e)
{
System.out.println ("Can't divide a number by 0");
}
}
}

11.5 Syntax of Exception Handling Code


❖ The basic concepts of exception handling are throwing an exception and catching it.
try and catch statements
❖ The try statement allows us to define a block of code to be tested for errors while it is being
executed.

145
❖ The catch statement allows us to define a block of code to be executed, if an error occurs in the
try block.
❖ The try and catch keywords come in pairs.
Syntax:
try
{
// Statements that may cause an exception
}
catch(Exception e)
{
// Exception handling ccode
}

❖ The try block can have one or more statements that could generate an exception. If any
statement generates an exception, the remaining statements in the block are skipped and
execution jumps to the catch block that is placed next to the try block.
❖ The catch block can have one or more statements that are necessary to process the exception.
❖ Every try statement should be followed by at least one catch statement; otherwise compiler
error will occur.
Example:
//Java program to demonstrate try…catch Statement
import java.io.*;
class TryCatch_Ex
{
public static void main(String args[])
{
int num1, num2;
try
{
num1 = 0;
num2 = 62 / num1;
System.out.println(num2);
}
catch (ArithmeticException e)
{
System.out.println("You should not divide a number by zero");
}
}
}

Output:
You should not divide a number by zero
11.6 Multiple catch Statements
❖ A single try block can have multiple catch blocks.
❖ Each catch block must contain a different exception handler.

146
Syntax:
try
{
//Statements that may cause an exxception
}
catch(ExceptionType1 e1)
{
//Statements
}
catch(ExceptionType2 e2)
{
//Statements
}
catch(ExceptionType3 e3)
{
//Staatements
}
...
catch(ExceptionTypeN en)
{
//Statements
}
Example:
//Java program using multiple catch blocks
import java.util.Scanner;
public class MultiCatchEx
{
public static void main(String[] args)
{
int x, y;
Scanner sc = new Scanner(System.in);
try
{
System.out.println("Enter the first number");
x = Integer.parseInt(sc.nextLine());
System.out.println("Enter the second number");
y = Integer.parseInt(sc.nextLine());
int z = x / y;
System.out.println("z = " +z);
}
catch(ArithmeticException ae)
{
System.out.println("A number cannot be divided by 0");
}
catch(NumberFormatException nfe)
{
System.out.println("Invalid data types are entered, number must be an integer.");
}
}
}
Output:
147
Enter the first number
40
Enter the second number
20
z=2
--------------------------------------------
Enter the first number
40
Enter the second number
0
A number cannot be divided by 0
--------------------------------------------
Enter the first number
40
Enter the second number
5.5
Invalid data types are entered, number must be an integer.
11.7 Nested try Statements
❖ A try block within another try block is known as nested try block.
❖ The try block which encloses another try block is called outer try block and the enclosed try
block is called inner try block.
Syntax:

try // Outer try block


{
//Statement(s)
try // Inner try block
{
//Statement(s)
}
catch(Exception1 e1) // Inner catch block
{
//Statement(s)
}
}
catch(Exception2 e2) // Outer catch block
{
//Statement(s)
}

Example:

//Java program to demonstrate nested try statement


import java.io.*;
class NestedTry_Ex
{
public static void main(String args[])
{
148
try
{
int a[] = {30, 45, 60, 75, 90, 105, 120, 140, 160, 200};
// Displaying element at index 8
System.out.println("Element at index 8 = "+a[8]);
// Another try block
try
{
System.out.println("Division");
int res = 100/ 0;
}
catch (ArithmeticException e)
{
System.out.println("Sorry! Division by zero isnot possible");
}
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println("ArrayIndexOutOfBoundsException");
}
}
}
Output:
Element at index 8 = 160
Division
Sorry! Division by zero isnot possible

11.8 finally Statement


❖ The finally block contains statements that must be executed whether an exception occurs or
not.
❖ The finally block follows the try-catch block.
Syntax:
try
{
//Statements that may cause an exception
}
catch
{
//Handling exception
}
finally
{
//Statements to be executed
}
Example:

149
//Java program to demonstrate finally sstatement
import java.io.*;
class Example
{
public static void main(String args[])
{
try
{
int num=101/0;
System.out.println(num);
}
catch(ArithmeticException e)
{
System.out.println("Number should not be divided by zero");
}
finally
{
System.out.println("This is finally block");
}
}
}
Output:
Number should not be divided by zero
This is finally block

11.9 Throwing our own Exceptions


throw statement
❖ The throw statement is used to throw an exception explicitly.
❖ The throw keyword is also used to throw custom exceptions.
Syntax:
throw exception;
or
throw new exception_class("Error Message");
Example:
//Java program to demonstrate throw staatement
public class throw_ex
{
static void Validate_Age(int age)
{
if(age<18)
throw new ArithmeticException("Not eligible to vote and drive");
else
System.out.println("Eligible to vote and drive");
}
public static void main(String args[])
{
Validate_Age(10);
150
System.out.println("rest of the code...");
}
}
Output:

Exception in thread “throw_ex” java.lang.ArithmeticException: Not eligible


to vote and drive
at throw_ex.Validate_Age(throw_ex.java:6)
at throw_ex.main(throw_ex.java:12)

throws clause

❖ The “throws” keyword is used to declare an exception.


❖ This keyword is used to indicate that an exception might occur in the program or method.
Syntax:
type MethodName(Parameter-list) throws exception-list
{
// Body of method
}

Here, exception-list is a comma-separated list of the exceptions that a method can throw.
Example:

//Java program to demonstrate throws keyword


import java.io.*;
class Throws_Ex
{
void TestMethod(int x) throws IOException, ArithmeticException
{
if(x==1)
throw new IOException("IOException Occurred");
else
throw new ArithmeticException("ArithmeticException");
}
}
class Main
{
public static void main(String args[])
{
try
{
Throws_Exobj=new Throws_Ex();
obj.TestMethod(1);
}
catch(Exception ex)
{
System.out.println(ex);
}
}
}

151
Output:
java.io.IOException: IOException occurred

11.10 Creating our own Exception Subclasses


❖ Java allows us to create our own exception class to provide own exception implementation.
❖ These type of exceptions are called user-defined exceptions or custom exceptions.
❖ We can create our own exception simply by extending java Exception class.
Syntax:
class MyException extends Exception
{
}

❖ The Exception class does not define any methods of its own. It does, of course, inherit those
methods provided by Throwable.
❖ Thus, all exceptions, including those that we create, have the methods defined by Throwable
available to them.
Methods Defined by Throwable
Sl. Method Description
No.
1. Throwable Returns a Throwable object that contains a
fillInStackTrace() completed stack trace. This object can be
rethrown.
2. String Returns a localized description of the exception.
getLocalizedMessage()
3. String getMessage() Returns a description of the exception.
4. void printStackTrace() Displays the stack trace.
5. void Sends the stack trace to the specified stream.
printStackTrace(PrintStream
stream)
6. void Sends the stack trace to the specified stream
printStackTrace(PrintWriter
stream)
7. String toString() Returns a String object containing a description of the
exception. This method is called by println() when
outputting a Throwable object.

Example:

// A Class that represents use-defined expception


import java.io.*;
class MyException extends Exception
{
}
public class setText

152
{
public static void main(String args[])
{
try
{
throw new MyException();
}
catch (MyException ex)
{
System.out.println("Exception Caught");
System.out.println(ex.getMessage());
}
}
}

Output:

Exception Caught: null


Exercises:

1. Define exception.
2. Explain the different types of errors in Java
3. What is exception handling?
4. Explain the various types of exception in Java.
5. List out any five built-in exception.
6. Explain multiple catch exception with an example.
7. What is the use of finally block?
8. Explain briefly the methods defined by throwable.
**************************

******************************************************************************
Chapter 12 Multithreading
******************************************************************************
12.1 Definition

❖ The process of executing multiple threads simultaneously is called multithreading.


153
❖ The primary purpose of multithreading is to provide simultaneous execution of two or more
parts of a program to make maximum use of CPU time.
❖ A multithreaded program contains two or more parts that can run concurrently.
❖ It enables programmers to write in a way where multiple activities can proceed simultaneously
within a single application.
12.2 Advantages of Multithreading

❖ The benefits of multithreaded programming are:


• Economical: It is economical as they share the same processor resources. It takes lesser time to
create threads.
• Resource Sharing: It allows the threads to share resources like data, memory, files, etc.
Therefore, an application can have multiple threads within the same address space
• Responsiveness: It increases the responsiveness to the user as it allows the program to continue
running even if a part of it is performing a lengthy operation or is blocked.
• Scalability: It increases parallelism on multiple CPU machines. It enhances the performance of
multi-processor machines.
12.3 Thread

❖ A thread is a lightweight process.


❖ A thread is similar to a program that has a single flow of control. It has a beginning, a body,
and an end, and executes commands sequentially.
❖ In fact, all main programs can be called single-threaded programs. Every program will have at
least one thread.
❖ Threads are extensively used in Java-enabled browsers such as HOTJAVA. These browsers can
download a file to the local computer, display a Web page in the window, outputs another Web
page to a printer and so on.

12.4 Thread Class


❖ Thread class provide constructors and methods to create and perform operations on a thread.
❖ Thread class extends Object class and implements Runnable interface.
Thread Constructors
• Thread(): Allocates a new Thread object
• Thread(Runnable target): Allocates a new Thread object
• Thread(Runnable target, String name): Allocates a new Thread object
• Thread(String name): Allocates a new Thread object
• Thread(ThreadGroup group, Runnable target): Allocates a new Thread object

154
• Thread(ThreadGroup group, Runnable target, String name): Allocates a new Thread
object so that it has target as its run object, has the specified name as its name, and belongs to
the thread group referred to by group
• Thread(ThreadGroup group, Runnable target, String name, long stackSize): Allocates a
new Thread object so that it has target as its run object, has the specified name as its name, and
belongs to the thread group referred to by group, and has the specified stack size
• Thread(ThreadGroup group, String name): CAllocates a new Thread object

Methods of Thread class


1. activeCount()
❖ This method returns an estimate of the number of active threads in the current thread’s thread
group and its subgroups.
Syntax:
public static int activeCount()
2. checkAccess()
❖ This method determines if the currently running thread has permission to modify this thread.
Syntax:
public final void checkAccess()
3. clone()
❖ This method returns a clone if the class of this object is Cloneable.
Syntax:
protected Object clone() throws CloneNotSupportedException
4. currentThread()
❖ This method returns a reference to the currently executing thread object.
Syntax:
public static Thread currentThread()
5. getId()
❖ This method returns the id of the thread.
Syntax:
public long getId()
6. getName()
❖ This method returns the name of the thread.
Syntax:
public final String getName()
7. getPriority()
❖ This method returns the priority of the thread.
155
Syntax:
public final int getPriority()
8. getStackTrace()
❖ This method returns an array of stack trace elements representing the stack dump of this
thread.
Syntax:
public StackTraceElement[] getStackTrace()
9. getState()
❖ This method returns the state of the thread.
Syntax:
public Thread.State getState()
10. interrupt()
❖ This method interrupts the thread.
Syntax:
public void interrupt()
11. interrupted()

❖ This method tests whether the current thread has been interrupted.
Syntax:
public static boolean interrupted()
12. isAlive()
❖ This method tests if the thread is alive.
Syntax:
public final boolean isAlive()
13. isInterrupted()
❖ This method tests whether the thread has been interrupted.
Syntax:
public boolean isInterrupted()
14. join()
❖ This method waits for a thread to die.
Syntax:
public final void join() throws InterruptedException

15. join(long millis)


❖ This method waits at most millis milliseconds for a thread to die.
Syntax:

156
public final void join(long millis) throws InterruptedException
Parameters:
millis - the time to wait in milliseconds

16. resume()
❖ This method is used to resume the suspended thread.
public void resume()
17. run()
❖ This method is used to perform action for a thread.
Syntax:
public void run()
18. start()
❖ This method causes the thread to begin execution; the Java Virtual Machine calls the run
method of the thread.
Syntax:
public void start()
19. sleep(long millis)
❖ This method causes the currently executing thread to sleep (temporarily cease execution) for
the specified number of milliseconds.
Syntax:
public static void sleep(long millis) throws InterruptedException
Parameters:
millis - the length of time to sleep in milliseconds
20. setPriority(int newPriority)
❖ This method changes the priority of the thread.
Syntax:
public final void setPriority(int newPriority)
Parameters:
newPriority - priority to set this thread to
21. setName(String name)
❖ This method changes the name of the thread.
Syntax:
public final void setName(String name)
Parameters:
name - the new name for this thread.
22. stop()
157
This method is used to stop the thread.
Syntax:
public void stop()
23. suspend()
❖ This method is used to suspend the thread.
Syntax:
public void suspend()
24. toString()
❖ This method returns a string representation of the thread, including the thread’s name, priority,
and thread group.
Syntax:
public String toString()
25. yield()
❖ This method causes the currently executing thread object to temporarily pause and allow other
threads to execute.
Syntax:
public static void yield()
12.5 Creating a Thread
❖ There are two ways to create a thread:
i) Extending the Thread class
ii) Implementing the Runnable interface
i) Extending the Thread class
❖ The first way to create a thread is to create a new class that extends Thread class using the
following steps.
1. Declare the class as extending the Thread class.
2. Implement the run() method that is responsible for executing the sequence of code that the
thread will execute.
3. Create a thread object and call the start() method to initiate the thread execution.
Declaring the Class
❖ The Thread class can be extended as follows:

class MyThread extends Thread


{
……………..
……………..
……………..
158
}
Example:
//Java program to create a Thread by extending the Thread class
import java.io.*;
class Multi extends Thread
{
public void run()
{
System.out.println("Thread is running...");
}
public static void main(String args[])
{
Multi t1=new Multi();
t1.start();
}
}
Output:
Thread is running…is running...

ii) Implementing the Runnable interface


❖ A thread can be created by implementing the Runnable interface.
❖ The Runnable interface declares the run() method that is required for implementing threads in
our programs. To do this, we must perform the steps listed below:
1. Declare the class as implementing the Runnable interface.
2. Implement the run() method.
3. Create a thread by defining an object that is instantiated from this “ runnable” class as the target
of the thread.
4. Call the thread’s start() method to run the thread.

❖ The run() method has been inherited by the class MyThread. We have to override this method in
order to implement the code to be executed by our thread. The basic implementation of run() will
look like this:
public void run()
{
……………….
………………. // Thread code here
……………….
}
When we start the new thread, Java calls the thread’s run() method, so it is the run() where all of
the action takes place.
Example:

159
// Java program to implement the Runnable interface
import java.io.*;
class Multi implements Runnable
{
public void run()
{
System.out.println("Thread is running...");
}
public static void main(String args[])
{
Multi m1=new Multi();
Thread t1 =new Thread(m1);
t1.start();
}
}
Output:
Thread is running...
12.6 Starting New Thread

❖ The start() method of thread class is used to begin the execution of thread. The result of this
method is two threads that are running concurrently: the current thread (which returns from the
call to the start method) and the other thread (which executes its run method).
❖ The start thread performs the following tasks:
• It stats a new thread
• The thread moves from New State to Runnable state.
• When the thread gets a chance to execute, its target run() method will run.
❖ To actually create and run an instance of our thread class, we must write the following:
MyThread Th=new MyThread();
Th.start();
The first line instantiates a new object of class MyThread.
The second line calls the start() method causing the thread to move into a runnable state.
Example:
// Creating threads using the Thread class
// File Name : ThreadClassDemo.java
import java.io.*;
public class ThreadClassDemo
{
public static void main(String [] args)
{
Runnable hello = new DisplayMessage();
Thread thread1 = new Thread(hello);
thread1.setDaemon(true);
thread1.setName("hello");
System.out.println("Starting hello thread...");
160
thread1.start();
Runnable bye = new DisplayMessage("Goodbye");
Thread thread2 = new Thread(bye);
thread2.setPriority(Thread.MIN_PRIORITY);
thread2.setDaemon(true);
System.out.println("Starting goodbye thread...");
thread2.start();
System.out.println("Starting thread3...");
Thread thread3 = new GuessANumber(27);
thread3.start();
try
{
thread3.join();
}
catch (InterruptedException e)
{
System.out.println("Thread interrupted.");
}
System.out.println("Starting thread4...");
Thread thread4 = new GuessANumber(75);
thread4.start();
System.out.println("main() is ending...");
}
}

Output:
Starting hello thread...
Starting goodbye thread...
Hello
Hello
Hello
Hello
Hello
Hello
Goodbye
Goodbye
Goodbye
Goodbye
Goodbye
.......
12.7 Stopping and Blocking a Thread
Stopping a Thread
❖ The stop() method is used to stop the thread from running further.

Example:
MyThread.stop()

161
This method causes the thread to move to the dead state. A thread will also move to the dead state
automatically when it reaches the end of its method. The stop() method may be used when the
premature death of the thread is desired.
Blocking a Thread
❖ A thread can be temporarily suspended or blocked from entering into the runnable and
subsequently running state by using either of the following thread methods:
sleep() // blocked for a specified time
suspend() // blocked until further orders
wait() // blocked until certain condition occurs
These methods cause the thread to go into the blocked (or non-runnable) state. The thread will
return to the runnable state when the specified time is elapsed in the case of sleep(), the resume()
method is invoked in the case of suspend(), and the notify() method is called in the case of
wait().
12.8 Life Cycle of a Thread

❖ A thread moves through several states from its creation to termination. During the lifetime of a
thread, there are many states it can enter. They include:

• New
• Runnable
• Running
• Blocked (Waiting)
• Dead (Terminated)
❖ A thread is always in one of these five states. It can move from one state to another via a variety
of ways as shown in Figure 12.1.

Figure 12.1: State transition diagram of a thread

1) New (Newborn) State

❖ A new thread begins its life cycle in the new state. It remains in this state until the program
starts the thread. It is also referred to as a born thread.

2) Runnable State

162
❖ The runnable state means that the thread is ready for execution and is waiting for the availability
of the processor. That is, the thread has joined the queue of threads that are waiting for
execution. If all threads have equal priority, then they are given time slots for execution in round
robin fashion i.e., first-come, first-serve manner. This process of assigning time to threads is
known as time-slicing.

3) Running State

❖ Running state means that the processor has given its time to the thread for its execution. A
thread can come into running state only from runnable state.

4) Blocked (Waiting) State

❖ A thread is said to be blocked when it is prevented from entering into the runnable state and
subsequently the running state. This happens when the thread is suspended, sleeping, or waiting
in order to satisfy certain requirements.

5) Dead (Terminated) State

❖ A runnable thread enters the terminated state when it completes its task or otherwise terminates.

12.9 Thread Priority


❖ Priority means the number of resources allocated to the particular thread.
❖ Every thread created in JVM is assigned with a priority.
❖ The priority range is between 1 and 10.
1. 1 is called minimum priority
2. 5 is called normal priority
3. 10 is called maximum priority

❖ The default priority of the main thread is 5, child thread will take the priority that is equal to its
parent thread priority.
❖ We can change the priority of any thread that it may be the main thread or user-defined thread.
❖ It is recommended to change the priority by using constants available in the Thread class like
follows:
1. Thread.MIN_PRIORITY;
2. Thread.NORM_PRIORITY;
3. Thread.MAX_PRIORITY;
❖ Threads are assigned priorities, based on that the thread scheduler can use to determine how the
thread will be scheduled.
❖ The thread scheduler can use thread priorities to determine which thread gets to run.

setPriority() method
❖ The setPriority() method is used to set the thread’s priority.

163
❖ The general form is:
ThreadName.setPriority(int newPriority);
Note: The newPriority value range should between 1 to 10 else it leads to exception
java.lang.illegalArgumentException.
Example:

t.setPriority(7); //Valid
t.setPriority(Thread.NORM_PRIORITY+2); //Valid(recommended)
getPriority() method
❖ The getPriority() method is used to obtain the current priority setting.
❖ The general form is:
ThreadName.getPriority();
Example:
// Java program using priority in threads
import java.io.*;
class TestMultiPriority1 extends Thread
{
public void run()
{
System.out.println("Running thread name is:"+Thread.currentThread().getName());
System.out.println("Running thread priority is:"+Thread.currentThread().getPriority());
}
public static void main(String args[])
{
TestMultiPriority1 m1=new TestMultiPriority1();
TestMultiPriority1 m2=new TestMultiPriority1();
m1.setPriority(Thread.MIN_PRIORITY);
m2.setPriority(Thread.MAX_PRIORITY);
m1.start();
m2.start();
}
}
Output:
Running thread name is : Thread-0
Running thread priority is: 10
Running thread name is : Thread-1
Running thread priority is: 1
12.10 Synchronization
❖ The process of allowing multiple threads to modify an object in a sequence is called
synchronization.
❖ Synchronization in Java is the capability to control the access of multiple threads to any shared
resource.

164
❖ Thread Synchronization is a process of allowing only one thread to use the object when
multiple threads are trying to use the particular object at the same time.
❖ A thread can be synchronized by using the synchronized keyword as a modifier in the method
declaration.
❖ The general form of the synchronized statement is
synchronized(object)
{
//Statements to be synchronized
}

Here, object is a reference to the objet being synchronized. If we want to synchronize only a
single statement, then the curly braces are not needed. A synchronized block ensures that a call
to a method that is a member of object occurs only after the current thread has successfully
entered object’s monitor.
Example:
// Java program for synchronization
// SyncDemo.java
import java.io.*;
import java.lang.*;
class ThreadX extends Thread
{
Thread s;
public void call(Thread name) throws IOException
{
s=name;
s.start();
}
public void run()
{
try
{
caller(s);
}
catch (Exception obj)
{
}
}
synchronized void caller(Thread r) throws Exception
{
System.out.println("Good Morning");
System.out.println("Good Afternoon");
r.sleep(2000);
System.out.println("Good Evening");
}
}

class SyncDemo
{
public static void main(String args[]) throws Exception
165
{
ThreadX one=new ThreadX();
Thread x= new Thread(one);
Thread y=new Thread(one);
Thread z=new Thread(one);
one.call(x);
one.call(y);
one.call(z);
}
}
Output:
Good Morning
Good Afternoon
Gooed Evening
Good Morning
Good Afternoon
Gooed Evening
Good Morning
Good Afternoon
Gooed Evening
12.11 Interthread Communication
❖ Interthread communication in Java is a technique through which multiple threads
communicate with each other.
❖ It provides an efficient way through which more than one thread communicate with each other
by reducing CPU idle time.
❖ When more than one threads are executing simultaneously, sometimes they need to communicate
with each other by exchanging information with each other. A thread exchanges information
before or after it changes its state.
❖ Interthread communication in Java can be achieved by using three methods provided by Object
class of java.lang package. They are:
1. wait()
2. notify()
3. notifyAll()
❖ These methods can be called only from within a synchronized method or synchronized block of
code otherwise, an exception named IllegalMonitorStateException is thrown.
• wait(): This method tells the calling thread to give up the monitor and go to sleep until some
other thread enters the same monitor and calls notify( ).
• notify(): This method wakes up the first thread that called wait( ) on the same object.
• notifyAll(): This method wakes up all the threads that called wait( ) on the same object The
highest priority thread will run first.
❖ These methods are declared within Object, as shown here:

166
final void wait() throws InterruptedException
final void notify()
final void notifyAll()
Example:

// Java program to implement Interthread Communication


import java.io.*;
class Chat
{
boolean flag = false;
public synchronized void Question(String msg)
{
if (flag)
{
try
{
wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
System.out.println(msg);
flag = true;
notify();
}
public synchronized void Answer(String msg)
{
if (!flag)
{
try
{
wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
System.out.println(msg);
flag = false;
notify();
}
}
class T1 implements Runnable

167
{
char m;
String[] s1 = { "Hi", "How are you ?", "I am also doing fine!" };
public T1(Chat m1)
{
this.m = m1;
new Thread(this, "Question").start();
}
public void run()
{
for (int i = 0; i < s1.length; i++)
{
m.Question(s1[i]);
}
}
}
class T2 implements Runnable
{
Chat m;
String[] s2 = { "Hi", "I am good, what about you?", "Great!" };
public T2(Chat m2)
{
this.m = m2;
new Thread(this, "Answer").start();
}
public void run()
{
for (int i = 0; i < s2.length; i++)
{
m.Answer(s2[i]);
}
}
}
public class TestThread
{
public static void main(String args[])
{
Chat m = new Chat();
new T1(m);
new T2(m);
}
}

Output:
Hi
Hi
168
How are you ?
I am good, what about you?
I am also doing fine!
Great!
12.12 Deadlock
❖ Deadlock describes a situation where two or more threads are blocked forever, waiting for
each other.
❖ Deadlock occurs when multiple threads need the same locks but obtain them in different order.
❖ A Java multithreaded program may suffer from the deadlock condition because the
synchronized keyword causes the executing thread to block while waiting for the lock, or
monitor, associated with the specified object.
Example:

// Java program using Deadlock concept


// TestThread.java
import java.io.*;
public class TestThread
{
public static Object Lock1 = new Object();
public static Object Lock2 = new Object();
public static void main(String args[])
{
ThreadDemo1 T1 = new ThreadDemo1();
ThreadDemo2 T2 = new ThreadDemo2();
T1.start();
T2.start();
}
private static class ThreadDemo1 extends Thread
{
public void run()
{
synchronized (Lock1)
{
System.out.println("Thread 1: Holding lock 1...");
try
{
Thread.sleep(10);
}
catch (InterruptedException e)
{}
System.out.println("Thread 1: Waiting for lock 2...");
synchronized (Lock2)
{
System.out.println("Thread 1: Holding lock 1 & 2...");

169
}
}
}
}
private static class ThreadDemo2 extends Thread
{
public void run()
{
synchronized (Lock2)
{
System.out.println("Thread 2: Holding lock 2...");
try
{
Thread.sleep(10);
}
catch (InterruptedException e)
{}
System.out.println("Thread 2: Waiting for lock 1...");
synchronized (Lock1)
{
System.out.println("Thread 2: Holding lock 1 & 2...");
}
}
}
}
}
Output:
Thread 1: Holding lock 1...
Thread 2: Holding lock 2...
Thread 1: Waiting for lock 2...
Thread 2: Waiting for lock 1...
12.13 Thread Control
Suspending, Resuming, and Stopping Threads
❖ The suspend( ), resume( ), and stop( ) methods defined by the Thread class are used to pause,
restart, and stop the execution of a thread.
❖ The functions of Suspend, Resume and Stop a thread is performed using Boolean-type flags in
a multithreading program. These flags are used to store the current status of the thread.
1. If the suspend flag is set to true then run() will suspend the execution of the currently
running thread.
2. If the resume flag is set to true then run() will resume the execution of the suspended
thread.
3. If the stop flag is set to true then a thread will get terminated.
❖ There are various static methods which we can use on thread objects to control their behavior.
Following table lists down those methods –
Sl. No Method Description
170
public void suspend() This method puts a thread in the suspended state and can
1
be resumed using resume() method.
2 public void stop() This method stops a thread completely.
This method resumes a thread, which was suspended
3 public void resume()
using suspend() method.
Causes the current thread to wait until another thread
4 public void wait()
invokes the notify().
Wakes up a single thread that is waiting on this object's
5 public void notify()
monitor.

Example:
//Java program to implement suspend, resume and stop operations
import java.io.*;
class temp implements Runnable
{
Thread Th;
boolean suspend_flag, stop_flag;
temp(String tN)
{
Th=new Thread(this, tN);
suspend_flag=false;
stop_flag=false;
Th.start();
}
public void run()
{
try
{
int j=1;
while(++j<20)
{
synchronized(this)
{
while(suspend_flag)
{
wait();
}
if(stop_flag)
{
break;
}
}
}
}
catch(InterruptedException IE)
{
System.out.println("Thread Interrupted");
}
}
synchronized void my_suspend()
{
suspend_flag=true;
171
}
synchronized void my_resume()
{
suspend_flag=false;
notify();
}
synchronized void my_stop()
{
suspend_flag=false;
stop_flag=true;
notify();
}
}
public class SRS
{
public static void main(String args[])
{
try
{
temp t1=new temp("SRS");
System.out.println("Thread SRS is Created and Started");
Thread.sleep(2000);
t1.my_suspend();
System.out.println("Thread SRS is Suspended");
Thread.sleep(2000);
t1.my_resume();
System.out.println("Thread SRS is Resumed");
Thread.sleep(2000);
t1.my_suspend();
System.out.println("Thread SRS is Suspended");
Thread.sleep(2000);
t1.my_resume();
System.out.println("Thread SRS is Resumed");
Thread.sleep(2000);
t1.my_stop();
System.out.println("Thread SRS is Stopped");
}
catch(InterruptedException IE)
{
System.out.println("Generated interrupted exception");
}
}
}
Output:
Thread SRS is Created and Started
Thread SRS is Suspended
Thread SRS is Resumed
Thread SRS is Suspended
Thread SRS is Resumed
Thread SRS is Stopped
12.14 Differences between a process and a thread
172
Sl. No. Process Thread
1. Process means any program in Thread means segment of a process.
execution.
2. Process takes more time for creation. Thread takes less time for creation.
3. Process takes more time to terminate. Thread takes less time to terminate.
4. Processes require more time for context Threads require less time for context
switching. switching.
5. Communication between processes Communication between threads requires
requires more time than between less time than between processes.
threads.
6. Process consumes more resources. Thread consumes less resources.
7. Process is called heavy weight process. Thread is called light weight process.
8. Processes have independent data and A thread shares the data segment, code
code segments. segment, files etc. with its peer threads.
9. If one process is blocked then it will not If a user level thread gets blocked, all of its
affect the execution of other processes. peer threads also get blocked.
10. Process has its own Process Control Thread has Parents’ PCB, its own Thread
Block, Stack and Address Space. Control Block and Stack and common
Address Space.

Exercises:
1. Define Thread.
2. What is Multithreading?
3. Explain the various methods of Thread class.
4. Explain the methods to create a thread.
5. Explain Thread Life Cycle.
6. List out the Thread priorities.
7. Define synchronization.
8. Discuss about synchronization in detail.
9. Discuss in detail about Inter-thread Communication.
10. Define Deadlock.
11. Explain thread controlling methods.
12. Diffrentiate between a process and a thread.
*****************************

********************************************************************************
Chapter 13 I/O Streams
********************************************************************************
13.1 Introduction

173
❖ An I/O Stream represents an input source or an output destination. A stream can represent many
different kinds of sources and destinations, including disk files, devices, other programs, and
memory arrays.
❖ Streams support many different kinds of data, including simple bytes, primitive data types,
localized characters, and objects. Some streams simply pass on data; others manipulate and
transform the data in useful ways.
❖ A stream is a sequence of data.
❖ A program uses an input stream to read data from a source, one item at a time.
❖ A program uses an output stream to write data to a destination, one item at time:

13.2 Concept of Streams


❖ In Java, a stream is composed of bytes. It's called a stream because it is like a stream of water
that continues to flow.
❖ Java streams are classified into two basic types, namely, InputStream and OutputStream. The
InputStream is used to read data from a source. The OutputStream is used for writing data to
a destination.
13.3 Stream Classes
❖ The java.io package contains a large number of stream classes that provide capabilities for
processing all types of data. These classes may be categorized into two groups based on the data
type in which they operate.
1. Byte stream classes that provide support for handling I/O operations on bytes.
2. Character stream classes that provide support for managing I/O operations on characters.
13.4 Byte Stream Classes
❖ Byte stream classes have been designed to provide functional features for creating and
manipulating streams and files for reading and writing bytes.
❖ A byte stream can be used with any type of object, including binary data. Since the streams are
unidirectional, they can transmit bytes in only one direction and therefore Java provides two
kinds of byte stream classes: InputStream class and OutputStream class.
i) InputStream Class
❖ The InputStream class is used to read data from a source; it may be a file, an array, peripheral
device. The InputStream class defines methods for performing input functions such as
• Reading bytes
• Closing streams
• Marking positions in streams
• Skipping ahead in a stream
• Finding the number of bytes in a stream

174
❖ Table 13.1 gives a brief description of all the methods provided by the InputStream class.

Method Description
int available() Returns the number of bytes of input currently available for reading.
void close() Closes the input source. Further read attempts will generate an
IOException.
Places a mark at the current point in the input stream that will
void mark(int numBytes) remain valid until numBytes bytes are read.
Returns true if mark()/reset() are supported by the invoking
Boolean markSupported() stream.
Returns an integer representation of the next available byte of input.
int read() –1 is returned when the end of the file is encountered.
Attempts to read up to buffer.length bytes into buffer and returns the
int read(byte buffer[]) actual number of bytes that were successfully read. –1 is returned
when the end of the file is encountered.
int read(byte buffer[], int Attempts to read up to numBytes bytes into buffer starting at
offset, int numBytes) buffer[offset], returning the number of bytes successfully read. –1 is
returned when the end of the file is encountered.
Resets the input pointer to the previously set mark.
void reset()
Ignores (that is, skips) numBytes bytes of input, returning the
long skip(long numBytes) number of bytes actually ignored.
Table 13.1: The methods defined by InputStream

ii) OutputStream Class


❖ The OutputStream class is used for writing data to a destination.
❖ The several subclasses of the OutputStream can be used for performing the output operations.
❖ The OutputStream includes methods that are designed to perform the following tasks:
• Writing bytes
• Closing streams
• Flushing streams
❖ Table 13.2 gives a brief description of all the methods defined by the OutputStream class.

Method Description
void close( ) Closes the output stream. Further write attempts will generate an
IOException.
void flush( ) Finalizes the output state so that any buffers are cleared. That is, it
flushes the output buffers.
void write(int b) Writes a single byte to an output stream. The parameter is an int,
which allows us to call write() with expressions without having to
cast them back to byte.
void write(byte buffer[ ]) Writes a complete array of bytes to an output stream.
void write(byte buffer[ ], int Writes a sub range of numBytes bytes from the array buffer,
offset, int numBytes) beginning at buffer[offset].
Table 13.2: The methods defined by OutputStream

ByteArrayInputStream

175
❖ ByteArrayInputStream is an implementation of an input stream that uses a byte array as the
source. In this stream, the data is read from a byte array.
❖ This class has two constructors, each of which requires a byte array to provide the data source:
ByteArrayInputStream(byte array[])
ByteArrayInputStream(byte array[], int start, int numBytes)
Here, array is the input source. The second constructor creates an InputStream from a subset
of our byte array that begins with the character at the index specified by start and is numBytes
long.

Methods

Method Description
int available() It is used to return the number of remaining bytes that can
be read from the input stream.
int read() It is used to read the next byte of data from the input stream.
int read(byte[] ary, int off, int len) It is used to read up to len bytes of data from an array of
bytes in the input stream.
boolean markSupported() It is used to test the input stream for mark and reset method.
long skip(long x) It is used to skip the x bytes of input from the input stream.
void mark(int readAheadLimit) It is used to set the current marked position in the stream.
void reset() It is used to reset the buffer of a byte array.
void close() It is used for closing a ByteArrayInputStream.

Example:

//Java Program using ByteArrayInputStream Class


import java.io.*;
public class ReadExample
{
public static void main(String args[]) throws IOException
{
byte[] buf = { 35, 36, 37, 38 };
// Create the new byte array input stream
ByteArrayInputStream byt = new ByteArrayInputStream(buf);
int k = 0;
while ((k = byt.read()) != -1)
{
//Conversion of a byte into character
char ch = (char) k;
System.out.println("ASCII value of Character is:" + k + "; Special character is: " + ch);
}
}
}
Output:

176
ASCII value of Character is:35; Special character is: #
ASCII value of Character is:36; Special character is: $
ASCII value of Character is:37; Special character is: %
ASCII value of Character is:38; Special character is: &
ByteArrayOutputStream
❖ The ByteArrayOutputStream class is used to write common data into multiple files. In this
stream, the data is written into a byte array which can be written to multiple streams later.
❖ The ByteArrayOutputStream holds a copy of data and forwards it to multiple streams.
❖ ByteArrayOutputStream has two constructors, shown here:
ByteArrayOutputStream()
ByteArrayOutputStream(int numBytes)
In the first form, a buffer of 32 bytes is created. In the second, a buffer is created with a size
equal to that specified by numBytes. The buffer size will be increased automatically, if needed.
Methods

Method Description
int size() It is used to returns the current size of a buffer.
byte[] toByteArray() It is used to create a newly allocated byte array.
String toString() It is used for converting the content into a string decoding
bytes using a platform default character set.
String toString(String charsetName) It is used for converting the content into a string decoding
bytes using a specified charsetName.
void write(int b) It is used for writing the byte specified to the byte array
output stream.
void write(byte[] b, int off, int len It is used for writing len bytes from specified byte array
starting from the offset off to the byte array output stream.
void writeTo(OutputStream out) It is used for writing the complete content of a byte array
output stream to the specified output stream.
void reset() It is used to reset the count field of a byte array output stream
to zero value.
void close() It is used to close the ByteArrayOutputStream.

Example:

//Java Program using ByteArrayOutputStream Class


import java.io.*;
public class DataStreamExample
{
public static void main(String args[])throws Exception
{
FileOutputStream fout1=new FileOutputStream("D:\f1.txt");

177
FileOutputStream fout2=new FileOutputStream("D:\f2.txt");
ByteArrayOutputStream bout=new ByteArrayOutputStream();
bout.write(65);
bout.writeTo(fout1);
bout.writeTo(fout2);
bout.flush();
bout.close();//has no effect
System.out.println("Success...");
}
}
Output:
Success...
f1.txt:
A
f2.txt:
A
Buffered Byte Streams
❖ The buffered byte stream classes are BufferedInputStream and BufferedOutputStream.
PushbackInputStream also implements a buffered stream.
i) BufferedInputStream

❖ The BufferedInputStream class is used to read information from stream.


❖ It internally uses buffer mechanism to make the performance fast.
❖ BufferedInputStream has two constructors:

BufferedInputStream(InputStream inputStream)
BufferedInputStream(InputStream inputStream, int bufSize)

The first form creates a buffered stream using a default buffer size. In the second, the size of
the buffer is passed in bufSize.

Methods

Method Description
int available() It returns an estimate number of bytes that can be read from the
input stream without blocking by the next invocation method for
the input stream.
int read() It read the next byte of data from the input stream.

178
int read(byte[] b, int off, int ln) It read the bytes from the specified byte-input stream into a
specified byte array, starting with the given offset.
void close() It closes the input stream and releases any of the system
resources associated with the stream.
void reset() It repositions the stream at a position the mark method was last
called on this input stream.
void mark(int readlimit) It sees the general contract of the mark method for the input
stream.
long skip(long x) It skips over and discards x bytes of data from the input stream.
boolean markSupported() It tests for the input stream to support the mark and reset
methods.

Example:

//Java Program using BufferedInputStream Class


import java.io.*;
public class BufferedInputStreamExample
{
public static void main(String args[])
{
try
{
FileInputStream fin=new FileInputStream("D:\testout.txt");
BufferedInputStream bin=new BufferedInputStream(fin);
int i;
while((i=bin.read())!=-1)
{
System.out.print((char)i);
}
bin.close();
fin.close();
}
catch(Exception e)
{
System.out.println(e);
}
}
}
Here, we are assuming that we have following data in "testout.txt" file:
Welcome
Output:
Welcome
ii) BufferedOutputStream
❖ The BufferedOutputStream class is used for buffering an output stream.
❖ It internally uses buffer to store data.
❖ It adds more efficiency than to write data directly into a stream. So, it makes the performance
fast.
179
❖ BufferedOutputStream has two constructors:
BufferedOutputStream(OutputStream outputStream)
BufferedOutputStream(OutputStream outputStream, int bufSize)
The first form creates a buffered stream using a buffer of 512 bytes. In the second form, the
size of the buffer is passed in bufSize.
Methods
Method Description
void write(int b) It writes the specified byte to the buffered output stream.
void write(byte[] b, int off, int len) It write the bytes from the specified byte-input stream into
a specified byte array, starting with the given offset
void flush() It flushes the buffered output stream.

Example:
//Java Program using BufferedOutputStream
import java.io.*;
public class BufferedOutputStreamExample
{
public static void main(String args[]) throws Exception
{
FileOutputStream fout=new FileOutputStream("D:\testout.txt");
BufferedOutputStream bout=new BufferedOutputStream(fout);
String S="Welcome to Java";
byte b[]=s.getBytes();
bout.write(b);
bout.flush();
bout.close();
fout.close();
System.out.println("Success");
}
}
Output:
Success
testout.txt
Welcome to Java

SequenceInputStream

❖ The SequenceInputStream class is used to read data from multiple streams.


❖ It reads data sequentially (one by one). It has the following constructors:
SequenceInputStream(InputStream s1, InputStream s2)
SequenceInputStream(Enumeration e)

180
The first form creates a new input stream by reading the data of two input stream in order, first
s1 and then s2.
The second form creates a new input stream by reading the data of an enumeration whose type
is InputStream.

Methods

Method Description
int read() It is used to read the next byte of data from the input
stream.
int read(byte[] ary, int off, int len) It is used to read len bytes of data from the input stream
into the array of bytes.
int available() It is used to return the maximum number of byte that can
be read from an input stream.
void close() It is used to close the input stream.

Example:
//Java Program to implement SequenceInputStream
import java.io.*;
class InputStreamExample
{
public static void main(String args[]) throws Exception
{
FileInputStream input1=new FileInputStream("D:\testin.txt");
FileInputStream input2=new FileInputStream("D:\testout.txt");
SequenceInputStream inst=new SequenceInputStream(input1, input2);
int j;
while((j=inst.read())!=-1)
{
System.out.print((char)j);
}
inst.close();
input1.close();
input2.close();
}
}

testin.txt:
Welcome to Java Programming.
testout.txt:
It is an example of Java SequenceInputStream class.
Output:

181
Welcome to Java Programming. It is an example of Java SequenceInputStream class.
PrintStream
❖ The PrintStream class provides methods to write data to another stream.
❖ The PrintStream class automatically flushes the data so there is no need to call flush() method.
❖ It has the following constructors:
PrintStream(OutputStream outputStream)
PrintStream(OutputStream outputStream, boolean flushOnNewline)
where flushOnNewline controls whether Java flushes the output stream every time a newline
(\n) character is output. If flushOnNewline is true, flushing automatically takes place. If it is
false, flushing is not automatic. The first constructor does not automatically flush.

❖ Java’s PrintStream objects support the print() and println() methods for all types, including
Object. If an argument is not a simple type, the PrintStream methods will call the object’s
toString() method and then print the result.
Example:

//Java Program using PrintStream Class


import java.io.*;
public class PrintStreamTest
{
public static void main(String args[]) throws Exception
{
FileOutputStream fout=new FileOutputStream("D:\testout.txt ");
PrintStream pout=new PrintStream(fout);
pout.println(2018);
pout.println("Hello Java");
pout.println("Welcome to Java");
pout.close();
fout.close();
System.out.println("Success");
}
}
Output:
Success

The content of a text file testout.txt is set with the below data
2021
Hello Java
Welcome to Java
13.5 Character Stream Classes
❖ Character streams can be used to read and write 16-bit Unicode characters. There are two kinds
of character stream classes, namely, Reader stream classes Writer stream classes.

182
i) Reader Stream Classes
❖ Reader stream classes are designed to read character from the files. Reader class is the base
class for all other classes.
❖ It has the following constructors:
Reader()
Reader(Object lock)
The first form creates a new character-stream reader whose critical sections will synchronize
on the reader itself.
The second form creates a new character-stream reader whose critical sections will synchronize
on the given object.

❖ Table 13.3 lists the methods in the Reader class. All of the methods in this class will throw an
IOException on error conditions.
Method Description
abstract void close() Closes the input source. Further read attempts will generate
an IOException.
void mark(int numChars) Places a mark at the current point in the input stream that will
remain valid until numChars characters are read.
boolean markSupported() Returns true if mark()/reset() are supported on this stream.
int read() Returns an integer representation of the next available
character from the invoking input stream. –1 is returned when
the end of the file is encountered.
int read(char buffer[]) Attempts to read up to buffer.length characters into buffer and
returns the actual number of characters that were successfully
read. –1 is returned when the end of the file is encountered.
abstract int read(char buffer[], Attempts to read up to numChars characters into buffer
int offset, int numChars) starting at buffer[offset], returning the number of characters
successfully read. –1 is returned when the end of the file is
encountered.
boolean ready() Returns true if the next input request will not wait.
Otherwise, it returns false.
void reset() Resets the input pointer to the previously set mark.
long skip(long numChars) Skips over numChars characters of input, returning the
number of characters actually skipped.
Table 13.3: The Methods Defined by Reader
Example:

//Java Program to implement Reader class


import java.io.*;
public class ReaderExample
{
public static void main(String args[])
{
try
183
{
Reader reader = new FileReader("file.txt");
int data = reader.read();
while (data != -1)
{
System.out.print((char) data);
data = reader.read();
}
reader.close();
}
catch (Exception ex)
{
System.out.println(ex.getMessage());
}
}
}

file.txt:
I love my country
Output:
I love my country
ii) Writer Stream Classes
❖ The Writer stream classes are designed to write characters.
❖ The Writer is an abstract class that defines streaming character output.
❖ It has the following constructors:
Writer()
Writer(Object lock)
The first form creates a new character-stream writer whose critical sections will synchronize on
the writer itself.
The second form creates a new character-stream writer whose critical sections will synchronize
on the given object.

❖ Table 13.4 lists the methods in the Writer class. All of the methods in this class return a void
value and throw an IOException in the case of errors.
Method Description
abstract void close() Closes the output stream. Further write attempts will
generate an IOException.
abstract void flush() Finalizes the output state so that any buffers are cleared.
That is, it flushes the output buffers.
void write(int ch) Writes a single character to the invoking output stream.
void write(char buffer[]) Writes a complete array of characters to the invoking output
stream.
184
abstract void write(char buffer[], Writes a subrange of numChars characters from the array
int offset, int numChars) buffer, beginning at buffer[offset] to the invoking output
stream.
void write(String str) Writes str to the invoking output stream.
void write(String str, int offset, Writes a subrange of numChars characters from the array
int numChars) str, beginning at the specified offset.
Table 13.4: The Methods Defined by Writer
Example:

//Java Program to implement Writer Class


import java.io.*;
public class WriterExample
{
public static void main(String args[])
{
try
{
Writer w = new FileWriter("output.txt");
String content = "I love my country";
w.write(content);
w.close();
System.out.println("Done");
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
Output:
Done
output.txt:
I love my country
CharArrayReader
❖ The CharArrayReader class is used to read character array as a reader (stream).
❖ This class has two constructors, each of which requires a character array to provide the data
source:
CharArrayReader(char array[])
CharArrayReader(char array[], int start, int numChars)
Here, array is the input source. The second constructor creates a Reader from a subset of our
character array that begins with the character at the index specified by start and is numChars
long.
Methods
Method Description

185
int read() It is used to read a single character
int read(char[] b, int off, int len) It is used to read characters into the portion of an array.
boolean ready() It is used to tell whether the stream is ready to read.
boolean markSupported() It is used to tell whether the stream supports mark() operation.
long skip(long n) It is used to skip the character in the input stream.
void mark(int readAheadLimit) It is used to mark the present position in the stream.
void reset() It is used to reset the stream to a most recent mark.
void close() It is used to closes the stream.

Example:
//Java Program to implement CharArrayReader
import java.io.*;
public class CharArrayExample
{
public static void main(String args[]) throws Exception
{
char[] ary = { 'j', 'a', 'v', 'a', 't', 'p', 'o', 'i', 'n', 't' };
CharArrayReader reader = new CharArrayReader(ary);
int k = 0;
// Read until the end of a file
while ((k = reader.read()) != -1)
{
char ch = (char) k;
System.out.print(ch + " : ");
System.out.println(k);
}
}
}
Output:
j : 106
a : 97
v : 118
a : 97
t : 116
p : 112
o : 111
i : 105
n : 110
t : 116

CharArrayWriter
❖ The CharArrayWriter class can be used to write common data to multiple files. This class
inherits Writer class.
❖ CharArrayWriter has two constructors, shown here:

186
CharArrayWriter()
CharArrayWriter(int numChars)
In the first form, a buffer with a default size is created. In the second, a buffer is created with a
size equal to that specified by numChars. The buffer size will be increased automatically, if
needed.
Methods

Method Description
int size() It is used to return the current size of the buffer.
char[] toCharArray() It is used to return the copy of an input data.
String toString() It is used for converting an input data to a string.
CharArrayWriter append(char c) It is used to append the specified character to the
writer.
CharArrayWriter append(CharSequence csq) It is used to append the specified character
sequence to the writer.
CharArrayWriter append(CharSequence csq, It is used to append the subsequence of a
int start, int end) specified character to the writer.
void write(int c) It is used to write a character to the buffer.
void write(char[] c, int off, int len) It is used to write a character to the buffer.
void write(String str, int off, int len) It is used to write a portion of string to the buffer.
void writeTo(Writer out) It is used to write the content of buffer to
different character stream.
void flush() It is used to flush the stream.
void reset() It is used to reset the buffer.
void close() It is used to close the stream.

Example:
//Java Program to implement CharArrayWriter
import java.io.*;
public class CharArrayWriterExample
{
public static void main(String args[]) throws Exception
{
CharArrayWriter out=new CharArrayWriter();
out.write("Welcome to Java");
FileWriter f1=new FileWriter("D:\a.txt");
FileWriter f2=new FileWriter("D:\b.txt");
FileWriter f3=new FileWriter("D:\c.txt");
FileWriter f4=new FileWriter("D:\d.txt");
out.writeTo(f1);
out.writeTo(f2);
out.writeTo(f3);
out.writeTo(f4);
f1.close();
187
f2.close();
f3.close();
f4.close();
System.out.println("Success...");
}
}
Output:
Success...

After executing the program, we can see that all files have common data: Welcome to Java

a.txt:

Welcome to Java
b.txt:
Welcome to Java
c.txt:
Welcome to Java
d.txt:
Welcome to Java
BufferedReader

❖ The BufferedReader class is used to read the text from a character-based input stream. It can
be used to read data line by line by readLine() method.
❖ It has two constructors:
BufferedReader(Reader inputStream)
BufferedReader(Reader inputStream, int bufSize)
The first form creates a buffered character stream using a default buffer size.
In the second, the size of the buffer is passed in bufSize.

Methods

Method Description
int read() It is used for reading a single character.
int read(char[] cbuf, int off, int len) It is used for reading characters into a portion of an array.
boolean markSupported() It is used to test the input stream support for the mark and
reset method.
String readLine() It is used for reading a line of text.
boolean ready() It is used to test whether the input stream is ready to be read.

188
long skip(long n) It is used for skipping the characters.
void reset() It repositions the stream at a position the mark method was
last called on this input stream.
void mark(int readAheadLimit) It is used for marking the present position in a stream.
void close() It closes the input stream and releases any of the system
resources associated with the stream.

Example:
//Java Program using BufferedReader Class
import java.io.*;
public class BufferedReaderExample
{
public static void main(String args[]) throws Exception
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter your name");
String name=br.readLine();
System.out.println("Welcome "+name);
}
}
Output:
Enter your name
Ashok
Welcome Ashok
BufferedWriter
❖ The BufferedWriter class is used to provide buffering for Writer instances.
❖ Using a BufferedWriter can increase performance by reducing the number of times data is
actually physically written to the output stream.
❖ A BufferedWriter has these two constructors:
BufferedWriter(Writer outputStream)
BufferedWriter(Writer outputStream, int bufSize)
The first form creates a buffered stream using a buffer with a default size.
In the second, the size of the buffer is passed in bufSize.

Methods

Method Description
void newLine() It is used to add a new line by writing a line separator.
void write(int c) It is used to write a single character.
void write(char[] cbuf, int off, int len) It is used to write a portion of an array of characters.
void write(String s, int off, int len) It is used to write a portion of a string.
void flush() It is used to flush the input stream.
void close() It is used to close the input stream

189
Example:

//Java Program to implement BufferedWriter Class


import java.io.*;
public class BufferedWriterExample
{
public static void main(String[] args) throws Exception
{
FileWriter writer = new FileWriter("D:\\Sample.txt");
BufferedWriter buffer = new BufferedWriter(writer);
buffer.write("Welcome to Java Programming.");
buffer.close();
System.out.println("Success");
}
}
Output:
Success
Sample.txt:
Welcome to Java Programming.
PrintWriter
❖ The PrintWriter class is the implementation of Writer class.
❖ It is used to print the formatted representation of objects to the text-output stream.
❖ PrintWriterhas four constructors:
PrintWriter(OutputStream outputStream)
PrintWriter(OutputStream outputStream, boolean flushOnNewline)
PrintWriter(Writer outputStream)
PrintWriter(Writer outputStream, boolean flushOnNewline)
where flushOnNewline controls whether Java flushes the output stream every time println( ) is
called. If flushOnNewline is true, flushing automatically takes place. If false, flushing is not
automatic. The first and third constructors do not automatically flush.

Methods

Method Description
void println(boolean x) It is used to print the boolean value.
void println(char[] x) It is used to print an array of characters.
void println(int x) It is used to print an integer.
PrintWriter append(char c) It is used to append the specified character to the
writer.

190
PrintWriter append(CharSequence ch) It is used to append the specified character
sequence to the writer.
PrintWriter append(CharSequence ch, int start, It is used to append a subsequence of specified
int end) character to the writer.
boolean checkError() It is used to flushes the stream and check its error
state.
protected void setError() It is used to indicate that an error occurs.
protected void clearError() It is used to clear the error state of a stream.
PrintWriter format(String format, Object args) It is used to write a formatted string to the writer
using specified arguments and format string.
void print(Object obj) It is used to print an object.
void flush() It is used to flushes the stream.
void close() It is used to close the stream.

Example:
//Java Program using PrintWriter
import java.io.*;
public class PrintWriterExample
{
public static void main(String args[]) throws Exception
{
//Data to write on Console using PrintWriter
PrintWriter writer = new PrintWriter(System.out);
writer.write("Java is an Object Oriented Language.");
writer.flush();
writer.close();
//Data to write in File using PrintWriter
PrintWriter writer1 =null;
writer1 = new PrintWriter(new File("D:\\testout.txt"));
writer1.write("I Like Java, Visual Basic, Android, PHP etc.”);
writer1.flush();
writer1.close();
}
}
Output:
Java is an Object Oriented Language.

The content of a text file testout.txt is set with the data I Like Java, Visual Basic, Android, PHP
etc.
13.6 Serialization
❖ Serialization in Java is a mechanism of writing the state of an object into a byte stream.
❖ It is mainly used in Hibernate, RMI, JPA, EJB and JMS technologies.
❖ The reverse operation of serialization is called deserialization.
❖ The interfaces and classes that support serialization are as follows.
191
Serializable
❖ Serializable is a marker interface (has no data member and method).
❖ It is used to "mark" Java classes so that objects of these classes may get the certain capability.
❖ The Cloneable and Remote are also marker interfaces.
❖ It must be implemented by the class whose object you want to persist.
❖ The String class and all the wrapper classes implement the java.io.Serializable interface by
default.
Externalizable
❖ The Externalizable interface provides the facility of writing the state of an object into a byte
stream in compress format. It is not a marker interface.
❖ The Externalizableinterface defines these two methods:
void readExternal(ObjectInput inStream) throws IOException, ClassNotFoundException
void writeExternal(ObjectOutput outStream) throws IOException

In these methods, inStream is the byte stream from which the object is to be read, and outStream
is the byte stream to which the object is to be written.
ObjectOutput

❖ The ObjectOutput interface extends the DataOutput interface and supports object
serialization.
❖ It defines the methods shown in Table 13.5.
Method Description
void close() Closes the invoking stream. Further write
attempts will generate an IOException.
void flush() Finalizes the output state so that any buffers
are cleared. That is, it flushes the output
buffers.
void write(byte buffer[]) Writes an array of bytes to the invoking
stream.
void write(byte buffer[], int offset, int Writes a subrange of numBytes bytes from
numBytes) the array buffer, beginning at buffer[offset].

void write(int b) Writes a single byte to the invoking stream.


The byte written is the low-order byte of b.
void writeObject(Object obj) Writes object obj to the invoking stream.
Table 13.5: The Methods Defined by ObjectOutput
ObjectOutputStream
❖ The ObjectOutputStream class is used to write primitive data types and Java objects to an
OutputStream.
❖ Only objects that support the java.io.Serializable interface can be written to streams.

192
❖ A constructor of this class is
ObjectOutputStream(OutputStream outStream) throws IOException
The argument outStream is the output stream to which serialized objects will be written.
❖ The most commonly used methods in this class are shown in Table 13.6. They will throw an
IOException on error conditions.
Method Description
void close() Closes the invoking stream. Further write attempts
will generate an IOException.
void flush() Finalizes the output state so that any buffers are
cleared. That is, it flushes the output buffers.
void write(byte buffer[]) Writes an array of bytes to the invoking stream.
void write(byte buffer[], int offset, int Writes a subrange of numBytes bytes from the array
numBytes) buffer, beginning at buffer[offset].

void write(int b) Writes a single byte to the invoking stream. The


byte written is the low-order byte of b.
void writeBoolean(boolean b) Writes a boolean to the invoking stream.
void writeByte(int b) Writes a byte to the invoking stream. The byte
written is the low-order byte of b.
void writeBytes(String str) Writes the bytes representing str to the invoking
stream.
void writeChar(int c) Writes a char to the invoking stream.
void writeChars(String str) Writes the characters in str to the invoking stream.
Table 13.6: Commonly Used Methods Defined by ObjectOutputStream
Example:

//Java Program using ObjectOutputStream - Serialization


import java.io.*;
class Persist
{
public static void main(String args[]) throws Exception
{
Student s1 =new Student(100,"Abilash");
FileOutputStream fout=new FileOutputStream("f.txt");
ObjectOutputStream out=new ObjectOutputStream(fout);
out.writeObject(s1);
out.flush();
System.out.println("Success");
}
}
Output:
Success
ObjectInput
❖ The ObjectInput interface extends the DataInput interface and defines the methods shown in
Table 13.7.
❖ It supports object serialization especially the readObject() method. This is called to deserialize
an object.
193
❖ All of these methods will throw an IOException on error conditions.
Method Description
void writeDouble(double d) Writes a double to the invoking stream.
void writeFloat(float f ) Writes a float to the invoking stream.
void writeInt(int i) Writes an int to the invoking stream.
void writeLong(long l) Writes a long to the invoking stream.
final void writeObject(Object obj) Writes obj to the invoking stream.
void writeShort(int i) Writes a short to the invoking stream.
int available() Returns the number of bytes that are now available in
the input buffer.
void close() Closes the invoking stream. Further read attempts will
generate an IOException.
int read() Returns an integer representation of the next available
byte of input. –1 is returned when the end of the file is
encountered.
int read(byte buffer[ ]) Attempts to read up to buffer.length bytes into buffer,
returning the number of bytes that were successfully
read. –1 is returned when the end of the file is
encountered.
Table 13.7: The Methods Defined by ObjectInput

ObjectInputStream

❖ An ObjectInputStream deserializes objects and primitive data written using an


ObjectOutputStream. ObjectInputStream is responsible for reading objects from a stream.
❖ Deserialization is the process of reconstructing the object from the serialized state.It is the
reverse operation of serialization.
❖ A constructor of this class is
ObjectInputStream(InputStream inStream) throws IOException, StreamCorruptedException

The argument inStream is the input stream from which serialized objects should be read. The
most commonly used methods in this class are shown in Table 13.8. They will throw an
IOException on error conditions.

Method Description
int read(byte buffer[], int offset, int Attempts to read up to numBytes bytes into
numBytes) buffer starting at buffer[offset], returning the
number of bytes that were successfully read. –1
is returned when the end of the file is
encountered.
Object readObject() Reads an object from the invoking stream.

194
long skip(long numBytes) Ignores (that is, skips) numBytes bytes in the
invoking stream, returning the number of bytes
actually ignored.
int available() Returns the number of bytes that are now
available in the input buffer.
void close() Closes the invoking stream. Further read
attempts will generate an IOException.
int read() Returns an integer representation of the next
available byte of input. –1 is returned when the
end of the file is encountered.
int read(byte buffer[], int offset, int Attempts to read up to numBytes bytes into
numBytes) buffer starting at buffer[offset], returning the
number of bytes successfully read. –1 is
returned when the end of the file is encountered.
boolean readBoolean() Reads and returns a boolean from the invoking
stream.
byte readByte() Reads and returns a byte from the invoking
stream.
char readChar() Reads and returns a char from the invoking
stream.
double readDouble() Reads and returns a double from the invoking
stream.
float readFloat() Reads and returns a float from the invoking
stream.
void readFully(byte buffer[]) Reads buffer.length bytes into buffer. Returns
only when all bytes have been read.
void readFully(byte buffer[], int offset, int Reads numBytes bytes into buffer starting at
numBytes) buffer[offset]. Returns only when numBytes
have been read.
int readInt() Reads and returns an int from the invoking
stream.
long readLong() Reads and returns a long from the invoking
stream.
final Object readObject() Reads and returns an object from the invoking
stream.
short readShort() Reads and returns a short from the invoking
stream.
int readUnsignedByte() Reads and returns an unsigned byte from the
invoking stream.
int readUnsignedShort() Reads an unsigned short from the invoking
stream.
Table 13.8: Commonly Used Methods Defined by ObjectInputStream
Example:

//Java Program using ObjectInputStream - Deserialization


import java.io.*;

195
class Deserial
{
public static void main(String args[]) throws Exception
{
ObjectInputStream in=new ObjectInputStream(new FileInputStream("f.txt"));
Student s=(Student)in.readObject();
System.out.println(s.id+" "+s.name);
in.close();
}
}
Output:
100 Abilash
13.7 Other Useful I/O Classes
❖ The java.io package supports many other classes for performing certain specialized functions.
They include:
• RandomAccessFile
• StreamTokenizer
RandomAccessFile
❖ RandomAccessFile enables us to read and write bytes, text and Java data types to any location
in a file.
❖ This class extends Object class and implements DataInput and DataOutput interfaces.
❖ It also supports positioning requests - that is, we can position the file pointer within the file.
❖ It has these two constructors:
RandomAccessFile(File fileObj, String access) throws FileNotFoundException
RandomAccessFile(String filename, String access) throws FileNotFoundException
In the first form, fileObj specifies the name of the file to open as a File object.
In the second form, the name of the file is passed in filename. In both cases, access determines
what type of file access is permitted. If it is “r”, then the file can be read, but not written. If it is
“rw”, then the file is opened in read-write mode. If it is “rws”, the file is opened for read-write
operations and every change to the file’s data or metadata will be immediately written to the
physical device. If it is “rwd”, the file is opened for read-write operations and every change to
the file’s data will be immediately written to the physical device.
Methods

Method Description
Void close() It closes this random access file stream and releases any system
resources associated with the stream.
FileChannel getChannel() It returns the unique FileChannel object associated with this file.
int readInt() It reads a signed 32-bit integer from this file.
String readUTF() It reads in a string from this file.

196
void seek(long pos) It sets the file-pointer offset, measured from the beginning of this
file, at which the next read or write occurs.
void writeDouble(double v) It converts the double argument to a long using the
doubleToLongBits method in class Double, and then writes that
long value to the file as an eight-byte quantity, high byte first.
void writeFloat(float v) It converts the float argument to an int using the floatToIntBits
method in class Float, and then writes that int value to the file as a
four-byte quantity, high byte first.
void write(int b) It writes the specified byte to this file.
int read() It reads a byte of data from this file.
long length() It returns the length of this file.
void seek(long pos) It sets the file-pointer offset, measured from the beginning of this
file, at which the next read or write occurs.

Example 1:
// Writing and reading with random access
import java.io.*;
class RandomIO
{
public static void main(String args[])
{
RandomAccessFile file=null;
try
{
file=new RandomAccessFile(“rand.dat”,”rw”);
// Writing to the file
file.writeChar(‘X’);
file.writeInt(555);
file.writeDouble(3.1412);
file.seek(0); // Go to the beginning
// Reading from the file
System.out.println(file.readChar());
System.out.println(file.readInt());
System.out.println(file.readDouble());
file.seek(2); // Go to the second item
System.out.println(file.readInt());
// Go to the end and append false to the file
file.seek(file.length());
file.writeBoolean(false);
file.seek(4);
System.out.println(file.readBoolean());
file.close();
}
catch(IOException e)
{
System.out.println(e);
197
}
}
}
Output:

X
555
3.1412
555
false
Appending to an existing file
Example 2:

// Appending to a text file using random access


import java.io.*;
class RandomAccess
{
public static void main(String args[])
{
RandomAccessFile rFile;
try
{
rFile=new RandomAccessFile(“city.txt”,”rw”);
rFile.seek(rFile.length()); // Go to the end
rFile.writeBytes(“MUMBAI\n”); // Append MUMBAI
rFile.close();
}
catch (IOException ioe)
{
System.out.println(ioe);
}
}
}

StreamTokenizer
❖ The StreamTokenizer class takes an input stream and parses it into "tokens" allowing the
tokens to be read one at a time.
❖ The StreamTokenizer can recognize identifiers, numbers, quoted strings, and various
comment styles.
❖ It has this constructor:
StreamTokenizer(Reader r)
This creates a tokenizer that parses the given character stream.

Field

❖ Following are the fields for Java.io.StreamTokenizer class −


• double nval − If the current token is a number, this field contains the value of that number.

198
• String sval − If the current token is a word token, this field contains a string giving the
characters of the word token.
• static int TT_EOF − A constant indicating that the end of the stream has been read.
• static int TT_EOL − A constant indicating that the end of the line has been read.
• static int TT_NUMBER − A constant indicating that a number token has been read.
• static int TT_WORD − A constant indicating that a word token has been read.
• int ttype − After a call to the nextToken method, this field contains the type of the token just
read.
Methods

Method Description
void commentChar(int ch) Specified that the character argument starts a
single-line comment.
void eolIsSignificant(boolean flag) This method determines whether or not ends of
line are treated as tokens.
int lineno() This method returns the current line number.
void lowerCaseMode(boolean fl) This method determines whether or not word
token are automatically lowercased.
int nextToken() This method parses the next token from the input
stream of this tokenizer.
void ordinaryChar(int ch) This method specifies that the character argument
is "ordinary" in this tokenizer.
void ordinaryChars(int low, int hi) This method specifies that all characters c in the
range low <= c <= high are "ordinary" in this
tokenizer.
void parseNumbers() This method specifies that numbers should be
parsed by this tokenizer.
void pushBack() This method causes the next call to the nextToken
method of this tokenizer to return the current
value in the ttype field, and not to modify the
value in the nval or sval field.
void quoteChar(int ch) This method specifies that matching pairs of this
character delimit string constants in this
tokenizer.
void resetSyntax() This method resets this tokenizer's syntax table so
that all characters are "ordinary." See the
ordinaryChar method for more information on a
character being ordinary.
void slashSlashComments(boolean flag) This method determines whether or not the
tokenizer recognizes C++ style comments.
void slashStarComments(boolean flag) This method determines whether or not the
tokenizer recognizes C style comments.
String toString() This method returns the string representation of
the current stream token and the line number it
occurs on.

199
void whitespaceChars(int low, int hi) This method specifies that all characters c in the
range low <= c <= high are white space
characters.
void wordChars(int low, int hi) This method specifies that all characters c in the
range low <= c >= high are word constituents.

Example:

//Java Program using StreamTokenizer Class


import java.io.*;
public class StreamTokenizerExample
{
public static void main(String args[]) throws IOException
{
Reader reader = new String Reader("This is a test string for Stream Tokenizer");
StreamTokenizer tokenizer = new StreamTokenizer(reader);
while(tokenizer.nextToken()!=StreamTokenizer.TT_EOF)
{
System.out.println(tokenizer.sval);
}
}
}
Output:

This
is
a
test
string
for
Stream
Tokenizer

13. 8 File Class


❖ The java.io package includes a class known as the File class that supports for creating files and
directories.
❖ The File class has several methods for working with directories and files such as creating new
directories or files, deleting and renaming directories or files, listing the contents of a directory
etc.
Constructors

i) File(File parent, String child) : Creates a new File instance from a parent abstract pathname
and a child pathname string.
ii) File(String pathname) : Creates a new File instance by converting the given pathname string
into an abstract pathname.
200
iii) File(String parent, String child) : Creates a new File instance from a parent pathname string
and a child pathname string.
iv) File(URI uri) : Creates a new File instance by converting the given file: URI into an abstract
pathname.
Methods

Method Description
boolean canExecute() Tests whether the application can execute the file
denoted by this abstract pathname.
boolean canRead() Tests whether the application can read the file denoted
by this abstract pathname.
boolean canWrite() Tests whether the application can modify the file
denoted by this abstract pathname.
boolean createNewFile() Atomically creates a new, empty file named by this
abstract pathname .
boolean delete() Deletes the file or directory denoted by this abstract
pathname. If this pathname denotes a directory, then the
directory must be empty in order to be deleted. Returns
true if and only if the file or directory is successfully
deleted; false otherwise.
boolean equals(Object obj) Tests this abstract pathname for equality with the given
object.
Tests whether the file or directory denoted by this
boolean exists()
abstract pathname exists. Returns true if and only if the
file or directory denoted by this abstract pathname
exists; false otherwise.
String getName() Returns the name of the file or directory denoted by this
abstract pathname.
String getParent() Returns the pathname string of this abstract pathname's
parent, or null if this pathname does not name a parent
directory.
String getPath() Converts this abstract pathname into a pathname string.
Tests whether this abstract pathname is absolute.
boolean isAbsolute()
Returns true if this abstract pathname is absolute, false
otherwise.
Returns the absolute pathname string of this abstract
String getAbsolutePath()
pathname.
Tests whether the file denoted by this abstract pathname
boolean isDirectory()
is a directory. Returns true if and only if the file denoted
by this abstract pathname exists and is a directory; false
otherwise.
Tests whether the file denoted by this abstract pathname
boolean isFile()
is a normal file. Returns true if and only if the file
denoted by this abstract pathname exists and is a normal
file; false otherwise.
201
long lastModified() Returns the time that the file denoted by this abstract
pathname was last modified.
Returns the length of the file denoted by this abstract
long length()
pathname. The return value is unspecified if this
pathname denotes a directory.
Returns an array of strings naming the files and
String[] list()
directories in the directory denoted by this abstract
pathname.
Returns an array of strings naming the files and
String[] list(FilenameFilter filter)
directories in the directory denoted by this abstract
pathname that satisfy the specified filter.
Returns an array of abstract pathnames denoting the files
File[] listFiles()
in the directory denoted by this abstract pathname.
File[] listFiles(FileFilter filter) Returns an array of abstract pathnames denoting the
files and directories in the directory denoted by this
abstract pathname that satisfy the specified filter.
Creates the directory named by this abstract pathname.
boolean mkdir()
Returns true if and only if the directory was created;
false otherwise.
Creates the directory named by this abstract pathname,
boolean mkdirs()
including any necessary but nonexistent parent
directories. Returns true if and only if the directory was
created, along with all necessary parent directories; false
otherwise.
Renames the file denoted by this abstract pathname.
boolean renameTo(File dest)
Returns true if and only if the renaming succeeded; false
otherwise.
Sets the last-modified time of the file or directory named
boolean setLastModified(long
by this abstract pathname. Returns true if and only if the
time) operation succeeded; false otherwise.

Marks the file or directory named by this abstract


boolean setReadOnly()
pathname so that only read operations are allowed.
Returns true if and only if the operation succeeded; false
otherwise.

Example:
//Demonstrate File class
import java.io.*;
public class RetrieveFileData
{
public static void main(String args[]) throwsIOException
{
File f1=newFile("abc.txt");

202
System.out.println("getName() : "+f1.getName());
System.out.println("getAbsolutePath() : "+f1.getAbsolutePath());
System.out.println("canRead() : "+f1.canRead());
System.out.println("canWrite() : "+f1.canWrite());
System.out.println("isFile() : "+f1.isFile());
System.out.println("isDirectory : "+f1.isDirectory());
System.out.println("File size in bytes : "+f1.length());
System.out.println("File exists() : "+f1.exists());
}
}
Output:
getName() : abc.txt
getAbsolutePath() : C:\Java\Jdk1.6.0_01\binabc.txt
canRead() : true
canWrite() : true
isFile() : true
isDirectory : false
File size in bytes : 53
File exists() : true
13.9 Reading / Writing Characters
❖ The two subclasses used for handling characters in files are FileReader (for reading characters)
and FileWriter (for writing characters)
i) FileReader
❖ FileReader class is used to read data from the file. It is character-oriented class which is used
for file handling in Java.
❖ Its two most commonly used constructors are shown here:
FileReader(String filePath)

FileReader(File fileObj)

Either can throw a FileNotFoundException. Here, filePath is the full path name of a file, and
fileObj is a File object that describes the file.

Methods

Method Description
int read() It is used to return a character in ASCII form. It returns -1 at the end of file.
void close() It is used to close the FileReader class.
Example:

//Java Program using FileReader Class


import java.io.*;
public class FileReaderExample
{
public static void main(String args[]) throws Exception
{
203
FileReader fr=new FileReader("D:\testout.txt");
int i;
while((i=fr.read())!=-1)
System.out.print((char)i);
fr.close();
}
}
testout.txt
Welcome to Java Programming.
Output:
Welcome to Java Programming.
ii) FileWriter

❖ The FileWriter class is used to write character-oriented data to a file. It is character-oriented


class which is used for file handling in Java.
❖ Its most commonly used constructors are shown here:
FileWriter(String filePath)
FileWriter(String filePath, boolean append)
FileWriter(File fileObj)
FileWriter(File fileObj, boolean append)
They can throw an IOException. Here, filePath is the full path name of a file, and fileObj is a
File object that describes the file. If append is true, then output is appended to the end of the
file.
Methods

Method Description
void write(String text) It is used to write the string into FileWriter.
void write(char c) It is used to write the char into FileWriter.
void write(char[] c) It is used to write char array into FileWriter.
void flush() It is used to flushes the data of FileWriter.
void close() It is used to close the FileWriter.

Example:

//Java Program using FileWriter Class


import java.io.*;
public class FileWriterExample
{
public static void main(String args[])
{
try
{
FileWriter fw=new FileWriter("D:\testout.txt");
fw.write("Welcome to Java Programming.");
fw.close();
204
}
catch(Exception e)
{
System.out.println(e);
}
System.out.println("Done.");
}
}
Output:
Done.
testout.txt:
Welcome to Java Programming.
13.10 Reading / Writing Bytes
❖ Two commonly used classes for handling bytes are FileInputStream and FileOutputStream
classes.
i) FileInputStream
❖ The FileInputStream class obtains input bytes from a file.
❖ It is used for reading byte-oriented data (streams of raw bytes) such as image data, audio, video
etc.
❖ We can also read character-stream data.
❖ Its two most common constructors are shown here:
FileInputStream(String filepath)
FileInputStream(File fileObj)
Either can throw a FileNotFoundException. Here, filepath is the full path name of a file, and
fileObj is a File object that describes the file.
Methods

Method Description
int available() It is used to return the estimated number of bytes that can be
read from the input stream.
int read() It is used to read the byte of data from the input stream.
int read(byte[] b) It is used to read up to b.length bytes of data from the input
stream.
int read(byte[] b, int off, int len) It is used to read up to len bytes of data from the input stream.
long skip(long x) It is used to skip over and discards x bytes of data from the
input stream.
FileChannel getChannel() It is used to return the unique FileChannel object associated
with the file input stream.
FileDescriptor getFD() It is used to return the FileDescriptor object.
protected void finalize() It is used to ensure that the close method is call when there is
no more reference to the file input stream.

205
void close() It is used to close the stream.

Example:
//Java Program using FileInputStream Class
import java.io.*;
public class DataStreamExample
{
public static void main(String args[])
{
try
{
FileInputStream fin=new FileInputStream("D:\testout.txt");
int i=0;
while((i=fin.read())!=-1)
{
System.out.print((char)i);
}
fin.close();
}
catch(Exception e)
{
System.out.println(e);
}
}
}

Output:
Welcome to Java Programming.

ii) FileOutputStream
❖ The FileOutputStream is an output stream used for writing data to a file.
❖ We can write byte-oriented as well as character-oriented data through FileOutputStream class.
❖ Its most commonly used constructors are shown here:
FileOutputStream(String filePath)
FileOutputStream(File fileObj)
FileOutputStream(String filePath, boolean append)
FileOutputStream(File fileObj, boolean append)

They can throw a FileNotFoundException or a SecurityException. Here, filePath is the full


path name of a file, and fileObj is a File object that describes the file. If append is true, the file
is opened in append mode.

Methods

Method Description

206
protected void finalize() It is used to clean up the connection with the file output
stream.
void write(byte[] ary) It is used to write ary.length bytes from the byte array to the
file output stream.
void write(byte[] ary, int off, int len) It is used to write len bytes from the byte array starting at
offset off to the file output stream.
void write(int b) It is used to write the specified byte to the file output stream.
FileChannel getChannel() It is used to return the file channel object associated with the
file output stream.
FileDescriptor getFD() It is used to return the file descriptor associated with the
stream.
void close() It is used to closes the file output stream.

Example:
//Java Program using FileOutputStream
import java.io.*;
public class FileOutputStreamExample
{
public static void main(String args[])
{
try
{
FileOutputStream fout=new FileOutputStream("D:\testout.txt");
String s="Welcome to Java Programming.";
byte b[]=s.getBytes();//Converting string into byte array
fout.write(b);
fout.close();
System.out.println("Success...");
}
catch(Exception e)
{
System.out.println(e);
}
}
}

Output:
Success...
The content of a text file testout.txt is set with the data Welcome to Java Programming.testout.txt
Welcome to Java Programming.
13.11 Other Stream Classes
❖ Java supports many other input / output streams that we might find useful in some situations.
Object Streams

❖ The object streams are created using the ObjectInputStream and ObjectOutputStream
classes.
❖ In this case, we may declare records as objects and use the object classes to write and read these
207
objects from files.
❖ This process is known as object serialization.
Piped Streams

❖ Piped streams provide functionality for threads to communicate and exchange data between
them.
❖ The write thread sends data to a read thread through a pipeline that connects an object of
PipedInputStream to an object of PipedOutputStream.
❖ The objects inputPipe and outputPipe are connected using the connect() method.
PushBack Streams
❖ The pushback streams created by the classes PushbackInputStream and PushbackReader
can be used to push a single byte or character (that was previously read) back into the input
stream so that it can be reread.
❖ This is commonly used with parsers.
❖ When a character indicating a new input token is read, it is pushed back into the input stream
until the current input token is processed. It is then reread when processing of the next input
token is initiated.
PushbackInputStream

❖ Pushback is used on an input stream to allow a byte to be read and then returned (that is, “pushed
back”) to the stream.
❖ The PushbackInputStream class provides a mechanism to “peek” at what is coming from an
input stream without disrupting it.
❖ PushbackInputStreamhas the following constructors:
PushbackInputStream(InputStream inputStream)

PushbackInputStream(InputStream inputStream, int numBytes)

The first form creates a stream object that allows one byte to be returned to the input stream.
The second form creates a stream that has a pushback buffer that is numBytes long. This allows
multiple bytes to be returned to the input stream.

❖ Beyond the familiar methods of InputStream, PushbackInputStream provides unread(),


shown here:
void unread(int ch)
void unread(byte buffer[ ])
void unread(byte buffer, int offset, int numChars)
The first form pushes back the low-order byte of ch. This will be the next byte returned by a
subsequent call to read( ). The second form returns the bytes in buffer. The third form pushes
back numChars bytes beginning at offset from buffer. An IOException will be thrown if there
is an attempt to return a byte when the pushback buffer is full.
208
Example:

// Demonstrate unread().
import java.io.*;
class PushbackInputStreamDemo
{
public static void main(String args[]) throws IOException
{
String s = "if (a == 4) a = 0;\n";
byte buf[] = s.getBytes();
ByteArrayInputStream in = new ByteArrayInputStream(buf);
PushbackInputStream f = new PushbackInputStream(in);
int c;
while ((c = f.read()) != -1)
{
switch(c)
{
case '=':
if ((c = f.read()) == '=')
System.out.print(".eq.");
else
{
System.out.print("<-");
f.unread(c);
}
break;
default:
System.out.print((char) c);
break;
}
}
}
}

Output:

if (a .eq. 4) a <- 0;

ii) PushbackReader

❖ The PushbackReader class allows one or more characters to be returned to the input stream.
This allows us to look ahead in the input stream.
❖ An IOException will be thrown if there is an attempt to return a character when the pushback
buffer is full.
❖ Here are its two constructors:

209
PushbackReader(Reader inputStream)
PushbackReader(Reader inputStream, int bufSize)
The first form creates a buffered stream that allows one character to be pushed back. In the
second, the size of the pushback buffer is passed in bufSize.
Methods

Method Description
int read() It is used to read a single character.
void mark(int readAheadLimit) It is used to mark the present position in a stream.
boolean ready() It is used to tell whether the stream is ready to be read.
boolean markSupported() It is used to tell whether the stream supports mark() operation.
long skip(long n) It is used to skip the character.
void unread (int c) It is used to pushes back the character by copying it to the
pushback buffer.
void unread (char[] cbuf) It is used to pushes back an array of character by copying it to the
pushback buffer.
void reset() It is used to reset the stream.
void close() It is used to close the stream.

Example:

// Demonstrate unread().
import java.io.*;
class PushbackReaderDemo
{
public static void main(String args[]) throws IOException
{
String s = "if (a == 4) a = 0;\n";
char buf[] = new char[s.length()];
s.getChars(0, s.length(), buf, 0);
CharArrayReader in = new CharArrayReader(buf);
PushbackReader f = new PushbackReader(in);
int c;
while ((c = f.read()) != -1)
{
switch(c)
{
case '=':
if ((c = f.read()) == '=')
System.out.print(".eq.");
else
{
System.out.print("<-");
f.unread(c);
}
break;
210
default:
System.out.print((char) c);
break;
}
}
}
}
Filtered Streams
❖ Java supports two abstract classes, namely, FilterInputStream and FilterOutputStream that
provide the basic capability to create input and output streams for filtering input/output in a
number of ways.
❖ These streams known as filters sit between an input stream and an output stream and perform
some optional processing on the data they transfer.
❖ The DataInputStream and DataOutputStream classes are used as filters for handling
primitive type data.
❖ The constructors defined for the FilterInputStream and FilterOutputStream classes are
shown below:
FilterOutputStream(OutputStream os)
FilterInputStream(InputStream is)

❖ The methods provided in these classes are identical to those in InputStream and
OutputStream.

Exercises:
1. Define stream.
2. What is file stream?
3. What are input and output streams?
4. Define Byte stream.
5. Define print stream.

211
6. Define character stream.
7. Distinguish between Input Stream and Output Stream classes.
8. Distinguish between Byte Stream and Character Stream clases.
9. Explain about buffered ByteStream and its methods.
10. Explain about Reader and Writer Stream classes.
11. What is serialization?
12. Explain serialization concepts in detail.
13. Define random access file.
14. Define streamtokenizer.
15. Explain various File class methods in detail.
*****************************

*******************************************************************************
Chapter 14 Applets
*******************************************************************************
14.1 Introduction
❖ An Applet is a Java program that runs in a Web browser.
❖ Applets are small Java programs that are primarily used for Internet computing. They can be
transported over the Internet from one computer to another and runs using the Appletviewer or
212
any Web Browser that supports Java.
❖ An Applet, like any other application program, can do many things for us. It can perform
arithmetic operations, display graphics, play sounds, accept user input, create animation, and
play interactive games.
❖ An Applet is embedded in an HTML page using the APPLET tag and hosted on a web server.
❖ Applets are used to make the web site more dynamic and entertaining.
Local and Remote Applets
❖ An applet developed locally and stored in a local system is known as a local applet. When
a Web page is trying to find a local applet, it does not need to use the Internet, and therefore the
local system does not require the Internet connection. It simply searches the directories in the
local system and locates and loads the specified applet.
❖ A remote applet is that which is developed by someone else and stored on a computer
connected to the Internet. If our system is connected to the Internet, we can download the
remote applet onto our system via the Internet and run it.
❖ In order to locate and load a remote applet, we must know the applet’s address on the Web. This
address is known as Uniform Resource Locator (URL) and must be specified in the applet’s
HTML document as the value of the CODEBASE attribute.
Example:

CODEBASE=http://www.netserve.com/applets
In the case of local applets, CODEBASE may be absent or may specify a local directory.
14.2 Differences between Applets and Applications
Applet Application
Applets are small Java programs that are Applications are stand-alone programs that can be
designed to be included with the HTML web executed independently without using the web
document. They require a Java-enabled web browser.
browser for execution.
Applet does not require a main function for Application program requires a main function for
its execution. its execution.
Applets can't read from or write to the files on An application can read from or write to the files
the local computer. on the local computer.
An Applet requires Graphical User Interface An application doesn't require Graphical User
(GUI). Interface (GUI).
Applets can't communicate with other servers The application can communicate with other
on the network. servers on the network.
Applets can only access the browser specific Applications can access all kinds of resources
services. They don’t have access to the local available on the system.
system.
An applet program is needed to perform An application program is needed to perform
small tasks or the part of it. some task directly for the user.

213
14.3 Applet Basics
❖ Applet is a Java program that can be embedded into a web page.
❖ It runs inside the web browser and works at client side.
❖ The applet code uses the services of the two classes, namely, Applet and Graphics from the
Java class library.
❖ The Applet class provides the necessary support for applets.
❖ The Applet class is contained in the java.applet package. Thus, all applets must import
java.applet.
❖ Applets must also import java.awt.AWT stands for Abstract Window Toolkit.
❖ Applets are executed by either a Web browser or an applet viewer.
❖ Applet contains several methods that give us detailed control over the execution of
our applet.
Example:

/*
<applet code="MyApplet" width=200 height=60>
</applet>
*/
❖ This comment contains an APPLET tag that will run an applet called MyApplet in a window
that is 200 pixels wide and 60 pixels high.
❖ An applet code will have a general format as shown below:
import java.awt.*;
import java.applet.*;
………………….
………………….
public class appletclassnaame extends Applet
{
…………………..
…………………..
public void paint(Graphics G)
{
………………….
…………………. // Applet operations code
}
…………………..
…………………..
}
The appletclassname is the main class for the applet. When the applet is loaded, Java creates an
instance of the class, and then a series of Applet class methods are called on that instance to
execute the code.
Example:

// Simple Applet program


import java.awt.*;
214
import java.applet.*;
public class HelloWorldApplet extends Applet
{
public void paint(Graphics g)
{
g.drawString(“Hello World,10,100);
}
}
/*<applet code="HelloWorldApplet.class" height=300 width-200>
</applet>/*
Output:
Hello World
14.4 The Applet Class
❖ The Applet class defines the methods shown in Table 14.1.
❖ Applet provides all necessary support for applet execution, such as starting and stopping. It also
provides methods that load and display images, and methods that load and play audio clips.
❖ Applet extends the AWT class Panel. In turn, Panel extends Container, which extends
Component. These classes provide support for Java’s window-based, graphical interface. Thus,
Applet provides all of the necessary support for window-based activities.
Method Description

void destroy() Called by the browser just before an applet is


terminated. Our applet will override this method if it needs
to perform any cleanup prior to its destruction.
AccessibleContext Returns the accessibility context for the invoking object.
getAccessibleContext()
AppletContext getAppletContext() Returns the context associated with the applet.
String getAppletInfo() Returns a string that describes the applet.
AudioClip getAudioClip(URL url) Returns an AudioClip object that encapsulates the audio clip
found at the location specified by url.
AudioClip getAudioClip(URL url, Returns an AudioClip object that encapsulates the audio clip
String clipName) found at the location specified by url and having the name
specified by clipName.
URL getCodeBase() Returns the URL associated with the invoking applet.
URL getDocumentBase() Returns the URL of the HTML document that invokes the
applet.
Image getImage(URL url) Returns an Image object that encapsulates the image found
at the location specified by url.
Image getImage(URL url, Returns an Image object that encapsulates the image found
String imageName) at the location specified by url and having the name specified
by imageName.
Locale getLocale() Returns a Locale object that is used by various locale-
sensitive classes and methods.
String getParameter(String Returns the parameter associated with paramName. null is
paramName) returned if the specified parameter is not found.
String[][] getParameterInfo() Returns a String table that describes the parameters
recognized by the applet. Each entry in the table must consist
of three strings that contain the name of the parameter, a
215
description of its type and/or range, and an explanation of its
purpose.
void init() Called when an applet begins execution. It is the first method
called for any applet.
boolean isActive() Returns true if the applet has been started. It returns false if
the applet has been stopped.
static final AudioClip Returns an AudioClip object that encapsulates the audio clip
newAudioClip(URL url) found at the location specified by url. This method is
similar to getAudioClip() except that it is static and can be
executed without the need for an Applet object.
void play(URL url) If an audio clip is found at the location specified by url, the
clip is played.
void play(URL url, String clipName) If an audio clip is found at the location specified by url with
the name specified by clipName, the clip is played.
void resize(Dimension dim) Resizes the applet according to the dimensions specified by
dim. Dimension is a class stored inside java.awt. It contains
two integer fields: width and height.
void resize(int width, int height) Resizes the applet according to the dimensions specified by
width and height.
final void setStub(AppletStub stubObj) Makes stubObj the stub for the applet. This method is used
by the run-time system and is not usually called by our applet.
A stub is a small piece of code that provides the linkage
between our applet and the browser.
void showStatus(String str) Displays str in the status window of the browser or applet
viewer. If the browser does not support a status window, then
no action takes place.
void start() Called by the browser when an applet should start (or
resume) execution. It is automatically called after init() when
an applet first begins.
void stop() Called by the browser to suspend execution of the applet.
Once stopped, an applet is restarted when the browser
calls start().

Table 14.1: The Methods Defined by Applet


14.5 Applet Architecture
❖ An applet is a window-based program. There are a few key concepts we must understand.
❖ First, applets are event driven. An applet resembles a set of interrupt service routines. An applet
waits until an event occurs. The AWT notifies the applet about an event by calling an event
handler.
❖ Second, the user initiates interaction with an applet - not the other way around. The user interacts
with the applet as he or she wants, when he or she wants. These interactions are sent to the applet
as events to which the applet must respond. For example, when the user clicks a mouse inside
the applet’s window, a mouse-clicked event is generated. If the user presses a key while the
applet’s window has input focus, a keypress event is generated.
❖ Applets can contain various controls, such as push buttons and check boxes. When the user
interacts with one of these controls, an event is generated.
14.6 Applet Life Cycle
216
❖ There are five methods that are called during the life cycle of an applet. They are:
1) init()
2) start()
3) stop()
4) destroy()
5) paint()

❖ The life cycle of an applet is as shown in the figure below:

init() method
❖ The init() method is the first method to be called.
❖ Variable declaration and initialization operations are performed in this method.
❖ This method is called only once during the run time of our applet.
❖ The general form is:
public void init()
{
…………
………… (Action)
…………
}
start() method
❖ The start() method is called after init().
❖ The start() method contains the actual code of the applet that should run.
❖ It also executes whenever the applet is restored, maximized or moving from one tab to another
tab in the browser.
❖ The general form is:
public void start()
{
…………
………… (Action)
…………
}
stop() method
❖ The stop() method stops the execution of the applet.
❖ The stop() method executes when the applet is minimized or when moving from one tab to
another in the browser.
❖ The general form is:
public void stop()
217
{
…………
………… (Action)
…………
}
destroy() method
❖ The destroy() method executes when the applet window is closed or when the tab containing the
webpage is closed.
❖ The stop() method is always called before destroy(). The destroy() method removes the applet
object from memory.
❖ The general form is:
public void destroy()
{
…………
………… (Action)
…………
}
paint()
❖ The paint() method is used to redraw the output on the applet display area.
❖ The paint() method executes after the execution of start() method and whenever the applet or
browser is resized.
❖ The general form is:
public void paint(Graphics g)
{
…………
………… (Display statements)
…………
}
Example:

//Simple Java Program Using Applets


import java.applet.*;
public class MyApplet extends Applet
{
public void init()
{
System.out.println("Applet initialized");
}
public void start()
{
System.out.println("Applet execution started");
}
public void stop()
{
System.out.println("Applet execution stopped");

218
}
public void paint(Graphicsg)
{
System.out.println("Painting...");
}
public void destroy()
{
System.out.println("Applet destroyed");
}
}

Output:

Applet initialized
Applet execution started
Painting…
Painting…
Applet execution stopped
Applet destroyed
update()
❖ This method is called when the applet has requested that a portion of its window be redrawn.
❖ The default version of update() first fills an applet with the default background color and then
calls paint().
❖ If we fill the background using different color in paint(), the user will experience a flash of the
default background each time update() is called – that is, whenever the window is repainted.
❖ One way to avoid is to override the update() method so that it performs all necessary display
activities.
Example:
// Java program using update() method
import java.awt.*;
import java.applet.*;
/*
<applet code=PaintTest width=100 height=100>
</applet>
*/
public class PaintTest extends Applet
{
public void paint(Graphics g)
{
System.out.println("In paint");
}
public void update(Graphics g)
{
System.out.println("In update");
}
}
219
14.7 Simple Applet Display Methods
❖ Applets are displayed in a window and they use the AWT to perform input and output.
drawString()
❖ The drawString() method is used to output a string to an applet.
❖ This method is a member of the Graphics class.
❖ It is called from within either update() or paint().
❖ The general form is:
void drawString(String message, int x, int y)

Here, message is the string to be output beginning at x, y. In a Java window, the upper left corner
is location 0, 0. The drawString method will not recognize newline characters. If we want to start
a line of text on another line, we must do so manually, specifying the precise x, y locations where
we want the line to begin.
setBackground()
❖ The setBackground() method is used to change the background color of an applet’s window.
❖ This method is defined by the Component class.
❖ The general form is:
void setBackground(Color newColor)
Here, newColor specifies the new color. The class Color defines the constants shown here that
can be used to specify colors:

Color.black Color.magenta
Color.blue Color.orange
Color.cyan Color.pink
Color.darkGray Color.red
Color.gray Color.white
Color.green Color.yellow
Color.lightGray
Example:
setBackground(Color.green);

setForeground()
❖ The setForeground() method is used to change the color of the text in the applet’s window. This
method is defined by the Component class.
❖ The general form is:
void setForeground(Color newColor)
Here, newColor specifies the new color.
Example:
setForeground(Color.red);
220
❖ A good place to set the foreground and background colors is in the init() method. The default
foreground color is black. The default background color is light gray.
getBackground()
❖ The getBackground() method is used to obtain the current settings for the background color.
❖ This method is also defined by the Component class. The general form is:
Color getBackground()
getForeground()
❖ The getForeground() method is used to obtain the current settings for the foreground color.
❖ This method is also defined by the Component class. The general form is:
Color getForeground()
Example:
// A simple applet that sets the foreground and background colors and outputs a string
import java.awt.*;
import java.applet.*;
/*
<applet code="Sample" width=300 height=50>
</applet>
*/
public class Sample extends Applet
{
String msg;
// Set the foreground and background colors.
public void init()
{
setBackground(Color.cyan);
setForeground(Color.red);
msg="Inside init() –";
}
// Initialize the string to be displayed.
public void start()
{
msg+="Inside start()..";
}
// Display msg in applet window.
public void paint(Graphics g)
{
msg+="Inside paint().";
g.drawString(msg, 10, 30);
}
}
Output:
Requesting Repainting
repaint()
❖ The repaint() method causes the AWT runtime system to execute the update() method of the

221
Component class which clears the window with the background color of the applet and then calls
the paint() method.
❖ The repaint() method has four forms. The simplest version of repaint() is shown here:
void repaint()
This version causes the entire window to be repainted. The following version specifies a region
that will be repainted:
void repaint(int left, int top, int width, int height)
Here, the coordinates of the upper-left corner of the region are specified by left and top, and the
width and height of the region are passed in width and height. These dimensions are specified in
pixels.
void repaint(long maxDelay)
void repaint(long maxDelay, int x, int y, int width, int height )
Here, maxDelay specifies the maximum number of milliseconds that can elapse before update()
is called. If the time elapses before update() can be called, it isn’t called. There is no return value
or exception thrown, so we must be careful.
14.8 Development and Execution of a Simple Applet
❖ The development and execution of an Applet involves the following steps:
1) Writing the applet’s code (.java file)
2) Compiling the applet’s code (.class file will be ready after compilation)
3) Writing the HTML code (.html file)
4) Invoking the appletviewer utility from a command shell window
Writing the applet’s code
// Java program to create an Applet
// HelloApplets.java
import java.awt.*;
import java.applet.*;

public class HelloApplets extends Applet


{
public void paint(Graphics g)
{
g.drawString(“Welcome to Java Applets”,65,35);
}
}

Compiling the applet’s code

❖ Compiling an applet is exactly the same as compiling an application. Therefore, we can use the
Java compiler to compile the applet.
❖ The steps required for compiling the HelloApplets applet are:

222
1. Move to the directory containing the source code and type the following command:

Javac HelloApplets.java
2. The compiled output file called HelloApplets.class is placed in the same directory as the source.
3. If any error message is received, then we must check for errors, correct them and compile the
applet again.
Writing the HTML code

❖ The code for the HelloApplets.html file shall be keyed in, as shown here:

<html>
<head>
<title>Hello World !</title>
</head>
<body>
<applet code=”HelloApplets.class” width=400 height=200>
</applet>
</body>
</html>
Invoking the appletviewer utility from a command shell window
❖ The appletviewer is available as part of the Java Development Kit that we have been using so far.
❖ We can use it to run our applet as follows:
appletviewer HelloApplets.html

14.9 The Status Window

❖ The showStatus() method is used to display a message in the status window of the browser or
applet viewer on which the applet is running.
❖ The status window is a good place to give the user feedback about what is occurring in the applet,
suggest options, or possibly report some types of errors.
❖ The status window also makes an excellent debugging aid, because it gives an easy way to output
information about our applet.

Example:

// Java program using the Status Window.


// StatusWindow.java
import java.awt.*;
import java.applet.*;

/*
<applet code="StatusWindow" width=300 height=50>
</applet>
*/
public class StatusWindow extends Applet
{
223
public void init()
{
setBackground(Color.cyan);
}
// Display msg in applet window.
public void paint(Graphics g)
{
g.drawString("This is in the applet window.",10,20);
showStatus("This is shown in the status window.");
}
}
14.10 The APPLET Tag
❖ The <APPLET> tag is used to incorporate an applet into a web page.
❖ The <APPLET> tag creates a space of the required size and then displays the applet output in that
space.
❖ The APPLET tag is used to start an applet from both an HTML document and from an applet
viewer.
❖ An applet viewer will execute each APPLET tag that it finds in a separate window, while web
browsers like Netscape Navigator, Internet Explorer, and HotJava will allow many applets on a
single page.
❖ The syntax for the standard Applet tag is shown here. Bracketed items are optional.
<APPLET
[CODEBASE=codebase_URL]
CODE=AppletFileName.class
[ALT=alternate_text]
[NAME=applet_instance_name]
WIDTH=pixels
HEIGHT=pixels
[ALIGN=alignment]
[VSPACE=pixels]
[HSPACE=pixels]
>
[<PARAM NAME=name1 VALUE=value1>]
[<PARAM NAME=name2 VALUE=value2>]
………………
………………
[Text to be displayed in the absence of Java]
</APPLET>

The minimum required attributes are:

CODE=AppletFileName.class
WIDTH=pixels
HEIGHT=pixels
The attributes of the APPLET tag are as follows:
Attribute Meaning
224
CODEBASE= codebase_URL Specifies the URL of the directory in which the applet
resides. If the applet resides in the same directory as the
HTML file, then the CODEBASE attribute may be
omitted entirely.
CODE= AppletFileName.class CODE is a required attribute that gives the name of the
file containing our applet’s compiled .class file. This file
is relative to the code base URL of the applet, which is
the directory that the HTML file was in or the directory
indicated by CODEBASE if set.
ALT=alternate_text The ALT tag is an optional attribute used to specify a
short text message that should be displayed if the
browser understands the APPLET tag but can’t
currently run Java applets.
NAME=applet_instance_name A name for the applet may optionally be specified so
that other applets on the page may refer to this applet.
This facilitates inter-applet communication.
WIDTH=pixels WIDTH and HEIGHT are required attributes that give
HEIGHT=pixels the size (in pixels) of the applet display area.
ALIGN=alignment ALIGN is an optional attribute that specifies the
alignment of the applet. Possible values are: LEFT,
RIGHT, TOP, BOTTOM, MIDDLE, BASELINE,
TEXTTOP, ABSMIDDLE, and ABSBOTTOM.
VSPACE=pixels VSPACE specifies the amount of vertical blank space,
in pixels, above and below the applet. Used only when
some vertical alignment is specified with the ALIGN
attribute (TOP, BOTTOM, etc.). This attribute is
optional.
HSPACE=pixels HSPACE specifies the amount of horizontal blank
space, in pixels, on each side of the applet. Used only
when ALIGN is set to LEFT or RIGHT. This attribute
is optional.
PARAM NAME and VALUE The PARAM tag allows us to specify applet-specific
arguments in an HTML page. Applets access their
attributes with the getParameter() method.

14.11 Passing Parameters to Applets


❖ The Applet tag in HTML allows us to pass parameters to our applet.
❖ To retrieve a parameter, use the getParameter() method.
❖ It returns the value of the specified parameter in the form of a String object.
❖ Thus, for numeric and boolean values, we will need to convert their string representations into
their internal formats.
Example:
// Passing parameters to applets
// HelloJavaParam.java
import java.awt.*;
import java.applet.*;
public class HelloJavaParam extends Applet
{

225
String str;
public void init()
{
str=getParameter("string"); // Receiving parameter value
if (str==null)
str="Java";
str="Hello"+str; // Using the value
}
public void paint(Graphics g)
{
g.drawString(str,10,20);
}
}
The HTML file for HelloJavaParam applet.
<HTML>
<!-- Parameterized HTML file -- >
<HEAD>
<TITLE>Welcome to Java Applets </TITLE>
</HEAD>
<BODY>
<APPLET CODE=HelloJavaParam.class WIDTH=400 HEIGHT=200>
<PARAM NAME=”string” VALUE=”Applet!”>
</APPLET>
</BODY>
</HTML>

❖ Save this file as HelloJavaParam.html and then run the applet using the applet viewer as follows:
appletviewer HelloJavaParam.html
14.12 Displaying Numeric Values
❖ In applets, we can display numerical values by first converting them into strings and then using
the drawString() method of Graphics class.
❖ We can do this easily by calling the valueOf() method of String class.
Example:

// Displaying numeric values


// NumericInput.java
import java.awt.*;
import java.applet.*;
/*
<applet code=”NumericInput” width=400 height=400>
</applet>
*/
public class NumericInput Extends Applet
{
public void paint(Graphics g)
{
int a=11;
int b=29;
int sum=a+b;
String S=”Sum:”+String.valueOf(sum);
226
g.drawString(S,100,100);
}
}

14.13 Getting input from the user

❖ Applets work in a graphical environment. Therefore, applets treat inputs as text strings.
❖ We must first create an area of the screen in which user can type and edit input items (which may
be any data type).
❖ We can do this by using the TextField class of the applet package. Once text fields are created for
receiving input, we can type the values in the fields and edit them, if necessary.
Example:

// Interactive input to an applet


// UserInput.java
import java.awt.*;
import java.applet.*;
/*
<applet code=”UserInput” width=300 height=200>
</applet>
*/
public class NumericInput Extends Applet
{
TextField text1, text2;
public void init()
{
text1=new TextField(10);
text2=new TextField(10);
add(text1);
add(text2);
text1.setText(“0”);
text2.setText(“0”);
}
public void paint(Graphics g)
{
int x=0, y=0, z=0;
String s1, s2, s;
g.drawString(“Input a number in each box”,10,50);
try
{
s1=text1.getText();
x=Integer.parseInt(s1);
s2=text2.getText();
y=Integer.parseInt(s2);
}
catch (Exception ex){}
z=x+y;
s=String.valueOf(z);
g.drawString(“THE SUM IS: “,10,75);
g.drawString(s,100,75);
}
227
public boolean action(Event event, Object obj)
{
repaint();
return true;
}
}
14.14 The Graphics Class
❖ The Graphics class includes methods for drawing many different types of shapes, from simple
lines to polygons to text in a variety of fonts.
❖ To display text, we can use the paint() method,and a Graphics object.
❖ To draw a shape on the screen, we may call one of the methods available in the Graphics class.
❖ Table 14.2 shows the most commonly used methods in the Graphics class.
❖ All the drawing methods have arguments representing end points, corners, or starting locations
of a shape as values in the applet’s coordinate system.
❖ To draw a shape, we only need to use the appropriate method with the required arguments.
Table 14.2 Drawing Methods of the Graphics Class

Method Description
clearRect() Erases a rectangular area of the canvas.
copyArea() Copies a rectangular area of the canvas to another area.
drawArc() Draws a hollow arc.
drawLine() Draws a straight line.
drawOval() Draws a hollow oval.
drawPolygon() Draws a hollow polygon.
drawRect() Draws a hollow rectangle.
drawRoundRect() Draws a hollow rectangle with rounded corners.
drawString() Displays a text string.
fillArc() Draws a filled arc.
fillOval() Draws a filled oval.
fillPolygon() Draws a filled polygon.
fillRect() Draws a filled rectangle.
fillRoundRect() Draws a filled rectangle with rounded corners.
getColor() Retrieves the current drawing color.
getFont() Retrieves the currently used font.
getFontMetrics() Retrieves information about the current font.
setColor() Sets the drawing color.
setFont() Sets the font.

14.15 Lines and Rectangles


drawLine()
❖ The drawLine() method is used to draw a straight line.
❖ This method takes two pair of coordinates, (x1, y1) and (x2, y2) as arguments and draws a line
between them.
❖ For example, the following statement draws a straight line from the coordinate point (10, 10) to
(50, 50);
228
g.drawLine(10, 10, 50, 50);

The g is the Graphics object passed to paint() method.

drawRect()

❖ The drawRect() method is used to draw a rectangle.


❖ This method takes four arguments. The first two represent the x and y coordinates of the top left
corner of the rectangle, and the remaining two represent the width and the height of the rectangle.
❖ For example, the statement
g.drawRect(10, 60, 40, 30)

will draw a rectangle starting at (10, 60) having a width of 40 pixels and a height of 30 pixels.
The drawRect() method draws only the outline of a box.
fillRect()
❖ The fillRect() method is used to draw a solid box.
❖ This also takes four parameters corresponding to the starting point, the width and the height of
the rectangle.
❖ For example, the statement
g.fillRect(60, 10, 30, 80);

drawRoundRect() and fillRoundrect()

❖ The drawRoundRect() and fillRoundRect() methods are used to draw rounded rectangles
(which are rectangles with rounded edges).
❖ These two methods are similar to drawRect() and fillRect() except thatthey taketwo extra
arguments representing the width and height of the angle of corners.
❖ These extra parameters indicate how much of corners will be rounded.
Example:

g.drawRoundRect(10, 100, 80, 50, 10, 10);


g.fillRoundRect(20, 110, 60, 30, 5, 5);
Example:
//Java program for drawing lines and rectangles
//LineRect.java
import java.awt.*;
import java.applet.*;
public class LineRect extends Applet
{
public void paint(Graphics g)
{
g.drawLine(10, 10, 50, 50);
g.drawRect(10, 60, 40, 30);

229
g.fillRect(60, 10, 30, 80);
g.drawRoundRect(10, 100, 80, 50, 10, 10);
g.fillRoundRect(20, 110, 60, 30, 5, 5);
g.drawLine(100, 10, 230, 140);
g.drawLine(100, 140, 230, 10);
}
}
LineRect.html
<APPLET
CODE=LineRect.class
WIDTH=250
HEIGHT=200>
</APPLET>
Output:

Applet

Applet Started

14.16 Circles and Ellipses


drawOval() and fillOval()
❖ The drawOval() method is used to draw a circle or an ellipse. Ovals are just like rectangles with
overly rounded corners.
❖ The drawOval() method takes fourarguments: the first two represent the top left corner of the
imaginary rectangle and the other two represent the height and width of the oval itself.
❖ If the width and height are the same, the oval becomes a circle.
❖ The oval’s coordinates are actually the coordinates of an enclosing rectangle.
❖ The drawOval() method draws outline of an oval, the fillOval() method draws a solid oval.
❖ The code segment shown below draws a filled circle with an oval.
setColor()
❖ The setColor() method is used to set the color of an object.
230
g.setColor(Color.green);
❖ After setting the color, all drawing operations will occur in that color.
Example:

//Java Program for drawing Ellipses


import java.awt.*;
import java.applet.*;
/*
<applet code="Ellipses" width=300 Height=300>
</applet>
*/
public class Ellipses extends Applet
{
public void paint(Graphics g)
{
g.drawOval(10,10,60,50);
g.fillOval(100,10,75,50);
g.drawOval(190,10,90,30);
g.fillOval(70,90,140,100);
}
}

Output:

14.17 Drawing Arcs


drawArc() & fillArc()
❖ The drawArc() method is used to draw an arc.
❖ The drawArc() designed to draw arcs takes six arguments. The first four are the same as the

231
arguments for drawOval() method and the last two represent the starting angle of the arc and
the number of degrees around the arc.
❖ The fillArc() method is used to fill anarc.Filled arcs are drawnas if they were sections of a pie.
Example:

//Java Program for drawing arcs


import java.awt.*;
import java.applet.*;
/*
<applet code="Arcs" width=300 Height=300>
</applet>
*/
public class Arcs extends Applet
{
public void paint(Graphics g)
{
g.drawArc(10,40,70,70,0,75);
g.fillArc(100,40,70,70,0,75);
g.drawArc(10,100,70,80,0,175);
g.fillArc(100,100,70,90,0,270);
g.drawArc(200,80,80,80,0,180);
}
}

Output:

Write a Java program to draw a human face.

//Applet for drawing a human face


import java.awt.*;
232
import java.applet.*;
/* <applet code=Face width=300 height=300></applet> */
public class Face extends Applet
{
public void paint(Graphics g)
{
g.drawOval(40, 40, 120, 150); // Head
g.drawOval(57, 75, 30, 20); // Left eye
g.drawOval(110, 75, 30, 20); // Right eye
g.fillOval(68, 81, 10, 10); // Pupil (left)
g.fillOval(121, 81, 10, 10); // Pupil (right)
g.drawOval(85, 100, 30, 30); // Nose
g.fillArc(60, 125, 80, 40, 180, 180); // Mouth
g.drawOval(25, 92, 15, 30); // Left ear
g.drawOval(160, 92, 15, 30); // Right ear
}
}
Output:

14.18 Drawing Polygons


❖ Polygons are shapes with many sides. A polygon may be considered a set of lines connected
together.
drawPoygon() & fillPolygon()

❖ The drawPolygon() method of the Graphics class is used to draw a polygon.


❖ This method takes three arguments:
• An array of integers containing x coordinates
• An array of integers containing y coordinates
• An integer for the total number of points
❖ The fillPolygon() method is used to fill a polygon.

Example:

//Java Program for drawing a Polygon


import java.awt.*;
import java.applet.*;
/*
<applet code="Polygon" width=300 Height=300>
233
</applet>
*/
public class Polygon extends Applet
{
public void paint(Graphics g)
{
int xpoints[]={30,200,30,200,30};
int ypoints[]={30,30,200,200,30};
int num=5;
g.drawPolygon(xpoints,ypoints,num);
}
}
Output:

Exercises:

1. Define applet.
2. Distinguish between applet and application.
3. Explain the various methods of Applet Class.
4. Describe the life cycle of an applet.
5. Discuss the applet display methods with an example.
6. Define <applet> tag.
7. Explain drawString method with an example program.
8. Explain about Graphics class in applets.
9. Define setColor() method.

234
10. Write an applet program to draw lines and rectangles.

11. Write an applet program to illustrate various shapes.


*****************************

*************************************************************************
Chapter 15 Introduction to Data Structures
*************************************************************************
15.1 What is a Data Structure?
❖ A Data Structure is a way of storing and organizing data in a computer so that it can be
used efficiently.
❖ Data Structures provide a means to manage large amounts of data efficiently.
❖ Efficient data structures are a key to designing efficient algorithms.
❖ Data Structures can be used to organize the storage and retrieval of information stored in
both main memory and secondary memory.

15.2 Classification of Data Structures


❖ Data Structures are normally divided into two broad categories
235
(1) Primitive Data Structures.
(2) Non-Primitive Data Structures.

Figure 15.1: Types of Data Structure


1) Primitive Data Structures
❖ The primitive data structures are primitive data types.
❖ The int, float, char and boolean are the primitive data structures that can hold a single value.
2) Non-Primitive Data Structures
❖ Data types derived from primary data types are known as Non-Primitive data types.
❖ Non-Primitive data types are used to store group of values.
❖ The Non-Primitive data structure is divided into two types:
i) Linear Data Structure
ii) Non-Linear Data Structure
i) Linear Data Structures

❖ Data Structures where data elements are arranged sequentially or linearly are
called linear data structures.
❖ Linear data structures are easy to implement because computer memory is arranged in a linear
way.
❖ Its examples are: Array, Stack, Queue, Linked List etc.
Array:
❖ An Array is a collection of data items having the same data types.
Stack:
❖ A Stack is a LIFO (Last-In First-Out) data structure where the element that is added last will be
deleted first.
❖ All operations on stack are performed from one end called TOP.
Queue:
❖ A Queue is a FIFO (First-In First-Out) data structure where the element that is added first will
be deleted first.

236
❖ In queue, insertion is performed from one end called REAR and deletion is performed from
another end called FRONT.
Linked List:
❖ A Linked List is a linear data structure, in which the elements are not stored at contiguous memory
locations.
❖ A Linked List is a collection of nodes where each node is made up of a data element and a
reference/link to the next node in the sequence.
ii) Non Linear Data Structures

❖ Data Structures where data elements are not arranged sequentially or linearly are
called non-linear data structures.
❖ Non-linear data structures are not easy to implement in comparison to linear data structure.
❖ It utilizes computer memory efficiently in comparison to a linear data structure.
❖ Its examples are: Trees and Graphs.
Trees:
❖ A tree is a non-linear data structure because it does not store in a sequential manner.
❖ It is a hierarchical structure as elements in a Tree are arranged in multiple levels.
❖ The topmost node in the hierarchy is called root node and the bottommost nodes are called leaf
nodes.
❖ Each node contains some data and a link or reference to adjacent nodes.
Graphs:
❖ A Graph is a non-linear data structure consisting of nodes and edges.
❖ The nodes are also referred to as vertices and the edges are lines that connect any two nodes in
the graph.
❖ Graphs are also used in social networks like LinkedIn, Facebook etc.
15.2 Advantages and Disadvantages of Data Structures
Advantages:
1) Allows easier processing of data.
2) It allows information stored on disk very efficiently.
3) These are necessary for designing an efficient algorithm.
4) It provides management of databases like indexing with the help of hash tables and arrays.
5) We can access data anytime and anywhere.
6) It is secure way of storage of data.
7) Graphs models real life problems
8) It allows processing of data on software system
Disadvantages:
237
1) It is applicable only for advanced users.
2) If any issue occurs it can be solved only by experts.
3) Slow access in case of some data types
15.4 Operations on Data Structures
1) Traversing: Traversing the data structure means visiting each element of the data structure in
order to perform some specific operation like searching or sorting.
Example: If we need to calculate the average of the marks obtained by a student in 5 different
subjects, we need to traverse the complete array of marks and calculate the total sum then we will
divide that sum by the number of subjects i.e. 5, in order to find the average.
2) Insertion: Insertion can be defined as the process of adding the elements to the data structure at
any location.
If the size of data structure is n then we can only insert n-1 data elements into it.
3) Deletion:The process of removing an element from the data structure is called Deletion. We can
delete an element from the data structure at any random location.
If we try to delete an element from an empty data structure then underflow occurs.
4) Searching: The process of finding the location of an element within the data structure is called
Searching. There are two algorithms to perform searching, Linear Search and Binary Search.
5) Sorting: The process of arranging the data structure in a specific order is known as Sorting. There
are many algorithms that can be used to perform sorting, for example, insertion sort, selection sort,
bubble sort, etc.
6) Merging: When two lists List A and List B of size M and N respectively, of similar type of
elements joined to produce the third list, List C of size (M+N), then this process is called merging.

15.5 DS Algorithm
What is an Algorithm?
❖ An Algorithm is a step by step procedure for solving any problem.
❖ The following are the characteristics of an algorithm:
1) Input: An algorithm has zero or more inputs.
2) Output: An algorithm has one or more outputs.
3) Definiteness: The steps in the algorithm must be clearly defined and detailed.
4) Finiteness: The algorithm must terminate after a finite number of steps.
5) Effectiveness: An algorithm is also generally expected to be effective. Effectiveness is precisely
measured after translating the algorithm into a Computer program.
Algorithm Complexity
❖ The performance of an algorithm can be measured on the basis of the following properties:
238
1. Time Complexity
2. Space Complexity
1. Time Complexity:
❖ The Time Complexity of an algorithm is the amount of time required to complete the execution.
2. Space Complexity:
❖ Space Complexity is the amount of memory used by the algorithm to execute and produce the
result.
Analysis of Algorithms
❖ There are three types of analysis that we perform on a particular algorithm.
• Best Case − Minimum time required for program execution.
• Average Case − Average time required for program execution.
• Worst Case − Maximum time required for program execution.
15.6 Asymptotic Notations
❖ Asymptotic Notations are the expressions that are used to represent the complexity of an
algorithm.
❖ There are mainly three types of asymptotic notations:
• Big-O Notation
• Omega Notation
• Theta Notation
i) Big-O Notation (O)
❖ The Big-O Notation is used to express the upper bound of an algorithm’s running time.
❖ It measures the worst case time complexity of an algorithm.
f(n) = O(g(n))
Here, f(n) and g(n) are the two functions defined for positive integers.
ii) Omega Notation (Ω)
❖ The Omega Notation is used to express the lower bound of an algorithm's running time.
❖ It measures the best case time complexity of an algorithm.
f(n) = Ω (g(n))
Here, f(n) and g(n) are the two functions defined for positive integers.
iii) Theta Notation (Θ)
❖ The Theta Notation is used to express both the lower bound and the upper bound of an
algorithm's running time.
❖ It measures thee average case time complexity of an algorithm.

f(n)= θg(n)

239
Here, f(n) and g(n) are the two functions defined for positive integers.
15.7 Abstract Data Type (ADT)
What is ADT?
❖ ADT stands for Abstract Data Type.
❖ An abstract data type is special kind of data type, whose behavior is defined by a set of
values and set of operations.
❖ The definition of ADT only mentioned what operations are to be performed but not how these
operations will be implemented.
❖ It does not specify how data will be organized in memory and what algorithms will be used
for implementing the operations.
❖ It is called “abstract” because it gives an implementation-independent view. The process of
providing only the essentials and hiding the details is known as abstraction.
❖ Some examples of ADT are Stack, Queue, List, etc.
❖ For example, an abstract stack could be defined by three operations: push, that inserts some data
items onto the stack, pop, that extracts an item from it, and peek, that allows data on top of the
stack to be examined without removal.
❖ Abstract data types are purely theoretical entities, used to simplify the description of abstract
algorithms, to classify and evaluate data structures, and to formally describe the type systems
of programming languages.
Advantages of ADT
❖ ADT is reusable and ensures robust data structure.
❖ It reduces coding efforts.
❖ Encapsulation ensures that data cannot be corrupted.
❖ ADT is based on principles of Object Oriented Programming (OOP) and Software Engineering
(SE).
❖ It specifies error conditions associated with operations.
15.8 List ADT
A list is a sequence of zero or more elements of a given type a1, a2,..., an (n=0)
n : length of the list
a1 : first element of the list
an : last element of the list
n=0 : empty list
elements can be linearly ordered according to their position in the list
We say ai precedes ai + 1, ai + 1 follows ai, and ai is at position i
Let us assume the following:
L : list of objects of type element type
240
x : an object of this type
p : of type position
END(L) : a function that returns the position following the last position in the list L
Define the following operations:
1. Insert (x, p, L)
Insert x at position p in list L
If p = END(L), insert x at the end
If L does not have position p, result is undefined
2. Locate (x, L)
returns position of x on L
returns END(L) if x does not appear
3. Retrieve (p, L)
returns element at position p on L
undefined if p does not exist or p = END(L)
4. Delete (p, L)
delete element at position p in L
undefined if p = END(L) or does not exist
5. Next (p, L)
returns the position immediately following position p
6. Prev (p, L)
returns the position previous to p

7. Makenull (L)
causes L to become an empty list and returns position END(L)
8. First (L)
returns the first position on L
9. Printlist (L)
print the elements of L in order of occurrence
15.9 Implementation of List
❖ A list can be implemented in two ways:
1. Array Based Implementation
2. Linked List Implementation
1. Array Based Implementation
❖ This implementation stores the list in an array.

241
❖ The position of each element is given by an index from 0 to n-1, where n is the number of
elements.
❖ The element with the index can be accessed in constant time (ie) the time to access does not
depend on the size of the list.
❖ The time taken to add an element at the end of the list does not depend on the size of the list.
But the time taken to add an element at any other point in the list depends on the size of the list
because the subsequent elements must be shifted to next index value. So the additions near the
start of the list take longer time than the additions near the middle or end.
❖ Similarly when an element is removed, subsequent elements must be shifted to the previous
index value. So removals near the start of the list take longer time than removals near the middle
or end of the list.
Problems with Array implementation of lists
❖ Insertion and deletion are expensive. For example, inserting at position 0 (a new first element)
requires first pushing the entire array down one spot to make room, whereas deleting the first
element requires shifting all the elements in the list up one, so the worst case of these operations
is O(n).
❖ Even if the array is dynamically allocated, an estimate of the maximum size of the list is
required. Usually this requires a high over-estimate, which wastes considerable space. This
could be a serious limitation, if there are many lists of unknown size.
❖ Simple arrays are generally not used to implement lists. Because the running time for insertion
and deletion is so slow and the list size must be known in advance.

2. Linked List Implementation


❖ The Linked List is stored as a sequence of linked nodes which are not necessarily adjacent in
memory.
❖ Each node in a linked list contains data and a reference to the next node. The list can grow and
shrink in size during execution of a program.
❖ The list can be made just as long as required. It does not waste memory space because successive
elements are connected by pointers.
❖ The position of each element is given by an index from 0 to n-1, where n is the number of
elements.
❖ The time taken to access an element with an index depends on the index because each element
of the list must be traversed until the required index is found.
❖ The time taken to add an element at any point in the list does not depend on the size of the list,
as no shifts are required
242
❖ Additions and deletion near the end of the list take longer than additions near the middle or start
of the list. Because the list must be traversed until the required index is found
Array versus Linked Lists
I. Arrays are suitable for
• Randomly accessing any element.
• Searching the list for a particular value
• Inserting or deleting an element at the end.
II. Linked lists are suitable for
• Inserting/Deleting an element.
• Applications where sequential access is required.
• In situations where the number of elements cannot be predicted beforehand.
Exercises:

1. What is Data Structure?


2. Explain the various categories of Data Structures.
3. What are linear data structures?
4. Explain the various operations on data strucures.
5. Define Time Complexity.
6. Define Space Complexity.
7. Explain asymptotic notation.
8. What is Abstract Data Type (ADT)?
9. Define list.
10. Discuss in detail how list is implemented using array.
****************************

243
************************************************************
Chapter 16 Linked Lists
************************************************************
16.1 Introduction to Linked List
❖ A Linked List is a linear data structure.
❖ A Linked List consists of a set of nodes where each node contains a data field and a reference
(link) to the next node in the list.
❖ The first node of the linked list is called the head, and the last node of the list is called the tail
of the list.
❖ A linked list is another way to collect similar data. However, unlike an array, elements in a
linked list are not stored in consecutive memory locations.
❖ It is a commonly used data structure in Computer programs and helps us to build even more
complex data structures like Stacks, Queues, etc.
❖ The Figure 16.1 illustrates a Linked List

Figure 16.1: Linked List


16.2 Advantages and Disadvantages of Linked List
Advantages of Linked List
❖ Linked list is a dynamic data structure so it can grow and shrink at runtime by allocating and
deallocating memory. So there is no need to give initial size of linked list.
❖ Data Structures such as stack and queues can be easily implemented using linked list.
❖ Insert and delete operation can be easily implemented in linked list.
❖ It reduces the access time.
Disadvantages of Linked List
❖ Reverse traversing is difficult in linked list.
❖ Linked list has to access each node sequentially; no element can be accessed randomly.
❖ In linked list, the memory is wasted as the link requires extra memory for storage.
16.3 Linked List Vs Array
❖ Array and Linked list are the two ways of organizing the data in the memory.
Array Linked list
An array is a collection of elements of a similar A linked list is a collection of objects known as a
data type. node where node consists of two parts, i.e., data
and address.
Array elements are stored in a contiguous Linked list elements can be stored anywhere in
memory location. the memory or randomly stored.

244
Array works with a static memory. Here static The Linked list works with dynamic memory.
memory means that the memory size is fixed and Here, dynamic memory means that the memory
cannot be changed at the run time. size can be changed at the run time according to
our requirements.
Array elements are independent of each other. Linked list elements are dependent on each other.
As each node contains the address of the next
node so to access the next node, we need to access
its previous node.
Array takes more time while performing any Linked list takes less time while performing any
operation like insertion, deletion, etc. operation like insertion, deletion, etc.
Accessing any element in an array is faster as the Accessing an element in a linked list is slower as
element in an array can be directly accessed it starts traversing from the first element of the
through the index. linked list.
In the case of an array, memory is allocated at In the case of a linked list, memory is allocated at
compile-time. run time.
Memory utilization is inefficient in the array. For Memory utilization is efficient in the case of a
example, if the size of the array is 6, and array linked list as the memory can be allocated or
consists of 3 elements only then the rest of the deallocated at the run time according to our
space will be unused. requirement.

16.4 Basic Operations on Linked List


❖ Traversal: To traverse all the nodes one after another.
❖ Insertion: To add a node at the given position.
❖ Deletion: To delete a node.
❖ Searching: To search an element(s) by value.
❖ Updating: To update a node.
❖ Sorting: To arrange nodes in a linked list in a specific order.
❖ Merging: To merge two linked lists into one.
16.5 Types of Linked List
❖ There are four common types of Linked List.
1. Singly Linked List
2. Doubly Linked List
3. Circular Linked List
4. Circular Doubly Linked List
1. Singly Linked List
❖ A Singly Linked List is a collection of nodes linked together in a sequential way where each
node of the singly linked list contains a data field and an address field that contains the
reference of the next node.
❖ The reference to the first node in the list is called the HEAD of the list. Head of the Linked List
only contains the Address of the First element of the List.
❖ The Last element of the Linked List contains NULL because it is the end of the List so it doesn’t
point to anything
245
❖ A Singly Linked List can be traversed in only one direction i.e. from head to the last node.
Singly Linked List Representation

Operations on Singly Linked Lists


i) Creating a Singly Linked List
❖ A singly linked list in Java can be created by using a self-referential class.
❖ A self-referential class is one that holds a reference to itself.
❖ Below is a class SinglyLinkedList that encloses an inner self-referential class Node having two
fields, a data field which is an integer and a “next” field which is of the type Node.
❖ The outer class also holds the reference/pointer/link to the HEAD of the list.
public class SinglyLinkedList
{
public Node head = null;
// Class Node that hold data and a reference/link to the next Node in the list
class Node
{
int data;
Node next;
Node(int d)
{
data = d;
next = null;
}
}
}
ii) Inserting Nodes into a Singly Linked List
❖ The Insert Operation is used to insert a new node in the linked list.
❖ There are three cases to consider for inserting a node into a singly linked list. Adding a node to
the :
a) Beginning of the list.
b) End of the list.
c) Specified position in the list.
a) Inserting a node at the beginning of the list
❖ To insert a new node at the beginning of the list the following algorithm is used :
• Assign the reference of the HEAD to the new node’s next field.
• Make the new node as the HEAD of the list.

246
Figure 16.6: Inserting a node with data N at the beginning of the list
b) Inserting a node at the end of the list
❖ To insert a node at the end of the list the following algorithm is followed –
• Traverse the list until we find the last node.
• The new node’s reference is assigned to the last node’s next field.

Figure 16.7: Inserting a node with data N at the end of the list
c) Inserting a node at a specified position in the list
❖ To insert a node at a specified position in the list the following algorithm is followed –
• Traverse (position – 1) times or till the end of the list is reached and maintain previous and
current references.
• Assign the reference of the new node to the prev node’s next field.
• Assign the cur node’s reference to the new node’s next field.

Figure 16.8: Inserting a node with data N at position 3 in the list


iii) Deleting Nodes from Singly Linked List
❖ The Delete Operation is used to delete a node from the list.
❖ Deleting a node from a singly linked list can be a little complex as the node to be deleted can
be the first node, the last node, or a node in the middle of the list.
• First Node: If the node to be deleted is the first node itself, we assign the reference of the next
of the HEAD node to the HEAD node.
• Last Node or Any Other Node: To delete any other node in the list, we traverse the list keeping
track of the previous and current nodes in the list until we find the node to be deleted with the
required data field or we reach the end of the list i.e. NULL without finding the data element in
the list.
• If the node is found, we assign the reference of the next field of the current node to the previous
node’s next.
247
Figure 16.9: Deleting any node from a singly Linked List

Example:

//Java Program to implement Singly Linked List


import java.io.*;
import java.util.*;
public class SinglyLinkedList
{
public Node head = null;
// Class Node that hold data and a reference link to the next Node in the list
class Node
{
private int data;
private Node next;
public Node(int data)
{
this.data = data;
this.next = null;
}
}

// Method to add a node at the beginning of the list


public void addNodeAtTheBeginning(int data)
{
System.out.println("Add a node with data " + data + " in the beginning.");
// Create a new node
Node newNode = new Node(data);
// Check if the list is empty
if (this.head == null)
{
// Make the new node as head
this.head = newNode;
}
else
{
// Point the new node's next to head
newNode.next = this.head;
// Make the new node as head
this.head = newNode;
}
}
// Method to add a node at the end of the list
public void addNodeAtTheEnd(int data)
{
// Create a new node
Node newNode = new Node(data);
// Check if the list is empty
248
if (this.head == null)
{
//Make the new node as head
this.head = newNode;
}
else
{
Node cur = this.head;
// Traverse to the end of the list
while (cur.next != null)
{
cur = cur.next;
}
cur.next = newNode;
}
}
// Method to add a node at the specified position in the list
public void addNodeAtPosition(int position, int data)
{
System.out.println("Add a node with data " + data + " at the position " + position);
// Create a new node
Node newNode = new Node(data);
// Init the cur and prev nodes to the head
Node cur = this.head, prev = this.head;
if (position == 1)
{
// Point the new node's next to head
newNode.next = head;
// Make the new node as head
this.head = newNode;
return;
}
//Ttraverse to the end of the list and check positions moved
while (cur.next != null && --position > 0)
{
// Update the prev and cur references
prev = cur;
cur = cur.next;
}

// Update prev to point to new node


prev.next = newNode;
// & new node to point to current node
newNode.next = cur;
}
// Method to delete the first occurrence of data in the list
public void deleteFirst(int data)
{
System.out.println("Deleting First Occurrence of data " + data + " from the list");
// Check if the list is empty
if (this.head == null)
{
System.out.println("The List is empty.\n");
return;
249
}
// Initialize the cur and prev nodes to the head
Node cur = this.head, prev = this.head;
// If the data is found at the first node assign the reference of current head's next to head
if (this.head.data == data)
{
this.head = this.head.next;
return;
}
// Traverse the list until it ends or we find the node that holds the data
while (cur != null && cur.data != data)
{
// Update the prev and cur references
prev = cur;
cur = cur.next;
}
// If the node was found, adjust the prev reference to point to the next of the node
// to be deleted.
if (cur != null)
{
prev.next = cur.next;
}
else
{
System.out.println("The data " + data + " could not be found in the List");
}
}
//Method to print the list
public void print()
{
if (this.head == null)
{
System.out.println("The List is empty.");
}
else
{
System.out.println("Singly Linked List = ");
Node cur = this.head;
while (cur != null)
{
System.out.print(cur.data + " -> ");
cur = cur.next;
}
System.out.println("NULL\n");
}
}
public static void main(String args[])
{
Scanner sc = new Scanner(System.in);
SinglyLinkedList SLL = new SinglyLinkedList();
char ch;
do
{
System.out.println("\nSingly Linked List Operations");
250
System.out.println("1. Insert at beginning");
System.out.println("2. Insert at end");
System.out.println("3. Insert at position");
System.out.println("4. Delete at position");
System.out.println("5. Printing the list");
System.out.println("6. Exit");
System.out.println("\nEnter Your Choice");
int choice = sc.nextInt();
switch (choice)
{
case 1 :
System.out.println("Enter the element to insert at the beginning");
int x=sc.nextInt();
SLL.addNodeAtTheBeginning(x);
SLL.print();
break;
case 2 :
System.out.println("Enter the element to insert at the end");
int x1=sc.nextInt();
SLL.addNodeAtTheEnd(x1);
SLL.print();
break;
case 3 :
System.out.println("Enter the element to insert at any position");
int x2= sc.nextInt() ;
System.out.println("Enter the position");
int pos = sc.nextInt();
SLL.addNodeAtPosition(pos, x2);
SLL.print();
break;
case 4 :
System.out.println("Enter the element to delete");
int x3 = sc.nextInt();
SLL.deleteFirst(x3);
SLL.print();
break;
case 5:
SLL.print();
break;
case 6 :
System.exit(0);
break;
default :
System.out.println("Wrong Choice\n ");
break;
}
System.out.println("Do you want to continue? (Type Y or N) \n");
ch = sc.next().charAt(0);
}
while (ch == 'Y'|| ch == 'y');
}
}

251
Output:
Singly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the List
6. Exit
Enter Your Choice
1
Enter the element to insert at the beginning
5
Singly Linked List = 5
Do you want to continue? (Type Y or N)
Y
Singly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the List
6. Exit
Enter Your Choice
1
Enter the element to insert at the beginning
7
Singly Linked List = 7->5
Do you want to continue? (Type Y or N)
Y
Singly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the List
6. Exit
Enter Your Choice
2
Enter the element to insert at the end
4
Singly Linked List = 7->5->4
Do you want to continue? (Type Y or N)
Y
Singly Linked List Operations
1. Insert at beginning
2. Insert at end
252
3. Insert at position
4. Delete at position
5. Printing the List
6. Exit
Enter Your Choice
2
Enter the element to insert at the end
2
Singly Linked List = 7->5->4->2
Do you want to continue? (Type Y or N)
Y
Singly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the List
6. Exit
Enter Your Choice
1
Enter the element to insert at the beginning
9
Singly Linked List = 9->7->5->4->2
Do you want to continue? (Type Y or N)
Y
Singly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the List
6. Exit
Enter Your Choice
3
Enter the element to insert at any position
3
Enter the position
3
Singly Linked List = 9->7->3->5->4->2
Do you want to continue (Type y or n)
y
Singly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the List
253
6. Exit
Enter Your Choice
3
Enter the element to insert at any position
2
Enter the position
2
Singly Linked List = 9->2->7->3->5->4->2
Do you want to continue? (Type Y or N)
Y
Singly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the List
6. Exit
Enter Your Choice
5
Singly Linked List = 9->2->7->3->5->4->2
Do you want to continue? (Type Y or N)
Y
Singly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the List
6. Exit
Enter Your Choice
4
Enter the position to delete
4
Singly Linked List = 9->2->7->5->4->2
Do you want to continue? (Type Y or N)
Y
Singly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the List
6. Exit
Enter Your Choice
5
Singly Linked List = 9->2->7->5->4->2
Do you want to continue? (Type Y or N)
254
Y
Singly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the List
6. Exit
Enter Your Choice:
6
Do you want to continue? (Type Y or N)
N
Advantages and Disadvantages of Singly Linked List
Advantages:
1) It is very easier for the accessibility of a node in the forward direction.
2) Insertions and deletions can be done easily.
3) Its size is not fixed. It can be extended or reduced according to requirements.
4) The Singly Linked List is the very easy data structure to implement.
5) It is less expensive.
Disadvantages:
1) No direct access to individual elements is possible. We have to access elements sequentially
starting from the first node.
2) A Singly Linked List uses more memory as compared to an array to store the reference to the
next node.
3) The accessing of a node is very time consuming.
4) It is not easy to sort the elements stored in the linear linked list.
Applications of Singly Linked List
❖ Linked Lists can be used to implement Stacks, Queues.
❖ Linked Lists can also be used to implement the Adjacency list representation of Graphs.
❖ A polynomial can be represented in an array or in a linked list by simply storing the coefficient
and exponent of each term.
❖ Linked lists are useful for dynamic memory allocation.
2. Doubly Linked List
❖ A Doubly Linked List is a linear data structure that consists of a sequence of elements called
nodes. Each node contains three fields: two link fields and one data field.
❖ The first link points to the previous node in the list and the second link points to the next node
in the list.

255
❖ The first node of the list has its previous link pointing to NULL similarly the last node of the
list has its next node pointing to NULL.
Doubly Linked List Representation

Advantages and Disadvantages of Doubly Linked List


Advantages of DLL:
❖ A DLL can be traversed in both forward and backward direction.
❖ It can allocate or reallocate memory easily during its execution.
❖ Insertions and Deletions can be done easily.
❖ Reversing the Doubly Linked List is very easy.
❖ Its size is not fixed.
Disadvantages of DLL:
❖ It uses extra memory when compared to the Array and Singly Linked List.
❖ Different amount of time is required to access each element.
❖ Since the elements in memory are stored randomly, therefore the elements are accessed
sequentially no direct access is allowed.
Uses of DLL:
❖ It is used in the navigation systems where front and back navigation is required.
❖ It is used by the browser to implement backward and forward navigation of visited web pages
that is a back and forward button.
❖ It is also used to represent a classic game deck of cards.
❖ It is also used by various applications to implement undo and redo functionality.
❖ Doubly Linked List is also used in constructing MRU/LRU (Most/Least Recently Used)
cache.
❖ Other data structures like Stacks, Hash Tables, and Binary Trees can also be constructed or
programmed using a Doubly Linked List.
❖ Also in many operating systems, the thread scheduler maintains a Doubly Linked List of all
processes running at that time.
Operations on Doubly Linked List
1) Inserting a node into the Doubly Linked List
❖ The Insert Operation is used to insert a new node into the Doubly Linked List.
❖ In a Doubly Linked List, a node can be added in four ways:
a) At the front of the DLL
b) After a given node
256
c) At the end of the DLL
d) Before a given node.
a) Add a node at the front: (A 5 steps process)
❖ The new node is always added before the head of the given Linked List. And newly added
node becomes the new head of DLL.

// 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;
}
b) Add a node after a given node: (A 7 steps process)
❖ We are given link to a node as prev_node, and the new node is inserted after the given 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;
}
257
/*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)
new_node.next.prev = new_node;
}
c) Add a node at the end: (7 steps process)
❖ The new node is always added after the last node of the given Linked List.
❖ Since a Linked List is typically represented by the head of it, we have to traverse the list till
end and then change the next of last node to 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, somake next of it as NULL*/
new_node.next = null;
/* 4. If the Linked List is empty, then make the newnode 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;
}

258
d) Add a node before a given node:
Steps:

1. Check if the next_node is NULL or not. If it’s NULL, return from the function because any
new node cannot be added before a NULL
2. Allocate memory for the new node, let it be called new_node
3. Set new_node->data = new_data
4. Set the previous link of this new_node as the previous node of the next_node, new_node->prev
= next_node->prev
5. Set the previous pointer of the next_node as the new_node, next_node->prev = new_node
6. Set the next pointer of this new_node as the next_node, new_node->next = next_node;
7. If the previous node of the new_node is not NULL, then set the next pointer of this previous
node as new_node, new_node->prev->next = new_node
8. Else, if the prev of new_node is NULL, it will be the new head node. So, make (*head_ref) =
new_node.

2) Deleting node in a Doubly Linked List

❖ The Delete Operation is used to delete a node from the list.


Original Doubly Linked List

❖ The deletion of a node in a doubly-linked list can be divided into three main categories:
i) Deleting the first node in a Doubly Linked List

❖ For deleting the first node, we need to change the head reference so that it starts referencing the
next node.

ii) Deleting the node at the given index in a Doubly Linked List

❖ If deleting node at index 0 that is equivalent to deleteFirst.

259
❖ If deleting node at index when (index == size-1) that is equivalent to deleteLast.
❖ Otherwise traverse to the node at the given index and change the references so that the node on
the left of the node to be deleted starts referencing the node on the right of the node to be deleted
and vice versa.

iii) Deleting the last node in a Doubly Linked List

❖ For deleting the last node in the doubly linked list change the reference for tail so that it starts
referencing the previous node.

1. If the node to be deleted is the head node then make the next node as head.
2. If a node is deleted, connect the next and previous node of the deleted node.

Example:

// Java Program to Implement Doubly Linked List


import java.io.*;
import java.util.*;
class Node
{
protected int data;
protected Node next, prev;
public Node()
{
next = null;
prev = null;
data = 0;
}
public Node(int d, Node n, Node p)
{
data = d;
next = n;
prev = p;
}
// Function to set link to next node
public void setLinkNext(Node n)
{
260
next = n;
}
// Function to set link to previous node
public void setLinkPrev(Node p)
{
prev = p;
}
// Funtion to get link to next node
public Node getLinkNext()
{
return next;
}
// Function to get link to previous node
public Node getLinkPrev()
{
return prev;
}
// Function to set data to node
public void setData(int d)
{
data = d;
}
//Function to get data from node
public int getData()
{
return data;
}
}
class DoublyLinkedList
{
protected Node start;
protected Node end ;
public int size;
public DoublyLinkedList()
{
start = null;
end = null;
size = 0;
}
// Function to check if list is empty
public boolean isEmpty()
{
return start == null;
}
// Function to get size of list
public int getSize()
{
261
return size;
}
// Function to insert element at begining
public void insertAtStart(int val)
{
Node nptr = new Node(val, null, null);
if(start == null)
{
start = nptr;
end = start;
}
else
{
start.setLinkPrev(nptr);
nptr.setLinkNext(start);
start = nptr;
}
size++;
}
// Function to insert element at end
public void insertAtEnd(int val)
{
Node nptr = new Node(val, null, null);
if(start == null)
{
start = nptr;
end = start;
}
else
{
nptr.setLinkPrev(end);
end.setLinkNext(nptr);
end = nptr;
}
size++;
}
// Function to insert element at position
public void insertAtPos(int val , int pos)
{
Node nptr = new Node(val, null, null);
if (pos == 1)
{
insertAtStart(val);
return;
}
Node ptr = start;
for (int i = 2; i <= size; i++)
262
{
if (i == pos)
{
Node tmp = ptr.getLinkNext();
ptr.setLinkNext(nptr);
nptr.setLinkPrev(ptr);
nptr.setLinkNext(tmp);
tmp.setLinkPrev(nptr);
}
ptr = ptr.getLinkNext();
}
size++ ;
}
// Function to delete element at position
public void deleteAtPos(int pos)
{
if (pos == 1)
{
if (size == 1)
{
start = null;
end = null;
size = 0;
return;
}
start = start.getLinkNext();
start.setLinkPrev(null);
size--;
return ;
}
if (pos == size)
{
end = end.getLinkPrev();
end.setLinkNext(null);
size-- ;
}
Node ptr = start.getLinkNext();
for (int i = 2; i <= size; i++)
{
if (i == pos)
{
Node p = ptr.getLinkPrev();
Node n = ptr.getLinkNext();

p.setLinkNext(n);
n.setLinkPrev(p);
size-- ;
263
return;
}
ptr = ptr.getLinkNext();
}
}
// Function to display list elements
public void display()
{
System.out.print("\nDoubly Linked List = ");
if (size == 0)
{
System.out.print("List is empty\n");
return;
}
if (start.getLinkNext() == null)
{
System.out.println(start.getData() );
return;
}
Node ptr = start;
System.out.print(start.getData()+ " <-> ");
ptr = start.getLinkNext();
while (ptr.getLinkNext() != null)
{
System.out.print(ptr.getData()+ " <-> ");
ptr = ptr.getLinkNext();
}
System.out.print(ptr.getData()+ "\n");
}
}
public class DoublyLinkedListTest
{
public static void main(String args[]) throws IOException
{
Scanner sc = new Scanner(System.in);
DoublyLinkedList dll = new DoublyLinkedList();
System.out.println("Doubly Linked List Test\n");
char ch;
do
{
System.out.println("\nDoubly Linked List Operations");
System.out.println("1. Insert at beginning");
System.out.println("2. Insert at end");
System.out.println("3. Insert at position");
System.out.println("4. Delete at position");
System.out.println("5. Printing the list");
System.out.println("6. Exit");
264
System.out.println("Enter your choice");
int choice = sc.nextInt();
switch (choice)
{
case 1 :
System.out.println("Enter the element to insert at the beginning");
dll.insertAtStart( sc.nextInt() );
dll.display();
break;
case 2 :
System.out.println("Enter the element to insert at the end");
dll.insertAtEnd(sc.nextInt());
dll.display();
break;
case 3 :
System.out.println("Enter the element to insert at the specified position");
int num = sc.nextInt() ;
System.out.println("Enter the position");
int pos = sc.nextInt() ;
if (pos < 1 || pos > list.getSize() )
{
System.out.println("Invalid position\n");
}
else
{
dll.insertAtPos(num, pos);
}
dll.display();
break;
case 4 :
System.out.println("Enter the position to delete");
int p = sc.nextInt() ;
if (p < 1 || p > list.getSize() )
{
System.out.println("Invalid position\n");
}
else
{
dll.deleteAtPos(p);
}
dll.display();
break;
case 5 :
dll.display();
break;
case 6 :
System.exit(0);
265
break;

default :
System.out.println("Wrong Choice \n ");
break;
}
System.out.println("\nDo you want to continue? (Type Y or N) \n");
ch = sc.next().charAt(0);
}
while (ch == 'Y'|| ch == 'y');
}
}
Output:

Doubly Linked List Test

Doubly Linked List Operations


1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
1
Enter the element to insert at the beginning
5
Doubly Linked List = 5
Do you want to continue? (Type Y or N)
Y
Doubly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
1
Enter the element to insert at the beginning
2
Doubly Linked List = 2 <-> 5
Do you want to continue? (Type Y or N)
Y
Doubly Linked List Operations
1. Insert at beginning
2. Insert at end
266
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
2
Enter the element to insert at the end
6
Doubly Linked List = 2 <-> 5 <-> 6
Do you want to continue? (Type Y or N)
Y
Doubly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
1
Enter the element to insert at the beginning
7
Doubly Linked List = 7 <-> 2 <-> 5 <-> 6
Do you want to continue? (Type Y or N)
Y
Doubly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
3
Enter the element to insert at the end
3
Enter position
3
Doubly Linked List = 7 <-> 2 <-> 3 <-> 5 <-> 6
Do you want to continue (Type Y or N)
Y
Doubly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
267
6. Exit
Enter your choice
4
Enter position
2
Doubly Linked List = 7 <-> 3 <-> 5 <-> 6
Do you want to continue? (Type Y or N)
Y
Doubly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
3
Enter the element to insert at the specified position
4
Enter the position
4
Doubly Linked List = 7 <-> 3 <-> 5 <-> 4 <-> 6
Do you want to continue? (Type Y or N)
Y
Doubly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
5
Doubly Linked List = 7 <-> 3 <-> 5 <-> 4 <-> 6
Do you want to continue? (Type Y or N)
Y
Doubly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
4
Enter the position to delete
1
268
Doubly Linked List = 3 <-> 5 <-> 4 <-> 6
Do you want to continue (Type Y or N)
Y
Doubly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
4
Enter the position to delete
2
Doubly Linked List = 3 <-> 4 <-> 6
Do you want to continue? (Type Y or N)
Y
Doubly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
4
Enter the position to delete
2
Doubly Linked List = 3 <-> 6
Do you want to continue? (Type Y or N)
Y

Doubly Linked List Operations


1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
4
Enter the position to delete
1
Doubly Linked List = 6
Do you want to continue? (Type Y or N)
Y
Doubly Linked List Operations
269
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
5
Doubly Linked List = 6
Do you want to continue? (Type Y or N)
Y
Doubly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
6
Do you want to continue? (Type Y or N)
Y
3) Circular Linked List
❖ A Circular Linked List is a variation of a linked list in which the last node points to the
first node of the list.
❖ A Circular Linked List doesn't have a null element at the end.
Circular Linked List Representation

Advantages and Disadvantages of Circular Linked List


Advantages of a Circular Linked List
❖ The list can be traversed from any node.
❖ Circular Linked Lists are the required data structure when we want a list to be accessed in a
circle or loop.
❖ This is very useful in the implementation of the queue data structure.
Disadvantages of Circular Linked List
❖ If not traversed carefully, then we could end up in an infinite loop because here we don't have
any NULL value to stop the traversal.
❖ Operations in a Circular Linked List are complex as compared to a Singly Linked List and
Doubly Linked List like reversing a circular linked list, etc.

270
Operations on Circular Linked List
1) Insertion on a Circular Linked List
❖ A node can be added in three ways:
1) Insertion at the beginning
2) Insertion at the end
3) Insertion in between the nodes
❖ Suppose we have a Circular Linked List with elements 1, 2, and 3.

Figure 16.10: Initial Circular Linked List


❖ Let's add a node with value 6 at different positions of the circular linked list we made above.
❖ The first step is to create a new node.
a) Allocate memory for newNode
b) Assign the data to newNode

New Node

a) Insertion at the Beginning


❖ Store the address of the current first node in the newNode (i.e. pointing the newNode to the
current first node)
❖ Point the last node to newNode (i.e making newNode as head)

Figure 16.11: Insertion at the beginning


b) Insertion at the end
❖ Store the address of the head node to next of newNode (making newNode the last node)
❖ Point the current last node to newNode
❖ Make newNode as the last node

Figure 16.12: Insertion at the end


c) Insertion in between two nodes
❖ Travel to the node given (let this node be p)

271
❖ Point the next of newNode to the node next to p
❖ Store the address of newNode at next of p

Figure 16.13: Insert at a node

2) Deletion on a Circular Linked List


❖ Suppose we have a Circular Linked List with elements 1, 2, and 3.

Figure 16.14: Initial Circular Linked List


❖ A node can be deleted in three ways:
a. Delete the first node
b. Delete the last node
c. Delete the specified node
i) Delete the first node
• If the node to be deleted is the only node
❖ Free the memory occupied by the node
❖ Store NULL in last
ii) Delete the last node
❖ Find the node before the last node (let it be temp)
❖ Store the address of the node next to the last node in temp
❖ Free the memory of last
❖ Make temp as the last node

Figure 16.15: Delete the last node

iii) Delete the specified node


❖ Travel to the node to be deleted (here we are deleting node 2)
❖ Let the node before node 2 be temp
❖ Store the address of the node next to 2 in temp
❖ Free the memory of 2

272
Figure 16.16: Delete the specified node

3) Traversing the List


❖ Traverse operation is a process of examining all the nodes of linked list from one end to the
other end.
Example:
// Java Program to Implement Circular Linked List
import java.io.*;
import java.util.*;
class Node
{
protected int data;
protected Node link;
public Node()
{
link = null;
data = 0;
}
public Node(int d,Node n)
{
data = d;
link = n;
}
// Function to set link to next Node
public void setLink(Node n)
{
link = n;
}
// Function to set data to current Node
public void setData(int d)
{
data = d;
}
// Function to get link to next node
public Node getLink()
{
return link;
}
// Function to get data from current Node
public int getData()
{
return data;
}
}

273
class CircularSinglyLinkedList
{
protected Node start ;
protected Node end ;
public int size ;
public CircularSinglyLinkedList()
{
start = null;
end = null;
size = 0;
}
// Function to check if list is empty
public boolean IsEmpty()
{
return start == null;
}
// Function to get size of the list
public int getSize()
{
return size;
}
// Function to insert element at the begining
public void InsertAtStart(int val)
{
Node nptr = new Node(val,null);
nptr.setLink(start);
if(start == null)
{
start = nptr;
nptr.setLink(start);
end = start;
}
else
{
end.setLink(nptr);
start = nptr;
}
size++ ;
}
// Function to insert element at end
public void InsertAtEnd(int val)
{
Node nptr = new Node(val,null);
nptr.setLink(start);
if(start == null)
{
start = nptr;
nptr.setLink(start);
end = start;
}
else
{
end.setLink(nptr);
end = nptr;
274
}
size++ ;
}
// Function to insert element at position
public void InsertAtPos(int val , int pos)
{
Node nptr = new Node(val,null);
Node ptr = start;
pos = pos - 1 ;
for (int i = 1; i < size - 1; i++)
{
if (i == pos)
{
Node tmp = ptr.getLink() ;
ptr.setLink( nptr );
nptr.setLink(tmp);
break;
}
ptr = ptr.getLink();
}
size++ ;
}
// Function to delete element at position
public void DeleteAtPos(int pos)
{
if (size == 1 && pos == 1)
{
start = null;
end = null;
size = 0;
return ;
}
if (pos == 1)
{
start = start.getLink();
end.setLink(start);
size--;
return ;
}
if (pos == size)
{
Node s = start;
Node t = start;
while (s != end)
{
t = s;
s = s.getLink();
}
end = t;
end.setLink(start);
size --;
return;
}
Node ptr = start;
275
pos = pos - 1 ;
for (int i = 1; i < size - 1; i++)
{
if (i == pos)
{
Node tmp = ptr.getLink();
tmp = tmp.getLink();
ptr.setLink(tmp);
break;
}
ptr = ptr.getLink();
}
size-- ;
}
// Function to display contents
public void Display()
{
System.out.print("\nCircular Singly Linked List = ");
Node ptr = start;
if (size == 0)
{
System.out.print("List is empty\n");
return;
}
if (start.getLink() == start)
{
System.out.print(start.getData()+ "->"+ptr.getData()+ "\n");
return;
}
System.out.print(start.getData()+ "->");
ptr = start.getLink();
while (ptr.getLink() != start)
{
System.out.print(ptr.getData()+ "->");
ptr = ptr.getLink();
}
System.out.print(ptr.getData()+ "->");
ptr = ptr.getLink();
System.out.print(ptr.getData()+ "\n");
}
}
public class CircularSinglyLinkedListTest
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
CircularSinglyLinkedList CSLL = new CircularSinglyLinkedList();
System.out.println("Circular Singly Linked List Test\n");
char ch;
do
{
System.out.println("\nCircular Singly Linked List Operations");
System.out.println("1. Insert at beginning");
System.out.println("2. Insert at end");
276
System.out.println("3. Insert at position");
System.out.println("4. Delete at position");
System.out.println("5. Printing the List");
System.out.println("6. Exit");
System.out.println("Enter your choice");
int choice = sc.nextInt();
switch (choice)
{
case 1 :
System.out.println("Enter the element to insert at the beginning");
CSLL.InsertAtStart( sc.nextInt() );
CSLL.Display();
break;
case 2 :
System.out.println("Enter the element to insert at the end");
CSLL.InsertAtEnd( sc.nextInt() );
CSLL.Display();
break;
case 3 :
System.out.println("Enter the element to insert at the specified position");
int num = sc.nextInt();
System.out.println("Enter the position");
int pos = sc.nextInt() ;
if (pos <= 1 || pos > cll.getSize() )
{
System.out.println("Invalid Position\n");
}
else
{
CSLL.InsertAtPos(num, pos);
}
CSLL.Display();
break;
case 4 :
System.out.println("Enter the position to delete");
int p = sc.nextInt() ;
if (p < 1 || p > list.getSize() )
{
System.out.println("Invalid position\n");
}
else
{
CSLL.DeleteAtPos(p);
}
CSLL.Display();
break;
case 5 :
CSLL.Display();
break;
case 6 :
System.exit(0);
break;
default :
System.out.println("Wrong Choice \n ");
277
break;
}
System.out.println("\nDo you want to continue? (Type Y or N) \n");
ch = sc.next().charAt(0);
}
while (ch == 'Y'|| ch == 'y');
}
}
Output:
Circular Singly Linked List Test
Circular Singly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
1
Enter the element to insert at the beginning
4
Circular Singly Linked List = 4->4
Do you want to continue? (Type Y or N)
Y
Circular Singly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
1
Enter the element to insert at the beginning
1
Circular Singly Linked List = 1->4->1
Do you want to continue (Type Y or N)
Y
Circular Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
2
Enter the element to insert at the end
3
Circular Singly Linked List = 1->4->3->1
Do you want to continue? (Type Y or N)
278
Y
Circular Singly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
2
Enter the element to insert at the end
7
Circular Singly Linked List = 1->4->3->7->1
Do you want to continue? (Type Y or N)
Y
Circular Singly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
3
Enter the element to insert to insert at the specified position
24
Enter the position
3
Circular Singly Linked List = 1->4->24->3->7->1
Do you want to continue? (Type Y or N)
Y
Circular Singly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
5
Circular Singly Linked List = 1->4->24->3->7->1
Do you want to continue? (Type Y or N)
Y

Circular Singly Linked List Operations


1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
4
Enter the position to delete
279
1
Circular Singly Linked List = 4->24->3->7->4
Do you want to continue? (Type Y or N)
Y
Circular Singly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
1
Enter the element to insert at the beginning
2
Circular Singly Linked List = 2->4->24->3->7->2
Do you want to continue? (Type Y or N)
Y
Circular Singly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
4
Enter the position to delete
1
Circular Singly Linked List = 4->24->3->7->4
Do you want to continue? (Type Y or N)
Y
Circular Singly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
4
Enter the position
2
Circular Singly Linked List = 4->3->7->4
Do you want to continue? (Type Y or N)
Y
Circular Singly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
280
5
Circular Singly Linked List = 4->3->7->4
Do you want to continue? (Type Y or N)
Y
Circular Singly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
6
Do you want to continue? (Type Y or N)
Nst:

4. Circular Doubly Linked List


❖ Circular Doubly Linked List is a linear data structure which consists of a set of sequentially
linked data items called nodes.
❖ Each node has two links one pointing to the next node in the list and one pointing to the previous
node in the list and the last node’s ‘next link’ points to the first node and the first node’s
‘previous link’ points to the last node.
❖ Circular Doubly Linked List doesn't contain NULL in any of the node.
❖ Circular Doubly Linked Lists are similar to Doubly Linked Lists. Both are dynamic data
structures. Any data type can be stored in both the data structures.
Circular Doubly Linked List Representation

Advantages and disadvantages of Circular Doubly Linked List:


Advantages:
❖ List can be traversed from both the directions i.e. from head to tail or from tail to head.
❖ Jumping from head to tail or from tail to head is done in constant time
❖ Circular Doubly Linked Lists are used for implementation of advanced data structures like
Fibonacci Heap.
Disadvantages:
❖ It takes slightly extra memory in each node to accommodate previous link.
❖ Lots of references/link involved while implementing or doing operations on a list. So, pointers
should be handled carefully otherwise data of the list may get lost.
Applications of Circular Doubly Linked List
❖ Managing songs playlist in media player applications.
281
❖ Managing shopping cart in online shopping.
Operations on Circular Doubly Linked Lists
❖ There are various operations which can be performed on circular doubly linked list. The node
structure of a circular doubly linked list is similar to doubly linked list.
1) Insertion in Circular Doubly Linked List
❖ Insertion operation in a Circular Doubly Linked List can be done in the following ways:
• Insertion at the end of list or in an empty list
• Insertion at the beginning of the list
• Insertion in between the nodes of the list
• Empty List (start = NULL): A node (Say N) is inserted with data = 5, so previous link of N
points to N and next link of N also points to N. But now start link points to the first node the
list.

• List initially contain some nodes, start points to first node of the List: A node(Say M) is
inserted with data = 7, so previous link of M points to last node, next link of M points to first
node and last node’s next link points to this M node and first node’s previous link points to
this M node.

54

4
• Insertion at the beginning of the list: To insert a node at the beginning of the list, create a
node(Say T) with data = 5, T’s next link points to first node of the list, T’s previous link points
to last node the list, last node’s next link points to this T node, first node’s previous link also
points this T node.

282
• Insertion in between the nodes of the list: To insert a node in between the list, two data
values are required one after which new node will be inserted and another is the data of the
new node.

eting
2) Deleting a node from a Circular Doubly Linked List
Given a ‘key’, delete the first occurrence of this key in the circular doubly linked list.
Algorithm
Case 1: Empty List(start = NULL)
• If the list is empty, simply return it.
Case 2: The List initially contains some nodes, start points at the first node of the List

1. If the list is not empty, then we define two pointers curr and prev_1 and initialize the
pointer curr points to the first node of the list and prev_1 = NULL.
2. Traverse the list using the curr pointer to find the node to be deleted and before moving
from curr to the next node, every time set prev_1 = curr.
3. If the node is found, check if it is the only node in the list. If yes, set start = NULL and free
the node pointing by curr.
4. If the list has more than one node, check if it is the first node of the list. The condition to check
this is (curr == start). If yes, then move prev_1 to the last node(prev_1 = start -> prev). After
prev_1 reaches the last node, set start = start -> next and prev_1 -> next = start and start ->
prev = prev_1. Free the node pointing by curr.
5. If curr is not the first node, we check if it is the last node in the list. The condition to check
this is (curr -> next == start). If yes, set prev_1 -> next = start and start -> prev = prev_1. Free
the node pointing by curr.
6. If the node to be deleted is neither the first node nor the last node, declare one more
pointer temp and initialize the pointer temp points to the next of curr pointer (temp = curr-
>next). Now set, prev_1 -> next = temp and temp ->prev = prev_1. Free the node pointing by
curr.
• If the given key(Say 4) matches with the first node of the list(Step 4):

283
• If the given key(Say 8) matches with the last node of the list(Step 5):

• If the given key(Say 6) matches with the middle node of the list(Step 6):

Example:

// Java Program to Implement Circular Doubly Linked List


import java.io.*;
import java.util.*;
class Node
{
protected int data;
protected Node next, prev;
public Node()
{
next = null;
prev = null;
data = 0;
}
public Node(int d, Node n, Node p)
{
data = d;
next = n;
prev = p;
}
// Function to set link to next node
public void setLinkNext(Node n)
{
284
next = n;
}
// Function to set link to previous node
public void setLinkPrev(Node p)
{
prev = p;
}

// Funtion to get link to next node


public Node getLinkNext()
{
return next;
}
// Function to get link to previous node
public Node getLinkPrev()
{
return prev;
}
// Function to set data to node
public void setData(int d)
{
data = d;
}
// Function to get data from node
public int getData()
{
return data;
}
}
class CircularDoublyLinkedList
{
protected Node start;
protected Node end ;
public int size;
public CircularDoublyLinkedList()
{
start = null;
end = null;
size = 0;
}
// Function to check if list is empty
public boolean isEmpty()
{
return start == null;
}
// Function to get size of list
public int getSize()
285
{
return size;
}
// Function to insert element at begining
public void InsertAtStart(int val)
{
Node nptr = new Node(val, null, null);
if (start == null)
{
nptr.setLinkNext(nptr);
nptr.setLinkPrev(nptr);
start = nptr;
end = start;
}
else
{
nptr.setLinkPrev(end);
end.setLinkNext(nptr);
start.setLinkPrev(nptr);
nptr.setLinkNext(start);
start = nptr;
}
size++ ;
}
//Function to insert element at end
public void InsertAtEnd(int val)
{
Node nptr = new Node(val, null, null);
if (start == null)
{
nptr.setLinkNext(nptr);
nptr.setLinkPrev(nptr);
start = nptr;
end = start;
}
else
{
nptr.setLinkPrev(end);
end.setLinkNext(nptr);
start.setLinkPrev(nptr);
nptr.setLinkNext(start);
end = nptr;
}
size++;
}
// Function to insert element at position
public void InsertAtPos(int val , int pos)
286
{
Node nptr = new Node(val, null, null);
if (pos == 1)
{
InsertAtStart(val);
return;
}
Node ptr = start;
for (int i = 2; i <= size; i++)
{
if (i == pos)
{
Node tmp = ptr.getLinkNext();
ptr.setLinkNext(nptr);
nptr.setLinkPrev(ptr);
nptr.setLinkNext(tmp);
tmp.setLinkPrev(nptr);
}
ptr = ptr.getLinkNext();
}
size++ ;
}
// Function to delete node at position
public void DeleteAtPos(int pos)
{
if (pos == 1)
{
if (size == 1)
{
start = null;
end = null;
size = 0;
return;
}
start = start.getLinkNext();
start.setLinkPrev(end);
end.setLinkNext(start);
size--;
return ;
}
if (pos == size)
{
end = end.getLinkPrev();
end.setLinkNext(start);
start.setLinkPrev(end);
size-- ;
}
287
Node ptr = start.getLinkNext();
for (int i = 2; i <= size; i++)
{
if (i == pos)
{
Node p = ptr.getLinkPrev();
Node n = ptr.getLinkNext();
p.setLinkNext(n);
n.setLinkPrev(p);
size-- ;
return;
}
ptr = ptr.getLinkNext();
}
}
// Function to display the list
public void Display()
{
System.out.print("Circular Doubly Linked List = ");
Node ptr = start;
if (size == 0)
{
System.out.print("List is empty\n");
return;
}
if (start.getLinkNext() == start)
{
System.out.print(start.getData()+ " <-> "+ptr.getData()+ "\n");
return;
}
System.out.print(start.getData()+ " <-> ");
ptr = start.getLinkNext();
while (ptr.getLinkNext() != start)
{
System.out.print(ptr.getData()+ " <-> ");
ptr = ptr.getLinkNext();
}
System.out.print(ptr.getData()+ " <-> ");
ptr = ptr.getLinkNext();
System.out.print(ptr.getData()+ "\n");
}
}
public class CircularDoublyLinkedListTest
{
public static void main(String args[])
{
Scanner sc = new Scanner(System.in);
288
CircularDoublyLinkedList CDLL = new CircularDoublyLinkedList();
System.out.println("Circular Doubly Linked List Test\n");
char ch;
do
{
System.out.println("\nCircular Doubly Linked List Operations");
System.out.println("1. Insert at beginning");
System.out.println("2. Insert at end");
System.out.println("3. Insert at position");
System.out.println("4. Delete at position");
System.out.println("5. Printing the list");
System.out.println("6. Exit");
System.out.println("Enter your choice");
int choice = sc.nextInt();
switch (choice)
{
case 1 :
System.out.println("Enter element to insert at the beginning");
CDLL.InsertAtStart( sc.nextInt() );
CDLL.Display();
break;
case 2 :
System.out.println("Enter the element to insert at the end");
CDLL.InsertAtEnd( sc.nextInt() );
CDLL.Display();
break;
case 3 :
System.out.println("Enter the element to insert at the specified position");
int num = sc.nextInt() ;
System.out.println("Enter the position");
int pos = sc.nextInt() ;
if (pos < 1 || pos > list.getSize() )
{
System.out.println("Invalid Position\n");
}
else
{
CDLL.InsertAtPos(num, pos);
}
CDLL.display();
break;
case 4 :
System.out.println("Enter the position to delete");
int p = sc.nextInt() ;
if (p < 1 || p > list.getSize() )
{
System.out.println("Invalid Position\n");
289
}
else
{
CDLL.DeleteAtPos(p);
}
CDLL.Display();
break;

case 5 :
CDLL.Display();
break;
case 6 :
System.exit(0);
break;
default :
System.out.println("Wrong Choice \n ");
break;
}
System.out.println("\nDo you want to continue? (Type Y or N) \n");
ch = sc.next().charAt(0);
}
while (ch == 'Y'|| ch == 'y');
}
}
Ouput:
Circular Doubly Linked List Test

Circular Doubly Linked List Operations


1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
1
Enter the element to insert at the beginning
5
Circular Doubly Linked List = 5 <-> 5
Do you want to continue? (Type Y or N)
Y
Circular Doubly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice

290
1
Enter the element to insertaat the beginning
7
Circular Doubly Linked List = 7 <-> 5 <-> 7
Do you want to continue? (Type Y or N)
Y
Circular Doubly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
2
Enter the element to insert at the end
3
Circular Doubly Linked List = 7 <-> 5 <-> 3 <-> 7
Do you want to continue? (Type Y or N)
Y
Circular Doubly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
3
Enter the element to insert at the specified position
2
Enter the position
2
Circular Doubly Linked List = 7 <-> 2 <-> 5 <-> 3 <-> 7
Do you want to continue? (Type Y or N)
Y
Circular Doubly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
3
Enter the element to insert at the specified position
4
Enter position
4
Circular Doubly Linked List = 7 <-> 2 <-> 5 <-> 4 <-> 3 <-> 7
Do you want to continue? (Type Y or N)
Y
Circular Doubly Linked List Operations
1. Insert at beginning
291
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
4
Enter the position to delete
1
Circular Doubly Linked List = 2 <-> 5 <-> 4 <-> 3 <-> 2
Do you want to continue (Type Y or N)
Y
Circular Doubly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
1
Enter the element to insert at the beginning
1
Circular Doubly Linked List = 1 <-> 2 <-> 5 <-> 4 <-> 3 <-> 1
Do you want to continue? (Type Y or N)
Y
Circular Doubly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
4
Enter the position to delete
1
Circular Doubly Linked List = 2 <-> 5 <-> 4 <-> 3 <-> 2
Do you want to continue? (Type Y or N)
Y
Circular Doubly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
4
Enter the position to delete
1
Circular Doubly Linked List = 5 <-> 4 <-> 3 <-> 5
Do you want to continue? (Type Y or N)
Y
292
Circular Doubly Linked List Operations
1. Insert at beginning
2. Insert at end
3. Insert at position
4. Delete at position
5. Printing the list
6. Exit
Enter your choice
5
Circular Doubly Linked List = 5 <-> 4 <-> 3 <-> 5
Do you want to continue? (Type Y or N)
N
Exercises:
1. What is a Linked List?
2. Differentiate Linked List vs Array.
3. Explain the various types of Linked Lists.
4. Explain briefly about the operations on Linked List.
5. Define Doubly Linked List.
6. Define Circular Linked List.
7. How do you create Singly Linked List?
8. Explain in detail about Doubly Linked List.
9. Discuss in detail about Circular Singly Linked List representation.
10. Write a Java program to implement Circular Singly Linked List.
11. Discuss in detail about Circular Doubly Linked List representation.
******************************

293
************************************************************
Chapter 17 Stacks
************************************************************
17.1 Introduction
❖ A Stack is a linear data structure that follows the LIFO (Last-In-First-Out) principle.
❖ A stack is an ordered collection of items where the addition of new items and the removal of
existing items always take place at the same end. This end is commonly referred to as the “top”.
❖ The most recently added item is always on the top of the stack and thus will be removed first.
❖ There are many examples of stacks in everyday situations. Consider a stack of plates on a table,
where it’s only possible to add or remove plates to or from the top. Or imagine a stack of books
on a desk. The only book whose cover is visible is the one on top. To access the others, we must
first remove the ones sitting on top of them.

Figure 17.1: A stack of books


17.2 Stack ADT
❖ “A stack is an ordered list in which all insertions and deletions are made at one end, called
the top”. Stacks are sometimes referred to as Last-In-First-Out (LIFO) lists.

Figure 17.2: Stack Data Structure


17.3 Operations on Stack
1) PUSH Operation
❖ Adding an element into the TOP of the stack is referred to as PUSH operation.
❖ The new element is inserted at the top of the stack.
2) POP Operation
❖ Deleting or removing element from the TOP of the stack is called POP operation.
❖ The value of the variable top will be decremented by 1 whenever an item is deleted from the
stack.

3) PEEK Operation
294
❖ Peek operation retrieves the element present at the top of the stack.
❖ The element retrieved does not get deleted or removed from the Stack.
17.4 Implementation of Stack Data Structure
❖ Stack can be easily implemented using an Array or a Linked List.
❖ Arrays are quick, but are limited in size and Linked List requires overhead to allocate, link,
unlink, and deallocate, but is not limited in size.
1) Array Implementation of Stack
❖ Stack can be implemented using one-dimensional array.
❖ One-dimensional array is used to hold elements of a stack.
❖ Implementing a stack using array can store fixed number of data values.
❖ In a stack, initially top is set to -1. Top is used to keep track of the index of the topmost element.
i) Algorithm for PUSH operation
1. Check if the stack is full or not.
2. If the stack is full, then print overflow error and exit the program.
3. If the stack is not full, then increment the top and add the element.

ii) Algorithm for POP operation


1. Check if the stack is empty or not.
2. If the stack is empty, then print underflow error and exit the program.
3. If the stack is not empty, then delete the element at the top and decrement the top.

iii) Algorithm for Peek Operation


❖ Check if the stack is empty or not.
❖ If the stack is empty, then print underflow error and exit the program.
❖ If the stack is not empty, then print the element at the top.

Example:

//Java Program to implement the Stack using Arrays


295
import java.io.*;
import java.util.*;
class MyStack
{
static final int MAX = 1000;
int top=-1;
int stk[] = new int[MAX];
boolean empty()
{
if(top >= 0)
{
return false;
}
else
{
return true;
}
}
// Function to push the element into the stack
void push(int num)
{
if(top == MAX)
{
System.out.println("\n Stack is full");
}
else
{
stk[++top] = num;
System.out.println("\n "+num+" is inserted into the stack");
}
}
// Function to pop the element from the stack
int pop()
{
if(top < 0)
{
System.out.println("\nStack is empty");
return 0;
}
else
{
int x = stk[top--];
System.out.println("\n "+x+" has been removed from stack");
return x;
}
}
// Function to return the topmost element
int peek()
{
if(empty())
{
System.out.println("\nStack is empty");
return 0;
}
296
else
{
System.out.println("\nThe top most position of the stack holds "+stk[top]);
return stk[top];
}
}
// Function to display the stack elements
void display()
{
if(empty())
{
System.out.println("\nStack is empty");
}
else
{
System.out.print("Stack: ");
for(int i=0; i<=top; i++)
{
System.out.print(stk[i]+" ");
}
}
}
}
class Stack
{
public static void main(String args[])
{
System.out.println("\nStack Implementation using Array\n");
Scanner sc = new Scanner(System.in);
int ch, x;
MyStack s = new MyStack();
do
{
System.out.println("\n1. PUSH\n 2. POP\n 3. PEEK\n 4. DISPLAY\n 5. QUIT\n");
System.out.println("Enter your choice");
ch = sc.nextInt();
switch(ch)
{
case 1:
System.out.println("Enter the element to insert");
x = sc.nextInt();
s.push(x);
break;
case 2:
s.pop();
break;
case 3:
s.peek();
break;

case 4:
s.display();
break;
case 5:
297
System.exit(0);
break;
default:
System.out.println("Wrong Choice");
break;
}
}
while(ch<=5);
}
}

Output:

Stack Implementation using Array

1. PUSH
2. POP
3. PEEK
4. DISPLAY
5. QUIT
Enter your choice:
1
Enter the element to insert
8
8 is inserted into the stack

1. PUSH
2. POP
3. PEEK
4. DISPLAY
5. QUIT
Enter your choice
1
Enter the element to insert
30
30 is inserted into the stack

1. PUSH
2. POP
3. PEEK
4. DISPLAY
5. QUIT
Enter your choice
4
Stack: 8 30

1. PUSH
2. POP
3. PEEK
4. DISPLAY
5. QUIT
Enter your choice
3
298
The top most position of the stack holds 30

1. PUSH
2. POP
3. PEEK
4. DISPLAY
5. QUIT
Enter your choice
2
30 has been removed from stack

1. PUSH
2. POP
3. PEEK
4. DISPLAY
5. QUIT
Enter your choice
4
Stack: 8

1. PUSH
2. POP
3. PEEK
4. DISPLAY
5. QUIT
Enter your choice
5
2) Linked List Implementation of Stack
❖ A stack can be easily implemented through the linked list.
❖ In linked list implementation of stack, the nodes are maintained non-contiguously in the
memory.
❖ Each node contains a link to its immediate successor node in the stack.
❖ The topmost node in the stack always contains null in its address field.
❖ The main advantage of using linked list over an array is that it is possible to implement a stack
that can shrink or grow as much as needed. While using an array, we will put a restriction to
the maximum capacity of the array which can lead to stack overflow. Here each new node
will be dynamically allocated. So overflow is not possible.

Push and Pop operations in linked list


1. Adding a node to the stack (Push operation)

299
❖ Adding a node to the stack is referred to as push operation.
❖ In order to push an element onto the stack, the following steps are involved.
• Create a newNode with the given data.
• Check whether the stack is empty (TOP == NULL).
• If it is empty, then set the pointer of the node to NULL.
• If it is not empty, then make the node point to TOP.
• Finally, make the newNode as TOP.
2. Deleting a node from the stack (POP Operation)
❖ Deleting a node from the top of stack is referred to as pop operation.
❖ In order to pop an element from the stack, we need to follow the following steps :
• Check whether stack is empty (top == NULL).
• If it is empty, then display "EMPTY STACK"
• If it is not empty, then create a temporary node and set it to TOP.
• Print the data of TOP.
• Make TOP to point to the next node.
• Delete the temporary node.
3. Display the nodes (Traversing)

❖ Displaying all the nodes of a stack needs traversing all the nodes of the linked list organized in
the form of stack.
❖ For this purpose, we need to follow the following steps.
1. Copy the head pointer into a temporary pointer.
2. Move the temporary pointer through all the nodes of the list and print the value field

Example:

//Java Program to implement the Stack Operations using Linked List


import java.io.*;
class Node
{
public int data;
public Node next;
public Node(int x)
{
data=x;
}
public void display()
{
System.out.println(data+" ");
}
}
class Stack
{
300
public Node first;
public Stack()
{
first=null;
}
public boolean isEmpty()
{
return(first==null);
}
// Function to push the element into the stack
public void push(int value)
{
Node newnode=new Node(value);
newnode.next=first;
first=newnode;
}
// Function to pop the element from the stack
public int pop()
{
if(isEmpty())
{
System.out.println("\nStack is Empty...");
return 0;
}
else
{
int r1=first.data;
first=first.next;
return r1;
}
}
// Function to display the stack elements
public void display()
{
Node current=first;
while(current!=null)
{
System.out.print(" "+current.data);
current=current.next;
}
System.out.println("");
}
}
class StackList
{
public static void main(String args[]) throws IOException
{
Stack S=new Stack();
int ch;
do
{
System.out.println("Select 1. Push 2. Pop 3. Display 4. Exit");
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
ch=Integer.parseInt(br.readLine());
301
switch(ch)
{
case 1:
System.out.println("Enter the number of elements to push");
int n1=Integer.parseInt(br.readLine());
System.out.println("Enter the elements:\n");
for(int i=0; i<n1; i++)
{
S.push(Integer.parseInt(br.readLine()));
}
break;
case 2:
System.out.println("\nEnter the number of elements to pop: ");
int n2=Integer.parseInt(br.readLine());
for(int i=0; i<n2; i++)
{
System.out.println(S.pop()+" is popped from stack... ");
}
break;
case 3:
System.out.println("\nThe current stack items:");
S.display();
break;
default:
break;
}
}
while(ch!=4);
}
}

Output:
Select 1. Push 2. Pop 3. Display 4. Exit
1
Enter the number of elements to push
3
Enter the elements:
10
20
30
Select 1. Push 2. Pop 3. Display 4. Exit
3
The current stack items:
30 20 10
Select 1. Push 2. Pop 3. Display 4. Exit
2
Enter the number of elements to pop:
1
30 is popped from stack...
Select 1. Push 2. Pop 3. Display 4. Exit
302
3
The current stack items:
20 10
Select 1. Push 2. Pop 3. Display 4. Exit
4
17.5 Applications of Stack
1) Expression Evaluation
❖ Stack is used to evaluate prefix, postfix and infix expressions.
2) Expression Conversion
❖ An expression can be represented in prefix, postfix or infix notation. Stack can be used to
convert one form of expression to another. This is one of the most important applications of
stack.
3) Syntax Parsing
❖ Many compilers use a stack for parsing the syntax of expressions, program blocks etc. before
translating into low level code.
4) Backtracking
❖ Suppose we are finding a path for solving maze problem. We choose a path and after following
it we realize that it is wrong. Now we need to go back to the beginning of the path to start with
new path. This can be done with the help of stack.
5) Parenthesis Checking
❖ Stack is used to check the proper opening and closing of parenthesis.
6) String Reversal
❖ Stack is used to reverse a string. We push the characters of string one by one into stack and then
pop character from stack.
7) Recursion
❖ The recursion means that the function is calling itself again. To maintain the previous states,
the compiler creates a system stack in which all the previous records of the function are
maintained.
8) DFS (Depth First Search)
❖ This search is implemented on a Graph, and Graph uses the stack data structure.
9) Function Call
❖ Stack is used to keep information about the active functions or subroutines.
10) Memory Management
❖ The stack manages the memory. The memory is assigned in the contiguous memory blocks.
The memory is known as stack memory as all the variables are assigned in a function call stack
memory. The memory size assigned to the program is known to the compiler. When the function

303
is created, all its variables are assigned in the stack memory. When the function completed its
execution, all the variables assigned in the stack are released.
17.6 Evaluating Arithmetic Expressions
❖ Stack data structure is used for evaluating the given expression.
❖ There are three ways of writing an expression: Infix, Prefix, and Postfix.
❖ Computers evaluate expressions in Prefix or Postfix, whereas humans are more familiar with
Infix way of denoting an expression.
❖ Conversion from one form of the expression to another form needs a stack.
Infix, Prefix and Postfix Notation
❖ An arithmetic expression can be written in three different but equivalent notations, i.e., without
changing the output of an expression. These notations are:
• Infix Notation
• Prefix (Polish) Notation
• Postfix (Reverse-Polish) Notation

Infix:
❖ An expression is called the infix expression if the operator appears in between the
operands.
❖ It has the following format:
(Operand1 Operator Operand2)
Example: (A+B) * (C-D))

Prefix:

❖ An expression is called the prefix expression if the operator appears in the expression
before the operands.
❖ It has the following format:
(Operator Operand1 Operand2)
❖ Prefix Notation is also known as Polish Notation.
Example: *+AB-CD (Infix: (A+B) * (C-D) )
Postfix:
❖ An expression is called the postfix expression if the operator appears in the expression
after the operands.
❖ It has the following format:
(Operand1 Operand2 Operator)
❖ Postfix notation is also known as Reversed Polish Notation.
Example: AB+CD-* (Infix: (A+B * (C-D))

The following table shows the difference in all three notations −


304
Sr. No. Infix Notation Prefix Notation Postfix Notation
1 a+b +ab ab+
2 (a + b) ∗ c ∗+abc ab+c∗
3 a ∗ (b + c) ∗a+bc abc+∗
4 a/b+c/d +/ab/cd ab/cd/+
5 (a + b) ∗ (c + d) ∗+ab+cd ab+cd+∗

1) Evaluation of Infix Expression


❖ Infix notation is commonly used in arithmetic formula or statements
❖ Infix notation is a notation for writing arithmetic expressions in which the operators are
written in between their operands.
❖ Infix Expressions are harder for Computers to evaluate because of the additional work needed
to decide precedence.
Algorithm:
1. Create an empty operator stack.
2. Create an empty operand stack.
3. For each token in the input String
a. Get the next token in the infix string.
b. If the next is an operand, place it on the operand stack.
c. If the next token is an operator
• Evaluate the operator.
4. While operator stack is not empty, pop operator and operands (left and right),evaluate left
operator right and push result onto operand stack.
5. Pop result from operator stack.

Example:

//Java program to evaluate the infix expression.


import java.io.*;
import java.util.*;
public class EvaluateString
{
public static int evaluate(String expression)
{
char[] tokens = expression.toCharArray();
// Stack for numbers: 'values'
Stack<Integer> values = new Stack<Integer>();
// Stack for Operators: 'ops'
Stack<Character> ops = new Stack<Character>();
for (int i = 0; i < tokens.length; i++)
{
// Current token is a whitespace, skip it
if (tokens[i] == ' ')
continue;

305
// Current token is a number, push it to stack for numbers
if (tokens[i] >= '0' && tokens[i] <= '9')
{
StringBuffer sbuf = new StringBuffer();
// There may be more than one digits in number
while (i < tokens.length && tokens[i] >= '0' && tokens[i] <= '9')
sbuf.append(tokens[i++]);
values.push(Integer.parseInt(sbuf.toString()));
i--;
}
// Current token is an opening brace, push it to 'ops'
else if (tokens[i] == '(')
ops.push(tokens[i]);
// Closing brace encountered, solve entire brace
else if (tokens[i] == ')')
{
while (ops.peek() != '(')
values.push(applyOp(ops.pop(), values.pop(), values.pop()));
ops.pop();
}
// Current token is an operator.
else if (tokens[i] == '+' || tokens[i] == '-' || tokens[i] == '*' || tokens[i] == '/')
{
// While top of 'ops' has same or greater precedence to current token, which
// is an operator. Apply operator on top of 'ops' to top two elements in values
// stack
while (!ops.empty() && hasPrecedence(tokens[i], ops.peek()))
values.push(applyOp(ops.pop(), values.pop(), values.pop()));
// Push current token to 'ops'.
ops.push(tokens[i]);
}
}
// Entire expression has been parsed at this point, apply remaining ops to
// remaining values
while (!ops.empty())
values.push(applyOp(ops.pop(), values.pop(), values.pop()));
// Top of 'values' contains result, return it
return values.pop();
}
// Returns true if 'op2' has higher or same precedence as 'op1', otherwise returns false.
public static boolean hasPrecedence(char op1, char op2)
{
if (op2 == '(' || op2 == ')')
return false;
if ((op1 == '*' || op1 == '/') && (op2 == '+' || op2 == '-'))
return false;
else
return true;
}

// A method to apply an operator 'op' on operands 'a' and 'b'. Return the result.
public static int applyOp(char op, int b, int a)

306
{
switch (op)
{
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
if (b == 0)
throw new UnsupportedOperationException("Cannot divide by zero");
return a / b;
}
return 0;
}
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String Str;
System.out.println("Enter the infix expression");
Str= br.readLine();
System.out.println(EvaluateString.evaluate(Str));
}
}

Output:
Enter the infix expression
10 + 2 * 6
22
2) Evaluation of Prefix Expression
❖ Prefix notation is a notation for writing arithmetic expressions in which the operands appear
after their operators.
❖ Prefix expression can be evaluated faster than an infix expression.
❖ This is because we don’t need to process any brackets or follow operator precedence rule.
❖ In the prefix expression, which ever operator comes before will be evaluated first, irrespective
of its priority.
❖ Also, there are no brackets in this expression.
Algorithm:
Step 1: Reverse the given expression and Iterate through it, one character at a time
Step 2: If a character is an operand push it to Stack
Step 3: If the character is an operator pop two elements from the Stack.Operate on these
elements according to the operator, and push the result back to the Stack
Step 4: Step 2 and 3 will be repeated until the end has reached.

307
Step 5: The Result is stored at the top of the Stack, return it
Example:
//Java program to evaluate the Prefix Expression using Stack
import java.io.*;
import java.util.*;
public class PrefixEvaluation
{
public static Double evaluate(double a, double b, char operator)
{
switch (operator)
{
case '+':
return a + b;
case '-':
return b - a;
case '*':
return a * b;
case '/':
if (a == 0)
throw new UnsupportedOperationException("Cannot divide by zero");
return b / a;
}
return 0.0;
}
public static Double convert(String expression)
{
StringBuilder input = new StringBuilder(expression);
input.reverse();
Stack<Double> stack = new Stack<>();
for (int i = 0; i < input.length(); i++)
{
char c = input.charAt(i);
//Check if it is a space (separator)
if(c==' ')
continue;
if (c == '*' || c == '/' || c == '^' || c == '+' || c == '-')
{
double s1 = stack.pop();
double s2 = stack.pop();
double temp = evaluate(s2, s1, c);
stack.push(temp);
}

else
{
//If it is a digit extract the characters and store it in num
308
StringBuffer temp = new StringBuffer();
while(Character.isDigit(c))
{
temp.append(c);
i++;
c = input.charAt(i);
}
i--;
//Push the number in stack
double num = Double.parseDouble(temp.reverse().toString());
stack.push(num);
}
}
double result = stack.pop();
return result;
}
public static void main(String args[]) throws IOException
{
String exp;
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter the Prefix Expression");
exp=br.readLine();
System.out.println("Prefix Expression: " + exp);
System.out.println("Evaluation: " + convert(exp));
}
}
Output:
Enter the Prefix Expression
- / * 20 * 50 + 3 6 300 2
Prefix Expression: - / * 20 * 50 + 3 6 300 2
Evaluation: 28.0
3) Evaluation of Postfix Expression
❖ The Postfix notation is used to represent algebraic expressions.
❖ The expressions written in postfix form are evaluated faster compared to infix notation as
parenthesis are not required in postfix.
Algorithm:
1) Create a stack to store operands (or values).
2) Scan the given expression and do following for every scanned element.
a) If the element is a number, push it into the stack
b) If the element is an operator, pop operands for the operator from stack. Evaluate
the operator and push the result back to the stack
3) When the expression is ended, the number in the stack is the final answer
Example:
309
// Java program to evaluate value the postfix expression
import java.io.*;
import java.util.Stack;
public class Test
{
// Method to evaluate value of a postfix expression
static int evaluatePostfix(String exp)
{
//Create an empty stack
Stack<Integer> stack=new Stack<>();
// Scan all characters one by one
for(int i=0;i<exp.length();i++)
{
char c=exp.charAt(i);
// If the scanned character is an operand, push it to the stack.
if (Character.isDigit(c))
stack.push(c - '0');
else
{
// If the scanned character is an operator, pop two elements from the stack
int x = stack.pop();
int y = stack.pop();
switch(c)
{
case '+':
stack.push(y + x);
break;
case '-':
stack.push(y - x);
break;
case '*':
stack.push(y * x);
break;
case '/':
stack.push(y / x);
break;
}
}
}
return stack.pop();
}
public static void main(String args[]) throws IOException
{
String exp;
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter the Postfix Expression");
exp=br.readLine();
System.out.println("Postfix Evaluation: "+evaluatePostfix(exp));
}
}
Output:
Enter the Postfix Expression

310
138×+
Postfix Evaluation: 25
17.7 Conversion of infix to postfix expression
❖ Infix expressions are the expression where operators are written in between every pair of
operands. It is the usual way to write an expression. For Ex: An expression like A + B is Infix.
❖ Postfix expressions are the expressions where operands precede operators. Here operators are
written after operands. The Expression AB+ is Postfix and is the Postfix representation of the
above shown A+B. The evaluation order is from left to right.
Algorithm:
1. Scan the infix expression from left to right.
2. If the scanned character is an operand, output it.
3. Else,
i) If the precedence of the scanned operator is greater than the precedence of the operator in
the stack (or the stack is empty or the stack contains a ‘(‘ ), push it.

❖ Else,

❖ ii) Pop all the operators from the stack which are greater than or equal to in precedence
than that of the scanned operator. After doing that Push the scanned operator to the stack.
(If we encounter parenthesis while popping then stop there and push the scanned operator
in the stack.)
4. If the scanned character is an ‘(‘, push it to the stack.
5. If the scanned character is an ‘)’, pop the stack and output it until a ‘(‘is encountered, and discard
both the parenthesis.
6. Repeat steps 2-6 until infix expression is scanned.
7. Print the output
8. Pop and output from the stack until it is not empty.

Example:

Suppose we are converting 3*3/(4-1)+6*2 expression into postfix form.


Following table shows the evaluation of Infix to Postfix:

Expression Stack Output


3 Empty 3
* * 3
3 * 33
311
/ / 33*
( /( 33*
4 /( 33*4
- /(- 33*4
1 /(- 33*41
) - 33*41-
+ + 33*41-/
6 + 33*41-/6
* +* 33*41-/62
2 +* 33*41-/62
Empty 33*41-/62*+

So, the Postfix Expression is 33*41-/62*+


Example:
//Java Program to convert the Infix Expression to Postfix
import java.io.*;
class Stack
{
char a[]=new char[100 ];
int top=-1;
void push(char c)
{
try
{
a[++top]= c;
}
catch(StringIndexOutOfBoundsException e)
{
System.out.println("Stack full, no room to push, size=100");
System.exit(0);
}
}
char pop()
{
return a[top--];
}
boolean isEmpty()
{
return (top==-1)?true:false;
}

char peek()
{
return a[top];
}

312
}
public class InfixToPostfix
{
static Stack operators = new Stack();
public static void main(String argv[]) throws IOException
{
String infix;
BufferedReader br = new BufferedReader (new InputStreamReader(System.in));
System.out.print("\nEnter the infix expression you want to convert: ");
infix = br.readLine();
/ System.out.println("Postfix expression for the given infix expression is:" + toPostfix(infix));
}
private static String toPostfix(String infix)
//Converts an infix expression to postfix
{
char symbol;
String postfix = "";
for(int i=0;i<infix.length();++i)
{
symbol = infix.charAt(i);
//If it's an operand, add it to the string
if (Character.isLetter(symbol))
postfix = postfix + symbol;
else if (symbol=='(')
/ {
operators.push(symbol);
}
else if (symbol==')')
{
while (operators.peek() != '(')
{
postfix = postfix + operators.pop();
}
operators.pop();
}
else
{
while (!operators.isEmpty() && !(operators.peek()=='(') && prec(symbol) <=
prec(operators.peek()))
postfix = postfix + operators.pop();
operators.push(symbol);
}
}
while (!operators.isEmpty())
postfix = postfix + operators.pop();
return postfix;
}
static int prec(char x)
{
if (x == '+' || x == '-')
return 1;

313
if (x == '*' || x == '/' || x == '%')
return 2;
return 0;
}
}
Output:
Enter the Infix Expression
A*(B-C)/D+E
The Infix Expression is: A*(B-C)/D+E
The Postfix of the given Infix Expression is: ABC-*D/E+

Exercises:

1. Define stack.
2. Explain the various operations that can be performed on stack.
3. Write a Java program to implement the stack operations using arrays.
4. Write a Java program to implement the stack operations using linked lists.
5. Explain briefly about the applications of stack.
6. Dsiscus in detail about infix, prefix and postfix expression with an example.
7. Write a Java program to convert the given infix expression to postfix form.
*************************

************************************************************
Chapter 18 Queues
************************************************************
18.1 Introduction
314
❖ Queue is a Linear Data Structure.
❖ It is used for temporary storage of data values.
❖ Queue is a First-In-First- Out (FIFO) data structure where the first item inserted is the
first to be removed.
❖ A new element is added at one end called rear end.
❖ The existing elements are deleted from the other end called front end.
18.2 Queue ADT
“A queue is an ordered list in which all insertions take place at the REAR end deletions take place
at another end called FRONT”. Queues are sometimes referred to as First-In-First-Out (FIFO) lists.

Figure 18.1: Queue Data Structure


Example:
1. The people waiting in line at a bank cash counter form a queue.
2. In Computer, the jobs waiting in line to use the processor for execution. This queue is called Job
Queue.
18.3 Operations on Queues
1. Insertion
❖ Adding an element to a queue is called “insertion or enqueue”.
❖ The new element is usually added to the back of the queue called “rear”.
2. Deletion
❖ Removing an element from a queue is called “deletion or dequeue”.
❖ On calling dequeue, the element from the front of the queue is removed.
3. Peek
❖ The peek operation is often used to return the value of the first element without removing it.
4. Display
❖ Prints all the element of the queue. If the queue is non-empty, traverse and print all the
elements from index front to rear.

18.4 Implementation of Queue Data Structure


❖ A Queue can be implemented using an Array or Linked List. The easiest way of implementing
a queue is by using an Array.
1) Array Representation of Queues
❖ Array is the easiest way to implement a queue.
315
❖ There are two variables i.e. front and rear, which are implemented in the case of every queue.
❖ Rear and front variables point to the position from where insertions and deletions are performed
in a queue.
❖ Initially, the values of front and rear variables are -1 which represents an empty queue.
Algorithm for ENQUEUE Operation
1. Check if the queue is full or not.
2. If the queue is full, then print overflow error and exit the program.

3. If the queue is not full, then increment the tail and add the element.

Algorithm for DEQUEUE Operation


1. Check if the queue is empty or not.
2. If the queue is empty, then print underflow error and exit the program.
3. If the queue is not empty, then remove the element at the head and increment the head.
Algorithm for PEEK Operation
1. Check if the queue is empty or not.
2. If the queue is empty, then print underflow error and exit the program.
3. If the queue is not empty, then print the element at the head of the queue.

Figure 18.2: Array Implementation of Queue

Example 1:
// Java program to implement a queue using an array
import java.io.*;
import java.util.*;
class Queue
{
int front, rear, size=100;
int queue=new int[size];
Queue()
{
front = rear = 0;
}
// Function to insert an element at the rear of the queue
316
void Enqueue(int data)
{
// Check queue is full or not
if (size == rear)
{
System.out.println("\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
void Dequeue()
{
// If queue is empty
if (front == rear)
{
System.out.println("\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 < size)
queue[rear] = 0;
// Decrement rear
rear--;
}
return;
}
// Print front of queue
void peek()
{
if (front == rear)
{
System.out.println("\nQueue is Empty\n");
return;
317
}
System.out.println("\nFront Element is: %d", queue[front]);
return;
}
}
// Print queue elements
void Display()
{
int i;
if (front == rear)
{
System.out.println("\nQueue is Empty\n");
return;
}
// Traverse front to rear and print elements
System.out.println(“The Queue elements are”)
for (i = front; i < rear; i++)
{
System.out.println(queue[i]+” “);
}
return;
}
public class Queue_Arr
{
public static void main(String args[) throws IOException
{
Scanner sc = new Scanner(System.in);
Queue q = new Queue();
System.out.println("Queue Implementation Using Array\n");
char ch;
do
{
System.out.println("Queue Operations");
System.out.println("1. Insert");
System.out.println("2. Delete");
System.out.println("3. Peek");
System.out.println("4. Display");
System.out.println("5. Exit");
System.out.println(“Enter your choice:”);
int choice = sc.nextInt();
switch (choice)
{
case 1 :
System.out.println("Enter the element to insert");
int x=sc.nextInt();
q.Enqueue( x);
q.display();
318
break;
case 2 :
System.out.println("Removed Element = "+q.Dequeue());
q.display();
break;
case 3 :
System.out.println("Peek Element = "+ q.peek());
q.display();
break;
case 4 :
q.display();
break;
case 5 :
exit(0);
break;
default :
System.out.println("Wrong Choice. Try again. \n ");
break;
}
System.out.println("\nDo you want to continue? (Type Y or N) \n");
ch = sc.next().charAt(0);
}
while (ch == 'Y'|| ch == 'y');
}
}
Output:
Queue Implementation Using Array

Queue Operations
1. Insert
2. Delete
3. Peek
4. Display
5. Exit
Enter your choice
1
Enter the element to insert
10
The Queue elements are
10
Do you want to continue? (Type Y or N)
Y
Queue Operations
1. Insert
2. Delete
3. Peek

319
4. Display
5. Exit
Enter your choice
1
Enter the element to insert
20
The Queue elements are
10 20
Do you want to continue? (Type Y or N)
Y
Queue Operations
1. Insert
2. Delete
3. Peek
4. Display
5. Exit
Enter your choice
1
Enter the element to insert
30
The Queue elements are
10 20 30
Do you want to continue? (Type Y or N)
Y
Queue Operations
1. Insert
2. Delete
3. Peek
4. Display
5. Exit
Enter your choice
2
Removed Element = 10
The Queue elements are
10 20
Do you want to continue? (Type Y or N)
Y
Queue Operations
1. Insert
2. Delete
3. Peek
4. Display
5. Exit
Enter your choice
3
Peek Element = 10
The Queue elements are
10 20
Do you want to continue? (Type Y or N)
320
Y
Queue Operations
1. Insert
2. Delete
3. Peek
4. Display
5. Exit
Enter your choice
4
The Queue elements are
10 20
Do you want to continue? (Type Y or N)
Y
Queue Operations
1. Insert
2. Delete
3. Peek
4. Display
5. Exit
Enter your choice
5
Do you want to continue? (Type Y or N)
N
2) Linked List implementation of Queue
❖ Queue is abstract data type which demonstrates First In First Out (FIFO) behavior.
❖ In a linked queue, each node of the queue consists of two parts i.e. data part and the link part.
Each element of the queue points to its immediate next element in the memory.
❖ Insertion and deletions are performed at rear and front end respectively. If front and rear both
are NULL, it indicates that the queue is empty.
❖ The linked representation of queue is shown in the following figure.

Figure 18.3: Linked Queue

Operations on Linked Queues


❖ There are two basic operations which can be implemented on the linked queues. The operations
are Insertion and Deletion.
1) Insert Operation
❖ The insert operation appends the queue by adding an element to the end of the queue.
❖ The new element will be the last element of the queue.
2) Deletion Operation
❖ Deletion Operation removes the element that is first inserted among all the queue elements.

321
❖ Firstly, we need to check either the list is empty or not.
❖ The condition front == NULL becomes true if the list is empty, in this case, we simply write
underflow on the console and make exit.
❖ Otherwise, we will delete the element that is available in the front. For this purpose, copy the
node pointed by the front into node ptr. Now, shift the front element, point to its next node and
free the node pointed by the node ptr.

Figure 18.4: Linked Representation of Queues

Example:

//Java program to implement the Queue Operations using Singly Linked Lists
//QueueList.java
import java.io.*;
class Node
{
public int data;
public Node next;
public Node(int x)
{
data=x;
}
public void displayNode()
{
System.out.print(data+" ");
}
}

class LinkedQueue
{
private Node first;
private Node last;
public LinkedQueue()
{
first=null;
322
last=null;
}
public void insertLast(int x)
{
Node newNode=new Node(x);
newNode.next=null;
if (isEmpty())
first=newNode;
else
last.next=newNode;
last=newNode;
}
public int deleteFirst()
{
int t=first.data;
if (first.next==null)
last=null;
first=first.next;
return t;
}
public int peekFirst()
{
return(first.data);
}
public boolean isEmpty()
{
return(first==null);
}
public void displayList()
{
Node current=first;
while(current!=null)
{
current.displayNode();
current=current.next;
}
}
}

class Queue
{
private LinkedQueue lq;
public Queue()
{
lq=new LinkedQueue();
}
323
public void insert(int x)
{
lq.insertLast(x);
System.out.println("Inserted");
}
public int delete()
{
return lq.deleteFirst();
}
public boolean isQueueEmpty()
{
return lq.isEmpty();
}
public void display()
{
lq.displayList();
}
public int peek()
{
return lq.peekFirst();
}
}
class QueueList
{
public static void main(String args[]) throws IOException
{
Queue q=new Queue();
int ch, d;
while(true)
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.println("MENU");
System.out.println("---------");
System.out.println("1. Insert");
System.out.println("2. Delete");
System.out.println("3. Peek");
System.out.println("4. Display");
System.out.println("5. Exit");
System.out.println("Enter Your Choice\n");
ch=Integer.parseInt(br.readLine());
if(ch==5)
break;
else
{
switch(ch)
{
case 1:
324
System.out.println("Enter the number of elements");
int n=Integer.parseInt(br.readLine());
System.out.println("Enter the elements:\n");
for(int i=0; i<n; i++)
{
d=Integer.parseInt(br.readLine());
q.insert(d);
}
break;
case 2:
if(q.isQueueEmpty())
System.out.println("Queue is Empty ");
else
{
d=q.delete();
System.out.println("Deleted Data:- "+d);
}
break;
case 3:
if(q.isQueueEmpty())
System.out.print("Queue is Empty ");
else
{
d=q.peek();
System.out.println("First Item: "+d);
}
break;
case 4:
if(q.isQueueEmpty())
System.out.println("Queue is Empty ");
else
{
System.out.println("Queue elements are ");
q.display();
}
break;
default:
System.out.println("Invalid Choice ");
}
}
System.out.println(" ");
}
}
}
Output:
MENU
325
----------
1. Insert
2. Delete
3. Peek
4. Display
5. Exit
Enter Your Choice:
1
Enter the number of elements
5
Enter the elements:
3
Inserted
6
Inserted
7
Inserted
12
Inserted
16
Inserted
MENU
----------
1. Insert
2. Delete
3. Peek
4. Display
5. Exit
Enter Your Choice:
4
Queue elements are
3 6 7 12 16
MENU
----------
1. Insert
2. Delete
3. Peek
4. Display
5. Exit
Enter Your Choice:
2
Deleted Data: 3
MENU
----------
1. Insert
2. Delete
3. Peek
4. Display
5. Exit
Enter Your Choice:
4
Queue elements are
6 7 12 16
MENU
326
----------
1. Insert
2. Delete
3. Peek
4. Display
5. Exit
Enter Your Choice:
3
First Item: 6
MENU
----------
1. Insert
2. Delete
3. Peek
4. Display
5. Exit
Enter Your Choice:
4
Queue elements are
6 7 12 16
MENU
----------
1. Insert
2. Delete
3. Peek
4. Display
5. Exit
Enter Your Choice:
5
18.5 Types of Queues
• There are three types of Queues:
1. Circular Queue
2. Priority Queue
3. Dequeue (Double Ended Queue)
1. Circular Queues
❖ A circular queue is similar to a linear queue as it is also based on the FIFO (First-In-First- Out)
principle except that the last node is connected to the first node.
❖ Circular queue is also called as Ring Buffer.
❖ It is an abstract data type.
❖ Circular queue contains a collection of data which allows insertion of data at the end of the
queue and deletion of data at the beginning of the queue.
❖ Traffic light functioning is the best example for circular queues. The colors in the traffic light
follow a circular pattern.

327
Figure 18.5: Circular Queue
2. Priority Queues

❖ A priority queue is an abstract data type which is like a regular queue or stack data structure, but
where additionally each element has a “priority” associated with it.
❖ It is a collection of elements where elements are stored according to their priority levels.
❖ In a priority queue, insertion is performed in the order of arrival and deletion is performed based
on the priority.
❖ While removing an element from a priority queue, the data item with the highest priority is
removed first.
❖ Two elements of same priority are processed first-come-first-served basis.
3. Dequeue
❖ Dequeue stands for double ended queue.
❖ Elements can be inserted or deleted at either end.
❖ It is also known as head-tail linked list.

Figure 18.6: Double Ended Queue (Dequeue)


18.6 Applications of Queue
❖ The following are the various applications of queue.
1. Real world Applications:
• Cashier line in any store.
• People in an escalator.
• Check in and check out at any book store.
2. Applications of queues related to Computer Science
• Queues are widely used as waiting lists for a single shared resource like printer, disk, CPU.

• Queues are used in asynchronous transfer of data (where data is not being transferred at the same
rate between two processes) for e.g. Pipes, File IO, Sockets.
• CPU Scheduling and Disk Scheduling.
• Round Robin scheduling technique is implemented using queue
• All types of customer service (like railway reservation) centers are designed using the concept
of queues.
• Queues are used in operating systems for handling interrupts.
Exercises:
1. Define queue.

328
2. List out the operations on queue.
3. Write a Java program to implement the queue operations using an array.
4. How linked list is implemented on queue?
5. Write a Java program to implement the queue using linked list.
6. Explain in detail about the various types of queues.
7. Explain briefly about the applications of queues.

**************************

UNIT – V

************************************************************
Chapter 19 Trees
************************************************************
19.1 Introduction to Trees
❖ A tree is a nonlinear data structure that consists of nodes connected by edges.
329
❖ Each node contains some data and a link or reference to other nodes that can be called children.
❖ A tree can be empty with no nodes or a tree is a structure consisting of one node called the root
and zero or one or more subtrees.
❖ A tree is a connected graph without any circuit.

Example:

Figure 19.1: Tree


Properties of Trees
❖ The important properties of tree data structure are:

• There is one and only one path between every pair of vertices in a tree.
• A tree with n vertices has exactly (n-1) edges.
• A graph is a tree if and only if it is minimally connected.
• Any connected graph with n vertices and (n-1) edges is a tree.
Applications of Trees
1. Manipulate hierarchical data.
2. Make information easy to search (see tree traversal).
3. Manipulate sorted lists of data.
4. As a workflow for compositing digital images for visual effects.
5. Router algorithms.
6. Form of a multi-stage decision-making.
Tree Terminology
❖ The important terms related to tree data structure are-
1. Root Node
❖ The first node from where the tree originates is called as a root node.
❖ In any tree, there must be only one root node..
Example:

Here, node A is the only root node.

330
2. Edge
❖ The connecting link between any two nodes is called as an edge.
❖ In a tree with n number of nodes, there are exactly (n-1) number of edges.
Example:

3. Parent Node
❖ The node which has one or more children is called as a parent node.
❖ In a tree, a parent node can have any number of child nodes.
Example:

Here,
• Node A is the parent of nodes B and C
• Node B is the parent of nodes D, E and F
• Node C is the parent of nodes G and H
• Node E is the parent of nodes I and J
• Node G is the parent of node K

4. Child Node
❖ The node which is the immediate successor of a node is called the child node of that node.
❖ All the nodes except root node are child nodes.

Example:

Here,
331
• Nodes B and C are the children of node A
• Nodes D, E and F are the children of node B
• Nodes G and H are the children of node C
• Nodes I and J are the children of node E
• Node K is the child of node G

5. Siblings
❖ Children of the same parent node are called siblings.
❖ In other words, nodes with the same parent are sibling nodes.
Example:

Here,
• Nodes B and C are siblings
• Nodes D, E and F are siblings
• Nodes G and H are siblings
• Nodes I and J are siblings
6. Degree of a Node
❖ The Degree of a node is the total number of children of that node.
❖ The degree of a tree is the degree of its root.
❖ The degree of a leaf node must be 0.
Example:

Here,
• Degree of node A = 2
• Degree of node B = 3
• Degree of node C = 2
• Degree of node D = 0
• Degree of node E = 2
• Degree of node F = 0
• Degree of node G = 1
332
• Degree of node H = 0
• Degree of node I = 0
• Degree of node J = 0
• Degree of node K = 0

7. Internal Node
❖ The node which has at least one child is called as an internal node.
❖ Internal nodes are also called as non-terminal nodes.
❖ Every non-leaf node is an internal node.
Example:

Here, nodes A, B, C, E and G are internal nodes.


8. Leaf Node
❖ The node which does not have any child is called as a leaf node.
❖ Leaf nodes are also called as external nodes or terminal nodes.
Example:

Here, nodes D, I, J, F, K and H are leaf nodes.


9. Level
❖ In a tree, each step from top to bottom is called as level of a tree.
❖ The root node has level 0.
❖ The level count starts with 0 and increments by 1 at each level or step.

Example:

333
10. Height
❖ Total number of edges that lies on the longest path from any leaf node to a particular node is
called as height of that node.
❖ The Height of a tree is the height of the root node.
❖ Height of all leaf nodes = 0

Example:

Here,
• Height of node A = 3
• Height of node B = 2
• Height of node C = 2
• Height of node D = 0
• Height of node E = 1
• Height of node F = 0
• Height of node G = 1
• Height of node H = 0
• Height of node I = 0
• Height of node J = 0
• Height of node K = 0

11. Depth
❖ Total number of edges from root node to a particular node is called as depth of that node.
❖ Depth of a tree is the total number of edges from root node to a leaf node in the longest path.
❖ Depth of the root node = 0
❖ The terms “level” and “depth” are used interchangeably.

Example:

Here,
• Depth of node A = 0
334
• Depth of node B = 1
• Depth of node C = 1
• Depth of node D = 2
• Depth of node E = 2
• Depth of node F = 2
• Depth of node G = 2
• Depth of node H = 2
• Depth of node I = 3
• Depth of node J = 3
• Depth of node K = 3
12. Subtree
❖ In a tree, each child from a node forms a subtree recursively.
❖ Every child node forms a subtree on its parent node.

Example:

13. Forest
❖ A forest is a set of disjoint trees.
Example:

19.2 Binary Trees


❖ A tree in which every node can have maximum of two children is called as Binary Tree.
❖ The node at the top of the hierarchy of a tree is called the root node. The nodes that hold other
sub-nodes are the parent nodes.
❖ A parent node has two child nodes: the left child and right child.
❖ Thus, in a binary tree, each node has either 0 child or 1 child or 2 children.

335
❖ It is a method of placing and locating the records in a database, especially when all the data is
known to be in random access memory (RAM).

Example:

Figure 19.2: Binary Tree

Types of Binary Trees

❖ Binary trees can be of the following types:


1. Full Binary Tree
2. Complete Binary Tree
3. Skewed Binary Tree
4. Extended Binary Tree
1. Full Binary Tree
❖ A binary tree in which every node has either 0 or 2 children is called as a Full Binary Tree.
❖ Full binary tree is also called as Strictly Binary Tree.
❖ Full binary tree is used to represent mathematical expressions .

Example:

Figure 19.3: Full Binary Tree

2. Complete Binary Tree


❖ A Binary Tree is a Complete Binary Tree if all the levels are completely filled except possibly
the last level and the last level has all keys as left as possible
❖ For example, at Level 2, there must be 22 = 4 nodesand at Level 3 there must be 23 = 8 nodes.
❖ Complete binary tree is also called as Perfect Binary Tree.
Example:

336
Figure 19.4: Complete Binary Tree
3. Skewed Binary Tree
❖ A skewed binary tree is a binary tree of n nodes such that its depth is (n-1).
❖ In a skewed binary tree, all nodes except one have only one child node. The remaining node has
no child.
❖ In a left skewed tree, most of the nodes have the left child without corresponding right child.
❖ In a right skewed tree, most of the nodes have the right child without corresponding left child.
Example:

a) Left Skewed Binary Tree b) Right Skewed Binary Tree

Figure 19.5: Skewed Binary Tree


4. Extended Binary Tree
❖ Extended binary tree consists of replacing every null subtree of the original tree with special
nodes.
❖ Empty circle represents internal node and filled circle represents external node.
❖ The nodes from the original tree are internal nodes and the special nodes are external nodes.
❖ Every internal node in the extended binary tree has exactly two children and every external node
is a leaf. It displays the result which is a complete binary tree.

Figure 19.6: Extended Binary Tree


Binary Tree Properties
❖ Important properties of binary trees are:

Property-01:
337
Minimum number of nodes in a binary tree of height H= H + 1

Example:
❖ To construct a binary tree of height = 4, we need at least 4 + 1 = 5 nodes.

Property-02:

Maximum number of nodes in a binary tree of height H= 2H+1 – 1

Example:
Maximum number of nodes in a binary tree of height 3= 23+1 – 1
= 16 – 1
= 15 nodes
Thus, in a binary tree of height = 3, maximum number of nodes that can be inserted = 15.

We cannot insert more number of nodes in this binary tree.


Property-03:

Total Number of leaf nodes in a Binary Tree= Total Number of nodes with 2 children + 1

Example:
Consider the following binary tree-

Here,
• Number of leaf nodes = 3
• Number of nodes with 2 children = 2
Clearly, number of leaf nodes is one greater than number of nodes with 2 children.
338
This verifies the above relation.
Property-04:

Maximum number of nodes at any level ‘L’ in a binary tree= 2 L

Example:

Maximum number of nodes at level-2 in a binary tree= 22

=4
Thus, in a binary tree, maximum number of nodes that can be present at level-2 = 4.

Applications of Binary Tree


❖ Applications of binary trees include:
• Used in many search applications where data is constantly entering/leaving
• As a workflow for compositing digital images for visual effects
• Used in almost every high-bandwidth router for storing router-tables
• Also used in wireless networking and memory allocation
• Used in compression algorithms and many more
Representation of Binary Tree using Array
❖ Binary tree using array represents a node which is numbered sequentially level by level from left
to right. Even empty nodes are numbered.

Figure 19.7: Binary Tree using Array


❖ Array index is a value in tree nodes and array value gives to the parent node of that particular
index or node.
❖ Value of the root node index is always -1 as there is no parent for root.
❖ When the data item of the tree is sorted in an array, the number appearing against the node will
work as indexes of the node in an array.

339
Figure 19.8: Location Number of an Array in a Tree
❖ Location number of an array is used to store the size of the tree. The first index of an array that
is '0', stores the total number of nodes.
❖ All nodes are numbered from left to right level by level from top to bottom. In a tree, each node
having an index i is put into the array as its ithelement.
❖ The above figure shows how a binary tree is represented as an array. Value '7' is the total number
of nodes. If any node does not have any children, null value is stored at the corresponding index
of the array.

Operations on Binary Trees


❖ The most common operations that can be performed on a binary tree are:
1) Insertion
2) Deletion
3) Searching
1) Insertion
❖ The Insertion operation is used to insert a node into the Binary Tree.
❖ Nodes can be inserted into binary trees in between two other nodes or added after a leaf node.
❖ In binary trees, a node that is inserted is specified as to which child it is.
❖ The node to be inserted can be an internal node or an external node.
2) Deletion
❖ Deletion is the process whereby a node is removed from the tree.
❖ Once we find the node to delete, there are 3 main different cases:
• A node has no children – this is the simplest case; we just need to replace this node
with null in its parent node
• A node has exactly one child – in the parent node, we replace this node with its only child.
• A node has two children – this is the most complex case because it requires a tree
reorganization
3) Searching
❖ Searching in a binary tree for a specific key can be programmed recursively or iteratively.
❖ We begin by examining the root node. If the tree is null, the key we are searching for does not
exist in the tree.
❖ Otherwise, if the key equals that of the root, the search is successful and we return the node. If
the key is less than that of the root, we search the left subtree.
340
❖ Similarly, if the key is greater than that of the root, we search the right subtree.
❖ This process is repeated until the key is found or the remaining subtree is null. If the searched
key is not found after a null subtree is reached, then the key is not present in the tree.
Benefits of a Binary Tree
❖ The search operation in a binary tree is faster as compared to other trees.
❖ Only two traversals are enough to provide the elements in sorted order.
❖ It is easy to pick up the maximum and minimum elements.
❖ Graph traversal also uses binary trees.
❖ Converting different postfix and prefix expressions are possible using binary trees.

19.3 Binary Tree Traversal


❖ Binary Tree Traversal is the process of accessing every node of the tree and exactly once.
❖ Binary Tree is non-linear data structure, and it provides few different options for traversal. On a
high level, we have the following 2 options for binary tree traversal in Java.
1) Depth First Search
2) Breadth First Search or Level Order Traversal
1) Depth First Search
❖ Depth First Search is a type of traversal that goes deep as much as possible in every child before
exploring the next sibling.
❖ The Stack data structure is used to implement DFS.
❖ There are few advantages of the Depth-First Search traversal.

1. DFS on binary tree requires less memory than breadth-first search.


2. It’s easy to implement (using recursion of loop).
❖ There are several ways to perform a Depth-First Search: in-order, pre-order and post-order.
1. In-order Traversal
❖ The in-order traversal consists of first visiting the left sub-tree, then the root node, and finally
the right sub-tree:
Algorithm
1. Traverse the left sub-tree.
2. Visit the root
3. Traverse the right sub-tree.
(Left → Root → Right)
Example:
Consider the following example:

341
Application
• In-order traversal is used to get infix expression of an expression tree.
2. Pre-order Traversal
❖ Pre-order traversal visits first the root node, then the left sub-tree, and finally the right sub-tree.
Algorithm
1. Visit the root.
2. Traverse the left sub-tree.
3. Traverse the right sub-tree.
(Root → Left → Right)
Example:
Consider the following example.

Applications
❖ Pre-order traversal is used to get prefix expression of an expression tree.
❖ Pre-order traversal is used to create a copy of the tree.
3. Post-order Traversal
❖ Post-order traversal visits the left sub-tree, the right sub-tree, and the root node at the end.

Algorithm
1. Traverse the left sub-tree.
2. Traverse the right sub-tree.
3. Visit the root
(Left → Right → Root)

Example:

Consider the following example:

342
Applications
❖ Post-order traversal is used to get postfix expression of an expression tree.
❖ Post-order traversal is used to delete the tree.
❖ This is because it deletes the children first and then it deletes the parent.

2. Breadth First Traversal


❖ This type of traversal visits all the nodes of a level before going to the next level.
❖ Breadth First Traversal is also called as Level Order Traversal.
❖ The Queue data structure is used to implement BFS.
Example:

Application
❖ Level order traversal is used to print the data in the same order as stored in the array
representation of a complete binary tree.
Binary Tree Implementation

//Java Program to Implement Binary Tree


import java.io.*;
import java.util.*;
class BTNode
{
BTNode left, right;
int data;
public BTNode() //Constructor
{
left = null;
right = null;
data = 0;

343
}
public BTNode(int n) //Constructor
{
left = null;
right = null;
data = n;
}
// Function to set left node
public void setLeft(BTNode n)
{
left = n;
}
// Function to set right node
public void setRight(BTNode n)
{
right = n;
}
// Function to get left node
public BTNode getLeft()
{
return left;
}
// Function to get right node
public BTNode getRight()
{
return right;
}
// Function to set data to node
public void setData(int d)
{
data = d;
}
// Function to get data from node
public intgetData()
{
return data;
}
}
class BT
{
private BTNode root;
public BT() //Constructor
{
root = null;
}
// Function to check if tree is empty
public boolean isEmpty()
344
{
return root == null;
}
// Functions to insert data
public void insert(int data)
{
root = insert(root, data);
}
// Function to insert data recursively
private BTNode insert(BTNode node, int data)
{
if (node == null)
node = new BTNode(data);
else
{
if (node.getRight() == null)
node.right = insert(node.right, data);
else
node.left = insert(node.left, data);
}
return node;
}
// Function to count number of nodes
public int countNodes()
{
return countNodes(root);
}
// Function to count number of nodes recursively
private int countNodes(BTNode r)
{
if (r == null)
return 0;
else
{
int l = 1;
l+=countNodes(r.getLeft());
l+=countNodes(r.getRight());
return l;
}
}
// Function to search for an element
public boolean search(intval)
{
return search(root, val);
}
// Function to search for an element recursively
private boolean search(BTNode r, intval)
345
{
if (r.getData() == val)
return true;
if (r.getLeft() != null)
if (search(r.getLeft(), val))
return true;
if (r.getRight() != null)
if (search(r.getRight(), val))
return true;
return false;
}
// Function for inorder traversal
public void inorder()
{
inorder(root);
}
private void inorder(BTNode r)
{
if (r != null)
{
inorder(r.getLeft());
System.out.print(r.getData() +" ");
inorder(r.getRight());
}
}
// Function for preorder traversal
public void preorder()
{
preorder(root);
}
private void preorder(BTNode r)
{
if (r != null)
{
System.out.print(r.getData() +" ");
preorder(r.getLeft());
preorder(r.getRight());
}
}
// Function for postorder traversal
public void postorder()
{
postorder(root);
}
private void postorder(BTNode r)
{
if (r != null)
346
{
postorder(r.getLeft());
postorder(r.getRight());
System.out.print(r.getData() +" ");
}
}
}
public class BinaryTreeTest
{
public static void main(String args[])
{
Scanner sc = new Scanner(System.in);
BT bt = new BT();
System.out.println("Binary Tree Test\n");
char ch;
do
{
System.out.println("Binary Tree Operations");
System.out.println("1. Insert ");
System.out.println("2. Search");
System.out.println("3. Count Nodes");
System.out.println("4. Exit");
System.out.println("Enter your choice");
int choice = sc.nextInt();
switch (choice)
{
case 1 :
System.out.println("Enter the element to insert");
bt.insert(sc.nextInt());
break;
case 2 :
System.out.println("Enter the element to search");
System.out.println("Search Result: "+ bt.search(sc.nextInt() ));
break;
case 3 :
System.out.println("Nodes = "+ bt.countNodes());
break;
case 4 :
System.exit(0);
break;
default :
System.out.println("Wrong Choice \n ");
break;
}
//Display Tree
System.out.print("\nPostOrder : ");
bt.postorder();
347
System.out.print("\nPreOrder : ");
bt.preorder();
System.out.print("\nInOrder : ");
bt.inorder();
System.out.println("\n\nDo you want to continue? (Type Y or N) \n");
ch = sc.next().charAt(0);
}
while (ch == 'Y'|| ch == 'y');
}
}
Output:
Binary Tree Test

Binary Tree Operations


1. Insert
2. Search
3. Count Nodes
4. Exit
Enter your choice
1
Enter the element to insert
6

PostOrder : 6
PreOrder : 6
InOrder : 6
Do you want to continue? (Type Y or N)
Y
Binary Tree Operations
1. Insert
2. Search
3. Count Nodes
4. Exit
Enter your choice
1
Enter the element to insert
24
PostOrder : 24 6
PreOrder : 6 24
InOrder : 6 24
Do you want to continue? (Type Y or N)
Y
Binary Tree Operations
1. Insert
2. Search
3. Count Nodes
348
4. Exit
Enter your choice
1
Enter the element to insert
19
PostOrder : 19 24 6
PreOrder : 6 19 24
InOrder : 19 6 24
Do you want to continue? (Type Y or N)
Y
Binary Tree Operations
1. Insert
2. Search
3. Count Nodes
4. Exit
Enter your choice
1
Enter the element to insert
94
PostOrder : 94 19 24 6
PreOrder : 6 19 94 24
InOrde r : 19 94 6 24

Do you want to continue? (Type Y or N)


Y
Binary Tree Operations
1. Insert
2. Search
3. Count Nodes
4. Exit
Enter your choice
1
Enter integer element to insert
5
PostOrder : 5 94 19 24 6
PreOrder : 6 19 5 94 24
InOrder : 5 19 94 6 24
Do you want to continue? (Type Y or N)
Y
Binary Tree Operations
1. Insert
2. Search
3. Count Nodes
4. Exit
Enter your choice
1
Enter the element to insert
349
1
PostOrder : 1 5 94 19 24 6
PreOrder : 6 19 5 1 94 24
InOrder : 5 1 19 94 6 24
Do you want to continue? (Type Y or N)
Y
Binary Tree Operations
1. Insert
2. Search
3. Count Nodes
4. Exit
Enter your choice
1
Enter the element to insert
10
PostOrder : 10 1 5 94 19 24 6
PreOrder : 6 19 5 10 1 94 24
InOrder : 10 5 1 19 94 6 24
Do you want to continue? (Type Y or N)
Y
Binary Tree Operations
1. Insert
2. Search
3. Count Nodes
4. Exit
Enter your choice
1
Enter the element to insert
3
PostOrder : 3 10 1 5 94 19 24 6
PreOrder : 6 19 5 10 3 1 94 24
InOrder : 10 3 5 1 19 94 6 24
Do you want to continue? (Type Y or N)
Y
Binary Tree Operations
1. Insert
2. Search
3. Count Nodes
4. Exit
Enter your choice
1
Enter the element to insert
8
PostOrder : 8 3 10 1 5 94 19 24 6
PreOrder : 6 19 5 10 8 3 1 94 24
InOorder : 8 10 3 5 1 19 94 6 24
Do you want to continue? (Type Y or N)
350
Y
Binary Tree Operations
1. Insert
2. Search
3. Count Nodes
4. Exit
Enter your choice
3
Nodes = 9
PostOrder : 8 3 10 1 5 94 19 24 6
PreOrder : 6 19 5 10 8 3 1 94 24
InOrder : 8 10 3 5 1 19 94 6 24
Do you want to continue? (Type Y or N)
Y
Binary Tree Operations
1. Insert
2. Search
3. Count Nodes
4. Exit
Enter your choice
2
Enter the element to search
24
Search Result: true
PostOrder : 8 3 10 1 5 94 19 24 6
PreOrder : 6 19 5 10 8 3 1 94 24
InOrder : 8 10 3 5 1 19 94 6 24
Do you want to continue? (Type Y or N)
Y
Binary Tree Operations
1. Insert
2. Search
3. Count Nodes
4. Exit
Enter your choice
2
Enter integer element to search:
7
Search Result: false
PostOrder : 8 3 10 1 5 94 19 24 6
PreOrder: 6 19 5 10 8 3 1 94 24
InOrder: 8 10 3 5 1 19 94 6 24
Do you want to continue? (Type Y or N)
N
19.4 Binary Search Trees

351
❖ Binary Search Tree is a binary tree where each node contains only smaller values in its
left subtree and only larger values in its right subtree.

Figure 19.7: Binary Search Tree

❖ The above tree represents binary search tree (BST) where left subtree of every node contains
smaller values and right subtree of every node contains larger value.
❖ Binary Search Tree (BST) is used to enhance the performance of binary tree.
❖ It focuses on the search operation in binary tree.
Note: Every binary search tree is a binary tree, but all the binary trees need not to be binary
search trees.
19.5 Advantages of using Binary Search Tree
❖ Searching become very efficient in a binary search tree since, we get a hint at each step, about
which sub-tree contains the desired element.

❖ The binary search tree is considered as efficient data structure in compare to arrays and linked
lists. In searching process, it removes half sub-tree at every step. Searching for an element in a
binary search tree takes O(log2n) time. In worst case, the time it takes to search an element is
0(n).
❖ It also speed up the insertion and deletion operations as compare to that in array and linked list.
❖ Binary search trees are used in various searching and sorting algorithms. There are many
variants of binary search trees like AVL tree, B-Tree, Red-black tree, etc.
19.6 Operations on Binary Search Tree
❖ There are many operations which can be performed on a Binary Search Tree.

Sl. No. Operation Description


Adding a new element to the binary search tree at the appropriate location
1 Insert
so that the property of BST do not violate.
Deleting some specific node from a binary search tree. The node can be
2 Delete
the root node, non-leaf, or leaf node.
Search the location of the given element in the BST. This operation
3 Search
checks if the tree contains the specified key.

Insert Operation

❖ The Insert operation is used to insert a new node to the Binary Search Tree.

352
❖ This operation starts from the root node
❖ The following algorithm shows the insert operation in Binary Search Tree:
Step 1: Create a new node with a value and set its left and right to NULL.
Step 2: Check whether the tree is empty or not.
Step 3: If the tree is empty, set the root to a new node.
Step 4: If the tree is not empty, check whether a value of new node is smaller or larger than the
node (here it is a root node).
Step 5: If a new node is smaller than or equal to the node, move to its left child.
Step 6: If a new node is larger than the node, move to its right child.
Step 7: Repeat the process until we reach to a leaf node.
Example:

• Consider the following example where key = 40 is inserted in the given BST-

• We start searching for value 40 from the root node 100.


• As 40 < 100, so we search in 100’s left subtree.
• As 40 > 20, so we search in 20’s right subtree.
• As 40 > 30, so we add 40 to 30’s right subtree.
Delete Operation
❖ The Delete operation is used to delete an element from the Binary Search Tree.
❖ There are multiple cases handled for deletion in the BST.
Case 1 - Deletion of a Node having no Child (Leaf Node)
• If the node to be deleted is a leaf node, then we can directly delete this node as it has no child
nodes.
Example:

Consider the following example where node with value = 20 is deleted from the BST-

Case 2 - Deletion of a Node having only one Child


353
❖ When we need to delete the node that has one child, then we copy the value of the child in the
node and then delete the child.
Example:

Consider the following example where node with value = 30 is deleted from the BST-

Case 3 - Deletion of a Node having two Children


❖ A node with two children may be deleted from the BST in the following two ways-
Method-01:
• Visit to the right subtree of the deleting node.
• Pluck the least value element called as inorder successor.
• Replace the deleting element with its inorder successor.

Example:

Consider the following example where node with value = 15 is deleted from the BST-

Method-02:

• Visit to the left subtree of the deleting node.


• Pluck the greatest value element called as inorder predecessor.
• Replace the deleting element with its inorder predecessor.

Example:

Consider the following example where node with value = 15 is deleted from the BST-

Search Operation

354
❖ The Search Operation is used to search whether the given element is present in the Binary
Search Tree or not.
❖ This operation starts from the root node.
❖ The following algorithm shows the search operation in binary search tree:
Step 1: Read the element from the user.
Step 2: Compare this element with the value of root node in a tree.
Step 3: If element and value are matching, display "Node is Found" and terminate the function.
Step 4: If element and value are not matching, check whether an element is smaller or larger than a
node value.
Step 5: If an element is smaller, continue the search operation in left subtree.
Step 6: If an element is larger, continue the search operation in right subtree.
Step 7: Repeat the same process until we found the exact element.
Step 8: If an element with search value is found, display "Element is found" and terminate the
function.
Step 9: If we reach to a leaf node and the search value is not match to a leaf node, display
"Element is not found" and terminate the function.
Example:
Consider key = 45 has to be searched in the given BST-

• We start our search from the root node 25.


• As 45 > 25, so we search in 25’s right subtree.
• As 45 < 50, so we search in 50’s left subtree.
• As 45 > 35, so we search in 35’s right subtree.
• As 45 > 44, so we search in 44’s right subtree but 44 has no subtrees.
• So, we conclude that 45 is not present in the above BST.
Example:
Create the binary search tree using the following data elements.
43, 10, 79, 90, 12, 54, 11, 9, 50

1. Insert 43 into the tree as the root of the tree.


2. Read the next element, if it is lesser than the root node element, insert it as the root of the left
sub-tree.
3. Otherwise, insert it as the root of the right of the right sub-tree.

355
The process of creating BST by using the given elements is shown in the image below.

Figure 19.8: Binary Search Tree Creation

BST Traversal
❖ A Binary Search Tree is traversed in exactly the same way a binary tree is traversed.
❖ In other words, BST traversal is same as binary tree traversal.
❖ There are 3 kinds of traversals that are done typically over a binary search tree.

1) In-order Traversal
❖ This traversal first goes over the left subtree of the root node then accesses the current node,
followed by the right subtree of the current node. The code represents the base case too, which
says that an empty tree is also a binary search tree.

2) Pre-order Traversal
❖ This traversal first accesses the current node value then traverses the left and right sub-trees
respectively.

3) Post-order Traversal
❖ This traversal puts the root value at last, and goes over the left and right sub-trees first. The
relative order of the left and right sub-trees remains the same. Only the position of the root
changes in all the above mentioned traversals
Example:
Consider the following binary search tree-

356
Now, let us write the traversal sequences for this binary search tree-

Pre-order Traversal:

100, 20, 10, 30, 200, 150, 300

In-order Traversal:

10, 20, 30, 100, 150, 200, 300

Post-order Traversal:

10, 30, 20, 150, 300, 200, 100


Types of Binary Search Trees

❖ There are many types of binary search trees. Some of the BST are AVL Trees, and Red–Black
Trees, Splay Trees etc.
1) AVL Tree
❖ AVL tree is a height balanced tree.
❖ It is a self-balancing binary search tree.
❖ AVL tree is another balanced binary search tree.
❖ It was invented by Adelson-Velskii and Landis.
❖ AVL trees have a faster retrieval.
❖ It takes O(logn) time for addition and deletion operation.
❖ In AVL tree, heights of left and right subtree cannot be more than one for all nodes.

Figure 19.9: AVL Tree

2) Red-Black Tree

❖ The Red-Black tree is a self-balancing binary search tree.


❖ AVL tree is also a height balancing binary search tree then why do we require a Red-Black
tree.
❖ In the AVL tree, we do not know how many rotations would be required to balance the tree, but
in the Red-black tree, a maximum of 2 rotations are required to balance the tree.
❖ It contains one extra bit that represents either the red or black color of a node to ensure the
balancing of the tree.

3) Splay Tree

357
❖ The splay tree data structure is also binary search tree in which recently accessed element is
placed at the root position of tree by performing some rotation operations.
❖ Here, splaying means the recently accessed node.
❖ It is a self-balancing binary search tree having no explicit balance condition like AVL tree.
❖ It might be a possibility that height of the splay tree is not balanced, i.e., height of both left and
right subtrees may differ, but the operations in splay tree takes order of logN time where n is the
number of nodes.
❖ Splay tree is a balanced tree but it cannot be considered as a height balanced tree because after
each operation, rotation is performed which leads to a balanced tree.
Binary Search Tree (BST) Implementation in Java
//Java Program to implement Binary Search Tree
import java.io.*;
import java.util.*;
class BSTNode
{
BSTNode left, right;
int data;
public BSTNode() //Constructor
{
left = null;
right = null;
data = 0;
}
public BSTNode(int n) //Constructor
{
left = null;
right = null;
data = n;
}
// Function to set left node
public void setLeft(BSTNode n)
{
left = n;
}
// Function to set right node
public void setRight(BSTNode n)
{
right = n;
}
// Function to get left node
public BSTNode getLeft()
{
return left;
}
358
// Function to get right node
public BSTNode getRight()
{
return right;
}
// Function to set data to node
public void setData(int d)
{
data = d;
}
// Function to get data from node
public int getData()
{
return data;
}
}
class BST
{
private BSTNode root;
public BST() //Constructor
{
root = null;
}
// Function to check if tree is empty
public boolean isEmpty()
{
return root == null;
}
// Functions to insert data
public void insert(int data)
{
root = insert(root, data);
}
// Function to insert data recursively
private BSTNode insert(BSTNode node, int data)
{
if (node == null)
node = new BSTNode(data);

else
{
if (data <= node.getData())
node.left = insert(node.left, data);
else
node.right = insert(node.right, data);
}
return node;
359
}
// Functions to delete data
public void delete(int k)
{
if (isEmpty())
System.out.println("Tree Empty");
else if (search(k) == false)
System.out.println("Sorry "+ k +" is not present");
else
{
root = delete(root, k);
System.out.println(k+ " deleted from the tree");
}
}
private BSTNode delete(BSTNode root, int k)
{
BSTNode p, p2, n;
if (root.getData() == k)
{
BSTNode lt, rt;
lt = root.getLeft();
rt = root.getRight();
if (lt == null &&rt == null)
return null;
else if (lt == null)
{
p = rt;
return p;
}
else if (rt == null)
{
p = lt;
return p;
}
else
{
p2 = rt;
p = rt;
while (p.getLeft() != null)
p = p.getLeft();
p.setLeft(lt);
return p2;
}
}
if (k <root.getData())
{
n = delete(root.getLeft(), k);
360
root.setLeft(n);
}
else
{
n = delete(root.getRight(), k);
root.setRight(n);
}
return root;
}
// Function to count number of nodes
public int countNodes()
{
return countNodes(root);
}
// Function to count number of nodes recursively
private int countNodes(BSTNode r)
{
if (r == null)
return 0;
else
{
int l = 1;
l += countNodes(r.getLeft());
l += countNodes(r.getRight());
return l;
}
}
// Functions to search for an element
public boolean search(intval)
{
return search(root, val);
}
// Function to search for an element recursively
private boolean search(BSTNode r, intval)
{
boolean found = false;
while ((r != null) && !found)
{
int rval = r.getData();
if (val<rval)
r = r.getLeft();
else if (val>rval)
r = r.getRight();
else
{
found = true;
break;
361
}
found = search(r, val);
}
return found;
}
// Function for inorder traversal
public void inorder()
{
inorder(root);
}
private void inorder(BSTNode r)
{
if (r != null)
{
inorder(r.getLeft());
System.out.print(r.getData() +" ");
inorder(r.getRight());
}
}
// Function for preorder traversal
public void preorder()
{
preorder(root);
}
private void preorder(BSTNode r)
{
if (r != null)
{
System.out.print(r.getData() +" ");
preorder(r.getLeft());
preorder(r.getRight());
}
}
// Function for postorder traversal
public void postorder()
{
postorder(root);
}

private void postorder(BSTNode r)


{
if (r != null)
{
postorder(r.getLeft());
postorder(r.getRight());
System.out.print(r.getData() +" ");
}
362
}
}
public class BinarySearchTreeTest
{
public static void main(String args[])
{
char ch;
Scanner sc = new Scanner(System.in);
BST bst = new BST();
System.out.println("Binary Search Tree Test\n");
do
{
System.out.println("Binary Search Tree Operations");
System.out.println("1. Insert ");
System.out.println("2. Delete");
System.out.println("3. Search");
System.out.println("4. Count Nodes");
System.out.println("5. Exit");
System.out.println("Enter your choice");
int choice = sc.nextInt();
switch (choice)
{
case 1 :
System.out.println("Enter the element to insert");
bst.insert(sc.nextInt() );
break;
case 2 :
System.out.println("Enter the element to delete");
bst.delete(sc.nextInt() );
break;
case 3 :
System.out.println("Enter the element to search");
System.out.println("Search Result : "+ bst.search(sc.nextInt() ));
break;
case 4 :
System.out.println("Nodes = "+ bst.countNodes());
break;
case 5 :
System.exit(0);
break;
default :
System.out.println("Wrong Choice \n ");
break;
}
// Display Tree
System.out.print("\nPostOrder : ");
bst.postorder();
363
System.out.print("\nPreOrder : ");
bst.preorder();
System.out.print("\nInOrder : ");
bst.inorder();
System.out.println("\nDo you want to continue? (Type Y or N) \n");
ch = sc.next().charAt(0);
}
while (ch == 'Y'|| ch == 'y');
}
}
Output:
Binary Search Tree Test

Binary Search Tree Operations


1. Insert
2. Delete
3. Search
4. Count Nodes
5. Exit
Enter your choice
1
Enter the element to insert
8
PostOrder : 8
PreOrder : 8
InOrder : 8
Do you want to continue? (Type Y or N)
Y
Binary Search Tree Operations
1. Insert
2. Delete
3. Search
4. Count Nodes
5. Exit
Enter your choice
1
Enter the element to insert
5
PostOrder : 5 8
PreOrder : 8 5
InOrder : 5 8
Do you want to continue? (Type Y or N)
Y
Binary Search Tree Operations
1. Insert
2. Delete

364
3. Search
4. Count Nodes
5. Exit
Enter your choice
1
Enter the element to insert
3
PostOrder : 3 5 8
PreOrder : 8 5 3
InOrder : 3 5 8
Do you want to continue? (Type Y or N)
Y
Binary Search Tree Operations
1. Insert
2. Delete
3. Search
4. Count Nodes
5. Exit
Enter your choice
1
Enter integer element to insert
7
PostOrder : 3 7 5 8
PreOrder : 8 5 3 7
InOrder : 3 5 7 8
Do you want to continue? (Type Y or N)
Y
Binary Search Tree Operations
1. Insert
2. Delete
3. Search
4. Count Nodes
5. Exit
Enter your choice
1
Enter the element to insert
10
PostOrder : 3 7 5 10 8
PreOrder : 8 5 3 7 10
InOrder : 3 5 7 8 10
Do you want to continue? (Type Y or N)
Y
Binary Search Tree Operations
1. Insert
2. Delete
3. Search
4. Count Nodes
365
5. Exit
Enter your choice
1
Enter the element to insert
15
PostOrder : 3 7 5 15 10 8
PreOrder : 8 5 3 7 10 15
InOrder : 3 5 7 8 10 15
Do you want to continue? (Type Y or N)
Y
Binary Search Tree Operations
1. Insert
2. Delete
3. Search
4. Count Nodes
5. Exit
1
Enter the element to insert
2
PostOrder : 2 3 7 5 15 10 8
PreOrder : 8 5 3 2 7 10 15
InOrder : 2 3 5 7 8 10 15
Do you want to continue? (Type Y or N)
Y
Binary Search Tree Operations
1. Insert
2. Delete
3. Search
4. Count Nodes
5. Exit
Enter your choice
4
Nodes = 7
PostOrder : 2 3 7 5 15 10 8
PreOrder : 8 5 3 2 7 10 15
InOrder : 2 3 5 7 8 10 15
Do you want to continue? (Type Y or N)
Y

Binary Search Tree Operations


1. Insert
2. Delete
3. Search
4. Count Nodes
5. Exit
Enter your choice
3
366
Enter the element to search
24
Search Result: false
PostOrder : 2 3 7 5 15 10 8
PreOrder : 8 5 3 2 7 10 15
InOrder : 2 3 5 7 8 10 15
Do you want to continue? (Type Y or N)
Y
Binary Search Tree Operations
1. Insert
2. Delete
3. Search
4. Count Nodes
5. Exit
Enter your choice
3
Enter the element to search
7
Search Result: true
PostOrder : 2 3 7 5 15 10 8
PreOrder : 8 5 3 2 7 10 15
InOrder : 2 3 5 7 8 10 15
Do you want to continue? (Type Y or N)
Y
Binary Search Tree Operations
1. Insert
2. Delete
3. Search
4. Count Nodes
5. Exit
Enter your choice
2
Enter the element to delete
2
2 deleted from the tree
PostOrder : 3 7 5 15 10 8
PreOrder : 8 5 3 7 10 15
InOrder : 3 5 7 8 10 15

Do you want to continue? (Type Y or N)


Y
Binary Search Tree Operations
1. Insert
2. Delete
3. Search
4. Count Nodes
5. Exit
367
Enter your choice
2
Enter the element to delete
8
8 deleted from the tree
PostOrder : 3 7 5 15 10
PreOrder : 10 5 3 7 15
InOrder : 3 5 7 10 15
Do you want to continue? (Type Y or N)
Y
Binary Search Tree Operations
1. Insert
2. Delete
3. Search
4. Count Nodes
5. Exit
Enter your choice
5
Do you want to continue? (Type Y or N)
N
Comparison between Binary Tree and Binary Search Tree

Binary Tree Binary Search Tree


A tree is said to be a binary tree if it has at A binary search tree is a binary tree in which
most two children. It does not have any order. the key values in the left node is less than the
root and the key values in the right node is
greater than the root.

Exercises:
1. Define Tree.
2. List out the applications of tree.
3. Explain briefly about Tree terminalogy.
4. What are sibilings in a Tree?
5. Define degree in tree terminology.
6. What are Leaf nodes?
368
7. Define Depth of a tree.
8. What is Binary Tree?
9. Explain the various types of Binary Trees in detail.
10. What is skewed binary tree?
11. Discuss some of the operations on Binary Trees.
12. Define BFS.
13. Define DFS.
14. Discuss about Tree Traversal with an example.
15. Write a Java program to implement Binary Tree.
16. Explain in detail about Binary Search Tree.
17. Discuss the operations on BST.
18. Explain Binary Search Tree traversal in detail.
19. Define AVL Tree.
20. Define Splay Tree.
21. Write a Java program to implement Binary Search Tree.
************************

************************************************************
Chapter 20 Graphs
************************************************************
20.1 Introduction
❖ A Graph is a non-linear data structure consisting of nodes and edges. The nodes are also
referred to as vertices and the edges are the lines that connect any two nodes in the graph.

369
❖ A Graph can be defined as G = {V, E} where V is the set of vertices and E is the set of edges.
❖ Cycle is a path that starts and ends at the same index.
❖ A graph with no cycles is called a tree. A tree is an acyclic connected graph.
❖ The degree of a node is the number of edges that are connected with that node.
Example:

Figure 20.1: Graphs


❖ A computer network is a graph where computers are vertices and network connections between
them are edges.
20.2 Application of Graphs
❖ Graphs are used to solve many real-life problems.
❖ Graphs are used to represent the networks. The networks may include paths in a city, telephone
network etc.
❖ In Computer Science graphs are used to represent the flow of computation.
❖ Google Maps uses graphs for building transportation systems, where intersection of two (or
more) roads are considered to be a vertex and the road connecting two vertices is considered
to be an edge, thus their navigation system is based on the algorithm to calculate the shortest
path between two vertices.
❖ Graphs are also used in social networks like LnkedIn, Facebook. For example, in Facebook, each
person is represented with a vertex (or node). Each node is a structure and contains information
like person id, name, gender, locale etc.
❖ The World Wide Web is a graph where web pages are vertices and hyperlinks are edges.
❖ In Operating System, we come across the Resource Allocation Graph where each process and
resources are considered to be vertices. Edges are drawn from resources to the allocated
process, or from requesting process to the requested resource. If this leads to any formation of
a cycle then a deadlock will occur.
20.3 Types of Graph
i) Directed Graph
❖ A graph in which every edge has a direction is called a directed graph. In a directed graph, we
use arrows instead of lines (edges).

❖ Direction denotes the way to reach from one node to another node.

370
Figure 20.2: Directed Graph

ii) Undirected Graph


❖ A graph in which edges are bidirectional is called an undirected graph. In an undirected graph,
we can traverse in any direction.

Figure 20.3: Undirected Graph


iii) Weighted Graph
❖ A weighted graph is a graph in which a weight is assigned to each edge to represent distance or
costs.
❖ A weighted graph can be directed or undirected.

Figure 20.4: Weighted Graph

iv) Connected Graph


❖ A graph is said to be connected if there exists at least one path between every pair of vertices.
Note that a graph with only a vertex is a connected graph.

Figure 20.5: Connected Graph


❖ There are two types of connected graphs.
1. Weekly Connected Graph: A graph in which nodes cannot be visited by a single path is
called a weekly connected graph.

371
Figure 20.6: Weekly Connected Graph
2. Strongly Connected Graph: A graph in which nodes can be visited by a single path is called
a strongly connected graph.

Figure 20.7: Strongly Connected Graph


v) Disconnected Graph
❖ A graph is said to be disconnected if there is no path between a pair of vertices is called a
disconnected graph. A disconnected graph may consist of two or more connected graphs.

Figure 20.8: Disconnected Graph


v) Multi Graph

❖ A graph that has multiple edges connecting the same pair of nodes. The following figure
represents a multi-graph.

Figure 20.9: Multi-graph


vi) Dense Graph
❖ A graph in which the number of edges is close to the maximal number of edges, the graph is
called the dense graph. The following figure represents a dense graph.

372
Figure 20.10: Dense Graph
vii) Sparse Graph

❖ A graph in which the number of edges is close to the minimal number of edges, the graph is
called the sparse graph. It can be a disconnected graph. The following figure represents a sparse
graph.

Figure 20.11: Sparse Graph


20.4 Representation of Graphs
❖ Graph representation is a technique used to store some graph into the computer's memory.
❖ There are two ways to store Graph into the computer's memory: Adjacency Matrix and
Adjacency List.
1) Adjacency Matrix
❖ An adjacency matrix is used to represent a graph. It is based on a 2D-array to represent
all the vertices and edges of a graph.
❖ The elements of the matrix typically have values ‘0' or ‘1'. A value of ‘1' indicates adjacency
between the vertices in the row and column and a value of ‘0' otherwise.
❖ In the adjacency matrix, vertices of the graph represent rows and columns. This means if the
graph has N vertices, then the adjacency matrix will have size N x N.
❖ If V is a set of vertices of the graph then intersection Mij in the adjacency list = 1 means there is
an edge existing between vertices i and j.

Figure 20.12: Adjacency Matrix for an Undirected Graph

❖ The Adjacency matrix for an undirected graph is always a symmetric matrix which means an
edge (i, j) implies the edge (j, i).

373
Figure 20.13: Adjacency Matrix for aDirected Graph
❖ If the graph s directed, then the intersection M ij will be set to 1 only if there is a clear edge
directed from Vi to Vj.

Figure 20.14: Adjacency Matrix for aWeighted Graph.


❖ In the weighted graph, an integer also known as weight is associated with each edge. We
represent this weight in the adjacency Matrix for the edge that exists. This weight is specified
whenever there is an edge from one vertex to another instead of ‘1’.
Advantages of Adjacency Matrix
❖ Adjacency matrix representation of graph is very simple to implement.
❖ Adding or removing time of an edge can be done in O(1) time. Same time is required to check,
if there is an edge between two vertices.
❖ It is very convenient and simple to program.
Disadvantages of Adjacency Matrix
❖ It consumes huge amount of memory for storing big graphs.
❖ It requires huge efforts for adding or removing a vertex. If we are constructing a graph in
dynamic structure, adjacency matrix is quite slow for big graphs.
Example:
//Java program to implement Adjacency Matrix
import java.io.*;
public class AdjacencyMatrix
{
int vertex;
int[][] matrix;
// Constructor
public AdjacencyMatrix(int vertex)
{

374
this.vertex = vertex;
matrix = new int[vertex][vertex];
}
public void addEdge(int start, int destination)
{
matrix[start][destination] = 1;
matrix[destination][start] = 1;
}
public void printGraph()
{
System.out.println("Adjacency Matrix: ");
for (int i = 0; i< vertex; i++)
{
for (int j = 0; j <vertex ; j++)
{
System.out.print(matrix[i][j]+ " ");
}
System.out.println();
}
}
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
AdjacencyMatrix adj = new AdjacencyMatrix(4);
int n, s, d;
System.out.println("Enter the start and the destination values");
n=Integer.parseInt(br.readLine());
for (int i=0;i<n;i++)
{
System.out.println("Enter the start");
s=Integer.parseInt(br.readLine());
System.out.println("Enter the destination");
d=Integer.parseInt(br.readLine());
adj.addEdge(s, d);
}
adj.printGraph();
}
}

Output:

Enter the start and the destination values


3
Enter the start
0
Enter the destination
1
Enter the start
375
1
Enter the destination
2
Enter the start
2
Enter the destination
3
Adjacency Matrix:
0100
1010
0101
2) Adjacency List
❖ An adjacency list represents a graph as an array of linked lists.
❖ The index of the array represents a vertex and each element in its linked list represents the other
vertices that form an edge with the vertex.
❖ Every Vertex has a Linked List. Each Node in this Linked list represents the reference to the
other vertices which share an edge with the current vertex.
❖ The weights can also be stored in the Linked List Node.
❖ When we have traversed all the adjacent nodes for a particular node, we store NULL in the next
link field of the last node of the adjacency list.

Figure 20.15: Adjacency List for the undirected graph


❖ The above figure shows the adjacency list for the undirected graph. We see that each vertex or
node has its adjacency list.
❖ In the case of the undirected graph, the total lengths of adjacency lists are usually twice the
number of edges. In the above graph, the total number of edges is 6 and the total or sum of the
length of all the adjacency list is 12.

Figure 20.16: Adjacency List for a Directed graph

376
❖ In the above directed graph the total length of the adjacency lists of the graph is equal to the
number of edges in the graph. In the above graph, there are 9 edges and sum of the lengths of
adjacency lists for this graph = 9.
❖ In the weighted directed graph, each edge has a weight associated with it. So when we represent
this graph with the adjacency list, we have to add a new field to each list node that will denote
the weight of the edge.

Figure 20.17: Adjacency List for the weighted graph


Advantages of Adjacency List
❖ Adjacency list requires less amount of memory.
❖ Adjacency list allows us to store the graph in more compact form than adjacency matrix.
❖ It allows to get the list of adjacent vertices in O(1) time.
Disadvantages of Adjacency List
❖ It is not easy for adding or removing an edge to/from adjacent list.
❖ It does not allow us to make an efficient implementation, if dynamically change of vertices
number is required.
Example:
//Java Program to implement Adjacency List
import java.io.*;
import java.util.*;
public class Adjacency_List
{
int vertex;
LinkedList<Integer> list[];
public Adjacency_List(int vertex)
{
this.vertex = vertex;
list = new LinkedList[vertex];
for (int i = 0; i<vertex ; i++)
{
list[i] = new LinkedList<>();
}
}
public void addEdge(int source, int destination)
{
//Add edge
list[source].addFirst(destination);
//Add back edge ((for undirected)
377
list[destination].addFirst(source);
}
public void printGraph()
{
for (int i = 0; i<vertex ; i++)
{
if(list[i].size()>0)
{
System.out.print("Vertex " + i + " is connected to: ");
for (int j = 0; j < list[i].size(); j++)
{
System.out.print(list[i].get(j) + " ");
}
System.out.println();
}
}
}
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int n, s, d;
Adjacency_List adj = new Adjacency_List(5);
System.out.println("Enter the total number of source and destination values");
n=Integer.parseInt(br.readLine());
for(int i=0;i<n;i++)
{
System.out.println("Enter the source");
s=Integer.parseInt(br.readLine());
System.out.println("Enter the destination");
d=Integer.parseInt(br.readLine());
adj.addEdge(s, d);
}
adj.printGraph();
}
}
Output:
Enter the total number of source and destination values
7
Enter the source
0
Enter the destination
1
Enter the source
0
Enter the destination
4
Enter the source
1
Enter the destination
2
Enter the source
1

378
Enter the destination
3
Enter the source
1
Enter the destination
4
Enter the source
2
Enter the destination
3
Enter the source
3
Enter the destination
4
Vertex 0 is connected to: 4 1
Vertex 1 is connected to: 4 3 2 0
Vertex 2 is connected to: 3 1
Vertex 3 is connected to: 4 2 1
Vertex 4 is connected to: 3 1 0
20.5 Graph Traversal
❖ Graph traversal means visiting each node exactly once. It is a method used to search nodes
in a graph.
❖ There are two techniques used in graph traversal:
1. Depth First Search
2. Breadth First Search
1. Depth First Search
❖ Depth-First Search (DFS) is a technique that is used to traverse a graph.
❖ DFS technique starts with a root node and then traverses the adjacent nodes of the root
node by going deeper into the graph.
❖ In the DFS technique, the nodes are traversed depth-wise until there are no more children to
explore.
❖ Once we reach the leaf node (no more child nodes), the DFS backtracks and starts with other
nodes and carries out traversal in a similar manner.
❖ DFS technique uses a stack data structure to store the nodes that are being traversed.
❖ Following is the algorithm for the DFS technique.
Algorithm
Step 1: Start with the root node and insert it into the stack
Step 2: Pop the item from the stack and insert into the ‘visited’ list
Step 3: For node marked as ‘visited’ (or in visited list), add the adjacent nodes of this node that are
not yet marked visited, to the stack.
Step 4: Repeat steps 2 and 3 until the stack is empty.

379
Example:
//Java Program to implement the Depth First Search for a Graph
import java.io.*;
import java.util.*;
public class DepthFirstSearch
{
// Function to perform depth first search
static void depthFirstSearch(int[][] matrix, int source)
{
boolean[] visited = new boolean[matrix.length];
visited[source-1] = true;
Stack<Integer> stack = new Stack<>();
stack.push();
int i, x;
System.out.println("The depth first order is");
System.out.println(source);
while(!stack.isEmpty())
{
x = stack.pop();
for(i=0; i<matrix.length; i++)
{
if(matrix[x-1][i] == 1 && visited[i] == false)
{
stack.push(x);
visited[i] = true;
System.out.println(i+1);
x = i+1;
i = -1;
}
}
}
}
// Main Program
public static void main(String args[]) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int vertices;
System.out.println("Enter the number of vertices in the graph");
vertices = Integer.parseInt(br.readLine());
int[][] matrix = new int[vertices][vertices];
System.out.println("Enter the adjacency matrix");
for(int i=0; i<vertices; i++)
{
for(int j=0; j<vertices; j++)
380
{
matrix[i][j] = Integer.parseInt(br.readLine());
}
}
int source;
System.out.println("Enter the source vertex");
source = Integer.parseInt(br.readLine());
depthFirstSearch(matrix,source);
}
}
Output:
Enter the number of vertices in the graph
3
Enter the adjacency matrix
0
0
0
1
0
1
1
1
1
Enter the source vertex
3

The depth first order is

3
1
2
Applications of DFS
1) Detect a cycle in a graph: DFS facilitates to detect a cycle in a graph when we can backtrack to
an edge.
2) Path Finding: As we have already seen in the DFS illustration, given any two vertices we can
find the path between these two vertices.
3) Minimum spanning tree and shortest path: If we run the DFS technique on the non-weighted
graph, it gives us the minimum spanning tree and the shorted path.
4) Topological Sorting: Topological sorting is used when we have to schedule the jobs. We have
dependencies among various jobs. We can also use topological sorting for resolving
dependencies among linkers, instruction schedulers, data serialization, etc.
2. Breadth First Search
❖ Breadth-first (BFS) technique uses a queue to store the nodes of the graph.
381
❖ In BFS we traverse the graph breadth-wise. This means we traverse the graph level wise.
❖ When we explore all the vertices or nodes at one level we proceed to the next level.
Algorithm
Step 1: Begin with the root node and insert it into the queue.
Step 2: Repeat steps 3 and 4 for all nodes in the graph.
Step 3: Remove the root node from the queue, and add it to the Visited list.
Step 4: Now add all the adjacent nodes of the root node to the queue and repeat steps 2 to 4 for
each node.[END OF LOOP]
Step 6: EXIT
Example:
//Java Program to implement Breadth First Search on a graph non-recursively
import java.io.*;
import java.util.*;
public class BreadthFirstSearch
{
// Function to perform breadth first search
static void breadthFirstSearch(int[][] matrix, int source)
{
boolean[] visited = new boolean[matrix.length];
visited[source-1] = true;
Queue<Integer> queue = new LinkedList<>();
queue.add(source);
System.out.println("The breadth first order is");
while(!queue.isEmpty())
{
System.out.println(queue.peek());
int x = queue.poll();
int i;
for(i=0; i<matrix.length;i++)
{
if(matrix[x-1][i] == 1 && visited[i] == false)
{
queue.add(i+1);
visited[i] = true;
}
}
}
}
// Main Program
public static void main(String args[]) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int vertices;

382
System.out.println("Enter the number of vertices in the graph");
vertices = Integer.parseInt(br.readLine());
int[][] matrix = new int[vertices][vertices];
System.out.println("Enter the adjacency matrix");
for(int i=0; i<vertices; i++)
{
for(int j=0; j<vertices; j++)
{
matrix[i][j] = Integer.parseInt(br.readLine());
}
}
int source;
System.out.println("Enter the source vertex");
source = Integer.parseInt(br.readLine());
breadthFirstSearch(matrix, source);
}
}
Output:
Enter the number of vertices in the graph
3
Enter the adjacency matrix
0
0
0
1
0
1
1
1
1
Enter the source vertex
2
The breadth first order is
2
1
3
Applications of BFS
1) Garbage Collection: One of the algorithms used by the garbage collection technique to copy
Garbage collection is “Cheney’s algorithm”. This algorithm uses a breadth-first traversal
technique.
2) Broadcasting in Networks: Broadcasting of packets from one point to another in a network is
done using the BFS technique.

383
3) GPS Navigation: We can use the BFS technique to find adjacent nodes while navigating using
GPS.
4) Social Networking Websites: BFS technique is also used in social networking websites to find
the network of people surrounding a particular person.
5) Shortest path and minimum spanning tree in un-weighted graph: In the unweighted graph,
the BFS technique can be used to find a minimum spanning tree and the shortest path between
the nodes.
20.6 Dijkstra's Algorithm

❖ Dijkstra's algorithm is an algorithm for finding the shortest paths between nodes in
a graph.
❖ It is a generalization of the BFS algorithm.
❖ It was conceived by computer scientist Edsger W. Dijkstra in 1956 and published three years
later.
❖ This algorithm uses the greedy method as it always picks the next closest vertex to the source.
Dijkstra Algorithm Details
❖ Any vertex can be selected as a source vertex and distance between a source vertex to itself is
zero.
❖ Initially, we assume all the other vertices are at a distance of infinity.
❖ Next, we find the direct neighbouring vertex of the source vertex which is at a minimum distance.
Let us assume, a vertex has 2 different neighbouring vertexes A and B at a distance of 2 and 4
then the minimum distance vertex is A in this case.
❖ We mark this vertex as a visited vertex and calculate the distance of each direct neighbouring
vertex.
❖ If the sum of the distance of minimum vertex (d[u]) and cost of edge to neighbouring vertex(c[u,
v]) is less than the distance of v(d[v]), then we update the distance of neighbouring vertex as the
sum of the distance of minimum vertex (d[u]) and cost of edge to neighbouring vertex(c[u, v]).
❖ if(d[u] + c[u, v] < d[v]) -> d[v] = d[u] + c[u, v]
❖ This algorithm always selects the shortest path and updates another vertex if above condition
matches.
❖ We repeat this process until we visit all the vertex of a given graph.
Example:

//Java Program to implement Dijkstra’s Algorithm using Queue


import java.io.*;
import java.util.*;
public class DijkstraQueue
{
private int distances[];
384
private Queue<Integer> queue;
private Set<Integer> settled;
private int number_of_nodes;
private int adjacencyMatrix[][];
public DijkstraQueue(int number_of_nodes)
{
this.number_of_nodes = number_of_nodes;
distances = new int[number_of_nodes + 1];
settled = new HashSet<Integer>();
queue = new LinkedList<Integer>();
adjacencyMatrix = new int[number_of_nodes + 1][number_of_nodes + 1];
}
public void dijkstra_algorithm(int adjacency_matrix[][], int source)
{
int evaluationNode;
for (int i = 1; i<= number_of_nodes; i++)
for (int j = 1; j <= number_of_nodes; j++)
adjacencyMatrix[i][j] = adjacency_matrix[i][j];
for (int i = 1; i<= number_of_nodes; i++)
{
distances[i] = Integer.MAX_VALUE;
}
queue.add(source);
distances[source] = 0;
while (!queue.isEmpty())
{
evaluationNode = getNodeWithMinimumDistanceFromQueue();
settled.add(evaluationNode);
evaluateNeighbours(evaluationNode);
}
}
private int getNodeWithMinimumDistanceFromQueue()
{
int min;
int node = 0;
Iterator<Integer> iterator = queue.iterator();
node = iterator.next();
min = distances[node];
for (int i = 1; i<= distances.length; i++)
{
if (queue.contains(i))
{
if (distances[i] <= min)
{
min = distances[i];
node = i;
}
}
}
queue.remove(node);
return node;
}

private void evaluateNeighbours(int evaluationNode)


385
{
Int edgeDistance = -1;
int newDistance = -1;
for (int destinationNode = 1; destinationNode<= number_of_nodes; destinationNode++)
{
if (!settled.contains(destinationNode))
{
if (adjacencyMatrix[evaluationNode][destinationNode] != Integer.MAX_VALUE)
{
edgeDistance = adjacencyMatrix[evaluationNode][destinationNode];
newDistance = distances[evaluationNode] + edgeDistance;
if (newDistance< distances[destinationNode])
{
distances[destinationNode] = newDistance;
}
queue.add(destinationNode);
}
}
}
}
public static void main(String args[])
{
int adjacency_matrix[][];
int n;
int source = 0;
Scanner sc = new Scanner(System.in);
try
{
System.out.println("Enter the number of vertices");
n = sc.nextInt();
adjacency_matrix = new int[n + 1][n + 1];
System.out.println("Enter the Weighted Matrix for the graph");
for (int i = 1; i<= n; i++)
{
for (int j = 1; j <=n; j++)
{
adjacency_matrix[i][j] = sc.nextInt();
if (i == j)
{
adjacency_matrix[i][j] = 0;
continue;
}
if (adjacency_matrix[i][j] == 0)
{
adjacency_matrix[i][j] = Integer.MAX_VALUE;
}
}
}
System.out.println("Enter the source ");
source = sc.nextInt();
DijkstraQueue DQ = new DijkstraQueue(n);
DQ.dijkstra_algorithm(adjacency_matrix, source);
System.out.println("The Shorted Path to all nodes are ");
for (int i = 1; i<= DQ.distances.length - 1; i++)
386
{
System.out.println(source + " to " + i + " is " + DQ.distances[i]);
}
}
catch (InputMismatchException ime)
{
System.out.println("Wrong Input Format");
}
sc.close();
}
}

Output:

Enter the number of vertices


5
Enter the Weighted Matrix for the graph
07002
00102
00040
00500
03850
Enter the source
1
The Shorted Path to all nodes are
1 to 1 is 0
1 to 2 is 5
1 to 3 is 6
1 to 4 is 7
1 to 5 is 2
20.7 Depth-First vs Breadth-First Search

Sr. No. DFS BFS


1 DFS stands for Depth First Search. BFS stands for Breadth First Search.
2 DFS uses Stack to find the shortest path. BFS uses Queue to find the shortest path.
DFS is better when target is far from BFS is better when target is closer to
3
source. Source.
DFS is more suitable for decision tree. As
As BFS considers all neighbour so it is not
with one decision, we need to traverse
4 suitable for decision tree used in puzzle
further to augment the decision. If we reach
games.
the conclusion, we won.
5 DFS is faster than BFS. BFS is slower than DFS.
Time Complexity of DFS is also O(V+E) Time Complexity of BFS = O(V+E)
6
where V is vertices and E is edges. where V is vertices and E is edges.
Exercises:
387
1. Define Graph.
2. Explain the applications of Graphs.
3. Discuss in detail about various kinds of Graphs.
4. Define dense Graph.
5. Define Sparse Graph.
6. What is disconnected Graph?
7. Explain Adjacency Matrix.
8. Explain Adjacency List in detail.
9. Discuss Graph Traversal in detail.
10. Write a Java program to implement DFS for a graph.
11. Explain few applications of Graph.
12. Define BFS in Graph.
13. How BFS performed in a Graph?
14. Explain in detail about dijkstra’s algorithm.
15. Distinguish between DFS and BFS.
****************************

388
PRACTICAL - III DATA STRUCTURES USING JAVA LAB

II YEAR / III SEM

OBJECTIVES:

• To implement linear and non-linear data structures


• To understand the different operations of search trees
• To implement graph traversal algorithms

OUTCOMES:

• Write functions to implement linear and non-linear data structure operations.


• Suggest appropriate linear and non-linear data structure operations for solving a given
problem.

LIST OF EXERCISES:

1. Write a Java program to implement the Stack ADT using a singly linked list.

2. Write a Java program to implement the Queue ADT using a singly linked list.

3. Write a Java program for the implementation of circular Queue.

4. Write a Java program that reads an infix expression, converts into postfix form.

5. Write a Java program to evaluate the postfix expression (use stack ADT).

6. Write a Java program to an Insert an element into a binary search tree.

7. Write a Java program to delete an element from a binary search tree.

8. Write a Java program to search for a key element in a binary search tree.

9. Write a Java program for the implementation of BFS for a given graph.

10. Write a Java program for the implementation of DFS for a given graph.

389
1. Implementation of Stack ADT using Singly Linked List

Aim:

To write a Java program to implement the Stack operations using Singly Linked Lists.

Algorithm:

Step 1: Start the execution.

Step 2: The push() method is used to insert an element on the top of the stack.

Step 3: The pop() method is used to remove the topmost element from the stack.

Step 4: The peek() method is used to display the topmost element from the stack.

Step 5: The display() method is used to display all the elements in the stack.

Step 6: Stop the execution.

Program:

// 1. Java Program to implement the Stack Using Singly Linked List


// StackList.java
import java.io.*;
import java.util.*;
class StackUsingLinkedList
{
private class Node
{
int data;
Node link;
}
Node top;
StackUsingLinkedList() // Constructor
{
this.top = null;
}
// Function to push an element into the stack
public void push(int x) // Insert at the beginning
{
// Create new node temp and allocate memory
Node temp = new Node();
if (temp == null)
{
System.out.print("\nStack Overflow");
return;
}
temp.data = x;
temp.link = top;
top = temp;
390
}
// Function to check if the stack is empty or not
public boolean isEmpty()
{
return top == null;
}
// Function to delete an element from the stack
public int pop()
{
if(isEmpty())
{
System.out.println("\n Stack is Empty...");
return 0;
}
else
{
int r1=top.data;
top=top.link;
return r1;
}
}
// Function to return the top element in the stack
public int peek()
{
if (!isEmpty())
{
return top.data;
}
else
{
System.out.println("Stack is empty");
return -1;
}
}
//Function to display the Stack elements
public void display()
{
if (top == null)
{
System.out.printf("\nStack Underflow");
}
else
{
Node temp = top;
while (temp != null)
{
System.out.println(temp.data +" ");
391
temp = temp.link;
}
}
}
}
// Main Class
public class StackList
{
public static void main(String args[]) throws IOException
{
int choice;
StackUsingLinkedList SL = new StackUsingLinkedList();
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.println("Stack Operations Using Linked Lists\n");
do
{
System.out.println("\nMENU");
System.out.println("-----------");
System.out.println("1. Push");
System.out.println("2. Pop");
System.out.println("3. Peek");
System.out.println("4. Display");
System.out.println("5. Exit");
System.out.println("Enter your choice:");
choice=Integer.parseInt(br.readLine());
switch(choice)
{
case 1:
System.out.println("Enter the element to push: ");
int n=Integer.parseInt(br.readLine());
SL.push(n);
break;
case 2:
System.out.println("The popped element is: "+ SL.pop());
break;
case 3:
System.out.println("The top element is: "+ SL.peek());
break;
case 4:
System.out.println("\nThe Stack elements are:");
SL.display();
break;
case 5:
System.exit(0);
default:
System.out.println("!Wrong Choice");
break;
392
}
}
while(choice!=5);
}
}
Output:
Stack Operations Using Linked Lists

MENU
---------
1. Push
2. Pop
3. Peek
4. Display
5. Exit
Enter your choice:
1
Enter the element to push:
11
MENU
---------
1. Push
2. Pop
3. Peek
4. Display
5. Exit
Enter your choice:
1
Enter the element to push:
22
MENU
---------
1. Push
2. Pop
3. Peek
4. Display
5. Exit
Enter your choice
1
Enter the element to push:
33
MENU
---------
1. Push
2. Pop
3. Peek

393
4. Display
5. Exit
Enter your choice:
4
The Stack elements are:
33 22 11
MENU
---------
1. Push
2. Pop
3. Peek
4. Display
5. Exit
Enter your choice
3
The top element is: 33
MENU
---------
1. Push
2. Pop
3. Peek
4. Display
5. Exit
Enter your choice
2
The popped element is: 33
MENU
---------
1. Push
2. Pop
3. Peek
4. Display
5. Exit
Enter your choice
4
The Stack elements are:
22 11
MENU
---------
1. Push
2. Pop
3. Peek
4. Display
5. Exit
Enter your choice
5
394
Result:
Thus, the Java program to implement the Stack operations using Singly Linked List has been
executed successfully.
*******************************************************************************

2. Implementation of Queue ADT using Singly Linked List


Aim:

To write a Java program to implement the Queue operations using Singly Linked Lists.

Algorithm:

Step 1: Start the execution.

Step 2: The insert() method is used to add the element at the rear of the queue.

Step 3: The delete() method is used to remove the element at the front of the queue.

Step 4: The peek() method is used to return the first element at the front of the queue.

Step 5: The display() method is used to display all the elements of the queue.

Step 6: Stop the execution.

Program:

// 2. Java Program to implement the Queue using Singly Linked List


// LinkedQueueImplement.java
import java.io.*;
import java.util.*;
class Node
{
protected int data;
protected Node link;
public Node() // Constructor
{
link = null;
data = 0;
}
public Node(int d, Node n) // Constructor
{
data = d;
link = n;
}
// Function to set link to next Node
public void setLink(Node n)
{
link = n;
}

395
// Function to set data to current Node
public void setData(int d)
{
data = d;
}
// Function to get link to next node
public Node getLink()
{
return link;
}
// Function to get data from current Node
public int getData()
{
return data;
}
}
class LinkedQueue
{
protected Node front, rear;
public int size;
public LinkedQueue() //Constructor
{
front = null;
rear = null;
size = 0;
}
// Function to check if queue is empty
public boolean isEmpty()
{
return front == null;
}
// Function to get the size of the queue
public int getSize()
{
return size;
}
// Function to insert an element to the queue
public void insert(int data)
{
Node nptr = new Node(data, null);
if (rear == null)
{
front = nptr;
rear = nptr;
}
else
{
396
rear.setLink(nptr);
rear = rear.getLink();
}
size++;
}
// Function to delete the front element from the queue
public int delete()
{
if (isEmpty())
throw new NoSuchElementException("Underflow Exception");
Node ptr = front;
front = ptr.getLink();
if (front == null)
rear = null;
size-- ;
return ptr.getData();
}
// Function to return the front element of the queue
public int peek()
{
if (isEmpty())
throw new NoSuchElementException("Underflow Exception");
return front.getData();
}
// Function to display the queue elements
public void display()
{
System.out.print("\nQueue = ");
if (size == 0)
{
System.out.print("Queue is Empty\n");
return;
}
Node ptr = front;
while (ptr != rear.getLink() )
{
System.out.print(ptr.getData()+" ");
ptr = ptr.getLink();
}
System.out.println();
}
}
public class LinkedQueueImplement
{
public static void main(String args[]) throws IOException
{
Scanner sc = new Scanner(System.in);
397
LinkedQueue lq = new LinkedQueue();
int x;
// Perform Queue Operations
System.out.println("Linked Queue Test\n");
char ch;
do
{
System.out.println("Queue Operations");
System.out.println("1. Insert");
System.out.println("2. Delete");
System.out.println("3. Peek");
System.out.println("4. Display");
System.out.println("5. Exit");
System.out.println("\nEnter your choice");
int choice = sc.nextInt();
switch(choice)
{
case 1 :
System.out.println("Enter the element to insert");
x = sc.nextInt();
lq.insert(x);
lq.display();
break;
case 2 :
System.out.println("Deleted Element = "+ lq.delete());
lq.display();
break;
case 3 :
System.out.println("Front Element = "+ lq.peek());
lq.display();
break;
case 4 :
lq.display();
break;
case 5 :
System.exit(0);
break;
default:
System.out.println("Wrong Choive\n ");
break;
}
System.out.println("\nDo you want to continue? (Type Y or N)");
ch = sc.next().charAt(0);
}
while (ch == 'Y'|| ch == 'y');
}
}
398
Output:
Linked Queue Test
Queue Operations
1. Insert
2. Delete
3. Peek
4. Display
5. Exit
Enter your choice
1
Enter the element to insert
24
Queue = 24
Do you want to continue? (Type Y or N)
Y
Queue Operations
1. Insert
2. Delete
3. Peek
4. Display
5. Exit
Enter your choice
1
Enter the element to insert
5
Queue = 24 5
Do you want to continue? (Type Y or N)
Y
Queue Operations
1. Insert
2. Delete
3. Peek
4. Display
5. Exit
Enter your choice
3
Front Element = 24
Queue = 24 5
Do you want to continue? (Type Y or N)
Y
Queue Operations
1. Insert
2. Delete
3. Peek
4. Display
5. Exit
399
Enter your choice
2
Deleted Element = 24
Queue = 5
Do you want to continue? (Type Y or N)
Y
Queue Operations
1. Insert
2. Delete
3. Peek
4. Display
5. Exit
Enter your choice
4
Queue = 5
Do you want to continue? (Type Y or N)
Y
Queue Operations
1. Insert
2. Delete
3. Peek
4. Display
5. Exit
Enter your choice
5
Do you want to continue? (Type Y or N)
N
Result:
Thus, the Java program to implement the Queue operations using Linked List has been executed
successfully.
***************************************************************************

3. Implementation of Circular Queue


Aim:

To write a Java program to implement the Circular Queue using Linked Lists.

Algorithm:

Step 1: Start the execution.


Step 2: The enqueue() method is used to add an item into the circular queue.
Step 3: The dequeue() method is used to remove an item from the circular queue.
Step 4: The display() method is used to display all the elements of the circular queue.
Step 5: Stop the execution.

400
Program:

// 3. Java Program to implement the Circular Queue using Linked List


// CircularQueueUsingLinkedList.java
import java.io.*;
import java.util.*;
class CircularQueueUsingLinkedList
{
static class Node
{
int data;
Node link;
}
static class Circular_Queue
{
Node front, rear;
}
// Function to add the element into the Circular Queue
static void enQueue(Circular_Queue q, int value)
{
Node temp = new Node();
temp.data = value;
if (q.front == null)
q.front = temp;
else
q.rear.link = temp;
q.rear = temp;
q.rear.link = q.front;
}
// Function to delete an element from the Circular Queue
static int deQueue(Circular_Queue q)
{
if (q.front == null)
{
System.out.printf("Queue is empty");
return 0;
}
// If this is the last node to be deleted
int value;
if (q.front == q.rear)
{
value = q.front.data;
q.front = null;
q.rear = null;
}
else
{
401
Node temp = q.front;
value = temp.data;
q.front = q.front.link;
q.rear.link = q.front;
}
return value;
}
// Function display the elements of a Circular Queue
static void display(Circular_Queue q)
{
Node temp = q.front;
System.out.println("\nThe Circular Queue Elements are: ");
while (temp.link != q.front)
{
System.out.println(temp.data+" ");
temp = temp.link;
}
System.out.println(temp.data+" ");
}
//Main Program
public static void main(String args[])
{
Circular_Queue cq = new Circular_Queue();
cq.front = cq.rear = null;
int ch, x;
Scanner sc=new Scanner(System.in);
do
{
System.out.println("\nCircular Queue Operations\n");
System.out.println("\n 1. Add \n 2. Delete \n 3. Display \n 4. Exit");
System.out.print("\nEnter Your Choice : ");
ch= sc.nextInt();
switch(ch)
{
case 1 :
System.out.print("\nEnter the element to add: ");
x = sc.nextInt();
enQueue(cq, x);
break;
case 2 :
x = deQueue(cq);
System.out.println("\nItem deleted from the queue is: " + x);
break;
case 3 :
display(cq);
break;

402
case 4 :
System.exit(0);
default :
System.out.println("\nWrong Choice !");
break;
}
}
while(ch!=4);
}
}

Output:
Circular Queue Operations
1. Add
2. Delete
3. Display
4. Exit
Enter Your Choice: 1
Enter the element to add:
10
Circular Queue Operations
1. Add
2. Delete
3. Display
4. Exit
Enter Choice: 1
Enter the element to add:
20
Circular Queue Operations
1. Add
2. Delete
3. Display
4. Exit
Enter Choice: 3
The Circular Queue elements are: 10 20
Circular Queue Operations
1. Add
2. Delete
3. Display
4. Exit
Enter Choice: 2
Item deleted from the queue is: 10
Circular Queue Operations
1. Add
2. Delete
3. Display

403
4. Exit
Enter Choice: 4

Result:

Thus, the Java program to implement the Circular Queue using Arrays has been executed
successfully.

***************************************************************************

4. Infix to Postfix Conversion


Aim:

To write a Java program to convert the given Infix expression to Postfix form using Stack.

Algorithm:
Step 1: Start the execution.

Step 2: Scan the infix notation from left to right one character at a time.

Step 3: If the next symbol scanned as an operand, append it to the postfix string.

Step 4: If the next symbol scanned is an operator, then:

i. Pop and append to the postfix string every operator on the stack that:

a. Is above the most recently scanned left parenthesis, and

b. Has precedence higher than or is a right-associative operator of equal precedence to


that of the new operator symbol.

ii. Push the new operator onto the stack

Step 5: If a left parenthesis is scanned, push it into the stack.

Step 6: If a right parenthesis is scanned, all operators down to the most recently scanned left
parenthesis must be popped and appended to the postfix string. Furthermore, the pair of
parentheses must be discarded.

Step 7: When the infix string is fully scanned, the stack may still contain some operators. All the
remaining operators should be popped and appended to the postfix string.

Step 8: Stop the execution.

Program:

// 4. Java program for Infix to Postfix Conversion


// InfixToPostfix
import java.io.*;
class Stack
{
char a[]=new char[100];
int top=-1;
404
void push(char c)
{
try
{
a[++top]= c;
}
catch(StringIndexOutOfBoundsException e)
{
System.out.println("Stack full, no room to push, size=100");
System.exit(0);
}
}
char pop()
{
return a[top--];
}
boolean isEmpty()
{
return (top==-1)?true:false;
}
char peek()
{
return a[top];
}
}
public class InfixToPostfix
{
static Stack operators = new Stack();
public static void main(String args[]) throws IOException
{
String infix;
BufferedReader br = new BufferedReader (new InputStreamReader(System.in));
System.out.print("\nEnter the infix expression you want to convert: ");
infix = br.readLine();
System.out.println("Postfix expression for the given infix expression is:" +
toPostfix(infix));
}
private static String toPostfix(String infix)
//Converts an infix expression to postfix
{
char symbol;
String postfix = "";
for(int i=0;i<infix.length();++i)
//While there is input to be read
{
symbol = infix.charAt(i);
//If it's an operand, add it to the string
405
if (Character.isLetter(symbol))
postfix = postfix + symbol;
else if (symbol=='(')
{
operators.push(symbol);
}
else if (symbol==')')
{
while (operators.peek() != '(')
{
postfix = postfix + operators.pop();
}
operators.pop();
}
else
{
while (!operators.isEmpty() && !(operators.peek()=='(') &&prec(symbol) <=
prec(operators.peek()))
postfix = postfix + operators.pop();
operators.push(symbol);
}
}

while (!operators.isEmpty())
postfix = postfix + operators.pop();
return postfix;
}
static int prec(char x)
{
if (x == '+' || x == '-')
return 1;
if (x == '*' || x == '/' || x == '%')
return 2;
return 0;
}
}
Output:
Enter the Infix Expression
A*(B-C)/D+E
The Postfix of the given Infix Expression is: ABC-*D/E+
Result:
Thus, the Java program to convert the given Infix Expression to postfix form using Stack has
been executed successfully.

***************************************************************************
406
5. Java program to evaluate the Postfix Expression using Stack
Aim:

To write a Java program to evaluate the given Postfix Expression using Stack.

Algorithm:

Step 1: Start the execution


Step 2: Create a stack to store operands (or values)
Step 3: Scan the given expression and do following for every scanned element.
a) If the element is a number, push it into the stack
b) If the element is a operator, pop operands for the operator from stack.
Evaluate the operator and push the result back to the stack
Step 4: When the expression is ended, the number in the stack is the final answer
Step 5: Stop the execution.
Program:
// 5. Java program to evaluate value the postfix expression using Stack
// Test.java
import java.io.*;
import java.util.*;
public class Test
{
// Method to evaluate value of a postfix expression
static int evaluatePostfix(String exp)
{
//Create an empty stack
Stack<Integer> stack=new Stack<>();
// Scan all characters one by one
for(int i=0;i<exp.length();i++)
{
char c=exp.charAt(i);
// If the scanned character is an operand, push it to the stack.
if (Character.isDigit(c))
stack.push(c - '0');
else
{
// If the scanned character is an operator, pop two elements from the stack
int x = stack.pop();
int y = stack.pop();
switch(c)
{
case '+':
stack.push(y + x);
break;
case '-':
stack.push(y - x);
break;

407
case '*':
stack.push(y * x);
break;
case '/':
stack.push(y / x);
break;
}
}
}
return stack.pop();
}
public static void main(String args[]) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter the Postfix Expression");
String exp=br.readLine();
System.out.println("Postfix Evaluation: "+evaluatePostfix(exp));
}
}
Output:
Enter the Postfix Expression
138×+
Postfix Evaluation: 25
Result:
Thus, the Java program to evaluate the Postfix expression using stack has been executed
successfully.

******************************************************************************

408
6. Java Program to insert an element into the Binary Search Tree

Aim:

To write a Java Program to insert an element into the Binary Search Tree.

Algorithm:

Step 1 : Start the execution

Step 2 : Read the value of n.

Step 3: Using for loop, read the node elements one by one.

Step 4 : Start from the root.

Step 3 : Compare the element to be inserted with the root node.

Step 4: If the value of the new node is less than the root node then, it will be inserted to the left
subtree.

Step 5: If the value of the new node is greater than root node then, it will be inserted to the right
subtree.

Step 6 : On reaching the end node, insert the value left (if the value is smaller than current node
value), else right.

Step 7 : Stop the execution.

Program:

// 6. Java Program to insert an element into the Binary Search Tree


// BinarySearchTree.java
import java.io.*;
public class BinarySearchTree
{
private Node root;
BinarySearchTree()
{
root = null;
}
static class Node
{
int value;
Node left;
Node right;
Node(int value)
{
this.value = value;
left = null;
right = null;
}
public void displayData()
{
System.out.print(value + " ");
409
}
}
public void insert(int i)
{
root = insert(root, i);
}
//Inserting node - recursive method
public Node insert(Node node, int value)
{
if(node == null)
{
return new Node(value);
}
// Move to the left if passed value is less than the current node
if (value <node.value)
{
node.left = insert(node.left, value);
}
// Move to the right if passed value is greater than the current node
else
if (value >node.value)
{
node.right = insert(node.right, value);
}
return node;
}
// For traversing in order
public void inOrder(Node node)
{
if(node != null)
{
inOrder(node.left);
node.displayData();
inOrder(node.right);
}
}
// Preorder traversal
public void preOrder(Node node)
{
if(node != null)
{
node.displayData();
preOrder(node.left);
preOrder(node.right);
}
}
// Postorder traversal
public void postOrder(Node node)
{
if(node != null)
{
postOrder(node.left);
postOrder(node.right);
node.displayData();
410
}
}
//Main Program
public static void main(String args[]) throws IOException
{
BinarySearchTree bst = new BinarySearchTree();
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int n, x;
System.out.println("Enter the total nodes");
n=Integer.parseInt(br.readLine());
System.out.println("Enter the node elements");
for (int i=1;i<=n;i++)
{
x=Integer.parseInt(br.readLine());
bst.insert(x);
}
System.out.println("Inorder traversal of binary search tree");
bst.inOrder(bst.root);
System.out.println();
System.out.println("Preorder traversal of binary search tree");
bst.preOrder(bst.root);
System.out.println();
System.out.println("Postorder traversal of binary search tree");
bst.postOrder(bst.root);
}
}
Output:
Enter the total nodes
6
Enter the node elements
50
70
15
35
30
31
Inorder traversal of binary search tree
15 30 31 35 50 70

Preorder traversal of binary search tree


50 15 35 30 31 70

Postorder traversal of binary search tree


31 30 35 15 70 50
Result:

Thus, the Java program to insert an element into the Binary Search Tree has been executed
successfully.

***************************************************************************

411
7. Java program to delete an element from a binary search tree

Aim:

To write a Java program to delete an element from a Binary Search Tree.

Algorithm:

Step 1 : Start the execution

Step 2 : Read the value of n.

Step 3 : Using for loop, read the node elements one by one.

Step 2 : Start from the root.

Step 3 : Compare the element to be inserted with the root node.

Step 4 : If the value of the new node is less than the root node then, it will be inserted to the left
subtree.

Step 5 : If the value of the new node is greater than root node then, it will be inserted to the right
subtree.

Step 6 : On reaching the end node, insert the value left (if the value is smaller than current node
value), else right.

Step 7 : Read the value of the node to be deleted.

Step 8 : When we delete a node, three possibilities arise.

i) Node to be deleted is the leaf: Simply remove from the tree.

ii) Node to be deleted has only one child: Copy the child to the node and delete the
child

iii) Node to be deleted has two children: Find inorder successor of the node. Copy
contents of the inorder successor to the node and delete the inorder successor.
Note that inorder predecessor can also be used.

Step 9 : Stop the execution.

Program:

// 7. Java Program to delete an element from a Binary Search Tree


// BinarySearchTree.java
import java.io.*;
class BinarySearchTree
{
class Node
{
int key;
Node left, right;
public Node(int item)
{
412
key = item;
left = right = null;
}
}
Node root;
BinarySearchTree() // Constructor
{
root = null;
}
// This method mainly calls deleteRec()
void deleteKey(int key)
{
root = deleteRec(root, key);
}
// A recursive function to delete an existing key in BST
Node deleteRec(Node root, int key)
{
// Base Case: If the tree is empty
if (root == null)
return root;
// Otherwise, recur down the tree
if (key <root.key)
root.left = deleteRec(root.left, key);
else if (key >root.key)
root.right = deleteRec(root.right, key);
// If key is same as root's key, then this is the node to be deleted
else
{
// Node with only one child or no child
if (root.left == null)
return root.right;
else if (root.right == null)
return root.left;
// Node with two children: Get the inorder successor (smallest in the right subtree)
root.key = minValue(root.right);
// Delete the inorder successor
root.right = deleteRec(root.right, root.key);
}
return root;
}
int minValue(Node root)
{
int minv = root.key;
while (root.left != null)
{
minv = root.left.key;
root = root.left;
}
return minv;
}
// This method mainly calls insertRec()
void insert(int key)
{
root = insertRec(root, key);
413
}
// A recursive function to insert a new key in BST
Node insertRec(Node root, int key)
{
// If the tree is empty, return a new node
if (root == null)
{
root = new Node(key);
return root;
}
// Otherwise, recur down the tree
if (key <root.key)
root.left = insertRec(root.left, key);
else if (key >root.key)
root.right = insertRec(root.right, key);
// Return the (unchanged) node pointer
return root;
}
// This method mainly calls InorderRec()
void inorder()
{
inorderRec(root);
}
// A utility function to do inorder traversal of BST
void inorderRec(Node root)
{
if (root != null)
{
inorderRec(root.left);
System.out.print(root.key + " ");
inorderRec(root.right);
}
}
// Main Program
public static void main(String args[]) throws IOException
{
BinarySearchTree bst = new BinarySearchTree();
/* Let us create following BST
50
/ \
30 70
/ \ / \
20 40 60 80 */
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int n, x, d;
System.out.println("Enter the total nodes");
n=Integer.parseInt(br.readLine());
System.out.println("Enter the node elements");
for (int i=1;i<=n;i++)
{
x=Integer.parseInt(br.readLine());
bst.insert(x);
}
System.out.println("Inorder traversal of the given binary search tree");
414
bst.inorder();
System.out.println("\nEnter the node to be deleted");
d=Integer.parseInt(br.readLine());
bst.deleteKey(d);
System.out.println( "Binary Search Tree after deleting a node");
bst.inorder();
}
}

Output:
Enter the total nodes
6
Enter the node elements
50
30
20
40
70
60
Inorder traversal of the given tree
20 30 40 50 60 70
Enter the node to be deleted
20
Binary Search Tree after deleting a node
30 40 50 60 70

Result:

Thus, the Java program to delete an element from the Binary Search Tree has been executed
successfully.

415
8. Java program to search for a key element in a binary search tree

Aim:

To write a Java program to search an element in a Binary Search Tree.

Algorithm:

Step 1 : Start the execution.

Step 2 : Read the value of n.

Step 3 : Using for loop, read the node elements one by one.

Step 2 : Start from the root.

Step 3 : Compare the element to be inserted with the root node.

Step 4 : If the value of the new node is less than the root node then, it will be inserted to the left
subtree.

Step 5 : If the value of the new node is greater than root node then, it will be inserted to the right
subtree.

Step 6 : On reaching the end node, insert the value left (if the value is smaller than current node
value), else right.

Step 7: Read the value of the node to be searched.

Step 8 : Compare the element to be searched with the root node.

Step 9 : If the key (element to be searched) = root, return root node.

Step 10: Else if key < root, traverse the left subtree.

Step 11: Else traverse right subtree.

Step 12: Repetitively compare subtree elements until the key is found or the end of the tree is
reached.

Step 13: If the element to search is found anywhere, return true, else return false.

Step 14: Stop the execution.

Program:

// 8. Java Program to search for a key element in a Binary Search Tree


// BinarySearchTreee.java
import java.io.*;
public class BinarySearchTree
{
private Node root;
BinarySearchTree()
{

416
root = null;
}
static class Node
{
int value;
Node left;
Node right;
Node(int value)
{
this.value = value;
left = null;
right = null;
}
public void displayData()
{
System.out.print(value + " ");
}
}
public void insert(int i)
{
root = insert(root, i);
}
//Inserting node - recursive method
public Node insert(Node node, int value)
{
if(node == null)
{
return new Node(value);
}

// Move to the left if passed value is less than the current node
if (value <node.value)
{
node.left = insert(node.left, value);
}
// Move to the right if passed value is greater than the current node
else
if (value >node.value)
{
node.right = insert(node.right, value);
}
return node;
}
// Search node in binary search tree
public Node find(int searchedValue)
{
Node current = root;
417
while(current.value != searchedValue)
{
if(searchedValue<current.value)
// Move to the left if searched value is less
current = current.left;
else
// Move to the right if searched value is >=
current = current.right;
if (current == null)
{
return null;
}
}
return current;
}
// For traversing in order
public void inOrder(Node node)
{
if(node != null)
{
inOrder(node.left);
node.displayData();
inOrder(node.right);
}
}
// Preorder traversal
public void preOrder(Node node)
{
if(node != null)
{
node.displayData();
preOrder(node.left);
preOrder(node.right);
}
}
// Postorder traversal
public void postOrder(Node node)
{
if(node != null)
{
postOrder(node.left);
postOrder(node.right);
node.displayData();
}
}

418
//Main Program
public static void main(String args[]) throws IOException
{
BinarySearchTree bst = new BinarySearchTree();
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int n, x, s;
System.out.println("Enter the total nodes");
n=Integer.parseInt(br.readLine());
System.out.println("Enter the node elements");
for (int i=1;i<=n;i++)
{
x=Integer.parseInt(br.readLine());
bst.insert(x);
}
System.out.println("Inorder traversal of binary search tree");
bst.inOrder(bst.root);
System.out.println();
System.out.println("Preorder traversal of binary search tree");
bst.preOrder(bst.root);
System.out.println();
System.out.println("Postorder traversal of binary searcg tree");
bst.postOrder(bst.root);
System.out.println();
System.out.println("Enter the element to search");
s=Integer.parseInt(br.readLine());
Node node = bst.find(s);
System.out.println((node == null)? "Node not found": String.valueOf(node.value));
}
}
Output:
Enter the total nodes
6
Enter the node elements
50
70
15
35
Enter the element to search
16
Inorder traversal of binary tree
15 35 50 70
Preorder traversal of binary tree
50 15 35 70
Postorder traversal of binary tree
35 15 70 50
Node not found
419
Result:

Thus, the Java program to search an element in a Binary Search Tree has been executed
successfully.

***************************************************************************

9. Implementation of BFS for a given graph

Aim:

To write a Java program to implement the BFS for a given graph.

Algorithm:

Step 1 : Start the execution.

Step 2 : Create an empty queue and push root node to it.

Step 3 : Do the following when the queue is not empty.

Step 4 : Pop a node from queue and print it.

Step 5 : Find neighbors of node with the help of adjacency matrix and check if node is

already visited or not.

Step 6 : Push neighbors of node into queue if not null

Step 7 : Stop the execution.

Program:

// 9. BFS_Graph.java
import java.io.*;
import java.util.*;
public class BFS_Graph
{
final int TRUE = 1;
final int FALSE = 0;
final int MAX = 20;
int [][] G = new int [MAX][MAX];
int [] visited = new int [MAX];
int [] q = new int [MAX];
int n, v1, v2;
int front, rear;
BFS_Graph()
{
System.out.println("Enter the number of nodes");
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
for (int i=1;i<=n;i++)
visited[i] = FALSE;
420
for (v1=1;v1<=n;v1++)
{
for (v2=1;v2<=n;v2++)
G[v1][v2] = FALSE;
}
front = rear = -1;
}
void CreateGraph()
{
char ans;
System.out.println("Enter the edges with vertex no. starting from 1");
do
{
System.out.println("Enter the vertices v1 & v2:");
Scanner sc = new Scanner(System.in);
v1 = sc.nextInt();
v2 = sc.nextInt();
if (v1 > n || v2 > n)
System.out.println("Invalid Vertex Number");
else
{
G[v1][v2] = TRUE;
G[v2][v1] =TRUE;
}
System.out.println("Want to add more edges (y/n)?");
ans = sc.next().charAt(0);
}
while (ans == 'Y' || ans == 'y');
}
void Adjacency_Matrix()
{
System.out.println("Adjacency Matrix for the Graph is");
for (int v1=1;v1<=n;v1++)
{
for (int v2=1;v2<=n;v2++)
System.out.print(G[v1][v2] + " ");
System.out.println();
}
}
void bfs(int v)
{
int i;
visited[v] = TRUE;
q[++rear] = v;
while (front != rear)
{
v = q[++front];
421
System.out.println(v +" ");
for (i=1;i<=n;i++)
{
if (G[v][i] == TRUE && visited[i] == FALSE)
{
q[++rear] = i;
visited[i] = TRUE;
}
}
}
}
public static void main(String args[])
{
System.out.println("Implementation of BFS for a given graph");
BFS_Graph g = new BFS_Graph();
g.CreateGraph();
g.Adjacency_Matrix();
System.out.println("Breadth First Traversal for the above graph is");
g.bfs(1);
}
}
Output:
Implementation of BFS for a given graph
Enter the number of nodes
4
Enter the edges with vertex no. starting from 1
Enter the vertices v1 & v2:
1
2
Want to add more edges (y/n)?
y
Enter the vertices v1 & v2:
1
3
Want to add more edges (y/n)?
y
Enter the vertices v1 & v2:
1
4
Want to add more edges (y/n)?

422
y
Enter the vertices v1 & v2:
2
3
Want to add more edges (y/n)?
n
Adjacency Matrix for the Graph is
0111
1010
0100
1000
Depth first traversal for the above graph is
1
2
3
4
Result:

Thus, the Java program to implement the Breadth First Search for a graph has been executed
successfully.

*******************************************************************************

10. Implementation of DFS for a given graph

Aim:

To write a Java program to implement the DFS for a given graph.

Algorithm:

Step 1: Start the execution.

Step 2: Create a stack of nodes and visited array.

Step 3: Insert the root in the stack.

Step 4: Run a loop till the stack is not empty.

Step 5: Pop the element from the stack and print the element.

Step 6: For every adjacent and unvisited node of current node, mark the node and insert it in the
stack.

Step 7: Stop the execution.

423
Program:

// 10. Java Program to implement the DFS for a given graph


// DFS_Graph.java
import java.io.*;
import java.util.*;
public class DFS_Graph
{
final int TRUE = 1;
final int FALSE = 0;
final int MAX = 25;
int [][] G = new int [MAX][MAX];
int [] visited = new int [MAX];
int [] q = new int [MAX];
int n, v1, v2;
int front, rear;
DFS_Graph()
{
System.out.println("Enter the number of nodes");
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
for (int i=1;i<=n;i++)
visited[i] = FALSE;
for (v1=1;v1<=n;v1++)
{
for (v2=1;v2<=n;v2++)
G[v1][v2] = FALSE;
}
front = rear = -1;
}
void CreateGraph()
{
char ans;
System.out.println("Enter the edges with vertex no. starting from 1");
do
{
System.out.println("Enter the vertices v1 & v2:");
Scanner sc = new Scanner(System.in);
v1 = sc.nextInt();
v2 = sc.nextInt();
if (v1 > n || v2 > n)
System.out.println("Invalid Vertex Number");
else
{
G[v1][v2] = TRUE;
G[v2][v1] =TRUE;
}
424
System.out.println("Want to add more edges (y/n)?");
ans = sc.next().charAt(0);
}
while (ans == 'Y' || ans == 'y');
}
void Adjacency_Matrix()
{
System.out.println("Adjacency Matrix for the Graph is");
for (int v1=1;v1<=n;v1++)
{
for (int v2=1;v2<=n;v2++)
System.out.print(G[v1][v2] + " ");
System.out.println();
}
}
void dfs(int v)
{
int i;
System.out.println(v + " ");
visited[v] = TRUE;
for (i=1;i<=n;i++)
{
if (G[v][i] == TRUE && visited[i] == FALSE)
dfs(i);
}
}
public static void main(String args[])
{
System.out.println("Implementation of DFS for a given graph");
DFS_Graph g = new DFS_Graph();
g.CreateGraph();
g.Adjacency_Matrix();
System.out.println("Depth First Traversal for the above graph is");
g.dfs(1);
}
}
Output:
Implementation of DFS for a given graph
Enter the number of nodes
4
Enter the edges with vertex no. starting from 1
Enter the vertices v1 & v2:
1
2
425
Want to add more edges (y/n)?
y
Enter the vertices v1 & v2:
1
4
Want to add more edges (y/n)?
y
Enter the vertices v1 & v2:
3
4
Want to add more edges (y/n)?
n
Adjacency Matrix for the Graph is
0101
1000
0001
1010
Depth first traversal for the above graph is
1
2
4
3
Result:

Thus, the Java program to implement the Depth First Search for a graph has been executed
successfully.

*******************************************************************************

426

You might also like