Ds 01
Ds 01
1. It must be rich enough in structure to mirror the actual relationships of the data in the real world.
2. The structure should be simple enough that one can effectively process the data whenever necessary.
Basic Terminology: Elementary Data Organization:
Data items that are divided into sub-items are called Group items. Ex: An Employee Name may be
divided into three subitems- first name, middle name, and last name.
Data items that are not able to divide into sub-items are called Elementary items. Ex: SSN
Entity: An entity is something that has certain attributes or properties which may be assigned values.
The values may be either numeric or non-numeric.
Each record in a file may contain many field items but the value in a certain field may uniquely
determine the record in the file. Such a field K is called a primary key and the values k1, k2, ….. in
such a field are called keys or key values.
Example: Student records have variable lengths, since different students take different numbers of
courses. Variable-length records have a minimum and a maximum length. The above organization of
data into fields, records and files may not be complex enough to maintain and efficiently process certain
collections of data. For this reason, data are also organized into more complex types of structures.
The study of complex data structures includes the following three steps:
3. Quantitative analysis of the structure, which includes determining the amount of memory needed to
store the structure and the time required to process the structure.
1. Primitive data Structures: Primitive data structures are the fundamental data types which are
supported by a programming language. Basic data types such as integer, real, character and Boolean are
known as Primitive data Structures. These data types consists of characters that cannot be divided and
hence they also called simple data types.
2. Non-Primitive data Structures: Non-primitive data structures are those data structures which are
created using primitive data structures. Examples of non-primitive data structures is the processing of
complex numbers, linked lists, stacks, trees, and graphs.
Based on the structure and arrangement of data, non-primitive data structures is further classified into
1. Linear Data Structure: A data structure is said to be linear if its elements form a sequence or a linear
list. There are basically two ways of representing such linear structure in memory.
1. One way is to have the linear relationships between the elements represented by means of
sequential memory location. These linear structures are called arrays.
2. The other way is to have the linear relationship between the elements represented by means
of pointers or links. These linear structures are called linked lists.
The common examples of linear data structure are Arrays, Queues, Stacks, Linked lists
2. Non-linear Data Structure: A data structure is said to be non-linear if the data are not arranged in
sequence or a linear. The insertion and deletion of data is not possible in linear fashion. This structure
is mainly used to represent data containing a hierarchical relationship between elements. Trees and
graphs are the examples of non-linear data structure.
The data appearing in data structures are processed by means of certain operations. The
following four operations play a major role in this text:
1. Traversing: accessing each record/node exactly once so that certain items in the record may
be processed. (This accessing and processing is sometimes called “visiting” the record.)
2. Searching: Finding the location of the desired node with a given key value, or finding the
locations of all such nodes which satisfy one or more conditions.
1. Sorting: Arranging the records in some logical order (e.g., alphabetically according to some
NAME key, or in numerical order according to some NUMBER key, such as social security
number or account number)
2. Merging: Combining the records in two different sorted files into a single sorted file
C provides extensive support for pointers. The actual value of a pointer type is an address of memory.
The two most important operators used with the pointer type are:
pi = &i;
then &i returns the address of i and assigns it as the value ofpi. To assign a value to i we can say:
i= 10;
or
*pi 10;
In both cases the integer 10 is stored as the value of i. In the second case, the * in front of the pointer pi
causes it to be dereferenced, by which we mean that instead of storing 10 into the pointer, 10 is stored
into the location pointed at by the pointer pi.
There are other operations we can do on pointers. We may assign a pointer to a variable of type pointer.
Since a pointer is just a nonnegative integer number, C allows us to perform arithmetic operations such
as addition, subtraction, multiplication, and division, on pointers. We also can determine if one pointer
is greater than, less than, or equal to another, and we can convert pointers explicitly to integers.
The size of a pointer can be different on different computers. In some cases the size of a pointer on a
computer can vary. For example, the size of a pointer to a char can be longer than a pointer to a float. C
has a special value that it treats as a null pointer. The null pointer points to no object or function.
Typically the null pointer is represented by the integer 0. There is a macro called NULL which is defined
to be this constant. The macro is defined either in stddefh for ANSI C or in stdio.h for K&R C. The null
pointer can be used in relational expressions, where it is interpreted as false.
if (pi == NULL)
or more simply:
if (!pi)
In your program you may wish to acquire space in which you will store information. When you write
your program you may not know how much space you will need, nor do you wish to allocate some very
large area that may never be required. To solve this problem C provides a mechanism, called a heap, for
allocating storage at run-time. Whenever you need a new area of memory, you may call a function,
malloc, and request the amount you need. If the memory is available, a pointer to the start of an area of
memory of the required size is returned. At a later time when you no longer need an area of memory,
you may free it by calling another function, free, and return the area of memory to the system. Once an
area of memory is freed, it is improper to use it. The following program shows how we might allocate
and deallocate storage to pointer variable
The call to malloc includes a parameter that determines the size of storage required to hold the int or
the float. The result is a pointer to the first address of a storage area of the proper size. The type of the
result can vary. On some systems the result of malloc is a char *, a pointer to a char. However, those
who use ANSI C will find that the result is void *. The notation {int *) and (float *) are type cast
expressions. They transform the resulting pointer into a pointer to the correct type. The pointer is then
assigned to the proper pointer variable. The free function deallocates an area of memory previously
allocated by malloc. In some versions of C, free expects an argument that is a char *, while ANSI C
expects void *. However, the casting of the argument is generally omitted in the call to free
pf = (float * ) malloc(sizeof(float));
immediately after the printf statement, then the pointer to the storage used to hold the value 3.14 has
disappeared. Now there is no way to retrieve this storage. This is an example of a dangling reference.
Whenever all pointers to a dynamically allocated area of storage are lost, the storage is lost to the
program. As we examine programs that make use of pointers and dynamic storage, we will make it a
point to always return storage after we no longer need it
By using pointers, we can attain a high degree of flexibility and efficiency. But pointers can be
dangerous as well. When programming in C, it is a wise practice to set all pointers to NULL when they
are not actually pointing to an object. This makes it less likely that you will attempt to access an area of
memory that is either out of range of your program or that does not contain a pointer reference to a
legitimate object. On some computers, it is possible to dereference the null pointer and the result is
NULL, permitting execution to continue. On other computers, the result is whatever the bits are in
location zero, often producing a serious error.
Another wise programming tactic is to use explicit type casts when converting between pointer types.
For example:
Another area of concern is that in many systems, pointers have the same size as type int. Since int is the
default type specifier, some programmers omit the return type when defining a function. The return type
defaults to int which can later be interpreted
The simplest type of data structure is a linear (or one dimensional) array. A list of a finite
number n of similar data referenced respectively by a set of n consecutive numbers, usually 1,
2, 3 . . . . . . . n. if A is chosen the name for the array, then the elements of A are denoted by
subscript notation a1, a2, a3….. an or
or
by the bracket notation A [1], A [2], A [3].............A [n]
For example,
declares two arrays each containing five elements. The first array defines five integers, while
the second defines five pointers to integers. In C all arrays start at index 0, so list[0], list[l],
list[2], list[3] are the names of the five array elements, each of which contains an integer value.
Similarly, plist[0], plist[1], plist[2], plist[3], and plist[4] are the names of five array elements,
each of which contains a pointer to an integer.
int *listl;
and
The variables list1 and list2 are both pointers to an int, but in the second case five memory
locations for holding integers have been reserved, list2 is a pointer to list2[0] and list2+i is a
pointer to list2[i]. Notice that in C, we do not multiply the offset i with the size of the type to
get to the appropriate element of the array. Thus, regardless of the type of the array list2, it is
always the case that (list2 + i) equals &list2[i]. So, *(list2 + i) equals list2[i].
It is useful to consider the way C treats an array when it is a parameter to a function. All
parameters of a C function must be declared within the function. However, the range of a one-
dimensional array is defined only in the main program since new storage for an array is not
allocated within a function. If the size of a one-dimensional array is needed, it must be either
passed into the function as an argument or accessed as a global variable.
Consider Program 2.1. When sum is invoked, input = &input [0] is copied into a temporary
location and associated with the formal parameter list. When /z5r[zj occurs on the right-hand
side of the equals sign, a dereference takes place and the value pointed at by (list + z) is
returned. If list[i} appears on the left-hand side of the equals sign, then the value produced on
the right-hand side is stored in the location (list 4- z). Thus in C, array parameters have their
values altered, despite the fact that the parameter passing is done using call-by-value.
int one[] = { 0 , 1, 2 , 3 , 4 } ;
We would like to write a function that prints out both the address of the zth element of this array and
the value found at this address. To do this, print1{Program 2.2) uses pointer arithmetic. The function
is invoked as print1(&one[0],5). As you can see from the printf statement, the address of the ith
element is simply ptr + i. To obtain the value of the ith element, we use the dereferencing operator, *.
Thus, *(ptr + i) indicates that we want the contents of the ptr+i position rather than the address.
In C, a way to group data that permits the data to vary in type. This mechanism is called the
structure, for short struct.
A structure (a record) is a collection of data items, where each item is identified as to its type
and name.
Syntax: struct {
data_type member 1;
data_type member 2;
……………………… ………………………
data_type member n; } variable_name;
Ex: struct {
char name[10];
int age;
float salary; } Person;
The above example creates a structure and variable name is Person and that has three fields:
Ex: strcpy(Person.name,“james”);
Person.age = 10;
Person.salary = 35000;
Type-Defined Structure
The structure definition associated with keyword typedef is called Type-Defined Structure.
Structure Operation
The various operations can be performed on structures and structure members.
1. Structure Equality Check:
Here, the equality or inequality check of two structure variable of same type or dissimilar type
is not allowed
typedef struct{
char name[10];
int age;
float salary;
}humanBeing;
humanBeing person1, person2;
if (person1 = = person2) is invalid.
The valid function is shown below
#define FALSE 0
#define TRUE 1
if (humansEqual(person1,person2))
printf("The two human beings are the same\n");
else
printf("The two human beings are not the same\n");
SELF-REFERENTIAL STRUCTURES
A self-referential structure is one in which one or more of its components is a pointer to itself.
Self-referential structures usually require dynamic storage management routines (malloc and
free) to explicitly obtain and release memory.
Consider as an example:
typedef struct {
char data;
struct list *link ;
}list;
Each instance of the structure list will have two components data and link.
• Data: is a single character,
• Link: link is a pointer to a list structure. The value of link is either the address in memory of
an instance of list or the null pointer.
Consider these statements, which create three structures and assign values to their respective
fields:
list item1, item2, item3;
item1.data = 'a';
item2.data = 'b';
item3.data = 'c';
item1.link = item2.1ink = item3.link = NULL;
Structures item1, item2 and item3 each contain the data item a, b, and c respectively, and the
null pointer. These structures can be attached together by replacing the null link field in item2
with one that points to item 3 and by replacing the null link field in item 1 with one that points
to item 2.
item1.link = &item2;
item2.1ink = &item3;
Unions:
Unions: A union is similar to a structure, it is collection of data similar data type or dissimilar.
Syntax: union{
data_type member 1;
data_type member 2;
………………………
………………………
data_type member n;
}variable_name;
Example:
union{
int children;
int beard;
} u;
Union Declaration:
A union declaration is similar to a structure, but the fields of a union must share their memory
space. This means that only one field of the union is "active" at any given time.
union{
char name;
int age;
float salary;
}u;
The major difference between a union and a structure is that unlike structure members whichare
stored in separate memory locations, all the members of union must share the same memory
space. This means that only one field of the union is "active" at any given time.
• Polynomial Representation in C:
• We have a polynomial,
•
• It is a collection of terms with a single variable ‘x’. Now let us see how to evaluate
a polynomial and perform the addition of polynomials. Once we know addition, we
can also learn how to perform subtraction and multiplication of polynomials.
Abstract Definition of Polynomial
What is a sparse matrix?
Sparse matrices are those matrices that have the
majority of their elements equal to zero. In other
words, the sparse matrix can be defined as the
matrix that has a greater number of zero elements
than the non-zero elements.
o Array representation
o Linked list representation
Example -
#include<stdio.h>
#include<stdlib.h>
struct list
{
int row, column, value;
struct list *next;
};
struct list *HEAD=NULL;
void insert(int, int , int );
void print ();
int main()
{
int Sparse_Matrix[4][4] ={ {9 , 0 , 0 , 0 },{0 , 0 , 0 , 0 },{0 ,
5 , 0 , 8 },{3 , 0 , 0 , 0 } };
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
if(Sparse_Matrix[i][j] != 0)
{
insert(i, j, Sparse_Matrix[i][j]);
}
}
}
// print the linked list.
print();
}
void insert( int r, int c, int v)
{
struct list *ptr,*temp;
int item;
ptr = (struct list *)malloc(sizeof(struct list));
if(ptr == NULL)
{
printf("\n OVERFLOW");
}
else
{
ptr->row = r;
ptr->column = c;
ptr->value = v;
if(HEAD == NULL)
{
ptr->next = NULL;
HEAD = ptr;
}
else
{
temp = HEAD;
while (temp -> next != NULL)
{
temp = temp -> next;
}
temp->next = ptr;
ptr->next = NULL;
}
}
}
void print()
{
struct list *tmp = HEAD;
printf("ROW NO COLUMN NO. VALUE \n");
while (tmp != NULL)
{
printf("%d \t\t %d \t\t %d \n", tmp->row, tmp->column,
tmp->value);
tmp = tmp->next;
}
}
Multidimensional Arrays in C
#include <stdio.h>
int main()
{ int a[2][3] = { { 1, 3, 2 }, { 6, 7, 8 } };
int i, j;
for (i = 0; i < 2; i++) {
for (j = 0; j < 3; j++) {
printf("\n a[%d][%d]=%d", i, j, a[i][j]);
} }
return 0;
}
Output
a[0][0]=1
a[0][1]=3
a[0][2]=2
a[1][0]=6
a[1][1]=7
a[1][2]=8
Declare string in C:
char str_name[size];
Initialize String in C:
C String Functions:
C String Program:-
#include<stdio.h>
#include<conio.h>
void main()
printf(“%s”,str);
getch();
C String Functions –
String.h file header in C language supports all the string
functions. All string functions are given below:-
C String Program:
Output :
Enter the first string: Ram
Enter the second string: Sham
Show First string length: 3
Show Frist string Lower case: ram
Show First string Upper case: RAM
Concatenate two String: RAMSham
Show string Reverse order: mahSMAR
Copy string str1 to str3: mahSMAR
Another example Practical program 2 given.
String Insertion:
Abstract Data Type Definition of Stack
STACKS AND QUEUES
STACKS
“A stack is an ordered list in which insertions (pushes) and deletions (pops) are
made at oneend called the top.”
Given a stack S= (a0, ... ,an-1), where a0 is the bottom element, an-1 is the top
element, and ai ison top of element ai-1, 0 < i < n.
As shown in above figure, the elements are added in the stack in the order A, B, C,
D, E, then E is the first element that is deleted from the stack and the last element
is deleted from stack is A. Figure illustrates this sequence of operations.
Since the last element inserted into a stack is the first element removed, a stack is
also known as a Last-In-First-Out (LIFO) list.
1. Stack Create
Stack CreateS(maxStackSize )::=
#define MAX_STACK_SIZE 100 /* maximum stack size*/
typedef struct
{
int key;
/* other fields */
} element;
element stack[MAX_STACK_SIZE];
int top = -1;
The element which is used to insert or delete is specified as a structure that consists of only a
key field.
The IsEmpty and IsFull operations are simple, and is implemented directly in the program
push and pop functions. Each of these functions assumes that the variables stack and top are
global.
4. Push( )
Function push checks whether stack is full. If it is, it calls stackFull( ), which prints an error
message and terminates execution. When the stack is not full, increment top and assign item
to stack [top].
5. Pop( )
Deleting an element from the stack is called pop operation. The element is deleted only from
the top of the stack and only one element is deleted at a time.
element pop ( )
{ /*delete and return the top element from the stack */
if (top == -1)
return stackEmpty(); /*returns an error key */
return stack[top--];
}
6. stackFull( )
The stackFull which prints an error message and terminates execution.
void stackFull()
{
fprintf(stderr, "Stack is full, cannot add element");
exit(EXIT_FAILURE);
}
The array is used to implement stack, but the bound (MAX_STACK_SIZE) should be known
during compile time. The size of bound is impossible to alter during compilation hence this
can be overcome by using dynamically allocated array for the elements and then increasing
the size of array as needed.
5. pop( )
In this function, no changes are made.
element pop ( )
{ /* delete and return the top element from the stack */
if (top == -1)
return stackEmpty(); /* returns an error key */
return stack[top--];
}
6. stackFull( )
The new code shown below, attempts to increase the capacity of the array stack so that new
element can be added into the stack. Before increasing the capacity of an array, decide what
the new capacity should be.
In array doubling, array capacity is doubled whenever it becomes necessary to increase the
capacity of an array.
void stackFull()
{
REALLOC (stack, 2*capacity*sizeof(*stack));
capacity *= 2;
}
doubling Analysis
In the worst case, the realloc function needs to allocate 2*capacity*sizeof (*stack) bytes of
memory and copy capacity *sizeof (*stack)) bytes of memory from the old array into the
new one. Under the assumptions that memory may be allocated in O(1) time and that a stack
element can be copied in O(1) time, the time required by array doubling is O(capacity).
Initially, capacity is 1.
Suppose that, if all elements are pushed in stack and the capacity is 2k for some k, k>O, then
the total time spent over all array doublings is O ( ∑𝑘𝑖=1 2𝑖 ) = O(2k+l) = O(2k).
Since the total number of pushes is more than 2k-1, the total time spend in array doubling is
O(n), where n is the total number of pushes. Hence, even with the time spent on array
doubling added in, the total run time of push over all n pushes is O(n).
Expressions: It is sequence of operators and operands that reduces to a single value after
evaluation is called an expression.
X=a/b–c+d*e– a*c
Infix Expression: In this expression, the binary operator is placed in-between the operand.
The expression can be parenthesized or un- parenthesized.
Example: A + B
Prefix or Polish Expression: In this expression, the operator appears before its operand.
Example: + A B
Postfix or Reverse Polish Expression: In this expression, the operator appears after its
operand.
Example: A B +
X=a/b–c+d*e– a*c
X= ((a / ( b – c + d ) ) * ( e – a ) * c
In C, there is a precedence hierarchy that determines the order in which operators are
evaluated. Below figure contains the precedence hierarchy for C.
• The operators are arranged from highest precedence to lowest. Operators with highest
precedence are evaluated first.
• The associativity column indicates how to evaluate operators with the same precedence. For
example, the multiplicative operators have left-to-right associativity. This means that the
expression a * b / c % d / e is equivalent to ( ( ( ( a * b ) / c ) % d ) / e )
• Parentheses are used to override precedence, and expressions are always evaluated from
theinnermost parenthesized expression first
INFIX TO POSTFIX CONVERSION
:ab/e–de*+ ac*
The expression a*(b +c)*d which results abc +*d* in postfix. Figure shows the translation
process.
• The analysis of the examples suggests a precedence-based scheme for stacking and
unstacking operators.
• The left parenthesis complicates matters because it behaves like a low-precedence
operatorwhen it is on the stack and a high-precedence one when it is not. It is placed inthe
stack whenever it is found in the expression, but it is unstacked only when its matching
right parenthesis is found.
• There are two types of precedence, in-stack precedence (isp) and incoming precedence
(icp).
The declarations that establish the precedence’s are:
/* isp and icp arrays-index is value of precedence lparen rparen, plus, minus, times, divide,
mod, eos */
int isp[] = {0,19,12,12,13,13,13,0};
int icp[] = {20,19,12,12,13,13,13,0};
void postfix(void)
{
char symbol;
precedence token;
int n = 0,top = 0; /* place eos on stack */
stack[0] = eos;
for (token = getToken(&symbol, &n); token != eos; token =
getToken(&symbol,& n ))
{
if (token == operand)
printf("%c", symbol);
else if (token == rparen)
{
while (stack[top] != lparen)
printToken(pop( ));
pop( );
}
else{
while(isp[stack[top]] >= icp[token])
printToken(pop());
push(token);
}
}
while((token = pop ())!= eos)
printToken(token);
printf("\n");
}
Program: Function to convert from infix to postfix
Analysis of postfix: Let n be the number of tokens in the expression. Ө (n) time is spent extracting
tokens and outputting them. Time is spent in the two while loops, is Ө (n) as the number of tokens
that get stacked and unstacked is linear in n. So, the complexity of function postfix is Ө (n).
EVALUATION OF POSTFIX EXPRESSION
• The evaluation process of postfix expression is simpler than the evaluation of infix
expressions because there are no parentheses to consider.
• To evaluate an expression, make a single left-to-right scan of it. Place the operands on
a stack until an operator is found. Then remove from the stack, the correct number of
operands for the operator, perform the operation, and place the result back on the stack
and continue this fashion until the end of the expression. We then remove the answer
from the top of the stack.
int eval(void)
{
precedence token;
char symbol;
int opl,op2, n=0;
int top= -1;
token = getToken(&symbol, &n);
while(token! = eos)
{
if (token == operand)
push(symbol-'0'); /* stack insert */
else {
op2 = pop(); /* stack delete */
opl = pop();
switch(token) {
case plus: push(opl+op2);
break;
case minus: push(opl-op2);
break;
case times: push(opl*op2);
break;
case divide: push(opl/op2);
break;
case mod: push(opl%op2);
}
}
token = getToken(&symbol, &n);
}
return pop(); /* return result */
}
Program: Function to evaluate a postfix expression
precedence getToken(char *symbol, int *n)
{
*symbol = expr[(*n)++];
switch (*symbol)
{
case '(' : return lparen;
case ')' : return rparen;
case '+' : return plus;
case '-' : return minus;
case '/' : return divide;
case '*' : return times;
case '%' : return mod;
case ' ' : return eos;
default: return operand;
}
}
Program: Function to get a token from the input string
• The function eval ( ) contains the code to evaluate a postfix expression. Since an operand
(symbol) is initially a character, convert it into a single digit integer.
• To convert use the statement, symbol-'0'. The statement takes the ASCII value of symbol
and subtracts the ASCII value of '0', which is 48, from it. For example, suppose symbol = '1.
The character '1' has an ASCII value of 49. Therefore, the statement symbol-'0' producesas
result the number 1.
• The function getToken( ), obtain tokens from the expression string. If the token is an
operand, convert it to a number and add it to the stack. Otherwise remove two operands
from the stack, perform the specified operation, and place the result back on the stack.
Whenthe end of expression is reached, remove the result from the stack.
RECURSION
A recursive procedure
Suppose P is a procedure containing either a Call statement to itself or a Call statement to a
second procedure that may eventually result in a Call statement back to the original procedure
P. Then P is called a recursive procedure. So that the program will not continue to run
indefinitely, a recursive procedure must have the following two properties:
1. There must be certain criteria, called base criteria, for which the procedure does not
callitself.
2. Each time the procedure does call itself (directly or indirectly), it must be closer to
thebase criteria.
A recursive function
A function is said to be recursively defined if the function definition refers to itself. A recursive
function must have the following two properties:
1. There must be certain arguments, called base values, for which the function does
notrefer to itself.
2. Each time the function does refer to itself, the argument of the function must be
closerto a base value
A recursive function with these two properties is also said to be well-defined.
Factorial Function
“The product of the positive integers from 1 to n, is called "n factorial" and is denoted by n!”
n! = 1*2 * 3 ... (n - 2)*(n - 1)*n
It is also convenient to define 0! = 1, so that the function is defined for all nonnegative integers.
Observe that this definition of n! is recursive, since it refers to itself when it uses (n - 1)!
(a) The value of n! is explicitly given when n = 0 (thus 0 is the base value)
(b) The value of n! for arbitrary n is defined in terms of a smaller value of n which is closer to
the base value 0.
The following are two procedures that each calculate n factorial .
1. Using for loop: This procedure evaluates N! using an iterative loop process
2. Using recursive function: This is a recursive procedure, since it contains a call to itself
GCD
The greatest common divisor (GCD) of two integers m and n is the greatest integer that divides
both m and n with no remainder.
That is, F0 = 0 and F1 = 1 and each succeeding term is the sum of the two preceding terms.
Definition: (Fibonacci
Sequence)
a) If n = 0 or n = 1, then Fn = n
b) If n > 1, then Fn= Fn-2+ Fn-1
Here
(a) The base values are 0 and 1
(b) The value of Fn is defined in terms of smaller values of n which are closer to the base values.
A procedure for finding the nth term Fn of the Fibonacci sequence follows.
Tower of Hanoi
Problem description
Suppose three pegs, labeled A, Band C, are given, and suppose on peg A a finite number n of
disks with decreasing size are placed.
The objective of the game is to move the disks from peg A to peg C using peg B as an auxiliary.
In other words,
n=3: A→C, A→B, C→B, A→C, B→A, B→C, A→C
For completeness, the solution to the Towers of Hanoi problem for n = 1 and n = 2
n=l: A→C
n=2: A→B, A→C, B→C
The Towers of Hanoi problem for n > 1 disks may be reduced to the following sub-problems:
(1) Move the top n - 1 disks from peg A to peg B
(2) Move the top disk from peg A to peg C: A→C.
(3) Move the top n - 1 disks from peg B to peg C.
• TOWER (N, BEG, AUX, END) to denote a procedure which moves the top n disks fromthe
initial peg BEG to the final peg END using the peg AUX as an auxiliary.
• When n > 1, the solution may be reduced to the solution of the following three
sub-problems:
(a) TOWER (N - I, BEG, END, AUX)
(b) TOWER (l, BEG, AUX, END) or BEG → END
(c) TOWER (N - I, AUX, BEG, END)
Ackermann function
The Ackermann function is a function with two arguments each of which can be assigned any
nonnegative integer: 0, 1, 2, ....
1. malloc( ):
The function malloc allocates a user- specified amount of memory and a pointer to the start of
the allocated memory is returned.
If there is insufficient memory to make the allocation, the returned value is NULL.
Syntax:
data_type *x;
x= (data_type *) malloc(size);
Where,
2. calloc( ):
The function calloc allocates a user- specified amount of memory and initializes the allocated
memory to 0 and a pointer to the start of the allocated memory is returned.
If there is insufficient memory to make the allocation, the returned value is NULL.
Syntax:
data_type *x;
x= (data_type *) calloc(n, size);
Where,
x is a pointer variable of type int
n is the number of block to be allocated
size is the number of bytes in each block
Ex: int *x
x= calloc (10, sizeof(int));
The above example is used to define a one-dimensional array of integers. The capacity of
thisarray is n=10 and x [0: n-1] (x [0, 9]) are initially 0
Macro CALLOC
3. realloc( ):
• Before using the realloc( ) function, the memory should have been allocated using malloc(
) or calloc( ) functions.
• The function relloc( ) resizes memory previously allocated by either mallor or calloc, which
means, the size of the memory changes by extending or deleting the allocated memory.
• If the existing allocated memory need to extend, the pointer value will not change.
• If the existing allocated memory cannot be extended, the function allocates a new block
andcopies the contents of existing memory block into new memory block and then deletes
theold memory block.
• When realloc is able to do the resizing, it returns a pointer to the start of the new block
and when it is unable to do the resizing, the old block is unchanged and the function
returns thevalue NULL
Syntax:
data_type *x;
x= (data_type *) realloc(p, s );
The size of the memory block pointed at by p changes to S. When s > p the additional s-p
memory block have been extended and when s < p, then p-s bytes of the old block are freed.
Macro REALLOC #define
REALLOC(p,S)\if (!((p) =
realloc(p,s))) \
{\
fprintf(stderr, "Insufficient
memory");\exit(EXIT_FAILURE);\
}\
4. free( )
Dynamically allocated memory with either malloc( ) or calloc ( ) does not return on its own.
The programmer must use free( ) explicitly to release space.
Syntax:
free(ptr);
This statement cause the space in memory pointer by ptr to be deallocated