DS Module 1
DS Module 1
For example
int list[5]; // declares an array that can store 5 integers
In C all array index start at 0 and so list[0],list[1],list[2],list[3],list[4] are the names of the five array
elements each of which contains an integer value.
1.3 Structures
Structure is basically a user-defined data type that can store related information that may be of same or
different data types together.
The major difference between a structure and an array is that an array can store only information of same
data type. A structure is therefore a collection of variables under a single name. The variables within a
structure are of different data types and each has a name that is used to select it from the structure.
For example,
Struct student {
char sname[10];
int age;
float average_marks;
} st;
1
Module-1
To assign values to these fields dot operator (. ) is used as the structure member operator. We use
this operator to select a particular member of the structure.
strcpy(st.sname,"james");
st.age = 10;
st.average_marks = 35;
We can create our own structure data types by using the typedef statement
Consider an example that creates a structure for the employee details.
or
typedef struct {
char name[10];
int age;
float salary;
} Employee;
Comparing structures
two structures are compared using a function where each field is
Return TRUE if employee 1compared
and employee 2 are the same otherwise return FALSE
2
Module-1
if (EmployeeEqual(p1,p2))
printf("The two employee are the same\n");
else
printf("The two Employee are not the same\n");
Nested Structure
a structure can be embedded within another structure. That is a structure can have another structure as its
member such a structure is called a nested structure.
For example, associated with our employee structure we may wish to include the date of Birth of an
employee by using nested stucture
typedef struct {
int month;
int day;
int year;
} date;
typedef struct {
char name[10];
int age;
float salary;
date dob;
}employee;
A person born on September 10, 1974, would have the values for the date struct set as:
p1.dob.month = 9;
p1.dob.day = 10;
p1.dob.year = 1974;
In the case of a student or the employee we may not store the details of only 1 student or 1
employee. When we have to store the details of a group of students we can declare an array of
structures.
strcpy(s[i[.sname,"james"); strcpy(s[I].name,"james")
s[i].age = 10;
s[i].average_marks = 35;
3
Module-1
Self-Referential Structures
A self-referential structure is one in which one or more of its data member is a pointer to itself. They
require dynamic memory allocation (malloc and free) to explicitly obtain and release memory.
Example:
typedef struct list {
int data;
list *link ; points to object of structure or to null
};
Each instance of the structure list will have two components, data and link. data is a single character,
while 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 = 5
item2.data = 10
item3.data = 15
item1.link = item2.link = item3.link = NULL;
We can attach these structures together by replacing the null link field in item 2 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;
1.4 Unions
A union is a user-defined data type that can store related information that may be of different data types or
same data type, 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.
Example1,
Suppose a program uses either a number that is int or float we can define a union as
Union num
{
int a;
Float b;
};
Now we can store values as n1.a=5 or n2.b= 3.14 only one member is active at a point of time.
4
Module-1
Uninitialized variables have unknown garbage values stored in them, similarly uninitialized pointer
variables will have uninitialized memory address stored inside them which may be interpreted as a memory
location, and may lead to runtime error. These errors are difficult to debug and correct, therefore a pointer
should always be initialized with a valid memory address.
NOTE: A pointer variable can only point at a variable of the same type.
We can have more than one pointer variable pointing at the same variable. For example
int a;
int *p,*q;
p=&a;
q=&a;
now both the pointer variable p and q are pointing at the same variable a. There is no limit to the number
of pointer variable that can point to a variable.
Indirection operator(*): An indirection operator is a unary operator whose operand must be a pointer
value.
For example to access a variable a through a pointer variable p we have to code it as follows
Void main()
{
int a=5;
5
Module-1
int *p
p=&a;// p is now pointing at a
*p=*p+1
printf(“ %d %d %p”, a, *p,p);
}
Output: 6 6 XXXXX(address of variable a)
Now the value of a is modified through the pointer variable p
Note:
we need parenthesis for expressions like (*p) ++ as the precedence of postfix increment is more
than precedence of the indirection operator (*). If the parenthesis is not used the address will be
incremented.
The indirection and the address operators are the inverse of each other when combined in an
expression such as *&a they cancel each other
Static memory allocation: the declaration and definition of memory should be specified in the
source program. The number of bytes reserved cannot be changed during runtime
6
Module-1
Dynamic memory allocation : Data definition can be done at runtime .It uses predefined functions to
allocate and release memory for data while the program is running. To use dynamic memory allocation
the programmer must use either standard data types or must declare derived data types
Memory usage
Four memory management functions are used with dynamic memory. malloc, calloc and realloc are used
for memory allocation. The function free is used to return memory when it is not used.
Heap: It is the unused memory allocated to the program When requests are made by memory allocating
functions, memory is allocated from the heap at run time.
The pointer returned by the malloc function can be type cast to the pointer of the required type by
making use of type cast expressions
Example:
To allocate an integer in the heap we code
int *pint
pint=(int*)malloc(sizeof(int))
Syntax: free(void*);
Example: int *p,a;
p=&a;
free(p);
7
Module-1
This function is used to allocate contiguous block of memory. It is primarily used to allocate memory for
arrays.
The function calloc() allocates a user specified amount of memory and initializes the allocated memory to
0. A pointer to the start of the allocated memory is returned. In case there is insufficient memory it returns
NULL
Example:
To allocate a one dimensional array of integers whose capacity is n the following code can be written.
Int *ptr
ptr=(int*)calloc(n,sizeof(int))
Reallocation of memory(realloc)
The function realloc resizes the memory previously allocated by either malloc or calloc.
Example
int *p;
p=(int*)calloc(n,sizeof(int))
p=realloc(p,s) /*where s is the new size*/
When s> oldsize(Block size increases) the additional (s – oldsize )have unspecified value
When s<oddsize (Block size reduces) the rightmost (oldsize-s) bytes of the old block are freed.
When realloc is able to do the resizing it returns a pointer to the start of the new block
When is not able to do the resizing the old block is unchanged and the function returns the value
NULL.
Example2:
int i,*p,*f;
i=2;
p=&i;
f=p;
free(p);
*f=*f+2 /* Invalid dangling reference*/
The location that holds the value 2 is freed but still there exist a reference to this location through f and
8
Module-1
pointer f will try to access a location that is freed so the pointer f is a dangling reference
When pointers are used the following points needs to be taken care
1. When a pointer is not pointing at any object it is a good practise to set it to NULL so that there is no
attempt made to access a memory location that is out of range of our program or that does not contain
a pointer reference to the legitimate object.
2. Use explicit type casts when converting between pointer types.
int *pi;
float *pf;
Pi= (int*) malloc (sizeof((int));
Pf= (float *)pi;
3. Define explicit return types for functions. If the return type is omitted it defaults to integer which
has the same size as a pointer and can be later interpreted as a pointer
In C we find the element x[i][j] by first accessing the pointer in x[i]. This pointer gives the address of
the zeroth element of row i of the array. Then by adding j*sizeof(int) to this pointer, the address of the
jth element of the ith row is determined
9
Module-1
Example to find x[1][3] we first access the pointer in x[1] this pointer gives the address of x1][0] now
by adding 3*sizeof (int) the address of the element x[1][3] is determined.
1.8 Arrays
1.8.1 Linear Arrays
A Linear Array is a list of finite number (n) of homogenous data elements.
a. The elements of the array are referenced by an index set consisting of n consecutive
numbers(0. ...(n-1)).
b. The elements of the array are stored in successive memory locations
The number n of elements is called the length or size of the array. Length of the array can be obtained
from the index set using the formula
Length = Upper bound – Lowe bound +1
The elements of an array may be denoted by a[0],a[2]………a[n-1]. The number k in a[k] is called a
subscript or index and a[k] is called the subscripted value.
An array is usually implemented as a consecutive set of memory locations
Declaration
Linear arrays are declared by adding a bracket to the name of a variable. The size of the array is
mentioned within the brackets.
Eg :- int list[5];
10
Module-1
The address of the first element list[0], is called the base address
base address=address(list[0])
Using the base address the address of any element of list can be calculated using the formula
Example:
int list[5]
A two dimensional m X n array A is a collection of m* n data elements such that each element is
specified by a pair of integers called subscripts.
It declares an array A that contains three elements where each element is a one dimensional array. Each
one dimensional array has 5 integer elements.
0 1 2 3
0 A[0][0] A[0][1] A[0][2] A[0][3]
Rows 1 A[1][0] A[1][1] A[1][2] A[1][3]
2 A[2][0] A[2][1] A[2][2] A[2][3]
11
Module-1
locations.If the array is stored column by column it is called column major order and if the array is stored
row by row it is called row major order.
Example: Representation of the two dimensional array A[3][4] in row major order and column major
order
A Subscript A Subscript
A[0][0] A[0][0] Column1
A[0][1] A[1][0]
Row1
A[0][2] A[2][0]
A[0][3] A[0][1] Column2
A[1][0] A[1][1]
A[1][1] A[2][1]
Row2
A[1][2] A[0][2] Column3
A[1][3] A[1][2]
A[2][0] A[2][2]
A[2][1] A[0][3] Column4
Row3
A[2][2] A[1][3]
A[2][3] A[2][3]
Using the base address , the address of any element in an array A of size row X col can be calculated
using the formula
Example
When the compiler encounters an array declaration such as int A[3][4] it creates an array A and allocates
20 consecutive memory locations. Each memory location is large enough to hold a single integer.
Let α be the address of the first element A[0][0], is called the base address
Considering Row major order
Using the bases address we can calculate the addresses of other element
Address of A[0][1] = 100 +2[0*4+ 1]= 100 +2=102
Address of A[0][2] = 100 +2[0*4+ 2]= 100 +4=104
Address of A[1][0] = 100 +2[1*4+ 0]= 100 +8=108
Addres of A[2][3]= 100 +2[2*4+3]= 100+22= 122
12
Module-1
where Π is the product of the upperi's. For instance, if we declare a as a[10][10][10], then we require
10·10·10 = 1000 memory cell to hold the array. There are two common ways to represent multidimensional
arrays: row major order and column major order. We consider only row major order here. As its name
implies, row major order stores multidimensional arrays by rows.
Two dimensional arrays
For instance, we interpret the two dimensional Array A[upper 0][upper1] as upper0 rows, , each row
containing upper1 elements.
If we assume that α the base address is the address of A[0][0]
Here the size is not considered. Considering the size the formula can be written as
Address (a[i][j]) = α + w(i·upper1 + j) where w is the size of each unit of memory location.
A[upper0][upper1][upper2], we interpret the array as upper0 two dimensional arrays of dimension upper1
× upper2.
A[upper0][upper1][upper2][upper3]
We interpret the array as upper0 three dimensional arrays of dimension upper1 x upper2 x upper3 .
A[upper0][upper1] … [uppern-1]
13
Module-1
Considering the processing applied during traversal as display of elements the array can be traversed as
follows
Insertion
Inserting an element at the end of the array can be done provided the memory space allocated for the array
is large enough to accommodate the additional element. If an element needs to be inserted in the middle
then all the elements form the specified position to the end of the array should be moved down wards to
accommodate the new element and to keep the order of the other element.The following function inserts
an element at the specified position
14
Module-1
printf("Invalid Position\n");
else
{
for(i=n-1;i>=pos;i--)
a[i+1]=a[i]; //Make space for the new element in the given position
a[pos]=element;
n++;
}
}
Deletion
If an element needs to be deleted in the middle then all the elements form the specified position to the end
of the array should be moved upwards to fill up the array.The following function deletes an element at the
specified position
for(i=pos;i<n;i++)
a[i]=a[i+1]; //Delete by pushing up other elements
n--;
}
}
Sorting
Sorting refers to the operation of rearranging the elements of an array in increasing or decreasing order.
Example : Write a program to sort the elements of the array in ascending order using bubble sort.
Bubble sort
#include<stdio.h>
void main()
{
int a[10],i,j,temp,n;
printf("enter the size of the array : ");
scanf("%d",&n);
for(i=1;i<=n-1;i++)
15
Module-1
for(j=0;j<n-i ;j++)
if (a[j] >a[j+1])
{
temp=a[j];
a[j]=a[j+1];
a[j+1]= temp;
}
printf("the sorted array is \n");
for(i=0;i<n;i++)
printf("%d \t",a[i]);
return(0);
}
Searching
Let DATA be a collection of data elements in memory and suppose a specific ITEM of information
is given. Searching refers to the operation of finding the Location LOC of the ITEM in DATA or
printing a message that the item does not appear here. The search is successful if the ITEM appear
in DATA and unsuccessful otherwise.
The algorithm chosen for searching depends on the way the data is organised. The two algorithm
considered here is linear search and binary search.
Linear search
This program traverses the array sequentially to locate key #include<stdio.h>
#include<stdlib.h>
void main()
{
int a[10],i,key,pos,n,flag=0;
printf("enter the size of the array : ");
scanf("%d",&n);
printf("enter the elements of the array\n");
for(i=0;i<n;i++)
scanf("%d",&a[i]);
printf("enter the key \n");
scanf("%d",&key);
for(i=0;i<=n-1;i++)
if (a[i]== key)
{
printf("key %d found at %d",key,pos+1);
exit();
}
printf("key not found"); }
16
Module-1
Worst case occurs when key element is not found in the array or when the element is in the last
position. Thus in worst case the running time is proportional to n C(n) O(n)
The running time of the average case uses the probabilistic notation of expectation.
Number of comparison can be any number from 1 to n and each occurs with probability p= 1/n
then
c(n) = 1.1/n +2.1/n+…........... n.1/n
= (1+2+3… ..... +n).1/n
=n(n+1)/2.1/n=n+1/2
Binary search
This algorithm is useful when the array is sorted. For example when searching for a name in a telephone
directory this algorithm is more efficient than linear search as the number of element to search is reduced
by half in each iteration.
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a[10],i,key,mid,low,high,n;
printf("enter the size of the array : ");
scanf("%d",&n);
low=0;
high=n-1;
while(low<=high)
{
mid=(low+high)/2;
if (key==a[mid])
{
printf("element %d found at %d",key,mid+1);
exit(0);
}
else
{
if (key<a[mid])
high = mid-1;
else
17
Module-1
low=mid+1;
}
}
Complexity of binary search algorithm : The complexity is based on the number of comparison C(n)
required to find the key in the array element. Each comparison reduces the sample size in half so C(n) is of
the order log 2 n +1
1.10 Polynomials
A polynomial is a sum of terms, where each term has a form axe, where x is the variable, a is the
coefficient, and e is the exponent.
The largest (or leading) exponent of a polynomial is called its degree. Coefficients that are zero are not
displayed.
Standard mathematical definitions for the sum and product of polynomials are:
then
ADT Polynomial is
objects: a set of ordered pairs of <ei, ai> where ai is Coefficients and ei is Exponents, ei are integers >=
0
functions:
for all poly,poly1,poly2 ∈ Polynomial,coef ∈ Coefficients, expon ∈ Exponents
18
Module-1
Coefficient Coef(poly,expon) ::= if (expon ∈ poly) return its coefficient else return
zero
Exponent LeadExp(poly) ::= return the largest exponent in poly
Polynomial Attach(poly,coef,expon) ::=
if (expon ∈ poly) return error else return the
polynomial poly with the term <coef, expon>
inserted
Polynomial Remove(poly,expon) ::=
if (expon ∈ poly) return the polynomial poly with
the term whose exponent is expon deleted else
return error
Polynomial SingleMult(poly,coef,expon) return the polynomial poly · coef · xexpon
::=
Polynomial Add(poly1,poly2) ::= return the polynomial poly1 + poly2
Polynomial Mult(poly1,poly2) ::= return the polynomial poly1 · poly2
end Polynomial
Polynomial a[MAX_DEGREE];
Only one global array, terms, is used to store all the polynomials. The C declarations needed are:
19
Module-1
Figure below shows how these polynomials are stored in the array terms. The index of the first term of A
and B is given by startA and startB, respectively, finishA and finishB give the index of the last term of A
and B respectively. The index of the next free location in the array is given by avail.
For our example, startA = 0, finishA = 1, startB = 2, finishB = 5, and avail =6.
Coef 2 1 1 10 3 1
exp 1000 0 4 3 2 0
0 1 2 3 4 5 6 7 8
since A (x) = 2x 1000 + 1 uses only six units of storage: one for startA, one for finishA, two for the
coefficients, and two for the exponents. However, when all the terms are nonzero, the current
representation requires about twice as much space as the first one. This representation is useful only when
the number of non zero terms are more.
C function that adds two polynomials, A and B to obtain the resultant polynomial D = A + B. The
polynomial is added term by term. The attach function places the terms of D into the array, terms starting
at position avail,. If there is not enough space in terms to accommodate D, an error message is printed to
the standard error device and we exit the program with an error condition.
void padd(int startA,int finishA,int startB, int finishB, int *startD,int *finishD)
{
/ * add A(x) and B(x) to obtain D(x) */
float coefficient;
*startD = avail;
while (startA <= finishA && startB <= finishB)
{
switch(COMPARE(terms[startA].expon, terms[startB].expon))
{
case -1: attach(terms[startB].coef,terms[startB].expon);
startB++;
break;
case 0: coefficient = terms[startA].coef + terms[startB].coef;
if (coefficient)
attach(coefficient,terms[startA].expon);
startA++;
startB++;
break;
20
Module-1
case 1: attach(terms[startA].coef,terms[startA].expon);
startA++;
}
}
for(; startA <= finishA; startA++)
attach(terms[startA].coef,terms[startA].expon); /* add in remaining terms of A(x) */
*finishD = avail-1;
}
Consider the matrix given below. It contains many zero entries, such a matrix is called a sparse matrix
Col0 Col1 Col2 Col3 Col4 Col5
Row0 15 0 0 22 0 -15
Row1 0 11 3 0 0 0
Row2 0 0 0 -6 0 0
Row3 0 0 0 0 0 0
Row4 91 0 0 0 0 0
Row5 0 0 28 0 0 0
21
Module-1
When a sparse matrix is represented as a two dimensional array space is wasted for example if we
have 1000x 1000 matrix with only 2000 non zero element, the corresponding 2 dimensional array
requires space for 1,000,000 elements
Functions:
for all a, b∈SparseMatrix, x∈item, i, j, maxCol, maxRow∈index
A Sparse matrix can be represented by using an array of triple <row, col, value >.
In addition to ensure the operations terminate , it is necessary to know the number of rows and columns,
and the number of nonzero elements in the matrix. Putting all this information together a sparse matrix
can be created as follows
term a[MAX_TERMS] ;
22
Module-1
Example
Figure 1.4 two dimensional array and its sparse matrix stored as triples
Write a program to store a sparse matrix in triplet form and search an element specified by the
user
#include<stdio.h>
#include<stdlib.h>
int main()
{
struct sparse
{
int r;
int c;
int v;
};
struct poly s[100];
int ele,i,j,k,n,m,key;
printf("enter the size of the array ; ");
scanf("%d %d",&m,&n);
k=1;
s[0].r=m;
s[0].c=n;
printf("\n enter the elements of the array\n");
for(i=0;i<m;i++)
for(j=0;j<n;j++)
{
scanf("%d",&ele);
if(ele !=0)
{
s[k].r=i;
s[k].c=j;
s[k].v= ele;
k++;
23
Module-1
}
s[0].v=k-1;
}
for(i=0;i<=s[0].v;i++)
printf(" %d\t %d \t %d \n ",s[i].r, s[i].c, s[i].v);
printf(" enter the key to be searched");
scanf("%d",&key);
for(i=0;i<=s[0].v;i++)
if (key== s[i].v)
{
printf("element found at %d row and %d column",s[i].r,s[i].c);
exit(0);
}
printf("element not found ");
return(0);
}
To transpose a matrix we must interchange the rows and columns. This means that each element a[i][j] in
the original matrix becomes element b[j][i] in the transpose matrix.
The algorithm finds all the elements in column 0 and store them in row 0 of the transpose matrix, find all the elements
in column 1 and store them in row 1, etc." Since the original matrix was ordered by rows and the columns were
ordered within each row. The transpose matrix will also be arranged in ascending order. The variable, currentb, holds
the position in b that will contain the next transposed term. The terms in b is generated by rows by collecting the
nonzero terms from column i of a
The transpose b of the sparse matrix a of figure 1.4b is shown in figure 1.5
24
Module-1
It first determines the number of elements in each column of the original matrix. This gives us the number
of elements in each row of the transpose matrix. From this information, we can determine the starting
position of each row in the transpose matrix. We now can move the elements in the original matrix one by
one into their correct position in the transpose matrix. We assume that the number of columns in the original
matrix never exceeds MAX_COL.
25
Module-1
The first two for loops compute the values for rowTerms, the third for loop carries out the
computation of startingPos, and the last for loop places the triples into the transpose matrix. These
four loops determine the computing time of fastTranspose.
The bodies of the loops are executed numCols, numTerms, numCols - 1, and numTerms times,
respectively. The computing time for the algorithm is O(columns + elements).
However, transpose requires less space than fastTranspose since the latter function must allocate
space for the rowTerms and startingPos arrays.
1.12 Strings
A string is an array of characters that is delimited by the null character (\0).
Example1:
Char s[100] = {“class”} ;
The string is internally represented as follows
C L A S S \0
S[0] S[1] S[2] S[3] S[4] S[5]
26
Module-1
Using this declaration the compiler would have reserved just enough space to hold each character word
including the null character. In such cases we cannot store a string of length more than 5 in s
ADT string is
Objects : a finite set of zero or more characters
String Null(m) ::= Return a string whose length is m characters long, but is initially set to NULL.
We write NULL as “”
Integer compare(s, t)::= If s equals t return 0
Else if s precedes t return -1
Else return +1
Boolean ISNull(s) ::= If (compares, NULL)) return FALSE
Else return TRUE
Integer Length(s) ::= If(compare(s, NULL))
Returns the number of characters in s else returns 0
String concat(s,t) ::= If(compare(t, NULL))
Return a string s whose elements are those of s followed by those of t
C provides several string functions which we access by including the header file string.h
Given below is a set of C string functions
char *strcat(char *dest, const char Appends the string pointed to, by src to the end of the
*src) string pointed to by dest.
char *strncat(char *dest, const char Appends the string pointed to, by src to the end of the
*src, size_t n) string pointed to, by dest up to n characters long.
int strcmp(const char *str1, const Compares the string pointed to, by str1 to the string
char *str2) pointed to bystr2.
char *strcpy(char *dest, const char Copies the string pointed to, by src to dest and return
*src) dest
char *strncpy(char *dest, const Copies n characters from the string pointed to,
char *src, size_t n) by src to dest and returns dest
27
Module-1
size_t strlen(const char *str) Returns the length of the string str . But not including the
terminating null character.
char *strchr(const char *str, int c) Returns pointer to the first occurrence of c in str . Returns
NULL if not present
char *strrchr(const char *str, int c) Returns pointer to the last occurrence of c in str . Returns
NULL if not present
char *strtok(char *str, const char Returns a token from string str . Tokens are separated
*delim) by delim.
char *strstr(char *str, const char Returns pointer to start of pat in str
*pat)
size_t strspn(const char *str, const Scan str for characters in spanset, returns the length of
char *spanset) the span
size_t strcspn(const char *str, Scans str for character not in spanset, returns the length
const char *spanset) of the span
char *strpbrk(const char *str, const Scan str for characters in spanset, returns pointer to first
char *spanset) occurrence of a character from spanset
Example:
S=
a m o b i l e „\0\
t=
u t o „\0\
Initially
Temp= ‘\0\
Strncpy(temp,s,i)
a „\0\
Strcat(temp,t)
a u t o „\0\
Strcat(temp,(s+i))
28
Module-1
a u t o m o b i l e „\0\
Consider two string str1 and str2 . insert srting str2 into str1 at position i.
# include<string.h>
# define max_size 100
Char str1[max_size];
Char str2 [max_size];
If (strlen(t))
{
Strncpy(temp,s,i);
Strcat(temp,t);
Strcat(temp,(s+i));
Strcpy(s,temp);
}}
Pattern matching
Consider two strings str and pat where pat is a pattern to be searched for in stri
The easiest way to find if the pat is in str is by using the built in function strstr.
Example: If we have a declaration as follows
Char pat[max_size], str[max_size], *t;
Since there are different methods to find pattern matching discussed below are two functions that finds
pattern matching in a more efficient way.
The easiest and the least efficient method in pattern matching is sequential search. The computing time is
of O(n.m).
⚫ Compare the first and last character if pat and string before we check the remaining
characters
for(i=0;endmatch<=lasts;endmatch++,strt++)
{
If(string[endmatch] == pat[lastp])
For(j=0,i=start;j<lastp && string[i]== pat[j];i++,j++)
;
If(j==lastp)
return start;
}
return -1
}
Simulation of nfind
Pattern
a a b
j lastp
a b a b b a a b a a
s em ls
No Match
a b a b b a a b a a
s em ls
No Match
a b a b b a a b a a
s em ls
30
Module-1
No Match
a b a b b a a b a a
s em ls
No Match
a b a b b a a b a a
s em ls
No Match
a b a b b a a b a a
s em ls
Match
Analysis of nfind algorithm.
The speed of the program is linear O(m) the length of the string in the best and average case but the worst
case computing is still O(n.m)
Ideally we would like an algorithm that works in O(strlen(str)+ strlen(pat)) time. This is optimal for this
problem as in the worst cast it is necessary to look at all characters in the pattern and string at least once.
We want to search the string for the pattern without moving backwards in the string. That is if a mismatch
occurs we want to use the knowledge of the characters in the pattern and the position in the pattern where
the mismatch occurred to determine where the search should continue. Knuth, Morris, and pratt have
developed an algorithm that works in this way and has linear complexity.
31
While (i<lens && j<lenp)
{
If (string[i] == pat[j])
{
i++; j++; }
else if (j==0) i++;
else j= failure[j-1] +1;
}
return ((j=lenp) ? (i-lenp) : -1);
}
Example:
For the pattern pat=abcabcacab we have the failure values calculated as below
j 0 1 2 3 4 5 6 7 8 9
pat a b c a b c a c a b
failure -1 -1 -1 0 1 2 3 -1 0 1
Analysis of pmatch
The time complexity of function pmatch is O (m) = O(strlen(string))
Analysis of fail
Therefore when the failure function is not known in advance the total computing time is
O(strlen(string)) + O(strlem(pa))
Stack
Stack Definition and Examples
stack is an ordered list in which insertions (also called push) and deletions (also called pops ) are
made at one end called the top.
Given a stack S = (a0, ... , an-1), we say that a0 is the bottom element, an-1 is the top element,
and ai is on top of element ai-1, 0 < i < n.
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.
CreateS will create and return an empty stack with maximum stack size.
StackCreateS(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 function pop deletes the topmost element from the stack and returns it.
element pop()
{/* delete and return the top element from the stack */
if (top == -1)
return stackEmpty(); /* returns an error key */
return stack[top--];
}
void stackFull()
{
fprintf(stderr, "Stack is full, cannot add element");
exit(EXIT_FAILURE);
}
Array Implementation of a stack of integers
#include<stdio.h>
#define MAX 10
int top= -1,a[MAX];
int pop()
{
int itemdel;
if (top==-1)
return 0;
else
{
itemdel=a[top--];
return itemdel;
}
}
void display()
{
int i;
if(top==-1)
printf("Stack Empty\n");
else
{
printf("Elements Are:\n");
for(i=top;i>=0;i--)
printf("%d\n",a[i]);
}
}
void main()
{
int ch,item,num,itemdel;
while(1)
{
printf("\nEnter the Choice\n1.Push\n2.Pop\n3.Display\n4.Exit\n");
scanf("%d",&ch);
switch(ch)
{
case 1: printf("Enter item to be inserted\n");
scanf("%d",&item);
push(item);
break;
case 2: itemdel=pop();
if(itemdel)
printf("\n Deleted Item is:%d\n",itemdel);
else
printf("Stack Underflow\n");
break;
case 3: display();
break;
case 4: exit(0);
}
}
}
Creation of stack
Here the capacity of the stack is taken as 1. The value of the capacity can be altered specific to
the application
StackCreateS() ::=
typedef struct {
int key;
/* other fields */
} element;
element
*stack;
MALLOC(stack,
sizeof(*stack)); int capacity = 1;
int top = -1;
The function push remains the same except that MAX_STACK_SIZE is replaced with capacity
void push(element item)
{
if (top >=capacity-1)
stackFull();
stack[++top] = item;
}
The code for the pop function remains unchanged
element pop()
{/* delete and return the top element from the stack */
if (top == -1)
return stackEmpty(); /* returns an error key */
return stack[top--];
}
The code for stackFull is changed. The new code for stackFull attempts to increase the capacity of the
array stack so that we can add an additional element to the stack. In array doubling, the capacity of the
array is doubled whenever it becomes necessary to increase the capacity of an array.
void stackFull()
{
REALLOC(stack, 2 * capacity * sizeof(*stack))
capacity =capacity * 2;
}
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). The total time spent
in array doubling is of O(n) where n is the total number of push operations.
Hence even with the time spent on array doubling in the total time of push over all n pushes in
O(n). This conclusion is valid even the stack array is resized by a factor c>1.
The prefixes “pre”, “post”, and “in” refer to the relative position of the operator with respect to the
two operands.
To convert an expression from infix to prefix or postfix we follow the rules of precedence.
Precedence : The order in which different operators are evaluated in an expression is called
precendence
Associativity : The order in which operators of same precedence are evaluated in an expression is
called Associativity.
The operators are listed in the order of higher precedence down to lower precedence
Operator Associativity
--,++ left-to-right
Unary operators ,!,-,+, &, Right to left
*,sizeof
*,/,% left-to-right
+,- left-to-right
Algorithm Polish(Q,P)
Suppose Q is an arithmetic expression written in infix notation. This algorithm finds the equivalent
Postfix expression P.
Analysis:
Let n be length of the infix string. (n) time is spent extracting tokens . There are two while loop
where the total time spent is (n) since the number of tokens that get stacked and unstacked is linear
in n . So the complexity of the function is (n)
2.1.3 Evaluating a postfix expression
Each operator in a postfix string refers to the previous two operands in the string. If we are parsing a
string, each time we read operands we push it to the stack and when we read a operator, its operands
will be the two topmost elements in the stack. We can then pop these two operands and perform the
indicated operation and push the result back to the stack so that it can be used by the next operator.
float s[25];
int top;
int i=0;
float
res=0,op1,op2;
char symbol;
While(postfix[i]!=‟\0‟)
{
Symbol=postfix[i];
If isdigit(symbol)
{
Push(symbol-„0‟);
}
Else
{
op2=pop();
op1=pop();
res=operation(symbol,op1,op2);
push(res);
}
}
res=pop();
return(res);
}
It does not check if the postfix expression is valid or not. If we input erroneous expression it
returns wrong result
We cannot enter negative numbers, as the symbol to indicate negation will be misinterpreted
as subtraction operation
Analysis:
Let n be length of the postfix string then the complexity of the function is (n)
Algorithm PostfixEval(P)
This algorithm finds the VALUE of an arithmetic expression P written in postfix notation
1. Scan P from Left to righ
2. Repeats steps 3 and 4 until we reach the end of P
3. If an operand is encountered put it on stack
4. If an operator is encountered then:
a) remove two top elements of STACK, where A is the top element and B is the next
top- element
b) Evaluate B A
c) Place the result of (4) in STACK.
[End of If structure]
[End of step 2 Loop]
5. Set VALUE equal to the top element of STACK.
6. EXit