You are on page 1of 130

Data Structures

BY

Kaivan Shah

Subject Expert at Ruchit's Academy


Data Structures
Kaivan Shah

Copyright © by Ques10. All rights reserved. No part of this publication may


be reproduced, copied, or stored in a retrieval system, distributed or
transmitted in any form or by any means, including photocopy, recording or
other electronic or mechanical methods without the prior written permission
of the publisher.

This book is sold subject to the condition that it shall not, by the way of trade
or otherwise, be lent, resold, hired out, or otherwise circulated without the
publisher's prior written consent in any form of building or cover other than
which it is published and without a similar condition including this condition
being imposed on the subsequent purchaser and without limiting the rights
under copyright reserved above.

Edition: May 2020

This edition is for sale in India only. Sale and purchase of this book outside
of this country is unauthorized by the publisher.

Published by:
Ques10
Shop No. 18, Tapovan Arcade, Nahur (W), Mumbai - 400078.
Email: helpdesk@ques10.com
Website: www.ques10.com
Preface
People say, "Don't judge a book by its cover". But don't we?

As engineering students, we are master procrastinators. We only want to


study stuff that is absolutely necessary.

So just days before the exams, when no-head-no-tail-heavy-weight reference


books stop making any sense, we start looking for something which does. We
run to the nearest bookstore and buy whatever everyone else has.

But, while studying we do notice that they are not up to the mark. No clear
explanation, tons of mistakes, tough sentences.. you know what we are
talking about. That's why we have made Ques10 books.

We thought what if we can write books which are concise and to-the-point?

So we approached academically proficient faculties who have been teaching


for years and asked them to write decent books. And we're proud of what
we've come out with.

It needs to be mentioned that many have helped us unconditionally along the


way. We can't name them all here because that'd be a really long list. We
thank them for their support. We also thank those who have dedicatedly
mailed us for their priceless comments and reviews.

That’s pretty much it. We hope you like our books and benefit from them.

Team Ques10
Syllabus
01 Introduction to Data Structures

Introduction, Types of Data Structures – Linear and Nonlinear, Operations on


Data Structures, Concept of ADT, Arrays.

02 Stack and Queues

Introduction, ADT of Stack, Operations on Stack, Array Implementation of


Stack, Applications of Stack – Well form-ness of Parenthesis, Infix to Postfix
Conversion and Postfix Evaluation, Recursion.

ADT of Queue, Operations on Queue, Array Implementation of Queue,


Circular Queue, Priority Queue, Double Ended Queue, Applications of
Queue.

03 Linked List

Introduction, Representation of Linked List, Linked List v/s Array,


Implementation of Linked List, Linked Implementation of Stack and Queue,
Circular Linked List, Doubly Linked List, Application – Polynomial
Representation and Addition.

04 Trees

Introduction, Tree Terminologies, Binary Tree, Representation, Types of


Binary Tree, Binary Tree Traversals, Binary Search Tree, Implementation of
Binary Search Tree, Applications – Expression Tree, Huffman Encoding.

Search Trees – AVL, B Tree, B+ Tree, Splay Tree and Trie.

05 Graphs

Introduction, Graph Terminologies, Representation, Graph Traversals –


Depth First Search (DFS) and Breadth First Search (BFS), Application –
Topological Sorting
06 Sorting and Searching

Introduction, Bubble Sort, Insertion Sort, Merge Sort, Quick Sort. Linear
Search, Binary Search, Hashing – Concept, Hash Functions, Collision
Handling Techniques.

V0514th20201
Chapter 1

Introduction to Data Structure


Content

Types of data structures


Abstract Datatype
File handling operations in C
Operations with files

/ Types of data structures


Chap 1

1. Explain different types of data structures with


examples
Appeared in exams: 2 times

1. A data structure is a particular way of storing and organizing data in a


computer so that it can be used efficiently

2. Data structure are broadly classified as


a. Primitive Data Structure
b. Non-Primitive Data Structure / Derived Data Structure
3. Primitive data structures are the basic data structures that can be
directly accessed and does not contain any sub-datatype.

4. Examples of Primitive data structures are


i. Integer
ii. Character
iii. Float and
iv. Pointer

5. Non-Primitive data Structures are derived from one or more primitive


data structures.

6. Examples of Non-primitive data structures are


i. Arrays
ii. Lists
iii. Files

7. Lists are further sub divided into Linear and Non Linear Data structure.

8. Linear Data Structure

i. A data structure that maintains a linear


relationship between its elements, it is called linear data
structure
ii. For example, an array,stack and Queue holds
the linear relationship between its elements, it is linear
data structure

9. Non-Linear Data Structure

i. In case of non-linear data structure, they do


not maintain any linear relationship between their elements
ii. For example tree,graph

/ Types of data structures


Chap 1

2. Explain different types of data structures with an


example
Data structure is a particular way of storing and organizing data in a
computer so that it can be used efficiently. So, it is a special format for
organizing and storing data. Arrays, linked lists, trees, graphs, etc. are all
data structures.
Here are different types of data structures:-

1. Array: It consists of a collection of elements, each identified by a


common variable name and an index. A block of continuous memory is
assigned for an array. Arrays may be one-dimensional or
multidimensional

1. Linked List: It consists of a group of nodes together which represent a


sequence. It consists of two main parts: the data and a pointer pointing
to the next node in the list. The start is marked by head pointer and the
end is denoted by null pointer.

1. Tree: It has a set of nodes which have data and pointers or references.
The pointers point to the children nodes of the node. The constraint is
that no reference is duplicated and no node points to the root.
1. Graph: It’s a collection of a set of vertices V and a set of edges E. Each
edge E is a pair (v, w) where v and w are elements of V (i.e. they are
vertices).

/ Abstract Datatype
Chap 1

3. Define ADT with an example


Appeared in exams: 2 times

1. Abstract Data type (ADT) is a type (or class) for objects whose behavior
is defined by a set of value and a set of operations
2. The definition of ADT only mentions what operations are to be
performed but not how these operations will be implemented
3. It does not specify how data will be organized in memory.
4. Also it does not specify what algorithms will be used for
5. ADT provides only the essentials information to the user and hides the
details of its implementation and hence it is called abstract.
6. Examples of ADT

1. Stack ADT:- A Stack contains elements of same type arranged in


sequential order. All operations takes place at a single end that is top of
the stack

2. Queue ADT:- A Queue contains elements of same type arranged in


sequential order. Operations takes place at both ends, insertion is done at
end and deletion is done at front.

/ File handling operations in C


Chap 1

4. What is file? Explain various file handling


operations in C
Appeared in exams: Once

1. A file represents a sequence of bytes on the disk where a group of


related data is stored. File is created for permanent storage of data.
2. In C language, we use a structure pointer of file type to declare a file.
FILE *fp;
3. C provides a number of functions that helps to perform basic file
operations.
4. Following are the functions.
1. fopen(): This command is used to open a particular file.
2. fclose(fptr): This command is used to close a file.
3. getc (): Used to read from the file.(SingleCharacter)
4. putc(): Used to write into the file. (SingleCharacter)
5. fprinf(): write multiple data to file.

/ Operations with files


Chap 1

5. What is file? Explain various file handling


operations in C
Appeared in exams: Once

1. A file represents a sequence of bytes on the disk where a group of


related data is stored. File is created for permanent storage of data.
2. In C language, we use a structure pointer of file type to declare a file.
FILE *fp;
3. C provides a number of functions that helps to perform basic file
operations.
4. Following are the functions.
1. fopen(): This command is used to open a particular file.
2. fclose(fptr): This command is used to close a file.
3. getc (): Used to read from the file.(SingleCharacter)
4. putc(): Used to write into the file. (SingleCharacter)
5. fprinf(): write multiple data to file.
Chap 1/ Operations with files
6. Discuss file I/O in C language with different
library functions
Appeared in exams: Once

1. A file represents a sequence of bytes on the disk where a group of


related data is stored. File is created for permanent storage of data.

2. In C language, we use a structure pointer of file type to declare a file.

FILE *fp;

3. C provides two different ways of file processing. These are


1. Standard Input/output (stream I/O or high-level I/O).
2. System-oriented Input/output (low-level I/O).
4. The Standard I/O is very simple and most commonly used way of
performing file I/O in C language.Here data is written as individual
characters or as strings.
5. The System-oriented I/O is complex to implement. The data cannot be
written as individual characters, or as strings, or as formatted data.
Using this approach the data must be written as a buffer full of bytes,
where user needs to create this buffers manually.
6. C provides a number of functions that helps to perform basic file
operations. Following are the functions
1. fopen(): This command is used to open a particular file. General
Syntax : *fp = FILE *fopen(const char *filename, const char
*mode); Example fp = fopen("one.txt", "w"); Here filename is
"one.txt" and mode w specifies the write mode.
2. fclose(fptr): This command is used to close a file. General Syntax :
int fclose( FILE *fp ); Here fclose() function closes the file and
returns zero on success, or EOF if there is an error in closing the
file. This EOF is a constant defined in the header file stdio.h
3. getc (): Used to read from the file.(SingleCharacter) char input =
getc(fp); where fp is file pointer.
4. putc(): Used to write into the file. (SingleCharacter) putc('c',fp);
where character 'c' is written in file pointed by file pointer fp;
Chapter 2

Stack and Queues


Content

Stack as ADT
Queue Program
Stack using Linked List
Recursion as an application of stack

/ Stack as ADT
Chap 2

1. Write ADT for stack. Give application of stack


Appeared in exams: Once

1. Stack is an LIFO structure.


2. It is represented using an array
3. Variable “Top” is used to track the topmost element of stack.

4. Stack is represented as follows


struct stack
{
int data[SIZE];
int top;
}s;

5. Where variable SIZE is used to specify the length of stack and its
declared as constant

6. “s” is variable of type stack consisting of


1. array “data[SIZE]” and
2. integer variable “top”.
7. Following are the applications of stack
1. Recursion
2. Polish notation conversion
3. Expression evaluation
4. Reversal of List

Chap 2/ Queue Program


2. Write a menu driven program in C to implement
QUEUE ADT. The program should perform the
following operations: (i) Inserting an Element in the
Queue (ii) Deleting Element from the Queue (iii) Dis
Appeared in exams: Once

