MC 0068 - 01 Data Structures Using C
MC 0068 - 01 Data Structures Using C
It sometimes has access to information not available to the user, - that is for ex.,
implementation details about space requirements - , although this is often a sign
of a poorly constructed specification.
preconditions, because the user is human and occasionally might forget to check,
or might think that checking was unnecessary when in fact it was needed.
Most important of all, if we ever change the specification, and wish to add,
delete, or modify preconditions, we can do this easily, because the precondition
occurs in exactly one place in our program.
But here are arguments on both sides. The literatures specifies that procedures should
signal a error if their preconditions are not satisfied. This means that these procedures
must check their own preconditions.
Then we have to sacrifice some efficiency for a high degree of maintainability and
robustness.
An additional possibility is to selectively include or exclude the implementations
condition checking code.
For ex, using #ifdef:
#ifdef SAFE
if (! condition) error (condition not satisfied);
#endif
This code will get included only if we supply the DSAFE argument to the compiler (or
otherwise define SAFE). Thus, in an application where the user checks carefully for all
preconditions, we have the option of omitting all checks by the implementation.
2) Discuss the STACK operation with suitable example and show to implement
stack operations of integer in C by using array.
A stack is defined as a special type of data structure where items are inserted from one
end called top of stack and items are deleted from the same end. Here, the last item
inserted will be on top of stack. Since deletion is done from the same end, Last item
inserted is the First item to be deleted. Out from the stack and so, stack is also called
Last In First Out (LIFO) data structure.
It is clear that initially stack is empty and top points to bottom of stack. As the items are
inserted top pointer is incremented and it points to the topmost item. Here, the items
30,20,25,10 and 40 are inserted one after the other. After inserting 40 the stack is full.
In this situation it is not possible to insert any new item. This situation is called stack
overflow. When an item is to be deleted, it should be deleted from the top like this
Since items are inserted from one end, in stack deletions should be done from the same
end. So as the items are deleted, the item below the top item becomes the new top item
and so the position of the top most item is decremented here. The items deleted in order
are 40, 10, 25, 20 and 30. Finally, when all items are deleted, top points to bottom of
stack. When the stack is empty, it is not possible to delete any item and this situation is
called under flow of stack.
So the main operations to be performed on stacks are insertion and deletion. Inserting an
item into the stack when stack is not full is called push operation and deleting an item
from the stack when stack is not empty is called pop operation. Other operations that
can be performed are display the contents of the stack, check whether the stack is empty
or not, etc.,
C program of implementing stack operations of integer by using array
#include <stdio.h>
#include <conio.h>
#define Max 5
int a[Max], top=-1;
void push ( )
{
int ele;
char ch;
if (top = = -1)
top = 0;
do
{
if(top>=5)
{
printf(Stack is full);
break;
else
{
clrscr ( );
printf (Enter element to be inserted\n);
scanf (%d, &ele);
a[top ++] = ele;
}
printf (Do you want to add more elements: ?\n);
scanf (\n%c, &ch);
printf(%c, ch);
}while ((ch = = Y)||(ch = = Y));
}
void pop ( )
{
if (top = =-1)
{
printf (Stack is underflow\n);
}
else
{
for(int i =top-1; i>=0; i--)
printf (%d\n, a[i] );
}
}
void main( )
{
clrscr ( );
char c;
int choice;
do
{
clrscr ( );
printf (enter Your Choice\n);
printf (1 -> Push\n);
print (2 -> Pop\n);
scanf (%d, & Choice);
if (choice = =1)
push ( );
else if (choice = =2)
pop ( );
else
printf (invalid choice);
printf (Do You Want to Continue\n);
scanf (n%c, & c);
} while ( (c = = y)|| (c = = Y) );
}
3) Discuss how Queues are differ from Stack
A queue is a pile in which items are added on one end and removed from the other. For
ex, this will like a line of customers waiting to be served by a bank teller. As customers
arrive, they join the end of the queue while the teller serves the customers at the head of
the queue. As a result, queue is used when a sequence of activities must be done on a
first come first served basis.
Queue is a linear list for which all insertions are made at one end of the list; all
deletions (and usually all accesses) are made at the other end (FIFO).
A queue is defined as a special type pf data structure where elements are inserted
from one end and elements are deleted from the other end. The end from the elements
are inserted is called rear end (r), and the end where elements are deleted is called
front end (f). In a queue, always elements are inserted from the rear end and elements
are deleted from the front end. The first item to be deleted from the queue is the item
which is at the front of the queue. The operations performed on queues that First item
inserted is the First item to be deleted out from the queue. So queue is also called First
In First Out (FIFO) data structure.
This data structure is useful in time-sharing systems where many user jobs will
be waiting in the system queue for processing. These jobs may request the services of
CPU, main memory or external devices such as printer etc. All these jobs will be given a
fixed time for processing and are allowed to use one after the other. This is the case of
an ordinary queue where priority is same for all the jobs and whichever job is submitted
first, that job will be processed. The primitive operations that can be performed on
queues are
-
Sometimes, based on the job preference, jobs may have to be processed. Such a queue
where a job is processed based on the priority is called a priority queue.
A stack is defined as a special type of data structure where items are inserted from one
end called top of stack and items are deleted from the same end. Here, the last item
inserted will be on top of stack. Since deletion is done from the same end, Last item
inserted is the First item to be deleted. Out from the stack and so, stack is also called
Last In First Out (LIFO) data structure.
The AVL property of this tree is restored through a succession of rotations. The root of
this tree is doubly unbalanced to the right. The child of the unbalanced node (node12) is
also doubly unbalanced rh, but its child (node 24) is lh. Before a rotation around the root
of the right sub-tree can be performed, a rotation around node 24 is required so that the
balance factors of both the child and grandchild of the unbalanced node-the subtree root
(node 12) agree in direction (both rh in this case).
Now both nodes 12 and 21 have a balance factor of rh, and a left rotation can be
performed about the node 12. This rotation reduces the height of the right sub-tree by 1
and will restore AVL balance to the tree
Next we add a new key 6 to this tree. Addition of a new node holding this key causes
the root to become doubly unbalanced to the right.
Since the root is doubly unbalanced right and its child is left high, we must perform a
right rotation around node 21. Now a rotation around the root readjusts the balance of
the tree.
The left rotation about the root promotes the right child of the original root (node 12),
and makes the old root (node 4) the left child of the new root replacing the left subtree
originally attached to node 12. The former left subtree of node 12 is now the right subtree of node 4. In a left rotation, all of the keys in the left in the left subtree of the right
child must be greater than the key of the root and less than the key of the parent. When
the root becomes the left child of the parent, the keys in this subtree remain in the left
subtree of the new root and in the right subtree of the new left child.
6) Explain the adjacency Matrix and adjacency List with suitable example.
Adjacency Matrix
One of the Way to represent a graph utilized an adjacency matrix. This is N by N array
( N is the number of vertices). The i, j entry contains a 1 if the edge (i, j) is in the graph,
otherwise it contains a 0. For an undirected graph, this matrix is symmetric. This
representation is easy to code. Its much less space efficient, especially for large, sparse
graphs. Debugging is harder, as the matrix is large. Finding all the edges incident to a
given vertex is fairly expensive (linear in the number of vertices), but checking if two
10
inexpensive operations.
For weighted graphs, the value of the (i, j) entry is used to store the weight of the
edge. For an unweighted multigraph, the (i, j) entry can maintain the number of edges
between the vertices. For a weighted multigraph, its harder to extend this.
The sample undirected graph would be represented by the following adjacency matrix.
V1
V2
V3
V4
V5
V6
V1
V2
V3
V4
V5
V6
It is sometimes helpful to sue the fact that the (i, j) entry of the adjacency matrix raised
to the k-th power gives the number of paths from vertex i to vertex j consisting of
exactly k edges.
Adjacency List
The third representation of a matrix is to keep track of all the edges incident to a given
vertex. This can be done by using an array of length N, where N is the number of
vertices. The i-th entry in this array is a list of the edges incident to i-th vertex 9edges
are represented by the index of the other vertex incident to that edge).
This representation is much more difficult to code, especially if the number of
edges incident to each vertex is not bounded, so the lists must be linked lists (or
dynamically allocated). Debugging this is difficult, as following linked lists is more
11
difficult. However, this representation uses about as much memory as the edge list.
Finding the vertices adjacent to each node is very cheap in this structure, but checking if
two vertices are adjacent requires checking all the edges adjacent to one of the vertices.
Adding an edge is easy, but deleting an edge is difficult, if the locations of the edge in
the appropriate lists are not known. Extend this representation to handle weighted
graphs by maintaining both the weight and the other incident vertex for each edge
instead of just the other incident vertex. Multigraphs are already representable. Directed
graphs are also easily handled by this representation, in one of several ways; store only
the edges in one direction, keep a separate list of incoming and outgoing arcs, or denote
the direction of each arc in the list.
The following example adjacency list representation of the undirected graph is under
Vertex
Adjacent Vertices
3, 6
5
6. 4. 1
3
2
3, 1
12
estimates of shortest path to each vertex) & pi (an array of predecessors for each
vertex).
The basic mode of operation is-
Initialise d and pi
Set S to empty
13
S: = (0)
/*Make S empty */
14
15