Vous êtes sur la page 1sur 15

MC 0068 01

DATA STRUCTURES USING C

1) Write the advantages of implementation checks preconditions


Checks pre conditions
It is important to state in the specification whether each performance will be
checked by the user or by the implementer. For ex, the precondition for POP may be
checked either by the procedure(s) that call POP or within the procedure that implements
POP.
The main advantage is, if the user checks preconditions and therefore
guarantees that they will be satisfied when the core operations are invoked- is efficiency.
For ex.,
PUSH(S,1);
POP(S);
There is no need to check is S is empty this precondition of POP is guaranteed to be
satisfied because it is a post condition of PUSH.
There are several advantages to having the implementation check its own preconditions.
They are as follows;-

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.

Programs wont bomb mysteriously errors will be detected (and reported?) at


the earliest possible moment.

This is not true when the user checks

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.

Thats what our model solutions will be doing.

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.

The various operations that can be performed on stacks are;


. Insert an item into the stack
. Delete an item from the stack
. Display the contents of the stack.
We can understand from the definition of stack, that it is a collection of similar type of
items and naturally we can use an array (An Array is a collection of similar data types) to
hold the items of stack. Since array is used, its size is fixed.
For ex, let us consider 5 items 30, 20, 25, 10 and 40 are to be placed on the stack. The
items can be inserted one by one like this

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
-

Insert an item into queue

Delete an item from queue

Display the contents of queue

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 various operations that can be performed on stacks are;


. Insert an item into the stack
. Delete an item from the stack
. Display the contents of the 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.,
4) Explain the AVL Tree with suitable example?
An AVL tree is a binary search tree whose left sub-tree and right sub-tree differ in height
by no more than 1, and whose left and right sub-trees are the AVL trees.
Example of AVL Tree:Lets consider the AVL tree shown under. the right sub-tree has height 1 and the left subtree, height ). the balance factor of the root is tiltled toward the right (right high rh)
since the right sub-tree has height one larger than the left sub-tree. Inserting the new
node 21 into the tree will cause the right sub-tree to have height 2 and cause a violation
of the definition of an AVL tree. This violation of the AVL property is indicted at the
root by showing that the balance factor is now doubly unbalanced to the right. The other
balance factors along the path of insertion will also be changed as indicted. The node
holding 12 also doubly unbalanced to the right.

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

vertices are adjacent is very quick.

Adding and removing edges are also very

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

7) Write an algorithm for the followings:-

12

Dijkstra Algorithm and Bellman-Ford Algorithm


Dijkstra Algorithm
Dijkstras algorithm (invented by Edsger W. Dijkstra) solves the problem
of finding the shortest path from a point in a graph (the source) to a destination. It
turns out that one can find the shortest paths from a given source to all points in a
graph in the same time. So its called the Single-Source shortest paths problem. The
graph is related to spanning tree. The graph must be a spanning tree an dit must
include all vertices. There will be no cycles as a cycle would define more than one
path from the selected vertex to at least one other vertex. For a graph, G = (V,E)
where V is a set of vertices and E is a set of edges.
Dijkstras algorithm keeps two sets of vertices- S (the set of vertices
whose shortest paths from the source have already been determined) and V-S (the
remaining vertices).

The other data structures needed are d (array of bese

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

While there are still vertices in V-S,


a) sort the vertices in V-S according to the current best estimate of their
distance from source
b) Add u, the closest vertex in V-S, to S,
c) Relax all the vertices still in V-S connected to u.
ALGORITHM:DIJKSTRA(Graph G, Node s)
initialize_single_source (G,s)

13

S: = (0)

/*Make S empty */

Q: Vertices (G)/*Put the vertices in a PQ*/


While not Empty (Q)
u: ExtractMin (Q);
AddNode (S,u);/* Add u to S*/
for each vertex v which Adjacent with u
relax (u,v,w)
Bellman-Ford Algorithm
It is a more generalized single-source shortest path algorithm which can find
the shortest path in a graph with negative weighted edges. If there is no negative cycle
in the graph, this algorithm will updates each d[v] with the shortest path from s to v, fill
up the predecessor list pi. and return TRUE. However, if there is a negative cycle in
the given graph, this algorithm will return FALSE
BELLMAN_FORD (Graph g, double w[ ][ ], Node s)
initialize_single_source (G,s)
for i = 1 to |V[G]|-1
for each edge (u, v) in E [g]
relax (u ,v, w)
for each edge (u, v) in E[G]
if d[v] > d[u] + w(u, v) then
return FALSE
return TRUE

14

15

Vous aimerez peut-être aussi