Sie sind auf Seite 1von 26

Vidyalankar

S.E. Sem. III [CMPN]


Data Structures & Files
Prelim Question Paper Solutions
1. (a) Recursion is the process of defining something in terms of itself. It is the attribute that allows a
method to call itself. A method that calls itself is said to be recursive.

Tower of Hanoi
The problem can be defined as follows: -
There are three pegs say A, B and C and n discs of different radii. All the n discs are stored in peg
A with the increasing radii from top to bottom. The aim is to shift all n discs from peg A to peg B
but by obeying the following rules:
1) Only one disc can be moved at a time.
2) Only disc at the top of the peg can be moved.
3) A disc with larger radii should not be kept on a disc with lower radii at any point of time.
The problem can be conveniently solved using recursion as given below:-
import java.util.*;
class TowerOfHanoi
{
public void hanoi (int n, char from, char to, char aux)
{
if (n==1)
System.out.println("Move a disc from peg "+from+" to peg "+to);
else
{
hanoi(n-1, from, aux, to);
hanoi(1, from, to, aux);
hanoi(n-1, aux, to , from);
}
}
}
class TowerExp
{
public static void main(String args[ ])
{
Scanner src=new Scanner(System.in);
System.out.println("Enter no of discs");
int num=src.nextInt();
TowerOfHanoi obj=new TowerOfHanoi();
obj.hanoi(num,'A','B','C');
}
}

Here the user has to give the number of disc and depending on that the program will display the
required moves. The sample output is shown for 3 discs.
Sample Output :
Enter no of discs
3
Move a disc from peg A to peg B
Move a disc from peg A to peg C
Move a disc from peg B to peg C
Move a disc from peg A to peg B
Move a disc from peg C to peg A
(2) Vidyalankar : S.E. – DSF

Move a disc from peg C to peg B


Move a disc from peg A to peg B

1. (b) Data Structure


Data Structure is the way of organizing data in such a way that the retrieval of data becomes
convenient.
The journey of data structures start from fundamental−data types as they are the first facility
provided by the language to store data. Due to the increasing needs and the size and variety of
data, data structures have gone ahead with derived data types, linear and finally non-linear data
structures. Let us take a brief look on the various types of data structures.

Types of Data Structures


1) Primitive Data Structures
These are the default data types provided by the specific language. For example, C language
provides int, float, char etc., which can be used to store simple primary level data. For basic
programming, these data types are more than sufficient for the management of data but as the
level of programming increases, these data types normally are not used directly but are
combined to form more complex data structures of the different types. We also form array
and structures from these primitive types that are known as derived data types.

2) Linear Data Structures


The data structure where all the elements are stored in a linear sequence is known as Linear
Data Structures. Here all elements are of same hierarchy or level. For example, array and
structure falls under the linear category. Stack, queue, linked list which are also considered as
linear data structures.
Such data structures are limited when the system only uses same level of data. But in many
situations we require to store data with hierarchy or level, for example directory structure. In
such cases we need to take the help of non-linear data structures.

3) Non-Linear Data Structures


The data structure in which the data is stored with hierarchy is known as Non-Linear Data
Structure. All elements in this are not at the same level. These are very useful when we have
to store data with precedence or hierarchy. Some non-linear data structures are binary tree
and graph.
The various operations performed on the data structures are as follows:-
1) Traversing – The process of visiting each and every element of a data structure.
2) Insertion – Adding new elements to the set of existing elements of a data structure.
3) Deletion – Removing the existing elements from a data structure.
4) Sorting – Arranging the elements of the data structure in the given order or sequence.
5) Searching – Finding the required element in the set of elements of a data structure.

2. (a) Hashing
Hashing is one of the most efficient searching techniques. But it uses large amount of extra space.
It uses a hash function and creates its own hash table from the set of input values. Using the hash
function, the position of the original value (key) within the hash table is calculated. While
searching, the search element is also hashed using hash function to get the hash key. Then the
corresponding hash table entry is checked. If the value is present then we declare success other
wise failure. But this can happen only in the absence of collision which is a rare case. A collision
occurs when two or more keys hashed to same hash key. This problem is handled by any of the
collision handling techniques available. The important terms used in the concept of hashing
are :
1) Hash Table : - It is the array which stores the input elements according to their hash keys.
2) Hash Function : - It is the function used to convert an input value into its corresponding hash
key which indicates the place for that key in the hash table. So if k is the original key and ‘h’
is the hash function then h(k) is its hash key. One would like to have a hash function which is
easy to compute and even capable of generating non-colliding hash keys.
Prelim Question Paper Solutions (3)

3) Collision : - The collision occurs when two or more keys are hashed to the same hash key.
Suppose k1 and k2 are two keys such that h(k1) = h(k2) then they result in collision. Its quite
obvious that two keys cannot be stored at the same place in the hash table, hence the first key
arriving is stored at the proper place and the place of the second key is decided by the
‘Collision Handling Technique’ used.
Some examples of Hash Functions :
1) Mid square : This function is calculated by squaring the original key and then selecting
appropriate number of bits from the middle of the squared number to obtain the hash key. The
number of bits to select depends on the size of the hash table. If ‘k’ bits are selected then the
size of hash table is required to be a minimum of 2k. The size of the hash table has to be a
power of 2 if this procedure is adopted.
We can even select the middle digits to form the hash key. So if we decided to select ‘k’
digits then the hash table size should be 10k.
For E.g.- Original Key = 23 Square = 529 Hash Key = 05
Original Key = 45 Square = 2025 Hash Key = 20

