Cds Full Notes
Cds Full Notes
TOTAL 45 PERIODS
COURSE OUTCOMES:
CO1: Develop C programs for any real world/technical application.
CO2: Apply advanced features of C in solving problems.
CO3: Write functions to implement linear and non–linear data structure operations.
CO4: Suggest and use appropriate linear/non–linear data structure operations for
solving a givenproblem.
CO5: Appropriately use sort and search algorithms for a given application.
CO6: Apply appropriate hash functions that result in a collision free scenario for data
storage andretrieval.
TEXT BOOKS:
1. Mark Allen Weiss, “Data Structures and Algorithm Analysis in C”, Second
Edition, PearsonEducation, 1997.
2. ReemaThareja, “Programming in C”, Second Edition, Oxford University Press,
2016.
REFERENCES:
1. Brian W. Kernighan, Rob Pike, “The Practice of Programming”, Pearson
Education, 1999.
2. Paul J. Deitel, Harvey Deitel, “C How to Program”, Seventh Edition,
Pearson Education,2013.
UNIT -II
PROGRAMMING - ADVANCED FEATURES
2.1 Introduction 2.1
2.2 Structure 2.1
2.2.1 Three Main Aspects of Working with Structure 2.1
2.2.1.1 Defining Structure 2.2
2.2.1.2 Initializing Structure Elements 2.3
UNIT - III
LINEAR DATA STRUCTURES
3.1 Abstract Data Types (ADTS) 3.1
3.1.1 Abstract Data Type Model 3.1
3.2 List ADT 3.3
3.2.1 Operations on the List Data Structure 3.4
3.3 Array-Based Implementation 3.4
3.3.1 Properties of Array 3.4
3.3.2 Representation of an Array 3.5
3.3.3 Memory Allocation of an Array 3.5
3.3.4 Access an Element from the Array 3.6
3.3.5 Basic Operations of an Array 3.6
UNIT - IV
NON-LINEAR DATA STRUCTURES
4.1 Introduction to Tress 4.1
4.1.1 Example of Tree Data Structure 4.1
4.1.2 Basic Terminologies in Tree Data Structure 4.2
4.1.3 Properties of a Tree 4.2
4.1.4 Syntax for Creating a Node 4.3
4.2 Binary Trees 4.3
4.2.1 Binary Tree Representation 4.3
4.2.2 Types of Binary Trees 4.4
4.2.3 Benefits of Binary Trees 4.4
4.3 Tree Traversal 4.6
4.3.1 Types of Tree Traversal 4.6
4.4 Expression Trees 4.10
4.4.1 Properties of an Expression Tree 4.10
4.4.2 Construction of Expression Tree 4.10
4.4.3 Example - Postfix Expression Construction 4.11
4.4.4 Implementation of Expression Tree in C Programming Language 4.12
UNIT - V
SORTING AND SEARCHING TECHNIQUES
5.1 Introduction to Sorting 5.1
5.2 Insertion Sort 5.2
5.2.1 Algorithm 5.3
5.2.2 Working of Insertion Sort Algorithm 5.3
5.2.3 Analysis of Insertion Sort 5.4
5.2.4 Applications 5.4
5.3 Quick Sort 5.6
5.3.1 Algorithm for Quick Sort 5.6
5.3.2 Working of Quick Sort Algorithm 5.6
5.3.3 Quicksort Complexity 5.8
5.3.4 Applications of Quick Sort 5.8
5.4 Heap Sort 5.11
5.4.1 What is a Heap 5.11
5.4.2 Working of Heap Sort Algorithm 5.11
5.4.3 Heapsort Complexity 5.16
5.4.4 Heap Sort Applications 5.16
5.5 Merge Sort 5.18
5.5.1 Algorithm 5.19
5.5.2 Working of Merge Sort Algorithm 5.19
I
C PROGRAMMING
FUNDAMENTALS
Data Types – Variables – Operations – Expressions and Statements – Conditional
Statements – Functions – Recursive Functions – Arrays – Single and Multi-Dimensional
Arrays.
Program 1.1
/* Program to find the area of a circle */ /* Documentation Section */
# include<stdio.h> /* Preprocessor Section */
# include<conio.h>
# define PI 3.14 /* Definition Section */
void main() /* main( ) function */
{
float area,r; /* Local variable declaration */
clrscr(); // Executable part of the program
printf("\n Enter the radius:\n");
scanf("%f",&r);
area= PI*(r*r);
printf("\n Area of the Circle = %8.2f", area);
Program 1.2
/* Program to find the sum of two numbers using function */
/*Documentation Section */
# include<stdio.h> /* Preprocessor Section */
# include<conio.h>
int a,b; /* Global Variable declaration */
int add(int,int); /* Function declaration */
void main() /* main( ) function */
{
int c; /* Local Variable declaration */
clrscr(); // Executable part of the main()
program printf("\n Enter the values for a and b:\n");
scanf("%d %d",&a,&b);
c = add(a,b);
printf("\n Sum of %d + %d = %d", a,b,c);
getch();
}
int add(int a,int b) /* Subprogram of add() function definition */
{
int c; /* Local Variable declaration */
c=a+b; // Executable part of the
function return(c);
}
1.5.2 Delimiters
The language pattern of C uses a special kind of symbols, which are called
delimiters. They are given in Table. 1.3.
Syntax
1.5.6 Constants
1.6 OPERATORS IN C
Operator: An operator is a symbol that specifies an operation to be performed on
operands. Eg: x= a+b; where + is an operator.
Operands: An operand is an entity on which an operation is to be performed. An
operand can be a variable name, a constant, a function call or a macro name.
Eg. x= a+b; where x, a, b are the operands.
Expression: An expression is a sequence of operands and operators that specifies the
computations of a value. An expression is made up of one or more operands. Eg. x= a+b.
Example:
void main()
{
int a=5, b=4, c;
c=a-b;
printf(“%d”, c);
}
The following table show the division operator on various data types.
Operation Result Example
int/int int 2/5=0
real/int real 5.0/2=2.5
int/real real 5/2.0=2.5
real/real real 5.0/2.0=2.5
Syntax
AE1 operator AE2
where, AE- Arithmetic Expression or Variable or Value.
These operators provide the relationship between two expressions.
If the condition is true it returns a value 1, otherwise it returns 0.
These operators are used in decision making process. They are generally used in
conditional or control statement.
1.6.1.3 Logical Operators
Logical Operators are used to combine the result of two or more conditions.
&& - This operator is usually used in situation where two or more expressions
must be true.
Syntax:
(exp1) && (exp2)
|| – This is used in situation, where at least one expression is true.
Syntax:
(exp1) || (exp2)
! – This operator reverses the value of the expression it operates on. (i.e.,) it
makes a true expression false and false expression true.
Syntax:
!(exp1)
Program 1.4
/* Program using Logical operators
*/ #include<stdio.h>
#include<conio.h>
void main( )
{
clrscr( );
printf("\n Condition : Return values ");
printf("\n 5<=8 && 4>2: %5d",5<=8 && 4>2);
printf("\n 5>=3 || 6<8: %5d",5>=3 || 6<8);
Program 1.5
/* Program using Assignment and Short-hand Assignment operators */
#include<stdio.h>
#include<conio.h>
void main( )
{
int a=20,b=10,c=15,d=25,e=34,x=5;
clrscr( );
printf("\n Value of a=
%d",a); printf("\n Value of
b=%d",b); a+=x;
Pre-increment operator
This operator increment the value of a variable first and then perform other
actions.
a) Comma operator(,):
The comma operator is used to separate the statement elements such as
variables, constants or expression etc.,
This operator is used to link the related expression together.
Such expression can be evaluated from left to right and the value of right most
expression is the value of combined expression.
1.7.2 Statements
A statement is an instruction given to the computer to perform an action. There
are three different types of statements in C:
1. Expression Statements
2. Compound Statements
3. Control Statements
Expression Statement
An expression statement or simple statement consists of an expression followed
by a semicolon (;).
Example
a=100;
b=20;
c=a/b;
Program 1.20
/* Program to Generate the Even numbers to a given limit*/
#include<stdio.h>
#include<conio.h>
void main()
{
int n,i;
printf(“\n Enter the limit:”);
scanf(“%d”,&n);
i=1;
while(i<=n)
{ if(i
%2==0)
return_type function_name(argument_list)
{
//function body
}
Example
int add(int x, int y)
{
int z;
z=x+y;
Before swapping:
num1 value is 35
1.11 ARRAYS
Introduction to Arrays
An Array is a collection of similar data elements
These data elements have the same data type
The elements of the array are stored in consecutive memory locations and are
referenced by an index
Definition
An array is a data structure that is used to store data of the same type. The
position of an element is specified with an integer value known as index or
subscript.
Example
type name[size]
Here the type can be either int, float, double, char or any other valid data type. The
number within the brackets indicates the size of the array, i.e., the maximum number of
elements that can be stored in the array.
Example: i) int marks[10]
ii) int a[5]={10,20,5,56,100}
The declaration of an array tells the compiler that, the data type, name of the
array, size of the array and for each element it occupies memory space. Like for int data
type occupies 2 bytes for each element and for float occupies 4 bytes for each element
etc. The size of the array operates the number of elements that can be stored in an array.
The values are written with curly brackets and every value is separated by a
comma. It is a compiler error to specify more number of values than the number of
elements in the array.
Example: int marks [5] = {90, 92, 78, 82, 58};
Example
int a[4]; // a is an array of 4 integers
char b[6]; //b is an array of 6
Program 1.33
/*Program for reversing an array*/
#include<stdio.h>
void main( )
Declaration
datatype arrayname [row size][column size]
a 1 4 6
2 0 0
}
}
/* Program module to sum colwise */
for(i=0;i<n;i++)
{
colsum=0;
for(j=0;j<n1;j++)
colsum+=a[j][i];
printf(“col no=%d sum=%d\n “,i,colsum);
}
/ * Program module to sum principle diagonal * /
}
Output
Enter order [row][col] of the matrix
33
Enter 9 elements
123456789
Sum of all elements
45 row no = 0 sum = 6
row no = 1 sum = 15
row no = 2 sum = 24
col no = 0 sum = 12
col no = 1 sum = 15
col no = 2 sum = 18
Principle diagonal sum 15
Off diagonal sum 15
Interpreters usually take less amount of Compilers usually take a large amount
time to analyze the source code. of time to analyze the source code.
However, the overall execution time is However, the overall execution time is
comparatively slower than compilers. comparatively faster than interpreters.
No Object Code is generated, hence are Generates Object Code which
memory efficient. further requires linking, hence
requires more memory.
Programming languages like Programming languages like C, C++,
JavaScript, Python, Ruby use Java use compilers.
interpreters.
PART-B
1. Explain the different types of operators with neat examples.
2. Illustrate the different conditional statements available in C with syntax and
examples
3. Explain the looping statements with neat examples.
4. What is an Array? Explain Single and Multi-Dimensional arrays with neat examples.
5. Write a C program for Matrix Multiplication with a 3*3 matrix.
6. Create a C program for Matrix Addition.
7. Write a C program to calculate the total, average and grade for 50 Students.
8. Write a C program to calculate the factorial of a given number.
9. Write a C program to check whether a given number is odd or even.
10. Write a C program to check whether a given number is prime or not.
11. Write a C program to check whether a given number is a palindrome or not.
12. Write a C program to check whether a given number is a Armstrong number or not.
II
PROGRAMMING - ADVANCED FEATURES
Structures – Union – Enumerated Data Types – Pointers: Pointers to Variables, Arrays
and Functions – File Handling – Preprocessor Directives.
2.1 INTRODUCTION
Structures, unions and enumerations are known as user defined data types.
These data types are used to create a flexible new data type.
Structure can be used for the storage of different data types. The similarity
between structure and array is both contain a finite number of elements.
Union is similar to structures in all aspects except the manner in which their
constituent elements are stored.
In structures, separate memory is allocated to each element, while in unions all
the elements are share the same memory.
Enumeration helps to define a data type whose objects can take a limited set of
values.
2.2 STRUCTURE
Definition
A Structure is a collection of variables of different data types under a single
name and provides a convenient way of grouping several of related information
together.
Unlike arrays, it can be used for the storage of heterogeneous data (data of
different data types).
int rno;
float mark;
};
struct student s;
void main()
{
printf(“enter the name”);
scanf(“%c”,&s.name);
printf(“enter the rno”);
scanf(“%d”,&s.rno);
printf(“enter the mark”);
scanf(“%f”,&s.mark);
printf(“NAME=%c”,s.name);
printf(“RNO=%d”,s.rno);
printf(“MARK=%f”,s.mark);
getch();
}
OUTPUT
Output:
enter the name
xyz
enter the rno
20
enter the marks
80
90
95
NAME=xyz
RNO=20
AVERAGE MARK=88.33
Example Program 2.3
#include<stdio.h>
struct book //Struct datatype declaration
{
int x,y;
};
void main()
{
struct book s1={4,5}; //s1-> variable of structure and values are
initialized
int a=10 , b=20 ;
printf(“\na=%d”,s1.x+a); // elements are accessed using dot operator(.)
printf(“\nb=%d”, s1.y+b);
}
Output:
a=4
b=5
Program 2.7
#include<stdio.h>
struct book //structure type declaration
{
char a; // elements are declared
int b;
char c;
float d;
}; //structure type declarations are terminated
void main()
{
struct book var; //variable declaratio
printf(“obj of struct book will take %d bytes\n”,sizeof(struct book));
printf(“structure variable var takes %d bytes\n”, sizeof var);
}
Output:
2.3 UNION
Union can be defined as a user-defined data type which is a collection of
different variables of different data types in the same memory location. The
union can also be defined as many members, but only one member can contain a
value at a particular point in time. Unions provide an efficient way of using the
same memory location for multiple-purpose.
Union is a user-defined data type, but unlike structures, they share the same
memory location.
Defining a Union
To define a union, you must use the union statement in the same way as did
while defining a structure. The union statement defines a new data type with
more than one member for your program. The format of the union statement is
as follows:
union [union tag]
{ member
definition; member
definition;
...
member definition;
} [one or more union variables];
The union tag is optional and each member definition is a normal variable
definition, such as int i; or float f; or any other valid variable definition. At the end
of the union's definition, before the final semicolon, you can specify one or more
union variables but it is optional. Here is the way you would define a union type
named Data having three members i, f, and str.
union Data
{ int i;
float f;
char str[20];
} data;
Now, a variable of Data type can store an integer, a floating-point number, or a
string of characters. It means a single variable, i.e., same memory location, can be
used to store multiple types of data. You can use any built-in or user defined data
types inside a union based on your requirement.
Example Program 2.9 Illustration of Union
#include <stdio.h>
#include <string.h>
union Data {
int i;
float f;
char str[20];
};
DOWNLOADED FROM STUCOR
DOWNLOADED FROM STUCOR
APP
void main( )
{ union Data
data; data.i = 10;
printf( "data.i : %d\n", data.i);
data.f = 220.5;
printf( "data.f : %f\n", data.f);
strcpy( data.str, "Charulatha publication");
printf( "data.str : %s\n", data.str);
}
Output
data.i : 10
data.f : 220.500000
data.str : Charulatha publication
Difference between Structure and Union
Sl.No Structure Union
1 The member of a structure occupies The member of union share same
its own memory space. memory space.
2 The keyword struct is used to define The keyword union is used to define a
a structure structure
3 All the members of a structure can Only the first member of a union can
be initialized. be initialized.
4 In structure, each member is stored In union, all members are stored in
in a separate memory location. So the same memory locations. So, need
need more memory space. less memory space.
2.4 POINTERS
2.4.1 Pointers to Variables
A pointer is a variable that stores an address of another variable of same type.
Pointer can have any name that is legal for other variable.
Here ‘a’ is a variable holds a value 50 and stored in a memory location 1001.
‘*ptr’ is pointer variable holds a address of a variable ‘a’.
#include<conio.h>
void main()
{
int i=4;
int *j;
j=&i;
clrscr();
printf(“Address of i=%u\n”,&i);
printf(“Address of i=%u\n”,j);
printf(“Address of j=%u\n”,&j);
printf(“value of j=%u\n”,j);
printf(“value of i=%d\n”,i);
printf(“value of i=%d\n”,*(&i));
printf(“value of i=%d\n”,*j);
getch();
}
Output
Address of i=65524
Address of i=65524
Address of j=65522
value of j=65524
value of i=4
value of i=4
value of i=4
Example Program 2.12
/*C program to add two numbers using pointers*/
#include<stdio.h>
#include<conio.h>
b) Dereferencing a pointer
The object referenced by a pointer can be indirectly accessed by
dereferencing the pointer.
Dereferencing operator (*) is used for this.
This operator is also known as indirection operator or value- at-operator.
Example
int b;
int a=12;
a int *p;
Example program 2.13
#include<stdio.h>
void main()
{
int a=12;
int *p;
int **pptr;
p=&a;
pptr=&p;
printf(“Value=%d”,a);
printf(“value by dereferencing p is %d \n”,*p);
printf(“value by dereferencing pptr is %d \n”,**pptr);
printf(“value of p is %u \n”,p);
printf(“value of pptr is %u\n”,pptr);
}
Output
Value=12
value by dereferencing p is 12
value by dereferencing pptr is 12
value of p is 1000
value of pptr is 2000
30
40
50
Total= 150
}
void swap(int* n1, int* n2)
{
int temp;
temp = *n1;
*n1 = *n2;
*n2 = temp;
}
Output
num1 = 10
num2 = 5
The address of num1 and num2 are passed to the swap() function using
swap(&num1, &num2);
When *n1 and *n2 are changed inside the swap() function, num1 and num2
inside the main() function are also changed.
Inside the swap() function, *n1 and *n2 swapped. Hence, num1 and num2 are
also swapped.
1. wb(write)
This opens a binary file in write mode.
SYNTAX: fp=fopen(“data.dat”,”wb”);
2. rb(read)
This opens a binary file in read mode
SYNTAX:fp=fopen(“data.dat”,”rb”);
3. ab(append)
This opens a binary file in a Append mode i.e. data can be added at the end
of file.
SYNTAX: fp=fopen(“data.dat”,”ab”);
4. r+b(read+write)
This mode opens preexisting File in read and write mode.
SYNTAX: fp=fopen(“data.dat”,”r+b”);
5. w+b(write+read)
This mode creates a new file for reading and writing in Binary mode.
SYNTAX: fp=fopen(“data.dat”,”w+b”);
6. a+b(append+write)
This mode opens a file in append mode i.e. data can be written at the end of
file.
SYNTAX: fp=fopen(“data.dat”,”a+b”);
Opening Modes in Standard I/O
r Open for reading If the file does not exist, fopen() returns
NULL
rb Open for reading in binary If the file does not exist, fopen() returns
mode. NULL.
w Open for writing. If the file exists, its contents are overwritten.
If the file does not exist, it will be created.
wb Open for writing in binary If the file exists, its contents are overwritten.
mode. If the file does not exist, it will be created.
FILE *fptr;
fptr = fopen(“C:\\program.txt”,”w”);
if(fptr == NULL)
{
printf(“Error!”);
exit(1);
}
printf(“Enter num: “);
scanf(“%d”,&num);
fprintf(fptr,”%d”,num);
fclose(fptr);
return 0;
}
This program takes a number from user and stores in the file program.txt. After
you compile and run this program, you can see a text file program.txt created in
C drive of your computer. When you open the file, you can see the integer you
entered.
Reading from a text file
Program 2.21: Read from a text file using fscanf()
#include <stdio.h>
int main()
{
int num;
FILE *fptr;
if ((fptr = fopen(“C:\\program.txt”,”r”)) == NULL)
{ printf(“Error! opening file”);
// Program exits if the file pointer returns NULL.
exit(1);
}
}
for(n = 1; n < 5; ++n)
{
num.n1 = n;
num.n2 = 5n;
num.n3 = 5n + 1;
fwrite(&num, sizeof(struct threeNum), 1, fptr);
}
fclose(fptr);
return 0;
}
We declare a structure three Num with three numbers - n1, n2 and n3, and
define it in the main function as num. Now, inside the for loop, we store the
value into the file using fwrite.
The first parameter takes the address of num and the second parameter takes the
size of the structure three Num. Since, we’re only inserting one instance of num,
the third parameter is 1. And, the last parameter *fptr points to the file we’re
storing the data. Finally, we close the file.
Reading from a binary file
Function fread() also take 4 arguments similar to fwrite() function as above.
fread(address_data,size_data,numbers_data,pointer_to_file);
Program 2.23: Reading from a binary file using fread()
#include <stdio.h>
struct threeNum
{
int n1, n2, n3;
};
int main()
{
int n;
1. fopen () : It creates a new file for use or opens an existing file for use.
2. fclose (): It closes a file which has been opened for use.
3. fscanf( file pointer, format string, address of the
variable) Example: fscanf(fptr,”%d”, &num);
4. fprintf(console output, “format string”, file pointer);
Example: fprintf(stdout, “%f \n”, f); /*note: stdout refers to screen */
5. getw (): This function returns the integer value from a given file and increment the
file pointer position to the next message.
Syntax: getw (fptr);
Where fptr is a file pointer which takes the integer value from file.
6. putw (): This function is used for writing an integer value to a given
file. Syntax: putw (value,fptr);
Where fptr is a file pointer Value is an integer value which is written to a given file.
Example Program for getw() and putw()
Program 2.24: Write a program to read integer data from the user and write it
into the file using putw() and read the same integer data from the file using getw()
and display it on the output screen.
#include<stdio.h>
#include<conio.h>
void main()
{
FILE *fp;
Example:
1. fseek( p,10L,0)
This 0 means pointer position is on beginning of the file, from this statement
pointer position is skipped 10 bytes from the beginning of the file.
2. fseek( p,5L,1)
This 1 means current position of the pointer position. From this statement
pointer position is skipped 5 bytes forward from the current position.
3. fseek(p,-5L,1):
From this statement pointer position is skipped 5 bytes backward from the
current position.
All preprocessor directives starts with hash # symbol. Let's see a list of
preprocessor directives.
#define: It substitutes a preprocessor using macro.
#include: It helps to insert a certain header from another file.
#undef: It undefines a certain preprocessor macro.
#ifdef: It returns true if a certain macro is defined.
#ifndef: It returns true if a certain macro is not defined.
#if, #elif, #else, and #endif: It tests the program using a certain condition;
these directives can be nested too.
#line: It handles the line numbers on the errors and warnings. It can be used
to change the line number and source files while generating output during
compile time.
#error and #warning: It can be used for generating errors and warnings.
...
member definition;
};
5. Difference between Structure and Union.
Structure Union
The Keyword struct is used to define The Keyword union is used to define
the Structure the Union
Structure allocates storage space for all Union allocates one storage space for
its members seperately. all its members.
Structure occupies high memory space Union occupies low memory space
when compared to Structure
We can access all members of Only one member of union can be
Structure at a time accessed at a time.
Altering the value of a member will Altering the value of a member will
not affect other member of a structure alter other member value in union.
User can only use the function but User can use this type of function.
cannot change (or) modify this function. User can also modify this function.
PART-B
3
LINEAR DATA STRUCTURES
Abstract Data Types (ADTs) – List ADT – Array-Based Implementation – Linked List
– Doubly-Linked Lists – Circular Linked List – Stack ADT – Implementation of Stack –
Applications – Queue ADT – Priority Queues – Queue Implementation – Applications.
Space Complexity
In array, space complexity for worst case is O(n).
2. Space Complexity
Operation Space complexity
Insertion O(n)
Deletion O(n)
Search O(n)
6. Deletion of the node Removing the node which is present just after the
having given data node containing the given data.
7. Searching Comparing each node data with the item to be
searched and return the location of the item in the
list if the item found else return null
8. Traversing Visiting each node of the list at least once in
order to perform some specific operation like
searching, sorting, display, etc.
Fig. 3.13: Deletion of a specified node in Doubly Linked List at the end
3.6.2.5 Searching
Searching in circular singly linked list needs traversing across the list.
The item which is to be searched in the list is matched with each node data of
the list once.
If the match found then the location of that item is returned otherwise -1 is
returned.
Algorithm 3.13
STEP 1: SET PTR = HEAD
STEP 2: Set I = 0
STEP 3: IF PTR = NULL
WRITE "EMPTY LIST"
GOTO STEP 8
END OF IF
STEP 4: IF HEAD → DATA = ITEM
WRITE i+1 RETURN [END OF IF]
STEP 5: REPEAT STEP 5 TO 7 UNTIL PTR->next != head
STEP 6: if ptr → data = item
write i+1
RETURN
3.6.2.5 Searching
Traversing in circular singly linked list can be done through a loop.
Initialize the temporary pointer variable temp to head pointer and run the
while loop until the next pointer of temp becomes head.
Algorithm 3.14
STEP 1: SET PTR = HEAD
STEP 2: IF PTR = NULL
WRITE "EMPTY LIST"
GOTO STEP 8
END OF IF
STEP 4: REPEAT STEP 5 AND 6 UNTIL PTR → NEXT != HEAD
STEP 5: PRINT PTR → DATA
STEP 6: PTR = PTR → NEXT
[END OF LOOP]
STEP 7: PRINT PTR→ DATA
STEP 8: EXIT
Let's take the example of Converting an infix expression into a postfix expression
In the above example, the only change from the postfix expression is that the
operator is placed before the operands rather than between the operands.
Evaluating Postfix expression
Stack is the ideal data structure to evaluate the postfix expression because the
top element is always the most recent operand. The next element on the Stack is
the second most recent operand to be operated on.
Before evaluating the postfix expression, the following conditions must be
checked. If any one of the conditions fails, the postfix expression is invalid.
For tracing the algorithm let us assume that the input is () (() [()])
Input Symbol Operation Stack Output
( Push ( (
) Pop (
Test if ( and A[i] match? YES
( Push ( (
3.9.4 Backtracking
Backtracking is used in algorithms in which there are steps along some path
(state) from some starting point to some goal. It uses recursive calling to find the
solution by building a solution step by step increasing values with time. It
removes the solutions that doesn't give rise to the solution of the problem based
on the constraints given to solve the problem.
Let’s see how Stack is used in Backtracking in the N-Queens Problem
For the N-Queens problem, one way we can do this is given by the following:
For each row, place a queen in the first valid position (column), and then
move to the next row
If there is no valid position, then one backtracks to the previous row and try
the next position
Starting with a queen in the first row, first column (represented by a stack
containing just "0"), we search left to right for a valid position to place another
queen in the next available row.
If we find a valid position in this row, we push this position (i.e., the column
number) to the stack and start again on the next row.
If we don't find a valid position in this row, we backtrack to the previous row --
that is to say, we pop the col position for the previous row from the stack and
search for a valid position further down the row.
Note, when the stack size gets to n, we will have placed n queens on the board,
and therefore have a solution.
Of course, there is nothing that requires there be only one solution. To find the
rest, every time a solution is found, we can pretend it is not a solution, backtrack
to the previous row, and proceed to find the next solution.
Ultimately, every position in the first row will be considered. When there are not
more valid positions in the first row and we need to backtrack, that's our cue that
there are no more solutions to be found. Thus, we may stop searching when we
try to pop from the stack, but can't as it is empty.
Putting all this into pseudo-code form, we have the following algorithm...
3.11.6 Heap
A heap is a tree-based data structure that forms a complete binary tree, and
satisfies the heap property.
If A is a parent node of B, then A is ordered with respect to the node B for all
nodes A and B in a heap.
It means that the value of the parent node could be more than or equal to the
value of the child node, or the value of the parent node could be less than or
equal to the value of the child node.
Therefore, we can say that there are two types of heaps:
Now, let’s try to insert a new element, 6. Since there are nodes present in the heap, we
insert this node at the end of heap so it looks like this:
Then, heapify operation is implemented. After which, the heap will look like this:
Now, let’s try to delete an element, 6. Since this is not a leaf node, we swap it with the
last leaf node so it looks like this:
Then, heapify operation is implemented. After which, the heap will look like this:
REVIEW QUESTIONS
PART-A
1. What do you mean by non-linear data structure? Give example.
The non-linear data structure is the kind of data structure in which the data may
be arranged in hierarchical fashion. For example- Trees and graphs.
2. List the various operations that can be performed on data structure.
Various operations that can be performed on the data structure are
Create
Insertion of element
Deletion of element
Searching for the desired element
Sorting the elements in the data structure
Reversing the list of elements.
3. What is abstract data type
The abstract datatype is special kind of datatype, whose behavior is defined by
a set of values and set of operations.
4. What is list ADT in data structure?
The list ADT is a collection of elements that have a linear relationship with
each other. A linear relationship means that each element of the list has a
unique successor.
5. What Are Arrays in Data Structures?
An array is a linear data structure that collects elements of the same data type
and stores them in contiguous and adjacent memory locations. Arrays work on
an index system starting from 0 to (n-1), where n is the size of the array.
6. What is a linked list?
A linked list is a set of nodes where each node has two fields ‘data’ and ‘link’.
The data field is used to store actual piece of information and link field is used
to store address of next node.
PART B
4
NON-LINEAR DATA STRUCTURES
Trees – Binary Trees – Tree Traversals – Expression Trees – Binary Search Tree –
Hashing - Hash Functions – Separate Chaining – Open Addressing – Linear Probing–
Quadratic Probing – Double Hashing – Rehashing.
Here,
Node A is the root node
B is the parent of D and E
Here, the root node is A. All the nodes on the left of A are a part of the left
subtree whereas all the nodes on the right of A are a part of the right subtree.
Thus, according to preorder traversal, we will first visit the root node, so A
will print first and then move to the left subtree.
B is the root node for the left subtree. So B will print next, and we will visit
the left and right nodes of B. In this manner, we will traverse the whole left
subtree and then move to the right subtree. Thus, the order of visiting the
nodes will be A→B→C→D→E→F→G→H→I.
o Next, read a'+' symbol, so two pointers to tree are popped, a new tree is
formed and push a pointer to it onto the stack.
o Next, 'c' is read, we create one node tree and push a pointer to it onto the
stack.
In the above figure, we can observe that the root node is 40, and all the nodes of
the left subtree are smaller than the root node, and all the nodes of the right
subtree are greater than the root node.
Similarly, we can see the left child of root node is greater than its left child and
smaller than its right child. So, it also satisfies the property of binary search tree.
Therefore, we can say that the tree in the above image is a binary search tree.
Step 5 - Insert 10
o 10 is smaller than 45 and 15, so it will be inserted as a left subtree of 15.
Step 6 - Insert 55
o 55 is larger than 45 and smaller than 79, so it will be inserted as the left
subtree of 79.
Step 8 - Insert 20
o 20 is smaller than 45 but greater than 15, so it will be inserted as the right
subtree of 15.
Step2:
Step3:
4.6 HASHING
Hashing in the data structure is a technique of mapping a large chunk of data
into small tables using a hashing function. It is also known as the message digest
function. It is a technique that uniquely identifies a specific item from a
collection of similar items.
It uses hash tables to store the data in an array format. Each value in the array
has been assigned a unique index number. Hash tables use a technique to
generate these unique index numbers for each value stored in an array format.
This technique is called the hash technique.
You only need to find the index of the desired item, rather than finding the data.
With indexing, you can quickly scan the entire list and retrieve the item you
wish. Indexing also helps in inserting operations when you need to insert data at
a specific location. No matter how big or small the table is, you can update and
retrieve data within seconds.
The hash table is basically the array of elements, and the hash techniques of
search are performed on a part of the item i.e. key. Each key has been mapped to
a number, the range remains from 0 to table size 1
Types of hashing in data structure is a two-step process.
o The hash function converts the item into a small integer or hash value. This
integer is used as an index to store the original data.
o It stores the data in a hash table. You can use a hash key to locate data
quickly.
4.6.1 Examples
In schools, the teacher assigns a unique roll number to each student. Later, the
teacher uses that roll number to retrieve information about that student.
DOWNLOADED FROM STUCOR
DOWNLOADED FROM STUCOR
APP
A library has an infinite number of books. The librarian assigns a unique number
to each book. This unique number helps in identifying the position of the books
on the bookshelf.
If we insert a new element 52 , that would also go to the fourth index as 52%7 is
3.
The lookup cost will be scanning all the entries of the selected linked list for the
required key. If the keys are uniformly distributed, then the average lookup cost
will be an average number of keys per linked list.
Step 2: Now we will insert all the keys in the hash table one by one. First key to
be inserted is 24. It will map to bucket number 0 which is calculated by using
hash function 24%6=0.
Step 4: The next key is 65. It will map to bucket number 5 because 65%6=5. So,
insert it to bucket number 5.
Step 5: Now the next key is 81. Its bucket number will be 81%6=3. But bucket 3
is already occupied by key 75. So separate chaining method will handles the
collision by creating a linked list to bucket 3.
Step 6: Now the next key is 42. Its bucket number will be 42%6=0. But bucket 0
is already occupied by key 24. So separate chaining method will again handles
the collision by creating a linked list to bucket 0.
Step 7: Now the last key to be inserted is 63. It will map to the bucket number
63%6=3. Since bucket 3 is already occupied, so collision occurs but separate
chaining method will handle the collision by creating a linked list to bucket 3.
4.10.1 Solution
Although, the quadratic probing eliminates the primary clustering, it still has the
problem.
When two keys hash to the same location, they will probe to the same alternative
location. This may cause secondary clustering. In order to avoid this secondary
clustering, double hashing method is created where we use extra multiplications
and divisions
The problem with linear probing is primary clustering. This means that even if
the table is empty, any key that hashes to table requires several attempt to
resolve the collision because it has to cross over the blocks of occupied cell.
These blocks of occupied cell form the primary clustering. If any key falls into
clustering, then we cannot predict the number of attempts needed to resolve the
collision. These long paths affect the performance of the hash table.
A binary tree is a tree data structure composed of nodes, each of which has
utmost, two children, referred to as left and right nodes. The tree starts off with
a single node known as the root.
2. What are the two methods of binary tree implementation?
Linear representation.
Linked representation
3. What are the applications of binary tree?
Binary tree is used in data processing.
o File index schemes
o Hierarchical database management system
4. List out few of the Application of tree data-structure?
The manipulation of Arithmetic expression
Used for Searching Operation
Used to implement the file system of several popular operating systems
Symbol Table construction
Syntax analysis
5. Define expression tree?
Expression tree is also a binary tree in which the leaf’s terminal nodes or
operands and non-terminal intermediate nodes are operators used for traversal.
6. Define tree– traversal and mention the type of traversals?
Three types of tree traversal
Inorder traversal
Preoder traversal
Postorder traversal.
7. Define in -order traversal?
In-order traversal entails the following steps;
5
SORTING AND SEARCHING TECHNIQUES
Insertion Sort – Quick Sort – Heap Sort – Merge Sort –Linear Search – Binary Search
The above steps represents how insertion sort works. Insertion sort works like
the way we sort playing cards in our hands. It always starts with the second
element as key. The key is compared with the elements ahead of it and is put it
in the right place.
5.2.4 Applications
The insertion sort is used when:
The array is has a small number of elements
There are only a few elements left to be sorted
Example Program 5.1
#include <stdio.h>
int main()
{
int n, array[1000], c, d, t;
printf("Enter number of elements\n");
scanf("%d", &n);
printf("Enter %d integers\n", n);
for (c = 0; c < n; c++)
{
scanf("%d", &array[c]);
}
for (c = 1 ; c <= n - 1; c++)
{
After converting the given heap into max heap, the array elements are
Next step is to delete the root element (89) from the max heap. To delete this
node, swap it with the last node, i.e. (11). After deleting the root element, again
heapify it to convert it into max heap.
After swapping the array element 89 with 11, and converting the heap into max-
heap, the elements of array are
In the next step, again delete the root element (81) from the max heap. To delete
this node, swap it with the last node, i.e. (54). After deleting the root element,
again heapify it to convert it into max heap.
After swapping the array element 81 with 54 and converting the heap into max-
heap, the elements of array are
In the next step, delete the root element (76) from the max heap again. To delete
this node, swap it with the last node, i.e. (9). After deleting the root element,
again heapify it to convert it into max heap.
After swapping the array element 76 with 9 and converting the heap into max-
heap, the elements of array are
In the next step, again delete the root element (54) from the max heap. To delete
this node, swap it with the last node, i.e. (14). After deleting the root element,
again heapify it to convert it into max heap.
After swapping the array element 54 with 14 and converting the heap into max-
heap, the elements of array are
In the next step, again delete the root element (22) from the max heap. To delete
this node, swap it with the last node, i.e. (11). After deleting the root element,
again heapify it to convert it into max heap.
After swapping the array element 22 with 11 and converting the heap into max-
heap, the elements of array are
In the next step, again delete the root element (14) from the max heap. To delete
this node, swap it with the last node, i.e. (9). After deleting the root element,
again heapify it to convert it into max heap.
After swapping the array element 14 with 9 and converting the heap into max-
heap, the elements of array are
In the next step, again delete the root element (11) from the max heap. To delete
this node, swap it with the last node, i.e. (9). After deleting the root element,
again heapify it to convert it into max heap.
After swapping the array element 11 with 9, the elements of array are
Now, heap has only one element left. After deleting it, heap will be empty.
heapify(a, n, largest);
}
}
/*Function to implement the heap sort*/
void heapSort(int a[], int n)
{
for (int i = n / 2 - 1; i >= 0; i--)
heapify(a, n, i);
// One by one extract an element from heap
for (int i = n - 1; i >= 0; i--) {
/* Move current root element to end*/
// swap a[0] with a[i]
int temp = a[0];
a[0] = a[i];
a[i] = temp;
heapify(a, i, 0);
}
}
/* function to print the array elements */
5.5.1 Algorithm
Merge sort keeps on dividing the list into equal halves until it can no more be
divided. By definition, if it is only one element in the list, it is sorted. Then,
merge sort combines the smaller sorted lists keeping the new list sorted too
Step 1 − if it is only one element in the list it is already sorted, return.
Step 2 − divide the list recursively into two halves until it can no more be divided.
Step 3 − merge the smaller lists into new list in sorted order.
First divide the given array into two equal halves. Merge sort keeps dividing the
list into equal parts until it cannot be further divided.
As there are eight elements in the given array, so it is divided into two arrays of
size 4.
Now, again divide these two arrays into halves. As they are of size 4, so divide
them into new arrays of size 2.
Now, again divide these arrays to get the atomic value that cannot be further
divided.
In the next iteration of combining, now compare the arrays with two data
values and merge them into an array of found values in sorted order.
Now, there is a final merging of the arrays. After the final merging of above
arrays, the array will look like
5.7.2 Algorithm
Linear_Search(a, n, val) // 'a' is the given array, 'n' is the size of given array, 'val'
is the value to search
Step 1: set pos = -1
Step 2: set i = 1
Step 3: repeat step 4 while i <= n
Step 4: if a[i] == val
set pos = i
print pos
go to step
6 [end of
if]
set ii = i + 1
[end of loop]
Step 5: if pos = -1
print "value is not present in the array "
[end of if]
Step 6: exit
The value of K, i.e., 41, is not matched with the first element of the array. So, move to
the next element. And follow the same process until the respective element is found.
5.8.1 Algorithm
Binary_Search(a, lower_bound, upper_bound, val) // 'a' is the given array,
'lower_bound' is the index of the first array element, 'upper_bound' is the index of the
last array element, 'val' is the value to search
Step 1: set beg = lower_bound, end = upper_bound, pos = - 1
Step 2: repeat steps 3 and 4 while beg <=end
Step 3: set mid = (beg + end)/2
Step 4: if a[mid] = val
set pos = mid
print pos
go to step 6
else if a[mid] > val
set end = mid - 1
else
set beg = mid + 1
[end of if]
[end of loop]
Step 5: if pos = -1
print "value is not present in the array"
[end of if]
Step 6: exit
Now, the element to search is found. So algorithm will return the index of the
element matched.
5.8.3 Binary Search complexity:
Time Complexity
Best O(1)
Worst O(logn)
Average O(logn)
Space Complexity O(1)
The elements of the array are - 21, 14, 35, 30, 40, 51, 55, 57, 70
Element to be searched is – 40
Element is present at 5 position of array
12. Why quick sort is preferred for arrays and merge sort for linked lists?
Quick sort is an in-place sorting algorithm, i.e. which means it does not require
any additional space, whereas Merge sort does, which can be rather costly. In
merge sort, the allocation and deallocation of the excess space increase the
execution time of the algorithm.
Unlike arrays, in linked lists, we can insert elements in the middle in O(1) extra
space and O(1) time complexities if we are given a reference/pointer to the
previous node. As a result, we can implement the merge operation in the merge
sort without using any additional space.
13. In which case insertion sort is used?
Insertion sort has a fast best-case running time and is a good sorting algorithm
to use if the input list is already mostly sorted.
PART B