You are on page 1of 170

ATME COLLEGE OF ENGINEERING

13th KM Stone, Bannur Road, Mysore - 560 028

DEPARTMENT OF COMPUTER SCIENCE AND ENGINEERING

(ACADEMIC YEAR 2019-20)

LESSON NOTES

SUBJECT: DATA STRUCTURES AND APPLICATIONS


SUB CODE: 18CS32
SEMESTER: III
DS(18CS32)

INSTITUTIONAL MISSION AND VISION


Objectives

 To provide quality education and groom top-notch professionals, entrepreneurs and


leaders for different fields of engineering, technology and management.
 To open a Training-R & D-Design-Consultancy cell in each department, gradually introduce
doctoral and postdoctoral programs, encourage basic & applied research in areas of social
relevance, and develop the institute as a center of excellence.
 To develop academic, professional and financial alliances with the industry as well as the
academia at national and transnational levels.
 To develop academic, professional and financial alliances with the industry as well as the
academia at national and transnational levels.
 To cultivate strong community relationships and involve the students and the staff in local
community service.
 To constantly enhance the value of the educational inputs with the participation of
students, faculty, parents and industry.

Vision

 Development of academically excellent, culturally vibrant, socially responsible and globally


competent human resources.

Mission

 To keep pace with advancements in knowledge and make the students competitive and
capable at the global level.
 To create an environment for the students to acquire the right physical, intellectual,
emotional and moral foundations and shine as torch bearers of tomorrow's society.
 To strive to attain ever-higher benchmarks of educational excellence.

Dept. of CSE, ATMECE Page 1


DS(18CS32)

Department of Computer Science & Engineering


Vision of the Department

 To develop highly talented individuals in Computer Science and Engineering to deal with
real world challenges in industry, education, research and society.
Mission of the Department

 To inculcate professional behaviour, strong ethical values, innovative research capabilities


and leadership abilities in the young minds & to provide a teaching environment that
emphasizes depth, originality and critical thinking.

 Motivate students to put their thoughts and ideas adoptable by industry or to pursue higher
studies leading to research

Program Educational Objectives (PEO'S):

1. Empower students with a strong basis in the mathematical, scientific and engineering
fundamentals to solve computational problems and to prepare them for employment,
higher learning and R&D.
2. Gain technical knowledge, skills and awareness of current technologies of computer
science engineering and to develop an ability to design and provide novel engineering
solutions for software/hardware problems through entrepreneurial skills.
3. Exposure to emerging technologies and work in teams on interdisciplinary projects with
effective communication skills and leadership qualities.
4. Ability to function ethically and responsibly in a rapidly changing environment by applying
innovative ideas in the latest technology, to become effective professionals in Computer
Science to bear a life-long career in related areas.

Program Specific Outcomes (PSOs)

1. Demonstrate understanding of the principles and working of the hardware and software
aspects of Embedded Systems.
Dept. of CSE, ATMECE Page 2
DS(18CS32)

2. Use professional Engineering practices, strategies and tactics for the development,
implementation and maintenance of software.
3. Provide effective and efficient real time solutions using acquired knowledge in various
domains.

DATA STRUCTURES AND APPLICATIONS


(Effective from the academic year 2018 -2019)
SEMESTER – III

Subject Code 18CS32 IA Marks 40


Number of Lecture Hours/Week 3:2:0 Exam Marks 60
Total Number of Lecture Hours 50 Exam Hours 03
CREDITS – 04
Course objectives: This course will enable students to
 Explain fundamentals of data structures and their applications essential for
programming/problem solving.
 Illustrate linear representation of data structures: Stack, Queues, Lists, Trees and
Graphs.
 Demonstrate sorting and searching algorithms. •
 Find suitable data structure during application development/Problem Solving.
Module – 1 Teaching
Hours
Introduction: Data Structures, Classifications (Primitive & Non Primitive), Data 10 Hours
structure Operations, Review of Arrays, Structures, Self-Referential Structures, and
Unions. Pointers and Dynamic Memory Allocation Functions. Representation of Linear
Arrays in Memory, Dynamically allocated arrays. Array Operations: Traversing,
inserting, deleting, searching, and sorting. Multidimensional Arrays, Polynomials and
Sparse Matrices. Strings: Basic Terminology, Storing, Operations and Pattern Matching
algorithms. Programming Examples. Textbook 1: Chapter 1: 1.2, Chapter 2: 2.2 - 2.7
Text Textbook 2: Chapter 1: 1.1 - 1.4, Chapter 3: 3.1 - 3.3, 3.5, 3.7, Ch apter 4: 4.1 - 4.9,
4.14 Reference 3: Chapter 1: 1.4 RBT: L1, L2, L3
Module – 2
Stacks: Definition, Stack Operations, Array Representation of Stacks, Stacks using 10 Hours
Dynamic Arrays, Stack Applications: Polish notation, Infix to postfix conversion,
evaluation of postfix expression. Recursion - Factorial, GCD, Fibonacci Sequence,
Tower of Hanoi, Ackerman's function. Queues: Definition, Array Representation, Queue
Operations, Circular Queues, Circular queues using Dynamic arrays, Dequeues, Priority
Queues, A Mazing Problem. Multiple Stacks and Queues. Programming Examples.
Textbook 1: Chapter 3: 3.1 -3.7 Textbook 2: Chapter 6: 6.1 -6.3, 6.5, 6.7-6.10, 6.12, 6.13
RBT: L1, L2, L3

Dept. of CSE, ATMECE Page 3


DS(18CS32)

Module – 3
Linked Lists: Definition, Representation of linked lists in Memory, Memory allocation; 10 Hours
Garbage Collection. Linked list operations: Traversing, Searching, Insertion, and
Deletion. Doubly Linked lists, Circular linked lists, and header linked lists. Linked
Stacks and Queues. Applications of Linked lists – Polynomials, Sparse matrix
representation. Programming Examples Textbook 1: Ch apter 4: 4.1 – 4.6, 4.8, Textbook
2: Ch apter 5: 5.1 – 5.10, RBT: L1, L2, L3
Module – 4
Trees: Terminology, Binary Trees, Properties of Binary trees, Array and linked 10 Hours
Representation of Binary Trees, Binary Tree Traversals - Inorder, postorder, preorder;
Additional Binary tree operations. Threaded binary trees, Binary Search Trees –
Definition, Insertion, Deletion, Traversal, Searching, Application of Trees-Evaluation of
Expression, Programming Examples
Textbook 1: Chapter 5: 5.1 –5.5, 5.7; Textbook 2: Chapter 7: 7.1 – 7.9 RBT: L1, L2, L3
Module – 5
Graphs: Definitions, Terminologies, Matrix and Adjacency List Representation Of 10 Hours
Graphs, Elementary Graph operations, Traversal methods: Breadth First Search and
Depth First Search. Sorting and Searching: Insertion Sort, Radix sort, Address
Calculation Sort. Hashing: Hash Table organizations, Hashing Functions, Static and
Dynamic Hashing. Files and Their Organization: Data Hierarchy, File Attributes, Text
Files and Binary Files, Basic File Operations, File Organizations and Indexing Textbook
1: Chapter 6 : 6.1 –6.2, Chapter 7:7.2, Chapter 8 : 8.1-8.3 Textbook 2: Chapter 8 : 8.1 –
8.7, Chapter 9 : 9.1-9.3, 9.7, 9.9 Reference 2: Chapter 16 : 16.1 - 16.7 RBT: L1, L2, L3
Course outcomes: The students should be able to:
 Use different types of data structures, operations and algorithms
 Apply searching and sorting operations on files
 Use stack, Queue, Lists, Trees and Graphs in problem solving
 Implement all data structures in a high-level language for problem solving.
Question paper pattern:
The question paper will have ten questions.
 Each full Question consisting of 20 marks
 There will be 2 full questions (with a maximum of four sub questions) from each module.
 Each full question will have sub questions covering all the topics under a module.
 The students will have to answer 5 full questions, selecting one full question from each
module
TextBooks:
1. Ellis Horowitz and Sartaj Sahni, Fundamentals of Data Structures in C, 2nd Ed, Universities Press,
2014.
2. Seymour Lipschutz, Data Structures Schaum's Outlines, Revised 1st Ed, McGraw Hill, 2014

Reference Books

Dept. of CSE, ATMECE Page 4


DS(18CS32)

1. Gilberg & Forouzan, Data Structures: A Pseudo-code approach with C, 2nd


Ed, Cengage Learning,2014.
2. 2. Reema Thareja, Data Structures using C, 3rd Ed, Oxford press, 2012.
3. 3. Jean-Paul Tremblay & Paul G. Sorenson, An Introduction to Data Structures
with Applications, 2 nd Ed, McGraw Hill, 2013
4. 4. A M Tenenbaum, Data Structures using C, PHI, 1989
5. 5. Robert Kruse, Data Structures and Program Design in C, 2nd Ed, PHI,
1996.

Dept. of CSE, ATMECE Page 5


DS(18CS32)

MODULE 1

STRUCTURE
1.0 Introduction
1.1 Objective
1.2 Introduction to Data Structures
1.3 Basic types of Data Structures
1.4 Data Structure Operations
1.5 Data Structures in C
1.5.1 Defining a structure
1.5.2 Accessing Structure Members
1.5.3 Arrays of structures
1.5.4 Pointers to Structures
1.6 Type definitions and structures
1.7 Unions
1.8 Self Referential structure
1.9 Arrays in C
1.10 Multi Dimensional Arrays
1.11 Operations on Arrays in C
1.12 Sparse Matrices
1.13 Polynomials
1.14 Dynamically allocated arrays
1.5 Strings
1.16 Dynamic Memory Management Functions

1.0 Introduction
This module gives introduction to data structures and classification of data structures.
Structures and unions are explained in detail. Arrays and operation on arrays are highlighted.
Sparse matrix and polynomials are discussed.

1.1 Objective
 Understand the concept of data structure operations, arrays, structures, unions.

 Understand the concept of strings and basic operation on strings.

Dept. of CSE, ATMECE Page 6


DS(18CS32)

1.2 Introduction to Data Structures


Data Structure is a way of collecting and organizing data in such a way that we can perform
operations on these data in an effective way. Data Structures is about rendering data elements in
terms of some relationship, for better organization and storage. For example, we have data
player's name "Virat" and age 26. Here "Virat" is of String data type whereas 26 is
of integer datatype.
We can organize this data as a record like Player record. Now we can collect and store player's
records in a file or database as a data structure. For example: "Dhoni" 30, "Gambhir" 31,
"Sehwag" 33
In simple language, Data Structures are structures programmed to store ordered data, so that
various operations can be performed on it easily.

1.3 Basic types of Data Structures


As we discussed above, anything that can store data can be called as a data structure, hence
Integer, Float, Boolean, Char etc, all are data structures. They are known as Primitive Data
Structures. Then we also have some complex Data Structures, which are used to store large and
connected data. They are known as Non – Primitive Data Structures. Some examples are:
 LinkedList
 Tree
 Graph
 Stack, Queueetc.
Non – Primitive data structures are further sub divided into linear and linear. All these data
structures allow us to perform different operations on data. We select these data structures based
on which type of operation is required. Let us look into these data structures in more details at a
later part.
Linear: A data structure is said to be linear if its elements form a sequence. The elements of
linear data structure represent by means of sequential memory locations. The other way is to
have the linear relationship between the elements represented by means of pointers or links.
Example: Array and Linked List.

Non-linear: A data structure is said to be non-linear if its elements show a hierarchical


relationship between each other. All elements assign the memory as random form and you can
Dept. of CSE, ATMECE Page 7
DS(18CS32)

fetch data elements through random access process.


Example: Trees and Graphs.

The diagram shown below would best explain it.

Figure 1.1 Classification of Data Structures

1.4 Data Structure Operations


Data are processed by means of certain operations which appearing in the data structure. Data
has situation on depends largely on the frequency with which specific operations are
performed. This section introduces the reader to some of the most frequently used of
theseoperations.
(1) Traversing: Accessing each record exactly once so that certain items in the record
maybe processed.
(2) Searching: Finding the location of a particular record with a given key value, or
findingthe location of all records which satisfy one or moreconditions.
(3) Inserting: Adding a new record to thestructure.
(4) Deleting: Removing the record from thestructure.
(5) Sorting: Managing the data or record in some logical order (Ascending or descending order).
(6) Merging: Combining the record in two different sorted files into a single sorted file.

Dept. of CSE, ATMECE Page 8


DS(18CS32)

1.5 Data Structures in C


1.5.1 Defining a structure
In the C language, structures are used to group together different types of variables under the
same name. To declare a structure, you must use the struct keyword. The struct keyword
defines a new data type, with more than one member. The syntax of the struct statement is as
follows − structstructure_name{
Date member 1;
Data member 2;
...
Data member n;
} [one or more structure tags];
The structure tag may be include before concluding the definition or can be included in the
main function and each data member is a normal variable definition, such as int i; or float f; or
any other valid variable definition. At the end of the structure's definition, a semicolon is
mandatory. Here is the way you would declare the Book structure −
struct Books {
char title[50];
charauthor[50];
char subject[100];
intbook_id;
} book;
1.5.2 Accessing Structure Members
To access any member of a structure, we use the member access operator (.). The member
access operator is coded as a period between the structure variable name and the structure
member that we wish to access. You would use the keyword struct to define variables of
structure type. The following example shows how to use a structure in a program −
#include <stdio.h>

#include<string.h>struc

t Books { char

Dept. of CSE, ATMECE Page 9


DS(18CS32)

title[50];

charauthor[50];

char subject[100];

intbook_id;

};

int main( ) {

structBooksBook1; /* Declare Book1 of typeBook*/

structBooksBook2; /* Declare Book2 of type Book*/

/* book 1 specification */

strcpy( Book1.title, "DataStructures");

strcpy( Book1.author, "Sahni"); strcpy(

Book1.subject, "DS"); Book1.book_id

=6495407;

/* book 2 specification */

strcpy( Book2.title, "Telecom Billing");

strcpy( Book2.author, "Shiney");

strcpy( Book2.subject, "Telecom Tutorial");

Book2.book_id = 6495700;

/* print Book1 info */

printf( "Book 1 title : %s\n", Book1.title); printf(

"Book 1 author : %s\n", Book1.author); printf(

"Book 1 subject : %s\n",Book1.subject);

printf( "Book 1 book_id : %d\n", Book1.book_id);

/* print Book2 info */

Dept. of CSE, ATMECE Page 10


DS(18CS32)

printf( "Book 2 title : %s\n", Book2.title); printf(

"Book 2 author : %s\n", Book2.author); printf(

"Book 2 subject : %s\n",Book2.subject);

printf( "Book 2 book_id : %d\n", Book2.book_id);

return 0;

When the above code is compiled and executed, it produces the following result −

Book 1 title : Data Structures

Book 1 author :Sahni

Book 1 subject : DS

Book 1 book_id : 6495407

Book 2 title : Telecom Billing

Book 2 author : Shiney

Book 2 subject : Telecom Tutorial

Book 2 book_id : 6495700

Structures as Function Arguments

You can pass a structure as a function argument in the same way as you pass any other variable or
pointer.

#include <stdio.h>

#include<string.h>str

uct Books { char

title[50];

charauthor[50];

char subject[100];

intbook_id;
Dept. of CSE, ATMECE Page 11
DS(18CS32)

};

/* function declaration */

voidprintBook( struct Books book ); int

main( )

structBooksBook1; /* Declare Book1 of

typeBook*/structBooksBook2; /* Declare Book2 of type

Book*/

/* book 1 specification */

strcpy( Book1.title, "DataStructures");

strcpy( Book1.author, "Sahni"); strcpy(

Book1.subject, "DS"); Book1.book_id

=6495407;

/* book 2 specification */

strcpy( Book2.title, "Telecom Billing");

strcpy( Book2.author, "Shiney");

strcpy( Book2.subject, "Telecom Tutorial");

Book2.book_id = 6495700;

/* print Book1 info */

printBook( Book1 );

/* Print Book2 info */

printBook( Book2 );

return 0;

}
Void printBook( struct Books book ) {
Dept. of CSE, ATMECE Page 12
DS(18CS32)

printf( "Book title : %s\n", book.title);

printf( "Book author : %s\n", book.author);

printf( "Book subject : %s\n",book.subject);

printf( "Book book_id : %d\n", book.book_id);

When the above code is compiled and executed, it produces the following result −

Book title : Data Structures

Book author :Sahni

Book subject : DS

Book book_id : 6495407

Book title : Telecom Billing

Book author : Shiney

Book subject : TelecomTutorial

Book book_id : 6495700

1.5.3 Arrays of structures

We can also declare an array of structures in order to store records of n number of entities.
Below program demonstrates the sameconcept.

#include <stdio.h>
#include
<conio.h>structBo
oks{
char *title;
char *author;
char *subject;
intbook_id;
};
Dept. of CSE, ATMECE Page 13
DS(18CS32)

void main()
{
struct Books book[3];
int i;
for(i=0;i<2;i++)
{
scanf("%s%s%s%d",book[i].title,book[i].author,book[i].subject,&book[i].book_id);
}
for(i=0;i<2;i++)
{
printf("%s\t%s\t%s\t%d\n",book[i].title,book[i].author,book[i].subject,book[i].book_id);
}
getch();
}
1.5.4 Pointers to Structures

You can define pointers to structures in the same way as you define pointer to any other variable

struct Books *struct_pointer;

Now, you can store the address of a structure variable in the above defined pointer variable. To
find the address of a structure variable, place the '&'; operator before the structure's name as
follows −

struct_pointer = &Book1;

To access the members of a structure using a pointer to that structure, you must use the →
operator as follows −

struct_pointer->title;

Let us re-write the above example using structure pointer.

#include <stdio.h>

#include<string.h>s

truct Books { char

title[50];

Dept. of CSE, ATMECE Page 14


DS(18CS32)

charauthor[50];

char subject[100];
intbook_id;

};

/* function declaration */

voidprintBook( struct Books *book ); int

main( )

structBooksBook1; /* Declare Book1 of

typeBook*/structBooksBook2; /* Declare Book2 of type

Book*/

/* book 1 specification */

strcpy( Book1.title, "DataStructures");

strcpy( Book1.author, "Sahni"); strcpy(

Book1.subject, "DS"); Book1.book_id

=6495407;

/* book 2 specification */

strcpy( Book2.title, "Telecom Billing");

strcpy( Book2.author, "Shiney");

strcpy( Book2.subject, "Telecom Tutorial");

Book2.book_id = 6495700;

/* print Book1 info by passing address of Book1 */

printBook(&Book1 );

/* print Book2 info by passing address of Book2 */

printBook(&Book2 );

Dept. of CSE, ATMECE Page 15


DS(18CS32)

return 0;

}
Void printBook( struct Books *book ) {
printf( "Book title : %s\n", book->title);

printf( "Book author : %s\n", book-

>author); printf( "Book subject :

%s\n",book->subject);

printf( "Book book_id : %d\n", book->book_id);

}
When the above code is compiled and executed, it produces the following result

− Book title : Data Structures

Book author

:Sahni Book

subject : DS

Book book_id : 6495407

Book title : Telecom

Billing Book author :

Shiney

Book subject : Telecom

Tutorial Book book_id :

6495700

1.6 Type definitions and structures


Type definitions make it possible to create your own variable types. In the following example we
will create a type definition called “intpointer” (a pointer to an integer):
#include<stdio.h>
typedefint
*int_ptr; intmain()
Dept. of CSE, ATMECE Page 16
DS(18CS32)

{
int_ptrmyvar; // create a variable of the typeint_ptr

return 0;
}
It is also possible to use type definitions with structures. The name of the type definition
of a structure is usually in uppercase letters. Take a look at the example:
#include<stdio.
h>struct
telephone
{
char
*name;
int
number;
};
Typedefstruct telephone
TELEPHONEintmain()
{
TELEPHONEindex; // create a variable of the typeint_ptr

index.name = "Jane Doe";


index.number = 12345;
printf("Name: %s\n",
index.name);
printf("Telephone number: %d\n",
index.number); return 0;
}
Note: The word struct is not needed before TELEPHONE index;

Dept. of CSE, ATMECE Page 17


DS(18CS32)

1.7 Unions
A union is like a structure in which all members are stored at the same address. Members of a
union can only be accessed one at a time. The union data type was invented to prevent memory
fragmentation. The union data type prevents fragmentation by creating a standard size for
certain data. Just like with structures, the members of unions can be accessed with the dot (.)
and arrow (->) operators. Take a look at this example:
#include<stdio.h>type
def union myunion
{
double
PI; int
B;
}MYUNION;
int main()
{
MYUNION
numbers;
numbers.PI = 3.14;
numbers.B = 50;
return 0;
}
If you would want to print the values of PI and B, only B value will be printed properly since
single memory is reserved to hold the data members’ value of union. Hence, 50 will be
displayed correctly.
Differences between structures and unions
Structure Union
Structure declaration starts with keyword Union declaration starts with keyword union
struct
Structure reserves memory for each data Union reserves memory i.e., equal to maximum
member separately data member size amongst all.

Dept. of CSE, ATMECE Page 18


DS(18CS32)

Any data member value can be accessed at Only one data member can be accessed at a
any time time
Ex: struct Book{ Ex: union Book{
intisbn; intisbn;
float price; float price;
char title[20]; char title[20];
}book; }book;
Total memory reserved will be Total memory reserved will be
sizeof(int)+sizeof(flaot)+(20*sizeof(char) Max(sizeof(int)+sizeof(flaot)+(20*sizeof(char))

1.8 Self Referential structure


A self referential structure is used to create data structures like linked lists, stacks, etc. A self-
referential structure is one of the data structures which refer to the pointer to (points) to another
structure of the same type. For example, a linked list is supposed to be a self-referential data
structure. The next node of a node is being pointed, which is of the same struct type. Following
is an example of this kind of structure:
Syntax:

struct struct_name
{
datatype datatypename;
struct_name *
pointer_name;
};
For example,

typedef struct listnode { int data;


structlistnode *next;
} linked_list;
In the above example, the listnode is a self-referential structure – because the *next is of
the type structlistnode.

Dept. of CSE, ATMECE Page 19


DS(18CS32)

Above syntactical representation can be pictorially presented as below:

data data data NULL

1.9 Arrays in C
In C programming, one of the frequently arising problems is to handle similar types of data. For
example, if the user wants to store marks of 100 students. This can be done by creating 100
variables individually but, this process is rather tedious and impracticable. This type of problem
can be handled in C programming using arrays.
An array is a sequence of data item of homogeneous value (same type).
Arrays are of two types: One-dimensional arrays, Multidimensional arrays
Declaration of one-dimensional array: data_typearray_name [array_size]; For
example: intage[5];

Here, the name of array is age. The size of array is 5, i.e., there are 5 items (elements) of
array age. All elements in an array are of the same type (int, in thiscase).
Array elements
Size of array defines the number of elements in an array. Each element of array can be accessed
and used by user according to the need of program.
For example: intage[5];

Figure 1.3
Note that, the first element is numbered 0 and so on. That means array indexing always starts
from 0 to n-1.
Here, the size of array is 5 times the size of int because there are 5 elements.
Suppose, the starting address of the array age[0] is 2120d and the size of int be 4 bytes. Then, the
next address (address of a[1]) will be 2124d, address of a[2] will be 2128d and so on.

Dept. of CSE, ATMECE Page 20


DS(18CS32)

Initialization of one-dimensional array Arrays


can be initialized at declaration time as:
intage[5]={2,4,34,3,4};

It is not necessary to define the size of arrays during initialization. Below instruction justifies
it.int age[]={2,4,34,3,4};
In this case, the compiler determines the size of array by calculating the number of elements of
an array.

Figure 1.4
Accessing array elements

In C programming, arrays can be accessed and treated like variables in C. For


example:
scanf("%d",&age[2]); // statement to insert value in the third position ofarrayage

scanf("%d",&age[i]); // statement to insert value in (i+1)th position


ofarrayageprintf("%d",age[0]); // statement to print first element of anarrayage
printf("%d",age[i]); // statement to print (i+1)th element of anarrayage Following
C program calculates the sum of marks of n students usingarrays

#include
<stdio.h>intmain(){
int marks[10],i,n,sum=0; printf("Enter
number of students: "); scanf("%d",&n);
for(i=0;i<n;++i){
printf("Enter marks of student%d: ",i+1);
scanf("%d",&marks[i]);
sum+=marks[i];

Dept. of CSE, ATMECE Page 21


DS(18CS32)

}
printf("Sum= %d",sum); return
0;
}
Output
Enter number of students: 3 Enter marks of student1: 12 Enter marks of student2: 31 Enter marks of
student3: 2

Sum=45

1.10 Multi Dimensional Arrays


C programming language allows programmer to create arrays of arrays known as
multidimensional arrays.
For example: float a[2][6];
Here, a is an array of two dimension, which is an example of multidimensional array.
For better understanding of multidimensional arrays, array elements of above example can be
thought of as below:

Figure 1.5

Initialization of Multidimensional Arrays


In C, multidimensional arrays can be initialized in different number of ways.
int c[2][3]={{1,3,0}, {-1,5,9}};
OR
int c[][3]={{1,3,0}, {-1,5,9}};
OR
int c[2][3]={1,3,0,-1,5,9};

Dept. of CSE, ATMECE Page 22


DS(18CS32)

Example of Multidimensional Array in C


C program to find sum of two matrix of order 2*2 using multidimensional arrays where,
elements of matrix are entered by user.

#include
<stdio.h>intmain()
{
float a[2][2], b[2][2], c[2][2];
inti,j;
printf("Enter the elements of 1st matrix\n");
/* Reading two dimensional Array with the help of two for loop. If there was an array of 'n'
dimension, 'n' numbers of loops are needed for inserting data to array.*/

for(i=0;i<2;++i)
for(j=0;j<2;++j)
{
printf("Enter a%d%d: ",i+1,j+1);
scanf("%f",&a[i][j]);
}
printf("Enter the elements of 2nd matrix\n");
for(i=0;i<2;++i)
for(j=0;j<2;++j)
{
printf("Enter b%d%d: ",i+1,j+1);
scanf("%f",&b[i][j]);
}
for(i=0;i<2;++i)
for(j=0;j<2;++j)
{
/* Writing the elements of multidimensional array using loop. */
c[i][j]=a[i][j]+b[i][j]; /* Sum of corresponding elements of two arrays. */
Dept. of CSE, ATMECE Page 23
DS(18CS32)

}
printf("\nSum Of Matrix:");
for(i=0;i<2;++i)
for(j=0;j<2;++j)
{
printf("%.1f\t",c[i][j]);
if(j==1) /* To display matrix sum inorder.
*/printf("\n");
}
return 0;
}
Output
Enter the elements of 1st matrix

Enter a11: 2
Enter a12: 0.5
Enter a21: -1.1
Enter a22: 2
Enter the elements of 2nd matrix
Enter b11: 0.2
Enter b12: 0
Enter b21: 0.23
Enter b22: 23
Sum of Matrix:
2.2 0.5
-0.9 25.0

1.11 Operations on Arrays in C


Various operations like create, display, insert, delete, search, merge, sort can be performed in
order to use arrays in programming. Below shown program performs all such operations on an
array in the form of a menu driven approach.

Dept. of CSE, ATMECE Page 24


DS(18CS32)

#include<stdio.h>

#include<stdlib.h>int

a[20],b[20],c[40];

intm,n,p,val,i,j,key,pos,temp;

/*Function

Prototype*/ void

create();

void display();

void insert();

void del(); void

search(); void

merge(); void

sort();

int main()

int choice; do{

printf("\n\n--------Menu-----------\n");

printf("1.Create\n");

printf("2.Display\n"); printf("3.Insert\n");

printf("4.Delete\n"); printf("5.Search\n");

Dept. of CSE, ATMECE Page 25


DS(18CS32)

printf("6.Sort\n"); printf("7.Merge\n");

printf("8.Exit\n");

printf("-----------------------");

printf("\nEnter your choice:\t");

scanf("%d",&choice); switch(choice)

case1: create();

break;

case 2:

display(); break;

case 3:

insert();

break;

case 4:

del();

break;

case 5:

search();

break;

case 6:
Dept. of CSE, ATMECE Page 26
DS(18CS32)

sort();

break;

case 7:

merge();

break;

case 8:

exit(0);

break;

default:

printf("\nInvalid choice:\n");

break;

}while(choice!=8);

return 0;

void create() //creating an array

printf("\nEnter the size of the array elements:\t");

scanf("%d",&n);

Dept. of CSE, ATMECE Page 27


DS(18CS32)

printf("\nEnter the elements for the array:\n");

for(i=0;i<n;i++)

scanf("%d",&a[i]);

}//end of create()

void display() //displaying an array elements

int i;

printf("\nThe array elements are:\n");

for(i=0;i<n;i++){

printf("%d\t",a[i]);

}//end of display()

void insert() //inserting an element in to an array

printf("\nEnter the position for the new element:\t");

scanf("%d",&pos);

Dept. of CSE, ATMECE Page 28


DS(18CS32)

printf("\nEnter the element to be inserted :\t");

scanf("%d",&val);

for(i=n-1;i>=pos;i--)

a[i+1]=a[i];

a[pos]=val;

n=n+1;

}//end of insert()

voiddel() //deleting an arrayelement

printf("\nEnter the position of the element to be deleted:\t");

scanf("%d",&pos);

val=a[pos];

for(i=pos;i<n-1;i++)

a[i]=a[i+1];

n=n-1;

Dept. of CSE, ATMECE Page 29


DS(18CS32)

printf("\nThe deleted element is =%d",val);

}//end of delete()

void search() //searching an array element

printf("\nEnter the element to be searched:\t");

scanf("%d",&key);

for(i=0;i<n;i++)

if(a[i]==key)

printf("\nThe element is present at position %d",i);

break;

if(i==n)

printf("\nThe search is unsuccessful");

Dept. of CSE, ATMECE Page 30


DS(18CS32)

}//end of serach()

voidsort() //sorting the arrayelements

for(i=0;i<n-1;i++)

for(j=0;j<n-1-i;j++)

if(a[j]>a[j+1])

temp=a[j];

a[j]=a[j+1];

a[j+1]=temp;

printf("\nAfter sorting the array elements are:\n");

display();

}//end of sort

