Sie sind auf Seite 1von 132

Programming in C

Part - II

TechnoCampus UCP

globsyn technologies
XI - 11 & 12, Block - EP, Sector - V, Salt Lake Electronics Complex,
Calcutta - 700091, India

Globsyn

YM/SR/CPRG2/1.0

All rights reserved. No part of this book shall be reproduced, stored in a


retrieval system, or transmitted by any means, electronic, mechanical,
photocopying, recording, or otherwise, without written permission from the
publisher. No patent liability is assumed with respect to the use of the
information contained herein.

Programming in C Part II

Programming in C Part II

Programming in C -- Part II
Single Linked List
Doubly Linked List
Stack, Queue, and Binary Trees
Enhanced Searching Indexing & Hashing
Using Data Structure
C Library

Programming in C Part II
Single Linked List ------------------------------------------------------------------------------------ 3
Data Structure - The need ------------------------------------------------------------- 4
Single Linked List -------------------------------------------------------------------- 5
Single Linked List in C --------------------------------------------------------------- 7
Creation of a List---------------------------------------------------------------------- 8
Insertion of nodes in an existing list ------------------------------------------------- 12
Sorted Linked List ------------------------------------------------------------------- 16
Traversal in the list------------------------------------------------------------------- 20
Search for a specific node------------------------------------------------------------ 24
Deletion of a node ------------------------------------------------------------------- 28
Quiz ---------------------------------------------------------------------------------- 32
Summary----------------------------------------------------------------------------- 33
Doubly Linked List----------------------------------------------------------------------------------34
Concept of doubly linked lists ------------------------------------------------------- 35
Structures in C to represent doubly linked list --------------------------------------- 37
Inserting a node in doubly linked list ------------------------------------------------ 38
Traversing in doubly linked list------------------------------------------------------ 45
Quiz ---------------------------------------------------------------------------------- 49
Summary----------------------------------------------------------------------------- 50
Stack, Queue and Binary Tree-------------------------------------------------------------------51
Stacks in C --------------------------------------------------------------------------- 53
The push() and the pop() functions -------------------------------------------------- 54
Appreciating queue in C ------------------------------------------------------------- 57
Structures in C to represent queue --------------------------------------------------- 58
Insert and delete in queue ------------------------------------------------------------ 59
The concept of Binary trees---------------------------------------------------------- 62

YM/SR/CPRG2/1.0

Programming in C Part II
Binary trees with structures in C----------------------------------------------------- 66
Insert node in binary tree ------------------------------------------------------------ 67
Traversing a binary tree -------------------------------------------------------------- 74
Deletion of a Node from Binary tree ------------------------------------------------ 79
Quiz ---------------------------------------------------------------------------------- 83
Summary----------------------------------------------------------------------------- 84
Enhanced searching Indexing & Hashing using Data structure -------------------85
Search Methods ---------------------------------------------------------------------- 86
Indexed Searching ------------------------------------------------------------------- 89
Structure in C to represent an Index ------------------------------------------------- 91
Create an Index for a Data file ------------------------------------------------------- 93
Hashing ---------------------------------------------------------------------------- 102
Hashing Functions ----------------------------------------------------------------- 104
Hashing Techniques --------------------------------------------------------------- 105
Hash Indexes----------------------------------------------------------------------- 106
Hash Tables ------------------------------------------------------------------------ 108
Collisions -------------------------------------------------------------------------- 109
A complete Example --------------------------------------------------------------- 112
Quiz -------------------------------------------------------------------------------- 119
Summary--------------------------------------------------------------------------- 120
C Library -------------------------------------------------------------------------------------------- 121
Need of software library ----------------------------------------------------------- 122
Creation and maintenance of software library------------------------------------- 123
Using the Library ------------------------------------------------------------------ 127
Quiz -------------------------------------------------------------------------------- 128
Summary--------------------------------------------------------------------------- 129

YM/SR/CPRG2/1.0

Programming in C Part II

Single Linked List


Appreciate the need of Data Structure
Appreciate the concept of Linked List

Appreciate Linked List in C


Create Linked List
Insert of nodes in an existing single Linked List
Create Sorted Linked List
Traverse the list
Search a Node in the Single Linked List
Delete of a Node in single Linked List

Single Linked List


At the end of the chapter, you will be able to:
Appreciate the need of Data Structure
Appreciate the concept of Linked List
Appreciate Linked List in C
Create Linked List
Insert nodes in an existing single Linked List
Create sorted Linked List
Traverse the list
Search a Node in a single Linked List
Delete a Node in a single Linked List

YM/SR/CPRG2/1.0

Programming in C Part II

Data Structure - The need


A data structure is a method of data presentation
in a logical manner.
Representation of data is made in the memory
using simple and complex data types.
Data structures are used for managing and
manipulation of huge data efficiently.

Data Structure - The need


If the oft-repeated question, why do we use computers, is asked, then don't get
irritated. It is obvious that you know the answer but still lets recapitulate it once
more.
One of the most important jobs performed by computers is, storing and
manipulating information.
A data structure is a method of data representation in a logical manner. The
representation of data is made in the memory using simple and complex data
types.
In C, we will be studying data structures from two perspectives:
Identify and understand some high-level data type as tool to represent and
organize data.
Implementation of such data type using existing data types.
Already we have seen some existing data structures in C like arrays and
structures. You must be familiar with using these structures and reaping the
benefit out of it.
For the rest of the chapter, we will concentrate on developing more complex data
types and how they can be used under different problem scenarios.

YM/SR/CPRG2/1.0

Programming in C Part II

Single Linked List


Link lists are a group of self-referential structure.
It is a chain of structures, which has a data part
and pointers, which store the address of the next
structure in the list.
200

200

I001

Data

215

215

Address

I002

Data

232

232

Address

I003

Data

Null

Address

Single Linked List


Lets consider the invoicing system for ABCs retail shop. When the bill is
prepared, can anybody guess about the number of items that the customer is
going to purchase? He may buy 1 item or 10 items depending upon his pocket
and his mood, and his need ofcourse! So while writing a program, to represent
this bill in the memory, the help of data structure is required.
Since already you know about arrays,
your first choice will be to represent the bill with the help of an array.
But, just words of caution over here, that working with the array in this situation
might not be a very pleasant experience.
But WHY?
Let's try to justify. Since already you have seen that the number of items in the
bill is variable, how can we determine the size of the array? If you are taking a
large sized array, to play safe, but the number of items happens to be small, you
would be simply wasting space. On the other hand, if you are declaring the array
size too small, then you will not be able to store all the items, if the number of
items is large.
In addition, if you have to insert or delete data in the middle of an array you have
to go through rigmarole. This will involve restructuring of the array. In this type of
situation, Linked List comes to be quite handy.
Linked lists are a group of self-referential structures. A linked list is a chain of
structures, which has a data part and pointers. The pointer stores the address of
the next structure in the list.

YM/SR/CPRG2/1.0

Programming in C Part II

The items that you can see in the figure are called nodes. It contains two parts,
the data part and an address part.
Let's understand the concept with the help of an example of billing for ABC shop.

200
200

start

I001

Data

215
215

I002

Address Data

232
232

I003

Address Data

Null

Address

As you can see in the above figure that there are three nodes in the linked list.
Each node has two parts. The first part consists of the data. In our example it is
only containing the Item Code. It can also be a variable of a derived data type
like structure.
The other part is a pointer that contains the address of the next node. You can
see that the third node is the last one in the chain. Its pointer contains Null since
there is no next node to point.
As you know, every thing has a starting. In the same manner, we have keep
track of the very first node of the list. This helps in accessing the first node, and
then we can navigate to any other node.
If you look at the figure, you will find that both in the address field and on top of
the nodes, certain numbers are written. These numbers notify the memory
addresses of the nodes. We have assigned certain arbitrary numbers to
represent the addresses, in reality these memory addresses can be altogether
different.

YM/SR/CPRG2/1.0

Programming in C Part II

Single Linked Lists in C


In C a single linked list is made up of Nodes.
Node contains a data part and an address part.
Node can be best represented in c with the help
of a structure.
The node can be represented like this:
struct bill
{
char itemno[5];
char itemdesc[30];
float rate;
int qty;
struct bill *next;
};

Single Linked List in C


After discussing the concepts of Linked List, lets try to understand its
implementation in C. In our previous discussions, we have seen that to
implement a list, the first step is to create a node.
Nodes contain a data part and an address part. Nodes can best be represented
in C with the help of structures.
A node can be represented in the following way:
struct bill{
char itemno[5];
char itemdesc[30];
float rate;
int qty;
struct bill *next;
};
You can see from the above code snippet that the first four elements of the
structure bill represent the data part, and the last element is a pointer of the
same structure, as that of bill. This will point to the next node, which will be of the
same type as bill.
Once we have declared the node, let's try to create a linked list. We will
concentrate on:
Creation of a list
Insertion of nodes in an existing list
Traversal of the list
Deletion of a node from the list
Searching for a specific node in the list

YM/SR/CPRG2/1.0

Programming in C Part II

Creation of a List
By creation of a list we mean adding a node to an
empty list.
The steps to create a list are:
Create a structure as we have seen earlier.
Declare a pointer, say start of the structure type and
initialize it with NULL.
Create a new node
Store the address of the newly created node in the
start.

Creation of a List
When we say creation of a list, we mean adding a node to an empty list. That is
the list is created for the first time. After creation of the list, we can go on adding
other nodes to the existing list.
Generally, the functions, for adding a node to an empty list,
and for adding a new node to an existing list, are clubbed
together into a single function for programming convenience. A
check is made to ascertain whether start is NULL or not. If
start is Null, the list is empty, otherwise the list exists.
The steps to create a list are:
Create a structure, as we have seen earlier.
Declare a pointer, say start, of the structure type declared earlier, and
initialize it with NULL.
Create a new node.
Store the address of the newly created node in the start.
struct bill
{
char itemno[5];
char itemdesc[30];
float rate;
int qty;
struct bill *next;
};
char c;
struct bill *start;

YM/SR/CPRG2/1.0

Programming in C Part II

main()
{
.
.
.
add();
.
..
}
add()
{
struct bill *createnode(),*new;
new=createnode(); // Creating a new node which we will
be
// Discussed a bit later.
if(start==NULL)
{
start=new; //The address of the newly created node is
//stored in the start
return;
}

..
}

From the above code, it is clear that a self-pointing structure called bill has been
created. After that, we are declaring a pointer called start of type bill structure.
Then from the main() method we are calling a method called add().
In the add() method we have declared a pointer called new. This is used to store
the address of the newly created node, returned by the function createnode().
The function createnode() dynamically creates a node. Soon we will be
discussing how it dynamically creates a node.
Then start is checked to make sure whether it is NULL or not. If it is NULL, it
means that the list is empty. So the address of the new node is assigned to the
start. In this way we have created the list with a single node.
Now let's look into the function createnode(), in detail.
struct bill *createnode()
{
struct bill *new1;
new1=(struct bill*)malloc(sizeof(struct bill));
printf("\n Enter :");

YM/SR/CPRG2/1.0

Programming in C Part II

printf("\n\t Item No:\t");


scanf("%s",new1->itemno);
fflush(stdin);
printf("\n\tDescription:\t");
scanf("%s",new1->itemdesc);
fflush(stdin);
printf("\n\t Rate:\t");
scanf("%f",&new1->rate);
fflush(stdin);
printf("\n\t Quantity:\t");
scanf("%d",&new1->qty);
return(new1);
};
Let's now explore the function.
The main advantage provided by linked list, as have often been mentioned, is the
flexibility of adding elements without bothering about a predefined number (of
elements). It requires us to reserve memory for the nodes during the runtime of
the program. This technique of allocating memory during execution of the
program (unlike allocating memory during the compilation time) is called
dynamic memory allocation. Using this technique, we will be allocating
memory when a node is created, and releasing it when a node is deleted.
Dynamic memory allocation in C, is done through a standard library function
called malloc().
char *malloc(unsigned size_of_memory_to_be_allocated)
Another library function, called calloc(), is also available. It is being consciously
overlooked, since we will not use it in our programs.
The function malloc(), reserves a chunk of memory as specified by the
parameter passed to it. It returns a character type pointer to the first byte of the
chunk reserved. We can use this pointer to access the reserved memory
location. If this function fails to reserve the memory due to some reason, it
returns a NULL value.
To use the function malloc() you may have to include the header
file called malloc.h. This header file contains the declaration of
this function.
In this program snippet, from the function createnode(), we are using malloc() to
reserve memory:
new1=(struct bill*)malloc(sizeof(struct bill));

YM/SR/CPRG2/1.0

10

Programming in C Part II

Here malloc() is being used to allocate memory for a node. The size of the
structure is passed (with the help of sizeof() operator) as an argument to the
function specifying the amount of memory to be allocated.
Since, malloc() returns a character type pointer, therefore the return value is type
cast to a pointer to structure of type bill.
The rest of the code is very simple. Accepting the details from the user and
assigning them to different member variable of the structure and ultimately
returning the address of the newly created Node.

YM/SR/CPRG2/1.0

11

Programming in C Part II

Insertion of nodes in an existing list


To add a node at the start of a list:
link the new node to the first node of the existing node.
pointer of the new node should point to the address of
the first node of the existing node.
178
178

New

I004
Data

200

NULL
Address

200
I001
Data

215
215

Address

I002
Data

232
232

Address

I003
Data

Null
Address

Insertion of nodes in an existing list


We have already created a node. Now, we will add a node to an existing list. In
this case, we will add a node at the beginning of the list.
#include <stdio.h>
#include<malloc.h>
struct bill
{
char itemno[5];
char itemdesc[30];
float rate;
int qty;
struct bill *next;
};
struct bill *start;
main()
{
char choice;
choice='x';
while((choice!='q')&&(choice!='E'))
{
system("tput clear");
printf("\n\n I. Insert into the list");
printf("\n Q. Quit");
choice=getchar();
fflush(stdin);
if((choice=='I')||(choice=='i'))
{
add();
}

YM/SR/CPRG2/1.0

12

Programming in C Part II

if((choice=='Q')||(choice=='q'))
{
exit();
}
}
}
add()
{
struct bill *createnode(),*new;
new=createnode();
if(start==NULL)
{
start=new;
return;
}
new->next=start;
start=new;
return;
}
struct bill *createnode()
{
struct bill *new1;
new1=(struct bill*)malloc(sizeof(struct bill));
printf("\n Enter :");
printf("\n\t Item No:\t");
scanf("%s",new1->itemno);
fflush(stdin);
printf("\n\tDescription:\t");
scanf("%s",new1->itemdesc);
fflush(stdin);
printf("\n\t Rate:\t");
scanf("%f",&new1->rate);
fflush(stdin);
printf("\n\t Quantity:\t");
scanf("%d",&new1->qty);
return(new1);
}

The above code is used for adding a node to an existing list.

YM/SR/CPRG2/1.0

13

Programming in C Part II
The following figure shows the existing list:

200
start

200
I001
Data

215

232

215

I002

232

I003

Address

Data

Address

Data

Null
Address

To add a new node to this existing list at the beginning of the list it has to be
arranged like the figure below.
178
178

Ne
w

200
I004

Null

Data

Address

start

200
I001
Data

215
Address

215
I002
Data

232
232

Address

I003
Data

Null
Address

From the figure above, it is clear that we have to do the following tasks to add the
new node to the existing list:
1. We have to link the new node to the first node of the existing node. That is,
the pointer of the new node should point to the address of the first node of the
existing list. The address of the first node is contained in the start pointer.
This is done by issuing the statement:
new->next=start;

2. Since, the new node has been inserted at the beginning of the list, therefore
start should point to the new node. Instead of 200 start should now contain the
address 178.

YM/SR/CPRG2/1.0

14