2) Modulo N: In this method we use a simple division technique. We decide a number N for
division. Each key is divided by N and the remainder obtained is used as the hash key. If k is
the original key then the function can be defined as follows.
h(k) = h % N
This will result in hash keys ranging from 0 to N-1 and hence needs to have hash table with
size N. Preferably a prime number is selected as N.
For E.g.- Suppose N = 13
Original Key = 23 Hash Key = 10
Original Key = 45 Hash Key = 06

3) Folding: In this method, the original element is partitioned into several equal parts except the
last one. These parts are then added together to form the hash key for that element. There are
two ways for doing that addition namely shift folding and folding at the boundaries. In shift
folding, except the last; all parts are shifted so that the least significant bit of each part lines
up with the corresponding bit of the last part. The different parts are then added together to
form the hash key. In the folding at boundaries method, the original element is folded at the
boundaries and digits falling into the same position are added together.
Let us take one example, suppose the number to be hashed is 234764365
Dividing it by equal parts of length 2.
P1= 23, P2= 47, P3= 64, P4= 36, P5= 5
Shift Folding Folding at the boundaries
23 23
47 74 Reverse of 47
64 64
36 63 Reverse of 36
5 5
175 229
For the above number, the hash key generated by Shift folding would be 175 and by Folding
at boundaries would be 229. As here the size of the table is difficult to predict, hence the hash
key generated by this technique can be rehashed using some functions like Modulo N.

4) Digit Analysis: This method is very useful when all the elements to be stored are known in
advance. Each element is interpreted as a number using some radix. Using this radix all the
digits of all elements are examined and the digits having very skewed representation are
deleted. This continues till the number of digits left is small enough to give an index of the
array which can be used as hash key. The digits to drop are selected such that the hash keys
generated would be as non-conflicting as possible.
For e.g. :-
1205, 5287, 6247, 355, 7225, 6347, 7273, 23, 415, 347
(4) Vidyalankar : S.E. – DSF

Dropping the hundredths place


105, 587, 647, 55, 725, 647, 773, 23, 15, 47

Dropping the unit place


10, 58, 64, 5, 72, 64, 77, 2, 1, 4

2. (b) Selection Sort


Algorithm
1) Create array a[0 … n-1] of n elements.
2) initialize i to 0
3) Set element at i as min and pos to i
4) initialize j to i+1
5) if element at j is less than min then
change min to x[j] and pos to i
6) increment j by 1
7) if j<n then goto step 4
8) Swap the element at i with element at pos.
9) increment i by 1
10) if i<n-1 then goto step 3
11) Return the sorted array.

Implementation
import java.util.*;
class SelectionSort
{
private int x[],n;
public SelectionSort(int n)
{
this.n=n;
x=new int[n];
System.out.println("Enter "+n+" elements");
Scanner src=new Scanner(System.in);
for (int i=0; i<n; i++)
x[i]=src.nextInt();
}
public void selection ()
{
int i,j,min,pos;
for (i=0;i<n-1; i++)
{
min=x[i];
pos=i;
for (j=i+1; j<n; j++)
if (x[j]<min)
{
min=x[j];
pos=j;
}
x[pos]=x[i];
x[i]=min;
System.out.println("After Pass "+(i+1));
for (int k=0; k<n; k++)
System.out.print(x[k]+" ");
System.out.println();
}
}
Prelim Question Paper Solutions (5)

public void display()


{
for (int i=0; i<n; i++)
System.out.print(x[i]+" ");
}
}
class SelectionExp
{
public static void main(String args[])
{
Scanner src=new Scanner(System.in);
System.out.println("Enter number of elements");
int n=src.nextInt();
SelectionSort obj=new SelectionSort(n);
obj.selection();
System.out.println("Sorted Array");
obj.display();
}
}

Analysis
Pass 1 :- n-1 comparisons
Pass 2 :- n-2 comparisons … Pass i :- n-i comparisons
So the total will be the summation of n-i from i=1 to n-1. We get 1/2 [ n (n-1) ] which finally
leads to the worst case complexity of O(n2).
Even exchange mechanisms can not be devised for this algorithm. So irrespective of pattern of
the set of input elements, the efficiency will always be O(n2) for best and average case also.

Sample Output
Initial Array
7 54 29 41 12 5 78 35 22 18

5 54 29 41 12 7 78 35 22 18

5 7 29 41 12 54 78 35 22 18

5 7 12 41 29 54 78 35 22 18

5 7 12 18 29 54 78 35 22 41

5 7 12 18 22 54 78 35 29 41

5 7 12 18 22 29 78 35 54 41

5 7 12 18 22 29 35 78 54 41