Dept. of CSE, ATMECE Page 31


DS(18CS32)

voidmerge() //merging twoarrays

printf("\nEnter the size of the second array:\t");

scanf("%d",&m);

printf("\nEnter the elements for the second array:\n");

for(i=0;i<m;i++)

scanf("%d",&b[i]);

for(i=0,j=0;i<n;i++,j++)

c[j]=a[i];

for(i=0;i<m;i++,j++)

c[j]=b[i];

p=n+m;

Dept. of CSE, ATMECE Page 32


DS(18CS32)

printf("\nArray elements after

merging:\n"); for(i=0;i<p;i++)

printf("%d\t",c[i]);

}//end of merge

MLQs: - 1. Define Arrays. Explain different types of arrays

1.11.1 How a one dimensional array can be initialized? Explain withexample


1.11.2 How a two dimensional array can be initialized? Explain withexample
1.11.3 What are the various operations performed on arrays? Explain withalgorithms
1.11.4 Write a C program to demonstrate basic arrayoperations

1.12 Sparse Matrices


Matrices with a relatively high proportion of zero entries are called sparse matrices. Two
general types of n-square matrices, which occur in various applications, are pictured in below
given figure. The first matrix, where all entries above the main diagonal are zero or,
equivalently where nonzero entries can only occur on or below the main diagonal, is called a
(lower) triangular matrix. The second matrix where nonzero entries can only occur on the
diagonal or on elements immediately above or below the diagonal is called a tridiagonal matrix.

Dept. of CSE, ATMECE Page 33


DS(18CS32)

Figure 1.6 Sparse Matrix Types

Below shown C program accepts a matrix of order mXn and verifies whether it is a sparse
matrix or not.

#include <stdio.h>
void main ()
{
staticint m1[10][10];
inti,j,m,n;
int counter=0;
printf ("Enter the order of the matix\n");
scanf ("%d %d",&m,&n);
printf ("Enter the co-efficients of the matix\n");
for (i=0;i<m;++i)
{
for (j=0;j<n;++j)
{
scanf ("%d",&m1[i][j]);
if (m1[i][j]==0)
{
++counter;
}
}

}
if (counter>((m*n)/2))
{
printf ("The given matrix is sparse matrix \n");
}
else

Dept. of CSE, ATMECE Page 34


DS(18CS32)

printf
("The
given
matrix is
not a
sparse
matrix
\n");

Dept. of CSE, ATMECE Page 35


DS(18CS32)

printf ("There are %d number of zeros",counter);


} /* End of main()*/
/*----------------------------------------------
Output
Enter the order of the matix
22
Enter the co-efficients of the matix
12
34
The given matrix is not a sparse matrix
There are 0 number of zeros
Run 2
Enter the order of the matix
33
Enter the co-efficients of the matix
100
001
010
The given matrix is sparse matrix
There are 6 number of zeros

1.13 Polynomials
Polynomials come under the section Algebra in Mathematics. A polynomial is an expression of
finite length constructed from variables, constants and non-negative integer exponents. The
operations addition, subtraction and multiplication determine its entire structure. Polynomials are
used in a wide variety of problems where they are called as polynomial equations.
An example of a polynomial is 3x2+2x+7; here, the total number of terms is 3. The coefficients
of each term are 3, 2, 7 and degrees 2, 1, 0 respectively.
While adding two polynomials, following cases need to be considered.
1. When the degrees of corresponding terms of the two polynomials are same:
This is the normal case when corresponding coefficients of each term can be added directly. For

Dept. of CSE, ATMECE Page 36


DS(18CS32)

example, the sum of the polynomials


5x3+2x2+7

7x3+9x2+12
-------------------
12x3+11x2+19 is a simple addition where all the degrees of the corresponding terms are same.
2. When the degrees of corresponding terms of the polynomials aredifferent:
Here, the term with the larger degreepre-dominates.
9x4+5x3+ +2x
3x4+ +4x2+7x
------------------------
12x4+5x3+4x2+9x
Below shown C program accepts two polynomials and performs addition operation on them.

#include<stdio.h>
main()
{
int a[10], b[10], c[10],m,n,k,i,j,p,count=0;
clrscr();
printf("\n\tPolynomial Addition\n");
printf("\t===================\n");
printf("\n\tEnter the no. of terms of the polynomial:");

scanf("%d", &m);
printf("\n\tEnter the degrees and coefficients:"); for
(i=0;i<2*m;i++)
scanf("%d", &a[i]); printf("\n\tFirst
polynomial is:");
for(i=0;i<2*m;i=i+2)
{
printf("%dX^%d+",a[i],a[i+1]);
}

Dept. of CSE, ATMECE Page 37


DS(18CS32)

printf("\b ");
printf("\n\n\n\tEnter the no. of terms of 2nd polynomial:");
scanf("%d", &n);
printf("\n\tEnter the degrees and co-efficients:");
for(j=0;j<2*n;j++)
scanf("%d", &b[j]); printf("\n\tSecond
polynomial is:"); for(j=0;j<2*n;j=j+2)
{
printf("%dX^%d+",b[j],b[j+1]);
}
printf("\b ");
i=j=k=1;
while (m>0 && n>0)
{
if(a[i]==b[j])
{
c[k-1]=a[i-1]+b[j-1];
c[k]=a[i];
count+=2; m--;
n--;

i+=2;
j+=2;
}
else if(a[i]>b[j])
{
c[k-1]=a[i-1];
c[k]=a[i];
count+=2; m--;
i+=2;
}
Dept. of CSE, ATMECE Page 38
DS(18CS32)

else
{
c[k-1]=b[j-1];
c[k]=b[j];
count+=2; n--;
j+=2;
} k+=2;
}
while (m>0)
{
c[k-1]=a[i-1];
c[k+1]=a[i];
count+=2; k+=2;
i+=2; m--;
}
while (n>0)

{
c[k-1]=b[j-1];
c[k+1]=b[j];
count+=2;
k+=2;
j+=2;
n--;
}
printf("\n\n\n\n\tSum of the two polynomials is:");
for(k=0;k<count;k=k+2)
{
printf("%dX^%d+",c[k],c[k+1]);
}
printf("\b ");
Dept. of CSE, ATMECE Page 39
DS(18CS32)

return 0;
}
1.14 Dynamically allocated arrays
Usually array at the time of its declaration gets it predefined size. Bounding to this size,
programmers will have to find out solution for several problems. For example, if SIZE value is
100, the program can be used to sort a collection up to 100 numbers. If the user wishes to sort
more than 100 numbers, we have to change the definition of SIZE using some larger value and
recompile the program. It becomes little tedious for someone to rethink on this number. Hence
the concept, Dynamic Arrays.

Let us follow the below program to understand the concept of dynamically allocated arrays with
the help of Dynamic Memory Allocation functions (described in 1.14)

#include <stdio.h>
void main(void)

{
int i,*list,n,p;
printf("Enter array size\n");
scanf("%d",&n);

malloc(n, sizeof(int));
printf("Contents and address of Reserved memory blocks for the array\n");
for(i=0;i<n;i++)

printf("%d\t%u\n",*(list+i),&*(list+i));
printf("Enter array elements\n");
for(i=0;i<n;i++) scanf("%d",&*(list+i));
printf("Entered array elements\n");
for(i=0;i<n;i++) printf("%d\n",*(list+i));

printf("Enter the resize value\n");


scanf("%d",&p);

Dept. of CSE, ATMECE Page 40


DS(18CS32)

realloc(list,p * sizeof(int));
printf("Contents and address of Reserved memory blocks for the array\n");

for(i=0;i<p;i++)

printf("%d\t%u\n",*(list+i),&*(list+i));
printf("Enter the elements\n");
for(i=n;i<p;i++) scanf("%d",&*(list+i));
printf("Updated array:\n"); for(i=0;i<p;i++)
printf("%d\t%u\n",*(list+i),&*(list+i));
list=NULL;

free(list);

printf("Array Contents after deallocation...\n");


for(i=0;i<p;i++)

printf("%d\n",*(list+i));
}
malloc(n, sizeof(int)); allocates n blocks of memory locations to hold integer data.
realloc(list,p * sizeof(int)); resizes n to pwhere p>n and allocates p number of memory locations
without disturbing the contents of older locations. The above program displays the status of array
before and after memory allocation toit.

2D – Dynamically declared Arrays

#include <stdio.h>
#include
<stdlib.h>intmain()
{
int **p;
int m, n, i, j;
printf("Enter number of rows and columns: ");

Dept. of CSE, ATMECE Page 41


DS(18CS32)

scanf("%d%d", &m, &n);


/* Allocate memory */
p = (int *) malloc(sizeof(int *) * m); /* Row pointers */
for(i = 0; i < m; i++) {
p[i] = (int *) malloc(sizeof(int) * n); /* Row data */
}
/* Assign values to array elements and print them */
for(i = 0; i < m; i++)
{
for(j = 0; j < n; j++)
{
scanf("%d",&*(*p+i)+j);
// p[i][j] = (i * 10) + (j + 1);

}
}
for(i = 0; i < m; i++)
{
for(j = 0; j < n; j++)
{
printf("%d",*(*p+i)+j);
}
printf("\n");
}
/* Deallocate memory */ for(i
= 0; i < m; i++)
{
free(p[i]); /* Rows */
}
free(p); /* Row pointers */
printf("Memory contents of the array after deallocation...\n"); for(i
Dept. of CSE, ATMECE Page 42
DS(18CS32)

= 0; i < m; i++)
{
for(j = 0; j < n; j++)
{
printf("%d",*(*p+i)+j);
}
printf("\n");
}
return 0;
}