Programming in C Part II
The following statement does the job of reassigning start:
start=new;

This type of list, where a node is inserted at the beginning of the list, and is not
arranged in a specific pattern, with respect to their data, is termed as unsorted
list.
But for most of the purpose like getting a piece of information as report, we
require a sorted linked list.

YM/SR/CPRG2/1.0

15

Programming in C Part II

Sorted Linked List


Sorted list are those type of list where the nodes
are inserted into the list on the basis of the data
part.
The nodes having the smaller data part is added
before the nodes with larger data part.
232

215
200

prev

ptr

200
I001

215
215

Address

Data

232

I002
Data

232

I004

Address

Null

Data

Address

110

I003

110

new

Sorted Linked List


Sorted lists are those, where the nodes are inserted into the list on the basis of
their data part. The nodes having the smaller data part is added before the nodes
with larger data part.

200
200
I001
Data

215

215

I002

Address

232
232

Data

Address

I004
Data

Null
Address

The figure above shows a sorted linked list. The list is sorted in ascending order
on the basis of the data part.
Now, say there is a new node with Item Code I003.
110
I003

X
New

The question is where should this node be inserted in the list.

YM/SR/CPRG2/1.0

16

Programming in C Part II
Since the data part of the new node, i.e. I003, is lest than the data part of the last
node, i.e. I004, so it will be added before the 3rd (or the last) node, and after the
2nd node of the existing list.
How can we achieve this?
A pointer, say ptr, has to be positioned at the node with data I004, because
a link has to be established with the new node. Generally speaking, a pointer
has to be positioned on the node before which the new node will be inserted.
Another pointer, say prev, should be positioned at the node after which the
new node will be added. In this case, it will be on 2nd node (that is containing
the data I002). This is necessary, since a link has to be established with the
new node to be inserted.
How can we position the pointers on the specific positions?
To position the pointers on the specific nodes, advance the pointer ptr from the
beginning of the list till it reaches the first node with data greater than the data
contained in the new node. The pointer prev, which is made to follow the ptr,
thereby points to the node just before the node that ptr is pointing to.

232

215

200

prev

200
I001
Data

ptr

215

215

I002

Address

Data

232
232
Address

I004
Data

Null
Address

110
110

I003

new

The figure above depicts how a node can be inserted in the middle of the list.
This is how you will create the sorted linked list.
Lets now see the code to achieve this:
#include <stdio.h>
#include<malloc.h>
struct bill
{

YM/SR/CPRG2/1.0

17

Programming in C Part II
char itemno[5];
char itemdesc[30];
float rate;
int qty;
struct bill *next;
};
char c;
struct bill *start;
main()
{
char choice;
choice='x';
while((choice!='q')&&(choice!='E'))
{
system("tput clear");
printf("\n\n I. Insert into the list");
printf("\n Q. Quit");
choice=getchar();
fflush(stdin);
if((choice=='I')||(choice=='i'))
{
add();
}
if((choice=='Q')||(choice=='q'))
{
exit();
}
}
}
add()
{
struct bill *createnode(),*new,*ptr,*prev;
new=createnode();
if(start==NULL)
{
start=new;
return;
}
for(ptr=start;(ptr)&&strcmp(new->itemno,ptr->itemno)>0;
prev=ptr,ptr=ptr->next);
if(ptr!=start)
{
prev->next=new;
new->next=ptr;
}
else
{
new->next=start;
start=new;
}

YM/SR/CPRG2/1.0

18

Programming in C Part II

return;
}
struct bill *createnode()
{
struct bill *new1;
new1=(struct bill*)malloc(sizeof(struct bill));
printf("\n Enter :");
printf("\n\t Item No:\t");
scanf("%s",new1->itemno);
fflush(stdin);
printf("\n\tDescription:\t");
scanf("%s",new1->itemdesc);
fflush(stdin);
printf("\n\t Rate:\t");
scanf("%f",&new1->rate);
fflush(stdin);
printf("\n\t Quantity:\t");
scanf("%d",&new1->qty);
return(new1);
}
In the above program, the additional new codes are in bold text.
Let's now take a look at them:
for(ptr=start;(ptr)&&strcmp(new->itemno,ptr->itemno)>0;
prev=ptr,ptr=ptr->next);

The above code snippet helps us in positioning the pointers prev and ptr to the
appropriate node.
After positioning the prev and ptr to the respective nodes, the new node has to
be linked.
The following block of code does this:
if(ptr!=start)
{
prev->next=new;
new->next=ptr;
}
else
{
new->next=start;
start=new;
}

YM/SR/CPRG2/1.0

19

Programming in C Part II

Traversal in the list


steps followed to traverse a list.
Declare a pointer to struct bill say in the example it is ptr.
Assign the address stored in the start to ptr assuming that
the list already exist.
Print the data contained by the node currently being
pointed by ptr.
Reinitialize the pointer ptr with the address of the next
node.
Repeat the previous two steps until ptr encounters NULL..

Traversal in the list