5 7 12 18 22 29 35 41 54 78

5 7 12 18 22 29 35 41 54 78

3. (a) Converting Infix to Postfix


Rules:-
1) If the operand is encountered, display it (or store it in result).
2) If the operator is encountered and the stack is empty then push it on the stack.
3) If operator is encountered and the stack is not empty then compare the entering operator with
residing operator (the current top of the stack).
(6) Vidyalankar : S.E. – DSF

(a) If the entering operator has higher precedence than the residing operator then push it on
the stack
(b) If the entering operator has lower or equal precedence than the residing operator then the stack
is popped and elements are displayed till either the residing operator’s precedence becomes
higher or the stack becomes empty. Then the entering operator is pushed onto the stack.
(c) In case of brackets, the opening bracket has highest priority as an entering operator but
the lowest priority as residing operator. Hence whenever opening bracket is encountered
it is pushed on to the stack (Highest Priority). If the residing operator is opening bracket
then any operator is pushed on the stack (Lowest Priority).
(d) Whenever the closing bracket is encountered, the stack is popped till the opening bracket
is getting popped and all the popped elements are displayed. Both the closing and
opening brackets are discarded.

Implementation
import java.util.*;
class Stack
{
private char s[];
int tos=-1,max;
public Stack(int k)
{
max=k;
s=new char[max];
}
public void push(char ele)
{
if (tos==max-1)
System.out.println("Stack Overflow");
else
{
tos++;
s[tos]=ele;
}
}
public boolean empty()
{
if (tos==-1)
return true;
else
return false;
}
public char pop()
{
if (empty()!=true)
{
char z=s[tos];
tos--;
return z;
}
else
return 0;
}
public char stackTop()
{
return (s[tos]);
}
Prelim Question Paper Solutions (7)

}
class In2Post
{
private Stack s;
private String infix,postfix;
public In2Post(String v)
{
infix=v;
postfix=null;
}
public boolean isOperand(char ch)
{
if (ch>='A'&&ch<='Z'||ch>='a'&&ch<='z')
return true;
else
return false;
}
public int ipr(char ch)
{
switch(ch)
{
case '+':;
case '-':return 1;
case '*':;
case '/':;
case '%':return 2;
case '(':return 3; // highest priority
}
return -1;
}
public int rpr(char ch)
{
switch(ch)
{
case '+':;
case '-':return 1;
case '*':;
case '/':;
case '%':return 2;
case '(':return 0; // lowest priority
}
return -1;
}
public void convert()
{
s=new Stack(infix.length());
char in[]=infix.toCharArray();
char po[]=new char[in.length];
int c=0;
int i=0;
while(i<in.length)
{
if(in[i]=='(')
s.push(in[i]);
else if (in[i]==')')
while(true)
(8) Vidyalankar : S.E. – DSF

{
char z=s.pop();
if (z=='(')
break;
po[c++]=z;
}
else if (isOperand(in[i]))
po[c++]=in[i];
else if (s.empty())
s.push(in[i]);
else if (ipr(in[i])>rpr(s.stackTop()))
s.push(in[i]);
else
{
while(s.empty()==false && ipr(in[i])<=rpr(s.stackTop()))
{
char z=s.pop();
po[c++]=z;
}
s.push(in[i]);
}
i++;
}
while(s.empty()==false)
{
char z=s.pop();
po[c++]=z;
}
postfix=String.valueOf(po);
}
public void display()
{
System.out.println("The postfix expression = "+postfix);
}
public static void main(String args[])
{
Scanner src=new Scanner (System.in);
System.out.println("Enter the infix expression");
String input=src.nextLine();
In2Post obj=new In2Post(input);
obj.convert();
obj.display();
}
}

3. (b) Array Implementation of Queue


import java.util.*;
class Queue
{
private int q[],f=-1,r=-1,max;
public Queue(int max)
{
this.max=max;
q=new int[max];
}
Prelim Question Paper Solutions (9)

public void insert(int ele)throws Exception


{
if (r==max-1)
throw new Exception("Queue Overflow");
else
{
r++;
q[r]=ele;
if (f == - 1)
f++;
display();
}
}
public boolean empty()
{
if (f==-1||f>r)
return true;
else
return false;
}
public int delete()throws Exception
{
if (empty())
throw new Exception("Queue Underflow");
else
{
int z=q[f];
f++;
display();
return z;
}
}
public int queueFront()
{
return (q[f]);
}
public void display()
{
for (int i=f; i<=r; i++)
System.out.println(q[i]+" ");
System.out.println();
}
boolean search(int ele)
{
for(int i=f; i<=r; i++)
if (q[i]==ele)
return true;
return false;
}
}
class QueueExp
{
public static void main(String args[])
{
Scanner src=new Scanner (System.in);
System.out.println("Enter the capacity of the queue");
(10) Vidyalankar : S.E. – DSF

int k=src.nextInt();
Queue obj1=new Queue(k);
int ch;
while(true)
{
System.out.println("Enter the choice");
System.out.println("1:Insert 2:Delete 3:QueueFront 4:Display 5:Search 6:Exit");
ch=src.nextInt();
if (ch==6)
break;
switch(ch)
{
case 1: System.out.println("Enter the element to push");
int ele=src.nextInt();
try
{
obj1.insert(ele);
}
catch(Exception e)
{
System.out.println(e);
}
break;
case 2: try
{
int pele=obj1.delete();
System.out.println("The deleted element is "+pele);
}
catch(Exception e)
{
System.out.println(e);
}
break;
case 3: if (obj1.empty()==true)
System.out.println("Queue is empty");
else
{
int t=obj1.queueFront();
System.out.println("The current front element of Queue is "+t);
}
break;
case 4: if (obj1.empty()==true)
System.out.println("Queue is empty");
else obj1.display();
break;
case 5: System.out.println("Enter the element to search");
ele=src.nextInt();
if (obj1.search(ele))
System.out.println(ele+" is present in the queue");
else System.out.println(ele+" is not present in the queue");
}
}
}
}
Prelim Question Paper Solutions (11)