Applications of Arrays
1. Arrays are used in sorting and searching methods
2. Arrays are used to represent graphs in the form of matrix
3. Arrays can be used in CPU Scheduling
4. Arrays can be used to demonstrate Stack and Queue data structures

1.15 Strings
Strings are one-dimensional array of characters terminated by a null character '\0'. Thus a null-
terminated string contains the characters that comprise the string followed by a null. The
following declaration and initialization create a string consisting of the word "Hello". To hold
the null character at the end of the array, the size of the character array containing the string is
one more than the number of characters in the word "Hello."
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
If you follow the rule of array initialization then you can write the above statement as follows −
char greeting[] = "Hello";
Following is the memory presentation of the above defined string in C

Dept. of CSE, ATMECE Page 43


DS(18CS32)

Note: Actually, you do not place the null character at the end of a string constant. The C
compiler automatically places the '\0' at the end of the string when it initializes the array.

Let us try to print the above mentioned string :−


#include
<stdio.h>int main
()
{

char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};


printf("Greeting message: %s\n", greeting );
return 0;
}
When the above code is compiled and executed, it produces the following result :−
Greeting message: Hello
C supports a wide range of built in functions that manipulate null-terminated strings :−

strcpy(s1, s2):- Copies string s2 into string s1.

strcat(s1, s2):- Concatenates string s2 onto the end of string s1.

strlen(s1):- Returns the length of string s1.

strcmp(s1, s2):- Returns 0 if s1 and s2 are the same; less than 0 if s1<s2; greater
than 0 if s1>s2.

Dept. of CSE, ATMECE Page 44


DS(18CS32)

strchr(s1, ch); Returns a pointer to the first occurrence of character ch in string


s1

strstr(s1, s2); Returns a pointer to the first occurrence of string s2 in string s1.

The following C program implements some of the above mentioned functions.


#include <stdio.h>
#include <string.h>int
main () {
char str1[12] = "Hello"; char
str2[12] = "World"; char
str3[12];
intlen ;
/* copy str1 into str3 */
strcpy(str3, str1);
printf("strcpy( str3, str1) : %s\n", str3 );
/* concatenates str1 and str2 */

strcat( str1, str2);


printf("strcat( str1, str2): %s\n", str1 );
/* total lenghth of str1 after concatenation */
len = strlen(str1);
printf("strlen(str1) : %d\n", len );
return 0;
}
When the above code is compiled and executed, it produces the following result
− strcpy( str3, str1) :Hello
strcat( str1, str2):
HelloWorldstrlen(str1) :10

1.16 Dynamic Memory Management Functions


The exact size of an array is unknown until the compile time, i.e., time when a compiler
Dept. of CSE, ATMECE Page 45
DS(18CS32)

compiles code written in a programming language into an executable form. The size of array
you have declared initially can be sometimes insufficient and sometimes more than required.
Dynamic memory allocation allows a programmer to obtain more memory space, while
running or to release space when no space is required.
Although, C language inherently does not have any technique to allocate memory dynamically,
there are 4 library functions under "stdlib.h" for dynamic memory allocation.

malloc() Allocates requested size of bytes and returns a pointer to first byte of allocated space

Allocates space for array elements, initializes to zero and then returns a pointer to
calloc()
memory

free() De-allocate the previously allocated space

realloc() Change the size of previously allocated space


malloc(): The name malloc stands for "memory allocation". The function malloc()reserves a block
of memory of specified size and return a pointer of type void which can be casted into pointer of
any form.

Syntax of malloc():- ptr=(cast-type*)malloc(byte-size)

Here, ptr is pointer of cast-type. The malloc() function returns a pointer to an area of memory
with size of byte size. If the space is insufficient, allocation fails and returns NULL pointer.

ptr=(int*)malloc(100*sizeof(int));

This statement will allocate either 200 or 400 according to size of int 2 or 4 bytes respectively
and the pointer points to the address of first byte ofmemory.

calloc(): The name calloc stands for "contiguous allocation". The only difference between
malloc() and calloc() is that, malloc() allocates single block of memory whereas calloc() allocates
multiple blocks of memory each of same size and sets all bytes tozero.

Syntax of calloc()

ptr=(cast-type*)calloc(n,element-size);

This statement will allocate contiguous space in memory for an array of n elements. For
example:

ptr=(float*)calloc(25,sizeof(float));

Dept. of CSE, ATMECE Page 46


DS(18CS32)

This statement allocates contiguous space in memory for an array of 25 elements each of size of
float, i.e, 4 bytes.

realloc(): The C library function void *realloc(void *ptr, size_t size) attempts to resize the
memory block pointed to by ptr that was previously allocated with a call to malloc or calloc.

Declaration
Following is the declaration for realloc() function.

void *realloc(void *ptr, size_t size)

Parameters
 ptr -- This is the pointer to a memory block previously allocated with malloc, calloc or realloc
to be reallocated. If this is NULL, a new block is allocated and a pointer to it is returned by
thefunction.

 size -- This is the new size for the memory block, in bytes. If it is 0 and ptr points to an
existing block of memory, the memory block pointed by ptr is deallocated and a NULL
pointer isreturned.

This function returns a pointer to the newly allocated memory, or NULL if the request fails.

Example
The following example shows the usage of realloc() function.

#include <stdio.h>

#include
<stdlib.h>intmain()

char *str;

/* Initial memory allocation


*/ str = (char *) malloc(12);
strcpy(str, "vivekananda");

printf("String = %s, Address = %u\n", str, str);

Dept. of CSE, ATMECE Page 47


DS(18CS32)

/* Reallocating memory */
str = (char *) realloc(str, 25);
strcat(str, "swamy");

printf("String = %s, Address = %u\n", str, str);


free(str);

return(0);

Output

String = vivekananda, Address = 355090448

String = vivekanandaswamy, Address = 355090448

free(): Dynamically allocated memory with either calloc() or malloc() does not get return on its
own. The programmer must use free() explicitly to release space.

syntax of free( )

e.g.: free(ptr);

This statement causes the space in memory pointer by ptr to be de-allocated.

1.17 Assignment Questions


1. What do you mean by DMA? Explain various functions under it
2. Bring out the difference between malloc, calloc and realloc
3. Compare between static memory allocation and Dynamic memory allocation
4. Comment on library functions under <stdlib.h> for DMA
5. Define String. Explain how a string can be declared and initialized with an example
6. List different string manipulation functions. Explain them along with syntax
7. Illustrate string manipulation functions with examples
8. Define Array. Explain how one – dimensional arrays are declared and initialized with an example
9. Explain how one – dimensional arrays are declared and initialized with an example
10. Write a C program to perform basic operations on single dimensional array
11. Differentiate between array and a structure
12. Compare Single and Multi – Dimensional arrays
13. List some of the applications of arrays
14. What are polynomials? Brief it with an example
15. 2. Write a C program to add two polynomials

Dept. of CSE, ATMECE Page 48


DS(18CS32)

1.18 Outcome
 Apply the concepts of arrays, structures and unions wherever required.
 Identify the applications of different types of data structures

Dept. of CSE, ATMECE Page 49


DS(18CS32)

Module – II
STRUCTURE

2.0 Introduction
2.1 Objective
2.2 Stack
2.3 Operations on Stack
2.3.1 Stack Representation
2.3.2 Array representation of stack
2.4 Representing stack using dynamic arrays
2.5 Polish Expressions (PN)
2.6 Reverse Polish Expressions (RPN)
2.7 Infix to postfix conversion
2.8 Evaluation of Postfix Expression
2.9 Infix to prefix conversion
2.10 Recursion
2.11 Tower of Hanoi Problem
2.12 Ackerman’s Recursive Function
2.13 Dynamic Implementation of stack
2.14 Queues
2.15 Queue Variants: Circular Queue
2.16 Queue Variants: Priority Queue
2.17 Queue Variants: Double Ended (De-Queue)
2.18 Assignment Questions
2.19 Outcomes
2.0 Introduction
This module gives overview of stack, different stack representation. Different polish
notations are discussed. Methodology for infix to postfix conversion, evaluation of postfix
expression, and infix to prefix conversion is discussed in detail. The recursion is explained with
tower of Hanoi problem and Ackerman’s Recursive Function as examples. The concepts of
queues are highlighted.

2.1 Objective
 Understand the concepts of stack, queues.
 Understand the methodology of infix to postfix conversion, evaluation of postfix
expression, and infix to prefix conversion.
 Understand the usage of recursive functions.

Dept. of CSE, ATMECE Page 1


DS(18CS32)

2.2 Stack
A Stack is data structure in which addition of new element or deletion of existing element always
takes place at a same end. This end is known as the top of the stack. That means that it is
possible to remove elements from a stack in reverse order from the insertion of elements into the
stack.

One other way of describing the stack is as a last in, first out (LIFO) abstract data type and linear
data structure. Pictorial representation of the same is shown below

PUSH POP

40 TOP
[3]
30
[2]
20
[1]

[0] 10

Fig 2.1 Structure of Stack

2.3 Operations on Stack


The stack is basically associated with two operations PUSH and POP.
Push and pop are the operations that are provided for insertion of an element into the stack and
the removal of an element from the stack, respectively.
To perform these operations, a reference is used i.e., stack – top. In the above figure, elementary
operations like push and pop are performed. Also, the current position of stack – top after
performing the operation is shown.
2.3.1 Stack Representation
Stack can be represented using two ways: static representation that is using array concept and
dynamic representation that is using linked list with the help of dynamic memory allocation
concept (explained in the next module).
2.3.2 Array representation of stack:
int stack[SIZE]; stack [] is an array of integer type with a predefined size SIZE .
Implementation of basic functions goes as below:

Dept. of CSE, ATMECE Page 2


DS(18CS32)

Push Function in C
void push()
{
int n;
printf("\n Enter item in stack");
scanf("%d",&n);
if(top==size-1)
{
printf("\nStack is Full");
}
else
{
top=top+1;
stack[top]=n;
}
}
Pop Function in C
void pop()
{
int item;
if(top==-1)
{
printf("\n Stack is empty");
}
else
{
item=stack[top];
printf("\n item popped is=%d", item);
top--;
}
}

Dept. of CSE, ATMECE Page 3


DS(18CS32)

2.4 Representing stack using dynamic arrays

#include <stdio.h>
#include <stdlib.h>
struct node
{
int info;
struct node *ptr;
}*top,*top1,*temp;
void push(int data);
void pop();
void display();
void destroy();
void main()
{
int no, ch, e;
printf("\n 1 - Push");
printf("\n 2 - Pop");
printf("\n 3 - Exit");
printf("\n 4 - Dipslay");
printf("\n 5 - Destroy stack");
top=NULL;
while (1)
{
printf("\n Enter choice : ");
scanf("%d", &ch);
switch (ch)
{
case 1:
printf("Enter data : ");
scanf("%d", &no);
push(no);

Dept. of CSE, ATMECE Page 4


DS(18CS32)

break;
case 2:
pop();
break;
case 3:
exit(0);
case 4:
display();
break;
case 5:
destroy();
break;
default :
printf(" Wrong choice, Please enter correct choice ");
break;
}
}
}
void push(int data)
{
if (top == NULL)
{
top =(struct node *)malloc(1*sizeof(struct node));
top->ptr = NULL;
top->info = data;
}
else
{
temp =(struct node *)malloc(1*sizeof(struct node));
temp->ptr = top;
temp->info = data;

Dept. of CSE, ATMECE Page 5


DS(18CS32)

top = temp;
}
}
/* Display stack elements */
void display()
{
top1 = top;
if (top1 == NULL)
{
printf("Stack is empty");
return;
}
while (top1 != NULL)
{
printf("%d ", top1->info);
top1 = top1->ptr;
}
}
/* Pop Operation on stack */
void pop()
{
top1 = top;
if (top1 == NULL)
{
printf("\n Error : Trying to pop from empty stack");
return;
}
else
top1 = top1->ptr;
printf("\n Popped value : %d", top->info);
free(top);

Dept. of CSE, ATMECE Page 6


DS(18CS32)

top = top1;
}
void destroy()
{
top1 = top;
while (top1 != NULL)
{
top1 = top->ptr;
free(top);
top = top1;
top1 = top1->ptr;
}
free(top1);
top = NULL;
printf("\n All stack elements destroyed");
}

2.5 Polish Expressions (PN)

Polish notation (PN), also known as normal Polish notation (NPN), Polish prefix notation or
simply prefix notation is a form of notation for logic, arithmetic, and algebra. Its distinguishing
feature is that it places operators to the left of their operands

Infix Version PN Version

3 –2 -3 2

3 * 2+5 +* 3 25

(12 - 3 ) /3 / -12 3 3

Dept. of CSE, ATMECE Page 7


DS(18CS32)

2.6 Reverse Polish Expressions (RPN)

Reverse Polish Notation (RPN), sometimes referred to as postfix notation, is a way of writing
mathematical expressions where each operand is preceded by the two operators it applies to and
looks something like 2 5 3 + * instead of (5 + 3 ) * 2

Well, it turns out that it is easier/more efficient for computers to parse an RPN expression than
an infix one. In fact, if you look at the code underlying most calculators you'd find that most of
them take the infix expressions that we write and first convert them to postfix before evaluating
them. Meta calculator's graphing and scientific calculators both do exactly this.

Examples

Infix Version RPN Version

3-2 32-

3 * 2+5 532*+

(12 - 3 ) /3 12 3 - 3 /

So what is wrong with infix?


The big problem is that operators have properties such as precedence and associativity. This
makes working out with an infix expression actually makes harder than it should be.
For example, multiplication has a higher precedence or priority than addition and this means
that:
2+3*4; is not 2+3 all times 4 which it would be in a strict left to right reading. In fact the
expression is 3*4 plus 2 and you can see that evaluating an infix expression often involves
reordering the operators and their operands.
Then there arises a small matter of inserting brackets to make some infix expressions clear.
For example: (2+3)*(4+5) cannot be written without brackets because 2+3*4+5 means 3*4 plus
2 plus 5.
The order that you have to evaluate operators is something that takes a long time to learn.
Beginners of arithmetic may get wrong answers even when they do the actual operations
correctly and it gives rise to the need to remember mnemonics like BODMAS - Brackets Of
Division, Multiplication, Addition, Subtraction. Hence, postfix or RPN is proved efficient as far
as computer calculation is concerned.

Dept. of CSE, ATMECE Page 8


DS(18CS32)

Infix notation is easy to read for humans, whereas pre-/postfix notation is easier to parse for a
machine. The big advantage in pre-/postfix notation is that there never arise any questions like
operator precedence.
For example, consider the infix expression 1 # 2 $ 3. Now, we don't know what those operators
mean, so there are two possible corresponding postfix expressions: 1 2 # 3 $ and 1 2 3 $ #.
Without knowing the rules governing the use of these operators, the infix expression is
essentially worthless.
Or, to put it in more general terms: it is possible to restore the original (parse) tree from a pre-
/postfix expression without any additional knowledge, but the same isn't true for infix
expressions.