#include<stdio.h>
#include<conio.h>
#define max 5
typedef struct Queue
{
int r,f;
int data[max];
}queue;
void initialize(queue *p);
int empty (queue *p);
int full(queue *p);
void enqueue(queue *p,int x);
int dequeue(queue *p);
void printQueue(queue *p);
void main()
{
queue q;
int op,x;
initialize(&q);
do
{
printf("\n 1. INSERT \n 2. DELETE \n 3. PRINT \n
4. QUIT") ;
printf("\n Enter your choice");
scanf("%d",&op);
switch(op)
{
case 1 : printf("\n Enter a number");
scanf("%d",&x);
if(!full(&q))
{
enqueue(&q,x);
}
else
{
printf("\n QUEUE IS FULL");
}
break;
case 2 : if(!empty(&q))
{
x=dequeue(&q);
printf("\n DELETED ELEMENT IS %d",x);
}
else
{
printf("\n QUEUE IS EMPTY");
}
break;
case 3 : if(!empty(&q))
{
printQueue(&q);
}
else
{
printf("\n QUEUE IS EMPTY");
}
break;
default : printf("\n INVALID OPTION ");

}
}while(op!=4);
}
void initialize(queue *p)
{
p->r=-1;
p->f=-1;
}
int empty(queue *p)
{
if(p->r==-1)
{
return (1);
}
else
{
return(0);
}
}
int full(queue *p)
{
if(p->r==max-1)
{
return(1);
}
else
{
return(0);
}
}
void enqueue(queue *p,int x)
{
if(p->r==-1)
{
p->r=p->f=0;
p->data[p->r]=x;
}
else
{
p->r=p->r+1;
p->data[p->r]=x ;
}
}
int dequeue(queue *p)
{
int t;
t=p->data[p->f];
if(p->f==p->r)
{
p->f=-1;
p->r=-1;
}
else
{
p->f=p->f=+1;
}
return(t);
}
void printQueue(queue *p)
{
int i;
for(i=p->f;i<=p->r;i++)
{
printf(" %d ",p->data[i]);
}
}

/ Queue Program
Chap 2

3. Write a program to implement Queue using


Linklist
Appeared in exams: Once

#include <stdio.h>
#include <stdlib.h>
struct node
{
int info;
struct node *ptr;
}*front,*rear,*temp,*front1;
int frontelement();
void enq(int data);
void deq();
void empty();
void display();
void create();
void queuesize();
int count = 0;
void main()
{
int no, ch, e;
printf("\n 1 - Enque");
printf("\n 2 - Deque");
printf("\n 3 - Front element");
printf("\n 4 - Empty");
printf("\n 5 - Exit");
printf("\n 6 - Display");
printf("\n 7 - Queue size");
create();
while (1)
{
printf("\n Enter choice : ");
scanf("%d", &ch);
switch (ch)
{
case 1:
printf("Enter data : ");
scanf("%d", &no);
enq(no);
break;
case 2:
deq();
break;
case 3:
e = frontelement();
if (e != 0)
printf("Front element : %d", e);
else
printf("\n No front element in Queue as
queue is empty");
break;
case 4:
empty();
break;
case 5:
exit(0);
case 6:
display();
break;
case 7:
queuesize();
break;
default:
printf("Wrong choice, Please enter correct
choice ");
break;
}
}
}
/* Create an empty queue */
void create()
{
front = rear = NULL;
}
/* Returns queue size */
void queuesize()
{
printf("\n Queue size : %d", count);
}
/* Enqueing the queue */
void enq(int data)
{
if (rear == NULL)
{
rear = (struct node *)malloc(1*sizeof(struct node));
rear->ptr = NULL;
rear->info = data;
front = rear;
}
else
{
temp=(struct node *)malloc(1*sizeof(struct node));
rear->ptr = temp;
temp->info = data;
temp->ptr = NULL;
rear = temp;
}
count++;
}
/* Displaying the queue elements */
void display()
{
front1 = front;
if ((front1 == NULL) && (rear == NULL))
{
printf("Queue is empty");
return;
}
while (front1 != rear)
{
printf("%d ", front1->info);
front1 = front1->ptr;
}
if (front1 == rear)
printf("%d", front1->info);
}
/* Dequeing the queue */
void deq()
{
front1 = front;
if (front1 == NULL)
{
printf("\n Error: Trying to display elements from
empty queue");
return;
}
else
if (front1->ptr != NULL)
{
front1 = front1->ptr;
printf("\n Dequed value : %d", front->info);
free(front);
front = front1;
}
else
{
printf("\n Dequed value : %d", front->info);
free(front);
front = NULL;
rear = NULL;
}
count--;
}
/* Returns the front element of queue */
int frontelement()
{
if ((front != NULL) && (rear != NULL))
return(front->info);
else
return 0;
}
/* Display if queue is empty or not */
void empty()
{
if ((front == NULL) && (rear == NULL))
printf("\n Queue empty");
else
printf("Queue not empty");
}

Chap 2/ Stack using Linked List


4. Write a program to implement STACK using
Linked List. What are the advantage of linked list
over array
Appeared in exams: Once

#include <stdio.h>
#include <stdlib.h>
struct node
{
int info;
struct node *ptr;
}*top,*top1,*temp;
int topelement();
void push(int data);
void pop();
void empty();
void display();
void destroy();
void stack_count();
void create();
int count = 0;
void main()
{
int no, ch, e;
printf("\n 1 - Push");
printf("\n 2 - Pop");
printf("\n 3 - Top");
printf("\n 4 - Empty");
printf("\n 5 - Exit");
printf("\n 6 - Dipslay");
printf("\n 7 - Stack Count");
printf("\n 8 - Destroy stack");
create();
while (1)
{
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:
if (top == NULL)
printf("No elements in stack");
else
{
e = topelement();
printf("\n Top element : %d", e);
}
break;
case 4:
empty();
break;
case 5:
exit(0);
case 6:
display();
break;
case 7:
stack_count();
break;
case 8:
destroy();
break;
default :
printf(" Wrong choice, Please enter correct choice
");
break;
}
}
}
/* Create empty stack */
void create()
{
top = NULL;
}
/* Count stack elements */
void stack_count()
{
printf("\n No. of elements in stack : %d", count);
}
/* Push data into stack */
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;
top = temp;
}
count++;
}
/* 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);
top = top1;
count--;
}
/* Return top element */
int topelement()
{
return(top->info);
}
/* Check if stack is empty or not */
void empty()
{
if (top == NULL)
printf("\n Stack is empty");
else
printf("\n Stack is not empty with %d elements", count);
}
/* Destroy entire stack */
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");
count = 0;
}
2.Following are the points in favour of Linked Lists.

a. The size of the arrays is fixed: So we must know the upper limit on the
number of elements in advance. Also, generally, the allocated memory is
equal to the upper limit irrespective of the usage, and in practical uses, upper
limit is rarely reached.

b. Inserting a new element in an array of elements is expensive, because room


has to be created for the new elements and to create room existing elements
have to shifted.

c. For example, suppose we maintain a sorted list of IDs in an array id[]. id[]
= [1000, 1010, 1050, 2000, 2040, …..]. And if we want to insert a new ID
1005, then to maintain the sorted order, we have to move all the elements
after 1000 (excluding 1000).

d. Deletion is also expensive with arrays until unless some special techniques
are used. For example, to delete 1010 in id[], everything after 1010 has to be
moved.

/ Recursion as an application of stack


Chap 2

5. Explain recursion as an application of stack with


examples
Appeared in exams: Once

1. "Recursion" is technique of solving any problem by calling same


function again and again until some breaking (base) condition where
recursion stops and it starts calculating the solution from there on. For
eg. calculating factorial of a given number
2. Thus in recursion last function called needs to be completed first.
3. Now Stack is a LIFO data structure i.e. ( Last In First Out) and hence it
is used to implement recursion.
4. The High level Programming languages, such as Pascal , C etc. that
provides support for recursion use stack for book keeping.
5. In each recursive call, there is need to save the
1. current values of parameters,
2. local variables and
3. the return address (the address where the control has to return from
the call).

6. Also, as a function calls to another function, first its arguments, then the
return address and finally space for local variables is pushed onto the
stack.
7. Recursion is extremely useful and extensively used because many
problems are elegantly specified or solved in a recursive way.

8. The example of recursion as an application of stack is keeping books


inside the drawer and the removing each book recursively.
Chapter 3

Linked List
Content

Linked Lists Over Arrays


Single-Doubly Linked List
Linked List Application

Chap 3/ Linked Lists Over Arrays


1. State advantages of Linked List over
arrays.Explain different applications of Linked List
Appeared in exams: Once

1. Following are the points in favour of Linked Lists.

1. The size of the arrays is fixed: So we must know the upper limit on
the number of elements in advance. Also, generally, the allocated
memory is equal to the upper limit irrespective of the usage, and in
practical uses, upper limit is rarely reached.
2. Inserting a new element in an array of elements is expensive,
because room has to be created for the new elements and to create
room existing elements have to shifted.
3. For example, suppose we maintain a sorted list of IDs in an array
id[]. id[] = [1000, 1010, 1050, 2000, 2040, …..]. And if we want to
insert a new ID 1005, then to maintain the sorted order, we have to
move all the elements after 1000 (excluding 1000).
4. Deletion is also expensive with arrays until unless some special
techniques are used. For example, to delete 1010 in id[], everything
after 1010 has to be moved.

2. Polynomial Algebra is one of the application of linked list as follows:-


1. The biggest integer that we can store in a variable of the type int is
231 - 1 on 32-but CPU.If the value becomes too large, Java saves
only the low order 32 (or 64 for longs) bits and throws the rest
away.
2. In real life applications we need to deal with integers that are larger
than 64 bits (the size of a long). To manipulate with such big
numbers, we will be using a linked list data structure
3. The following numbers can also be expressed as below:- 937 =
910^2 + 310^1 + 710^0 and 2011 = 210^3 + 010^2 + 110^1 +
1*10^0
4. Now, if we replace a decimal base 10 by a character, say 'x', we
obtain a univariate polynomial, such as 0.45 - 1.89 x2 + 3.4 x5 + 9
x16. This can be saved using linked list as follows

Chap 3/ Linked Lists Over Arrays


2. What are the advantages of using linked lists
over arrays
Appeared in exams: Once

1. Following are the points in favour of Linked Lists.


1. The size of the arrays is fixed: So we must know the upper limit on
the number of elements in advance. Also, generally, the allocated
memory is equal to the upper limit irrespective of the usage, and in
practical uses, upper limit is rarely reached.
2. Inserting a new element in an array of elements is expensive,
because room has to be created for the new elements and to create
room existing elements have to shifted.
3. For example, suppose we maintain a sorted list of IDs in an array
id[]. id[] = [1000, 1010, 1050, 2000, 2040, …..]. And if we want to
insert a new ID 1005, then to maintain the sorted order, we have to
move all the elements after 1000 (excluding 1000).
4. Deletion is also expensive with arrays until unless some special
techniques are used. For example, to delete 1010 in id[], everything
after 1010 has to be moved.
5. In a linked list, new elements can be stored anywhere in the
memory unlike arrays where memory needs to be contiguous in
nature.
6. In array, Insertion and Deletion operation takes more time, as the
memory locations are consecutive and fixed whereas in case of
linked list, a new element is stored at the first free and available
memory location, with only a single overhead step of storing the
address of memory location in the previous node of linked
list.hence Insertion and Deletion operations are fast in linked list.
7. In arrays, Memory is allocated as soon as the array is declared, at
compile time whereas in linked list, Memory is allocated at
runtime, as and when a new node is added. It's also known as
Dynamic Memory Allocation.

Chap 3/ Single-Doubly Linked List


3. Write a program to implement Single Linked
List.Provide the following operations (i) Insert a
node at the specified location (ii) Delete a node from
end (iii) display the list
Appeared in exams: 3 times

# include <stdio.h>
# include <conio.h>
# include <stdlib.h>
typedef struct node
{
int data;
struct node* next;
}node;
node* create(int);
void print(node*);
int count(node*);
node* insertB(node*,int);
node* insertM(node*,int);
node* insertE(node*,int);
node* del(node*);
void main()
{
node *HEAD;
int n,number,ch,value;
clrscr();
printf("\n Enter no. of Item");
scanf("%d",&n);
HEAD=create(n);
do
{
printf("\n 1.Insert at Begining \n 2.Insert after a
specified value \n 3.Insert at End \n 4.DELETE \n 5.Display \n
6.Count \n 7.Exit \n");
printf("Enter your choice \n");
scanf("%d",&ch);
switch(ch)
{
case 1:
printf("Enter the value to be inserted");
scanf("%d",&value);
HEAD = insertB(HEAD,value);
break;
case 2:
printf("Enter the value to be inserted");
scanf("%d",&value);
HEAD = insertM(HEAD,value);
break;
case 3:
printf("Enter the value to be inserted");
scanf("%d",&value);
HEAD = insertE(HEAD,value);
break;
case 4:
HEAD=del(HEAD);
break;
case 5:
print(HEAD);
break;
case 6:
number = count(HEAD);
printf("Number of Nodes = %d",number);
break;
case 7:
printf("Exit");
break;
default:
printf("Invalid input \n");
}

}
while(ch!=7);
getch();
}
node* create(int n)
{
node *head,*P;
int i;
head=(node*)malloc(sizeof(node));
head->next=NULL;
printf("Enter your Data \n");
scanf("%d",(&head->data));
P=head;
for(i=1;i<n;i++)
{
P->next=(node*)malloc(sizeof(node));
P=P->next;
printf("Enter your Data \n");
scanf("%d",(&P->data));
P->next=NULL;
}
return(head);
}
void print(node *P)
{
while(P!=NULL)
{
printf("--%d--",P->data);
P=P->next;
}
}
int count(node *P)
{
int i=0;
while(P!=NULL)
{
P=P->next;
i++;
}
return(i);
}

node* insertB(node* HEAD,int x)


{
node* p;
p=(node*)malloc(sizeof(node));
p->data = x;
if(HEAD==NULL)
{
HEAD=p;
HEAD->next=NULL;
}
else
{
p->next=HEAD;
HEAD=p;
}
return(HEAD);
}
node* insertM(node* HEAD,int x)
{
node* p,*q;
int y;
p=(node*)malloc(sizeof(node));
p->data = x;
p->next = NULL;
printf("Insert after which number \n");
scanf("%d",&y);
q=HEAD;
while(q!=NULL && q->data!=y)
{
q=q->next;
}
if(q!=NULL)
{
p->next = q->next;
q->next = p;
}
else
{
printf("Data not found \n");
}
return(HEAD);
}
node* insertE(node* HEAD,int x)
{
node* p,*q;
p=(node*)malloc(sizeof(node));
p->data = x;
p->next = NULL;
if(HEAD==NULL)
{
return(p);
}
q=HEAD;
while(q->next!=NULL)
{
q=q->next;
}
q->next = p;
return(HEAD);
}
node* del(node * HEAD)
{
node *p,*q;
int e;
if(HEAD==NULL)
{
printf("Empty LL \n");
return(HEAD);
}
printf("Enter element to be deleted \n");
scanf("%d",&e);
flushall();
p=HEAD;
if(HEAD->data==e)
{
HEAD = HEAD->next;
free(p);
return(HEAD);
}

while(p!=NULL && (p->next)->data!=e)


{
p=p->next;
}
if( (p->next)->data!=e)
{
printf("Data not found");
return(HEAD);
}
else
{
q=p->next;
p->next=q->next;
free(q);
return(HEAD);
}

Chap 3/ Single-Doubly Linked List


4. Write a program to implement Doubly
LinkedList.perform the following operations (i)
Insert a node in the beginning (ii) Insert a node in
the End (iii)Delete a node from the End (iv) Display
t
Appeared in exams: 3 times

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
typedef struct Dnode
{
int data;
struct Dnode* next;
struct Dnode* prev;
}Dnode;
Dnode* create(int);
void print(Dnode*);
int count(Dnode*);
Dnode* insertB(Dnode*,int);
Dnode* insertM(Dnode*,int);
Dnode* insertE(Dnode*,int);
Dnode* del(Dnode*);
void main()
{
Dnode *HEAD;
int n,number,ch,value;
clrscr();
printf("\n Enter no. of Item");
scanf("%d",&n);
HEAD=create(n);
do
{
printf("\n 1.Insert at Begining \n 2.Insert after a
specified value \n 3.Insert at End \n 4.DELETE \n 5.Display \n
6.Count \n 7.Exit \n");
printf("Enter your choice \n");
scanf("%d",&ch);
switch(ch)
{
case 1:
printf("Enter the value to be inserted");
scanf("%d",&value);
HEAD = insertB(HEAD,value);
break;
case 2:
printf("Enter the value to be inserted");
scanf("%d",&value);
HEAD = insertM(HEAD,value);
break;
case 3:
printf("Enter the value to be inserted");
scanf("%d",&value);
HEAD = insertE(HEAD,value);
break;
case 4:
HEAD=del(HEAD);
break;
case 5:
print(HEAD);
break;
case 6:
number = count(HEAD);
printf("Number of Nodes = %d",number);
break;
case 7:
printf("Exit");
break;
default:
printf("Invalid input \n");
}

}
while(ch!=7);
getch();
}
Dnode* create(int n)
{
Dnode *head,*P,*Q;
int i;
head=(Dnode*)malloc(sizeof(Dnode));
head->next=NULL;
printf("Enter your Data \n");
scanf("%d",(&head->data));
P=head;
for(i=1;i<n;i++)
{
P->next=(Dnode*)malloc(sizeof(Dnode));
(P->next)->prev = P;
P=P->next;
printf("Enter your Data \n");
scanf("%d",(&P->data));
P->next=NULL;
}
return(head);
}
void print(Dnode *P)
{
while(P!=NULL)
{
printf("--%d--",P->data);
P=P->next;
}
}
int count(Dnode *P)
{
int i=0;
while(P!=NULL)
{
P=P->next;
i++;
}
return(i);
}
Dnode* insertB(Dnode* HEAD,int x)
{
Dnode* p;
p=(Dnode*)malloc(sizeof(Dnode));
p->data = x;
if(HEAD==NULL)
{
HEAD=p;
HEAD->next=NULL;
}
else
{
p->next=HEAD;
HEAD=p;
}
HEAD->prev=NULL;
return(HEAD);
}
Dnode* insertM(Dnode* HEAD,int x)
{
Dnode* p,*q;
int y;
p=(Dnode*)malloc(sizeof(Dnode));
p->data = x;
p->next = NULL;
p->prev = NULL;
printf("Insert after which number \n");
scanf("%d",&y);
q=HEAD;
while(q!=NULL && q->data!=y)
{
q=q->next;
}
if(q!=NULL)
{
p->next = q->next;
p->prev = q;
(p->next)->prev = p;
q->next = p;
}
else
{
printf("Data not found \n");
}
return(HEAD);
}
Dnode* insertE(Dnode* HEAD,int x)
{
Dnode* p,*q;
p=(Dnode*)malloc(sizeof(Dnode));
p->data = x;
p->next = NULL;
p->prev = NULL;
if(HEAD==NULL)
{
return(p);
}
q=HEAD;
while(q->next!=NULL)
{
q=q->next;
}
q->next = p;
p->prev = q;
return(HEAD);
}
Dnode* del(Dnode * HEAD)
{
Dnode *p,*q;
int e;
if(HEAD==NULL)
{
printf("Empty LL \n");
return(HEAD);
}
printf("Enter element to be deleted \n");
scanf("%d",&e);
flushall();
p=HEAD;
if(HEAD->data==e)
{
HEAD = HEAD->next;
free(p);
return(HEAD);
}

while(p!=NULL && (p->next)->data!=e)


{
p=p->next;
}
if( (p->next)->data!=e)
{
printf("Data not found");
return(HEAD);
}
else
{
q=p->next;
p->next=q->next;
(q->next)->prev = p;
free(q);
return(HEAD);
}

/ Linked List Application


Chap 3

5. Application of Linked List -Polynomial Addition


Appeared in exams: Once
1. Polynomial Algebra is one of the application of linked list as follows:-

1. The biggest integer that we can store in a variable of the type int is
231 - 1 on 32-but CPU.If the value becomes too large, Java saves
only the low order 32 (or 64 for longs) bits and throws the rest
away.
2. In real life applications we need to deal with integers that are larger
than 64 bits (the size of a long). To manipulate with such big
numbers, we will be using a linked list data structure
3. The following numbers can also be expressed as below:- 937 =
910^2 + 310^1 + 710^0 and 2011 = 210^3 + 010^2 + 110^1 +
1*10^0
4. Now, if we replace a decimal base 10 by a character, say 'x', we
obtain a univariate polynomial, such as 0.45 - 1.89 x2 + 3.4 x5 + 9
x16. This can be saved using linked list as follows

/ Linked List Application


Chap 3

6. Explain any one application of linked with an


example
Appeared in exams: Once

1. Linked list is used to implement Frame Management within Virtual


memory.
2. Virtual memory is a mapping of address space that allows a process to
execute without being completely in physical memory, the real memory
of the system.
3. A process running in virtual memory deals with virtual addresses. These
are addresses that seem like physical addresses to the process, but that
the system must translate before using.
4. Address translation takes place using a page table. Each process has its
own page table that maps pages of its virtual address space to frames in
physical memory.

5. When a process references a particular virtual address, the appropriate


entry in its page table is inspected to determine in which physical frame
the page resides. When a process references a virtual address not yet in a
frame, a page fault occurs and a frame is allocated in physical memory.

6. For Example of frame management consider two functions ; alloc_frame


and free_frame. The alloc_frame and free_frame functions employ a
linked list to maintain the frames that are available to be allocated.

7. The alloc_frame function retrieves the number of a free frame from a list
of available frames.
8. Given a specific page, this number is placed in the page table to indicate
in which physical frame the page is to reside. The free_frame function
accepts a frame number and places it back into the list of available
frames once a page has been removed from physical memory.
9. Both functions assume that before either function is called, the operating
system has inserted into the list all frames that it wishes to make
available. The example for circular lists later in this chapter addresses
what happens when allot frame is called and the list is empty.
10. A linked list is a good way to manage frames because frame allocation
involves frequent insertions and deletions, and these operations are
performed at the head of the list. The runtime complexity of both
alloc_fiame and free_frame is O(1) because the two functions simply
call list_rem_next and list_ins_next respectively, which are both O(1)
operations.
Chapter 4

Trees
Content

Binary Search Tree


Threaded Binary Tree
B Tree-B Tree
Tree Traversals Technique
Huffman Coding
AVL Tree
Applications Of Trees

/ Binary Search Tree


Chap 4

1. Define Binary Search Tree. Write algorithm to


implement insertion and deletion operation.
Definition: A binary tree is said to be a binary search tree if it is the empty
tree or

1. if there is a left-child, then the data in the left-child is less than the data
in the root,
2. if there is a right-child, then the data in the right-child is no less than the
data in the root, and every sub-tree is a binary search tree. // algorithm to
implement insertion operation in BST

Insertion in Binary Search Tree:

Check whether root node is present or not(tree available or not). If root


is NULL, create root node.
If the element to be inserted is less than the element present in the root
node, traverse the left sub-tree recursively until we reach T->left/T-
>right is NULL and place the new node at T->left(key in new node <
key in T)/T->right (key in new node > key in T).
If the element to be inserted is greater than the element present in root
node, traverse the right sub-tree recursively until we reach T->left/T-
>right is NULL and place the new node at T->left/T->right.

Algorithm for insertion in Binary Search Tree:

TreeNode insert(int data, TreeNode T) {


if T is NULL {
T = (TreeNode *)malloc(sizeof (Struct
TreeNode));
(Allocate Memory of new node and load the data
into it)
T->data = data;
T->left = NULL;
T->right = NULL;
} else if T is less than T->left {
T->left = insert(data, T->left);
(Then node needs to be inserted in left sub-
tree.So,
recursively traverse left sub-tree to find the
place
where the new node needs to be inserted)
} else if T is greater than T->right {
T->right = insert(data, T->right);
(Then node needs to be inserted in right sub-
tree
So, recursively traverse right sub-tree to
find the
place where the new node needs to be
inserted.)
}
return T;
}
// algorithm for implementing the delete operation in BST

Delete operation on binary search tree is more complicated, then add and
search. Basically, in can be divided into two stages:

search for a node to delete;


if the node is found, run delete algorithm.
Delete algorithm in detail:

Now, let's see more detailed description of a remove algorithm. First stage is
identical to algorithm for lookup, except we should track the parent of the
current node. Second part is trickier. There are three cases, which are
described below.

1. Node to be deleted has no children.

This case is quite simple. Algorithm sets corresponding link of the


parent to NULL and disposes the node. Example. Remove -4 from a
BST.

1. Node to be deleted has one child.

It this case, node is cut from the tree and algorithm links single child
(with it's subtree) directly to the parent of the removed node. Example.
Remove 18 from a BST.
1. Node to be deleted has two children.

This is the most complex case. To solve it, let us see one useful BST
property first. We are going to use the idea, that the same set of values
may be represented as different binary-search trees. For example those
BSTs:
contains the same values {5, 19, 21, 25}. To transform first tree into second
one, we can do following:

choose minimum element from the right subtree (19 in the example);
replace 5 by 19;
hang 5 as a left child.

The same approach can be utilized to remove a node, which has two children:

replace value of the node to be removed with found minimum. Now,


right subtree contains a duplicate!
apply remove to the right subtree to remove a duplicate.

/ Binary Search Tree


Chap 4

2. Traverse the binary tree into preorder, inorder


and postorder by giving its algorithm.
The preorder tree traversal’s algorithm is:-

Visit the node.

Traverse the left subtree.

Traverse the right subtree.

The inorder tree traversal’s algorithm is:-

Traverse the left subtree

Visit the node.

Traverse the right subtree.

The postorder tree traversal’s algorithm is:-

Traverse the left subtree.

Traverse the right subtree.

Visit the node.

The preorder traversal is: A-B-D-E-H-I-C-F-G

The inorder traversal is: D-B-H-I-E-A-C-G-F

The postorder traversal is: D-I-H-E-B-G-F-C


Chap 4/ Binary Search Tree
3. Construct the binary tree for the inorder and
post order traversal sequence given below: -
Inorder “INFORMATION”

Postorder “INOFMAINOTR”

Write a function to traverse a tree in postOrder


Binary tree construction:

Since, R is the last element in the post order sequence, R will be the root.

Elements to the left of R will be a part of left sub tree and the elements to the
right of R will be a part of right sub tree.

Further, F is the last element of post Order sequence in the left sub tree.

Hence, F will be the root element in this case.

Elements before F i.e. I and N will be a part of left sub tree and O will be a
part of right sub tree.

This process can be continued for the remaining elements to obtain the
resultant binary tree.

The steps mentioned above can be represented graphically as follows:


C++ function to traverse a tree in postOrder
voidBinarySearchTree::postOrder(node *ptr)
{
if (root == NULL)
{
cout<<"Tree is empty."<<endl;
return;
}
if (ptr != NULL)
{
postOrder(ptr->left);
postOrder(ptr->right);
cout<<ptr->info<<" ";
}
}

Chap 4/ Binary Search Tree


4. Write a program to implement Binary search
Tree. Show BST of the following 10, 5, 4,12, 15, 11,
3
Appeared in exams: 2 times

Program for BST


#include<stdio.h>
#include<stdlib.h>
struct node
{
int key;
struct node *left, *right;
};
struct node *newNode(int item)
{
struct node *temp = (struct node *)malloc(sizeof(struct
node));
temp->key = item;
temp->left = temp->right = NULL;
return temp;
}
void inorder(struct node *root)
{
if (root != NULL)
{
inorder(root->left);
printf("%d ", root->key);
inorder(root->right);
}
}
struct node* insert(struct node* node, int key)
{
if (node == NULL) return newNode(key);
if (key < node->key)
node->left = insert(node->left, key);
else
node->right = insert(node->right, key);
return node;
}
struct node * minValueNode(struct node* node)
{
struct node* current = node;
while (current->left != NULL)
current = current->left;
return current;
}
struct node* deleteNode(struct node* root, int key)
{
struct node* temp;
if (root == NULL) return root;
if (key < root->key)
root->left = deleteNode(root->left, key);
else if (key > root->key)
root->right = deleteNode(root->right, key);
else
{
if (root->left == NULL)
{
struct node *temp = root->right;
free(root);
return temp;
}
else if (root->right == NULL)
{
struct node *temp = root->left;
free(root);
return temp;
}
temp = minValueNode(root->right);
root->key = temp->key;
root->right = deleteNode(root->right, temp->key);
}
return root;
}
void main()
{
struct node *root = NULL;
root = insert(root, 50);
root = insert(root, 30);
root = insert(root, 20);
root = insert(root, 40);
root = insert(root, 70);
root = insert(root, 60);
root = insert(root, 80);
printf("Inorder traversal of the given tree \n");
inorder(root);
printf("\nDelete 20\n");
root = deleteNode(root, 20);
printf("Inorder traversal of the modified tree \n");
inorder(root);
printf("\nDelete 30\n");
root = deleteNode(root, 30);
printf("Inorder traversal of the modified tree \n");
inorder(root);
printf("\nDelete 50\n");
root = deleteNode(root, 50);
printf("Inorder traversal of the modified tree \n");
inorder(root);
getch();
}

Example
/ Threaded Binary Tree
Chap 4

5. Explain threaded Binary tree


Appeared in exams: 2 times

1. In a linked list representation of binary trees, there are more null links
than the node links. Such null links are replaced by pointers called as
threads, such a tree is called as Threaded Binary Tree.

2. A left null link of a node is replaced with the address of its in-order
predecessor.

3. A right null link of a node is replaced with the address of its in-order
successor.

4. Example

1. There are two types of Threaded Binary Trees:-

a. Single Threaded: each node is threaded towards either(right)' the in-


order predecessor or' successor.

b. Double threaded: each node is threaded towards both(left & right)' the
in-order predecessor and' successor.

/ Tree Traversals Technique


Chap 4

6. Explain different types of tree traversals


technique with examples. Also write recursive
function for each traversal technique
Appeared in exams: Once

1. To traverse a binary tree means to visit each node of the tree exactly
once in a systematic fashion.

2. Binary tree is non-linear data structure. Hence, we can’t traverse it like a


linked list is a sequential manner but it requires a different approach.

3. We mainly have three algorithms for traversing binary tree. A. Pre-order


Traversal

B. In-order Traversal

C. Post-order Traversal

4. Consider the Tree

1. Pre-order traversal:-To traverse a non-empty binary tree by pre-order


method, the following operations are performed recursively until all
nodes are visited: i. Visit the root node. ii. Traverse the left sub-tree
fully. iii. Traverse the right sub-tree.

The pre-order traversal of above tree is A,Q,W,Z,C,H,G,D


void printPreorder(struct Node* node)
{
if (node == NULL)
return;
/* first print data of node */
cout << node->data << " ";
/* then recur on left sutree */
printPreorder(node->left);
/* now recur on right subtree */
printPreorder(node->right);
}

2. In-order Traversal:- To traverse a non-empty binary tree by in-order


method, the following operations are performed recursively until all
nodes are visited:

i. Traverse the left sub-tree.

ii. Now, visit the root node.

iii. Then, finally traverse the right sub-tree.

The in-order traversal of the tree is Q, Z, W, C, A, H, D, G


void printInorder(struct Node* node)
{
if (node == NULL)
return;
/* first recur on left child */
printInorder(node->left);
/* then print the data of node */
cout << node->data << " ";
/* now recur on right child */
printInorder(node->right);
}

1. Post-Order traversal:- To traverse a non-empty binary tree by post-order


method, the following operations are performed recursively until all
nodes are visited:

i. Traverse the left sub-tree.

ii. Now, move to the right sub tree

iii. Then, finally visit the root node.

The post-order traversal of the tree is Z, C, W, Q, D, G, H, A


void printPostorder(struct Node* node)
{
if (node == NULL)
return;
// first recur on left subtree
printPostorder(node->left);
// then recur on right subtree
printPostorder(node->right);
// now deal with the node
cout << node->data << " ";
}

/ Huffman Coding
Chap 4

7. Adaptive Huffman coding:


1. In adaptive Huffman coding both the compression and the
decompression start with an empty Huffman tree.

2. No symbols are assigned codes and every new symbol is treated as a leaf
node with the same weight.

3. As new symbols are added, the tree is also updated such that the updated
tree is also a Huffman tree.

4. The first symbol is written on the output stream as it is. This symbol is
then added to the tree and a code is assigned to it.

5. The next time this symbol occurs, its current code is written on the
output stream and its frequency is incremented by

6.

7. Each time the symbols are processed, it has to be checked whether the
tree satisfies the Huffman properties.

8. The Huffman properly is that if we scan the tree, the frequency of


occurrence of symbols should decrease from right to left and from top to
bottom i.e. the symbol on top right position will have the highest
frequency and the one at the bottom left will have the lowest frequency.

9. This property is called as sibling property of Huffman tree.

Updating the Huffman tree:

1. The process of updating the tree starts always at the current node which
is a leaf S with f as it frequency of occurrence.

2. Every iteration has three steps:

• Compare S to its successors in the tree from left to right and bottom to top.
If the immediate successor has frequency (f + 1) or more then the nodes are
still in sorted order and swapping is not required. Otherwise some successors
of S have identical frequency f or smaller frequency. In such a case S should
be swapped with the last node in this group.

• Increment the frequency from f to f + 1. Also increase the frequency of all


its parents.

• If S becomes the root then the process stops otherwise the process repeats
with the parent of node S.
Drawbacks of Adaptive Huffman coding:

Count overflow:

• The frequency counts are accumulated and this field can overflow.
Normally the width of this field is 16 bits and can store a count up to 65535.

• The count of the root is monitored every time it is incremented.

• When the maximum count limit is reached, all the weights are revealed with
an integer division by 2.

• This is actually done by performing an integer division only on the leaf


nodes and updating the tree again.

• Sometimes it leads to violation of Huffman property and the tree needs to


be updated again.

Code overflow:

• Code overflow when many symbols are added to the tree and the tree grows
longer.

• The compressor has to find out the code for an input symbol S in the tree by
linear search method.

• If S is found in the tree, the compressor moves from node S back to root
thus building the code bit by bit.

• These bits have to be accumulated as they are transmitted in the reverse


order.

• When the tree gets longer, the codes get longer and if the field size is
exceeded, the program malfunctions.

• Another drawback of the Huffman coding is that the codes generated


contain integer no. of bits which adds redundancy to the data.
/ Huffman Coding
Chap 4

8. Explain extended huffman coding. What is the


advantage of extended Huffman coding?

Extended Huffman Coding:


In applications where the alphabet size is large, pmax is generally quite small,
and the amount of deviation from the entropy, especially in terms of a
percentage of the rate, is quite small.

However, in cases where the alphabet is small and the probability of


occurrence of the different letters is skewed, the value of pmax can be quite
large and the Huffman code can become rather inefficient when compared to
the entropy.

To overcome this inefficiency we use adaptive Huffman coding, the same can
be illustrated with the help of following example:

Consider a source that puts out iid letters from the alphabet A = {a1, a2, a3}
with the probability model P(a1) = 0.8, P(a2) = 0.02, and P(a3) = 0.18. The
entropy for this source is 0.816 bits/symbol. A Huffman code for this source
is shown in Table below

TABLE 1: The Huffman code.

LetterCodeword
a1 0
a2 11
a3 10

The average length for this code is 1.2 bits/symbol. The difference between
the average code length and the entropy, or the redundancy, for this code is
0.384 bits/symbol, which is 47% of the entropy. This means that to code this
sequence we would need 47% more bits than the minimum required.
Now for the source described in the above example, instead of generating a
codeword for every symbol, we will generate a codeword for every two
symbols. If we look at the source sequence two at a time, the number of
possible symbol pairs, or size of the extended alphabet, is 32 = 9. The
extended alphabet, probability model, and Huffman code for this example are
shown in Table below

TABLE 2: The extended alphabet and corresponding Huffman code.

LetterProbability Code
a1a1 0.64 0
a1a2 0.016 10101
a1a3 0.144 11
a2a1 0.016 10100
a2a2 0.0004 10100101
a2a3 0.0036 1010011
a3a1 0.1440 100
a3a2 0.0036 10100100
a3a3 0.0324 10100

The average codeword length for this extended code is 1.7228 bits/symbol.
However, each symbol in the extended alphabet corresponds to two symbols
from the original alphabet.

Therefore, in terms of the original alphabet, the average codeword length is


1.7228/2 = 0.8614 bits/symbol.

This redundancy is about 0.045 bits/symbol, which is only about 5.5% of the
entropy.

Advantage of extended Huffman coding

We see that by coding blocks of symbols together we can reduce the


redundancy of Huffman codes.

Chap 4 / Huffman Coding


9. Encode and decode the following sequence using
L-77wabbabrarbarracbac Give drawbacks of Lz-77
and Lz-78
Encoding the given sequence using L-77

Given Sequence: wabbabrarbarracbac

Consider the length of the window is 13 in which the size of search buffer is
7.

Size of look ahead buffer is 6. It is assumed that contents of search buffer are
already encoded.

Search buffer (First 7 bits)

Look ahead buffer (last 6 bits)

For ‘a’ in look ahead buffer, a match at maximum offset of 6 is obtained.

Offset (o) = 6

Length (l) = 1

Code = c(r)

Therefore, the triple is <6, 1, c(r)>

For ‘b’ in look ahead buffer, a match at maximum offset of 7 is obtained.


Offset (o) = 7

Length (l) = 1

Code = c(a)

Therefore, the triple is <7, 1, c(a)>

For ‘r’ in look ahead buffer, a match at maximum offset of 5 is obtained.

Offset (o) = 5

Length (l) = 1 + 1 =2

Now, in this case the actual length l = 2 because ‘r’ is following after the
match ‘r’ in search buffer. As ‘r’ is already encoded in the sequence the
modified length becomes 1 + 1 = 2 where additional length of 1 is for ‘r’
sequence in look ahead buffer.

Code = c(a)

Therefore, the triple is <5, 2, c(a)>

For ‘c’ in look ahead buffer, there is no match found in search buffer.

Offset (o) = 0

Length (l) = 0

Code = c(c)

Therefore, the triple is <0, 0, c(c)>


For ‘b’ in look ahead buffer, a match at maximum offset of 6 is obtained.

Offset (o) = 6

Length (l) = 2

Code = c(c)

Therefore, the triple is <7, 1, c(c)>

Hence, look ahead buffer is now empty and encoding is stopped.

The encoding triples are

<6, 1, c(r); 7, 1, c(a); 5, 2, c(a); 0, 0, c(c); 7, 1, c(c)>

Encoding the given sequence using L-78

Given Sequence: wabbabrarbarracbac

Output IndexEntry
<0, c(w)>1 w
<0, c(a)> 2 a
<0, c(b)> 3 b
<3, c(a)> 4 ba
<3, c(r)> 5 br
<2, c(r)> 6 ar
<4, c(r)> 7 bar
<0, c(r)> 8 r
<2, c(c)> 9 ac
<3, c(c)> 10 bac
Sequence: w a b ba bra r bar r ac bac

Drawbacks of L-77 compression technique:

This method assumes that a match is found around the window which is not
the case in practical applications.

Compression ratio can be improved only by increasing the size of search


window which increases the latency.

This method is not practically applicable as there is no definite data structure.

Drawbacks of L-78 compression technique:

The drawback of the L-78 algorithm is the memory size as the frequently
encountered symbols as well as the longer matches have to be stored as
entries in the dictionary.

If the dictionary is full then either the dictionary has to be restarted or some
of the entries have to be deleted.

/ Huffman Coding
Chap 4

10. What is the difference between Shannon Fano


Coding and Huffman Coding.
To generate a sequence of length m, using Huffman procedure requires
the entire code for all possible sequence of length ‘m’.

E.g If the original size was k, then the size of the codebook would be .
Taking reasonable value k =16 and m=20. It gives a codebook size of .
This is obviously not a viable option.

For Shannon Fano coding procedure we do not need to build the entire
codebook instead, we simply obtain the code for the tag corresponding
to a given sequence. It is entirely feasible to code sequenced of length
20 or much more.
We can’t make large m Huffman Coding because we can’t got rates
closer to maximum entropy.

Shannon Fano Coding is vice versa (exception for sources whole


probabilities are powers of two).

Shannon Fano coding is more complex then Huffman coding.

Huffman coding is not adoptable for changing input statistics. There is


need to preserve the tree.

It is much easier to ‘adapt arithmetic exists to changing input statistics.


All we need to do is estimate the probabilities of the input alphabet by
keeping a count of the letters as they are coded . No need to preserve the
tree in case of Shannon Fano Coding.

In Huffman there is need to generate a code a prior so separation of


modeling and coding procedures is not feasible with Huffman.

Shannon Fano coding has no need to generate a code a priori, Thus


property about to separate the modeling and coding procedures in a
manner that is not very feasible with Huffman Coding.

/ Huffman Coding
Chap 4

11. What is huffman coding? Construct the


huffman Tree and determine the code for each
symbol in the setence "Engineering"
Appeared in exams: 4 times

1. Huffman algorithm or Huffman coding is an entropy encoding


algorithm.

2. It is used widely for data compression (like Winzip Compression-


Winzip doesn’t use it but!)
3. Huffman coding is used in JPEG compression.

4. The key idea behind Huffman coding is to encode the most common
characters using shorter strings of bits than those used for less common
source characters.

5. It works by creating a binary tree stored in an array.

6. We also need to know the external path length (sum of all paths from
root to external node) and internal path length (sum of all paths from
root to internal node).

7. The Huffman Algorithm

Step 1: Create a leaf node for each character. Add the character and its
weight or frequency of occurrence to the priority queue.

Step 2: Repeat Steps 3 to 5 while the total number of nodes in the queue
is greater than 1

Step 3: Remove two nodes that have the lowest weight (or highest
priority)

Step 4: Create a new internal node by merging these two nodes as


children and with weight equal to the sum of the two nodes' weights.

Step 5: Add the newly created node to the queue.

8. Example
/ Huffman Coding
Chap 4

12. Design Huffman Code


For a source which generates letters from an alphabet with also
calculate entropy of the source.

SymbolsCodeword
01
1
000
0010
0011

Verification
SymbolsCodeword
01
1
000
0010
0011

Entropy = 2.122 bits/ symbol

/ Huffman Coding
Chap 4

13. Apply Huffman Coding for the word


MALAYALAM. Give the Huffman code for each
symbol
Appeared in exams: Once

1. Huffman Tree for Malayalam:


Length of Word 'Malayalam' = 9
2. Huffman code for each symbol
Chap 4/ Huffman Coding
14. Huffman code and minimum variance Huffman
code.
Design a minimum variance Huffman code for a source that
put out letter from an alphabet A={ } with .Find the entropy of
the source, avg. length of the code and efficiency. Also comment
on the difference between Huffman code and minimum
variance Huffman code.
i. The probabilities for each character are arranged in descending order and
by using Minimum variance Huffman coding, we obtained following
Huffman tree.

ii. Therefore, the codewords generated are as follows,

SymbolsCodeword
11
000
01
101
011
100

iii. Entropy:

Average length:

Where, = length of codeword.

Chap 4/ Huffman Coding


15. Calculate the entropy of the source. Also find
the huffman code with minimum variance.
A source emits letters A {, , , } with probabilities p () = 0.5, p ()
0. I5, p () = 0.25, p () = 0.10 calculate the entropy of the source.
Also find the huffman code with minimum variance.
p () = 0.5

p () = 0. I5

p () = 0.25

p () = 0.10

Huffman code using minimum variance

p(a1) 0.5 0.751


p(a2) 0.250.751
p(a3) 0.150.251
p(a4) 0.100.251
LetterProbabilityCodeNo. of bits
a1 0.5 00 2
a2 0.15 10 2
a3 0.25 01 2
a4 0.10 11 2

Average length:

L = ∑ P(i) x No. of bits

= 0.5 x 2 + 0.15 x 2 + 0.25 x 2 + 0.10 x 2

= 1 + 0.3 + 0.5 + 0.2

L = 2 bits/symbol

Entropy:

H = ()

= - 1/log⁡2 [0.5 log (0.5) + 0.15 log (0.15) + 0.25 log (0.25) + 0.10 log
(0.10)]

= -3.322 (-0.151 – 0.124 – 0.151 – 0.1)

H = 1.747 bits/symbol

/ AVL Tree
Chap 4

16. Short note on AVL Tree


1. Searching in a binary search tree is efficient if the heights of both left
and right sub-trees of any node are equal.However, frequent insertions
and deletions in a BST are likely to make it unbalanced.

2. The efficiency of searching is ideal if the difference between left and


right sub-trees of all the nodes in a binary search tree is at the most
one.This is the basic approach of AVL trees.

3. An AVL tree is a binary search tree which has the following properties:-

a. The sub-trees of every node differ in height by at most one.


b. Every sub-tree is an AVL tree.

c. Each node in the AVL Tree possesses any one of the following
properties:

d. A node is called left heavy, if the largest path in its left sub tree is one
level larger than the largest path of its right sub tree.

e. A node is called right heavy, if the largest path in its right sub tree is
one level larger than the largest path of its left sub tree.

f. The node is called balanced, if the largest paths in both the right and
left sub trees are equal.

4. Consider the following example of AVL tree where every left subtree
has a height one greater than each right subtree.

5. The motivation of AVL trees was to guarantee a height of log(n) so that


insertions and deletions always occur at O(log(n)).

6. A balanced factor is an integer which is associated with each node of the


tree. It indicates weather a tree is left-heavy (height of left subtree is
greater than that of right subtree), balanced (both subtress are of the
same height), or right-heavy(opposite of left-heavy).

7. Balance factor of a node = height othe left subtree - the height of the
right subtree
8. Each node of an AVL tree can have a balanced factor of -1, 0 or +1
only.

9. If the balanced factor’s magnitude exceeds 1after an operation such as


insertion or deletion, then balancing is required. This is done with the
help of rotations.

Chap 4/ AVL Tree


17. Explain AVL trees. Insert the following
elements in a AVL search tree: 63, 52, 49, 83, 92, 29,
23, 54, 13, 99
Appeared in exams: Once

1. An AVL tree is a binary search tree which has the following properties:-

a. The sub-trees of every node differ in height by at most one.

b. Every sub-tree is an AVL tree.

c. Each node in the AVL Tree possesses any one of the following
properties:

d. A node is called left heavy, if the largest path in its left sub tree is one
level larger than the largest path of its right sub tree.

e. A node is called right heavy, if the largest path in its right sub tree is
one level larger than the largest path of its left sub tree.

f. The node is called balanced, if the largest paths in both the right and
left sub trees are equal.

2. Consider the example


Chap 4/ AVL Tree
18. Insert the following elements in AVL tree:44,
17, 32, 78, 50, 88, 48, 62, 54.Explain different
rotations that can be used
Appeared in exams: Once

1. An AVL tree is a binary search tree which has the following properties:-
a. The sub-trees of every node differ in height by at most one.

b. Every sub-tree is an AVL tree.

c. Each node in the AVL Tree possesses any one of the following
properties:

d. A node is called left heavy, if the largest path in its left sub tree is one
level larger than the largest path of its right sub tree.

e. A node is called right heavy, if the largest path in its right sub tree is
one level larger than the largest path of its left sub tree.

f. The node is called balanced, if the largest paths in both the right and
left sub trees are equal.

2. Consider the Example


Chap 4/ AVL Tree
19. Insert the following elements in a AVL search
tree: 40, 23, 32, 84, 55, 88, 46, 71, 57 Explain
different rotations used in AVL trees
Appeared in exams: Once

1. AVL Search Tree is as follows


1. Following are the four Types of Rotations in AVL
/ Applications Of Trees
Chap 4

20. Short note on Splay Tree and Trie


Appeared in exams: 2 times

Splay Tree

1. Splay tree is another varient of binary search tree. In a splay tree, the
recently accessed element is placed at the root of the tree.
2. A splay tree is defined a self - adjusted Binary Search Tree in which
every operation on an element rearrange the tree so that the element is
placed at the root position of the tree.
3. In a splay tree, every operation is performed at root of the tree. All the
operations on a splay tree are involved with a common operation called
"Splaying".
4. Splaying an element is the process of bringing it to the root position by
performing suitable rotation operations.
5. In a splay tree, splaying an element rearrange all the elements in the tree
so that splayed element is placed at root of the tree.
6. With the help of splaying an element we can bring most frequently used
element closer to the root of the tree so that any operation on those
element performed quickly.
7. In a splay tree, to splay any element we use the following rotation
operations...
1. Zig Rotation
2. Zag Rotation
3. Zig - Zig Rotation
4. Zag - Zag Rotation
5. Zig - Zag Rotation
6. Zag - Zig Rotation

Tries

1. In computer science,tries is also called digital tree and sometimes radix


tree or prefix tree.
2. Tries is used for storing strings in order to support fast pattern matching.
3. Tries are used for information retrieval.Tries is used to store the
character in each node not the key.Path from root to node is associated
with key.
4. Tries uses character of a key to guide the search process.
5. All the descendants of the node have a common prefix of the string
associated with that node.
6. Following are the Types of Tries:

I. Standard Tries:

The standard tries for a set of strings S is an ordered tree such that:

a. Each node but the root is labeled with a character.

b. The children of a node are alphabetically ordered

c. The paths from the external nodes to the root yield the strings of S.

II. Compressed Tries:

1. Compressed Tries are with nodes of degree at least 2.


2. They are Obtained from standard tries by compressing chains of
redundant nodes.

III. Suffix Tries:

1. A suffix trie is a compressed trie for all the suffixes of a text.


2. The suffix trie for a text X of size n from an alphabet of size d.
3. Suffix tries stores all the n(n−1)/2 suffixes of X in O(n) space.
4. Suffix tries supports arbitrary pattern matching and prefixes matching
queries in O(dm) time, where m is the length of the pattern.

/ Applications Of Trees
Chap 4

21. Discuss some practical applications of trees


Appeared in exams: 2 times

1. Trees are extremely useful data structure with lots of practical


applications.Following are its few practical applications.
1. Binary Search Trees(BSTs) are used to quickly check whether an
element is present in a set or not.
2. Heap is a kind of tree that is used for heap sort.
3. A modified version of tree called Tries is used in modern routers to
store routing information.
4. Most popular databases use B-Trees and T-Trees, which are
variants of the tree structure we learned above to store their data
5. Compilers use a syntax tree to validate the syntax of every program
you write.
Chapter 5

Graphs
Content

Graph Traversal Technique


BFS Traversal
Topological Sorting

/ Graph Traversal Technique


Chap 5

1. Graph Traversal Technique


Appeared in exams: Once

1. Graphs can be traverse in two ways

a. BFS (Breadth First Search)

b. DFS(Depth First Search)

2. BFS

1.Breadth-first search starts at a given vertex “S”, which is at level 0.

2.In the first stage, we visit all the vertices that are at the distance of one
edge away.

3.When we visit there, we mark them as "visited," the vertices adjacent


to the start vertex s - these vertices are placed into level 1.

4.In the second stage, we visit all the new vertices we can reach at the
distance of two edges away from the source vertex “S”. These new
vertices, which are adjacent to level 1 vertices and not previously
assigned to a level, are placed into level 2, and so on.
5.The BFS traversal terminates when every vertex has been visited.

3. DFS

1.Depth First Search is like pre-order traversal of tree.

2.DFS can be started from any vertex and it continuous recursively until
all nodes are visited.

3.After visiting a node it is marked as visited so as to avoid re-visiting


the same node and avoid cycles.

4.Marking of nodes can be done by using a global array visited[] which


is initialed to 0.

5.Similarly all the remaining vertices are traversed.

4. Consider the example

BFS will visit the nodes in the following order: A, B, C, E,


D, F, G.
DFS will visit the nodes in the following order: A, B, D, F,
E, C, G.

/ Graph Traversal Technique


Chap 5

2. What is graph? Explain methods to represent


graph
Appeared in exams: 3 times
1. Graph is a non-linear data structure that is same as the mathematical
(discrete mathematics) concept of graphs.
2. It is a collection of nodes (also called as vertices) and edges that connect
these vertices.
3. Graphs are used to represent arbitrary relationship among objects.
4. A graph can be directed or undirected.

5. Consider the graph

G= (V, E)

V (G) = Vertices of Graph G

E (G) = Edges of Graph G

then,

V(G)={A,B,C,D,E,F}

E(G)={(AB),(AC),(BD),(BC),(DE),(DF),(EF)}

1. Graphs can be represented in two forms


a. Sequential Representation
b. Linked Representation
2. Sequential Representation

1.Graphs can be represented through matrix in systems memory.

2.This is sequential in nature.

3.This type of representation is called sequential representation of


graphs

4.Following are the types of sequential representation of graphs


a.Adjacent matrix representation
b.Path matrix representation

5.Adjacent matrix representation


a.The Adjacency matrix of a graph G with n vertices is N x
N.
b.It is given by A=[aij].
aij=1 if ith and jth vertices are adjacent.
=0 if ith and jth vertices are not adjacent.
c.Example

3. Linked Representation

1. A graph can be represented using a linked list.

2. It requires less amount of memory.

3. For each vertex, a list of adjacent vertices is maintained using a


linked list.
4. Adjacency list of a graph is represented by an array of pointers and
each pointer points to the respected linked list of vertex.

5. Example Consider the diagram

Adjacency list of a graph as shown below

Chap 5/ BFS Traversal


3. Write a program in C to implement the BFS
traversal of a graph. Explain the code with an
example
Appeared in exams: 2 times

BFS Traversal Program


#include<stdio.h>
#include<stdlib.h>
#define MAX 100
#define initial 1
#define waiting 2
#define visited 3
int n;
int adj[MAX][MAX];
int state[MAX];
void create_graph();
void BF_Traversal();
void BFS(int v);
int queue[MAX], front = -1,rear = -1;
void insert_queue(int vertex);
int delete_queue();
int isEmpty_queue();
int main()
{
create_graph();
BF_Traversal();
return 0;
}
void BF_Traversal()
{
int v;
for(v=0; v<n; v++)
state[v] = initial;
printf("Enter Start Vertex for BFS: \n");
scanf("%d", &v);
BFS(v);
}
void BFS(int v)
{
int i;
insert_queue(v);
state[v] = waiting;
while(!isEmpty_queue())
{
v = delete_queue( );
printf("%d ",v);
state[v] = visited;
for(i=0; i<n; i++)
{
if(adj[v][i] == 1 && state[i] == initial)
{
insert_queue(i);
state[i] = waiting;
}
}
}
printf("\n");
}
void insert_queue(int vertex)
{
if(rear == MAX-1)
printf("Queue Overflow\n");
else
{
if(front == -1)
front = 0;
rear = rear+1;
queue[rear] = vertex ;
}
}
int isEmpty_queue()
{
if(front == -1 || front > rear)
return 1;
else
return 0;
}
int delete_queue()
{
int delete_item;
if(front == -1 || front > rear)
{
printf("Queue Underflow\n");
exit(1);
}
delete_item = queue[front];
front = front+1;
return delete_item;
}
void create_graph()
{
int count,max_edge,origin,destin;
printf("Enter number of vertices : ");
scanf("%d",&n);
max_edge = n*(n-1);
for(count=1; count<=max_edge; count++)
{
printf("Enter edge %d( -1 -1 to quit ) : ",count);
scanf("%d %d",&origin,&destin);
if((origin == -1) && (destin == -1))
break;
if(origin>=n || destin>=n || origin<0 || destin<0)
{
printf("Invalid edge!\n");
count--;
}
else
{
adj[origin][destin] = 1;
}
}
}

1. Example of BFS

a. Consider below Graph as follows


b. The vertex 0 is the starting vertex in our case. We start our traversal
from the vertex 0. Then we will visit all vertices adjacent to vertex 0 i.e.,
1, 4, 3. Here, we can visit these three vertices in any order.

c. Suppose we visit the vertices in order 1,3,4.The traversal would be: 0


134

d. Now, we shall visit all the vertices adjacent to 1, then all the vertices
adjacent to 3 and then all the vertices adjacent to

e. So first we shall visit 2 (since it is adjacent to 1), then 6 (since it is


adjacent to 3) and 5, 7 (since these are adjacent to 3.

f. The traversal would be: 0 1 3 4 2 6 5 7

/ Topological Sorting
Chap 5

4. Explain Topological Sorting with example


Appeared in exams: Once

1. Topological sort: It id defined as an ordering of the vertices in a directed


acyclic graph, such that if there is a path from u to v, then v appears
after u in the ordering.

2. Types of graphs:

a. The graphs should be directed: otherwise for any edge (u,v) there
would be a path from u to v and also from v to u, and hence they cannot
be ordered.

b. The graphs should be acyclic: otherwise for any two vertices u and v
on a cycle u would precede v and v would precede u.

3. The algorithm for topological sort uses "indegrees" of vertices.

4. Complexity of this algorithm: O(|V|2), |V| - the number of vertices.


5. Algorithm

1. Compute the indegrees of all vertices

2. Find a vertex U with indegree 0 and print it (store it in the ordering)


If there is no such vertex then there is a cycle and the vertices
cannot be ordered. Stop.

3. Remove U and all its edges (U,V) from the graph.

4. Update the indegrees of the remaining vertices.


5. Repeat steps 2 through 4 while there are vertices to be processed.
6. Example

Compute the indegrees:


V1: 0
V2: 1
V3: 2
V4: 2
V5: 2
Find a vertex with indegree 0: V1
Output V1 , remove V1 and update the indegrees:
Sorted: V1
Remove edges: (V1,V2) , (V1, V3) and (V1,V4)
Updated indegrees:
V2: 0
V3: 1
V4: 1
V5: 2
The process is depicted in the following table:
One possible sorting: V1, V2, V4, V3, V5
Another sorting: V1, V2, V4, V5, V3
Chapter 6

Sorting and Searching


Content

Sorting Method
Indexed Sequential Search
Hashing
Binary Search

/ Sorting Method
Chap 6

1. Write a program in C to implement Insertion


Sort
Appeared in exams: Once

#include<stdio.h>
#include<conio.h>
void insertion(int a[],int n)
{
int i,j,x,k;
for(i=1;i<=n-1;i++)
{ x=a[i];
for(j=i;a[j-1]>x && j>0;j=j-1)
{
a[j]=a[j-1];
}
a[j]=x;
printf("\n\n The array after pass no.%d: ",i);
for(k=0;k<=n-1;k++)
{
printf("%4d",a[k]);
}
}//end of outer for loop.
} //end of insertion function.
void main()
{
int a[1000],n,i;
printf("\n\nEnter an integer value for total no.s of
elements to be sorted: ");
scanf("%3d",&n);
for(i=0;i<=n-1;i++)
{
printf("\n\nEnter an integer value for element no.%d:
",i+1);
scanf("%4d",&a[i]);
}
insertion(a,n);
printf("\n\n\nFinally sorted array is : ");
for(i=0;i<=n-1;i++)
{
printf("%4d",a[i]);
}
}//end program.

Chap 6/ Sorting Method


2. Compare Quick Sort and Radix Sort based on
their advantages and disadvantages
Appeared in exams: Once
/ Sorting Method
Chap 6

3. Write a program in C to perfrom Quick sort.


Show steps with example
Appeared in exams: 2 times

1. Program for Quick Sort


#include<stdio.h>
#include<conio.h>
void swap(int* a, int* b)
{
int t = *a;
*a = *b;
*b = t;
}
int partition (int arr[], int low, int high)
{
int pivot = arr[high]; // pivot
int i = (low - 1); // Index of smaller element
int j;
for (j = low; j <= high- 1; j++)
{
// If current element is smaller than or
// equal to pivot
if (arr[j] <= pivot)
{
i++; // increment index of smaller element
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]);
return (i + 1);
}
void quickSort(int arr[], int low, int high)
{
if (low < high)
{
int pi = partition(arr, low, high);
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
void printArray(int arr[], int size)
{
int i;
for (i=0; i < size; i++)
printf("%d ", arr[i]);
printf("\n");
}
void main()
{
int arr[] = {4, 7, 8, 9, 1, 5};
int n = sizeof(arr)/sizeof(arr[0]);
clrscr();
printf("Unsorted array: \n");
printArray(arr, n);
quickSort(arr, 0, n-1);
printf("\nSorted array: \n");
printArray(arr, n);
getch();
}

2. Step by Step Example for Quick Sort a. Consider the unsorted values
{25, 13, 7, 34, 56, 23, 13, 96, 14, 2} with first element as pivot element
i.e 25 is pivot
b. Hence after quick sort the sorted array becomes 2, 07, 13, 13, 14, 23, 25,
34, 56, 96

/ Sorting Method
Chap 6

4. Write a program in C to implement Merge Sort.


Appeared in exams: Once
#include<stdio.h>
#include<conio.h>
void mergeSort(int [], int, int, int);
void partition(int [],int, int);
void main()
{
int list[50];
int i, size;
printf("Enter total number of elements:");
scanf("%d", &size);
printf("Enter the elements:\n");
for(i = 0; i < size; i++)
{
scanf("%d", &list[i]);
}
partition(list, 0, size - 1);
printf("After merge sort:\n");
for(i = 0;i < size; i++)
{
printf("%d ",list[i]);
}
getch();
}
void partition(int list[],int low,int high)
{
int mid;
if(low < high)
{
mid = (low + high) / 2;
partition(list, low, mid);
partition(list, mid + 1, high);
mergeSort(list, low, mid, high);
}
}
void mergeSort(int list[],int low,int mid,int high)
{
int i, mi, k, lo, temp[50];
lo = low;
i = low;
mi = mid + 1;
while ((lo <= mid) && (mi <= high))
{
if (list[lo] <= list[mi])
{
temp[i] = list[lo];
lo++;
}
else
{
temp[i] = list[mi];
mi++;
}
i++;
}
if (lo > mid)
{
for (k = mi; k <= high; k++)
{
temp[i] = list[k];
i++;
}
}
else
{
for (k = lo; k <= mid; k++)
{
temp[i] = list[k];
i++;
}
}
for (k = low; k <= high; k++)
{
list[k] = temp[k];
}
}

/ Sorting Method
Chap 6

5. What is heap? Sort the following numbers using


heap sort. 67, 12, 89, 26, 38, 45, 22, 79, 53
Appeared in exams: 2 times

1. A heap is a special kind of tree-based data structure.


2. A heap is a complete binary tree in which every node satisfies the Heap
property which states that: “The node_value(A) ≥ node_value(B) where
B is a Child of A”
3. This means that at elements at every node will be having a value greater
than or equal to its parent element. That means, the root node will be
having the highest value in the tree.
4. Such kind of tree is popularly called as max-heap.
5. A tree which works in exactly the opposite fashion of the above
mentioned property is called as min-heap.
6. The root element of a min-heap will be having the lowest value.
7. Consider the array " 67, 12, 89, 26, 38, 45, 22, 79, 53"

Step 1: Build a heap using elements of array

Step 2:Repeatedly delete the Root element of the heap created


Chap 6/ Indexed Sequential Search
6. Write a program in C to search a list using
indexed sequential search.What are the advantages
of indexed sequential search over sequential search.
Appeared in exams: Once

1. In Index sequential searching technique, first of all an index file is


created that contains references to a group of records,.
2. Once an index is obtained, the partial searching takes less time since it is
to be located in the group/bucket specified by the index.
3. The program given below creates an index file for the employee records
by grouping the records and then locates the required key by searching
the index first and then returns the required record.
4. The advantage of indexed sequential over sequential is that here we can
achieve both sequential as well as Random access (i.e. jump directly to a
record from the index value).
5. Moreover, it is faster than sequential method.

6. The program to implement indexed sequential search is given below


/*Indexed Sequential Search*/
#include <stdio.h>
#include <conio.h>
#define MAX 5
struct mainfile
{
int empid;
char name[25];
float basic;
};
struct indexfile
{
int index_id;
int kindex;
};
void main()
{
struct mainfile fobj[MAX];
struct indexfile index[MAX];
int i, num, low, high, ct = 4;
float basicsal;
for (i = 0;i < MAX;i++)
{
printf("\nEnter employee id?");
scanf("%d", &fobj[i].empid);
printf("\nEnter name?");
scanf("%s", fobj[i].name);
printf("\nEnter basic?");
scanf("%f", &basicsal);
fobj[i].basic = basicsal;
}
printf("\nNow creating index file...!");
for (i = 0;i < (MAX / 5);i++)
{
index[i].index_id = fobj[ct].empid;
index[i].kindex = ct;
ct = ct + 5;
}
printf("\n\nEnter the empid to search?");
scanf("%d", &num);
for (i = 0;(i < MAX / 5) && (index[i].index_id <=
num);i++);
low = index[i-1].kindex;
high = index[i].kindex;
for (i = low;i <= high;i++)
{
if (num == fobj[i].empid)
{
printf("\nThe record is: \n\t");
printf("\nEmpid: %d", fobj[i].empid);
printf("\nName: %s", fobj[i].name);
printf("\nBasic: %f", fobj[i].basic);
getch();
}
}
printf("\nNumber not found...!");
}

/ Indexed Sequential Search


Chap 6

7. Write a function to implement indexed


Sequential Search, Explain with an Example
Appeared in exams: Once

1. Consider the example as follows


1. In the above diagram, if the user wants to search for "01235" data, then
instead of searching in entire data store only subsection of datastore is
searched.i.e Section A
2. This subsection is selected based on the key value generated while
searching.

3. Following is the program for Indexed Sequential Search


/*Indexed Sequential Search*/
#include <stdio.h>
#include <conio.h>
#define MAX 5
struct mainfile
{
int empid;
char name[25];
float basic;
};
struct indexfile
{
int index_id;
int kindex;
};
void main()
{
struct mainfile fobj[MAX];
struct indexfile index[MAX];
int i, num, low, high, ct = 4;
float basicsal;
for (i = 0;i < MAX;i++)
{
printf("\nEnter employee id?");
scanf("%d", &fobj[i].empid);
printf("\nEnter name?");
scanf("%s", fobj[i].name);
printf("\nEnter basic?");
scanf("%f", &basicsal);
fobj[i].basic = basicsal;
}
printf("\nNow creating index file...!");
for (i = 0;i < (MAX / 5);i++)
{
index[i].index_id = fobj[ct].empid;
index[i].kindex = ct;
ct = ct + 5;
}
printf("\n\nEnter the empid to search?");
scanf("%d", &num);
for (i = 0;(i < MAX / 5) && (index[i].index_id <=
num);i++);
low = index[i-1].kindex;
high = index[i].kindex;
for (i = low;i <= high;i++)
{
if (num == fobj[i].empid)
{
printf("\nThe record is: \n\t");
printf("\nEmpid: %d", fobj[i].empid);
printf("\nName: %s", fobj[i].name);
printf("\nBasic: %f", fobj[i].basic);
getch();
}
}
printf("\nNumber not found...!");
}

Chap 6 / Hashing
8. What is hashing ? What is mean by collision?
Using modulo division method insert the following
values in a hash table of size 10. Show how many
collisions occurred. 99, 33, 23, 44, 56, 43, 19
Appeared in exams: Once

1. Hashing is a technique by which updating or retrieving any entry can be


achieved in constant time O(1).
2. In mathematics, a map is a relationship between two sets. A map M is a
set of pairs, where each pair is in the form of (key, value).
3. For a given key, its corresponding value can be found with the help of a
function that maps keys to values. This function is known as the hash
function.
4. So, given a key k and a hash function h, we can compute the
value/location of the value v by the formula v = h(k).
5. Hash function is a division modulo operation, such as h(k)=k mod size,
where size is the size of the data structure that holds the values.
6. Collision is the event of two keys hashing to the same location.
7. A collision can be dealt with by a. linear probing (looking at the next
available location-i+1, i+2,…), b. quadratic probing (same as linear
probing with quadratic spaces-i+1, i+4, i+9,…) and c. chaining (process
of creating a linked list of values if they hash into the same location)
8. The following is the solution to the given hashing problem:-
99 mod 10 is 9. Since it’s vacant, 99 gets stored at position 9.

33 mod 10 is 3. Since it’s vacant, 33 gets stored at position 3.

23 mod 10 is 3. Since 3 is already occupied by 33, 23 gets stored at the next


available location, 4. (1 collision)

44 mod 10 is 4. Since 4 is already occupied by 23, 44 gets stored at the next


available location, 5. (1 collision)

56 mod 10 is 6. Since it’s vacant, 56 gets stored at position 6.

43 mod 10 is 3. Since 3 is already occupied by 33, 43 gets stored at the next


available location, 7. (4 collisions)

19 mod 10 is 9. Since it is already occupied by 99, 19 gets stored at the next


available location, 0. (1 collision)

/ Hashing
Chap 6

9. What is hashing and what are different hashing


functions. OR Short note on hashing.
Hash Table is a data structure which stores data in an associative manner. In a
hash table, data is stored in an array format, where each data value has its
own unique index value. Access of data becomes very fast if we know the
index of the desired data.

Thus, it becomes a data structure in which insertion and search operations are
very fast irrespective of the size of the data. Hash Table uses an array as a
storage medium and uses hash technique to generate an index where an
element is to be inserted or is to be located from.

Hash function

A hash function is any function that can be used to map a data set of an
arbitrary size to a data set of a fixed size, which falls into the hash table. The
values returned by a hash function are called hash values, hash codes, hash
sums, or simply hashes.

Different Hashing Functions:

Division Method: It is the most simple method of hashing an integer x.


This method divides x by M and then uses the remainder obtained. In
this case, the hash function can be given as h(x) = x mod M.

The division method is quite good for just about any value of M and
since it requires only a single division operation, the method works very
fast. However, extra care should be taken to select a suitable value for
M.

Multiplication Method:

This method has following steps:

Step 1: Choose a constant A such that 0 < A < 1.

Step 2: Multiply the key k by A.


Step 3: Extract the fractional part of kA.

Step 4: Multiply the result of Step 3 by the size of hash table (m).

Hence, the hash function can be given as:

h(k) = I m (kA mod 1) ˚

where (kA mod 1) gives the fractional part of kA and m is the total
number of indices in the hash table.

Mid-Square Method:

The mid-square method is a good hash function which works in two


steps:

Step 1: Square the value of the key. That is, find k2.

Step 2: Extract the middle r digits of the result obtained in Step 1.

The algorithm works well because most or all digits of the key value
contribute to the result. This is because all the digits in the original key
value contribute to produce the middle digits of the squared value.

Therefore, the result is not dominated by the distribution of the bottom


digit or the top digit of the original key value. In the mid-square method,
the same r digits must be chosen from all the keys. Therefore, the hash
function can be given as: h(k) = s where s is obtained by selecting r
digits from k2.

Folding Method: The folding method works in the following two steps:

Step 1: Divide the key value into a number of parts. That is, divide k
into parts k1, k2, ..., kn, where each part has the same number of digits
except the last part which may have lesser digits than the other parts.

Step 2: Add the individual parts. That is, obtain the sum of k1 + k2 + ...
+ kn. The hash value is produced by ignoring the last carry, if any.
Note that the number of digits in each part of the key will vary depending
upon the size of the hash table. For example, if the hash table has a size of
1000, then there are 1000 locations in the hash table.

To address these 1000 locations, we need at least three digits; therefore, each
part of the key must have three digits except the last part which may have
lesser digits.

Chap 6 / Hashing
10. Using Linear probing and Quadratic probing,
insert the following values in the hash table of size
10.Show how many collisions occur in each
iterations 28, 55, 71, 67, 11, 10, 90, 44
Appeared in exams: 2 times

1. Linear Probing

1. Quadratic Probing
Chap 6/ Hashing
11. Hash the following in a table of size 11. Use any
two collision resolution techniques: 23, 55, 10, 71,
67, 32, 100, 18, 10, 90, 44.
Appeared in exams: Once

1. Linear Probing
1. Quadratic Probing
/ Binary Search
Chap 6

12. Implement the binary search, and derive its


complexity.
1. If the array is arranged in ascending or descending order, several
searching techniques are available that can be that can be used to
improve search efficiency.
2. Of all there techniques, Binary search is most commonly used. Binary
search starts by initializing low to 0 and high to n-1 where n is the
number of elements in the original array
3. In each parce of binary search the key is searched at position mid where
mid is evaluated as mid= (low+high)/2.That is the key is always
compared with the middle element.
4. If the required key is present at position mid, then search stops.
Otherwise low changes to mid+1 if key is greater than middle element
or high changes to mid-1 if key is lesser than the middle element.
5. Every pass of binary search reduces the number of candidates by the
factor of 2, hence the name binary.

6. Program to demonstrate binary search //Assume that the array is sorted


in ascending order
Import.java.io.*;
Class BinarySearch
{
public static void main(String args[]) throws IOException
{
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader stdin = new BufferedReader(isr);
int i, n ,key;
System.out.println(“Enter the number of elements:”);
n=Integer.parseInt(stdin.readLine());
int x[] = new int[n];
System.out.println(“Enter the elements:”);
for (i=0;i<n;i++)
x [i] = Integer.parseInt(stdin.readLine());
System.out.println(“Enter the elements to be searched:”);
key = Integer.parseInt(stdin.readLine());
i=binary(x, key, 0, n-1);
if(i==1)
System.out.println(key+“not found”);
else
System.out.println( key+“ found at position “+i);
}
public static int binary(int x[], int key, int low, int
high)
{
Int mid;
if(low>high)
return(-1);
mid=(low+high)/2;
if(key==x[mid])
return(mid)
else
if(key<x[mid])
return(binary(x,key,low,mid-1));
else
return(binary(x,key,mid+1,high));
}
}

Deriving Complexity of binary search:

Consider I, such that 2i>= (N+1)


Thus, 2i-1-1 is the maximum number of comparisons that are left with
first comparison.
Similarly 2i-2-1 is maximum number of comparisons left with second
comparison.
In general we say that 2i-k-1 is the maximum number of comparisons
that are left after ‘k’ comparisons. If the number of elements are left then
the desired data item is obtained by ith comparisons.

Thus, the maximum number of comparisons required for successful


search is:

For unsuccessful search, the maximum number of comparisons:

Cms = Cmv

for, computing average number of comparisons ‘Cs’ indicates successful


search.

Now, consider that the probability for searching a requested data item is
1/n, then,

It can be easily observed that for successful and unsuccessful search the
expected number of cases is given by:

It should be noted that Binary Search provides to be more efficient than


the sequential search. But when implemented with linked lists it would
not be efficient.

On the basis of the above analysis the time complexity of Binary Search
is:

E(n) = [log2 n] +1, it is actually 2E(a) >n, that is O(log2 n).

Chap 6/ Binary Search


13. Write a program to implement Binary search
on sorted set of integers
Appeared in exams: Once

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
void main()
{
int n,i,search,f=0,low,high,mid,a[100];
clrscr();
printf("Enter the size of array");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("Enter a[%d] ",i);
scanf("%d",&a[i]);
}
printf("Enter the search element:");
scanf("%d",&search);
low=0;
high=n-1;
while(low<=high)
{
mid=(low+high)/2;
if(search<a[mid])
{
high=mid-1;
}
else if(search>a[mid])
{
low=mid+1;
}
else
{
f=1;
printf("Element found at %d:",mid);
exit(1);
}
}
if(f==0)
{
printf("not present");
}
getch();
}
Congratulations! you've done it.

Hope you found this book useful. We'd love to hear your comments. Just
send them over to helpdesk@ques10.com .

Question papers included

• "+ lesson_no +" • "+ seq_num +"


" + answer_block.html() + "
"); if( !answer_block.html().match('Found repeated in ') ) {
answer_block.html("

Answer:

— Found repeated in "+ paper_year + " • "+ lesson_no +" • "+ seq_num
+"

"); } } else { elem_paper.after("NOT FOUND!"); }


elem_paper.siblings(".paper-ques-desc").wrap(""); } else {
elem_paper.after("Not mapped"); } }); function
get_seq_num(paper_year, lesson_no) { if(typeof chap_seq_obj ===
"undefined") { chap_seq_obj = { "Chap 1": 0, "Chap 2": 0, "Chap 3":
0, "Chap 4": 0, "Chap 5": 0, "Chap 6": 0, "Chap 7": 0, "Chap 8": 0,
"Chap 9": 0, "Chap 10": 0, "Chap 11": 0, "Chap 12": 0, "Chap 13": 0,
"Chap 14": 0, "Chap 15": 0 } } var key = paper_year + " " + lesson_no;
if(typeof chap_seq_obj[key] === "undefined") { chap_seq_obj[key] = 0;
} return ++chap_seq_obj[key] } // Arrange questions chapter-wise within
paper var chap_seq_arr = ['Chap 1', 'Chap 2', 'Chap 3', 'Chap 4', 'Chap
5', 'Chap 6', 'Chap 7', 'Chap 8', 'Chap 9', 'Chap 10', 'Chap 11', 'Chap
12', 'Chap 13', 'Chap 14', 'Chap 15',]; $(".papers-
page").each(function(k,v) { $(v).append("
Solution to the paper
"); $.each(chap_seq_arr, function(k1,v1) { var this_lessno =
$(v).find(".paper-question .lessno:contains('"+ v1 +"')");
if(this_lessno.length > 0) { var cflag = true; $.each(this_lessno,
function(k2, v2){ var this_question = $(v2).closest('.paper-question');
if(this_question.html().indexOf("Found repeated") 0) { if(cflag) {
$(v).append("

"+ v1 + ": " + $(".lesson-no:contains('"+ v1 +"')").siblings(".lesson-


heading").text() || "" +"

"); cflag = false; } $(v).append(this_question.html());


this_question.find(".answer-block").html("

— " + this_question.find(".bubble.right").text() + "

"); } this_question.find(".bubble.right").remove(); }) } }); // create


papers box on last page $(".qp-included-wrapper").append("

" + $(v).find("h2 .paper-header").text().split("-")[1].trim() + "

"); // create link to the paper header $(v).find("h2 .paper-


header").html(""+ $(v).find("h2 .paper-header").text() +""); }); // show
papers and hide lessons $(".qp-included-
wrapper").removeClass("hide"); $('.lesson-container').addClass('hide');
} else if(print_type == "chapwise") { // if not solutions // remove repeated
topic names $(".question-block p:contains('Subject')").remove();
$(".question-block p:contains('subject')").remove(); // remove question
metadata from older questions $(".question-block p:contains('Mumbai
University')").remove(); $(".question-block p:contains('Mumbai
university')").remove(); $(".question-block p:contains('mumbai
university')").remove(); $(".question-block
p:contains('Year')").remove(); $(".question-block
p:contains('year')").remove(); // Map questions in QP to lessons
$(".paper-page-id").each(function(k,v){ var elem_paper = $(v); var
page_id = $.trim(elem_paper.text()); if(page_id != "00") { var elem_ques
= $("div[data-page-id="+ page_id +"]"); if(elem_ques.length > 0) { var
lesson_no = elem_ques.siblings(".lesson-no").text(); var ques_no =
elem_ques.find(".qno").text().replace(")", ""); elem_paper.after(""+
lesson_no +""+ ques_no +""); } else { elem_paper.after("NOT
FOUND!"); } } else { elem_paper.after("Not mapped"); } }); } });

You might also like