4. (a) Queue is defined as the collection of elements stored sequentially such that the elements can be
deleted from one end known as front end and can be added at another end known as rear end.
Queue follows the concept of FIFO (First In First Out). Hence unlike stack, in queue the first
element to be deleted will be the first element inserted.
Front Rear

Deletion Insertion
Fig.: Representation of a queue.

Operations on Queue
There are mainly two operations performed on queues known as ‘insert’ and ‘delete’.
Queue is like a both end open pipe. One end is known as ‘front’ end at which the deletion takes
place and other is ‘rear’ where the insertion takes place. The queue ADT keeps two pointers
namely front and rear. The ‘front’ pointer points to the frontmost element in the queue or the
element which is to be deleted first. The ‘rear’ pointer points to the last (rear most) element in the
queue or the element after which the insertion is to be done.
Initially both front and rear pointer will point to zero. When the deletion is to be done then the
element at front pointer is deleted and front is incremented by one. Whereas insertion is done at
the position next to the rear pointer and then rear pointer is also incremented to point to the newly
stored value.

Algorithm for Queue Implementation


Variables used :-
1) queue is a collection of sequential memory of size MAX
2) eltype is the type of elements of the stacks.
3) ‘f’ is data pointer which points to the front most element of the queue whereas ‘r’ is the data
pointer which points to the rear most element of the queue
4) a constant initpos which is the initial position of the f and r pointers of the queue (as array
starts from 0, generally initpos is initialized to -1)
5) a constant maxpos which is the maximum position till the r pointer can go upto ( if the array
size is MAX, then the elements can be stored upto MAX-1 hence maxpos is generally
initialized to MAX-1 )
Function insert (queue q, eltype x)
1) Start
2) If r = maxpos then return with “overflow error”
3) Increment r
4) Place x at position r in q
5) If (f = initpos) then increment f
6) Return
Function delete (queue q) returns eltype
1) Start
2) If (f = initpos) then return with “underflow error”
3) Store the element at f in temporary variable z. (deleted element)
4) Increment f
5) Return z
Function empty (queue q) returns boolean
1) Start
2) If f = initpos or f > r then return TRUE
3) Return FALSE
(12) Vidyalankar : S.E. – DSF

Function queueFront(queue q) returns eltype


1) Start
2) Return element at f in q

Function display (queue q)


1) Start
2) Initialize i with f
3) Display the element at i
4) Increment i
5) If i<=r then goto step 3
6) Return

Function search (queue q, eltype x) returns boolean


1) Start
2) Initialize i with f
3) If the element at i in q is equal to x then return TRUE
4) Increment i
5) If i<=r then goto step 3
6) Return FALSE

4. (b) Priority Queues :


A queue in which we are able to insert items or remove items from any position based on some
priority (such as priority of the task to be processed) is often referred to as a priority queue.
Figure (a) represents a priority queue of jobs waiting to use a computer. Priorities of 1, 2 and 3
have been attached to jobs of type real-time, on-line and batch respectively. Therefore, if a job is
initiated with priority i, it is inserted immediately at the end of the list of other jobs with priority i,
for i = 1, 2 or 3. In this example, jobs are always removed from the front of the queue. (In
general, this is not a necessary restriction on a priority queue.)

A priority queue can be conceptualized as a series of queue representing situations in which it is


known what priorities are associated with queue items. Figure (b) shows how the single-priority
queue can be visualized as three separate queues each exhibiting a strictly FIFO behavior.
Elements in the second queue are removed only when the first queue is empty, and elements from
the third queue are removed only when the first and second queues are empty. This separation of
a single-priority queue into a series of queues also suggests an efficient storage representation of
a priority queue. When elements are inserted, they are always added at the end of one of the
queues as determined by the priority. Alternatively, if a single sequential storage structure is used
for the priority queue then insertion may mean that the new element must be placed in the middle
of the structure. This can require the movement of several items. It is better to split the priority
queue into several queues, each having its own storage structure.

Task identification
R1 R2 … Ri-1 O1 O2 … Oi−1 B1 B2 … Bk−1 …
1 1 … 1 2 2 … 2 3 4 … 3 …
Priority ↑ ↑ ↑
Ri Rj Rk

