You are on page 1of 24

Data Structure lab manual

Experiment No. 1

Aim : To implement Singly Linked List.


Theory : Linked lists are a way to store data with structures so that the programmer can
automatically create a new place to store data whenever necessary. Specifically, the programmer
writes a struct definition that contains variables holding information about something and that
has a pointer to a struct of its same type (it has to be a pointer--otherwise, every time an element
was created, it would create a new element, infinitely). Each of these individual structs or classes
in the list is commonly known as a node or element of the list. One way to visualize a linked list
is as though it were a train. The programmer always stores the first node of the list in a pointer he
won't lose access to. This would be the engine of the train. The pointer itself is the connector
between cars of the train. Every time the train adds a car, it uses the connectors to add a new car.
This is like a programmer using malloc to create a pointer to a new struct.
One way to visualize a linked list is as though it were a train. The programmer always stores the
first node of the list in a pointer he won't lose access to. This would be the engine of the train.
The pointer itself is the connector between cars of the train. Every time the train adds a car, it
uses the connectors to add a new car. This is like a programmer using malloc to create a pointer
to a new struct.

Program :
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct info
{
char name[30];
int eno;
struct info *next;
};
struct info *head=NULL,*temp,*disp;
void addrecord();
void deleterecord();
void disrecord();
void main()
{
int ch;
clrscr();
while (1)
{

1
Data Structure lab manual

printf("\n 1. To add records\n");


printf("\n 2. To delete a records\n");
printf("\n 3. To view the records\n");
printf("\n 4. To exit\n");
printf("\n Enter your choice\n");
scanf("%d",&ch);
fflush(stdin);
switch(ch)
{
case 1:addrecord();
break;
case 2:deleterecord();
break;
case 3: disrecord();
break;
case 4:exit(0);
}
}
}
void addrecord()
{
struct info *add;
char ans='y';
while (ans=='y')
{
add=(struct info*)malloc(sizeof(struct info));
printf("\n Enter the names:\n");
gets(add->name);
fflush(stdin);
printf("\n Enter the enrollment number:\n");
scanf("%d",&add->eno);
fflush(stdin);
if (head==NULL)
{
head=add;
add->next=NULL;
temp=add;
}
else
{
temp->next=add;
add->next=NULL;
temp=add;

2
Data Structure lab manual

}
printf("\n Would you like to enter another name(y\\n): \n");
ans = getchar();
fflush(stdin);
}
} void deleterecord()
{
struct info *delete;
int teno, present=0;
if (head==NULL)
{
printf("\n No records to delete\n");
return;
}
printf("\n Enter the enrollment number to be deleted \n");
scanf("%d",&teno);
fflush(stdin);
for (delete=head;delete!=NULL;delete=delete->next)
{
if (delete->eno==teno)
{
if (head->eno==teno)
{
delete=head;
head=head->next;
free(delete);
return;
}
else
{
temp->next=delete->next;
free(delete);
return;
}
}
temp=delete;
}
if (present==0)
printf("\nNo such enrollment number present\n");
}
void disrecord()
{
if (head==NULL)

3
Data Structure lab manual

{
printf("\n No records to view\n");
return;
}
for (disp=head;disp!=NULL;disp=disp->next)
{
printf("\n\n Name : %s",disp->name);
printf("\n\n Number : %d",disp->eno);
}
}

Conclusion : Thus we have implemented Singly Linked List.

4
Data Structure lab manual

Experiment No.2

Aim : To implement Doubly Linked List.


Theory : Doubly-linked list is a more sophisticated form of linked list data structure. Each node
of the list contain two references (or links) – one to the previous node and other to the next node.
The previous link of the first node and the next link of the last node points to NULL. In
comparison to singly-linked list, doubly-linked list requires handling of more pointers but less
information is required as one can use the previous links to observe the preceding element. It has
a dynamic size, which can be determined only at run time.
The advantage of a doubly linked list is that we don’t need to keep track of the previous node for
traversal or no need of traversing the whole list for finding the previous node.

The disadvantage is that more pointers needs to be handled and more links need to updated.

Program :