A typical Polish expression and an equivalent infix form

− × ÷ 15 − 7 + 1 1 3 + 2 + 1 1 =

− × ÷ 15 − 7 2 3+2+11=

− × ÷ 15 5 3+2+11=

−×3 3+2+11=

−9 +2+11=

−9 +22 =

−9 4 =

Answer is 5

An equivalent in-fix is as follows: ((15 ÷ (7 − (1 + 1))) × 3) − (2 + (1 + 1)) = 5

2.7 Infix to postfix conversion


Now that we have seen different forms of expression, let us try to convert an expression of one
form to another. We can manually convert the given expression.

A/B^C-D

Parse the expression from left to right. Since ^ has precedence than other operators in the
expression, consider its operands and convert it into immediate postfix form.

Now, the expression looks like

A/BC^-D, say BC^ as E1 => A/E1-D

Dept. of CSE, ATMECE Page 9


DS(18CS32)

Since, / has higher precedence, consider its operands and convert it into its immediate postfix
notation. i.e.,AE1/-D. Now say the converted portion as E2 and rewrite the expression

E2-D

Finally, it becomes E2D-. [Recall; E2 -> AE1/, & E1 -> BC^]

Now its time to substitute, AE1/D-

ABC^/D-

That’s it!!

Computer converts the same expression using stack and here comes one of the main applications
of stack. The below shown tabular conversion would best explain the overall process.

Current
Expression Stack Output Comment
Symbol

Initial
A/B^C-D NULL – Initially Stack is Empty
State

/B^C-D A NULL A Print Operand

B^C-D / / A Push Operator Onto Stack

^C-D B / AB Print Operand

Push Operator Onto Stack because Priority


C-D ^ /^ AB of ^ is greater than Current Topmost
Symbol of Stack i.e ‘/’

-D C /^ ABC Print Operand

Step 1: Now ‘^’ Has Higher Priority than


Incoming Operator So We have to Pop
D – / ABC^ Topmost element.
Step 2: Remove Topmost Operator From
Stack and Print it

Dept. of CSE, ATMECE Page 10


DS(18CS32)

Step 1: Now ‘/’ is topmost Element of


Stack Has Higher Priority than Incoming
Operator So We have to Pop Topmost
D – NULL ABC^/
Element again.
Step 2: Remove Topmost Operator From
Stack and Print it

Step 1: Now Stack Becomes Empty and


D – – ABC^/
We can Push Operand Onto Stack

NULL D – ABC^/D Print Operand

Expression Scanning Ends but we have


NULL NULL – ABC^/D- still one more element in stack so pop it
and display it

2.8 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. We have discussed infix to postfix conversion. In this post, evaluation of postfix
expressions is discussed.
Following is algorithm for evaluating postfix expressions.
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 a operator, pop operands for the operator from stack. Evaluate the
operator and push the result back to the stack
3) When the expression ends, the number in the stack is the final answer
Example:
Let the given expression be “2 3 1 * + 9 -“. We scan all elements one by one.

Dept. of CSE, ATMECE Page 11


DS(18CS32)

Try it yourself

1) Scan ‘2’, it’s a number, so push it to stack. Stack contains ‘2’


2) Scan ‘3’, again a number, push it to stack, stack now contains ‘2 3′ (from bottom to top)
3) Scan ‘1’, again a number, push it to stack, stack now contains ‘2 3 1′
4) Scan ‘*’, it’s an operator, pop two operands from stack, apply the * operator on operands, we
get 3*1 which results in 3. We push the result ‘3’ to stack. Stack now becomes ‘2 3′.
5) Scan ‘+’, it’s an operator, pop two operands from stack, apply the + operator on operands, we
get 3 + 2 which results in 5. We push the result ‘5’ to stack. Stack now becomes ‘5’.
6) Scan ‘9’, it’s a number, we push it to the stack. Stack now becomes ‘5 9′.
7) Scan ‘-‘, it’s an operator, pop two operands from stack, apply the – operator on operands, we
get 5 – 9 which results in -4. We push the result ‘-4′ to stack. Stack now becomes ‘-4′.
8) There are no more elements to scan, we return the top element from stack (which is the only
element left in stack).

2.9 Infix to prefix conversion


Now that we have seen different forms of expression, let us try to convert an expression of one
form to another. We can manually convert the given expression.
A/B^C-D
Parse the expression from left to right. Since ^ has precedence than other operators in the
expression, consider its operands and convert it into immediate postfix form.
Now, the expression looks like
A/^BC-D, say ^BC as E1 => A/E1-D
Since, / has higher precedence, consider its operands and convert it into its immediate postfix
notation. i.e., /AE1-D. Now say the converted portion as E2 and rewrite the expression

Dept. of CSE, ATMECE Page 12


DS(18CS32)

E2-D
Finally, it becomes - E2D. [Recall; E2 -> /AE1 , & E1 -> ^BC]
Now its time to substitute, AE1/D-
-/A^BCD

That’s it!!

2.10 Recursion
A function that calls itself is known as recursive function. And, this technique is
known as recursion.

How recursion works?


void recurse()
{
... .. ...
recurse();
... .. ...
}
int main()
{
... .. ...
recurse();
... .. ...
}

Dept. of CSE, ATMECE Page 13


DS(18CS32)

The recursion continues until some condition is met to prevent it. To prevent infinite
recursion, if...else statement (or similar approach) can be used where one branch
makes the recursive call and other doesn't.

An example program in C

#include <stdio.h>
int sum(int n);
int main()
{
int number, result;
printf("Enter a positive integer: ");
scanf("%d", &number);
result = sum(number);
printf("sum=%d", result);
}
int sum(int n)
{

Dept. of CSE, ATMECE Page 14


DS(18CS32)

if (n!=0)
return n + sum(n-1); // sum() function calls itself
else
return n;
}
Initially, the sum() is called from the main() function with number passed as an
argument.
Suppose the value of n is 3 init ially. During next function call, 2 is passed to
the sum() function. In next function call, 1 is passed to the function. This process
continues until n is equal to 0.
When n is equal to 0, there is no recursive call and the sum of integers is returned to
the main() function.

Dept. of CSE, ATMECE Page 15


DS(18CS32)

Advantages and Disadvantages of Recursion


Recursion makes program elegant and cleaner. All algorithms can be defined
recursively which makes it easier to visualize and prove.
If the speed of the program is vital then, you should avoid using recursion.
Recursions use more memory and are generally slo w.
C Program to find factorial of a given number using recursion

#include <stdio.h>

int factorial(int);

void main()

int result,num;

scanf("%d",&num);

result=factorial(num);

printf("%d",result);

int factorial(int ele)

if(ele==0)

return 1;

else

return (ele*factorial(ele-1));

Output

Enter a positive integer: 6

Factorial of 6 = 720

Dept. of CSE, ATMECE Page 16


DS(18CS32)

Suppose the user entered 6. Initially, the multiplyNumbers() is called from the main() function
with 6 passed as an argument. Then, 5 is passed to the multiplyNumbers() function from the
same function (recursive call). In each recursive call, the value of argument nis decreased by 1.
When the value of n is less than 1, there is no recursive call.

C Program to find GCD of Two Numbers using Recursion


#include <stdio.h>
int gcd(int, int);
int main()
{
int a,b,result;
printf("Enter two numbers\n");
scanf("%d%d",&a,&b);
result=gcd(a,b);
printf("GCD:%d\n",result);
}
int gcd(int a, int b)
{
int ans;
if(b<a && a%b==0)
return b;
else if(a<b)
return gcd(b,a);
else
{
ans=a%b;
return gcd(b,ans);
}
}
Output
Enter two positive integers: 366

Dept. of CSE, ATMECE Page 17


DS(18CS32)

60
G.C.D of 366 and 60 is 6.

C Program to generate Fibonacci Sequence using Recursion


#include<stdio.h>
int Fibonacci(int);
int main()
{
int n, i = 0, c;
scanf("%d",&n);
printf("Fibonacci series\n");
for ( c = 1 ; c <= n ; c++ )
{
printf("%d\n", Fibonacci(i));
i++;
}
return 0;
}
int Fibonacci(int n)
{
if ( n == 0 )
return 0;
else if ( n == 1 )
return 1;
else
return ( Fibonacci(n-1) + Fibonacci(n-2) );
}
Output
Enter the range of the Fibonacci series: 10
Fibonacci Series: 0 1 1 2 3 5 8 13 21 34 55 89

Dept. of CSE, ATMECE Page 18


DS(18CS32)

C Program to solve Towers of Hanoi problem using Recursion


#include <stdio.h>
void towers(int, char, char, char);
int main()
{
int num;

printf("Enter the number of disks : ");


scanf("%d", &num);
printf("The sequence of moves involved in the Tower of Hanoi are :\n");
towers(num, 'A', 'C', 'B');
return 0;
}
void towers(int num, char frompeg, char topeg, char auxpeg)
{
if (num == 1)
{
printf("\n Move disk 1 from peg %c to peg %c", frompeg, topeg);
return;
}
towers(num - 1, frompeg, auxpeg, topeg);
printf("\n Move disk %d from peg %c to peg %c", num, frompeg, topeg);
towers(num - 1, auxpeg, topeg, frompeg);
}

In the above program, towers (…) is the function that shows its execution in a recursive manner.

OK, now let us see the problem constraints of Tower of Hanoi and let us try to understand how it
can be addressed non-programmatically….

2.11 Problem: Move all the disks over to the rightmost tower, one at a time, so that they end up
in the original order on that tower. You may use the middle tower as temporary storage, but at no
time during the transfer should a larger disk be on top of a smaller one.

Dept. of CSE, ATMECE Page 19


DS(18CS32)

3
2
1

A: FROM B:Auxiliary C:TO

3
2
1

A: FROM B:Auxiliary C:TO

What you are observing is the problem (in the upper part) and its solution (in the lower part). If
we manually try to work it out keeping all the constraints in mind, the sequence of steps that one
would perform for 3 disks:

Move disk 1 from peg A to peg C


Move disk 2 from peg A to peg B
Move disk 1 from peg C to peg B
Move disk 3 from peg A to peg C
Move disk 1 from peg B to peg A
Move disk 2 from peg B to peg C
Move disk 1 from peg A to peg C

Dept. of CSE, ATMECE Page 20


DS(18CS32)

O K….. now that you got an idea of how this problem can be solved manually. But, we being
programmers should find out solution with computer as a tool. Let’s do that…..

For simplicity purpose, I have annotated disks as 1, 2, and 3, and stands as


A->From, B->Auxiliary and C->To

A small note to you all, it would be better if you take a copy (print or handwritten) of the
program shown above in your hand for analysis purpose otherwise you need to scroll several
times.

Yup… I am starting my explanation now… Please don’t get exhausted  


Firstly, the function call invokes the called function upon supplying the parameters (as shown
below)
towers(num, ‘A’,’C’,’B’);
void towers(int num, char frompeg, char topeg, char auxpeg) -------------------------------(1)
So, recursion makes use of stack, the stack content would be:

3, A, C, B Pushed to
Stack TOP
n f t a

Let us interpret it as follows:


num=3; frompeg=A; topeg=C; auxpeg=B;
After this, a condition is checked i.e., if(num==1) ? As of now, it’s not.
A recursive call takes place after that;
towers(num - 1, frompeg, auxpeg, topeg); i.e., num-1 = 2; frompeg=A; auxpeg=B; topeg=C;
(From the figure)
Now, these parameter values will be mapped to the parameters in (1)
Resulting into as below,
num = num-1 = 2; frompeg = frompeg = A; topeg = auxpeg = B; auxpeg = topeg = C;
Now the stack content would look like this

Dept. of CSE, ATMECE Page 21


DS(18CS32)

Pushed to
2, A, B, C Stack TOP
3, A, C, B
Not stack
contents n f t a

Once again, the condition is checked i.e., if(num==1) ? it’s not again.
One more time recursive call takes place:
towers(num - 1, frompeg, auxpeg, topeg); i.e., num-1 = 1; frompeg=A; auxpeg=C; topeg=B;
Now, these parameter values will be mapped to the parameters in (1)
Resulting into as below,
num = num-1 = 1; frompeg = frompeg = A; topeg = auxpeg = C; auxpeg = topeg = B;
Now the stack content would look like this

Pushed to
1, A, C, B Stack TOP
2, A, B, C

3, A, C, B

n f t a

This time the condition satisfies i.e., num =1 now. Top of the stack will be popped as recursion
gets a break. The statement inside will get executed and the following statement would get
printed

Move disk 1 from peg A to peg C ; num=1, frompeg = A, topeg = C

2, A, B, C Pushed to
Stack TOP
3, A, C, B

n f t a
Figure X

Dept. of CSE, ATMECE Page 22


DS(18CS32)

Here, the first recursive call gets totally a break.


Immediately, the next print statement gets executed by popping the stack contents.
Move disk 2 from peg A to peg B ; num=2, frompeg = A, topeg = B

Stack contents now,

Pushed to
3, A, C, B Stack TOP

n f t a

Now with the popped parameter values, second function call invokes the function.
towers(num - 1, auxpeg, topeg, frompeg); num-1 = 1; auxpeg = C; topeg = B; frompeg = A;
[referring to stack top of figure X ]
Now, the above parameter values will be mapped to the parameters in (1)
Resulting into as below,
num = num-1 = 1; frompeg = auxpeg = C; topeg = topeg = B; auxpeg = frompeg = A;

Now the stack content would look like this

1, C, B, A Pushed to
Stack TOP
3, A, C, B

n f t a
Since the condition if(num == 1) satisfies, the print statement would get executed by taking the
popped parameters.
Hence, we see
Move disk 1 from peg C to peg B; num=1, frompeg = C, topeg = B
Stack contents now,

Dept. of CSE, ATMECE Page 23


DS(18CS32)

Pushed to
3, A, C, B Stack TOP

n f t a
Figure Y

Finally, the stack top is popped and the parameters are used for executing the print statement
outside the condition. Stack is empty now.

n f t a

Move disk 3 from peg A to peg C; num=3, frompeg = A, topeg = C


Now, the second recursive function is processed with the popped values and the called function
is executed by pushing the contents onto the stack.
towers(num - 1, auxpeg, topeg, frompeg); num-1 = 2; auxpeg = B; topeg = C; frompeg = A;
[referring to stack top of figure Y ]

Now, the above parameter values will be mapped to the parameters in (1)
Resulting into as below,
num = num-1 = 2; frompeg = auxpeg = B; topeg = topeg = C; auxpeg = frompeg = A;
Now the stack content would look like this

Pushed to
2, B, C, A Stack TOP

n f t a

Dept. of CSE, ATMECE Page 24


DS(18CS32)

The condition will not hold because num = 2. Now, the first recursive call invokes the function
by supplying parameters onto the stack.
towers(num - 1, frompeg, auxpeg, topeg); i.e., num-1 = 1; frompeg=B; auxpeg=C; topeg=A;
Now, the above parameter values will be mapped to the parameters in (1)
Resulting into as below,
num = num-1 = 1; frompeg = frompeg = B; topeg = auxpeg = C; auxpeg = topeg = A;
Now the stack content would look like this

Pushed to
2, B, C, A Stack TOP

Gets n f t a
Popped 1, B, A, C

Figure Z

Move disk 1 from peg B to peg A; num=1, frompeg = B, topeg = A


Next, Using the stack top contents, print statement will be executed by popping out stack top.
[Refer to the above figure; minus popped contents].
Move disk 2 from peg B to peg C; num=2, frompeg = B, topeg = C
Stack becomes empty.
Now, the second recursive call will be invoked by supplying the popped contents as input.
towers(num - 1, auxpeg, topeg, frompeg); num-1 = 1; auxpeg = A; topeg = C; frompeg = B;
[referring to stack top of figure Z ]
Now, the above parameter values will be mapped to the parameters in (1)
Resulting into as below,
num = num-1 = 1; frompeg = auxpeg = A; topeg = topeg = C; auxpeg = frompeg = B;

The ‘if’ condition holds, hence print statement executes popping the stack.

Move disk 1 from peg A to peg C; num=1, frompeg = A, topeg = C

Finally, Stack goes empty. … I hope mind is not   


Hope my explanation has reached you and clarified few of your doubts in this regard.

Dept. of CSE, ATMECE Page 25


DS(18CS32)

2.12 Ackerman’s Recursive Function


In computability theory, the Ackermann function, named after Wilhelm Ackermann, is one of the
simplest and earliest-discovered examples of a total computable function that is not primitive
recursive. All primitive recursive functions are total and computable, but the Ackermann
function illustrates that not all total computable functions are primitive recursive.
The Ackermann function is defined for integer and by

C program to illustrate Ackermann’s Function


#include<stdio.h>
static int w=0;
int ackerman(int m,int n)
{
w=w+1;
if(m==0)
return n+1;
else if(m>0 && n==0)
return ackerman(m-1,1);
else if(m>0 && n>0)
return ackerman(m-1,ackerman(m,n-1));
}

Dept. of CSE, ATMECE Page 26


DS(18CS32)

int mainackerman()
{
int m,n;
scanf("%d %d",&m,&n);
printf("%d %d",ackerman(m,n),w);
return 0;
}

2.13 Dynamic Implementation of stack