Fig. (a) : A priority queue viewed as a single queue with insertion allowed at any position.

Priority 1
R1 R2 … Ri−1 … ↑ Ri

Priority 2
O1 O2 … Oi−1 … ↑ Oj
Prelim Question Paper Solutions (13)

Priority 3
B1 B2 … Bk−1 … ↑ Bk

Fig. (b) : A priority queue viewed as a setoff queue.

4. (c) Descending Priority Queue


In this, the elements are considered in the descending order of their priority. Hence on deleting,
the element with the highest priority is deleted first. Processors keep such queues for processes,
hence the process having higher priority is executed first irrespective of the arrival time.

There can be two methods of implementing the priority in the priority queue.
Method 1:
It would be to have normal insertion and adjusting on delete. Hence while inserting it follows the
rules of normal queue and elements are kept in the order of their arrival. But while deleting the
smallest or the largest element is searched and deleted. In this type, the queue will never be in
sorted position but deletion is done by selecting the appropriate element.

Method 2:
In this delete takes place in normal fashion i.e. by following the rules of the queue. But while
inserting we have to search for the proper place of the element for inserting so that the queue will
remain in the required sequence. Hence while deleting the largest or the smallest element it would
be available in the beginning only. In this type, at each point the queue would be in required
sorted position.

Let us go for the implementation of Priority Queue with above two methods.
Method 1
import java.util.*;
/********* Descending PQ with normal insert ************/
class PQ
{
final int MAX=10;
private int q[],f=-1,r=-1;
public PQ()
{
q=new int[MAX];
System.out.println("Queue is initialized");
}
public void insert(int x)
{
if(r==MAX-1)
System.out.println("Overflow Error");
else
{
q[++r]=x;
if(f==-1)
f++;
}
}
public void del()
{
int pos,ele,i,k;
if(r==-1||f>r)
System.out.println("Underflow Error");
else
{
(14) Vidyalankar : S.E. – DSF

pos=f;
for (i=pos+1; i<=r; i++)
if (q[i]>q[pos])
pos=i;
ele =q[pos];
for (k=pos; k<r; k++)
q[k]=q[k+1];
r--;
System.out.println("Deleted Element is "+ele);
}
}
public void display()
{
int i;
if(f>r||r==-1)
System.out.println("Queue is empty");
else
{
System.out.println("Queue is");
for(i=f;i<=r;i++)
System.out.print(q[i]+" ");
}
System.out.println();
}
}
class PQExp1
{
public static void main(String args[])
{
int choice,x;
PQ obj=new PQ();
while(true)
{
System.out.println("1.Insert 2.Remove 3.Display");
System.out.println("4.Exit Enter your choice :");
Scanner src=new Scanner(System.in);
choice=src.nextInt();
if (choice==4)
break;
switch(choice)
{
case 1 :System.out.println("Enter element to insert");
x=src.nextInt();
obj.insert(x);
break;
case 2 :obj.del();
break;
case 3 :obj.display();
break;
}
}
}
}
Method 2
import java.util.*;
/********* Descending PQ with normal delete ************/
Prelim Question Paper Solutions (15)

class PQ2
{
final int MAX=10;
private int q[],f=-1,r=-1;
public PQ2()
{
q=new int[MAX];
System.out.println("Queue is initialized");
}
public void insert(int x)
{
int pos,i,k;
if(r==MAX-1)
System.out.println("Overflow Error");
else
{
if (r==-1)
{
q[++r]=x;
f++;
}
else
{
pos=f;
for (i=f;i<=r;i++)
if (q[i]<x)
break;
for (k=r;k>=i; k--)
q[k+1]=q[k];
q[i]=x;
r++;
}
}
}
public void del()
{
int ele,i,k;
if(r==-1||f>r)
System.out.println("Underflow Error");
else
{
ele=q[f];
f++;
System.out.println("Deleted Element is "+ele);
}
}
public void display()
{
int i;
if(f>r||r==-1)
System.out.println("Queue is empty");
else
{
System.out.println("Queue is");
for(i=f;i<=r;i++)
System.out.print(q[i]+" ");
(16) Vidyalankar : S.E. – DSF

}
System.out.println();
}
}
class PQExp2
{
public static void main(String args[])
{
int choice,x;
PQ2 obj=new PQ2();
while(true)
{
System.out.println("1.Insert 2.Remove 3.Display");
System.out.println("4.Exit Enter your choice :");
Scanner src=new Scanner(System.in);
choice=src.nextInt();
if (choice==4)
break;
switch(choice)
{
case 1 : System.out.println("Enter element to insert");
x=src.nextInt();
obj.insert(x);
break;
case 2 : obj.del();
break;
case 3 : obj.display();
break;
}
}
}
}

5. (a) Array Implementation of Linked List


Sometimes we need to implement a linked list using array. So we can use a two dimensional array
of n x 2 where n denotes maximum number of elements the linked list can store. The first column
is used to store data and the second column stores the index of the next element. Using array
implementation of linked list, we can achieve the advantages like easy insertion and deletion
without shifting elements.