#include<stdio.h>
#include<stdlib.h>
typedef struct Node
{
int data;
struct Node *next;
struct Node *prev;
}node;
void insert(node *pointer, int data)
{
/* Iterate through the list till we encounter the last node.*/
while(pointer->next!=NULL)
{
pointer = pointer -> next;
}
/* Allocate memory for the new node and put data in it.*/
pointer->next = (node *)malloc(sizeof(node));
(pointer->next)->prev = pointer;
pointer = pointer->next;
pointer->data = data;
pointer->next = NULL;
}
int find(node *pointer, int key)
{
pointer = pointer -> next; //First node is dummy node.
/* Iterate through the entire linked list and search for the key. */
while(pointer!=NULL)

5
Data Structure lab manual

{
if(pointer->data == key) //key is found.
{
return 1;
}
pointer = pointer -> next;//Search in the next node.
}
/*Key is not found */
return 0;
}
void delete(node *pointer, int data)
{
/* Go to the node for which the node next to it has to be deleted */
while(pointer->next!=NULL && (pointer->next)->data != data)
{
pointer = pointer -> next;
}
if(pointer->next==NULL)
{
printf("Element %d is not present in the list\n",data);
return;
}
/* Now pointer points to a node and the node next to it has to be removed */
node *temp;
temp = pointer -> next;
/*temp points to the node which has to be removed*/
pointer->next = temp->next;
temp->prev = pointer;
/*We removed the node which is next to the pointer (which is also temp) */
free(temp);
/* Beacuse we deleted the node, we no longer require the memory used for it .
free() will deallocate the memory.
*/
return;
}
void print(node *pointer)
{
if(pointer==NULL)
{
return;
}
printf("%d ",pointer->data);
print(pointer->next);
}
int main()
{

6
Data Structure lab manual

/* start always points to the first node of the linked list.


temp is used to point to the last node of the linked list.*/
node *start,*temp;
start = (node *)malloc(sizeof(node));
temp = start;
temp -> next = NULL;
temp -> prev = NULL;
/* Here in this code, we take the first node as a dummy node.
The first node does not contain data, but it used because to avoid handling special cases
in insert and delete functions.
*/
printf("1. Insert\n");
printf("2. Delete\n");
printf("3. Print\n");
printf("4. Find\n");
while(1)
{
int query;
scanf("%d",&query);
if(query==1)
{
int data;
scanf("%d",&data);
insert(start,data);
}
else if(query==2)
{
int data;
scanf("%d",&data);
delete(start,data);
}
else if(query==3)
{
printf("The list is ");
print(start->next);
printf("\n");
}
else if(query==4)
{
int data;
scanf("%d",&data);
int status = find(start,data);
if(status)
{
printf("Element Found\n");
}

7
Data Structure lab manual

else
{
printf("Element Not Found\n");

}
}
}

Conclusion :Thus we have implemented Doubly Linked List.

8
Data Structure lab manual

Experiment No.3

Aim : To implement Stack using array.


Theory : The stack is a common data structure for representing things that need to maintained in
a particular order. For instance, when a function calls another function, which in turn calls a third
function, it's important that the third function return back to the second function rather than the
first.

One way to think about this implementation is to think of functions as being stacked on top of
each other; the last one added to the stack is the first one taken off. In this way, the data structure
itself
enforces the proper order of calls.

Conceptually, a stack is simple: a data structure that allows adding and removing elements in a
particular order. Every time an element is added, it goes on the top of the stack; the only element
that can be removed is the element that was at the top of the stack. Consequently, a stack is said
to have "first in last out" behavior (or "last in, first out"). The first item added to a stack will be
the last item removed from a stack.

So what's the big deal? Where do stacks come into play? As you've already seen, stacks are a
useful way to organize our thoughts about how functions are called. In fact, the "call stack" is the
term used for the list of functions either executing or waiting for other functions to return.

In a sense, stacks are part of the fundamental language of computer science. When you want to
express an idea of the "first in last out" variety, it just makes sense to talk about it using the
common terminology. Moreover, such operations show up an awful lot, from theoretical
computer science tools such as a push-down automaton to AI, including implementations of
depth-first search.

Stacks have some useful terminology associated with them:

 Push To add an element to the stack


 Pop To remove an element from the stock
 Peek To look at elements in the stack without removing them
 LIFO Refers to the last in, first out behavior of the stack
 FILO Equivalent to LIFO

9
Data Structure lab manual

10
Data Structure lab manual

Program :
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>

#define size 5
struct stack {
int s[size];
int top;
} st;

int stfull() {
if (st.top >= size - 1)
return 1;
else
return 0;
}

void push(int item) {


st.top++;
st.s[st.top] = item;
}

int stempty() {
if (st.top == -1)
return 1;
else
return 0;
}

int pop() {
int item;
item = st.s[st.top];
st.top--;
return (item);
}

void display() {
int i;
if (stempty())
printf("\nStack Is Empty!");
else {
for (i = st.top; i >= 0; i--)
printf("\n%d", st.s[i]);
}
}

11
Data Structure lab manual

int main() {
int item, choice;
char ans;
st.top = -1;

printf("\n\tImplementation Of Stack");
do {
printf("\nMain Menu");
printf("\n1.Push \n2.Pop \n3.Display \n4.exit");
printf("\nEnter Your Choice");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("\nEnter The item to be pushed");
scanf("%d", &item);
if (stfull())
printf("\nStack is Full!");
else
push(item);
break;
case 2:
if (stempty())
printf("\nEmpty stack!Underflow !!");
else {
item = pop();
printf("\nThe popped element is %d", item);
}
break;
case 3:
display();
break;
case 4:
exit(0);
}
printf("\nDo You want To Continue?");
ans = getche();
} while (ans == 'Y' || ans == 'y');

return 0;
}