#include <stdio.h>
#include <stdlib.h>
struct node
{
int info;
struct node *ptr;
}*top,*top1,*temp;
void push(int data);
void pop();
void display();
void destroy();
void main()
{
int no, ch, e;
printf("\n 1 - Push");
printf("\n 2 - Pop");
printf("\n 3 - Exit");
printf("\n 4 - Display");
printf("\n 5 - Destroy stack");
top=NULL;
while (1)
{
Dept. of CSE, ATMECE Page 27
DS(18CS32)

printf("\n Enter choice : ");


scanf("%d", &ch);
switch (ch)
{
case 1:
printf("Enter data : ");
scanf("%d", &no);
push(no);
break;
case 2:
pop();
break;
case 3:
exit(0);
case 4:
display();
break;
case 5:
destroy();
break;
default :
printf(" Wrong choice, Please enter correct choice ");
break;
}
}
}
void push(int data)
{
if (top == NULL)
{
top =(struct node *)malloc(1*sizeof(struct node));

Dept. of CSE, ATMECE Page 28


DS(18CS32)

top->ptr = NULL;
top->info = data;
}
else
{
temp =(struct node *)malloc(1*sizeof(struct node));
temp->ptr = top;
temp->info = data;
top = temp;
}
}
/* Display stack elements */
void display()
{
top1 = top;
if (top1 == NULL)
{
printf("Stack is empty");
return;
}
while (top1 != NULL)
{
printf("%d ", top1->info);
top1 = top1->ptr;
}
}
/* Pop Operation on stack */
void pop()
{
top1 = top;
if (top1 == NULL)

Dept. of CSE, ATMECE Page 29


DS(18CS32)

{
printf("\n Error : Trying to pop from empty stack");
return;
}
else
top1 = top1->ptr;
printf("\n Popped value : %d", top->info);
free(top);
top = top1;
}
void destroy()
{
top1 = top;
while (top1 != NULL)
{
top1 = top->ptr;
free(top);
top = top1;
top1 = top1->ptr;
}
free(top1);
top = NULL;
printf("\n All stack elements destroyed");
}

2.14 Queues
Queue is an abstract data structure, somewhat similar to Stack. In contrast to Stack, queue is
opened at both end. One end is always used to insert data, that end is referred to as REAR and
the operation is called enqueue and the other end referred to as FRONT, is used to remove data
and the operation is called dequeue. Queue follows First-In-First-Out methodology, i.e., the data
item stored first will be accessed first.

Dept. of CSE, ATMECE Page 30


DS(18CS32)

A real world example of queue can be a single-lane one-way road, where the vehicle enters first,
exits first. More real-world example can be seen as queues at ticket windows & bus-stops.

Logical representation of Queue data structure in computer’s memory

Queue [6]: 10 20 30 40 50

REAR
FRONT
The representation of queue is using arrays. Initially, FRONT & REAR indices are initialized to
-1. As elements are inserted, rear is incremented by 1 and as elements are deleted, front is
incremented by 1. Shaded cells in the above figure are empty. If an element is added, it sits in the
immediate next cell to rear and rear shifts right by one cell (i.e., rear++). Similarly if an element
is deleted, front shifts right by one cell (i.e. front++).

Applications of Queue

Queue, as the name suggests is used whenever we need to have any group of objects in an order
in which the first one coming in, also gets out first while the others wait for their turn, like in the
following scenarios:
1. Serving requests on a single shared resource, like a printer, CPU task scheduling etc.
2. In real life, Call Center phone systems will use Queues, to hold people calling them in an
order, until a service representative is free.
3. Handling of interrupts in real-time systems. The interrupts are handled in the same order as
they arrive, First come first served.
Array Implementation of a Queue
#include <stdio.h>
#define MAX 50
int queue_array[MAX];
int rear = - 1;
int front = - 1;

Dept. of CSE, ATMECE Page 31


DS(18CS32)

main()
{
int choice;
while (1)
{
printf("1.Insert element to queue \n");
printf("2.Delete element from queue \n");
printf("3.Display all elements of queue \n");
printf("4.Quit \n");
printf("Enter your choice : ");
scanf("%d", &choice);
switch (choice)
{
case 1:
insert();
break;
case 2:
delete();
break;
case 3:
display();
break;
case 4:
exit(1);
default:
printf("Wrong choice \n");
} /*End of switch*/
} /*End of while*/
} /*End of main()*/
insert()
{

Dept. of CSE, ATMECE Page 32


DS(18CS32)

int add_item;
if (rear == MAX - 1)
printf("Queue Overflow \n");
else
{
if (front == - 1)
/*If queue is initially empty */
front = 0;
printf("Inset the element in queue : ");
scanf("%d", &add_item);
rear = rear + 1;
queue_array[rear] = add_item;
}
} /*End of insert()*/

delete()
{
if (front == - 1 || front > rear)
{
printf("Queue Underflow \n");
return ;
}
else
{
printf("Element deleted from queue is : %d\n", queue_array[front]);
front = front + 1;
}
} /*End of delete() */
display()
{
int i;

Dept. of CSE, ATMECE Page 33


DS(18CS32)

if (front == - 1)
printf("Queue is empty \n");
else
{
printf("Queue is : \n");
for (i = front; i <= rear; i++)
printf("%d ", queue_array[i]);
printf("\n");
}
}

2.15 Queue Variants: Circular Queue


A circular queue is an abstract data type that contains a collection of data which allows addition
of data at the end of the queue and removal of data at the beginning of the queue. Circular queues
have a fixed size. Circular queue follows FIFO principle. Queue items are added at the rear end
and the items are deleted at front end of the circular queue.

In a standard queue data structure re-buffering problem occurs for each de queue operation. To
solve this problem by joining the front and rear ends of a queue to make the queue as a circular
queue.

1. Circular queue is a linear data structure. It follows FIFO principle.


2. In circular queue the last node is connected back to the first node to make a circle.
3. Circular linked list fallow the First In First Out principle
4. Elements are added at the rear end and the elements are deleted at front end of the
queue
5. Both the front and the rear pointers points to the beginning of the array.
6. It is also called as “Ring buffer”.

Dept. of CSE, ATMECE Page 34


DS(18CS32)

2.16 Queue Variants: Priority Queue


Priority Queue is more specialized data structure than Queue. Like ordinary queue, priority
queue has same method but with a major difference. In Priority queue items are ordered by key
value so that item with the lowest value of key is at front and item with the highest value of key
is at rear or vice versa. So we're assigned priority to item based on its key value. Lower the
value, higher the priority. Following are the principal methods of a Priority Queue.

Basic Operations
1. Insert / enqueue − add an item to the rear of the queue.

2. Remove / dequeue − remove an item from the front of the queue.

3. Peek − get the element at front of the queue.

4. isFull − check if queue is full.

5. isEmpty − check if queue is empty.

Priority Queue Representation

C program to demonstrate working of priority queue


#include <stdio.h>
#include <stdlib.h>
#define SIZE 5
int rear=-1,ch,front=-1,i,j,item,queue[SIZE],choice;
int Q_full();
int Q_Empty();
void insert();
void delet();
void display();
Dept. of CSE, ATMECE Page 35
DS(18CS32)

int main()
{
printf("1.Insert\n2.Delete\n3.Display\n4.Exit\n");
while(1)
{
printf("Enter your choice\n");
scanf("%d",&ch);
switch(ch)
{
case 1: if(Q_full())
printf("Priority Queue is Full\n");
else
insert();
break;
case 2: if(Q_Empty())
printf("Priority Queue Empty\n");
else
delet();
break;
case 3: if(Q_Empty())
printf("Priority Queue Empty\n");
else
display();
break;
case 4: exit(0);
}
}
}
void insert()
{
int ele;

Dept. of CSE, ATMECE Page 36


DS(18CS32)

printf("Enter the element\n");


scanf("%d",&item);
if(front==-1)
front++;
j=rear;
while(j>=0 && item<queue[j])
{
queue[j+1]=queue[j];
j--;
}
queue[j+1]=item;
rear++;
}
int Q_full()
{
if(rear==SIZE-1)
return 1;
else
return 0;
}
void delet()
{
printf("The item deleted is %d",queue[front]);
front++;
}
int Q_Empty()
{
if((front==-1)||(front>rear))
return 1;
else
return 0;

Dept. of CSE, ATMECE Page 37


DS(18CS32)

}
void display()
{
printf("Elements of Priority Queue...");
for(i=front;i<=rear;i++)
printf("%d\t",queue[i]);
}

2.17 Queue Variants: Double Ended (De-Queue)


A double-ended queue is an abstract data type similar to an simple queue, it allows you to insert
and delete from both sides means items can be added or deleted from the front or rear end.
Following reasons may help you understand why DE-Queue?
1. A nice application of the deque is storing a web browser's history. Recently visited URLs are
added to the front of the deque, and the URL at the back of the deque is removed after some
specified number of insertions at the front.
2. Another common application of the deque is storing a software application's list of undo
operations.
3. One example where a deque can be used is the A-Steal job scheduling algorithm.[5] This
algorithm implements task scheduling for several processors. A separate deque with threads
to be executed is maintained for each processor. To execute the next thread, the processor
gets the first element from the deque (using the "remove first element" deque operation). If
the current thread forks, it is put back to the front of the deque ("insert element at front") and
a new thread is executed. When one of the processors finishes execution of its own threads
(i.e. its deque is empty), it can "steal" a thread from another processor: it gets the last element
from the deque of another processor ("remove last element") and executes it
4. One of the best application of DE-Queue is in verifying whether given string is a
palindrome?

Dept. of CSE, ATMECE Page 38


DS(18CS32)

Rear Front

RADAR inserted R A D A R

Rear Front
Verification R A D A R

R (remove from rear) R (remove from front)


2.18 Assignment Questions
1. Convert A/B^C-D to postfix
2. Explain circular queue and its operations
3. Explain Tower of Hanoi problem with example
4. Explain dynamic implementation of stack
5. What is priority queue and double ended queue? Explain with example

2.19 Outcomes
 Know the methodology for infix to postfix conversion, evaluation of postfix expression,
and infix to prefix conversion.
 Identify the applications of stacks and queues.
 Familiarized with the usage of recursive function.

Dept. of CSE, ATMECE Page 39


DS(18CS32)

Module III
STRUCTURE
3.0 Introduction
3.1 Objective
3.2 Linked List
3.3 Linked list types
3.4 Linked List Representation
3.5 Operations on Linked Lists
3.5.1 Inserting a node
3.5.2 Deleting a node
3.6 Types of Linked Lists
3.7 Header Linked List
3.8 Doubly Linked list operations
3.9 Assignment Questions
3.10 Outcomes

3.0 Introduction
This module discusses the linked list data structures, operations on linked list. Different
types of liked list are explained in detail. The header linked list and its usage is highlighted. The
concept of doubly linked list is discussed.

3.1 Objective
 Understand the linked list data structures and its operation
 Understand the usage of header linked list and doubly linked list operations

Dept. of CSE, ATMECE Page 1


DS(18CS32)

3.2 Linked List

Linked list is the collection of inter connected nodes with a head node representing the first node
and a tail node representing the last node of it. A node can be viewed as a block consisting of
two major fields : a data field and a pointer field. The pointer field is used to interconnect nodes
of a list. Below diagram depicts the linked list setup.

Tail

NULL

3.3 Linked list types

There are few variants of linked lists. Below diagram shows a brief classification of Linked
Lists.
Linked List

Singly LL Circular LL Doubly LL

Singly Circular LL Doubly Circular LL

Regarding these variants of LL, explanations and examples are given in subsequent sections of
the notes.

3.4 Linked List Representation

A simple representation of singly linked list would look like the below:
struct node {
int data;
struct node *next; };

Dept. of CSE, ATMECE Page 2


DS(18CS32)

struct node *newnode;


With the above declaration we can create a node of the pattern below:
data *next

new node
Initially, the pointer field of the first node in singly linked list would contain NULL value.
Instruction that makes it is: newnode->next = NULL;
Note: Structure variables’ fields of self referential type are accessed through -> (arrow
operator)
Now, let us try to understand few conventions w.r.t linked lists. Consider below given list.

10 1008h 20 1016h 30 1024h 40 NULL

Head (1000h) (1008h) (1016h) tail (1024h)


In this list, head node contains data = 10 and tail node contains data = 40. This list has 4 nodes
that are interconnected. Head node is connected to the next node since the pointer value contains
the address of next node. Tail node is not linked to any node since its pointer value is NULL.
Struct node *head, *tail, *newnode; // variables declared of type struct node
head = (struct node *) malloc (1 * sizeof(struct node));
This instruction creates one node of type struct. Memory gets allocated using DMA function
malloc(). Created node in the above instruction is referred to as “head”. It can be any other name
as well.
Head->data = 10; // assigns head node’s data field with 10
head->next = NULL; //assigning pointer value to NULL

10 NULL
head; tail
tail = head; // assigning the reference of head to tail. This means both head and tail are referring
to the same node.
Now, let us add a new node to this list.
Newnode = (struct node *) malloc (1 * sizeof(struct
node)); newnode->data = 20; newnode->next =
NULL;

Dept. of CSE, ATMECE Page 3


DS(18CS32)

10 NULL 10 NULL

Head; tail new node

Dept. of CSE, ATMECE Page 4


DS(18CS32)

The above nodes can be connected using the following instructions:


head->next = newnode; // assigning head node’s pointer value with address of newnode

10 1008h 20 NULL

head; tail (1000h) newnode (1008h)


Now, if we execute the instruction, tail = newnode; tail & newnode both refer to the node with
value 20.
In this way, linked lists can be created.
3.5 Operations on Linked Lists
Major operations performed on linked lists are inserting a node, deleting a node, searching a
node and traversing the list to display all of its nodes.
3.5.1 Inserting a node: Node can be inserted at the beginning, at the end or anywhere in the linked
list
10 1008h 20 1016h 30 1024h 40 NULL
head (1000h) (1008h) (1016h) tail (1024h)
Consider the above list. Suppose we wish to insert a node at the beginning, following set of
instruction are to be executed.
newnode = (struct node *) malloc (1 * sizeof(struct node));
newnode->data = 50; newnode->next = head; 50 1000h
head = newnode;

10 1008h 20 1016h 30 1024h 40 NULL

(1000h) (1008h) (1016h) tail (1024h)

50 1000h
head; newnode
Suppose we wish to insert a node at the end, following set of instruction are to be executed.

10 1008h 20 1016h 30 1024h 40 1032h


head (1000h) (1008h) (1016h) tail (1024h)

newnode = (struct node *) malloc (1 * sizeof(struct node)); 80 NULL


newnode->data = 80; newnode->next = NULL; 80 NULL (1032h)

Dept. of CSE, ATMECE Page 5


DS(18CS32)

Take a temporary variable of type struct node, traverse the list until you reach the last node (i.e
tail )
while(temp->next !=NULL)
{
temp=temp->next;
}
temp->next = newnode;
tail = newnode;
Now let us see how to insert a node at a particular position in the list. For this, we need to ask
user to specify after which node in the list he would want to insert. Call it as “key” node. This
can be realized as below:
temp
10 1008h 20 1016h 30 1040h 40 1032h

head (1000h) (1008h) (1016h) tail (1024h)

80 NULL
Key = 30 100 1032h
Newnode (1040h) (1032h)
Take a temporary variable of type struct node, traverse the list until you reach the desired node
(i.e 30)
while(temp->data !=key)
100 NULL
{
temp=temp->next; newnode (1040h)
}
newnode->next = temp->next;
temp->next = newnode;
3.5.2 Deleting a node: A node in the list can be deleted using the standard function free ( ). Let us
see an example to understand delete operations on linked list.
10 1008h 20 1024h 30 NULL 40 NULL
head (1000h) temp2 (1008h) temp(1016h) tail (1024h)
Let us try to delete node with 30 data value.
Take two temporary variables and position them to key node and the previous node of it.

Dept. of CSE, ATMECE Page 6


DS(18CS32)

Now, key =30.


While(temp->data!=key)
{
temp=temp->next;
}
While(temp2->next!=key)
{
temp2=temp2->next;
}
temp2->next = temp->next;
temp->next = NULL;
free(temp);

Below C program creates a singly linked list and performs few operations like insert, delete,
display, search, insert and delete at specific positions in the list.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
struct node{
int data;
struct node *ptr;
};
struct node *head, *last,*temp, *temp2;
void create();
void delet();
void dele_spec();
void display();
void spec_ins();
int search(int);
int num,con=1,ch,key,f;
void main()

Dept. of CSE, ATMECE Page 7


DS(18CS32)