To show the data stored in the linked list or to manipulate it, we have to traverse
it. For example, if we want to extract all the data stored in the linked list, we have
to move from the beginning to the end of the list.
Look at the code given below, which handles the traversal of the list. The bold
portion of the code is actually doing the job.
#include <stdio.h>
#include<malloc.h>
struct bill
{
char itemno[5];
char itemdesc[30];
float rate;
int qty;
struct bill *next;
};
char c;
struct bill *start;
main()
{
char choice;
choice='x';
while((choice!='q')&&(choice!='E'))
{
system("tput clear");

YM/SR/CPRG2/1.0

20

Programming in C Part II

printf("\n\n I. Insert into the list");


printf("\n D. Display the List");
printf("\n Q. Quit");
choice=getchar();
fflush(stdin);
if((choice=='I')||(choice=='i'))
{
add();
}
if((choice=='D')||(choice=='d'))
{
display();
}
if((choice=='Q')||(choice=='q'))
{
exit();
}
}
}
add()
{
struct bill *createnode(),*new,*ptr,*prev;
new=createnode();
if(start==NULL)
{
start=new;
return;
}
for(ptr=start;(ptr)&&strcmp(new->itemno,ptr>itemno)>0;prev=ptr,ptr=ptr->next);
if(ptr!=start)
{
prev->next=new;
new->next=ptr;
}
else
{
new->next=start;
start=new;
}
return;
}
display()
{
struct bill *ptr;

YM/SR/CPRG2/1.0

21

Programming in C Part II
printf("\n\nItem code\tDescription\tRate\t Quantity
sold\n");
for(ptr=start;(ptr);ptr=ptr->next)
{
printf("%s\t
",ptr->itemno);
printf("%s\t
",ptr->itemdesc);
printf("%f\t
",ptr->rate);
printf("%d\t\n
",ptr->qty);
}
c=getchar();
}
struct bill *createnode()
{
struct bill *new1;
new1=(struct bill*)malloc(sizeof(struct bill));
printf("\n Enter :");
printf("\n\t Item No:\t");
scanf("%s",new1->itemno);
fflush(stdin);
printf("\n\tDescription:\t");
scanf("%s",new1->itemdesc);
fflush(stdin);
printf("\n\t Rate:\t");
scanf("%f",&new1->rate);
fflush(stdin);
printf("\n\t Quantity:\t");
scanf("%d",&new1->qty);
return(new1);
}

Looking at the function display(), in the above code, we find that the following
steps are required to traverse a list:
Declare a pointer to struct bill, which is ptr in our example.
Assign the address stored in start to ptr, assuming the list already exist.
Print the data contained by the node currently being pointed to by ptr
Re-initialize the pointer ptr with the address of the next node.
Repeat the previous two steps until ptr encounters NULL.

YM/SR/CPRG2/1.0

22

Programming in C Part II
The output of the program is given below:

YM/SR/CPRG2/1.0

23

Programming in C Part II

Search for a specific node


logic will be same as that of traversing the list, only we
have to give another extra condition to find whether the
data searched is equivalent to the data of the node
currently pointed or not.
for(ptr=start;(ptr);prev=ptr,ptr=ptr->
next)
{
if(strcmp(icode_del,ptr->itemno)==0)
{
//code to do certain task
}

Search for a specific node


Once we know how to traverse a linked list, searching for a particular node and
changing the data of that node will not be a great problem. The logic will be the
same as that of traversing the list, only we have to give another extra condition to
find whether the data searched is equivalent to the data of the node currently
pointed to or not. Once we accessed the desired node, changing the data of that
node is very simple.
Consider the following code, which achieves this:
#include <stdio.h>
#include<malloc.h>
struct bill
{
char itemno[5];
char itemdesc[30];
float rate;
int qty;
struct bill *next;
};
char c;
char icode_del[5];
struct bill *start;
main()
{
char choice;
choice='x';
while((choice!='q')&&(choice!='E'))
{
system("tput clear");

YM/SR/CPRG2/1.0

24

Programming in C Part II
printf("\n\n I. Insert into the list");
printf("\n D. Display the List");
printf("\n S. search a node");
printf("\n Q. Quit");
printf("\n\n\t Enter your choice :\t");
choice=getchar();
fflush(stdin);
if((choice=='I')||(choice=='i'))
{
add();
}
if((choice=='D')||(choice=='d'))
{
display();
}
if((choice=='Q')||(choice=='q'))
{
exit();
}
if((choice=='S')||(choice=='s'))
{
search();
}
}
}
add()
{
struct bill *createnode(),*new,*ptr,*prev;
new=createnode();
if(start==NULL)
{
start=new;
return;
}
for(ptr=start;(ptr)&&strcmp(new->itemno,ptr>itemno)>0;prev=ptr,ptr=ptr->next);
if(ptr!=start)
{
prev->next=new;
new->next=ptr;
}
else
{
new->next=start;
start=new;
}
return;
}

YM/SR/CPRG2/1.0

25

Programming in C Part II

display()
{
struct bill *ptr;
printf("\n\nItem code\tDescription\tRate\t Quantity
sold\n");
for(ptr=start;(ptr);ptr=ptr->next)
{
printf("%s\t
",ptr->itemno);
printf("%s\t
",ptr->itemdesc);
printf("%f\t
",ptr->rate);
printf("%d\t\n
",ptr->qty);
}
c=getchar();
}
struct bill *createnode()
{
struct bill *new1;
new1=(struct bill*)malloc(sizeof(struct bill));
printf("\n Enter :");
printf("\n\t Item No:\t");
scanf("%s",new1->itemno);
fflush(stdin);
printf("\n\tDescription:\t");
scanf("%s",new1->itemdesc);
fflush(stdin);
printf("\n\t Rate:\t");
scanf("%f",&new1->rate);
fflush(stdin);
printf("\n\t Quantity:\t");
scanf("%d",&new1->qty);
return(new1);
}
search()
{
struct bill *ptr,*prev;
printf("\nEnter The Item code to Search :\t");
scanf("%s",icode_del);
fflush(stdin);
for(ptr=start;(ptr);prev=ptr,ptr=ptr->next)
{
if(strcmp(icode_del,ptr->itemno)==0)
{
printf("Description :\t%s\n
",ptr->itemdesc);
printf("Rate
:\t%f\n
",ptr->rate);
printf("Quantity
:\t%d\n
",ptr->qty);
c=getchar();
return;
}
}

YM/SR/CPRG2/1.0

26

Programming in C Part II
printf("\nNo such item found");
c=getchar();
return;
}

To your existing code you just have to add the codes in bold. If you supply a
particular Item Code it will search and show you the other details pertaining to
that Item. If you execute the program, the following will be its output:

YM/SR/CPRG2/1.0

27

Programming in C Part II

Deletion of a node
To delete the node logically i.e. node previous to
the node marked for deletion has to be connected
to the node just after the node marked for
deletion.
200
200

215

prev
ptr

200

I001

Data

215

215

Address

232

I002

232

Data

Address

I004

Null

Data

Address

Deletion of a node
To delete an existing node from a linked list we have to follow the following steps.
We have to traverse the list and point to the node that has to be deleted. This
can be done in a manner similar to what we did while traversing the list.
If and when we find the node to be deleted, we have to logically delete it first.
In other words, the node before the one marked for deletion has to be
connected to the node just it (the one marked for deletion). So we have to
keep another pointer say prev to point to the node just before the node to be
deleted.

200
start

200

215

prev

ptr

200
I001
Data

215
215

Address

I002
Data

232
232
Address

I004
Data

Null
Address

From the above figure, you find that the node with the item code I002 has to be
deleted. That requires pointer ptr to be positioned on the node (to be deleted),

YM/SR/CPRG2/1.0

28

Programming in C Part II
and another pointer, say prev, to be positioned on the previous node with data
I001.
Once the pointers are positioned appropriately, you have to just link the first node
with the third node, so that logically the second node is deleted from the list. This
linking can be achieved by writing the following code.
prev->next=ptr->next;
This code holds true for deleting any node from the beginning or the end of the
list. A slight change is required in the code for deleting the first node from the list.
The start then needs to point to second node.
start=ptr->next;
Even after you have logically deleted the desired node, the node still exists
physically in the memory. To delete it physically, use the library function free().
Let's now look into the complete code for the deletion of node from a list
#include <stdio.h>
#include<malloc.h>
struct bill
{
char itemno[5];
char itemdesc[30];
float rate;
int qty;
struct bill *next;
};
char c;
char icode_del[5];
struct bill *start;
main()
{
char choice;
choice='x';
while((choice!='q')&&(choice!='E'))
{
system("tput clear");
printf("\n\n I. Insert into the list");
printf("\n D. Display the List");
printf("\n X. Delete a node");
printf("\n Q. Quit");
printf("\n\n\t Enter your choice :\t");
choice=getchar();

YM/SR/CPRG2/1.0

29

Programming in C Part II
fflush(stdin);
if((choice=='I')||(choice=='i'))
{
add();
}
if((choice=='D')||(choice=='d'))
{
display();
}
if((choice=='Q')||(choice=='q'))
{
exit();
}
if((choice=='X')||(choice=='x'))
{
remove1();
}
}
}
add()
{
struct bill *createnode(),*new,*ptr,*prev;
new=createnode();
if(start==NULL)
{
start=new;
return;
}
for(ptr=start;(ptr)&&strcmp(new->itemno,ptr>itemno)>0;prev=ptr,ptr=ptr->next);
if(ptr!=start)
{
prev->next=new;
new->next=ptr;
}
else
{
new->next=start;
start=new;
}
return;
}
display()
{
struct bill *ptr;
printf("\n\nItem code\tDescription\tRate\t Quantity
sold\n");
for(ptr=start;(ptr);ptr=ptr->next)
{

YM/SR/CPRG2/1.0

30

Programming in C Part II
printf("%s\t
printf("%s\t
printf("%f\t
printf("%d\t\n

",ptr->itemno);
",ptr->itemdesc);
",ptr->rate);
",ptr->qty);

}
c=getchar();
}
struct bill *createnode()
{
struct bill *new1;
new1=(struct bill*)malloc(sizeof(struct bill));
printf("\n Enter :");
printf("\n\t Item No:\t");
scanf("%s",new1->itemno);
fflush(stdin);
printf("\n\tDescription:\t");
scanf("%s",new1->itemdesc);
fflush(stdin);
printf("\n\t Rate:\t");
scanf("%f",&new1->rate);
fflush(stdin);
printf("\n\t Quantity:\t");
scanf("%d",&new1->qty);
return(new1);
}
remove1()
{
struct bill *ptr,*prev;
printf("\nEnter The Item code to delete :\t");
scanf("%s",icode_del);
fflush(stdin);
for(ptr=start;(ptr);prev=ptr,ptr=ptr->next)
{
if(strcmp(icode_del,ptr->itemno)==0)
{
if(ptr==start)
{
start=ptr->next;
return;
}
else
{
prev->next=ptr->next;
return;
}
free(ptr);
}
}
printf("\nNosuch item found");
return;
}

YM/SR/CPRG2/1.0

31

Programming in C Part II

Quiz
What is the difference between sorted and unsorted
single link list?
Write a function to insert a node at the beginning of an
unsorted single linked list.
Write a function to insert a node in a sorted single
linked list.

Quiz

YM/SR/CPRG2/1.0

32

Programming in C Part II

Summary
After the completion of this module now you
will be able to:
Appreciate the need of Data Structure
Appreciate the concept of Linked List
Appreciate Linked List in C
Create Linked List
Insert of nodes in an existing single Linked
List
Create Sorted Linked List
Traverse the list
Search a Node in the Single Linked List
Delete of a Node in single Linked List

Summary
At the end of this chapter, you will now be able to:
Appreciate the need of Data Structure
Appreciate the concept of Linked List
Appreciate Linked List in C
Create Linked List
Insert nodes in an existing single Linked List
Create sorted Linked List
Traverse the list
Search a Node in a single Linked List
Delete a Node in a single Linked List

YM/SR/CPRG2/1.0

33

Programming in C Part II

Doubly Linked List


Learn the concept of doubly linked lists
Use structures in C to represent doubly linked
list
Insert in doubly linked list
Traversing in doubly linked list

Doubly Linked List


At the end of this module, you will be able to:
Learn the concept of doubly linked lists
Use structures in C to represent doubly linked list
Insert in doubly linked list
Traverse in doubly linked list

YM/SR/CPRG2/1.0

34

Programming in C Part II

Concept of doubly linked lists


Doubly linked list is very similar to single linked list but
differs in having two pointers instead of a single pointer.
It is also a self referential structure containing the address
of both the next and the previous node.
150

197

Start
Last

150

NULL

176

Prev

I001

data

176

Next

197

150

I002

197

Prev

data

Next

176

Prev

I003

NULL

data

Next

Concept of doubly linked lists


After discussing the Single linked list, you must now be conversant with the
concepts of linked list. In the previous chapter you have learnt how to organize
data in the memory, so as to retrieve it efficiently as and when required.
But you must have noticed one limitation of single liked list in case of data
retrieval. While retrieving data from the single linked list, we can only move
forward. There is no way we can move backward. This is because every node
only contains the address of the next node, and not the previous node.
For certain kind of applications this can be a big constraint e.g. database
applications.
So, you must be wondering about the solution of this shortcoming.
The answer of C to this problem is, doubly linked list.

150

197

Start

Last

150

NULL

Prev

176

I001

data

176

Next

YM/SR/CPRG2/1.0

197

150

I002

197

Prev

data

Next

176

Prev

I003

NULL

data

Next

35

Programming in C Part II
From the figure above, you find that doubly linked list differs from the single
linked list in having two pointers, one pointing to the next node and the other
pointing to the previous one. Only the first and the last nodes are the exception.
The first node only points to the next node, and the last node points only to the
previous node. Like single linked list, start contains the address of the first node.
An additional pointer, i.e. last, contains the address of the last node.
Now, the question is how to represent doubly linked list in C?
We will give answer to this question in the next section.

YM/SR/CPRG2/1.0

36

Programming in C Part II

Structures in C to represent doubly


linked list
Nodes in doubly linked list are represented with the help
of structure.
struct bill
{
char itemno[5];
char itemdesc[30];
float rate;
int qty;
struct bill *prev; //pointer to point to
// the previous node
struct bill *next; //pointer to point to
// the next node
};

Structures in C to represent doubly linked list


We have already discussed the use of structure to represent single linked list.
You will find not much difference in the representation of doubly linked list. The
only difference that you will find is that it contains an additional pointer to the
structure itself.
Given below is a typical representation of a structure for implementation of
doubly linked list:
struct bill
{
char itemno[5];
char itemdesc[30];
float rate;
int qty;
struct bill *prev; //pointer to point to the
previous node
struct bill *next; //pointer to point to the next
node
};

If you consider the above code you will find that there is an extra pointer, called
prev, which will point to the previous node.
After knowing how to represent a node of a doubly linked list, let's find out how to
create and manipulate such lists.

YM/SR/CPRG2/1.0

37

Programming in C Part II

Inserting a node in doubly linked list


Insertion in doubly linked list can be of three types
Insertion at the beginning of a list
Insertion in the middle of a list and at the end of a list
120

197
150
120

Last

Start

NULL

I004

150

Prev

data

Next

150

176

197

NULL

I001

176

150

I002

197

176

I003

Prev

data

Next

Prev

data

Next

Prev

data

Prev1

NULL
Next

Ptr
197
Last

150
Start

150
NULL
Prev

176
I001
data

176
Next

197

150

I002

197

176

I005

NULL

Prev

data

Next

Prev

data

Next

120
120
New

NULL
Prev

I004
data

NULL
Next

Inserting a node in doubly linked list


Inserting a node in a doubly linked list is not much different from inserting a node
in a single linked list. The only extra job that you have to do is maintain two
pointers, one pointing to the next node and the other pointing to the previous one
of the list.
During insertion of a node in a list, there can be three situations:
Insertion at the beginning of a list
Insertion in the middle of a list
Insertion at the end of a list

Insertion at the beginning of a list

120

197
150
NEW

120

Last

Start

150

176

197

NULL

I004

150

NULL

I001

176

150

I002

197

176

I003

NULL

Prev

data

Next

Prev

data

Next

Prev

data

Next

Prev

data

Next

You can find from the figure above, that node pointed to by the pointer new will
be inserted before the node pointed by the pointer start.

YM/SR/CPRG2/1.0

38

Programming in C Part II
The code below shows the addition of a node at the beginning of a list:
#include <stdio.h>
#include<malloc.h>
struct bill
{
char itemno[5];
char itemdesc[30];
float rate;
int qty;
struct bill *prev;
struct bill *next;
};
char c;
struct bill *start;
main()
{
char choice;
choice='x'; start=NULL;
while((choice!='q')&&(choice!='E'))
{
system("tput clear");
printf("\n\n I. Insert into the list");
printf("\n Q. Quit");
choice=getchar();
fflush(stdin);
if((choice=='I')||(choice=='i'))
{
add();
}
if((choice=='Q')||(choice=='q'))
{
exit();
}
}
}
add()
{
struct bill *createnode(),*new;
new=createnode();
if(start==NULL)
{
start=new;
return;
}
new->next=start;
start->prev=new;
start=new;
return;

YM/SR/CPRG2/1.0

39

Programming in C Part II
}

struct bill *createnode()


{
struct bill *new1;
new1=(struct bill*)malloc(sizeof(struct bill));
printf("\n Enter :");
printf("\n\t Item No:\t");
scanf("%s",new1->itemno);
fflush(stdin);
printf("\n\tDescription:\t");
scanf("%s",new1->itemdesc);
fflush(stdin);
printf("\n\t Rate:\t");
scanf("%f",&new1->rate);
fflush(stdin);
printf("\n\t Quantity:\t");
scanf("%d",&new1->qty);
return(new1);
}

The code, which is in bold, is for handling the addition of a node at the beginning
of a list. You have to first of all check, whether the list exists or not. This can be
done with the help of the start pointer. If the start pointer is NULL then the list is
empty. So you just have to assign the address of the first node to the start
pointer.
if(start==NULL)
{
start=new;
return;
}

If the list already exists, the next pointer of the new node should store the
address of the node pointed by the start pointer.
new->next=start;
The prev pointer of the node pointed by start pointer should contain the address
of the new node.
start->prev=new;
The start pointer should contain the address of the new node.
start=new;

YM/SR/CPRG2/1.0

40

Programming in C Part II

Insertion of a node in the middle and at the end of a list

Prev1

Ptr
197

150

Last

Start

150

176

197

NULL

I001

176

150

I002

197

176

I005

NULL

Prev

data

Next

Prev

data

Next

Prev

data

Next

120
120

NULL

I004

New

Prev

data

NULL
Next

Insertion in the middle of the list is very similar to that of a single linked list. Only
thing that you have to do is to maintain two pointers next and prev while linking
the nodes. The code is given below:
#include <stdio.h>
#include<malloc.h>
struct bill
{
char itemno[5];
char itemdesc[30];
float rate;
int qty;
struct bill *prev;
struct bill *next;
};
char c;
struct bill *start;
main()
{
char choice;
choice='x';
while((choice!='q')&&(choice!='E'))
{
system("tput clear");
printf("\n\n I. Insert into the list");
printf("\n Q. Quit");
choice=getchar();
fflush(stdin);

YM/SR/CPRG2/1.0

41

Programming in C Part II
if((choice=='I')||(choice=='i'))
{
add();
}
if((choice=='Q')||(choice=='q'))
{
exit();
}
}
}
add()
{
struct bill *createnode(),*new,*prev1,*ptr;
new=createnode();
if(start==NULL) //Adding a node in an empty list
{
start=new;
return;
}
for(ptr=start;(ptr)&&strcmp(new->itemno,ptr->
itemno)>0;prev1=ptr,ptr=ptr->next);
if(ptr!=start&&ptr!=NULL) //Adding the node in the
middle
{
new->next=ptr;
new->prev=prev1;
prev1->next=new;
ptr->prev=new;
}
else
{
if(ptr==NULL) //Adding the node at the end of the
node
{
new->next=ptr;
new->prev=prev1;
prev1->next=new;
}
else
{
new->next=start;// If the new node is the first
node
start=new;
new->prev=NULL;
}
}
}

YM/SR/CPRG2/1.0

42

Programming in C Part II

struct bill *createnode()


{
struct bill *new1;
new1=(struct bill*)malloc(sizeof(struct bill));
printf("\n Enter :");
printf("\n\t Item No:\t");
scanf("%s",new1->itemno);
fflush(stdin);
printf("\n\tDescription:\t");
scanf("%s",new1->itemdesc);
fflush(stdin);
printf("\n\t Rate:\t");
scanf("%f",&new1->rate);
fflush(stdin);
printf("\n\t Quantity:\t");
scanf("%d",&new1->qty);
return(new1);
}

As you can see from the add() function, which is in bold, we are writing three
different code snippet for adding, in the existing list.
If the node inserted is in between two nodes, you have to position the two
pointers appropriately. That is, ptr will point to the node before which the new
node is inserted and prev1 points to the node after which the new node will be
inserted. This positioning of the two pointers is done in the same way as it
happened in the single linked list. After that you have to write the following code
snippet to link the nodes:
new->next=ptr;
new->prev=prev1;
prev1->next=new;
ptr->prev=new;

If the new node added happens to be the last node then you have to place the ptr
and prev1 accordingly.

YM/SR/CPRG2/1.0

43

Programming in C Part II

120

197

NUL
L

prev1

Last

Ptr

150
Start

150

176

197

NU
LL

I001

176

150

I002

197

176

I005

NU
LL

Prev

data

Next

Prev

data

Next

Prev

data

Next

120
120
New

NU
LL
Prev

I004
data

NU
LL
Next

Following this, you have to link the nodes using the following code snippet:
new->next=ptr;
new->prev=prev1;
prev1->next=new;

If the new node is supposed to be added in an existing list and that node
happens to be the first node, then the following code snippet is used to link the
nodes:

new->next=start;
start=new;
new->prev=NULL;

YM/SR/CPRG2/1.0

44

Programming in C Part II

Traversing in doubly linked list


display()
{
struct bill *ptr,*last,*x;
for(ptr=start;(ptr);x=ptr,ptr=ptr->next);
last=x;
printf("press Next record<n>, previous record<p>,<e> to
Exit\t");
ptr=start;
while((c!='E')&&(c!='e'))
{ c=getchar();
if((c=='n')||c=='N')
{ptr=ptr->next;
if(ptr==NULL)
{ptr=last;}
printf("Item Code:\t %s\n
if((c=='p')||c=='P')
{ptr=ptr->prev;
if(ptr==NULL){ptr=start;}
printf("Item Code: \t%s\n
}}}

",ptr->itemno);}

",ptr->itemno);

Traversing in doubly linked list


Traversing the doubly linked list is very similar to the traversing in the single
linked list. The only difference, and its an advantage, is that of the movement in
both the direction. The following code explains how this can be achieved:
#include <stdio.h>
#include<malloc.h>
struct bill
{
char itemno[5];
char itemdesc[30];
float rate;
int qty;
struct bill *prev;
struct bill *next;
};
char c;
struct bill *start;
main()
{
char choice;
choice='x';
while((choice!='q')&&(choice!='E'))
{
system("tput clear");
printf("\n\n I. Insert into the list");
printf("\n D. Display the List");
printf("\n Q. Quit");
choice=getchar();
fflush(stdin);
if((choice=='I')||(choice=='i'))

YM/SR/CPRG2/1.0

45

Programming in C Part II
{
add();
}
if((choice=='D')||(choice=='d'))
{
display();
}
if((choice=='Q')||(choice=='q'))
{
exit();
}
}
}
add()
{
struct bill *createnode(),*new,*prev1,*ptr;
new=createnode();
if(start==NULL)
{
start=new;
return;
}
for(ptr=start;(ptr)&&strcmp(new->itemno,ptr>itemno)>0;prev1=ptr,ptr=ptr->next);
if(ptr!=start&&ptr!=NULL)
{
new->next=ptr;
new->prev=prev1;
prev1->next=new;
ptr->prev=new;
}
else
{
if(ptr==NULL)
{
new->next=ptr;
new->prev=prev1;
prev1->next=new;
}
else
{
new->next=start;
start=new;
new->prev=NULL;
}
}
}
display()

YM/SR/CPRG2/1.0

46

Programming in C Part II
{
struct bill *ptr,*last,*x;
for(ptr=start;(ptr);x=ptr,ptr=ptr->next);
last=x;
printf("To First record press<f>,Next record<n>,
previous record<p>,Last record <l>.<e> to Exit\t");
ptr=start;
while((c!='E')&&(c!='e'))
{
c=getchar();
if((c=='f')||c=='F')
{
ptr=start;
printf("Item Code: \t%s\n
",ptr>itemno);
printf("Description\t %s\n
",ptr>itemdesc);
printf("Rate%f\t\n
",ptr->rate);
printf("Quantity\t%d\n
",ptr->qty);
}
if((c=='n')||c=='N')
{
ptr=ptr->next;
if(ptr==NULL)
{
ptr=last;
}
printf("Item Code:\t %s\n

",ptr-

printf("Description\t %s\n

",ptr-

>itemno);
>itemdesc);
printf("Rate%f\t\n
printf("Quantity\t%d\n

",ptr->rate);
",ptr->qty);

}
if((c=='p')||c=='P')
{
ptr=ptr->prev;
if(ptr==NULL)
{
ptr=start;
}
printf("Item Code: \t%s\n

",ptr-

>itemno);
printf("Description \t%s\n

",ptr-

>itemdesc);
printf("Rate%f\t\n
printf("Quantity\t%d\n

",ptr->rate);
",ptr->qty);

YM/SR/CPRG2/1.0

47

Programming in C Part II

if((c=='l')||c=='L')
{
ptr=last;
printf("Item Code: \t%s\n

",ptr-

printf("Description \t%s\n

",ptr-

>itemno);
>itemdesc);
printf("Rate%f\t\n
printf("Quantity\t%d\n

",ptr->rate);
ptr->qty);

",

}
}
}
struct bill *createnode()
{
struct bill *new1;
new1=(struct bill*)malloc(sizeof(struct bill));
printf("\n Enter :");
printf("\n\t Item No:\t");
scanf("%s",new1->itemno);
fflush(stdin);
printf("\n\tDescription:\t");
scanf("%s",new1->itemdesc);
fflush(stdin);
printf("\n\t Rate:\t");
scanf("%f",&new1->rate);
fflush(stdin);
printf("\n\t Quantity:\t");
scanf("%d",&new1->qty);
return(new1);
}

YM/SR/CPRG2/1.0

48

Programming in C Part II

Quiz
How many pointers are declared in the structure
which represents a node in doubly linked list?
What is the difference in instructions between
inserting at the middle of the linked list an at the
end of the linked list.
Write a code to search a particular node in a
doubly linked list.

Quiz
.

YM/SR/CPRG2/1.0

49

Programming in C Part II

Quiz
Summary
After
How the
many
pointers
declared
in the
structure
end
of thisare
chapter,
now
you
are
which
a node in doubly linked list?
able represents
to:
What
is the
instructions
Learn
thedifference
concept ofindoubly
linkedbetween
lists
inserting
at the middle
ofrepresent
the linkeddoubly
list anlinked
at the
Use structures
in C to
endlist
of the linked list.
Insert
in doubly
linked
list
Write
a code
to search
a particular
node in a

Traversing
in
doubly
linked
list
doubly linked list.

Summary
After this chapter, you are now able to:
Learn the concept of doubly linked lists
Use structures in C to represent doubly linked list
Insert in doubly linked list
Traverse in doubly linked list

YM/SR/CPRG2/1.0

50

Programming in C Part II

Stack, Queue and Binary Tree

Appreciate Stacks in C
Represent Stacks in C
Use push() and the pop() functions
Appreciate queue in C
Use structures in C to represent queue
Insert and delete in queue
Appreciate the concept of Binary trees
Implement Binary trees with structures in C
Insert node in binary tree
Search a node in a binary tree
Traverse a binary tree

Delete a node from a binary tree

Stack, Queue and Binary Tree


At the end of the chapter, you will be able to:
Appreciate Stacks in C
Represent Stacks in C
Use push() and the pop() functions
Appreciate queue in C
Use structures in C to represent queue
Insert and delete in queue
Appreciate the concept of Binary trees
Implement Binary trees with structures in C
Insert node in binary tree
Traverse a binary tree
Delete a node from a binary tree

YM/SR/CPRG2/1.0

51

Programming in C Part II

Appreciate Stacks in C
"A stack is an ordered collection of items into
which new items may be inserted and from which
items may be deleted at one end, called top of
the stack".

Appreciate Stacks in C
You must have heard the term stack very frequently, i.e in the kitchen or music
CD shop. It is one of the most useful and important concepts in computer
science. We will try to discover its importance and implementation in C.
Now the question is what is a stack.
"A stack is an ordered collection of items into which new items may be inserted
and older ones deleted, from only one end, called the top of the stack".

To draw an analogy for stack in real life, just think about CD's piled one on top of
the other.

As you can see from the figure that if you want to add a new item, you have to
put it on the top of the stack. Conversely, if you want to remove any item from the
stack, you have to do it from the top again. That is the item added last will be
removed first.
Thus, stacks are also known as Last-In-First-Out (LIFO) lists.

YM/SR/CPRG2/1.0

52

Programming in C Part II

Stacks in C
Stacks are represented with the help of linked list.
struct stack
{
char itemno[5];
char itemdesc[30];
float rate;
int qty;
struct stack *next;
}*new1,*top;

Stacks in C
By definition, a stack is an ordered collection of items. C already has a data type,
i.e. array, which is a collection of ordered items.
Therefore, we might think that array can be a choice to represent stack in C. But
there are a lot of difference between stack and array. In array, the number of
elements is fixed, and it is determined during the definition of the array. Whereas
a stack has to be a dynamic object, whose size has to change on demand.
Therefore we will represent stacks with the help of linked list.
A stack item can be depicted in this form:
struct stack
{
char itemno[5];
char itemdesc[30];
float rate;
int qty;
struct stack *next;
}*new1,*top;
You can see, from the above code, that a structure pointer, called top, has been
declared. It points to the beginning of the stack.

YM/SR/CPRG2/1.0

53

Programming in C Part II

The push() and the pop() functions


The addition and deletion to a stack is conventionally known as push() and
pop() respectively.
push()
{new1=(struct stack*)malloc(sizeof(struct stack));
printf("\n Enter :");
printf("\n\t Item No:\t");
scanf("%s",new1->itemno);
fflush(stdin);
printf("\n\tDescription:\t");
scanf("%s",new1->itemdesc);
fflush(stdin);
printf("\n\t Rate:\t");
scanf("%f",&new1->rate);
fflush(stdin);
printf("\n\t Quantity:\t");
scanf("%d",&new1->qty);
new1->next=top;
top=new1;
c=getchar();}

The push() and the pop() functions


One of the important tasks in stack implementation is to add to, and remove
elements from it. The addition and deletion to a stack is conventionally known as
push and pop respectively.
The push() and the pop() functions are special cases of insertion and deletion
from a linked list. You can only insert into, or delete from the top of a stack.
These two functions are just special cases of insertion and deletion in a linked
list.

#include <stdio.h>
#include<malloc.h>
struct stack
{
char itemno[5];
char itemdesc[30];
float rate;
int qty;
struct stack *next;
}*new1,*top;
char c;
main()
{
char choice;
choice='x';
top=NULL;
while((choice!='q')&&(choice!='E'))

YM/SR/CPRG2/1.0

54

Programming in C Part II

{
system("tput clear");
printf("\n\n I. Insert onto the Stack");
printf("\n D. Display the Stack");
printf("\n Q. Quit");
choice=getchar();
fflush(stdin);
if((choice=='I')||(choice=='i'))
{
push();
}
if((choice=='D')||(choice=='d'))
{
pop();
}
}
}
push()
{
new1=(struct stack*)malloc(sizeof(struct stack));
printf("\n Enter :");
printf("\n\t Item No:\t");
scanf("%s",new1->itemno);
fflush(stdin);
printf("\n\tDescription:\t");
scanf("%s",new1->itemdesc);
fflush(stdin);
printf("\n\t Rate:\t");
scanf("%f",&new1->rate);
fflush(stdin);
printf("\n\t Quantity:\t");
scanf("%d",&new1->qty);
new1->next=top;
top=new1;
c=getchar();
}
pop()
{
printf("Item Code: \t%s\n
printf("Description\t %s\n
printf("Rate%f\t\n
printf("Quantity\t%d\n
new1=top;
top=top->next;
free(new1);
}

YM/SR/CPRG2/1.0

",top->itemno);
",top->itemdesc);
",top->rate);
",top->qty);

55

Programming in C Part II

In code given above, look at the function push(). First of all, we are just creating
a node and storing the address, in a pointer called new1.
new1=(struct stack*)malloc(sizeof(struct stack));

Then you have to make the new element (pointed to by the new1 pointer) the
top-most one, and the previous element the next element.
new1->next=top;
top=new1;
So we find that just by manipulating the next and the top pointers, you can add
an element on top of the stack.
In the same way, you can pop the values from the top by just re-assigning top by
the value of next pointer (of the first element of the stack), and then releasing the
memory for that element.
new1=top;
top=top->next;
free(new1);

YM/SR/CPRG2/1.0

56

Programming in C Part II

Appreciate queue in C
Queues are ordered collection of items where
items are added at the end of the queue, and the
items are removed from the front.
Queue it is also termed as FIFO (First in First
out list).

Appreciating queue in C
We have seen that stacks are ordered collection of items, where items are added
and removed from the top. Queues also ordered collection of items, but it differs
from the stack in the order of addition and removal of items.
In queue, items are deleted from one end known as the front, and inserted from
the other end known as the rear of the queue. Due to this nature, queues are
also known as FIFO (First in First out) list.

The following figure illustrates a queue:

You must be asking this pertinent question at this point of time: Where do
we apply this concept of queue?
Generally, queues are used in applications where some kind of scheduling job is
done. Operating Systems, that are mostly time-sharing in nature, use this
concept to schedule the execution of applications. When a new program is to be
executed, it is put at the end of the queue. The programs, which are at the
beginning, are executed first.
In real life scenario, you must have waited in a queue in front of the railway
reservation counter.

YM/SR/CPRG2/1.0

57

Programming in C Part II

Structures in C to represent queue


struct queue
{
char itemno[5];
char itemdesc[30];
float rate;
int qty;
struct queue *next;
}*new1,*front,*rear;

Structures in C to represent queue


Queues are also implemented in the same manner as stacks, in C. They only
differ in the order of insertion and deletion of the constituent elements. We will be
representing the queue with the help of linked list.

struct queue
{
char itemno[5];
char itemdesc[30];
float rate;
int qty;
struct queue *next;
}*new1,*front,*rear;
You can notice that the structure is very similar to that of the node in a linked list.
Just two pointers front and rear are declared to point to the front and rear of the
queue, respectively.

YM/SR/CPRG2/1.0

58

Programming in C Part II

Insert and delete in queue


insert()
{
new1=(struct stack*)malloc(sizeof(struct queue));
printf("\n Enter :");
printf("\n\t Item No:\t");
scanf("%s",new1->itemno);
fflush(stdin);
printf("\n\tDescription:\t");
scanf("%s",new1->itemdesc);
fflush(stdin);
printf("\n\t Rate:\t");
scanf("%f",&new1->rate);
fflush(stdin);
printf("\n\t Quantity:\t");
scanf("%d",&new1->qty);
if(rear==NULL)
{front=new1;}
else{rear->next=new1;}
rear=new1;
c=getchar();}

Insert and delete in queue


In queue you can only insert at the end of the queue:
#include <stdio.h>
#include<malloc.h>
struct queue
{
char itemno[5];
char itemdesc[30];
float rate;
int qty;
struct queue *next;
}*new1,*front,*rear;
char c;
main()
{
char choice;
choice='x';
front=NULL;
rear=NULL;
while((choice!='q')&&(choice!='E'))
{
system("tput clear");
printf("\n\n I. Insert onto the Queue");
printf("\n D. Display the queue");
printf("\n Q. Quit");
choice=getchar();
fflush(stdin);
if((choice=='I')||(choice=='i'))
{
insert();
}
if((choice=='D')||(choice=='d'))
{
remove1();

YM/SR/CPRG2/1.0

59

Programming in C Part II
}
}
}
insert()
{
new1=(struct stack*)malloc(sizeof(struct queue));
printf("\n Enter :");
printf("\n\t Item No:\t");
scanf("%s",new1->itemno);
fflush(stdin);
printf("\n\tDescription:\t");
scanf("%s",new1->itemdesc);
fflush(stdin);
printf("\n\t Rate:\t");
scanf("%f",&new1->rate);
fflush(stdin);
printf("\n\t Quantity:\t");
scanf("%d",&new1->qty);
if(rear==NULL)
{
front=new1;
}
else
{
rear->next=new1;
}
rear=new1;
c=getchar();
}
remove1()
{
new1=front;
printf("Item Code: \t%s\n
printf("Description\t %s\n
printf("Rate%f\t\n
printf("Quantity\t%d\n
front=new1->next;
if(front==NULL)
{
rear=NULL;
}
free(new1);
c=getchar();

",new1->itemno);
",new1->itemdesc);
",new1->rate);
", new1->qty);

YM/SR/CPRG2/1.0

60

Programming in C Part II
Consider the following code snippet. First we are creating a node and storing the
address in a pointer called new1:
new1=(struct stack*)malloc(sizeof(struct queue));
If the queue is empty, the pointer front should point to the node, whose address
is stored in the pointer new1.
Otherwise if the queue exists, the next pointer of the last node (whose address is
stored in the rear pointer), is assigned the address of the newly created node, i.e.
new1.
Nevertheless for both the cases, the pointer rear is assigned the address of the
new node, i.e. new1.
if(rear==NULL)
{
front=new1;
}
else
{
rear->next=new1;
}
rear=new1;

Items can only be removed from the front of the queue.


So first, the address of the node to be deleted, i.e. front, is stored in a pointer
called new1.
Then the pointer front is re-assigned the address of the second (next) node in the
queue, pointed to by the next pointer of the node, whose address is stored in
new1.
Finally, node is physically deleted with the help of the library function, free().
new1=front;
printf("Item Code: \t%s\n
printf("Description\t %s\n
printf("Rate%f\t\n
printf("Quantity\t%d\n
front=new1->next;
if(front==NULL)
{
rear=NULL;
}
free(new1);

YM/SR/CPRG2/1.0

",new1->itemno);
",new1->itemdesc);
",new1->rate);
", new1->qty);

61

Programming in C Part II

The concept of Binary trees


A binary tree is a data structure, which represents
data in inverted tree like structure.
It contains a finite set of elements that is either
empty or is partitioned into three disjoint subsetsRoot, left and right.
It is generally used to represent data, which has
some kind of hierarchical relationship among
elements.

The concept of Binary trees


In the previous chapters, we have learnt about the use of linked list (single and
double) to implement data structures. We have also understood how it offers
flexibility in comparison to arrays, in terms of dynamically adding or deleting
items in a list.
Though lists are very flexible in terms of addition and deletion of items, it suffers
a major drawback in terms of the searching time. The searching in a linked list is
linear i.e. the search-time is directly proportional to the size of the list. So if the
size of the linked list is very large, the time required to search for a particular
element is also longer.
To do away with this inefficiency, we will discuss another data structure called
binary tree. The main objective of this data structure is to reduce the searchtime of an element.
Now the big question is - what is this binary tree?
A binary tree is a data structure, which represents data in inverted tree like
structure. It contains a finite set of elements that is either empty or is partitioned
into three disjoint subsets- Root, Left, and Right. It is generally used to
represent data, which has some kind of hierarchical relationship among
elements.
The figure below depicts a binary tree containing the Item Code.

YM/SR/CPRG2/1.0

62

Programming in C Part II

I010
I002
I001

I013
I005

I004

I017

I016

I019

From the figure given above, lets try to understand the concept of a binary tree.
Each bubble in the figure is actually a node or a leaf. Each node has a data part
and pointers (which stores the address of the nodes to which it points).
The top most node in the tree is called the root. In the above figure, the node
with the Item Code I010 is the root. Each node under a node is called subtree.
For example, node with item code I002 is a subtree. A node with a subtree under
it, is called a parent node. For example, the node with the item code I002 is the
parent node of the node with item code I005 and I001. If a node has no subtree
under it, then it is known as terminal node. For example, the node containing
the item code I016 is a terminal node.
Different types of binary tree
Binary trees can be of different types. But we will be concentrating on the
following two types of binary trees:
Unbalanced binary tree
Balanced binary tree
Unbalanced binary tree
In this type of binary tree, the heights of the subtrees are not equal. Although,
each node can have a maximum of two subtrees, but it may not contain any node
at all. This produces an unbalanced tree.
The following figure depicts an unbalanced tree:

YM/SR/CPRG2/1.0

63

Programming in C Part II

I010
I003

I002
I001

I005

I000

Balanced binary tree


In balanced binary tree, the numbers of nodes in both sides are balanced. That is
the heights of the two subtrees are almost same. They can differ by one node, at
most.
The following figure depicts a balanced binary tree:

I010
I002
I001

I013
I005

I004

I016

I015

I019

In this chapter we will concentrate on the most popular form of binary tree, i.e.
sorted binary tree.
In a sorted binary tree all the nodes are arranged following a particular pattern.
The pattern is that all the nodes having data larger than the data of the parent
node is arranged on the right side of the tree.

YM/SR/CPRG2/1.0

64

Programming in C Part II
On the other hand, the nodes having data smaller than the data of the parent
node are added on the left side of the tree.
The following figures depicts a sorted binary tree:

I010
I006
I005

I0013
I008

I007

I0019

I0018

I0029

From the figure above you can see that the node with data larger than the parent
(root) node, i.e. the node containing the data item I006, is added on the left of the
root .
The advantage that we get from sorted binary tree is that searching, insertion,
and deletion becomes much faster.
Though we have explained what is binary tree but still we have not answered the
question - What is the application of binary tree?
Binary tree is a very handy data structure when we require two-way decision
making at different points of a process. It is also useful when we have to store or
represent some kind of hierarchical data.
For instance if you want to show the Unix file system, which is hierarchical in
nature, then binary tree can be the best option.

YM/SR/CPRG2/1.0

65

Programming in C Part II

Binary trees with structures in C


struct bill
{
char itemno[5];
char itemdesc[30];
float rate;
int qty;
struct bill *left;
struct bill *right;
};
struct bill *root;

Binary trees with structures in C


In the course of studying C, we have already seen the implementation of several
data structures. Binary tree is represented in a similar fashion as doubly linked
list:
struct bill
{
char itemno[5];
char itemdesc[30];
float rate;
int qty;
struct bill *left;
struct bill *right;
};
struct bill *root;
From the above code snippet you can find a resemblance with the doubly linked
list. Conventionally the two pointers are named left and right, respectively. We
have also declared another pointer called root. It will be used to store the
address of the first node.

YM/SR/CPRG2/1.0

66

Programming in C Part II

Insert node in binary tree


in binary sorted tree, first we have to compare the data
part of the newly created node with the data part of the
existing nodes. This is required to insert the node in
the appropriate place.
Root
100

110

I005

120

left

Data

right

110

120

NULL

I003

NULL

NULL

I009

NULL

left

Data

right

left

Data

right

130
NULL

I016

NULL

left

Data

right

Insert node in binary tree


We our concentrating on the discussion of sorted binary trees. Therefore, we will
be discussing insertion in a sorted binary tree.
Like any other sorted structure, in binary sorted tree we first have to compare the
data part of the newly created node with the data part of the existing nodes. This
is required to insert the node in the appropriate place.
After working with linked lists it is sure that you are not to be told that, to insert a
new node first of all you have to create the node by allocating memory to it. After
that, you have to change the left and right pointer of the node accordingly, under
which the new node will be added.
Lets look into the figure given below and try to understand it:
Root
100
110

I005

120

left

Data

right

110

120

NULL

I003

NULL

NULL

I009

NULL

left

Data

right

left

Data

right

An existing binary tree

YM/SR/CPRG2/1.0

67

Programming in C Part II
Root
100
110

I005

120

left

Data

right

110

120

NULL

I003

NULL

NULL

I009

NULL

left

Data

right

left

Data

right

130
NULL

I016

NULL

left

Data

right

A node has to be inserted


A question might have spawned in your mind:
How I will know where to add the newly created node?
From the figure given above, it is clear that the Item code in the newly created
node is I016, which is greater than the Item code of the root node. So it will be
added to the right side of the root node. Again under the root there is another
node whose item code is less than the item code of the newly created node. So
the new node will move to right side of that node. In the right side of the node
with the item code I009, there is no other node. So the newly created node will to
be added to the right pointer of this node. As a result we have to place a pointer
say prev on the node with the item code I009.
The following code places the pointer on the appropriate node:
struct bill *find(struct bill *neo)
{
struct bill *ptr,*prev;
ptr=root;
while(ptr)
{
if((strcmp(neo->itemno,ptr->itemno))>0)
{
prev=ptr;
ptr=ptr->right;
}
else
{
if((strcmp(neo->itemno,ptr->itemno))<0)

YM/SR/CPRG2/1.0

68

Programming in C Part II
{
prev=ptr;
ptr=ptr->left;
}
else
{
prev=NULL;
ptr=NULL;
}
}
}
return prev;
}

From the above code, you can find that we have taken two pointers, i.e. ptr and
prev. The pointer ptr is assigned the address stored by the pointer root. A loop is
started, which continues until it encounters NULL. Inside the loop we are
comparing the data part of the newly created node with the data of the node
pointed to by the pointer ptr. If the value contained in the data part of the newly
created node is greater than the node pointed to by the ptr, then it is advanced
towards the right of the list. Otherwise, it is advanced towards the left of the list.
Whether the ptr is advanced to the right or the left of the list, the pointer prev is
made to follow the pointer ptr.
Root
100
110

I005

120

left

Data

right

120
prev

NULL
ptr

110

120

NULL

I003

NULL

NULL

I009

NULL

left

Data

right

left

Data

right

130

YM/SR/CPRG2/1.0

NULL

I016

NULL

left

Data

right

69

Programming in C Part II
Once the pointer prev is positioned appropriately, it is returned to the caller. Now
lets look into the caller function, which actually adds the newly created node to
the list.
add()
{
struct bill *createnode(),*new,*prev1,*find();
new=createnode();
if(root==NULL)
{
root=new;
}
else
{
prev1=find(new);
if(prev1!=NULL)
{
if((strcmp(new->itemno,prev1->itemno))>0)
{
prev1->right=new;
}
else
{
prev1->left=new;
}
}
else
{
printf("\nThe Item code already exists\n");
}
}
}

Let's try to understand the code. First of all we are checking whether the root is
NULL or not. If the root is NULL, it means the tree is empty. Therefore, we are
straightway assigning the address of the newly created node to the root.
Otherwise we are calling the function find() to get the pointer pointing to the node
where the newly created node has to be added.
Once we get the pointer, again we are checking the data part of the newly
created node with that of that node under which it will be added. If the data part
of the newly created node is greater than the node pointed to by the prev, we are
assigning the address of the newly created node to the right pointer of the node
pointed to by the prev. Otherwise if it is less, then we are assigning the address
of the newly created node to the left pointer of the node pointed to by the prev.

YM/SR/CPRG2/1.0

70

Programming in C Part II

if((strcmp(new->itemno,prev1->itemno))>0)
{
prev1->right=new;
}
else
{
prev1->left=new;
}

If we combine the code, it will be like this:


#include <stdio.h>
#include<malloc.h>
struct bill
{
char itemno[5];
char itemdesc[30];
float rate;
int qty;
struct bill *left;
struct bill *right;
};
char c;
struct bill *root;
main()
{
char choice;
choice='x';
while((choice!='q')&&(choice!='E'))
{
system("tput clear");
printf("\n\n I. Insert into the Binary tree");
printf("\n Q. Quit");
printf("\n Enter your choice :\t");
choice=getchar();
fflush(stdin);
if((choice=='I')||(choice=='i'))
{
add();
}
if((choice=='Q')||(choice=='q'))
{
exit();
}
}
}

YM/SR/CPRG2/1.0

71

Programming in C Part II
add()
{
struct bill *createnode(),*new,*prev1,*find();
new=createnode();
if(root==NULL)
{
root=new;
}
else
{
prev1=find(new);
if(prev1!=NULL)
{
if((strcmp(new->itemno,prev1->itemno))>0)
{
prev1->right=new;
}
else
{
prev1->left=new;
}
}
else
{
printf("\nThe Item code already exists\n");
}
}
}
struct bill *createnode()
{
struct bill *new1;
new1=(struct bill*)malloc(sizeof(struct bill));
printf("\n Enter :");
printf("\n\t Item No:\t");
scanf("%s",new1->itemno);
fflush(stdin);
printf("\n\tDescription:\t");
scanf("%s",new1->itemdesc);
fflush(stdin);
printf("\n\t Rate:\t");
scanf("%f",&new1->rate);
fflush(stdin);
printf("\n\t Quantity:\t");
scanf("%d",&new1->qty);
return(new1);
}
struct bill *find(struct bill *neo)
{
struct bill *ptr,*prev;
ptr=root;
while(ptr)

YM/SR/CPRG2/1.0

72

Programming in C Part II
{
if((strcmp(neo->itemno,ptr->itemno))>0)
{
prev=ptr;
ptr=ptr->right;
}
else
{
if((strcmp(neo->itemno,ptr->itemno))<0)
{
prev=ptr;
ptr=ptr->left;
}
else
{
prev=NULL;
ptr=NULL;
}
}
}
return prev;
}

YM/SR/CPRG2/1.0

73

Programming in C Part II

Traverse a binary tree


We can traverse a binary tree with recursion.
show(struct bill *ptr)
{ if(!ptr)
{return;}
show(ptr->left);
printf("%s\t
",ptr->itemno);
printf("%s\t
",ptr->itemdesc);
printf("%f\t
",ptr->rate);
printf("%d\t\n ",ptr->qty);
show(ptr->right);}

Traversing a binary tree


To traverse a sorted binary tree, the best possible solution is to take the help of
recursion. You have already learnt about recursive functions. So there is no
need to explain recursion again.
We will be traversing and at the same time displaying the information of a sorted
binary tree. We know that in a sorted binary tree, the smallest data is stored in
the leftmost node of the tree. So we will start displaying the data from the
leftmost node.
Lets understand this with the help of an example. Say, the binary tree is
somewhat like this:
Root
100
110

I005

120

left

Data

right

110

120

NULL

I003

NULL

NULL

I009

NULL

left

Data

right

left

Data

right

So the task before us is to display the items of this tree. The data should be
shown like this:
I003

I005

YM/SR/CPRG2/1.0

I009

74

Programming in C Part II
Now the question is how to achieve this?
show(struct bill *ptr)
{
if(!ptr)
{
return;
}
show(ptr->left);
printf("%s\t
",ptr->itemno);
printf("%s\t
",ptr->itemdesc);
printf("%f\t
",ptr->rate);
printf("%d\t\n
",ptr->qty);
show(ptr->right);
}
From above code snippet, you can find that the function is recursive in nature.
The pointer ptr passed to this function initially contains the address of the root.
The first instruction is:
show(ptr->left);
This is an instruction to traverse the left subtree of the root. This will continue
until and unless it meets a NULL pointer. So in our example, the traversal starts
from the node containing the data I005. Then it traverses the left subtree. Now
ptr points to the node with data I003. After that it traverses left and encounters a
NULL value, since it is not having any subtree, and I003 is displayed. After this it
encounters the statement:
show(ptr->right);
Therefore it traverses to the right subtree. Since the pointer ptr is pointing to the
node with data I003, so on traversing right, it encounters a NULL pointer.
Therefore, it returns. Since the traversal of both the left and the right subtree is
complete, with ptr pointing to the node containing the data I003, it now returns to
the node containing the data I005.
The traversal is not yet complete. It will first print I005. Then it will traverse the
right subtree. ptr will now point to the node containing the data I009. Again it will
move to the left subtree. Once again the same sequence will be followed as
discussed earlier. And it will print I009.
So the complete code will be like this:
#include <stdio.h>
#include<malloc.h>
struct bill
{
char itemno[5];

YM/SR/CPRG2/1.0

75

Programming in C Part II
char itemdesc[30];
float rate;
int qty;
struct bill *left;
struct bill *right;
};
char c;
struct bill *root;
main()
{
char choice;
choice='x';
while((choice!='q')&&(choice!='E'))
{
system("tput clear");
printf("\n\n I. Insert into the Binary tree");
printf("\n D. Display the Binary tree");
printf("\n Q. Quit");
printf("\n Enter your choice :\t");
choice=getchar();
fflush(stdin);
if((choice=='I')||(choice=='i'))
{
add();
}
if((choice=='D')||(choice=='d'))
{
display();
}
if((choice=='Q')||(choice=='q'))
{
exit();
}
}
}
add()
{
struct bill *createnode(),*new,*prev1,*find();
new=createnode();
if(root==NULL)
{
root=new;
}
else
{
prev1=find(new);
if(prev1!=NULL)
{
if((strcmp(new->itemno,prev1->itemno))>0)
{

YM/SR/CPRG2/1.0

76

Programming in C Part II
prev1->right=new;
}
else
{
prev1->left=new;
}
}
else
{
printf("\nThe Item code already exists\n");
}
}
}
display()
{
struct bill *ptr;
ptr=root;
show(ptr);
}

struct bill *createnode()


{
struct bill *new1;
new1=(struct bill*)malloc(sizeof(struct bill));
printf("\n Enter :");
printf("\n\t Item No:\t");
scanf("%s",new1->itemno);
fflush(stdin);
printf("\n\tDescription:\t");
scanf("%s",new1->itemdesc);
fflush(stdin);
printf("\n\t Rate:\t");
scanf("%f",&new1->rate);
fflush(stdin);
printf("\n\t Quantity:\t");
scanf("%d",&new1->qty);
return(new1);
}
struct bill *find(struct bill *neo)
{
struct bill *ptr,*prev;
ptr=root;
while(ptr)
{
if((strcmp(neo->itemno,ptr->itemno))>0)
{
prev=ptr;
ptr=ptr->right;
}

YM/SR/CPRG2/1.0

77

Programming in C Part II
else
{
if((strcmp(neo->itemno,ptr->itemno))<0)
{
prev=ptr;
ptr=ptr->left;
}
else
{
prev=NULL;
ptr=NULL;
}
}
}
return prev;
}
show(struct bill *ptr)
{
if(!ptr)
{
return;
}
show(ptr->left);
printf("%s\t
",ptr->itemno);
printf("%s\t
",ptr->itemdesc);
printf("%f\t
",ptr->rate);
printf("%d\t\n
",ptr->qty);
show(ptr->right);
}

YM/SR/CPRG2/1.0

78

Programming in C Part II

Deletion of a Node from Binary tree


Deletion of a node in binary tree is very similar to
deletion in doubly linked list.
Deletion from binary tree has several scenarios
Deletion of a terminal node, which has no
subtrees
Deletion of a node, which has only one subtree
Deletion of a node, which has both subtrees.
The root node is being deleted.

Deletion of a Node from Binary tree


The deletion of a node from a binary tree is not very different from the deletion of
a node from the doubly linked list. It is all a game of pointer manipulation. Since
the organizing of the data is different in case of binary tree as compared to
doubly linked list, there will be certain changes in pointer manipulation.
Let's try to understand it with the help of an example.

I010
I002
I001

I003
I005

I004

I007

I006

I009

Consider the binary tree depicted in the diagram above. Whenever we are
deleting any node from the above tree, we have to link the left and the right
subtree accordingly. Otherwise, all the information will be lost.
Depending upon the position of the node that we are deleting there can be
several situations of deletion.
Situation 1: Deletion of a terminal node, which has no subtrees, e.g. I009

YM/SR/CPRG2/1.0

79

Programming in C Part II
Since, I009 is the terminal node on right side, therefore the right pointer of its
parent node (i.e. I007) has to be initialized to NULL.
If the terminal node happens to be the left node, then the left pointer should be
initialized to NULL.
Situation 2: Deletion of a node, which has only one subtree, e.g. I005
In this situation depending upon the position of the node i.e. left or right, the left
or the right pointer of the parent node of the deleted one should point to the
left/right subtree of the deleted node.

I010
I002

I003

I001

I007

I005

I006

I009

Situation 3: Deletion of a node, which has both subtrees, e.g. I002

I010
I002

I003

I001

I007

I002

I009

In this situation both the left and the right pointers of the parent node of the
deleted node has to be linked to the subtrees of the node being deleted.

YM/SR/CPRG2/1.0

80

Programming in C Part II
Situation 4: The root node is being deleted.
It is very similar to other cases of deletion. The only difference is that the root
pointer has to be updated.
Once we have seen the different situations now lets look at a function
implementing them:
void del()
{
char rep='y';
char mempno[5];
if(root==NULL)
return;
while(rep=='y')
{
printf("\nEnter Empno to delete :");
scanf("%s",mempno);
fflush(stdin);
ptr=root;
pptr=search1(ptr,mempno);
if(pptr!=NULL)
{
root=delet(ptr,mempno);
}
else
{
printf("\nNo such Node");
}
printf("\nWish to
continue:");scanf("%c",&rep);fflush(stdin);
}
}
struct tree *delet(struct tree *ptr,char *mempno)
{
struct tree *p1,*p2;
if(strcmp(ptr->tempno,mempno)==0)
{
printf("\nNode Found");getchar();
if (ptr->left==ptr->right)
{
free(ptr);
return NULL;
}
else if(ptr->left!=NULL && ptr->right==NULL)
{
p1=ptr->left;
free(ptr);
return p1;
}
else if(ptr->left==NULL && ptr->right !=NULL)

YM/SR/CPRG2/1.0

81

Programming in C Part II
{
p1=ptr->right;
free(ptr);
return p1;
}
else if(ptr->left!=NULL && ptr->right!=NULL)
{
p1=ptr->right;
p2=ptr->right;
while(p1->left)
{
p1=p1->left;
}
p1->left=ptr->left;
free(ptr);
return p2;
}
}
else if(strcmp(mempno,ptr->tempno)>0)
{
printf("\nMove right");getchar();
ptr->right=delet(ptr->right,mempno);
}
else if(strcmp(mempno,ptr->tempno)<0)
{
printf("\nMove left");getchar();
ptr->left=delet(ptr->left,mempno);
}
return ptr;
}
struct tree *search1(struct tree *ptr,char *mempno)
{
while(ptr)
{
if (strcmp(ptr->tempno,mempno)==0)
{
break;
}
else if (strcmp(mempno,ptr->tempno)>0)
{
ptr=ptr->right;
}
else
{
ptr=ptr->left;
}
}
return ptr;
}

YM/SR/CPRG2/1.0

82

Programming in C Part II

Quiz

What is the difference between binary tree and


doubly linked list?
What is the difference between a balanced and
unbalanced tree?
What are the cases you have to resolve while
deleting a node from a binary tree

Quiz

YM/SR/CPRG2/1.0

83

Programming in C Part II

Summary
After the completion of this chapter now, you will be
able to:

Appreciate Stacks in C
Represent Stacks in C
Use push() and the pop() functions
Appreciate queue in C
Use structures in C to represent queue
Insert and delete in queue
Appreciate the concept of Binary trees
Implement Binary trees with structures in C
Insert node in binary tree
Traverse a binary tree
Delete a node from a binary tree

Summary
After the completion of this chapter, you will now be able to:
Appreciate Stacks in C
Represent Stacks in C
Use push() and the pop() functions
Appreciate queue in C
Use structures in C to represent queue
Insert and delete in queue
Appreciate the concept of Binary trees
Implement Binary trees with structures in C
Insert node in binary tree
Traverse a binary tree
Delete a node from a binary tree

YM/SR/CPRG2/1.0

84

Programming in C Part II
Enhanced searching -Indexing &
Hashing using Data structure
At the end of this chapter, you will be able to:

Appreciate different Search Methods


Appreciate Indexed Sequential Searching
Use data structures to represent an Index
Create an Index for a Data file
Appreciate Hashing
Write Hashing functions
Appreciate different Hashing Techniques
Use Hash Indexes
Use Hash Tables
Resolve Collisions
Solve an Example

Enhanced searching Indexing & Hashing


using Data structure
At the end of this chapter, you will be able to:
Appreciate different Search Methods
Appreciate Indexed Sequential Searching
Use data structures to represent an Index
Create an Index for a Data file
Appreciate Hashing
Write Hashing functions
Appreciate different Hashing Techniques
Use Hash Indexes
Use Hash Tables
Resolve Collisions
Solve an Example

YM/SR/CPRG2/1.0

85

Programming in C Part II

Search Methods
This search algorithm will again depend
upon different access methodologies.
Sequential access
Random access
Indexed access

Search Methods
When we started learning data structure, we had mentioned that its all about
managing huge amount of data. When we talk about management of data, we
mean adding new data, modifying, and deleting existing data and to answer adhoc queries, efficiently.
Answering ad-hoc queries means searching for a particular piece of information
from huge amount of data. While doing so we have to keep in mind the efficiency
in terms of search time.
In this chapter we will be learning certain techniques of storage and retrieval of
data that makes the process of searching much more efficient.
Storage or retrieval of data is made from different external storage media. While
searching, we have to access the data from these external storage media. In this
chapter we will be trying to understand the different techniques for accessing
data and its implementation in C.
Different Search techniques
When data is stored on the disk, generally it is organized into files or tables.
Files or tables are made up of records. For example, if you are storing
information about employees, probably you will be keeping it under a file/table
called Employee. This file/table will contain information about several employees.
The information will be stored under certain fields, like Employee Code, Name,
Designation, Department, Basic, etc. All the information about a particular
Employee, for example Samuel, is called a record
There is always a chance that two or more employee has all the information
same. If that is the condition how can we identify an employee uniquely?

YM/SR/CPRG2/1.0

86

Programming in C Part II
We will identify an employee uniquely with the help of Employee Code, which
cannot be same for two employees, under any circumstances. Any filed that
uniquely identifies a record is called a key field.
This key fields play a major role in searching or accessing for a particular record
from the file/table.
Now we have to devise certain search algorithms to find a piece of information.
A search algorithm accepts the key value, finds and retrieves the record
matching that key.
This search algorithm will depend upon different access methodologies. There
are several access methodologies but we will be concentrating on three popular
access methodologies:
Sequential access
Random access
Indexed access
Sequential Access
To find a particular information, with the help of sequential access method, we
have to start from the beginning of a file and traverse through all the records,
until we find the desired record. It is very similar to listening to songs from a tape
cassette. You have to traverse through the first four songs, before being able to
listen to the fifth one.
Although this is a very simple technique, but by no means an efficient one. Think
about an organization that has 10,000 employees. The probability of finding
information about a particular employee is 1 in 10,000.
Random Access
To eradicate the inefficiency of sequential access method, and to reduce the
search time, random access methodology has been devised. The name itself
suggests that we can pick up any relevant record from a file randomly, without
traversing through all the records preceding it.
This is possible only if all the records are of fixed length. In such a case, you
just have to find the relative position of the record being searched and then
retrieve it in a single operation.
It is similar to listening to music from a CD. If you want to listen to the fifth track,
you can do so immediately, without traversing through all the preceding tracks.
But this access methodology has one limitation. You can not search a record with
the help of the key value. For that you have to calculate the offset value from the
record number. Then you can access a particular record using that offset value.

YM/SR/CPRG2/1.0

87

Programming in C Part II
For example, the record length of employee is 300 bytes, then the 3rd record will
be found at
(3-1)*300=600 bytes relative to the beginning of the file.
The general formula is:
Offset value = ( record_number - 1 ) * record_length

YM/SR/CPRG2/1.0

88

Programming in C Part II

Indexed Searching
To search a particular record randomly but with
the help of key values Index files are used.
In the index file key-offset pair is stored
Searching a particular record with the help of
index file is termed as Indexed Searching.

Indexed Searching
In the previous topic, we have learnt that random access is very fast. We have
also seen one limitation of it, i.e. it cannot search any record with a key value.
Instead, it has to do so with the help of the offset value.
Again, reconsider the case of the organization with 10,000 employees. Do you
think it possible (or feasible) to remember the offset value of a record of a
particular employee? In fact, it is next to impossible.
In such cases, probably we would like to access the record with the help of the
Employee Code.
The probable solution is to search for a particular record randomly, but with the
help of a key value.
This can be achieved if we store the key values along with its offset some where
in the disk. We can store this in another table or a file like this:

Key field
E0001
E0002
E0003
E0004

Offset
0
300
600
800

This table or file is termed as Index. To search for a particular record with the
help of a key value, first we have to refer this table, find the matching offset value
for that key, and then retrieve the particular record. This Index file is also written
to the disk along with the data file.

YM/SR/CPRG2/1.0

89

Programming in C Part II
This type of accessing is termed as Indexed Searching.
Since we have to refer to two tables for accessing a particular record, it takes a
toll over the speed of execution of the query. It is a bit slower than random
access but is more convenient than it.

YM/SR/CPRG2/1.0

90

Programming in C Part II

Structure in C to represent an Index


Indexed files can be represented as
Arrays
Linked List
Binary tree
struct emp {char flag;
char empno[5];
char name[21];
int basic;
char grade;}e;
struct li {char key[5];
long off;
struct li *next;
}*start,*ptr,*pptr,*new;

Structure in C to represent an Index


In the previous topic, we have seen that searching for a particular record using
Index is a bit slower process. Therefore, when we have to select a data structure
to represent an index keeping in mind the aspect of the speed of access. So lets
discuss various data structures, suited for representing Indexes, and the pros
and cons of them.
The first data structure that we have learnt is array. Therefore, our first choice to
represent an index will be an array.
Index in the form of an array
An array used to represent an index has two parts. The first part contains the key
value of the record and the second part contains the offset position of this record
from the beginning of the file.
You know array manipulation already, therefore it will be redundant to explain it
here once again. Manipulation of array is very simple. This can be treated as one
the advantages of array as a structure to represent indexes.
On the other hand, it poses certain limitations:
You have to search for a particular key stored in the array, as index,
sequentially. This is quite time consuming.
You first have to sort the array, based on the key value, to search for a
record.
When a new row is inserted or an existing row is deleted, the corresponding
key has to be inserted or deleted accordingly, in the index file. To achieve this
task in an array is very cumbersome.

YM/SR/CPRG2/1.0

91

Programming in C Part II
Index in the form of Linked Lists
As we have seen that array representation of index has some serious problems,
therefore let us ponder on some other data structure to represent it.
Linked list can be one of the options. Using linked list to represent an index can
solve certain limitations posed by array representation of indexes. The key and
the offset value will comprise the data part of the node, in the linked list.
The problem of sorting an array is automatically eradicated in case of the linked
list, since we use sorted linked lists to store indexes. Apart from this, insertion
and deletion of items is very easy, as we have seen earlier. But the limitation of
sequential searching still exists.
Index in the form of Binary tree
The problem of searching the index file sequentially can be solved, if we use
Binary tree to represent an index. Search time decreases significantly with the
use of binary tree, used to represent an index.

YM/SR/CPRG2/1.0

92

Programming in C Part II

Structure in C to represent an Index


Indexed files can be represented as
Arrays
Linked List
Binary tree
struct emp {char flag;
char empno[5];
char name[21];
int basic;
char grade;}e;
struct li {char key[5];
long off;
struct li *next;
}*start,*ptr,*pptr,*new;

Create an Index for a Data file


Once we have learnt the concept of Index and the different data structures that
can be used to represent it, lets now look into its implementation in C.
In our discussion, we will be using Linked list to represent indexes, since it is
easy to manipulate it on one hand and efficient on the other.
The data to be stored in the linked list, i.e. the key values and the offset position
of each record comes from a file.
The structure to represent an index is as follows:
struct emp {
char flag;
char empno[5];
char name[21];
int basic;
char grade;
}e;
struct li {
char key[5];
long off;
struct li *next;
}*start,*ptr,*pptr,*new;
FILE *fp;

From the code snippet given above, you can see that we have declared a
structure, called emp, to store the employees data. We have also declared

YM/SR/CPRG2/1.0

93

Programming in C Part II
another structure, called li, to represent the node of the linked list, which will act
as an index. This structure contains the key and the offset value of the records.
Creation of the file
Next, we will be creating the data file, which will store the employees records.
This function will accept the details from the user and will write it to a file called
emp.dat.
void cf()
{
char rep='y';
fp=fopen("emp.dat","a");
while(rep=='y')
{
printf("\nEmpno :");
scanf("%s",e.empno);
fflush(stdin);
printf("\nEnter Name :");
scanf("%s",e.name);
fflush(stdin);
printf("\nBasic :");
scanf("%d",&e.basic);
fflush(stdin);
printf("\nEnter Grade :");
scanf("%c",&e.grade);fflush(stdin);
e.flag=' ';
fwrite(&e,sizeof(e),1,fp);
printf("\nWish to Continue :");
scanf("%c",&rep);
fflush(stdin);
}
fclose(fp);
}

Creating the index


void ci()
{
start=NULL;
fp=fopen("emp.dat","r");
fread(&e,sizeof(e),1,fp);
while(!(feof(fp)))
{
new=(struct li *)malloc(sizeof(struct li));
new->next=NULL;
strcpy(new->key,e.empno);
new->off=ftell(fp)-sizeof(e);
if (start==NULL)

YM/SR/CPRG2/1.0

94

Programming in C Part II
{
start=new;
}
else
{
for(ptr=start;(ptr)&&strcmp(new->key,ptr>key)>0;pptr=ptr,ptr=ptr->next);
if(ptr==start)
{
new->next=start;
start=new;
}
else if(ptr==NULL)
{
pptr->next=new;
}
else
{
new->next=ptr;
pptr->next=new;
}
}
fread(&e,sizeof(e),1,fp);
}
fclose(fp);
}
Consider the above code snippet. First of all, we are opening the file in read
mode. Then we are reading a record from it. After that, the loop is started, and it
iterates unless and until it encounters the end of file. Then we simply create a
new node and add it to the list. Before adding the node to the list, the key is
copied in the variable of the node and the offset value is taken and assigned to
the node.
strcpy(new->key,e.empno);
new->off=ftell(fp)-sizeof(e);

While adding the node, care should be taken that it is done in a sorted manner.
You have already learnt how to add a node in a sorted linked list.

YM/SR/CPRG2/1.0

95

Programming in C Part II
Accessing a record using index and modifying it
void modi()
{
char rep='y';
char mempno[5];
fp=fopen("emp.dat","r+");
if (fp==NULL)
return;
if(start==NULL)
return;
while(rep=='y')
{
printf("\nEnter Code to Modify :");
scanf("%s",mempno);fflush(stdin);
for(ptr=start;(ptr)&&strcmp(ptr->key,mempno)!=0;ptr=ptr->next);
if(ptr==NULL)
{
printf("No Such Empno");
}
else
{
fseek(fp,ptr->off,0);
fread(&e,sizeof(e),1,fp);
printf("\nEmpno :%s",e.empno);
printf("\nName %s",e.name);
scanf("%s",e.name);fflush(stdin);
printf("\nBasic :%d",e.basic);
scanf("%d",&e.basic);fflush(stdin);
printf("\nGrade :%c",e.grade);
scanf("%c",&e.grade);fflush(stdin);
fseek(fp,ptr->off,0);
fwrite(&e,sizeof(e),1,fp);
printf("\nRecord modified successfully");
}
printf("\nWish to continue :");
rep=getchar();
fflush(stdin);
}
fclose(fp);
}
Look at the above code snippet. We are first accepting the key to be searched
from the user. Then we are searching for the node having that particular key
value. Once that node is found, we are reading the offset value from it. Using that
offset value we search for the record, then display the existing record if found,
finally and ask for the new values. At the end, we write the new values onto the
disk.
Like wise we can create functions to write, delete, and display records.

YM/SR/CPRG2/1.0

96

Programming in C Part II
The consolidated code is as follows:
struct emp {
char flag;
char empno[5];
char name[21];
int basic;
char grade;
}e;
struct li {
char key[5];
long off;
struct li *next;
}*start,*ptr,*pptr,*new;
FILE *fp;
main()
{
int ch=0;
start=NULL;
while (ch < 8)
{
printf("\nMain Menu");
printf("\n\t1. Create File");
printf("\n\t2. Create Index");
printf("\n\t3. Display Data");
printf("\n\t4. Modify Data");
printf("\n\t5. Delete Data");
printf("\n\t6. Recall Data");
printf("\n\t7. Pack");
printf("\n\t8. Exit");
printf("\n\tEnter your choice:");
scanf("%d",&ch);fflush(stdin);
switch(ch)
{
case 1: cf();break;
case 2: ci();break;
case 3: disp();break;
case 4: modi();break;
case 5: del();break;
case 6: recall();break;
case 7: pack();break;
case 8: exit();
}
}
}
void cf()
{
char rep='y';
fp=fopen("emp.dat","w");
while(rep=='y')

YM/SR/CPRG2/1.0

97

Programming in C Part II
{
printf("\nEmpno :");
scanf("%s",e.empno);
fflush(stdin);
printf("\nEnter Name :");
scanf("%s",e.name);
fflush(stdin);
printf("\nBasic :");
scanf("%d",&e.basic);
fflush(stdin);
printf("\nEnter Grade :");
scanf("%c",&e.grade);fflush(stdin);
e.flag=' ';
fwrite(&e,sizeof(e),1,fp);
printf("\nWish to Continue :");
scanf("%c",&rep);
fflush(stdin);
}
fclose(fp);
}
void ci()
{
start=NULL;
fp=fopen("emp.dat","r");
fread(&e,sizeof(e),1,fp);
while(!(feof(fp)))
{
new=(struct li *)malloc(sizeof(struct li));
new->next=NULL;
strcpy(new->key,e.empno);
new->off=ftell(fp)-sizeof(e);
if (start==NULL)
{
start=new;
}
else
{
for(ptr=start;(ptr)&&strcmp(new->key,ptr->
key)>0;pptr=ptr,ptr=ptr->next);
if(ptr==start)
{
new->next=start;
start=new;
}
else if(ptr==NULL)
{
pptr->next=new;
}
else
{
new->next=ptr;
pptr->next=new;

YM/SR/CPRG2/1.0

98

Programming in C Part II
}
}
fread(&e,sizeof(e),1,fp);
}
fclose(fp);
}
void disp()
{
fp=fopen("emp.dat","r");
if (fp==NULL)
return;
if (start==NULL)
return;
for(ptr=start;(ptr);ptr=ptr->next)
{
fseek(fp,ptr->off,0);
fread(&e,sizeof(e),1,fp);
printf("\nFlag :%c",e.flag);
printf("\nEmp No: %s",e.empno);
printf("\nName :%s",e.name);
printf("\nBasic:%d",e.basic);
printf("\nGrade:%c",e.grade);
}
fclose(fp);
}
void modi()
{
char rep='y';
char mempno[5];
fp=fopen("emp.dat","r+");
if (fp==NULL)
return;
if(start==NULL)
return;
while(rep=='y')
{
printf("\nEnter Code to Modify :");
scanf("%s",mempno);fflush(stdin);
for(ptr=start;(ptr)&&strcmp(ptr->key
,mempno)!=0;ptr=ptr->next);
if(ptr==NULL)
{
printf("No Such Empno");
}
else
{
fseek(fp,ptr->off,0);
fread(&e,sizeof(e),1,fp);
printf("\nEmpno :%s",e.empno);
printf("\nName %s",e.name);
scanf("%s",e.name);fflush(stdin);
printf("\nBasic :%d",e.basic);

YM/SR/CPRG2/1.0

99

Programming in C Part II
scanf("%d",&e.basic);fflush(stdin);
printf("\nGrade :%c",e.grade);
scanf("%c",&e.grade);fflush(stdin);
fseek(fp,ptr->off,0);
fwrite(&e,sizeof(e),1,fp);
printf("\nRecord modified successfully");
}
printf("\nWish to continue :");
rep=getchar();
fflush(stdin);
}
fclose(fp);
}
void recall()
{
char rep='y';
char mempno[5];
fp=fopen("emp.dat","r+");
if (fp==NULL)
return;
if(start==NULL)
return;
while(rep=='y')
{
printf("\nEnter Code to Recall :");
scanf("%s",mempno);fflush(stdin);
for(ptr=start;(ptr)&&strcmp(ptr->
key,mempno)!=0;ptr=ptr->next);
if(ptr==NULL)
{
printf("No Such Empno");
}
else
{
fseek(fp,ptr->off,0);
fread(&e,sizeof(e),1,fp);
e.flag=' ';
fseek(fp,ptr->off,0);
fwrite(&e,sizeof(e),1,fp);
printf("\nRecord Recalled successfully");
}
printf("\nWish to continue :");
rep=getchar();
fflush(stdin);
}
fclose(fp);
}
void del()
{
char rep='y';
char mempno[5];
fp=fopen("emp.dat","r+");

YM/SR/CPRG2/1.0

100

Programming in C Part II
if (fp==NULL)
return;
if(start==NULL)
return;
while(rep=='y')
{
printf("\nEnter Code to Delete :");
scanf("%s",mempno);fflush(stdin);
for(ptr=start;(ptr)&&strcmp(ptr>key,mempno)!=0;ptr=ptr->next);
if(ptr==NULL)
{
printf("No Such Empno");
}
else
{
fseek(fp,ptr->off,0);
fread(&e,sizeof(e),1,fp);
e.flag='*';
fseek(fp,ptr->off,0);
fwrite(&e,sizeof(e),1,fp);
printf("\nRecord mark for deletion
successfully");
}
printf("\nWish to continue :");
rep=getchar();
fflush(stdin);
}
fclose(fp);
}
void pack()
{
FILE *fp1;
if(start==NULL)
return;
fp=fopen("emp.dat","r");
fp1=fopen("temp.dat","w");
for(ptr=start;(ptr);ptr=ptr->next)
{
fseek(fp,ptr->off,0);
fread(&e,sizeof(e),1,fp);
if(e.flag==' ')
{
fwrite(&e,sizeof(e),1,fp1);
}
}
fclose(fp);
fclose(fp1);
system("rm emp.dat");
system("mv temp.dat emp.dat");
ci();}

YM/SR/CPRG2/1.0

101

Programming in C Part II

Hashing
Hashing is a technique, which converts the key
field stored in data file to the offset thereby
allowing us to access a record in a single
operation.

Hashing
In the previous topic, we have discussed data retrieval using index. In indexed
access, we have to scan two files, i.e. the index file and the actual data file,
which is a disadvantage. Another disadvantage with indexed search is that, if the
numbers of records are very large, then you have to at least scan through the
keys, which decreases the efficiency of the data access.
This disadvantage can be removed if we can devise certain data organization
where there is no requirement of scanning through the records, and in a single
operation, we are able to access a record.
This is what the concept of hashing provides us.
Hashing is a technique, which converts the key field stored in data files, to
the offset thereby allowing us to access a record in a single operation.
With the help of this technique, data retrieval becomes much faster. However,
the question is:
HOW?
Let's try to answer this question with the help of an example. Say, we have a file
that stores the Employee Code, Name, and Address, of each employee. Each
record length is 34 bytes (say).
Employee Code (key)
100
101
102

YM/SR/CPRG2/1.0

Name
Roger Miller
Morris Longfellow
Andre King

Address
New York
Oklahoma
Massachusetts

102

Programming in C Part II
Given a key, we can find a particular record with the formula:
(Key-100)*Record Length 100 is subtracted from the key because the
employee code starts from100.
So to find the records of Employee with Employee code 102, the offset value will
be:
(102-100)*38=76 bytes.
Considering the above example, we can infer that certain methods can be
devised by which the offset can be calculated.
Although, in the above example we are assuming the key to be numeric, and
increasing by a value of 1, but in real life scenario it might not be so simple.
Generally, the keys are alphanumeric in nature. For example, employee code
may be E001, E002 etc.
But still in such cases, we can always devise a method to convert the key to an
offset value.
In short, we can say that to retrieve a record from a file, the offset value is
calculated by converting the key of the record. The advantage that we get out of
it is the elimination of searching, by accessing the records, with direct
addressing. This reduces the searching time considerably.
Now a million-dollar question is, How and where is this conversion taking
place?
This is done, with the help of a special function, called hashing function.

YM/SR/CPRG2/1.0

103

Programming in C Part II

Hashing
Hashing is a technique, which converts the key
field stored in data file to the offset thereby
allowing us to access a record in a single
operation.

Hashing Functions
We have to convert the key to an address, to access a particular record. This
conversion is achieved by an algorithm, called hashing function. A hashing
function establishes a relationship to convert a key value to provide a hash value.
This hash value is actually the address of the record. With the help of the hash
value, we can directly access a record in a file, with a single operation.
This conversion is also known as key to address transformation.
The hash value that is generated by a hashing function is the actual offset
address within the file, determined by the hashing techniques implemented. The
records are inserted using this hash value. While retrieving the record, the same
hash function is utilized to locate that particular record.
There are several commonly used hashing functions. We will be implementing
one of them to solve an example.

YM/SR/CPRG2/1.0

104

Programming in C Part II

Hashing Techniques
The two commonly used techniques
implemented are
Hash indexes
Hash tables

Hashing Techniques
In the previous session, we have discussed about hashing functions. These can
be used to convert the key into an address, where the record pertaining to that
key field can be located. There are various techniques of converting the key
values to an address of a record.
Even the most cryptic key value can be transformed into a tangible address
corresponding to the record.
The two most commonly used techniques to implement the same are:
Hash indexes
Hash tables

YM/SR/CPRG2/1.0

105

Programming in C Part II

Hash Indexes
In this technique of hashing, a hash index file is
created.
The index file contains the keys and the hash
value of the key that is calculated by the hashing
function
Two files are created in this technique
Data file
Indexfile

Hash Indexes
In this technique of hashing, we create a hash index file. The hash index file
contains the keys and the hash value of the key, which is calculated using the
hashing function. For each record in the data file the hash index file contains the
key and the offset value.
In this technique, two files are generated:
The data file which contain the records
A hash index file that contain the key-offset value
Employee code (key)
103
101
104
102

Name
Dick Hastings
Mathew Hastings
Norman snow
Julia Caesar

Offset
0
32
64
96

Data File

Employee Code (Key)


101
102
103
104

Offset
32
96
0
64
Hash Index file

YM/SR/CPRG2/1.0

106

Programming in C Part II
As you can see from the data in the data file are arranged randomly. The other
file, i.e. hash index file, stores the key and the offset, i.e. address of each record,
relative to the beginning of the file.
To search for a particular record, we have to provide the key value. By providing
the key, the offset value for that particular record is calculated. To calculate the
location of the key-offset pair (offset value) in the hash index file, a hashing
function is utilized. Then from the hash index table the offset part is picked up.
With the help of this offset, that particular record is retrieved.

YM/SR/CPRG2/1.0

107

Programming in C Part II

Hash Tables
In this technique only one file is used
to retrieve a particular piece
information called hash table.

Hash Tables
In hash indexes, for searching a particular record we have search using two files.
This is an overhead on the execution time. To eliminate this disadvantage
another technique can be used. The technique, which achieves this, is called
hash table. In this technique, only one file is used to retrieve a particular piece of
information.

Employee code (key)


103
101
104
102

Name
Dick Hastings
Mathew Hastings
Norman snow
Julia Caesar

Offset
0
32
64
96

A hash table

In this particular methodology, like hash index, we have to calculate the offset
value of a record based on the key. But in this case no separate table is created
like hash index file. Instead of that, a complete record is inserted into the data file
at a calculated position. After this the file is no longer called a data file. Instead, it
is termed a hash table.
Whatever may be the hashing technique (hash indexes or hash tables), there are
certain limitations.
What are the limitations and how can it be resolved will be the subject of our
discussion in the next session.

YM/SR/CPRG2/1.0

108

Programming in C Part II

Collisions
In certain situations where there is an attempt
made to store two keys along with record at the
same offset position is called collision.
Collision can be resolved by
rehashing
Chaining

Collisions
In hash indexes, as well as hash tables, we encounter certain serious problems.
Both this methodologies work fine if the hash value generated for the keys, in a
table, are unique. But consider a situation, where two keys have similarity in
them in terms of the same hash value. In such cases, the offset values, i.e. the
locations where both the keys and their corresponding records, will be the same.
This situation, where there is an attempt made to store two keys along with
record at the same offset position is called collision.
Lets try to understand collision with the help of an example.
Say the hashing function used is:
Hashvalue=key%8
Using the above defined hash function on the key values 16, 6, 20, 10, and 32,
the following situation arises:
Key
16
6
20
10
32

Hash values
0
6
4
2
0

From the above table you can find that two keys are occupying the same offset
value 0. This is a collision.
You might be thinking that this is a big problem with the hashing function. It is
true to some extent. But still, whatever may be the hashing function, collision
may take place. A better function can only minimize the number of collisions.

YM/SR/CPRG2/1.0

109

Programming in C Part II

Since we have established the fact that collision will occur, there must be certain
way to get rid of it.
There are several methods for resolving collisions. The most common methods
are:
Rehashing
As its name suggests, once there is a collision after hashing the keys, a
secondary hashing is done by another hash function. The second time hashing is
done on the hash values generated during the first hashing. This secondary
hashing is done by the rehash function.
Whenever there is a collision in the hash values of the keys during the first
hashing, rehashing will be done successively (using the same rehash function,
designed in a special way) until a unique hash value is generated for each key.
Chaining
Instead of using rehashing to resolve the collision, this method uses links to
remove it.
Two common types of chaining techniques used, are:
Coalesed Chaining
Separate Chaining
Coalesed Chaining: This technique has an advantage over rehashing. Once
there is a collision between two hash values, it can resolve the collision without
further repetition.
It divides storage area into two parts:
A prime hash area.
An Overflow area.
Lets try to understand this with the example of collision stated above.
Hashvalue=key%8
Using the above defined hash function on the key values 6,10,16,20 the following
situation arises:

YM/SR/CPRG2/1.0

110

Programming in C Part II

Key
16
6
24
20
28
10

Hash values
0
6
0
4
4
2

Lets now try to find how this can be solved using this technique.

Offset values
0
1
2
3
4

Key
16
-10
-20

8
9
10

24
28

Prime area
Data
------------------------------Overflow area
---------------------------

Link
8
NULL
NULL
NULL
9

NULL
NULL

The keys are picked one after another and translated into the offset address. The
first key value that is converted to a particular hash value is stored in the prime
area. After that if any other key has the same hash value, which might produce a
collision, it is placed in the overflow area.
A link is kept between all those keys, which have the same hash value. If no link
is there for a particular value a NULL is placed.
In this way using the prime area and overflow area collision is avoided.
Separate Chaining
In rehashing and coalesed chaining, we made an assumption. The assumption
made is that we know the fixed storage space in advance. But it poses certain
problems if the number of records become more than the available space. On the
other hand, if you allocate too much space, then that is sheer wastage of space.
To address this problem the separate chaining method is adopted. In this
method, we use array of header nodes. And each node stores the address of
another linked list. The linked list, to which the individual node points, is a list of
records whose hash values are the same.
When we have to retrieve a particular record, we provide the key value to a
hashing function, which converts it to give the subscript of the array of header
nodes. Then we search the list pointed by that element of the header node.

YM/SR/CPRG2/1.0

111

Programming in C Part II

A complete Example

A complete Example
We will be solving the same example, which we had done in the case of
indexing, the only difference is the implementation of a hashing function to
convert the key to a hash value (offset addres relative to the beginning of the
file). In this case we have not created any index. Other wise every thing else is
same.

#include<stdio.h>
struct emp {
char flag;
char empno[5];
char name[21];
int basic;
char grade;
}e;
struct li {
char key[5];
long off;
struct li *next;
}*start[10],*ptr,*pptr,*new;
FILE *fp;

void cf()
{
char rep='y';
fp=fopen("emp.dat","w");
while(rep=='y')
{

YM/SR/CPRG2/1.0

112

Programming in C Part II
printf("\nEmpno :");
scanf("%s",e.empno);
fflush(stdin);
printf("\nEnter Name :");
scanf("%s",e.name);
fflush(stdin);
printf("\nBasic :");
scanf("%d",&e.basic);
fflush(stdin);
printf("\nEnter Grade :");
scanf("%c",&e.grade);fflush(stdin);
e.flag=' ';
fwrite(&e,sizeof(e),1,fp);
printf("\nWish to Continue :");
scanf("%c",&rep);
fflush(stdin);
}
fclose(fp);
}
int hash(char *);
void ci()
{
int i=0;
int index=0;
for(i=0;i<10;i++)
{
start[i]=NULL;
}
fp=fopen("emp.dat","r");
fread(&e,sizeof(e),1,fp);
while(!(feof(fp)))
{
new=(struct li *)malloc(sizeof(struct li));
new->next=NULL;
strcpy(new->key,e.empno);
new->off=ftell(fp)-sizeof(e);
index=hash(new->key);
if (start[index]==NULL)
{
start[index]=new;
}
else
{
for(ptr=start[index];(ptr)&&strcmp(new->key,ptr>key)>0;pptr=ptr,ptr=ptr->next);
if(ptr==start[index])
{
new->next=start[index];
start[index]=new;
}
else if(ptr==NULL)

YM/SR/CPRG2/1.0

113

Programming in C Part II
{
pptr->next=new;
}
else
{
new->next=ptr;
pptr->next=new;
}
}
fread(&e,sizeof(e),1,fp);
}
fclose(fp);
}
int hash(char *mempno)
{
int tot=0;
while(*mempno!='\0')
{
tot=tot + *mempno;
mempno++;
}
return tot % 10;
}
void disp()
{
int ctr=0;
fp=fopen("emp.dat","r");
if (fp==NULL)
return;
for(ctr=0;ctr<10;ctr++)
{
for(ptr=start[ctr];(ptr);ptr=ptr->next)
{
fseek(fp,ptr->off,0);
fread(&e,sizeof(e),1,fp);
printf("\nFlag :%c",e.flag);
printf("\nEmp No: %s",e.empno);
printf("\nName :%s",e.name);
printf("\nBasic:%d",e.basic);
printf("\nGrade:%c",e.grade);
}
}
fclose(fp);
}
void modi()
{
char rep='y';
char mempno[5];
int ctr=0;
fp=fopen("emp.dat","r+");

YM/SR/CPRG2/1.0

114

Programming in C Part II
if (fp==NULL)
return;
while(rep=='y')
{
printf("\nEnter Code to Modify :");
scanf("%s",mempno);fflush(stdin);
ctr=hash(mempno);
for(ptr=start[ctr];(ptr)&&strcmp(ptr>key,mempno)!=0;ptr=ptr->next);
if(ptr==NULL)
{
printf("No Such Empno");
}
else
{
fseek(fp,ptr->off,0);
fread(&e,sizeof(e),1,fp);
printf("\nEmpno :%s",e.empno);
printf("\nName %s",e.name);
scanf("%s",e.name);fflush(stdin);
printf("\nBasic :%d",e.basic);
scanf("%d",&e.basic);fflush(stdin);
printf("\nGrade :%c",e.grade);
scanf("%c",&e.grade);fflush(stdin);
fseek(fp,ptr->off,0);
fwrite(&e,sizeof(e),1,fp);
printf("\nRecord modified successfully");
}
printf("\nWish to continue :");
rep=getchar();
fflush(stdin);
}
fclose(fp);
}
void del()
{
char rep='y';
char mempno[5];
int ctr=0;
fp=fopen("emp.dat","r+");
if (fp==NULL)
return;
while(rep=='y')
{
printf("\nEnter Code to Delete :");
scanf("%s",mempno);fflush(stdin);
ctr=hash(mempno);
for(ptr=start[ctr];(ptr)&&strcmp(ptr->
key,mempno)!=0;ptr=ptr->next);
if(ptr==NULL)
{
printf("No Such Empno");

YM/SR/CPRG2/1.0

115

Programming in C Part II
}
else
{
fseek(fp,ptr->off,0);
fread(&e,sizeof(e),1,fp);
e.flag='*';
fseek(fp,ptr->off,0);
fwrite(&e,sizeof(e),1,fp);
printf("\nRecord mark for deletion
successfully");
}
printf("\nWish to continue :");
rep=getchar();
fflush(stdin);
}
fclose(fp);
}
void recall()
{
char rep='y';
int ctr=0;
char mempno[5];
fp=fopen("emp.dat","r+");
if (fp==NULL)
return;
while(rep=='y')
{
printf("\nEnter Code to Recall :");
scanf("%s",mempno);fflush(stdin);
ctr=hash(mempno);
for(ptr=start[ctr];(ptr)&&strcmp(ptr->
key,mempno)!=0;ptr=ptr->next);
if(ptr==NULL)
{
printf("No Such Empno");
}
else
{
fseek(fp,ptr->off,0);
fread(&e,sizeof(e),1,fp);
e.flag=' ';
fseek(fp,ptr->off,0);
fwrite(&e,sizeof(e),1,fp);
printf("\nRecord Recalled successfully");
}
printf("\nWish to continue :");
rep=getchar();
fflush(stdin);
}
fclose(fp);
}

YM/SR/CPRG2/1.0

116

Programming in C Part II
void sdisp()
{
int ctr=0;
char rep='y';
char mempno[5];
fp=fopen("emp.dat","r");
if (fp==NULL)
return;
while(rep=='y')
{
printf("\nEnter the Empno to display:");
scanf("%s",mempno);fflush(stdin);
ctr=hash(mempno);
for(ptr=start[ctr];(ptr)&&strcmp(ptr>key,mempno)!=0;ptr=ptr->next);
if(ptr==NULL)
{
printf("\nNo such Emp. No");
}
else
{
fseek(fp,ptr->off,0);
fread(&e,sizeof(e),1,fp);
printf("\nFlag :%c",e.flag);
printf("\nEmp No: %s",e.empno);
printf("\nName :%s",e.name);
printf("\nBasic:%d",e.basic);
printf("\nGrade:%c",e.grade);
}
printf("\nWish to Continue :");
rep=getchar();fflush(stdin);
}
fclose(fp);
}
void pack()
{
FILE *fp1;
int ctr=0;
fp=fopen("emp.dat","r");
fp1=fopen("temp.dat","w");
for(ctr=0;ctr<10;ctr++)
{
for(ptr=start[ctr];(ptr);ptr=ptr->next)
{
fseek(fp,ptr->off,0);
fread(&e,sizeof(e),1,fp);
if(e.flag==' ')
{
fwrite(&e,sizeof(e),1,fp1);
}
}
}

YM/SR/CPRG2/1.0

117

Programming in C Part II
fclose(fp);
fclose(fp1);
system("rm emp.dat");
system("mv temp.dat emp.dat");
ci();
}
main()
{
int ch=0;
while (ch < 9)
{
printf("\nMain Menu");
printf("\n\t1. Create File");
printf("\n\t2. Create Hash Index");
printf("\n\t3. Display Data");
printf("\n\t4. Display Select Data");
printf("\n\t5. Modify Data");
printf("\n\t6. Delete Data");
printf("\n\t7. Recall Data");
printf("\n\t8. Pack");
printf("\n\t9. Exit");
printf("\n\tEnter your choice:");
scanf("%d",&ch);fflush(stdin);
switch(ch)
{
case 1: cf();break;
case 2: ci();break;
case 3: disp();break;
case 4: sdisp();break;
case 5: modi();break;
case 6: del();break;
case 7: recall();break;
case 8: pack();break;
case 9: exit();
}
}
}

YM/SR/CPRG2/1.0

118

Programming in C Part II

Quiz
What is indexing?
How many tables are created during indexing?
How many tables are created in the hashing
technique?
What are collisions?
What are the different methods for resolving
collision ?

Quiz

YM/SR/CPRG2/1.0

119

Programming in C Part II

Summary
At the end of this chapter, now you are able to:

Appreciate different Search Methods


Appreciate Indexed Sequential Searching
Use data structures to represent an Index
Create an Index for a Data file
Appreciate Hashing
Write Hashing functions
Appreciate different Hashing Techniques
Use Hash Indexes
Use Hash Tables
Resolve Collisions
Solve an Example

Summary
At the end of this chapter, you are now able to:
Appreciate different Search Methods
Appreciate Indexed Sequential Searching
Use data structures to represent an Index
Create an Index for a Data file
Appreciate Hashing
Write Hashing functions
Appreciate different Hashing Techniques
Use Hash Indexes
Use Hash Tables
Resolve Collisions
Solve an Example

YM/SR/CPRG2/1.0

120

Programming in C Part II

C Library
At the end of the chapter, you will be able to:
Appreciate the need to software
Create and maintenance of software library
Use Library

C Library
At the end of the chapter, you will be able to:
Appreciate the need of software library
Create and maintain software library
Use Library

YM/SR/CPRG2/1.0

121

Programming in C Part II

Need of software library


A collection of functions is known as library.
Almost all compiler-based languages including C,
C++ etc provides standard library that contains
rich set of functions used by programs.
Software library enhances the reusability of code.

Need of software library


A software library is defined as a collection of functions. The ANSI/ISO standard
for C has defined a set of functions stored in standard C library. This library,
which contains a set of C functions, is supported by all standard compilers.
Besides, each compiler is free to supply its own additional functions to the
clients.
Almost all compiler-based languages, including C, C++, etc., provide standard
library that contains rich set of functions used by programs, written in the
language. While writing C programs, we have used the standard C library, i.e.
stdio.h. The main advantage of using a software library is that it saves time and
effort in rewriting important functions time and again.
The basic function of software library is that it allows reusability of codes. Each
time a function is redeveloped, it involves a lot of coding, testing and debugging,
which in turn consumes a lot of time.
Secondly, in real-life development scenario, a lot of manpower is put into a
particular project. So when a function is developed and put inside a library, it not
only benefits the concerned developer, but also allows other team members to
use those functions.
Thirdly, if a function is written in several files and all of a sudden, we feel the
need to modify its code, then all the respective files, containing the function, has
to be changed. Overlooking a single file will lead to inconsistency. On the other
hand, we can store all the useful functions in a common place (library), so the
maintenance of code becomes easier. This approach also saves disk space.

YM/SR/CPRG2/1.0

122

Programming in C Part II

Creation and maintenance of software


library
Different Libraries offered by C compilers are:
Standard C Library
Graphics Library
Maths Library
C Libraries can be created with ar command available in unix
and Linux.
The syntax is:
ar -[option] [Library Name] [list of files
with the extension .o]

Creation and maintenance of software library


In our previous discussion, we have established the need of software library.
Software libraries can be of several types. Already while developing our program
we have used several library functions like printf(), scanf() which are included in
the standard C library file, called stdio.h. These library functions are not written
by the application programmer, but comes in-built with the compiler. The different
libraries provided along with the C compiler are:
1. Standard C Library
2. Graphics Library
3. Maths Library
Apart from the libraries already provided by the compiler, users can also create
their own library functions. These types of libraries are created by the user mainly
for the automation of a big and complex process. For example, think of the
automation of a Financial Accounting process.
The sub processes may be:
+
+
+
+
+

Data Entry in Journal


Posting the entry from the Journal to specific ledgers
Preparation of the general ledger
Preparation of P/L
Preparation of Balance sheet

To automate this financial accounting process, you will require several sub
processes to be automated. It is impossible for a single person to complete the
entire job, in time. Therefore, many individuals or group will be assigned the job.
They will write their portion of the code, compile it, and make libraries. Then all
the library functions will be integrated via a single function.

YM/SR/CPRG2/1.0

123

Programming in C Part II
From the above discussion, one fact is established that Libraries are a group of
functions. That means we have to develop individual functions to make libraries.
While developing individual functions, which are to be integrated, we have to
keep certain points in our mind:
+ The function should do only one particular task. Ideally the function should
not do more than one logical job.
+ The variables declared in the functions should be private.
+ Every function should have a return value, so that the caller function can
receive it.
+ Functions should be independent in handling exceptions, which might occur
during the execution of the program.
Once we have written the individual functions, adhering to the above guidelines,
we can venture to create our own Libraries i.e. User Libraries.
How can we create a user library?
To create Library functions, most of the C compilers provide us special utility
called library manager. A group of programs, which allow the user to maintain
and manipulate library, is called library manager.
Maintenance and manipulation of library means creating a new library, adding
new functions to a library, deleting existing functions from the library, and change
functions in the library.
Creation of a new library
There are various Library managers, which comes bundled with different
compilers of C. We will be discussing about a library manager, available under
the Unix operating system called ar. ar is an archive and library maintainer for
portable archives. The ar command combines groups of files into a single archive
file. The primary purpose for which it's used is to create and update linker library
files.
Let us now create a library of functions.
Consider certain files, containing string-related functions, like le.c, search.c
We will create a library with the following functions. To do so we have to do the
following tasks:
Compile all the programs with the -c option:
cc -c list_ of_ program_file

The list of the program file names should be separated by spaces.


The -c option is to instruct the compiler, that the linking stage should be
suppressed and no executables created.

YM/SR/CPRG2/1.0

124

Programming in C Part II
Therefore, in our discussion we will compile it in this fashion:

When you issue this command the two files generated are as follows:
le.o
search.o
Now we can create a library out of these functions in the form of object file, with
the help of ar command. ar is available both in Unix and Linux.
The syntax of ar command is as follows:
ar -[option] [Library Name] [list of files with the
extension .o]
In the above syntax:
Option- is list of options that has to be provided while creating, adding, deleting,
or modifying the Library. These will be explained as we advance through the
course.
While giving the library its name, we have to follow certain rules followed by ar:
The library name should be prefixed by lib. Then it can contain any other name.
The extension has to be .a
For example:
ar -r

libmylibrary.a

le.o search.o

The -r option is used to add and update library functions. It does the following
jobs:
It creates the library (if the specified library name does not exist). It will also add
the specified object files to the library. If the Library does exist, it will only add the
object files to the library, only if it does not exist.

YM/SR/CPRG2/1.0

125

Programming in C Part II
Delete a function (in the form of object file) from the library
To delete an object function from an existing library, the command used is:
ar

-d [libraryname] [object file name]

For example, if you want to delete search.o from the library, the command will
be:
ar -d libmylibrary.a search.o

YM/SR/CPRG2/1.0

126

Programming in C Part II

Using the Library


To use the functions available in a library, we have to
create a program, which will integrate the functions
available in the library.
The syntax:
cc -o first first.c -L /usr/user1 -l mylibrary

The other options are:


-o to specify the name of the executable file name. Here it is first.
first.c is the name of the program file.
-L is to specify the path of the library file.
-l is to specify the name of the library file.

Using the Library


To use the functions available in a library, we have to create a program, which
will integrate the functions available in the library.
In our example, we have two functions search and le. To integrate them we have
to write a main function in a file, say first.c. From the main function, we will call
the functions. Then we will compile the first.c and make an executable file. The
command to compile the code is:
cc -o first first.c -L /usr/user1 -l mylibrary

Now, lets try to understand the command. Already you know, that cc is to
compile any C program. The other options are:
1.
2.
3.
4.

-o to specify the executable file name (to be created). Here it is first.


first.c is the name of the program file.
-L is to specify the path of the library file.
-l is to specify the name of the library file. The library file that we have created
is named as libmylibrary.a . But with -l option you dont have to provide the
prefix lib and the extension .a.

YM/SR/CPRG2/1.0

127

Programming in C Part II

Quiz

What is library function?


List certain standard Library function provided by C
what is the purpose of the ar utility?
What is the significance of -r option in ar utility?

What is the significance of -d option in ar utility?


What do we signify with -L option of the ar utility?
What do we signify with -l option of the ar utility?
What are the guidelines to be followed to create a library
function?

Quiz

YM/SR/CPRG2/1.0

128

Programming in C Part II

Summary
After this chapter, you are now able to:
Appreciate the need to software
Create and maintenance of software library
Use Library

Summary
After this chapter, you are now able to:
Appreciate the need of software library
Create and maintain software library
Use Library

YM/SR/CPRG2/1.0

129

Das könnte Ihnen auch gefallen