Conclusion : Thus we have implemented Stack using Array.

12
Data Structure lab manual

Experiment No.4

Aim : To implement Binary Search Tree.

Theory :

 A prominent data structure used in many systems programming applications for


representing and managing dynamic sets.

 Average case complexity of Search, Insert, and Delete Operations is O(log n), where n is
the number of nodes in the tree.
 DEF: A binary tree in which the nodes are labeled with elements of an ordered dynamic
set and the following BST property is satisfied: all elements stored in the left subtree of
any node x are less than the element stored at x and all elements stored in the right
subtree of x are greater than the element at x.
 An Example: Figure shows a binary search tree. Notice that this tree is obtained by
inserting the values 13, 3, 4, 12, 14, 10, 5, 1, 8, 2, 7, 9, 11, 6, 18 in that order, starting
from an empty tree.
 Note that inorder traversal of a binary search tree always gives a sorted sequence of the
values. This is a direct consequence of the BST property. This provides a way of sorting a
given sequence of keys: first, create a BST with these keys and then do an inorder
traversal of the BST so created.
 Note that the highest valued element in a BST can be found by traversing from the root in
the right direction all along until a node with no right link is found (we can call that the
rightmost element in the BST).
 The lowest valued element in a BST can be found by traversing from the root in the left
direction all along until a node with no left link is found (we can call that the leftmost
element in the BST).
 Search is straightforward in a BST. Start with the root and keep moving left or right
using the BST property. If the key we are seeking is present, this search procedure will
lead us to the key. If the key is not present, we end up in a null link.
 Insertion in a BST is also a straightforward operation. If we need to insert an element x,
we first search for x. If x is present, there is nothing to do. If x is not present, then our
search procedure ends in a null link. It is at this position of this null link that x will be
included.
 If we repeatedly insert a sorted sequence of values to form a BST, we obtain a completely
skewed BST. The height of such a tree is n - 1 if the tree has n nodes. Thus, the worst
case complexity of searching or inserting an element into a BST having n nodes is O(n).

13
Data Structure lab manual

Figure 4: An example of a binary search tree

Program :
#include<stdlib.h>
#include<stdio.h>

struct bin_tree {
int data;
struct bin_tree * right, * left;

14
Data Structure lab manual

};
typedef struct bin_tree node;

void insert(node ** tree, int val)