2 0 4 1
32 0 41 4 8 1 21

2
start

The diagram shows the diagrammatic representation of a linked list. Instead of address, each node
is assigned the index of the array where it is stored. The contents of array storing the above linked
list will be as follows.

start 2
Prelim Question Paper Solutions (17)

Index Data Next


0 41 4
1 21 -1
2 32 0
3 0 -2
4 8 1
5 0 -2
From the above information, it is clear that the linked list starts at index 2, so the first element is
32. It’s next stores 0, so the next element is at index 0 i.e. 41 then 8 and then 21. As the next of 21 is
marked as ‘-1’, it is taken as null and the linked list terminates. The nodes having next marked as -2
are considered to be unallocated irrespective of whatever data is stored in it. The concept is
implemented in the following program.

import java.util.*;
class ArrayLL
{
private int a[][],max;
private final int data=0, next=1, NULL=-1,empty=-2;
private int start=-1;
public ArrayLL(int cap)
{
max=cap;
a=new int[max][2];
for (int i=0; i<max; i++)
a[i][next]=-2;
}
public void show()
{
System.out.println("The memory map");
for (int i=0; i<max; i++)
System.out.println(i+" "+a[i][data]+" "+a[i][next]);
}
public int allocate()
{
for (int i=0; i<max; i++)
if (a[i][next]==empty)
return i;
return -1;
}
public boolean empty()
{
if (start==NULL)
return true;
else
return false;
}
public void create(int n)
{
Scanner src=new Scanner(System.in);
for (int i=0; i<n; i++)
{
int k=allocate();
if (k==-1)
System.out.println("Memory Full");
else
(18) Vidyalankar : S.E. – DSF

{
System.out.println("Enter data");
a[k][data]=src.nextInt();
a[k][next]=NULL;
if (start==NULL)
start=k;
else
{
int q=start;
while(a[q][next]!=NULL)
q=a[q][next];
a[q][next]=k;
}
}
}
}
public void insertBeg(int ele)
{
int k=allocate();
if (k==-1)
System.out.println("Memory Full");
else
{
a[k][data]=ele;
a[k][next]=start;
start=k;
}
}
public void insertEnd(int ele)
{
int k=allocate();
if (k==-1)
System.out.println("Memory Full");
else
{
a[k][data]=ele;
a[k][next]=NULL;
int q=start;
while(a[q][next]!=NULL)
q=a[q][next];
a[q][next]=k;
}
}
public int deleteBeg()
{
int p=start;
if (start==NULL)
return -1;
if (a[start][next]==NULL)
start=NULL;
else start=a[start][next];
int z=a[p][data];
a[p][next]=empty;
return z;
}
public int deleteEnd()
Prelim Question Paper Solutions (19)

{
int p,q=start;
if (start==NULL)
return -1;
if (a[start][next]==NULL)
{
p=start;
start=NULL;
}
else
{
while(a[a[q][next]][next]!=NULL)
q=a[q][next];
p=a[q][next];
a[q][next]=NULL;
}
int z=a[p][data];
a[p][next]=empty;
return z;
}
public void deleteEle(int ele)
{
int q=start;
if (a[q][data]==ele)
{
System.out.println(ele+" is deleted");
start=a[start][next];
return;
}
while(a[q][next]!=NULL)
{
if(a[a[q][next]][data]==ele)
break;
q=a[q][next];
}
if(a[q][next]==NULL)
System.out.println(ele+" is not found");
else
{
System.out.println(ele+" is deleted");
a[q][next]=a[a[q][next]][next];
}
}
public void display()
{
int q=start;
while(q!=NULL)
{
System.out.print(a[q][data]+" ");
q=a[q][next];
}
System.out.println();
show(); // to display contents of array (optional)
}
}
class ArrayLLExp
(20) Vidyalankar : S.E. – DSF

{
public static void main(String args[])
{
int ch,pele;
Scanner src=new Scanner(System.in);
System.out.println("Enter capacity");
int cap=src.nextInt();
ArrayLL x=new ArrayLL(cap);
System.out.println("Enter no of elements");
int n=src.nextInt();
x.create(n);
while(true)
{
System.out.println("Enter choice 1:Insert Beg 2:Insert End");
System.out.println("3:Delete Beg 4:Delete End 5:Delete Element");
System.out.println("6:Display 7:Exit");
ch=src.nextInt();
if (ch==7)
break;
switch(ch)
{
case 1: System.out.println("Enter the element to insert");
int ele=src.nextInt();
x.insertBeg(ele);
break;
case 2: System.out.println("Enter the element to insert");
ele=src.nextInt();
x.insertEnd(ele);
break;
case 3: if (x.empty())
System.out.println("Linked List is empty");
else
{
pele=x.deleteBeg();
System.out.println("Deleted Element is "+pele);
}
break;
case 4:if (x.empty())
System.out.println("Linked List is empty");
else
{
pele=x.deleteEnd();
System.out.println("Deleted Element is "+pele);
}
break;
case 5: if (x.empty())
System.out.println("Linked List is empty");
else
{
System.out.println("Enter element to delete");
ele=src.nextInt();
x.deleteEle(ele);
}
break;
case 6: if (x.empty())
System.out.println("Linked List is empty");
Prelim Question Paper Solutions (21)

else
x.display();
break;
}
}
}
}