{
clrscr();
head=NULL;
printf("1.Create\n2.Delete\n3.Delete Specific\n4.Insert After Specific node\n5.Display\n6.
Search\n7.Exit\n");
while(1)
{
printf("Enter choice\n");
scanf("%d",&ch);
switch(ch)
{
case 1: printf("Enter number\n");
scanf("%d",&num);
create();
break;
case 2: delet();
break;
case 3: dele_spec();
break;
case 4: spec_ins();
break;
case 5: display();
break;
case 6: printf("Enter the node data to be searched\n");
scanf("%d",&key);
f=search(key);
if(f==1) printf("NODE FOUND\n");
else printf("NODE NOT FOUND\n");
break;
case 7: exit(0);
}

Dept. of CSE, ATMECE Page 8


DS(18CS32)

}
}
void create()
{
if(head==NULL)
{
head = (struct node*)malloc(1*sizeof(struct node));
head->data=num;
head->ptr=NULL;
last=head;
}
else
{
temp= (struct node*)malloc(1*sizeof(struct node));
temp->data=num;
last->ptr=temp;
temp->ptr=NULL;
last=temp;
}
}
void delet()
{
if(head==NULL)
{
printf("List is empty\n");
}
else
{
temp=head->ptr;
free(head);
head=temp;

Dept. of CSE, ATMECE Page 9


DS(18CS32)

}
}
void dele_spec()
{
int key;
printf("Enter the node to be deleted\n");
scanf("%d",&key);
temp=head;
temp2=head;
while(temp->data!=key)
{
temp=temp->ptr;
}
while(temp2->ptr!=temp)
{
temp2=temp2->ptr;
}
if(temp->ptr==NULL)
{
temp2->ptr=NULL;
free(temp);
last=temp2;
}
else
{
temp2->ptr=temp->ptr;
free(temp);
}
}
void spec_ins()
{

Dept. of CSE, ATMECE Page 10


DS(18CS32)

int key;
printf("Enter the node info next to which to be inserted\n");
scanf("%d",&key);
printf("Enter data for newnode\n");
scanf("%d",&num);
temp2= (struct node*)malloc(1*sizeof(struct node));
temp2->data=num;
temp=head;
while(temp->data!=key)
{
temp=temp->ptr;
}
temp2->ptr=temp->ptr;
temp->ptr=temp2;
}
void display()
{
if(head==NULL)
{
printf("List empty\n");
}
else
{
temp=head;
while(temp!=NULL)
{
printf("%d\t",temp->data);
temp=temp->ptr;
}
}
}

Dept. of CSE, ATMECE Page 11


DS(18CS32)

int search(int key)


{
int flag=0;
temp=head;
while(temp!=NULL)
{
if(temp->data==key)
{
flag=1;
return flag;
}
else
temp=temp->ptr;
}
return flag;
}
Advantages of Linked Lists
 They are a dynamic in nature which allocates the memory when required.
 Insertion and deletion operations can be easily implemented.
 Stacks and queues can be easily executed.
 Linked List reduces the access time.
Disadvantages of Linked Lists
 The memory is wasted as pointers require extra memory for storage.
 No element can be accessed randomly; it has to access each node sequentially.
 Reverse Traversing is difficult in linked list.

Applications of Linked Lists


 Linked lists are used to implement stacks, queues, graphs, etc.
 Linked lists let you insert elements at the beginning and end of the list.
 In Linked Lists we don’t need to know the size in advance.

Dept. of CSE, ATMECE Page 12


DS(18CS32)

Dept. of CSE, ATMECE Page 13


DS(18CS32)

3.6 Types of Linked Lists


Singly Linked List: Singly linked lists contain nodes which have a data part as well as an address
part i.e. next, which points to the next node in sequence of nodes. The operations we can perform
on singly linked lists are insertion, deletion and traversal.

Doubly Linked List : In a doubly linked list, each node contains two links the first link points to
the previous node and the next link points to the next node in the sequence.

Circular Linked List : In the circular linked list the last node of the list contains the address of
the first node and forms a circular chain.

3.7 Header Linked List

Dept. of CSE, ATMECE Page 14


DS(18CS32)

Header linked list is similar to Singly linked List but the difference is that in this type of list,
there exists a special node called “head”, which either contains information regarding total nodes
in the list or the address of the last node in the whole list.
C Program to implement header linked list is shown below
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
struct node{
int data;
struct node *ptr;
};
struct node *head, *last,*temp, *newnode;
void create();
void delet();
void display();
int num,count=0,ch;
void main()
{
clrscr();
head=NULL;
printf("1.Create\n2.Delete\n3.Display\n4.Exit\n");
while(1)
{
printf("Enter choice\n");
scanf("%d",&ch);
switch(ch)
{
case 1: if(head==NULL)
{
head = (struct node*)malloc(1*sizeof(struct node));
head->data=count;

Dept. of CSE, ATMECE Page 15


DS(18CS32)

head->ptr=NULL;
last=head;
}
printf("Enter number\n");
scanf("%d",&num);
create();
break;
case 2: delet();
break;
case 3: display();
break;
case 4: exit(0);
}
}
}
void create()
{
newnode = (struct node*)malloc(1*sizeof(struct node));
newnode->data=num;
newnode->ptr=NULL;
last->ptr=newnode;
last=newnode;
count++;
head->data=count;
}
void delet()
{
if(head->data==0)
{
printf("List is empty\n");
}

Dept. of CSE, ATMECE Page 16


DS(18CS32)

else
{
temp=head;
while(temp->ptr!=last)
{
temp=temp->ptr;
}
free(last);
last =temp;
last->ptr=NULL;
}
count--;
head->data=count;
}
void display()
{
if(head==NULL)
{
printf("List empty\n");
}
else
{
temp=head->ptr;
while(temp!=NULL)
{
printf("%d\t",temp->data);
temp=temp->ptr;
}
}
printf("\nHeader Information:%d\n",head->data);
}

Dept. of CSE, ATMECE Page 17


DS(18CS32)

Linked implementation of Stack


#include <stdio.h>
#include <stdlib.h>
struct Node
{
int Data;
struct Node *next;
}*top;
void popStack()
{
struct Node *temp, *var=top;
if(var==top)
{
top = top->next;
free(var);
}
else
printf("\nStack Empty");
}
void push(int value)
{
struct Node *temp;
temp=(struct Node *)malloc(sizeof(struct Node));
temp->Data=value;
if (top == NULL)
{
top=temp;
top->next=NULL;
}
else
{

Dept. of CSE, ATMECE Page 18


DS(18CS32)

temp->next=top;
top=temp;
}
}
void display()
{
struct Node *var=top;
if(var!=NULL)
{
printf("\nElements are as:\n");
while(var!=NULL)
{
printf("\t%d\n",var->Data);
var=var->next;
}
printf("\n");
}
else
printf("\nStack is Empty");
}
int main(int argc, char *argv[])
{
int i=0;
top=NULL;
printf(" \n1. Push to stack");
printf(" \n2. Pop from Stack");
printf(" \n3. Display data of Stack");
printf(" \n4. Exit\n");
while(1)
{
printf(" \nChoose Option: ");

Dept. of CSE, ATMECE Page 19


DS(18CS32)

scanf("%d",&i);
switch(i)
{
case 1:
{
int value;
printf("\nEnter a valueber to push into Stack: ");
scanf("%d",&value);
push(value);
display();
break;
}
case 2:
{
popStack();
display();
break;
}
case 3:
{
display();
break;
}
case 4:
{
struct Node *temp;
while(top!=NULL)
{
temp = top->next;
free(top);
top=temp;

Dept. of CSE, ATMECE Page 20


DS(18CS32)

}
exit(0);
}
default:
{
printf("\nwrong choice for operation");
}
}
}
}
Merging of two lists
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *next;
};
void insert_list1();
void insert_list2();
void display();
void merge_list();
struct node *list1, *list2,*list3,*temp1,*temp2,*temp3,*temp4;
void main()
{
int ch;
clrscr();
printf("1 for insert in first linklist\n");
printf("2 for insert in second linklist\n");
printf("3 for display first & second linklist\n");

Dept. of CSE, ATMECE Page 21


DS(18CS32)

printf("4 for merge linklist\n");


printf("5 for exit\n");
while(1)
{
printf("\nEnter ur choice:");
scanf("%d",&ch);
switch(ch)
{
case 1: insert_list1();
break;
case 2: insert_list2();
break;
case 3: display();
break;
case 4: merge_list();
break;
case 5: exit(0);
}
}
}

void merge_list()
{
temp1=list1;
temp2=list2;
while(temp1!=NULL || temp2!=NULL)
{
temp3=(struct node*)malloc(1*sizeof(struct node));
if(list3==NULL)
{
list3=temp3;

Dept. of CSE, ATMECE Page 22


DS(18CS32)

temp4=temp3;
}
if(temp1->data<temp2->data)
{
temp3->data=temp1->data;
temp4->next=temp3;
temp4=temp3;
temp1=temp1->next;
}
else
{
temp3->data=temp2->data;
temp4->next=temp3;
temp4=temp3;
temp2=temp2->next;
}
if(temp2==NULL)
{
while(temp1!=NULL)
{
temp3=(struct node*)malloc(1*sizeof(struct node));
temp3->data=temp1->data;
temp4->next=temp3;
temp4=temp3;
temp1=temp1->next;
}
break;
}
if(temp1==NULL)
{
while(temp2!=NULL)

Dept. of CSE, ATMECE Page 23


DS(18CS32)

{
temp3=(struct node*)malloc(1*sizeof(struct node));
temp3->data=temp2->data;
temp4->next=temp3;
temp4=temp3;
temp2=temp2->next;
}
break;
}
}
temp3->next=NULL;
}

void insert_list1()
{
struct node *new;
if(list1==NULL)
{
list1=(struct node *)malloc(sizeof(struct node));
printf("Enter the info");
scanf("%d",&list1->data);
list1->next=NULL;
temp1=list1;
}
else
{
new=(struct node *)malloc(sizeof(struct node));
printf("Enter the info");
scanf("%d",&new->data);
new->next=NULL;
temp1->next=new;

Dept. of CSE, ATMECE Page 24


DS(18CS32)

temp1=temp1->next;
}
}

void insert_list2()
{
struct node *new;
if(list2==NULL)
{
list2=(struct node *)malloc(sizeof(struct node));
printf("Enter the info");
scanf("%d",&list2->data);
list2->next=NULL;
temp2=list2;
}
else
{
new=(struct node *)malloc(sizeof(struct node));
printf("Enter the info");
scanf("%d",&new->data);
new->next=NULL;
temp2->next=new;
temp2=temp2->next;
}
}

void display()
{
temp1=list1;
temp2=list2;
printf("\nThe Information of First linklist:");

Dept. of CSE, ATMECE Page 25


DS(18CS32)

while(temp1!=NULL)
{
printf("%d ",temp1->data);
temp1=temp1->next;
}
printf("\nThe Information of Second linklist:");
while(temp2!=NULL)
{
printf("%d ",temp2->data);
temp2=temp2->next;
}
temp3=list3;
printf("\nMerged List:");
while(temp3!=NULL)
{
printf("%d ",temp3->data);
temp3=temp3->next;
}
}
Reversing a Singly Linked List
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *next;
};
void insert_list();
void display();
void revers();

Dept. of CSE, ATMECE Page 26


DS(18CS32)

struct node *head,*tail,*temp,*temp1;


void main()
{
int ch;
clrscr();
printf("1 insert in list\n");
printf("2 Reverse and display list\n");
printf("3.Exit\n");
while(1)
{
printf("\nEnter ur choice:");
scanf("%d",&ch);
switch(ch)
{
case 1: insert_list();
break;
case 2: revers();
break;
case 3: exit(0);
}
}
}
void revers()
{
temp=tail;
temp1=head;
while(temp!=head)
{
temp1=head;
while(temp1->next!=temp)
{

Dept. of CSE, ATMECE Page 27


DS(18CS32)

temp1=temp1->next;
}
temp->next=temp1;
temp=temp1;
}
temp=tail;
head->next=NULL;
printf("Reversed list: ");
while(temp!=NULL)
{
printf("%d ",temp->data);
temp=temp->next;
}
}
void insert_list()
{
struct node *new;
if(head==NULL)
{
head=(struct node *)malloc(sizeof(struct node));
printf("Enter the info");
scanf("%d",&head->data);
head->next=NULL;
tail=temp=head;

}
else
{
new=(struct node *)malloc(sizeof(struct node));
printf("Enter the info");
scanf("%d",&new->data);

Dept. of CSE, ATMECE Page 28


DS(18CS32)

new->next=NULL;
temp->next=new;
temp=temp->next;
tail=temp;
}
temp1=head;
printf("Created list: ");
while(temp1!=NULL)
{
printf("%d ",temp1->data);
temp1=temp1->next;
}
}
Singly Circular Linked List Operations
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
struct node{
int data;
struct node *ptr;
};
struct node *newnode, *front,*rear, *temp;

void create();
void display();
void delet();
int num,ch;
void main()
{
front=rear=NULL;
while(1)

Dept. of CSE, ATMECE Page 29


DS(18CS32)

{
printf("Enter choice\n");
scanf("%d",&ch);
switch(ch)
{
case 1: printf("Enter number\n");
scanf("%d",&num);
create();
break;
case 2: delet();
break;
case 3: display();
break;
case 4: exit(0);

}
}
}
void create()
{
newnode = (struct node*)malloc(1*sizeof(struct node));
newnode->data=num;
if(rear==NULL)
front=rear=newnode;
else
{
rear->ptr=newnode;
rear=newnode;
}
rear->ptr=front;
}

Dept. of CSE, ATMECE Page 30


DS(18CS32)