{
node *temp = NULL;
if(!(*tree))
{
temp = (node *)malloc(sizeof(node));
temp->left = temp->right = NULL;
temp->data = val;
*tree = temp;
return;
}

if(val < (*tree)->data)


{
insert(&(*tree)->left, val);
}
else if(val > (*tree)->data)
{
insert(&(*tree)->right, val);
}

void print_preorder(node * tree)


{
if (tree)
{
printf("%d\n",tree->data);
print_preorder(tree->left);
print_preorder(tree->right);
}

void print_inorder(node * tree)


{
if (tree)
{
print_inorder(tree->left);
printf("%d\n",tree->data);
print_inorder(tree->right);
}
}

15
Data Structure lab manual

void print_postorder(node * tree)


{
if (tree)
{
print_postorder(tree->left);
print_postorder(tree->right);
printf("%d\n",tree->data);
}
}

void deltree(node * tree)


{
if (tree)
{
deltree(tree->left);
deltree(tree->right);
free(tree);
}
}

node* search(node ** tree, int val)


{
if(!(*tree))
{
return NULL;
}

if(val < (*tree)->data)


{
search(&((*tree)->left), val);
}
else if(val > (*tree)->data)
{
search(&((*tree)->right), val);
}
else if(val == (*tree)->data)
{
return *tree;
}
}

void main()
{
node *root;
node *tmp;

16
Data Structure lab manual

//int i;

root = NULL;
/* Inserting nodes into tree */
insert(&root, 9);
insert(&root, 4);
insert(&root, 15);
insert(&root, 6);
insert(&root, 12);
insert(&root, 17);
insert(&root, 2);

/* Printing nodes of tree */


printf("Pre Order Display\n");
print_preorder(root);

printf("In Order Display\n");


print_inorder(root);

printf("Post Order Display\n");


print_postorder(root);

/* Search node into tree */


tmp = search(&root, 4);
if (tmp)
{
printf("Searched node=%d\n", tmp->data);
}
else
{
printf("Data Not found in tree.\n");
}

/* Deleting all nodes of tree */


deltree(root);
}

Conclusion : Thus we have implemented Binary Search Tree.

17
Data Structure lab manual

Experiment No.5

Aim : To implement Graph.

Theory : Graph is a data structure that consists of following two components:


1. A finite set of vertices also called as nodes.
2. A finite set of ordered pair of the form (u, v) called as edge. The pair is ordered because (u, v)
is not same as (v, u) in case of directed graph(di-graph). The pair of form (u, v) indicates that
there is an edge from vertex u to vertex v. The edges may contain weight/value/cost.

Graphs are used to represent many real life applications: Graphs are used to represent networks.
The networks may include paths in a city or telephone network or circuit network. Graphs are
also used in social networks like linkedIn, facebook. For example, in facebook, each person is
represented with a vertex(or node). Each node is a structure and contains information like person
id, name, gender and locale. This can be easily viewed by
http://graph.facebook.com/barnwal.aashish where barnwal.aashish is the profile name. See this
for more applications of graph.

Following is an example undirected graph with 5 vertices.

Following two are the most commonly used representations of graph.


1. Adjacency Matrix
2. Adjacency List
There are other representations also like, Incidence Matrix and Incidence List. The choice of the
graph representation is situation specific. It totally depends on the type of operations to be
performed and ease of use.

Adjacency Matrix:
Adjacency Matrix is a 2D array of size V x V where V is the number of vertices in a graph. Let
the 2D array be adj[][], a slot adj[i][j] = 1 indicates that there is an edge from vertex i to vertex j.
Adjacency matrix for undirected graph is always symmetric. Adjacency Matrix is also used to
represent weighted graphs. If adj[i][j] = w, then there is an edge from vertex i to vertex j with
weight w.

The adjacency matrix for the above example graph is:

18
Data Structure lab manual

Adjacency Matrix Representation of the above graph

Pros: Representation is easier to implement and follow. Removing an edge takes O(1) time.
Queries like whether there is an edge from vertex ‘u’ to vertex ‘v’ are efficient and can be done
O(1).

Cons: Consumes more space O(V^2). Even if the graph is sparse(contains less number of edges),
it consumes the same space. Adding a vertex is O(V^2) time.

AdjacencyList:
An array of linked lists is used. Size of the array is equal to number of vertices. Let the array be
array[]. An entry array[i] represents the linked list of vertices adjacent to the ith vertex. This
representation can also be used to represent a weighted graph. The weights of edges can be
stored in nodes of linked lists. Following is adjacency list representation of the above graph.

Adjacency List Representation of the above Graph

19
Data Structure lab manual

Program :

# include < stdio.h >


# include < conio.h >

void main()
{
int option;
clrscr();
do
{ printf("\n A Program to represent a Graph by using an ");
printf("Adjacency Matrix method \n ");
printf("\n 1. Directed Graph ");
printf("\n 2. Un-Directed Graph ");
printf("\n 3. Exit ");
printf("\n\n Select a proper option : ");
scanf("%d", &option);
switch(option)
{
case 1 : dir_graph();
break;
case 2 : undir_graph();
break;
case 3 : exit(0);
} // switch
}while(1);
} // main

int dir_graph()
{
int adj_mat[50][50];
int n;
int in_deg, out_deg, i, j;

printf("\n How Many Vertices ? : ");


scanf("%d", &n);

read_graph (adj_mat, n);


printf("\n Vertex \t In_Degree \t Out_Degree \t Total_Degree ");
for (i = 1; i < = n ; i++ )
{
in_deg = out_deg = 0;
for ( j = 1 ; j <= n ; j++ )
{

20
Data Structure lab manual

if ( adj_mat[j][i] == 1 )
in_deg++;
} // for
for ( j = 1 ; j <= n ; j++ )
if (adj_mat[i][j] == 1 )
out_deg++;
printf("\n\n %5d\t\t\t%d\t\t%d\t\t%d\n\n",i,in_deg,out_deg,in_deg+out_deg);
} // for
return;
} // dir_graph

int undir_graph()
{
int adj_mat[50][50];
int deg, i, j, n;

printf("\n How Many Vertices ? : ");


scanf("%d", &n);

read_graph(adj_mat, n);
printf("\n Vertex \t Degree ");

for ( i = 1 ; i <= n ; i++ )


{
deg = 0;
for ( j = 1 ; j <= n ; j++ )
if ( adj_mat[i][j] == 1)
deg++;
printf("\n\n %5d \t\t %d\n\n", i, deg);
} // for
return;
} // undir_graph

int read_graph ( int adj_mat[50][50], int n )


{
int i, j;
char reply;

for ( i = 1 ; i <= n ; i++ )


{
for ( j = 1 ; j <= n ; j++ )
{
if ( i == j )
{
adj_mat[i][j] = 0;
continue;

21
Data Structure lab manual

} // if
printf("\n Vertices %d & %d are Adjacent ? (Y/N) :",i,j);
flushall();
scanf("%c", &reply);
if ( reply == 'y' || reply == 'Y' )
adj_mat[i][j] = 1;
else
adj_mat[i][j] = 0;
} // for
} // for
return;
} // read_graph

Conclusion : Thus we have implemented Graph using adjacency matrix.

22
Data Structure lab manual

Experiment No.6

Aim : To implement Insertion Sort.

Theory : Insertion sort iterates, consuming one input element each repetition, and growing a
sorted output list. Each iteration, insertion sort removes one element from the input data, finds
the location it belongs within the sorted list, and inserts it there. It repeats until no input elements
remain.

Sorting is typically done in-place, by iterating up the array, growing the sorted list behind it. At
each array-position, it checks the value there against the largest value in the sorted list (which
happens to be next to it, in the previous array-position checked). If larger, it leaves the element in
place and moves to the next. If smaller, it finds the correct position within the sorted list, shifts
all the larger values up to make a space, and inserts into that correct position.

The most common variant of insertion sort, which operates on arrays, can be described as
follows:

1. Suppose there exists a function called Insert designed to insert a value into a sorted
sequence at the beginning of an array. It operates by beginning at the end of the sequence
and shifting each element one place to the right until a suitable position is found for the
new element. The function has the side effect of overwriting the value stored immediately
after the sorted sequence in the array.
2. To perform an insertion sort, begin at the left-most element of the array and invoke Insert
to insert each element encountered into its correct position. The ordered sequence into
which the element is inserted is stored at the beginning of the array in the set of indices
already examined. Each insertion overwrites a single value: the value being inserted.

Program :

#include<stdio.h>
int main(){

int i,j,s,temp,a[20];

printf("Enter total elements: ");


scanf("%d",&s);

printf("Enter %d elements: ",s);


for(i=0;i<s;i++)
scanf("%d",&a[i]);

23
Data Structure lab manual

for(i=1;i<s;i++){
temp=a[i];
j=i-1;
while((temp<a[j])&&(j>=0)){
a[j+1]=a[j];
j=j-1;
}
a[j+1]=temp;
}

printf("After sorting: ");


for(i=0;i<s;i++)
printf(" %d",a[i]);

return 0;
}

Conclusion : Thus we have implemented Insertion Sort.

24

You might also like