5. (b) import java.util.*;


class Node
{
int data;
Node next;
public Node(int k)
{
data=k;
next=null;
}
}
class LinkedList
{
private Node start=null;
public void create(int n)
{
Node p,q;
for (int i=0; i<n; i++)
{
Scanner src=new Scanner(System.in);
System.out.println("Enter data");
int ele=src.nextInt();
p=new Node(ele);
if (start==null)
start=p;
else
{
q=start;
while(q.next!=null)
q=q.next;
q.next=p;
}
}
}
public void display()
{
Node q=start;
while(q!=null)
{
System.out.print(q.data+" ");
q=q.next;
}
System.out.println();
}
public void rev()
{
Node p,q,r;
q=null;
(22) Vidyalankar : S.E. – DSF

p=start;
while(p!=null)
{
r=p.next;
p.next=q;
q=p;
p=r;
}
start=q;
}
}
class LRev
{
public static void main(String args[])
{
int ch,pele;
Scanner src=new Scanner(System.in);
System.out.println("Enter no of elements to create");
int n=src.nextInt();
LinkedList obj=new LinkedList();
obj.create(n);
System.out.println("Original Linked List");
obj.display();
obj.rev();
System.out.println("\nReversed Linked List");
obj.display();
}
}

6. (a) The tree T is drawn from its root downward as follows :


(i) The root of T is obtained by choosing the first node in its preorder. Thus, F is the root of T.
(ii) The left child of the node F is obtained as follows. First use the inorder of T to find the nodes
in the left subtree T1 of F. Thus, T1 consists of the nodes E, A, C and K. Then the left child
of F is obtained by choosing the first node in the preorder of T1 (which appears in the
preorder of T). Thus A is the left son of F.
(iii) Similarly, the right subtree T2 of F consists of the nodes H, D, B and G and D is the root of T2
i.e. D is the right child of F.
Repeating the above process with each now node, we finally obtain the required tree.
F
A D
K H
E G
C C
1) Inorder :- In this root is traversed in between the left and right sub tree.
2) Preorder :- In this root is traversed prior to both the sub trees.

The algorithm can be given as follows.


Function inorder (root)
1) start
2) if root is not null then
a) call inorder with left pointer of root (root->left)
b) display the data in root.
c) call inorder with right pointer of root. (root->right)
3) stop
Prelim Question Paper Solutions (23)

Function preorder (root)


1) start
2) if root is not null then
a) display the data in root.
b) call preorder with left pointer of root (root->left)
c) call preorder with right pointer of root. (root->right)
3) stop

6. (b) Difference between B- tree and B + tree.


B-tree B+ tree
1 Every key is stored only once either in leaf Values stored in a non-leaf node are repeated
node or non leaf node again in one of the leaf node. i.e. leaf nodes
can contain all the keys
2 All leaf nodes are at same node but are All leaves are at same level and are
isolated from each other connected by using an additional pointer.
3. Records are stored inside the B-tree i.e. Records are stored outside B+ tree and the
every key is associated with its Record addition of these records are stored by the
∴B− tree is larger in size and it cannot fit pointer of the leaf node.
in RAM. ∴B+ tree smaller in size and can fit in RAM.
4. B- tree supports Random traversal only B+ tree supports both Random & sequential
traversal.

6. (c) AVL Trees: Any binary search tree T that satisfies the height balance property is called as AVL tree.
Height−Balance property states that for every internal node v of T, the heights of the children of v
differ by at most 1.
| h − hr | ≤ 1
h  = height of left subtree
h r = height of right subtree
The consequence of the height balance property is that a subtree of an AVL tree is itself an AVL tree.
AVL gives 4 Rotation Algorithm for 4 different cases, which are useful for Balancing the tree.
Case I − Left − Left Case
root
100

50

25

100 is not balanced due to left−left case. So rotate 100 to right. This is Right rotation.
Case 2 − Right − Right case
root
100
root
200
200

100 300
300

100 is not balanced due to right−right case. So rotate 100 to left. This is left rotation.
(24) Vidyalankar : S.E. – DSF

Case 3 : − Left − Right case


100 100

75
50 75
50 100
75
50

Left − left case


100 is not balanced due to left-right case. So rotate left child of 100. i.e. so this is left rotation.
Case 4 : − Right − Left case
100
100

150
200
150
100 200
150
200

100 is not balanced due to right-left case. So rotate right child of 100. i.e. 150 this is right rotation.

7. (a) (i) Threaded binary tree : Because of the importance of linked binary trees, it is worthwhile to
develop nonrecursive algorithms to manipulate them and to study the time and space
requirements of these algorithms. We shall find that by changing the NULL links in a binary
tree to special links called threads, it is possible to perform traversals, insertions, and
deletions without using either a stack or recursion.

