Unit II
Unit II
Unit II
The List ADT – The Stack ADT – The Queue ADT - Recursion
Data may be defined as a set and the elements of the set are
called the values of the type. It is a set of atomic data having identical
properties. It is defined by a set of values and a set of operations that act on
the values. There are four basic (atomic or primitive) data types. These are
int, float, char and double.
For example, we can define atomic data types are shown below:
Integer
Values : - ∞, ….., -2, -1, 0,1 ,2, ……….., ∞
Operations : *,+,-,/,%,++,--,…….
Real
Values : -∞,……….0.0,………… ∞
Operations : *,+,-,/,…….
Character
Values : \0,……..,’A’,’B’,……..’a’,’b’,…….~
Operations : +, - ,……….
It can be broken down out sub fields that have meaning. For example,
consider a telephone number. There are actually three different parts to a
telephone number. First one is country code, then area code and third is the
actual telephone number.
The simple data types built from primitives are arrays, pointers ,strings
and records with which we can build new data types called structured or
composite types.
1. Abstract Level
Here, we recognize the relationships among the data elements and
general accessing procedures and functions. But we do not decide any thing
about how the data will actually be stored or how the operations will actually
implemented.
3. Implementation Level
Here, one can decide the ways to represent the data elements in
computer memory and to implement the operations in a programming
language.
4. Application Level
Here, final details of the particular application are decided.
The first level is called conceptual because at these levels we are more
concerned with problem solving than with programming.
The middle two levels can be called algorithmic because they concern
precise methods for representing data and operating with it.
The last two levels are specifically concerned with programming.
It allows the user to define new data types. These data types can be
used to declare variable names later in the program. The user defined data
type has two types, namely
1. typedef data_type 2. enumerated data_type
typedef data__type
The typedef can be used to define new data types and also used to
define structures. Its syntax is :
typedef data_type identifier;
where,
data_type ----> refers to int, float or char
identifier ----> refers to the new names given to the data_type.
Example :
typedef int marks;
typedef float salary;
typedef char string;
Here, marks, salary and string represents int, float and char
respectively. These can be later used to declare variables names.
Example :
marks phy,chem,compu;
salary total;
string name[20];
Here, phy, chem and compu are declared as integer variables, total is
declared as floating point variable and name is declared as character array
variable.
It creates a new data type called month in which the enumeration list
are automatically set to 0 to 11. That is, JAN as 0 , FEB as 1, MAR as 2 and so
on.
Suppose, if you want to assign the enumeration list from 1 to 12, the
declaration should be,
enum month {JAN=1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP,
OCT, NOV, DEC};
One can also assign different initializes for the enumeration list.
For example,
enum month {JAN=1, FEB, MAR=10, APR, MAY, JUN, JUL=25, AUG,
SEP, OCT, NOV=50, DEC};
Then the values of the enumeration constant will be
Arrays are used to store a large amount of data. The array may be
defined as a group of related data items that share a common name and type.
The variables which are used to represent the individual data in the memory
are called by subscripted variables.
For example, assumes the group v = 2.0, 1.2, 3.6, ..... If we want to refer
to the second number of the group, we write in C as v[1] where 1 is called the
subscript. The subscript is enclosed in parenthesis.
1. One dimensional array : Which is used for the complete list of item.
2. Two dimensional array : Which is used for all the entries in a given table.
The elements in a list (or) table can be either numerical quantity (or)
string quantity.
NOTE : No two arrays can have the same name (or) An array and an
ordinary variable can be assigned the same name.
Example :
x[3] ........... an element of the list x contain three characters.
t[8][4]......... an element of the table t contains a total of 32 characters.
In C, the array is declared as follows :
Example :
int a[10];
This means that, 10 variables are declared to be integers and they are
referred to as a[0],a[1],a[2],.....a[9]. In C, the array elements are started
Example:
int marks[5]={50,60,70,80,90};
Here, the values 50,60,70,80 and 90 are assigned to the variable
marks[0],marks[1],marks[2],marks[3] and marks[4] respectively.
char xyz[10]={'a','b','c'};
Here, the number of values in the array is less than the size of the
array. So, the values 'a', 'b' and 'c' are assigned to the variable xyz[0], xyz[1]
and xyz[2] and the remaining variables xyz[4] to xyz[9] will be set to zero
automatically.
float a[]={1.1,2.24,3.33,4.44}
Note :
The character array can be initialized by a string constant. Here, the
first element of the array being set to the first character in the string, the
second element to the second character and so an. The array also receives the
terminating string constant '\0'. For example,
char name[]="RUSHMI"; which is equivalent to
char name[]={'R','U','S','H','M','I','\0'};
Example :
for (i=0;i<10;i++)
scanf("%d",&a[i]);
The above segment can also be written as using while loop as follows:
int a[10],i=0;
while (i<10)
{
scanf("%d",&a[i]);
i++;
}
Arrays can also be represented as more than one subscript value. This
is called as multi dimensional array. The arrays of more than one dimension
is also called as arrays of arrays. It is mainly used in matrix operations. Its
syntax is :
variable_name [size][size];
Here the first size denotes the size of row and the second size denotes
the size of column.
Example :
int a[5][6];
int b[10][10];
In the above example an array name a has 5 rows and 6 columns and
an array b has 10 rows and 10 columns.
2.5 POINTERS IN C
Advantages of pointer:
1. Execution time is reduced.
2. Reduce the length and complexity of a program.
3. Storage space is reduced.
4. Efficient in handling multidimensional arrays (data tables).
5. It normally returns multiple data items from a function via function
arguments.
6. It is used to pass information back and forth between a function and its
reference point.
Example : &a --- a is a varilable, and &a is the address in the value of a
is stored.
Example :
Call by Value :
The process of passing the actual value of variables using in the calling
function is copied into the corresponding formal arguments used in the called
function.
Advantages
Example :
Write a program to interchange two values
#include <stdio.h>
main()
{
int x=5;
int y=10;
interchange(x,y);
printf("\n X = %d",x);
printf("\n Y = %d",y);
}
interchange(int a,int b)
{
int k; k=a; a=b; b=k;
printf("\n A = %d",a);
printf("\n B = %d",b);
}
Example :
#include <stdio.h>
void add(int);
void main()
{
int a = 5;
printf("\n The value of A before calling the function is %d",a);
add(a);
printf("\n The value of A after calling the function is %d",a);
}
void add(int x)
{
x = x + 5;
printf("\n The value of A in the called function is %d",x);
}
CALL BY REFERENCE
Example :
Write a program to interchange two values using pointers.
#include <stdio.h>
main()
{
int x=5;
int y=10;
interchange(&x,&y);
printf("\n X = %d",x);
printf("\n Y = %d",y);
}
interchange(int *a,int *b)
{
int k;
k=*a;
*a=*b;
*b=k;
}
In C, all the variables have datatypes and storage classes. Datatype may
be int, float or char, that represents the type of variable and storage classes
determine the lifetime of the storage, associated with the functions. The
various storage classes in C are:
1.Automatic storage class
2. External storage classes
3. Static storage classes
4. Register storage classes
Example:
#include <stdio.h>
main()
{
auto int n; is equivalent to
.....
}
Example :
#include <stdio.h>
main()
{
int n=10;
fun();
printf("\n n = %d in function main",n);
}
fun1()
{
int n=5;
n=n*5; /* compound statement with another n */
{
int n;
n=1;
printf("\nn = %d in inner most block ",n);
}
printf("\n n= %d (parameter of function fun) ",n);
}
Example :
#include <stdio.h>
int x;
main()
{
x=5;
run1();
run2();
run3();
printf("%d \t",x);
}
run1()
{
x=x+10;
printf("%d\t",x);
}
run2()
{
x=10;
printf("%d\t",x);
}
run3()
{
x+=100;
printf("%d\t",x);
}
Example :
#include <stdio.h>
main()
{
int i;
for (i=0;i<5;i++)
state();
}
state()/*static variable */ state() /* automatic variable*/
{ {
static int x=5; int x=5;
x=x+1; x=x+1;
printf("\nx = %d",x); printf("\nx = %d",x);
} }
In the above program static variable is initialized only once. During the
first call to state, x is incremented to 1. Because x is static, this value persists
and therefore, next call adds another 1 to x giving it a value of 7. The value of
x becomes 8 when the third call is made.
Suppose if x is declared as auto, then the output will be:
x=6 x=6 x=6
This is because, each time state() is called, the auto variable x is set to 6.
Example :
Write a program to display a number and its square from 0 to 5 using
register variables.
#include <stdio.h>
main()
{
register int i,x,y,z;
x=0;
y=0;
while (x<=10)
{
z=f(x,y);
printf("%d\t%d\n",x,z);
++x;
++y;
}
}
f(x,y)
register int x,y;
{
register int temp;
temp = x*y;
return(temp);
}
Note:
The CPU registers in the microcomputers are usually 16 or 32 bit
registers and therefore it is impossible to declare float or double as register
type. When you use float or double as register type, then C compiler will
automatically ignore the register data type and it keeps them in the memory
and compiler will be treated as an automatic variables.
Example :
char class[25];
It reserves 25 memory locations for the array named class as type char.
In static memory allocation, the address of a variable is assigned to a pointer
variable which is declared as the same data type. The compiler allocates the
required memory space for a variable declared. For
Example,
int a,b,*c;
*c = &b;
malloc() statement:
It is used to assign sufficient blocks of memory for a given variable in
bytes. The syntax is :
var = malloc(parameter);
where,
var ---> must be a pointer variable and
parameter ---> must be an integer value.
Example :
ptr = malloc(10);
Example :
ptr = calloc(3,2)
realloc( ) statement :
It is used to increase or decrease the size of memory previously
allocated in each by using malloc( ) or calloc( ) function. Its syntax is :
var = realloc(old_pointer_variable, new_size)
where,
old_pointer_variable ---> is the variable used in malloc( ) or
calloc( ) function.
new_size ---> size of the new memory area needed.
Example:
ptr = malloc(10)
x = realloc(ptr,20)
The first statement allocates memory space of size 10 bytes and returns
the starting address of the memory through the pointer ptr. The second
statement reallocates (increases) the already allocated space to 20 bytes.
free() statement :
Example:
ptr = malloc(10)
free(ptr);
The first statement allocates memory space of 10 bytes and returns the
starting address of the allocated memory. The second statement frees the
allocated memory.
Definition :
C provides a compound data type called a structure. It is defined as a
collection of one or more variables of different data types grouped together
under a single name.
For example, if we consider the student details, we may refer student
roll number(integer), his/her name(character), his/her marks(integer),
his/her total mark(integer) and an average(float). These data are of different
types organized together under a single name called as a structure.
The general form of the structure is :
struct <tag_name>
{
data type declarations;
};
where
struct ---> is a keyword.
tag_name ---> It is used to identify the structure and it is optional.
For example :
A book has name, author's name, contents, index and year of
publication. It is defined as follows :
struct book
{
char book_name[20];
char auth_name[20];
char contents[10];
char index[5];
int year;
};
From the above declarations , the name of the structure is book. The
members of the structure are book_name, auth_name, contents, index and
year.
One can also declare structure variable using the tag name anywhere in
the program. Its syntax is :
struct <tag_name>
{
data type declarations;
}structure_name;
where,
struct ---> is a keyword.
tag_name ---> It is used to identify the structure and it is optional.
structure_name ---> Name of the structure.
struct book
{
char book_name[20];
char auth_name[20];
char contents[10];
char index[5];
int year;
};
struct book b1,b2,b3; OR
One can also written as :
struct book struct
{ {
char book_name[20]; char book_name[20];
char auth_name[20]; char auth_name[20];
char contents[10]; OR char contents[10];
char index[5]; char index[5];
int year; int year;
}b1,b2,b3; }b1,b2,b3;
In the second example, the tag_name book is omitted and it does not
include later use in declaration. The above structure declares b1, b2 and b3 as
structure variables representing three b's.
structure_name.member_name
Example :
To assign a value to the structure variable,
book.book_name="digital electronics"
Example:
main( )
{
static struct student
{
int height;
float weight;
} student = {170,90}
}
In the above example, 170 assigns to student.height and 90 assigns to
student.weight. Note that, the assigning values must be in same order as that
in which the members are specified. That is, there must be one-to-one
correspondence between the members and their initialization values.
NESTING OF STRUCTURES :
It is nothing but a structure containing one or more structures.
The syntax is:
struct struct_name
{
data_type_declarations;
struct another_structure_name
{
data_type_declarations;
}
}
Example:
struct student
{
int rollno;
char name[20];
struct stud_addr
{
int no;
char street[15];
char place[15];
char city[10];
long pincode;
}address;
char deptname[15];
char year[5];
}stud1,stud2;
Example :
stud1.address.no
2.8.5 UNIONS :
It is another compound data type that may hold objects of different
types and sizes. Union provides different kinds of data in a single area of
storage. Its syntax is:
union union_name
{
datatype_declarations;
}union_variables;
Example :
union stud
{
char name[20];
int rollno;
float mark1,mark2,mark3;
};
In the above example, union stud has 5 members. The first member is a
character name having 20 characters. The second member is a integer type
rollno having 2 bytes. All the other members mark1, mark2 and mark3 are of
type float which requires 4 bytes each.
Rules :
1. Any number of union members can be present in the union. But union
type variables will take the largest memory occupied by its members.
2. At any time only one value can be stored.
3. The data can be retrieved with the type of the largest storage.
4. Unions can also appear in an array and structures.
5. Pointers to union is also possible and the members of the pointer to
union are referred using the symbol ->
OR
A
23
45
37
56
97
Example
An automobile company uses an array Auto to record the number of
automobiles sold each year from 1945 to 2004. Find the number of
automobiles sold?
Solution
Length = UB - LB + 1
= 2004 - 1945 + 1
= 60
2.10.1 Representation of Linear Array in memory
Let A be an array in the memory of the computer. The memory of the
computer is simply a sequence of addressed locations, which can be defined
as follows:
LOC(A[k]) = Address of the element A[k] of the array A
The elements of A are stored in successive memory cells. We know
that, the computer does not keep track of the address of every element of A,
but needs to keep track only of the address of the first element of A, denoted
by Base(A) is called the base address of A. Using this base address, the
computer calculates the address of any element of A by the following
formula:
LOC(A[K]) = Base (A) + w(K - Lower Bound)
Where, w = Number of words per memory cell of array A.
Example:
Consider the arrays A(5:50), B(-5:10) and C(18)
a. Find the number of elements in each array
b. Suppose Base (A)=300, w = 4 words per memory cell for A. Find
the address of A[15], A[35] and A[55].
Solution:
a. The number of elements is equal to the length.
Length = UB - LB + 1
Therefore, Length (A) = 50 - 5 + 1 = 46
Length (B) = 10 - (-5) + 1 = 16
Length(C) = 18 - 1 + 1 = 18
Note: Length (C) = UB, Since LB = 1
b. Use the formula LOC (A[K]) = Base (A) + w(K - LB)
Hence, LOC(A[15]) = 300 + 4 (15 - 5) = 340
LOC(A[35])= 300 + 4 (35 - 5) = 420
A[55] is not an element of A, since 55 exceeds UB = 50.
2.10.2 Representation of Two-Dimensional Array
A two-dimensional array m x n array A is a collection of mxn elements
such that each element is specified by a pair of integers (such as J,K) called
subscripts, with the property that,
1 <= J <= m and 1 <= K <= n
The element of A with subscripts J and K will be denoted by AJ,K or
A[J, K] .
The two-dimensional arrays are called matrices in mathematics and
tables in business applications. Hence two-dimensional arrays are sometimes
called matrix arrays.
The length of the array = Pair of lengths J x K.
Li = Upper Bound - Lower Bound - 1
For two-dimensional array, the computer also keeps track of Base (A) -
the address of the first element A[1,1] of A and computes the address
LOC(A[J, K]) of A[J, K] using the formula:
Example:
Consider the 25 x 4 matrix array A. Suppose Base (A) = 200 and there
are w = 4 words per memory cell. Find the address of A[12,3] using row-
major order.
Solution
LOC(A[12, 3]) = 200 + 4[4(12 - 1) + (3 - 1)]
= 200 + 4[46] = 384
Example:
Suppose a three dimensional array A is declared as A(2:8, -4:1, 6:10).
Find the length of A. Also find A[5, -1, 8]. Assume Base(A)=200 and w = 4
words per memory cell.
Solution
L1 = 8 - 2 + 1 = 7
L2 = 1 - (-4) + 1 = 6
L3 = 10 - 6 + 1 = 5
The total elements of A = L1.L2.L3 = 7.6.5 = 210 elements.
Suppose, the programming language stores A in memory in row-major
order.
The effective indices of the subscripts are:
E1 = 5 - 2 = 3
E2 = -1 - (-4) = 3
E3 = 8 - 6 = 2
For row-major order, we have:
E1L2 = 3.6 = 18
E1L2 + E2 = 18 + 3 = 21
(E1L2 + E2)L3 = 21.5 = 105
(E1L2 + E3)L3 + E3 = 105 + 2 = 107
Therefore, LOC(A[5, -1, 8]) = 200 + 4(107)
= 200 + 428 = 628.
Example:
Suppose multi-dimensional arrays A and B are declared using A(-2:2,
2:22) and B(1:8, -5:5, -10:5)
Solution:
(a).
The Length = Upper bound - Lower bound + 1
Hence the length Li of the dimensions of A are:
L1 = 2 - (-2) + 1 = 5
L2 = 22 - 2 + 1 = 21
Therefore, A has 5.21 = 105 elements.
Similarly, the length Li of the dimensions of B are:
L1 = 8 - 1 + 1 = 8
L2 = 5 - (-5) + 1 = 11
L3 = 5 - (-10) + 1 = 16
Therefore, B has 8.11.16 = 1408 elements.
(b).
The effective indes Ei is obtained from Ei = Ki - LB
where, Ki = Given Index and LB = Lower Bound
E1 = 3 - 1 = 2
E2 = 3 - (-5) = 8
E3 = 3 - (-10) = 13
x x x x x x 0 0 0 0
0 x x x x x x 0 0 0
0 0 x x x x x x 0 0
0 0 0 x x x x x x 0
0 0 0 0 x x x x x x
a. Upper Triangular Array b. Lower Triangular Array
n n( n + 1)
The total number of non-zero elements is not more than, ∑i = 2
i =1
0 0 0 0 0 1 0 0 0 0
0 0 2 6 1 0 0 0 0 0
0 0 0 0 2 1 0 0 0 0
0 0 1 0 0 0 0 1 0 0
0 0 0 0 5 0 0 2 0 0
2.11 LIST
2.11.2 Disadvantages
The Next address field of the last node contains a special value, known
as null value. This is not a valid address. This is only tells us that we have
reached the end of the list.
Figure shows a schematic diagram of a linked list with 3 nodes.
Figure : Linked List wity 5 nodes
The left part represents the information part of the node, which may
contain an entire record of data items(e.g., NAME, ADDRESS, . . .).
The right part represents the nextpointer field of the node, and there is
an arrow drawn from it to the next node in the list.
There are five basic types of operations associated with linked list.
1. To determine if the list is empty or not. It returns true if the list
contains no elements.
2. Create a list.
3. Add new elements anywhere in the list
4. To check if the particular element is present in the list or not.
5. To delete a particular element from the list placed any where in the list.
6. Find the size of the list
7. To print all the elements of the list.
list = null
Also, we can check whether the list is empty by checking whether the
external pointer is null.
if list = null
then
return (true)
else
return(false)
This routine will return true if the list is empty, otherwise it will return
false.
1. p = list
2. Repeat steps 3 and 4 while list <> null
3. print info(p)
4. p=next(p) [Updates pointer]
[End of Step 2 loop]
5. Return
If we do not use the traversal pointer and instead change the value of
the external pointer list, we will not be able to access that node anymore.
To add a new node containing data value x in the beginning of the list
we need to follow the step.
The above algorithm works even if the list is initially empty. Using
these steps iteratively, we can create a linked list.
Figure (a)
In order to carry out step c and d, we must find the correct place for
inserting x.
p = list
while x >= info(p)
p = next(p)
The above steps are used to find the correct place for insertion, p will
point the node that should follow the new node. This enables us to carry step
(c). But, there is no way to access the node which should precede the new
node to carry out step (d).
To overcome this problem, we must check the data field of the next
node, rather than the node itself.
p=list
while x>= info(next(p))
p=next(p)
getnode(new)
info(new)=x
p=list
while x>=info(next(p))
p=next(p)
next(new)=next(p)
next(p)=new
p = list
if x < info(p)
then
next(new) = list /* To insert new node as first
node */
list = new
else
while ....
Figure: b
Please note that, the compiler stops checking the second condition if
the first one fails.
Another special condition is to insert when the list is empty. In this
case we must check if the list is empty, we can make the list pointer point to
the new node
if list = null
list = new
Hence putting all the above conditions together our algorithm to insert
anywhere in the ordered list becomes as follows:
getnode(new)
info(new) = x
next (new) = null
if list = null
then
list = new
else
{
p = list
if x < info(p)
then
next(new) = list
list = new
else
{
while (next(p)<>null) and (x >= info (next(p)))
p = next(p)
next(new) = next(p)
next(p) = new
}
}
For example, if the node to be deleted is the first one in the list, we are
simply required to make the external pointer list equal to the next field of the
first node in the list.
Consider the following figure:
The dashed arrows in the figure shows that list now point to the next field
of the first node in the list.
The first node (data field containing 2) is still connected to the node
containing 7 but there is no way to access that node as it is not pointed to by
any pointer. Therefore, this is a logical deletion.
Also, the node that was first on the list is currently useless because it is
no longer on the list. Therefore, there should be a mechanism for making this
node available for reuse. To do this, we need to access the node. This means,
before we change pointer list to point to next node, we must assign a new
pointer to this node which we can use t access it later. Also we need to store
the value of the data item of this node. Therefore, to delete the first node, the
algorithm is as follows:
p = list
x = info(p)
list = next (list)
To find the node containing value x we have to traverse the list till we
find the node or till we reach the end of the list (the node with value x is not
present in the list).
p = list
while (p <> null) and (info (p) <> x)
p = next(p)
When we reach the node containing x, that is info (p) =x, p is pointing to
the node, we wish to delete.
But, to delete a node, we must know the address of the previous node.
Deleting the node means, changing the next pointer of the previous node to
point to the node following the node, which is to be deleted.
To solve this problem, we have to check the contents of the next node.
Another way is to keep two pointers PREV and CURRENT to traverse the
list. So that, when current points to the node to deleted, prev points to the
preceding node.
prev = null
current = list
while (current <> null) and (info (current) <> x)
{
prev = current
current = next(current)
}
next(prev) = next(current)
freenode(current)
Please note that, if the node to be deleted is the last one in the list,
which mean next of current points to null, the above two statement will work.
As in that case next(prev) will point to null, as we desire.
Suppose we want to delete the first node, we will not enter into the
search loop and therefore prev will remain null. We can add the following
steps to our algorithm.
if prev = null
then
list = next(list)
freenode (urrent)
If x doesn’t exit in the list when we dropout of the loop, current will be
null. We can check that and print a message.
Finally, we can put together these steps to make a complete algorithm
to delete a node which is as follows:
current = list
prev=null
while (current <> null) and (info(current)<>x) do
{
prev=current
current=next(current)
}
if current not null
then
if prev=null
then
list=next(list)
else
next(prev)=next(current)
freenode(current)
else
print(“Node with a given value doesn’t exist in the list”)
Figure (a)
Now, let us try to delete 2.
Since, it is the first node, prev will be null. The pointer adjustment to
delete 2 is shown in figure b.
Figure (b)
Now, let us try to delete 10. Since this node is not present in the list, it
will print a message Node with the given value doesn’t exist in the list” and
a pointer positions will be shown in figure (c).
Figure (c)
Next, we delete node 12. It is in the middle of the list. Neither current
nor prev is null. So, pointer adjustment is as shown in figure (d).
Figure (d)
Lastly, we can delete node 15 which is the last node of the list. The next
(prev) will point to next (current) which is null as shown in figure (e).
Figure (e)
1. The computer runs through all lists, tagging those cells which are
currently in use.
2. Then the computer runs through the memory, collecting all untagged
space onto the free-storage list.
The garbage collection may takes place when there is only some
minimum amount of space or no space at all left in the free storage list or
when the CPU is idle and has time to do the collection. Please note that, the
garbage collection is invisible to the programmer.
Sometimes new data are to be entered into a data structure but there is
no available space, then such situation is called Overflow. Similarly, when
one wants to delete data from a data structure, that is empty, then it is called
Underflow.
AVAIL List
Figure (a)
if (avail=null)
then
print “Overflow”
else
{
p=avail
avail=next(avail)
}
The available list will only be empty when all nodes are currently in
use and it is not possible to allocate any more. Figure(b) shows how
getnode(p) works pictorially.
Figure (b)
1. Set P=START
2. Repeat steps 3 and 4 while P<>Null
3. Write:INFO[P]
4. Set P:=LINK[P] [Update pointer]
[End of Step 2 loop]
5. Return
1. [Initialize counter]
Set Num=0
2. [Initialize pointer]
Set P=START
3. Repeat steps 3 and 4 while P<> Null
4. Set Num=Num+1 [Increment Num by 1]
5. Set P=LINK[P] [Update pointer]
[End of Step 3 loop]
6. Return
2.13.4 Searching
Let LIST is a linked list in memory. This algorithm finds the location
LOC of the node where ITEM first appears in LIST or sets LOC=NULL.
1. Set P=START
2. Repeat steps 3 while P<>NULL
3. If ITEM=INFO[P], then
Set LOC=P and Exit
Else:
Set P=LINK[P] [Pointer now points to the next node]
[End of IF structure]
[End of Step 2 loop]
4. [Search is unsuccessful?]
Set LOC=NULL
5. Exit
1. [Overflow?]
If Avail=Null, then:
Write: Overflow and Exit
2. [Remove first node from Avail list]
Set New=Avail and Avail=Link[Avail]
3. [Copies new data into new node]
Set INFO[New]=ITEM
4. [New node now points to original first node]
Set LINK[New]=START
5. [Changes START so it points to the new node]
Set START=NEW
6. Exit
This algorithm inserts ITEM so that ITEM follows the node with
location LOC or inserts ITEM as the first node when LOC=NULL.
1. [Overflow?]
If Avail= NULL, then:
Write: Overflow and Exit
2. [Remove First node from Avail list]
Set New=Avail and Avail=LINK[Avail]
3. [Copies new data into new node]
Set INFO[New]=ITEM
4. [Inset as first node]
If LOC=Null, then:
Set LINK[New]=START and START=New
Else:
[Insert after node with location LOC]
Set LINK[New]=LINK[Loc] and LINK[LOC]=NEW
[End of IF structure]
5. Exit
This algorithm deletes the node N with location LOC. LOCP is the
location of the node which precedes N or, when N is the first node, LOCP =
NULL.
Assume, we allocate 100 nodes to the program and place them all on the
available list as all nodes are initially unused. We link these nodes initially in
their natural order so that each node point to the next node in the array.
Node [0] is the first node and node [99] is the last one.
Let the link list be defined as follows:
};
struct nodetype node[maxnodes];
initialize()
{
int k;
avail = 0;
for(k=0;k<maxnodes - 1 ; k++)
node[k].next=k+l;
node[maxnodes-l].next = - 1 ;
}
Now all the 100 nodes are on the avail list. Here we have
assumed avail to be global variable. Whenever an individual list for
a particular model requires a node, a getnode function may be
called. Let us now write getnode, which removes a node from the
available list and returns a pointer to it. If there are no more nodes
available, avail contains value null that is -1 and in that case, it
prints an error message.
getnode ()
{
int p;
if (avail == -1)
{
printf ("no more nodes available \n");
exit(l);
}
p = avail;
avail = node [avail] .next ;
return (p);
}
freenode(int p)
{
node[p] .next =avail;
avail = p;
return;
}
Using the avail list, we can create four lists, one for each model. We
initialize the external pointer of all the four lists to null.
We can write a routine in C, which accepts address p of a
node and item x which is to be inserted as parameter. p is the
starting address of the list in which item x is to be inserted.
inserted (p,x)
int p, x;
{
int r,q;
/* put x into a new node */
q = getnode();
node[q] .info = x;
node[q] .next= -1;
/* insert the new node into the list */
if (p == -1)
{
p = q;
return;
}
/ * insert into empty list */
if (x < node[p] .info)
{
node[q].next = p;.
p = q;
return;
}
/* insert before first node*/
r = p;
while (node[r] .next <> -1) && (x >= node[r] .info)
{
r = node[r] .next;
}
/ * find insertion place */
node[q] .next = node[r] .next;
node[r] .next = q;
return;
/* connect the pointers */
}
The routine delete (p, x), called by the statement delete (list, val) deletes
the node containing x.)
delete (p, x)
int p, x;
{
int q, current, trail;
current = p;
trail = -1;
while (current != -1) && (node [current] .info !=x)
{
trail = current;
current = node [current] .next;
}
/* search the node with value x */
if (current == -1)
{
printf ("void deletion \n");
return;
}
/* the node with value x is not present */
if (trail == -1)
{
q = p;
p = node[p] .next;
freenode (q) ;
return;
}
/* delete the first node */
q = current;
node [trail] .next = node [current] .next;
freenode (q) ;
return;
}
struct node
{
int info;
struct node *next;
};
typedef struct node *nodeptr;
nodeptr getnode()
{
nodeptr p;
p = (nodeptr) malloc(size of(struct node));
return (p);
}
insert (p,x)
nodeptr p;
int x;
{
nodeptr r, q;
q = getnode();
q → info = x;
q → next = null;
/* insert the new node into the list */
if (p == null)
{
p = q;
return;
}
if (x < p →info)
{
q → next = p;
p = q;
return;
}
r = p;
/* find the insertion place */
while (r → next != null) && (x >= r → info)
r = r → next;
q → next = r → next;
r → next = q;
return;
/* connect the pointers */
}
#include <stdio.h>
#include <conio.h>
#include <alloc.h>
struct node
{
int data;
struct node *link;
};
void append (struct node **);
void delete (struct node **);
void display (struct node *);
int count (struct node *);
void search (struct node *);
main ( )
{
int ch;
struct node *list=NULL;
while (1)
{
clrscr();
printf(“\n1. ADD A NODE\n”);
printf(“2. DELETE A NODE\n”);
printf(“3. SEARCH \n”);
printf(“4. VIEW THE LIST \n”);
printf(“5. COUNT THE LIST \n”);
printf(“6. QUIT\n”);
printf(“\nENTER YOUR CHOICE:”);
scanf (“%d”, &ch) ;
switch (ch)
{
case 1: append (&list);
break;
case 2: delete (&list);
break;
case 3: search (&list);
break;
case 4: display (&list);
break;
case 5: printf(“ Number of nodes in the list = %d”,i);
getch;
break;
case 6: exit();
default: printf(“Invalid choice ….. Try again……\n”);
}
}
}
}
}
}
}
1. A grounded header list is a header list where the last node contains the
null pointer.
Figure (a). Grounded Header List
2. A circular header list is a header list where the last node points back to
the header node.
Observe that the list pointer START always points to the header node.
Accordingly, LINK[START] = NULL indicates that a grounded header list is
empty, and LINK[START] = START indicates that a circular header list is
empty.
1. The null pointer is not used, and hence all pointers contain valid
addresses.
2. Every (ordinary) node has a predecessor, so the first node may not
require a special case.
A linked list whose last node points back to the first node instead of
containing the null pointer, called a circular list.
Observe that the null pointer appears in the NEXT field of the last node
in the list and also in the BACK field of the first node in the list.
Advantages:
1. It is more efficient.
P(x)=2x8 – 3 x4 – 2x2 + 4x + 5
2.18 PROBLEMS
1. Let LIST be a linked list in memory. Write a procedure which
Solution:
a.
1. [Initialize Counter]
Set NUM=0
2. [Initialize pointer P]
Set P:= START
3. Repeat steps 4 and 5 while P<> Null
4. Apply PROCESS to INFO[P]
5. If INFO[P]=ITEM, then: set NUM=NUM+1
[End of Step 3 loop]
6. Exit
b.
a. [Initialize Counter]
Set NUM=0
b. [Initialize pointer P]
Set P:= START
3. Repeat steps 4 and 5 while P<> Null
4. Apply PROCESS to INFO[P]
5. If INFO[P] <> ITEM, then: set NUM=NUM+1
[End of Step 3 loop]
6. Exit
c.
1. [Initialize Counter]
Set NUM=0
2. [Initialize pointer P]
Set P:= START
3. Repeat steps 4 and 5 while P<> Null
4. Apply PROCESS to INFO[P]
5. Set INFO[P] =INFO[P]+1
[End of Step 3 loop]
6. Exit
Solution
The last node can be deleted only when one also knows the location of
the next-to-last Accordingly, traverse the list using a pointer variable P, and
keep track of the preceding node using pointer variable SAVE. P points to the
last node when LINK[P] = NULL, and in such a case, SAVE points to the next
to last node. The case that LIST has only one node is treated separately, since
SAVE can be defined only when the list has 2 or more elements. The
algorithm follows.
1. [List empty?]
If START = NULL, then Write: UNDERFLOW, and Exit.
2. [List contains only one element?]
If LINK[START] = NULL, then:
a. Set START:= NULL. [Removes only node from list]
b. Set LINK[START]:= AVAIL and AVAIL:= START.
[Returns node to AVAIL list.]
c. Exit
[End of If structure.]
3. Set P:= LINK[START] and SAVE:= START. [Initializes pointers]
4. Repeat while LINK[P] <> NULL. [Traverses list, seeking last node.]
Set SAVE:= P and P:= LINK[P]. [Updates SAVE and P].
[End of loop.]
5. Set LINK[SAVE]:= LINK[P]. [Removes last node.]
6. Set LINK[P]:= AVAIL and AVAIL:= P. [Returns node to AVAIL List]
7. Exit.
First set NAME2:= NULL to form an empty list. Then traverse NAME1
using a pointer variable P, and while visiting each node of NAME1, copy its
contents INFO[P] into a new node, which is then inserted at the end of
NAME2. Use LOC to keep track of the last node of NAME2 during the
traversal. Inserting the first node into NAME2 must be treated separately,
since LOC is not defined until NAME2 has at least one node. The algorithm
follows:
This algorithm makes a copy of a list NAME1 using NAME2 as the list
pointer variable of the new list.
The algorithm for deleting the last node from the header list.
6. Imagine we have the two linked lists shown below. What would happen
if we apply the following statement to these two lists?
list1=list2
Solution:
list1 no longer points to the head of the first list, rather it points to the
head of the second list in the figure shown below.
1. temp=pList
2. loop (temp->link not null)
i. temp=temp->link
3. temp->link=pList
Solution:
This will create a circularly linked list.
Solution:
Header is a unique pointer that is used to keep track of the head or the
first node of the list. Executing statements like header = header → link
modifies header which no longer points to the first node of the list, an
effect that may be devastating for the whole program.
2.19 STACK
Examples:
A stack of books, stack of folded towels, stack of discs, stack of coins,
computer stack
a. Push
It is used to insert an element into the stack.
b. Pop
It is used to remove an element from the stack.
c. Stack Top
It copies the item at the top of the stack. That is, it returns the
data in the top element to the user but does not delete it. It can also
result in underflow if the stack is empty.
Example:
Suppose the following 6 elements are pushed, in order, onto an empty
stack:
AA, BB, CC, DD, EE, FF
Please note that, EEE cannot be deleted before FFF is deleted, DDD
cannot be deleted before EEE and FFF are deleted, and so all.
Since TOP = 6, the stack has six elements, AA, BB, CC, DD, EE and FF.
and since MAXSTACK = 12, there is room for 6 more items in the stack.
This procedure deletes the top element of STACK and assigns it to the
variable ITEM.
1. Reversing a data
2. Parsing
3. Postponement
It is used to convert infix to postfix notation and also to evaluate a
postfix notation.
4. Backtracking
It is used to make decisions between two or more paths. Backtracking
is found in applications such as computer gaming, decision analysis and
expert systems.
2.19.5.2 Parsing
Parsing is a logic that breaks data into independent pieces for further
processing. For example, to translate a source program into machine
language, a compiler must parse the program into individual parts such as
keywords, names and tokens.
The common problem you have faced is unmatched parenthesis in an
algebraic expression. When parenthesis are unmatched, two types of error can
occur:
1. The opening parenthesis can be missing
Example: ((A+B)/C
2. The closing parenthesis can be missing
Example: (A+B)/C)
2.19.5.3 Postponement
It is used to convert infix to postfix notation and also to evaluate a postfix
notation.
An arithmetic expression can be represented in three different formats:
infix, prefix and postfix.
Infix Notation
Disadvantage:
1. We need to use parenthesis to control the evaluation of the
operators.
Prefix Notation
In a prefix expression, the operator is placed before the two operands.
Example:
+ab
Postfix Notation
In a postfix expression, the operator is placed after the two operands.
Example:
ab+
1. Evaluate parenthesis
2. Evaluate power
3. Evaluate multiplication and division; the operations are done from left
to right.
4. Evaluate addition and subtraction; the operations are done from left to
right.
5. Change all infix notations in each parenthesis to postfix notation
starting from the innermost expressions.
6. Remove all parenthesis.
Example:
Infix Notation Postfix Notation
ABC*+
A+B*C
A B + C * D + E F * +G -
(A+B)*C+D+E*F-G
AB*C+
A*B+C
ABC*DE/-+
A+B*C-D/E
AB*CD+-E+
A*B-(C+D)+E
AB+C-
A+B – C
AB+CD-*
(A+B)*(C-D)
ABC+*D*
A*(B+C)*D
BC*D-EF/GH+/+
B*C-D+E/F/(G+H)
ABC*DEF↑/G*-H*H
A+(B*C-(D/E↑F)*G)*H
AB-DE/*
A-B*(D/E)
ABD↑+EF-/G+
(A+B↑D)/(E-F)+G
ABD+*E/FGHK/+*-
A*(B+D)/E-F*(G+H/K)
AB+D*EF-↑
((A+B)*D) ↑(E-F)
Example:
2.19.5.4 Backtracking
It is used to make decisions between two or more paths. It is found in
application such as computer gaming, decision analysis and expert systems.
Examples of backtracking are: Goal seeking and Eight-queens problem.
Algorithm
This algorithm finds the VALUE of an arithmetic expression P
written in postfix notation.
Please note that, when Step 5 is executed, there should be only one
number on STACK.
Algorithm
1. [Initialize]
match=True;
stack=empty;
2. Read symbol from input string
3. While not end of input string and matching
{
If symbol =’(‘ or ‘{‘ or ‘[‘
Push(symbol,stack);
Else
If symbol =’)’ or ‘}’ or ‘]’ or
if stack is empty
then
match=false
Write (“More right parenthesis than left parenthesis”)
Else
C=pop(stack)
Match c and the input symbol;
If not matched
{
match=false;
write(“Mismatched parenthesis”);
}
read the next input symbol;
}
if stack is empty then
write (“Parenthesis are balanced properly”)
else
write (“More left parenthesis than write parenthesis”)
2.19.8 Eight Queens Problem (using stack and backtracking logic)
A classic chess problem requires that you place eight queens on the
chessboard in such a way that no queen can capture another queen. A queen
can attack another queen if it is in the same row, same column or on a
diagonal. There are actually several solutions to this problem. The computer
solution to this problem requires that we place a queen on the board and then
analyze all of the attack positions to see if there is a queen that could capture
the new queen. If there is, then we try another queen.
Now, let us first demonstrate four queen’s on a four-by-four
chessboard. The queens capture rule and one solution are shown in figure.
After placing a queen in the first row, we look for a position in the
second row. Position 2, 1 is not possible because the queen in the first row is
guarding this solution on the vertical. Likewise, position 2, 2 is guarded on
the diagonal. We therefore place a queen in the third column in row 2 and
push this location into the stack. This is shown below.
We now begin to locate a position in row 3. It is noted that, none of the
positions in row 3 are possible. The first column is guarded by the queen in
row one, and the other three positions are guarded by the queen in row two.
At this point we must backtrack the second row by popping the stack and
continue looking for a position for the second row queen. Because column
four is not guarded, we place a queen there and push its location into the
stack. This is shown below:
Looking again at row three, we see that the first column is still guarded
by the queen in row one, but that we can place a queen in the second column.
We do so and push this location into the stack. This is shown below.
When we try to place a queen in row four, however we find that all
positions are guarded. Column one is guarded by the queen in row one and
the queen in row three.
Column two is guarded by the queen in row two and the queen in row
three.
Column three is guarded by the queen in row three and the column
four is guarded by both the queen in row one and the queen in row two.
We therefore backtrack to the queen in row three and try to find
another place for her. Because the queen in row two is guarding both column
three and column four, there is no position for a queen in row three. Once
again backtrack by popping the stack and find that the queen in row two has
nowhere else to go, so we backtrack to the queen in row one and move her to
column two. This is shown below.
Analyzing row two, we see that the only possible solution for a queen
is column four because the queen in row one is guarding the first three
positions. We therefore place the queen in this location and push the location
into the stack. This is shown below.
2.19.9 PROBLEMS
Solution:
The POP procedure always deletes the top element from the stack, and
the PUSH procedure always adds the new element to the top of the stack.
Accordingly:
a. STACK: A,C,D,F,_,_,_,
b. STACK: A, C, D, -, -, -, -, -
c. STACK: A, C, D, L, -, -, -, -
d. STACK: A, C, D, L, P, -, -, -
e. STACK: A, C, D, L, -, -, -, -
f. STACK: A, C, D, L, R, -, -, -
g. STACK: A, C, D, L, R, S, -, -
h. STACK: A, C, D, L, R, -, -, -
2. Consider the data in above problem. (a) When will overflow occur?
(b) When will C be deleted before D?
Solution:
a. Since STACK has been allocated N = 8 memory cells, overflow
will occur when STACK contains 8 elements and there is a
PUSH operation to add another element to STACK.
b. Since STACK is implemented as a stack, C will never be deleted
before D.
3. Consider the following stack, where STACK is allocated N = 6
memory cells:
STACK: AA, DD, EE, FF, GG, -
Describe the stack as the following operations take place:
a. PUSH(STACK,KK)
b. POP(STACK, ITEM)
c. PUSH(STACK,LL)
d. PUSH(STACK,SS)
e. POP(STACK, ITEM)
f. PUSH(STACK, TT).
Solutions:
a. KK is added to the top of STACK, yielding
STACK: AA,DD,EE,FF,GG,KK
b. The top element is removed from STACK, yielding
STACK: AA, DD, EE, FF, GG,-
c. LL is added to the top of STACK, yielding
STACK: AA, DD, EE, FF, GG, LL
d. Overflow occurs, since STACK is full and another element SS is to be
added to STACK.
e. The top element is removed from STACK, yielding
STACK: AA, DD, EE, FF, GG,-
f. TT is added to the top of STACK, yielding
STACK: AA, DD, EE, FF, GG, TT
Solution:
Observe that, this is the reverse of the order in which the elements
were added to stack.
Solution:
a. Scanning from left to right, translate each operator from postfix to infix
notation. (We use brackets [ ] to denote a partial translation.)
P = 12, [7 - 3], /, 2, 1, 5, +, *, +
= [12/(7 - 3)], 2, 1, 5, +, *, +
= [12/(7 - 3)], 2, [1 + 5], *, +
= [12/(7 - 3)], [2 * (1 + 5)], +
= 12/(7 - 3) + 2* (1 + 5)
b. Using the infix expression, we obtain:
P = 12/(7 - 3) + 2 * (1 + 5)
= 12/4 + 2 * 6
= 3 + 12
= 15
Solution:
SOLUTION:
Solution:
a. 7 b. 9
8. Change the following infix expressions to postfix expressions using
the algorithmic method (a stack).
a. D – B + C b. A * B + C * D
c. (A + B) * C – D * F + C d. (A – 2 * (B + C) – D * E) * F
Solution:
a.
Figure also indicates the way elements will be deleted from the queue
and the way the new elements will be added to the queue. Observe that
whenever an element is deleted from the queue, the value of FRONT is
increased by 1; this can be implemented by the assignment
FRONT: = FRONT + 1
REAR:=REAR+ 1
This, means that after N insertions, the rear element of the queue will
occupy QUEUE[N] or, in other words, the queue will occupy the last part of
the array. This occurs even though the queue may not contain many elements.
2.20.4 DEQUES
A deque is a linear list in which elements can be added or removed at
either end but not in the middle.
There are various ways of representing a deque in a computer. The
deque is maintained by a circular array DEQUE with pointers LEFT and
RIGHT, which point to the two ends of the deque. We assume that the
elements extend from the left end to the right end in the array. The term
"circular" comes from the fact that we assume that DEQUE[1] comes after
DEQUE[N] in the array.
There are two variations of a deque-namely, an input -restricted deque
and an output-restricted deque-which are intermediate between a deque and
a queue.
An input-restricted deque is a deque which allows insertions at only
one end of the list but allows deletions at both ends of the list.
An output-restricted deque is a deque which allows deletions at only
one end of the list but allows insertions at both ends of the list.
Here,
1. Each node in the list will contain three items of information:
a. An information field INFO
b. A priority number PRNUM
c. A link number LINK.
2. A node X precedes a node Y in the list
a. When X has higher priority than Y or
b. When both have the same priority but X was added to the list
before Y.
This means that, the order in the one-way list
corresponds to the order of the priority queue.
Example:
Consider the following figure:
Algorithm :
This algorithm deletes and processes the first element in a priority
queue which appears in memory as a one-way list.
1. Set ITEM:= INFO[START].
[This saves the data in the first node.]
2. Delete first node from the list.
3. Process ITEM.
4. Exit.
Algorithm:
This algorithm adds an ITEM with priority number N to a priority
queue which is maintained in memory as a one-way list.
1. Traverse the one-way list until finding a node X whose
priority number exceeds N. Insert ITEM in front of node X.
2. If no such node is found, insert ITEM as the last element of the
list.
Example:
FRONT REAR 1 2 3 4 5 6
1 2 2 1 AAA
2 1 3 2 BBB CCC XXX
3 0 0 3
4 5 1 4 FFF DDD EEE
5 4 4 5 GGG
Algorithm:
Algorithm :
This algorithm adds an ITEM with priority number M to a priority
queue maintained by a two-dimensional array QUEUE.
1. Insert ITEM as the rear element in row M of QUEUE.
2. Exit.
2.20.7 PROBLEMS
Solution:
a. F is added to the rear of the queue, yielding FRONT = 2, REAR = 5
Queue : -, A, C, D, F, -
Note that REAR is increased by 1.
b. The two letters, A and C, are deleted, leaving FRONT = 4, REAR = 5
QUEUE: -, -, -, D, F,
Note that FRONT is increased by 2.
c. K, L and M are added to the rear of the queue. Since K is placed
in the last memory cell of QUEUE, L and M are placed in the first
two memory cells. This yields FRONT = 4, REAR = 2
QUEUE: L, M, _ , D, F, K
Note that REAR is increased by 3 but the arithmetic is modulo 6:
REAR = 5 + 3 = 8 = 2 (mod 6)
d. The two front letters, D and F are deleted, leaving
FRONT = 6, REAR = 2 QUEUE: L, M, -, -, -, K
e. R is added to the rear of the queue, yielding
FRONT = 6, REAR = 3, QUEUE: L, M, R, -, -, K
f. The two front letters, K and L, are deleted, leaving FRONT=2,
REAR=3,
QUEUE: -, M, R, -, -,
Note that FRONT is increased by 2 but the arithmetic is
modulo 6:
FRONT=6+2=8=2(mod 6)
g. S is added to the rear of the queue, yielding
FRONT = 2, REAR = 4 QUEUE: -, M, R, S, -, -
h. The two front letters, M and R, are deleted, leaving FRONT = 4,
REAR = 4
QUEUE: -, -, -, S, -,
i. The front letter S is deleted. Since FRONT = REAR, this means
that the queue is empty; hence assign NULL to FRONT and
REAR. Thus
FRONT = 0, REAR = 0 QUEUE: -, -, -, -, -, -
j. Since FRONT= NULL, no deletion can take place. That is,
underflow has occurred.
Solution:
Solution:
a. If the element is added on the left, then LEFT is decreased by 1 (mod
N). On the other hand, if the element is added on the right, then
RIGHT is increased by 1 (mod N).
b. If the element is deleted from the left, then LEFT is increased by 1 (mod
N). However if the element is deleted from the right, then RIGHT is
decreased by 1 (mod N). In the case that LEFT = RIGHT before the
deletion (that is, when the deque has only one element), then LEFT and
RIGHT are both assigned NULL to indicate that the deque is empty.
1 2 3 4 5 6
1 AAA SS MM
2 BBB CCC XXX NN
3 PP
4 FFF RR II DDD EEE
5 GGG
b. First delete the elements with the highest priority in row 1. Since
row 1 contains three elements AAA, SS and MM, then the front
element in row 2, BBB is also deleted. The resulting structure is as
shown below.
1 2 3 4 5 6
1
2 BBB CCC XXX NN
3 PP
4 FFF RR II DDD EEE
5 GGG
Please note that, in both cases the FRONT and REAR elements
are changed accordingly.
The data are: 5, 7, 12, 4, 0, 4, 6, 8, 67, 34, 23, 5, 0, 44, 33, 22, 6, 0
Solution:
5, 7, 12, 4, 4, 4, 6, 8, 67, 34, 23, 5, 5, 44, 33, 22, 6, 6
The data are: 5, 7, 12, 4, 0, 4, 6, 8, 67, 34, 23, 5, 0, 44, 33, 22, 6, 0.
Solution
7, 5, 34, 67, 8, 6, 4, 33, 44
2.21 Recursion
n! = {
1
n x (n - 1)!
if n = 0
if n > 0
Now, let us consider the case of 4! , since n>0, we use the second clause of
the definition
4! = 4 x 3!
= 4 x (3 x 2!)
= 4 x (3 x (2 x 1!))
= 4 x (3 x (2 x (1 x 0!)))
= 4 x (3 x (2 x (1 x 1)))
= 4 x (3 x (2 x 1))
= 4 x (3 x 2)
= 4 x (6)
= 24.
Such definition is called iterative because it calls for the explicit relation of
some process until a certain condition is met.
The C language routine for calculating factorial of n is as follows:
factorial(n)
int n;
{
int x;
if (n==0)
return 1;
else
x=n-1;
return(n*factorial(x));
}
Note that, the second return statement factorial calls itself. This is essential
for recursive routine. Therefore, a procedure call to itself or a procedure call to a
second procedure, which eventually causes the first procedure to be called, is
known as recursive procedure.
The general algorithm for recursive procedure is as follows:
1. Save the parameters, local variables and return address
2. If the base criterian has been reached, then perform the final computation
and go to step 3, otherwise perform the partial computation and go to step 1
with reduced parameter values (initiate a recursive call)
3. Restore the most recently saved parameters, local variables and return
address. Go to this return address.
Note:
One should not use recursion if the answer to any of the following
questions is no.
1. Is the algorithm or data structure naturally suited to recursion?
2. Is the recursion solution shorter and more understandable?
3. Does the recursive solution run in acceptable time and space limits?
Now, let us convert this algorithm to C program. For that let us decide about
the input and output to the program. As an input to the program, we must give n,
the number of disks. Apart from number of disks, we must also specify the needles
which are to act as the initial needle from which we are moving disks, the final
needle to which we are moving disks and temporary needle.
We must also decide about the names of the disks. Let the numbering itself
represents the names of the disks. The smallest disk, which is on the top of the
needle is numbered 1, the next disk is 2 and so on. Such that the largest disk is
represented by number n.
The output from the program could be a list statements as:
void main()
{
int n;
printf(“Enter number of disks to be moved\n”);
scanf(“%d”,&n);
hanoi (n,’A’,’B’,’C’);
}
2.21.1.6 PROBLEMS:
Solution:
a. Q(2,3) = 0, since 2 < 3.
Q(14, 3) = Q(11, 3) + 1
= [Q(8, 3) + 1] + 1 = Q(8, 3) + 2
= [Q(5, 3) + 1] + 2 = Q(5, 3) + 3
= [Q(2, 3) + 1] + 3 = Q(2, 3) + 4
=0+4=4
Solution:
Here, m = 1 and n = 3
Solution:
a.
3*4 = 12
b.
(2*fun1(5) + 7)
= (2 * (2 *fun1(0) +7) + 7)
= (2 * (2*(3 * 0) +7) + 7)
= 21
c.
(2* fun1(7)+7)
= (2* (2* fun1(2)+7) + 7)
= (2* (2* (3*2) + 7) + 7
= 45
Solution:
a.
-1
b.
-1
c.
(4 * fun2(5, 7))
= (4 * (5 * fun2(6, 7)))
= 4 * (5 * (6* fun2(7, 7)))
=4*5*6*1
= 120
d.
1
Review Questions