void delet()
{
if(front==NULL)
printf("List is empty\n");
else if(front==rear)
{
printf("Element deleted is %d",front->data);
front=NULL;
}
else
{
temp=front;
printf("Deleted element is %d",temp->data);
temp=temp->ptr;
free(front);
front=temp;
rear->ptr=front;
}
}
void display()
{
if(front==NULL)
{
printf("List empty\n");
}
else
{
temp=front;
while(temp!=rear)
{

Dept. of CSE, ATMECE Page 31


DS(18CS32)

printf("%d\t",temp->data);
temp=temp->ptr;
}
}
printf("%d\n",temp->data);
}
Adding and evaluating Polynomials using Circular Linked List
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <math.h>
struct node{
int coeff;
int expo;
struct node *ptr;
};
struct node *head1,*head2,*head3, *temp,*temp1,*temp2,*temp3,*list1,*list2,*list3;
struct node *dummy1,*dummy2;
void create_poly1(int , int);
void create_poly2(int , int);
void display();
void add_poly();
void eval_poly(int );
int n,ch;
int c,e,i;
void main()
{
int x;
list1=list2=NULL;
printf("1.Create first polynomial\n2.Create Second Polynomial\n3.Display both the
polynomials\n");

Dept. of CSE, ATMECE Page 32


DS(18CS32)

printf("4.Add Polynomials\n5.Evaluate a Polynomial\n6.Exit\n");


while(1)
{
printf("Enter choice\n");
scanf("%d",&ch);
switch(ch)
{
case 1: printf("Enter the number of terms\n");
scanf("%d",&n);
printf("Enter coefficient & power of each term\n");
for(i=0;i<n;i++)
{
scanf("%d%d",&c,&e);
create_poly1(c,e);
}
break;
case 2: printf("Enter the number of terms\n");
scanf("%d",&n);
printf("Enter coefficient & power of each term\n");
for(i=0;i<n;i++)
{
scanf("%d%d",&c,&e);
create_poly2(c,e);
}
break;
case 3: display();
break;
case 4: add_poly();
break;
case 5:printf("Enter the value for x\n");
scanf("%d",&x);

Dept. of CSE, ATMECE Page 33


DS(18CS32)

eval_poly(x);
break;
case 6:exit(0);
}
}
}
void create_poly1(int c, int e)
{
dummy1=(struct node*)malloc(1*sizeof(struct node));
dummy1->coeff=0;
dummy1->expo=0;
dummy1->ptr=list1;
if(list1==NULL)
{
list1=(struct node*)malloc(1*sizeof(struct node));
list1->coeff=c;
list1->expo=e;
list1->ptr=list1;
head1=list1;
head1->ptr=dummy1;
}
else
{
temp=(struct node*)malloc(1*sizeof(struct node));
temp->coeff=c;
temp->expo=e;
head1->ptr=temp;
temp->ptr=dummy1;
head1=temp;

Dept. of CSE, ATMECE Page 34


DS(18CS32)

void create_poly2(int c, int e)


{
dummy2=(struct node*)malloc(1*sizeof(struct node));
dummy2->coeff=0;
dummy2->expo=0;
dummy2->ptr=list2;
if(list2==NULL)
{
list2=(struct node*)malloc(1*sizeof(struct node));
list2->coeff=c;
list2->expo=e;
list2->ptr=list2;
head2=list2;
head2->ptr=dummy2;
}
else
{
temp=(struct node*)malloc(1*sizeof(struct node));
temp->coeff=c;
temp->expo=e;
head2->ptr=temp;
temp->ptr=dummy2;
head2=temp;
}
}
void add_poly()
{
temp1=list1;
temp2=list2;

Dept. of CSE, ATMECE Page 35


DS(18CS32)

while((temp1!=dummy1)&&(temp2!=dummy2))
{
temp=(struct node*)malloc(1*sizeof(struct node));
if(list3==NULL)
{
list3=temp;
head3=list3;
}
if(temp1->expo==temp2->expo)
{
temp->coeff=temp1->coeff+temp2->coeff;
temp->expo=temp1->expo;
temp->ptr=list3;
head3->ptr=temp;
head3=temp;
temp1=temp1->ptr;
temp2=temp2->ptr;
}
else if(temp1->expo>temp2->expo)
{
temp->coeff=temp1->coeff;
temp->expo=temp1->expo;
temp->ptr=list3;
head3->ptr=temp;
head3=temp;
temp1=temp1->ptr;
}
else
{
temp->coeff=temp2->coeff;

Dept. of CSE, ATMECE Page 36


DS(18CS32)

temp->expo=temp2->expo;
temp->ptr=list3;
head3->ptr=temp;
head3=temp;
temp2=temp2->ptr;
}
}
if(temp1==dummy1)
{
while(temp2!=dummy2)
{
temp=(struct node*)malloc(1*sizeof(struct node));
temp->coeff=temp2->coeff;
temp->expo=temp2->expo;
temp->ptr=list3;
head3->ptr=temp;
head3=temp;
temp2=temp2->ptr;
}
}
if(temp2==dummy2)
{
while(temp1!=dummy1)
{
temp=(struct node*)malloc(1*sizeof(struct node));
temp->coeff=temp1->coeff;
temp->expo=temp1->expo;
temp->ptr=list3;
head3->ptr=temp;
head3=temp;
temp1=temp1->ptr;

Dept. of CSE, ATMECE Page 37


DS(18CS32)

}
}
}

void display()
{
temp1=list1;
temp2=list2;
temp3=list3;
printf("\nPOLYNOMIAL 1:");
while(temp1!=dummy1)
{
printf("%dX^%d+",temp1->coeff,temp1->expo);
temp1=temp1->ptr;
}
printf("\b ");
printf("\nPOLYNOMIAL 2:");
while(temp2!=dummy2)
{
printf("%dX^%d+",temp2->coeff,temp2->expo);
temp2=temp2->ptr;
}
printf("\b ");
printf("\n\nSUM OF POLYNOMIALS:\n");
while(temp3->ptr!=list3)
{
printf("%dX^%d+",temp3->coeff,temp3->expo);
temp3=temp3->ptr;
}
printf("%dX^%d\n",temp3->coeff,temp3->expo);

Dept. of CSE, ATMECE Page 38


DS(18CS32)

void eval_poly(int x)
{
int result=0;
temp1=list1;
temp2=list2;
while(temp1!=dummy1)
{
result+=(temp1->coeff)*pow(x,temp1->expo);
temp1=temp1->ptr;
}
printf("Polynomial 1 Evaluation:%d\n",result);
result=0;
while(temp2!=dummy2)
{
result+=(temp2->coeff)*pow(x,temp2->expo);
temp2=temp2->ptr;
}
printf("Polynomial 2 Evaluation:%d\n",result);
}
3.8 Doubly Linked list operations
Below shown C program demonstrates basic operations on Doubly Linked List
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int count=0;
struct stud
{
long long int ph;
int sem;

Dept. of CSE, ATMECE Page 39


DS(18CS32)

char name[15],usn[15],brnch[8];
struct stud *next;
}*head=NULL,*tail=NULL,*temp=NULL,*temp1;
void create(long long int n,int s,char na[20],char u[15],char b[5])
{
if(head==NULL)
{
head=(struct stud*)malloc(1*sizeof(struct stud));
head->ph=n;
head->sem=s;
strcpy(head->name,na);
strcpy(head->usn,u);
strcpy(head->brnch,b);
head->next=NULL;
tail=head;
count++;
}
else
{
temp=(struct stud*)malloc(1*sizeof(struct stud));
temp->ph=n;
temp->sem=s;
strcpy(temp->name,na);
strcpy(temp->usn,u);
strcpy(temp->brnch,b);
temp->next=NULL;
tail->next=temp;
tail=temp;
count++;
}
}

Dept. of CSE, ATMECE Page 40


DS(18CS32)

void display()
{
temp1=head;
if(temp1==NULL)
{
printf("\nlist is empty\n");
}
else
{
printf("student details are as follows:\n");
while(temp1!=NULL)
{
printf("-----------------------\n");
printf("NAME:%s\nUSN:%s\nBRANCH:%s\nSEM:%d\nPHONE NO.:%lld\n",temp1-
>name,temp1->usn,temp1->brnch,temp1->sem,temp1->ph);
printf("-----------------------\n");
temp1=temp1->next;
}
printf("no. of nodes=%d\n",count);
}
}
void insert_head(long long int n,int s,char na[15],char u[15],char b[8])
{
temp=(struct stud*)malloc(1*sizeof(struct stud));
temp->ph=n;
temp->sem=s;
strcpy(temp->name,na);
strcpy(temp->usn,u);
strcpy(temp->brnch,b);
temp->next=head;
head=temp;

Dept. of CSE, ATMECE Page 41


DS(18CS32)

count++;
}
void insert_tail(long long int n,int s,char na[15],char u[15],char b[8])
{
temp=(struct stud*)malloc(1*sizeof(struct stud));
temp->ph=n;
temp->sem=s;
strcpy(temp->name,na);
strcpy(temp->usn,u);
strcpy(temp->brnch,b);
tail->next=temp;
temp->next=NULL;
tail=temp;
count++;
}
void delete_head()
{
temp1=head;
if(temp1==NULL)
{
printf("list is empty\n");
}
else
{
head=head->next;
printf("deleted node is:\n");
printf("-----------------------\n");
printf("NAME:%s\nUSN:%s\nBRANCH:%s\nSEM:%d\nPHONE NO.:%lld\n",temp1-
>name,temp1->usn,temp1->brnch,temp1->sem,temp1->ph);
printf("-----------------------\n");
free(temp1);

Dept. of CSE, ATMECE Page 42


DS(18CS32)

count--;
}
}
void delete_tail()
{
temp1=head;
if(temp1==NULL)
{
printf("list is empty\n");
}
while(temp1->next!=tail)
{
temp1=temp1->next;
}
printf("deleted node is:\n");
printf("-----------------------\n");
printf("NAME:%s\nUSN:%s\nBRANCH:%s\nSEM:%d\nPHONE NO.:%lld\n",tail->name,tail-
>usn,tail->brnch,tail->sem,tail->ph);
printf("-----------------------\n");
free(tail);
tail=temp1;
tail->next=NULL;
count--;
}
void main()
{
int choice;
long long int ph;
int sem;
char name[20],usn[15],brnch[5];
printf("--------MENU----------\n");

Dept. of CSE, ATMECE Page 43


DS(18CS32)

printf("1.create\n2.Insert from head\n3.Insert from tail\n4.Delete from head\5.Delete from


tail\n6.display\n7.exit\n");
printf("----------------------\n");
while(1)
{
printf("enter your choice\n");
scanf("%d",&choice);
switch(choice)
{
case 1: printf("enter the name usn branch sem phno. of the student respectively\n");
scanf("%s%s%s%d%lld",name,usn,brnch,&sem,&ph);
create(ph,sem,name,usn,brnch);
break;
case 2: printf("enter the name usn branch sem phno. of the student respectively\n");
scanf("%s%s%s%d%lld",name,usn,brnch,&sem,&ph);
insert_head(ph,sem,name,usn,brnch);
break;
case 3: printf("enter the name usn branch sem phno. of the student respectively\n");
scanf("%s%s%s%d%lld",name,usn,brnch,&sem,&ph);
insert_tail(ph,sem,name,usn,brnch);
break;
case 4: delete_head();
break;
case 5: delete_tail();
break;
case 6: display();
break;
case 7: exit(0);
default:printf("invalid option\n");
}
}}

Dept. of CSE, ATMECE Page 44


DS(18CS32)

3.9 Assignment Questions


1. What is linked list?
2. Explain the node structure of linked list?
3. What the operations that can be performed on linked list?
4. Explain header linked list with example.
5. Explain doubly linked list with example.

3.10 Outcome
 Identify the application of linked list.
 Familiarized with different linked list operation

Dept. of CSE, ATMECE Page 45


DS(18CS32)

MODULE 4: TREES

STRUCURE
4.0 Introduction
4.1 Objective
4.2 Definition
4.3 Terminology
4.4 Representation of Trees
4.4.1 List Representation
4.4.2 Left Child-Right Sibling Representation
4.4.3 Representation as a Degree-Two Tree
4.5 Binary Trees
4.5.1 Different Kinds of Binary Tree
4.6 Properties of Binary Trees
4.7 Binary Tree Representation
4.7.1 Array Representation
4.7.2 Linked Representation
4.8 Binary Tree Traversals
4.8.1 Inorder
4.8.2 Preorder
4.8.3 Postorder
4.8.4 Iterative Inorder
4.8.5 Level-Order Traversal
4.9 Additional Binary Tree Operations
4.10 Threaded Binary Tree
4.10.1 Inorder Traversal of A Threaded Binary Tree
4.10.2 Inserting a Node into a Threaded Binary Tree
4.11 Assignment Questions
4.12 Outcomes

4.0 Introduction
This module gives the overview of tree data structures, representation of trees using list.
Concepts of binary tree and its representation of array and linked representation are discussed in detail.
Different binary tree traversal is discussed with example. Threaded binary trees are highlighted.

4.1 Objective
 Understand the concept of tree data structure, binary trees and its operation.
 Understand the different methodology for binary tree traversal.

Dept of CSE, ATMECE Page 1


DS(18CS32)

4.2 DEFINITION
A tree is a finite set of one or more nodes such t h a t
 There is a specially designated node called root.
 The remaining nodes are partitioned into n >= 0 disjoint set T1,…,Tn, where each of
these sets is a tree. T1,…,Tn are called the subtrees of the root.

Every node in the tree is the root of some subtree

4.3 TERMINOLOGY
 Node: The item of information plus the branches to other nodes
 Degree: The number of subtrees of a node
 Degree of a tree: The maximum of the degree of the nodes in the tree.
 Terminal nodes (or leaf): nodes that have degree zero or node with no successor
 Nonterminal nodes: nodes that don’t belong to terminal nodes.
 Parent and Children: Suppose N is a node in T with left successor S1 and right
successor S2, then N is called the Parent (or father) of S1 and S2. Here, S1 is called
left child (or Son) and S2 is called right child (or Son) of N.
 Siblings: Children of the same parent are said to be s i b l i n g s .
 Edge: A line drawn from node N of a T to a successor is called an edge
 Path: A sequence of consecutive edges from node N to a node M is called a p a t h .
 Ancestors of a node: All the nodes along the path from the root to that node.
 The level of a node: defined by letting the root be at level zero. If a node is at level l,
then it children are at level l+1.
 Height (or depth): The maximum level of any node in the tree

Dept of CSE, ATMECE Page 2


DS(18CS32)

A is the root node


B is the parent of E and F
C and D are the sibling of B
E and F are the children of B
K, L, F, G, M, I, J are external nodes, or leaves
A, B, C, D, E, H are internal nodes
The level of E is 3
The height (depth) of the tree is 4
The degree of node B is 2
The degree of the tree is 3
The ancestors of node M is A, D, H
The descendants of node D is H, I, J, M

4.4 Representation of Trees

There are several ways to represent a given tree such as:

Figure (A)

1. List Representation
2. Left Child- Right Sibling Representation
3. Representation as a Degree-Two tree

Dept of CSE, ATMECE Page 3


DS(18CS32)

4.4.1 List Representation:

The tree can be represented as a List. The tree of figure (A) could be written as the list.
(A (B (E (K, L), F), C (G), D (H (M), I, J) ) )

 The information in the root node comes first.


 The root node is followed by a list of the subtrees of that node.

Tree node is represented by a memory node that has fields for the data and pointers to the tree
node's children

Since the degree of each tree node may be different, so memory nodes with a varying number of
pointer fields are used.
For a tree of degree k, the node structure can be represented as below figure. Each child field is
used to point to a subtree.

4.4.2 Left Child-Right Sibling Representation

The below figure show the node structure used in the left child-right sibling representation

To convert the tree of Figure (A) into this representation:


1. First note that every node has at most one leftmost child
2. At most one closest right sibling.

Dept of CSE, ATMECE Page 4


DS(18CS32)

Ex: In Figure (A), the leftmost child of A is B, and the leftmost child of D is H.
 The closest right sibling of B is C, and the closest right sibling of H is I.
 Choose the nodes based on how the tree is drawn. The left child field of each node points
to its leftmost child (if any), and the right sibling field points to its closest right sibling (if
any).
Figure (D) shows the tree of Figure (A) redrawn using the left child-right sibling representation.

Figure (D): Left child-right sibling representation of tree of figure (A)

4.4.3 Representation as a Degree-Two Tree

To obtain the degree-two tree representation of a tree, simply rotate the right-sibling pointers in a
left child-right sibling tree clockwise by 45 degrees. This gives us the degree-two tree displayed
in Figure (E).

Figure (E): degree-two representation

In the degree-two representation, a node has two children as the left and right children.

Dept of CSE, ATMECE Page 5


DS(18CS32)

4.5 BINARY TREES


Definition: A binary tree T is defined as a finite set of nodes such that,
 T is empty or
 T consists of a root and two disjoint binary trees called the left subtree and the right
subtree.

Figure: Binary Tree

4.5.1 Different kinds of Binary Tree

1. Skewed Tree
A skewed tree is a tree, skewed to the left or skews to the right.
or
It is a tree consisting of only left subtree or only right subtree.
 A tree with only left subtrees is called Left Skewed Binary Tree.
 A tree with only right subtrees is called Right Skewed Binary Tree.

2. Complete Binary Tree


A binary tree T is said to complete if all its levels, except possibly the last level, have the
maximum number node 2i, i ≥ 0 and if all the nodes at the last level appears as far left as
possible.

Figure (a): Skewed binary tree Figure (b): Complete binary tree

Dept of CSE, ATMECE Page 6


DS(18CS32)

3. Full Binary Tree


A full binary tree of depth ‘k’ is a binary tree of depth k having 2k – 1 nodes, k ≥ 1.

Figure: Full binary tree of level 4 with sequential node number

4. Extended Binary Trees or 2-trees


An extended binary tree is a transformation of any binary tree into a complete binary tree.
This transformation consists of replacing every null subtree of the original tree with
“special nodes.” The nodes from the original tree are then internal nodes, while the special
nodes are external nodes.
For instance, consider the following binary tree.

The following tree is its extended binary tree. The circles represent internal nodes, and square
represent external nodes.
Every internal node in the extended tree has exactly two children, and every external node is a
leaf. The result is a complete binary tree

Dept of CSE, ATMECE Page 7


DS(18CS32)

4.6 PROPERTIES OF BINARY TREES

Lemma 1: [Maximum number of nodes]:


(1) The maximum number of nodes on level i of a binary tree is 2 i-1 , i ≥ 1.
(2) The maximum number of nodes in a binary tree of depth k is 2k -1, k ≥ 1.

Proof:
(1) The proof is by induction on i.
Induction Base: The root is the only node on level i = 1. Hence, the maximum number of nodes
on level i =1 is 2i-1 = 20 = 1.
Induction Hypothesis: Let i be an arbitrary positive integer greater than 1. Assume that the
maximum number of nodes on level i -1is 2i-2
Induction Step: The maximum number of nodes on level i -1 is 2i-2 by the induction hypothesis.
Since each node in a binary tree has a maximum degree of 2, the maximum number of nodes
on level i is two times the maximum number of nodes on level i-1, or 2i-1

(2) The maximum number of nodes in a binary tree of depth k is


k k
∑ (maximum number of nodes on level i) = ∑ 2i-1 = 2k-1
i=0 i=0

Lemma 2: [Relation between number of leaf nodes and degree-2 nodes]:


For any nonempty binary tree, T, if n0 is the number of leaf nodes and n2 the number of nodes
of degree 2, then n0 = n2 + 1.

Proof: Let n1 be the number of nodes of degree one and n the total number of nodes.
Since all nodes in T are at most of degree two, we have
n = n0 + n1+ n2 (1)
Count the number of branches in a binary tree. If B is the number of branches, then n
=B + 1.
All branches stem from a node of degree one or two. Thus,
B =n 1+ 2n2.
Hence, we obtain
n = B + 1= n 1+ 2n2 + 1 (2)

Subtracting Eq. (2) From Eq. (1) and rearranging terms, we get

n0 = n2 +1

Dept of CSE, ATMECE Page 8


DS(18CS32)

Consider the figure:

Here, For Figure (b) n2=4, n0= n2+1= 4+1=5


Therefore, the total number of leaf node=5

4.7 BINARY TREE REPRESENTATION


The storage representation of binary trees can be classified as
1. Array representation
2. Linked representation .

4.7.1 Array representation:


 A tree can be represented using an array, which is called sequential representation.
 The nodes are numbered from 1 to n, and one dimensional array can be used to store
the nodes.
 Position 0 of this array is left empty and the node numbered i is mapped to position i of
the array.

Below figure shows the array representation for both the trees of figure (a).

Dept of CSE, ATMECE Page 9


DS(18CS32)

 For complete binary tree the array representation is ideal, as no space is wasted.
 For the skewed tree less than half the array is utilized.

4.7.2 Linked representation:


The problems in array representation are:
 It is good for complete binary trees, but more memory is wasted for skewed and many
other binary trees.
 The insertion and deletion of nodes from the middle of a tree require the movement of
many nodes to reflect the change in level number of these n o d e s .

These problems can be easily overcome by linked representation

Each node has three fields,


 LeftChild - which contains the address of left subtree
 RightChild - which contains the address of right subtree.
 Data - which contains the actual information

C Code for node:

typedef struct node *treepointer;


typedef struct {
int data;
treepointer leftChild, rightChild;
}node;

Dept of CSE, ATMECE Page 10


DS(18CS32)

Figure: Node representation

Linked representation of the binary tree

Dept of CSE, ATMECE Page 11


DS(18CS32)

4.8 BINARY TREE TRAVERSALS

Visiting each node in a tree exactly once is called tree traversal

The different methods of traversing a binary tree are:


1. Preorder
2. Inorder
3. Postorder
4. Iterative inorder Traversal
5. Level-Order traversal

4.8.1 Inorder: Inorder traversal calls for moving down the tree toward the left until you cannot go
further. Then visit the node, move one node to the right and continue. If no move can be done, then
go back one more node.

Let ptr is the pointer which contains the location of the node N currently being scanned.
L(N) denotes the leftchild of node N and R(N) is the right child of node N
Recursion function:
The inorder traversal of a binary tree can be recursively defined as

 Traverse the left subtree in inorder.


 Visit the root.
 Traverse the right subtree in inorder.

void inorder(treepointerptr)
{
if (ptr)
{
inorder (ptr→leftchild);
printf (“%d”,ptr→data);
inorder (ptr→rightchild);
}
}

Shruthi P, Asst. Professr, Dept of CSE, ATMECE Page 12


DS(18CS32)

4.8.2 Preorder: Preorder is the procedure of visiting a node, traverse left and continue. When
you cannot continue, move right and begin again or move back until you can move right and
resume.

Recursion function:
The Preorder traversal of a binary tree can be recursively defined as
 Visit the root
 Traverse the left subtree in preorder.
 Traverse the right subtree in preorder

void preorder (treepointerptr)


{
if (ptr)
{
printf (“%d”,ptr→data);
preorder (ptr→leftchild);
preorder (ptr→rightchild);
}
}

4.8.3 Postorder: Postorder traversal calls for moving down the tree towards the left until you
can go no further. Then move to the right node and then visit the node and continue.
Recursion function:
The Postorder traversal of a binary tree can be recursively defined as
 Traverse the left subtree in postorder.
 Traverse the right subtree in postorder.
 Visit the root

void postorder(treepointerptr)
{
if (ptr)
{
postorder (ptr→leftchild);
postorder (ptr→rightchild);
printf (“%d”,ptr→data);
}
}

Shruthi P, Asst. Professr, Dept of CSE, ATMECE Page 13


DS(18CS32)

4.8.4 Iterative inorder


Traversal:
Iterative inorder traversal explicitly make use of stack function.
The left nodes are pushed into stack until a null node is reached, the node is then removed from
the stack and displayed, and the node’s right child is stacked until a null node is reached. The
traversal then continues with the left child. The traversal is complete when the stack is empty.

4.8.5 Level-Order traversal:


Visiting the nodes using the ordering suggested by the node numbering is called
level ordering traversing.
The nodes in a tree are numbered starting with the root on level 1 and so o n .
Firstly visit the root, then the root’s left child, followed by the root’s right child. Thus
continuing in this manner, visiting the nodes at each new level from the leftmost node to the
rightmost node.

Level order traversal: 1 2 3 4 5


Initially in the code for level order add the root to the queue. The function operates by
deleting the node at the front of the queue, printing the nodes data field and adding the nodes
left and right children to the queue.

Shruthi P, Asst. Professr, Dept of CSE, ATMECE Page 14


DS(18CS32)
Function for level order traversal of a binary tree:

4.9 ADDITIONAL BINARY TREE OPERATIONS

1. Copying a Binary tree


This operations will perform a copying of one binary tree to another.

C function to copy a binary tree:

treepointer copy(treepointer original)


{ if(original)
{ MALLOC(temp,sizeof(*temp));
temp→leftchild=copy(original→leftchild);
temp→rightchild=copy(original→rightchild);
temp→data=original→data;
return temp;
}
return NULL;
}

2. Testing Equality
This operation will determin the equivalance of two binary tree. Equivalance binary tree have
the same strucutre and the same information in the corresponding nodes.

Shruthi P, Asst. Professr, Dept of CSE, ATMECE Page 15


DS(18CS32)

C function for testing equality of a binary tree:


int equal(treepointer first,treepointer second)
{
return((!first && !second) || (first && second && (first→data==second→data)
&& equal(first→leftchild,second→leftchild) && equal(first→rightchild,
second→rightchild))
}

This function will return TRUE if two trees are equivalent and FALSE if they are not.

3. The Satisfiability problem


 Consider the formula that is constructed by set of variables: x1, x2, …, xn and operators
(and), (or), ¬ (not).
 The variables can hold only of two possible values, true or false.
 The expression can form using these variables and operators is defined by the
following rules.
 A variable is an expression
 If x and y are expressions, then ¬x, xy, xy are expressions
 Parentheses can be used to alter the normal order of evaluation (¬ >  > )

Example: x1  (x2  ¬ x3) If x1 and x3 are false and x2 is true


= false  (true  ¬false)
= false  true
= true

The satisfiablity problem for formulas of the propositional calculus asks if there is an
assignment of values to the variable that causes the value of the expression to be true.

Let’s assume the formula in a binary tree

(x1  ¬x2)  (¬ x1  x3)  ¬x3

Shruthi P, Asst. Professr, Dept of CSE, ATMECE Page 16


DS(18CS32)

The inorder traversal of this tree is


x1  ¬x2  ¬ x1  x3  ¬x3

The algorithm to determine satisfiablity is to let (x1, x2, x3) takes on all the possible
combination of true and false values to check the formula for each combination.

For n value of an expression, there are 2n possible combinations of true and false
For example n=3, the eight combinations are (t,t,t), (t,t,f), (t,f,t), (t,f,f), (f,t,t), (f,t,f), (f,f,t),
(f,f,f).
The algorithm will take O(g 2n), where g is the time to substitute values for x1, x2,… xn and
evaluate the expression.

Node structure:
For the purpose of evaluation algorithm, assume each node has four fields:

Define this node structure in C as:

Satisfiability function: The first version of Satisfiability algorithm

Shruthi P, Asst. Professr, Dept of CSE, ATMECE Page 17


DS(18CS32)

4.10 THREADED BINARY TREE

The limitations of binary tree are:


 In binary tree, there are n+1 null links out of 2n total l i n k s .
 Traversing a tree with binary tree is time consuming.
These limitations can be overcome by threaded binary tree.

In the linked representation of any binary tree, there are more null links than actual pointers.
These null links are replaced by the pointers, called threads, which points to other nodes in the
tree.

To construct the threads use the following rules:


1. Assume that ptr represents a node. If ptr→leftChild is null, then replace the null link
with a pointer to the inorder predecessor of ptr.
2. If ptr →rightChild is null, replace the null link with a pointer to the inorder successor of
ptr.
Ex: Consider the binary tree as shown in below figure:

Figure A: Binary Tree

Figure B: Threaded tree corresponding to Figure A


There should be no loose threads in threaded binary tree. But in Figure B two threads
have been left dangling: one in the left child of H, the other in the right child of G.

In above figure the new threads are drawn in broken lines. This tree has 9 node and 10 0 -links
which has been replaced by threads.

Shruthi P, Asst. Professr, Dept of CSE, ATMECE Page 18


DS(18CS32)
When trees are represented in memory, it should be able to distinguish between threads and
pointers. This can be done by adding two additional fields to node structure, ie., leftThread
and rightThread
 If ptr→leftThread = TRUE, then ptr→leftChild contains a thread,
otherwise it contains a pointer to the left child.
 If ptr→rightThread = TRUE, then ptr→rightChild contains a thread,
otherwise it contains a pointer to the right child.

Node Structure:
The node structure is given in C declaration

typedef struct threadTree *threadPointer


typedef struct{
short int leftThread;
threadPointer leftChild;
char data;
threadPointer rightChild;
short int rightThread;
}threadTree;

The complete memory representation for the tree of figure is shown in Figure C

Shruthi P, Asst. Professr, Dept of CSE, ATMECE Page 19


DS(18CS32)

The variable root points to the header node of the tree, while root →leftChild points to the start of
the first node of the actual tree. This is true for all threaded trees. Here the problem of the loose
threads is handled by pointing to the head node called root.

4.10.1 Inorder Traversal of a Threaded Binary Tree


 By using the threads, an inorder traversal can be performed without making use of a
stack.
 For any node, ptr, in a threaded binary tree, if ptr→rightThread =TRUE, the inorder
successor of ptr is ptr →rightChild by definition of the threads. Otherwise we obtain
the inorder successor of ptr by following a path of left-child links from the right-
child of ptr until we reach a node with leftThread = TRUE.
 The function insucc ( ) finds the inorder successor of any node in a threaded tree
without using a stack.

threadedpointer insucc(threadedPointer tree)


{ /* find the inorder successor of tree in a threaded binary tree */
threadedpointer temp;
temp = tree→rightChild;
if (!tree→rightThread)
while (!temp→leftThread)
temp = temp→leftChild;
return temp;
Program: Finding inorder successor of a node

To perform inorder traversal make repeated calls to insucc ( ) function

void tinorder (threadedpointer tree)


{
Threadedpointer temp = tree;
for(; ;){
temp = insucc(temp);
if (temp == tree) break;
printf(“%3c”, temp→data
}
}
Program: Inorder traversal of a threaded binary tree

Shruthi P, Asst. Professr, Dept of CSE, ATMECE Page 20


DS(15CS33)

4.10.2 Inserting a Node into a Threaded Binary Tree


In this case, the insertion of r as the right child of a node s is studied.
The cases for insertion are:
 If s has an empty right subtree, then the insertion is simple and
diagrammed in Figure
 If the right subtree of s is not empty, then this right subtree is made the right
subtree of r after insertion. When this is done, r becomes the inorder
predecessor of a node that has a leftThread == true field, and
consequently there is a thread which has to be updated t o point to r. The
node containing this thread was previously the inorder successor of s .

void insertRight(threadedPointer Sf threadedPointer r)


{ /* insert r as the right
child of s */
threadedpointer
temp; r→rightChild
= parent→rightChild;
r→rightThread =
parent→rightThread; r→leftChild =
parent;
r→leftThrea
d = TRUE;
s→rightChil
d = child;

Shruthi P, Asst. Professr, Dept of CSE, ATMECE Page 21


DS(15CS33)
s→rightThre
ad =
FALSE; if
(!r→rightTh
read) {
temp =
insucc(r);
temp→leftChil
d = r;
}
}

4.11 Assignment Questions


1. What are the different Binary Tree Traversals with example?
2. Explain the terminologies of trees?
3. How to represent trees using linked list? Explain with example.
4. Explain different type’s binary trees.
5. Explain array representation of binary trees with example.

4.12. Outcome
 Familiarized with different tree traversal methodologies.
 Identify the applications of tree data structure.

Shruthi P, Asst. Professr, Dept of CSE, ATMECE Page 22


DS(18CS32)

Module V
STRUCTURE
5.0 Introduction
5.1 Objective
5.2 Definitions & Concept
5.3 Graph Terminologies
5.4 Basic Operations on Graphs
5.5 Representing Graph Data Structure
5.6 Complete Graphs and Connected Graphs
5.7 Graph Traversal Methods
5.7.1 Depth First Search (DFS)
5.7.2 Breadth First Traversal (BFS)
5.8 Sorting
5.8.1 Insertion Sort
5.9 Assignment Questions
5.10 Outcomes

5.0 Introduction
This module gives the overview of graphs and its terminologies. The DFS and BS traversal
methods are discussed in detail with examples. The different sorting techniques are explained in
detail. Different types of graph are highlighted.

5.1 Objective
 Understand the graph data structures and its operations.
 Understand the different graph traversal methods.
 Understand the different sorting techniques.

Dept. of CSE, ATMECE Page 1


DS(18CS32)

5.2 Definitions & Concept

A graph is a pictorial representation of a set of objects where some pairs of objects are connected
by links. The interconnected objects are represented by points termed as vertices, and the links
that connect the vertices are called edges.

Formally, a graph is a pair of sets (V, E), where V is the set of vertices and E is the set of edges,
connecting the pairs of vertices. Take a look at the following graph –

In the above graph,

V = {a, b, c, d, e}

E = {ab, ac, bd, cd, de}

5.3 Graph Terminologies

 Vertex – Each node of the graph is represented as a vertex. In the following example,
the labeled circle represents vertices. Thus, A to E are vertices.

 Edge – Edge represents a path between two vertices or a line between two vertices. In
the following example, the lines from A to B, B to C, and so on represents edges.

 Adjacency – Two node or vertices are adjacent if they are connected to each other
through an edge. In the following example, B is adjacent to A, C is adjacent to B, and so
on.

 Path – Path represents a sequence of edges between the two vertices. In the following
example, ABCD represents a path from A to D.

 Self – loop: A self-loop is an edge that connects a vertex to itself. A has self loop

Dept. of CSE, ATMECE Page 2


DS(18CS32)
 Out – Degree: The out – degree of a vertex is the number of edges pointing from it.
Out degree of D is 2 in Figure b
 In – Degree: The in-degree of a vertex is the number of edges pointing to it. In degree of
D is 1 in Figure b
 Sub Graph: A sub graph is a subset of a digraph’s edges (and associated vertices)
that constitutes a digraph.
 Path Length: The length of a path or a cycle is its number of edges. Length of path from
A to C is 2
 DAG: A directed acyclic graph (or DAG) is a digraph with no directed cycles. Figure b is
a DAG

A B

E D

Figure a

A B

E D

Figure b

Dept. of CSE, ATMECE Page 3


DS(18CS32)

5.4 Basic Operations on Graphs


Following are basic primary operations of a Graph –

 Add Vertex – Adds a vertex to the graph.

 Delete Vertex – Deletes a vertex from the graph

 Add Edge – Adds an edge between the two vertices of the graph.

 Delete Edge – Deletes an edge from the graph

 Display Vertex – Displays a vertex of the graph.

5.5 Representing Graph Data Structure

Graphs can be represented using a two dimensional array or with the help of linked lists.

If two dimensional array is used to represent a graph, such matrix is referred to as adjacency
matrix.

If linked list representation is used then such list is referred to as adjacency list.

To represent a graph in computer’s memory, we first need to understand what type of graph it is.
There are different types of graphs: - directed, undirected, weighted and un weighted graphs.

1. Directed graphs: These are the graphs that have directed edges, i.e., edges with
direction. Figure b is an example for this.

2. Un Directed Graphs: These are the graphs that have undirected edges, i.e., edges with
no direction. Figure a is an example for this.

3. Weighted Graphs: These are the graphs that contains edges with weights (values).
5
A B 6

8 C
7

D 3
E
9

Figure c

Dept. of CSE, ATMECE Page 4


DS(18CS32)

4. Unweighted Graphs: These are the graphs that contains edges with no weights (values).
Figure a and b are un weighted.

Combinations of above graphs would result in graphs such as weighted – directed, weighted
– un directed, Directed – un weighted graphs

Now, let us represent a directed graph using adjacency matrix concept. Consider figure b.

Basically, the size of adjacency matrix will be equal to the number of vertices in the graph. In
the above graph, there are 5 vertices therefore size is 5x5.

0 1 0 0 0 A B

0 0 1 0 0
C
0 0 0 0 0

0 0 1 0 0 E D

1 0 0 1 0
Figure b

If in the graph, there exists an edge between two vertices, it is denoted 1 in the matrix
otherwise 0.

Here, Row 1 pertains to A, Row 2 pertains to B, and so on.

Similarly Column 1 to A, Column 2 to B, and so on.

Example, A to B there is an edge. Therefore matrix [0,1] =1.

From A to D there is no edge, so matrix [0,4] =0.

To represent an undirected graph, the matrix shows symmetry property. Consider the below
graph.

Dept. of CSE, ATMECE Page 5


DS(18CS32)

A B
0 1 0 0 1
1 0 1 1 0
C
0 1 0 1 0
0 1 1 0 1
E D
1 0 0 1 0
Figure d

To represent a weighted directed graph, little modification in the representation procedure has to
be done.

0 5 999 999 999


999 0 6 999 999
999 999 0 999 999
999 7 3 0 999
8 999 0 9 0

5
A B 6

8 C
7

D 3
E
9

Figure c

Here, if there exists an edge between two vertices then in the matrix its value is
denoted otherwise a infinity ( or larger value like 999). All diagonal values will be 0.

Below is the adjacency list representation. Vertex 0 has edge to vertex 1 and vertex 4. Hence there

Dept. of CSE, ATMECE Page 6


DS(18CS32)
is a link between 0 and 1&4.

5.6 Complete Graphs and Connected Graphs

A complete graph is any graph where there's an edge between every pair of vertices in the
graph. Figure x is complete.

In a connected graph, there is a path between any given pair of vertices. Figure y is connected

A B

E D

Figure x

A B

E D

Figure y

5.7 Graph Traversal Methods

Basically, there are two graph traversal methods – Depth First Search & Breadth First Search.

Dept. of CSE, ATMECE Page 7


DS(18CS32)
5.7.1 Depth First Search (DFS)

The depth first traversal is similar to the preorder traversal of a binary tree. An initial or source
vertex is identified to start traversing, then from that vertex any one vertex which is adjacent to
the current vertex is traversed i.e. only one adjacent vertex is traversed from the vertex which
had been traversed last.
The general algorithm is:
for each vertex v in the graph
if v is not visited
Start the depth first traversal at v
The general algorithm to do a depth first traversal at a given node v is:
1. Mark node v as visited
2. Visit the node
3. For each vertex u adjacent to v
a. if u is not visited
b. start the depth first traversal at u
c. Clearly, this is a recursive algorithm.
Consider the below shown graph, chose A as source vertex and apply DFS. The resulting
traversal sequence
A BDC E
This algorithm uses stack data structure.

A B

E D

Figure b

Dept. of CSE, ATMECE Page 8


DS(18CS32)

5.7.2 Breadth First Traversal (BFS)


The breadth first traversal of a graph is similar to traversing a binary tree level by level (the
nodes at each level are visited from left to right).All the nodes at any level, i, are visited before
visiting the nodes at level i + 1.

As in the case of the depth first traversal, because it might not be possible to traverse the entire
graph from a single vertex, the breadth first traversal also traverses the graph from each vertex
that is not visited. Starting at the first vertex, the graph is traversed as much as possible; we then
go to the next vertex that has not been visited. In other words it can be stated as all vertices that
are adjacent to the current vertex are traversed first. To implement the breadth first search
algorithm, we use a queue.

The general algorithm is:


a.for each vertex v in the graph

if v is not visited

add v to the queue // start the breadth first search at v

b. Mark v as visited

c. while the queue is not empty

Remove vertex u from the queue

Retrieve the vertices adjacent to u

for each vertex w that is adjacent

to u if w is not visited

Add w to the queue

Mark w as visited
Consider the
below graph

Dept. of CSE, ATMECE Page 9


DS(18CS32)

A B

E D

Figure b

BFS uses queue data structure. Let us chose A as source vertex.

A is visited, then vertices adjacent to A are inserted into the queue. B is in queue now. Adjacent
to B are C & D so D & C are in queue. Adjacent to D is E therefore E will be in the queue.
When all the vertices in the queue are removed, the final sequence will be obtained

A B C D E

C program to perform BFS and DFS on a given graph

#include <stdio.h>
#include <stdlib.h>
int a[20][20],q[20],visited[20],reach[10],n,i,j,f=0,r=-1,count=0;
void bfs(int v)
{
for(i=1;i<=n;i++)
if(a[v][i] && !visited[i])
q[++r]=i;
if(f<=r)
{
visited[q[f]]=1;
bfs(q[f++]);
}
}
void dfs(int v)
{
int i;
reach[v]=1;
for(i=1;i<=n;i++)
{
Dept. of CSE, ATMECE Page 10
DS(18CS32)

if(a[v][i] && !reach[i])


{
printf("\n %d->%d",v,i);
count++;
dfs(i);
}
}
}
void main()
{
int v, choice;
printf("\n Enter the number of vertices:");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
q[i]=0;
visited[i]=0;
}
for(i=1;i<=n-1;i++)
reach[i]=0;

printf("\n Enter graph data in matrix form:\n");


for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
scanf("%d",&a[i][j]);
printf("1.BFS\n 2.DFS\n 3.Exit\n");
scanf("%d",&choice);
switch(choice)
{
case 1: printf("\n Enter the starting vertex:");
scanf("%d",&v);
bfs(v);
if((v<1)||(v>n))
{
printf("\n Bfs is not possible");
}
else
{
printf("\n The nodes which are reachable from %d:\n",v);
for(i=1;i<=n;i++)

Dept. of CSE, ATMECE Page 11


DS(18CS32)

if(visited[i])
printf("%d\t",i);
}
break;
case 2:dfs(1);
if(count==n-1)
printf("\n Graph is connected");
else
printf("\n Graph is not connected");
break;
case 3: exit(0);
}
}

5.8 Sorting
Sorting is a technique in which elements are arranged either in ascending or descending order.
There are number of sorting algorithms. Here, majorly three sorting algorithms are identified and
explained.

1. Insertion Sort

2. Radix Sort

3. Address Calculation Sort

5.8.1 Insertion Sort

#include<stdio.h>
int main(){

int i,j,s,temp,a[20];

printf("Enter total elements: ");


scanf("%d",&s);

printf("Enter %d elements: ",s);


for(i=0;i<s;i++)
scanf("%d",&a[i]);

for(i=1;i<s;i++){
temp=a[i];
j=i-1;
while((temp<a[j])&&(j>=0)){

Dept. of CSE, ATMECE Page 12


DS(18CS32)

a[j+1]=a[j];
j=j-1;
}
a[j+1]=temp;
}

printf("After sorting: ");


for(i=0;i<s;i++)
printf(" %d",a[i]);

return 0;
}

5.9 Assignment Questions


1. What is graph? Explain the terminologies of graph data structures.
2. Explain DFS with example.
3. Explain BFS with example.
4. Explain insertion ort with example.

5.10 Outcomes
 Identify the applications of graph data structure.
 Familiarized with graph traversal methods, DFS and BFS.
 Familiarized with different sorting technologies.

Dept. of CSE, ATMECE Page 13

You might also like