A Threaded Binary Tree is a binary tree in which every node that does not have a right child
has a THREAD (in actual sense, a link) to its INORDER successor. By doing this threading
we avoid the recursive method of traversing a Tree which makes use of stacks and consumes
a lot of memory and time.
For example :
To make the Threaded Binary tree out of a
normal binary tree as shown in figures:

The INORDER traversal for the above tree


is -- D B A E C. So, the respective Threaded
Binary tree will be –

B has no right child and its inorder successor is A so a thread has been made in between
them. Similarly, for D and E, C has no right child but it has no inorder successor so it has a
hanging thread.

A binary tree is threaded by making all right child pointers that would normally be null point
to the inorder successor of the node and all left child pointers that would normally be null
point to the inorder predecessor of the node."

A threaded binary tree makes it possible to traverse the values in the binary tree via a linear
traversal that is more rapid than a recursive in-order traversal.
Prelim Question Paper Solutions (25)

It is also possible to discover the parent of a node from a threaded binary tree without explicit
use of parent pointers or a stack, albeit slowly. This can be useful where stack space is limited
or where a stack of parent pointers is unavailable.

(ii) Huffman Codes


The most common way to represent characters internally in a computer is by using fixed−length
bit strings. For example, ASCII (American Standard Code for Information Interchange)
represents each character by a string of seven bits. Examples are given in table:
Character ASCII Code
A 100 0001
B 100 0010
C 100 0011
1 011 0001
2 011 0010
1 010 0001
∗ 010 1010
Huffman codes which represent characters by variable−length bit strings provide alternatives to
ASCII and other fixed−length codes. The idea is to use short bit strings to represent the most
frequently used characters. In this way it is generally possible to represent strings of characters
such as text and programs in less space than if ASCII were used. Root
1 0
A Huffman code is most easily defined by a rooted tree. To decode a bit A 1 0
string, we begin at the root and move down the tree until a character is
1 0 O
encountered. The bit, 0 or 1, tells us whether to move right or left.
1 0
As an example, let us decode the string : 01010111 R
T S

We begin at the root. Since the first bit is 0, the first move is right. Next, we move left and then
right. At this point, we encounter the first character R. To decode the next character, we begin
again at the root. The next bit is 1 so we move left and encounter the next character A. The last
bits 0111 decode as T. Therefore, the bit string represents the word RAT.

Huffman gave an algorithm to construct a Huffman code from a table giving the frequency of
occurrence of the characters to be represented so that the code constructed represents strings of
characters in minimal space, provided that the strings to be represented have character
frequencies identical to the character frequencies in the table.

Constructing an Optimal Huffman Code


This algorithm constructs an optimal Huffman code from a table giving the frequency of
occurrence of the characters to be represented. The output is a rooted tree with the vertices at the
lowest levels labeled with the frequencies and with the edges labeled with bits as in the above
figure. The coding tree is obtained by replacing each frequency by a character having that
frequency.
Input: A sequence of n frequencies, n ≥ 2 1 0
Output: A rooted tree that defines an optimal Huffman code
f1 f2
The case n = 2 for Algorithm
Procedure Huffman (f, n)
If n = 2 then
begin
let f1 and f2 denote the frequencies 1 0
let T be as in figure
return (T)
end
let fi and fj denote the smallest frequencies fi fj
replace fi and fj in the list f by fi + fj The case n > 2 for Algorithm
T′ := Huffman (f, n−1)
(26) Vidyalankar : S.E. – DSF

replace a vertex in T′ labeled fi + fj by the tree shown in


figure to obtain the tree T
return (T)
end Huffman

7. (b) Graphs
Graph consists of two sets V and E of vertices and edges respectively. So G = (V,E) represents a graph.
In Un-directed Graph, the pairs (V1, V2) and (V2, V1) are same.
In Directed graph,
(V1, V2) = V1  V2
(V2, V1) = V2  V1
The graph shown in figure is an undirected graph and can be represented as, 1
V(G1) = {1,2,3,4}
E(G1) = {(1,2), (1,3), (1,4), (2,3), (2,4), (3,4)}
2 4
In un-directed graph of n nodes (vertices),
Maximum number of edges = n(n-1)/2
3
Implementation
import java.util.*;
class DFS
{
private int adj[ ][ ], visited[ ], n;
public DFS(int n)
{
this.n=n;
adj=new int[n][n];
visited=new int[n];
Scanner src=new Scanner(System.in);
System.out.println("Enter the adjacency matrix of "+n+"x"+n);
for (int i=0; i<n; i++)
for (int j=0; j<n; j++)
adj[i][j]=src.nextInt();
for (int i=0; i<n; i++)
visited[i]=0;
}
public void dfs(int node)
{
int i;
System.out.print((node+1)+" ");
visited[node]=1;
for (i=0; i<n; i++)
if (adj[node][i]!=0 && visited[i]!=1)
dfs(i);
}
}
class DFSExp
{
public static void main(String args[ ])
{
Scanner src=new Scanner(System.in);
System.out.println("Enter number of nodes");
int n=src.nextInt();
DFS obj=new DFS(n);
System.out.println("Enter the starting node");
int node=src.nextInt();
obj.dfs(node-1);
}
}


Das könnte Ihnen auch gefallen