Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
August 2010
Master of Computer Application (MCA) – Semester 2
MC0068 – Data Structures using C – 4 Credits
(Book ID: B0701 & B0702) Assignment Set – 1
3. Function names.
Advantages of Pointers:
Pointers are declared similar to normal variables, but we must specify when we declare them
what they are going to point to it. We declare a pointer to point to an integer, then it cant be
used to point a floating-point value etc.
Pointer Operators:
To declare and refer a pointer variable, provides two special operators & and *.
2. Indirectional Operator : *
& ß (ampersand ) This Operator gives the memory Address of the variable.
Example : if i = 100
Example :
Example: Program to assign the pointer values. (using operator & and *)
#include< iostream.h>
#include<conio.h>
main( )
{
int *x, y; /* xis pointer to integer variable */
clrscr ( );
y = 10;
x = &y; /* y value stored in pointer x.*/
Output
Address of y = 65555
Value of y = 10
Address of y = 65555
Value of y = 10
Note:
ii) last statement value of y indirectly by using *x. *x-value at address stored by x.
Output
The value of y is = 8
Note: Variable y is assigned to value at the address stored in ipt. since ipt contains
address of x, the value at address of x is 8, so * ipt is equal to 10.
It is mechanism by which pointers can be passed as arguments to the function. Thus, the
data items of the calling program can be accessed by the called program. No values is copied
when pointers are passed as arguments, as in the called by value method. Another important
point is that, if the values are changed in the function this will modify the original contents of
the actual parameters, this is not true in case of call by value method.
When the pointers are passed as an argument we must follow the following points.
a. In the calling program, the function is invoked with a function name and addresses of actual
parameters enclosed within the parenthesis.
Example :
b. In the called program parameter list, each & every formal parameter (pointers) must be
preceeded by an indirection operatore(*)
Example :
Example : Program to illustrate the call by reference method to interchange the value
of 2 integer variable.
main()
{
int num1,num2;
int interchange( int *n1, int *n2);
printf( “Enter any Two integer numbern”);
scanf(“%d %d “, &num1,&num2);
printf(“before interchanging n);
printf(“num1 = %d and num2 = %d”,num1,num2);
interchange(&num1,&num2);
printf(“after interchanging n);
printf(“num1 = %d and num2 = %d” num1, num2);
}
int interchange(int *n1, int *n2)
{
int temp;
temp=*n1;
* n1=*n2;
*n2=temp;
}
Pointers can be used with array to increase the efficiency of the execution of the program.
Pointers can be used with single dimensional or multi-dimensional arrar.
Pointers using in Single Dimensional Array.: The name of a array itself designates some
memory location & this location in memory is the address of the very first element of an array,
the address of the first element of array & num[0], where num is an array name.
Example :
Write a program to use an array of 5 elements & illustrate the relationship between
elements of an array & their address.
main()
{
int arrlist[5];
int *ptr,index,value=3;
ptr = arrlist;
for(index=0; index<5; index++)
{
*(ptr+index)=value++;
printf(“*(ptr+index)=%dtarrlist(index)=%d n”,*(ptr+index),arrlist[index]);
}
}
Output :
*(ptr+index)= 3 arrlist(index)= 3
*(ptr+index)= 4 arrlist(index)= 4
*(ptr+index)= 5 arrlist(index)= 5
*(ptr+index)= 6 arrlist(index)= 6
*(ptr+index)= 7 arrlist(index)= 7
Example :
Write a program to find the sum of 5 elements static in nature using pointers with
function.
main()
{
static int array[5]={200,400,600,800,1000};
int addnum(int *ptr); / * function protype */
int sum;
sum = addnum(array);
printf(“ Sum of all array elements = %d n”,sum);
}
2. Demonstrate with your own programming example the usage of structures within an
array.
Ans: Each and every structure must be defined or declared before it appears or using in program.
Syntax:
struct <structurer name>
{
<type1> <field/data1>
<type2> <field/data2>
<type3> <field/data3>
………………………
……………………….
<type n> <field/data n>
};
Example :
Struct student
{
int rollno;
char name[30];
char address[30];
char city[15];
float marks;
};
It means that, Structure within the another structure is called an embedded structure.
b) There may be a separate structure, the embedded structure declared first and the other
structure declared next.
{ {
{ };
int month; {
}; int month;
}; int year;
};
Processing of Structure: The process of structure is mainly concerned with the accessing
structure member. Each member of a structure is accessed with .(dot) operator to access a
particular member of the structure, the dot operator must be placed between the name of the
structure & the name of the structure member.
Examples:
Write a program to accept the student details as roll_no, name, city, marks using
structure and print the details.
struct std
{
int rollno;
char name[30];
char city[15];
int marks;
} st; /* structure definition */ /* st -> is the structure point */
main() /*main program */
{
printf(“enter the Roll no n”);
scanf(“%d “, &st.rollno);
printf(“enter the Name n”);
scanf(“%s “, st.name);
printf(“enter the city n”);
scanf(“%d “, st.city);
printf(“enter the Marks n”);
scanf(“%d “, &st.marks);
/* printing details */
Structure used with an Array: However we know that different type of data sets cannot be
stored an array, So, to overcome this disadvantage structure can be stored along with its
members in array structure.
Trees: we consider one of the most Important non-linear Information structures- trees. A tree
Is often used to represent a hierarchy. This is because the relationships between the Items In
the hierarchy suggest the branches of a botanical tree.
For example, a tree-like organization charts often used to represent the lines of responsibility
in a business as shown in Figure. The president of the company is shown at the top of the
tree and the vice-presidents are indicated below her. Under the vice-presidents we find the
managers and below the managers the rest of the clerks. Each clerk reports to a manager.
Each manager reports to a vice-president, and each vice-president reports to the president.
It just takes a little imagination to see the tree in Figure. Of course. The tree is upside-down.
However, this is the usual way the data structure is drawn. The president is called the root of
the tree and the clerks are the leaves.
A tree is extremely useful for certain kinds of computations. For example. Suppose we wish to
determine the total salaries paid to employees by division or by department. The total of the
salaries in division A can be found by computing the sum of the salaries paid in departments
Al and A2 plus the salary of the vice-president of division A. Similarly. The total of the salaries
paid in department Al is the sum of the salaries of the manager of department Al and of the
two clerks below her.
Clearly, in order to compute all the totals. It is necessary to consider the salary of every
employee. Therefore, an implementation of this computation must visit all the employees in
the tree. An algorithm that systematically visits all the items in a tree is called a tree traversal.
In the same chapter we consider several different kinds of trees as well as several different
tree traversal algorithms. In addition. We show how trees can be used to represent arithmetic
expressions and how we can evaluate an arithmetic expression by doing a tree traversal. The
following is a mathematical definition of a tree:
3. A designated node of the set, r, is called the root of the tree: and
4. The remaining nodes are partitioned into n≥ O subsets T, T. …Tn each of which is a tree
for convenience, we shall use the notation T= {r. T, T, …T} denote the tree T.
Notice that Definition is recursive-a tree is defined in terms of itself! Fortunately, we do not
have a problem with infinite recursion because every tree has a finite number of nodes and
because in the base case a tree has n=0 subtrees.
It follows from Definition that the minimal tree is a tree comprised of a single root node. For
example Ta = {A}.
How do Ta Tb. & Tc resemble their arboreal namesake? The similarity becomes apparent
when we consider the graphical representation of these trees shown in Figure. To draw such
a pictorial representation of a tree, T = {r. T1 ,T2, …Tn, beside each other below the root.
Finally, lines are drawn from rto the roots of each of the subtrees. T1T2…….Tn
Examples of trees
Of course, trees drawn in this fashion are upside down. Nevertheless, this is the conventional
way in which tree data structures are drawn. In fact, it is understood that when we speak of
“up” and “down,” we do so with respect to this pictorial representation. For example, when we
move from a root to a subtree, we will say that we are moving down the tree.
The inverted pictorial representation of trees is probably due to the way that genealogical
lineal charts are drawn. A lineal chart is a family tree that shows the descendants of some
person. And it is from genealogy that much of the terminology associated with tree data
structures is taken.
Figure shows one representation of the tree Tc defined in Equation. In this case, the tree is
represented as a set of nested regions in the plane. In fact, what we have is a Venn diagram
which corresponds to the view that a tree is a set of sets.
Binary Tree: Used to implement lists whose elements have a natural order (e.g. numbers)
and either (a) the application would like the list kept in this order or (b) the order of elements
is irrelevant to the application (e.g. this list is implementing a set).
Each element in a binary tree is stored in a "node" class (or struct). Each node contains
pointers to a left child node and a right child node. In some implementations, it may also
contain a pointer to the parent node. A tree may also have an object of a second "tree" class
(or struct) which as a header for the tree. The "tree" object contains a pointer to the root of the
tree (the node with no parent) and whatever other information the programmer wants to
squirrel away in it (e.g. number of nodes currently in the tree).
In a binary tree, elements are kept sorted in left to right order across the tree. That is if N is a
node, then the value stored in N must be larger than the value stored in left-child(N) and less
than the value stored in right-child(N). Variant trees may have the opposite order (smaller
values to the right rather than to the left) or may allow two different nodes to contain equal
values.
Hash Tables: A very common paradigm in data processing involves storing information in a
table and then later retrieving the information stored there. For example, consider a database
of driver’s license records. The database contains one record for each driver’s license issued.
Given a driver’s license number. we can look up the information associated with that number.
Similar operations are done by the C compiler. The compiler uses a symbol table to keep
track of the user-defined symbols in a Java program. As it compiles a program, the compiler
inserts an entry in the symbol table every time a new symbol is declared. In addition, every
time a symbol is used, the compiler looks up the attributes associated with that symbol to see
that it is being used correctly.
In general, an application may perform a large number of insertion and/ or look-up operations.
Occasionally it is also necessary to remove items from the database. Because a large
number of operations will be done we want to do them as quickly as possible.
Hash tables are a very practical way to maintain a dictionary. As with bucket sort, it assumes
we know that the distribution of keys is fairly well-behaved.
Once you have its index. A hash function is a mathematical function which maps keys to
integers.
In bucket sort, our hash function mapped the key to a bucket based on the first letters of the
key. "Collisions" were the set of keys mapped to the same bucket. If the keys were uniformly
distributed. then each bucket contains very few keys!
The resulting short lists were easily sorted, and could just as easily be searched
We examine data structures which are designed specifically with the objective of providing
efficient insertion and find operations. In order to meet the design objective certain
concessions are made. Specifically, we do not require that there be any specific ordering of
the items in the container. In addition, while we still require the ability to remove items from
the container, it is not our primary objective to make removal as efficient as the insertion and
find operations.
Ideally we would’ build a data structure for which both the insertion and find operations are
0(1) in the worst case. However, this kind of performance can only be achieved with complete
a priori knowledge. We need to know beforehand specifically which items are to be inserted
into the container. Unfortunately, we do not have this information in the general case. So, if
we cannot guarantee 0(1) performance in the worst case, then we make it our design
objective to achieve 0(1) performance in the average case.
The constant time performance objective immediately leads us to the following conclusion:
Our implementation must be based in some way Kh element of an array in constant time,
whereas the same operation in a linked list takes O{k) time.
In the previous section, we consider two searchable containers-the ordered list and the sorted
list. In the case of an ordered list, the cost of an insertion is 0(1) and the cost of the find
operation is O(n). For a sorted list the cost of insertion is O(n) and the cost of the find
operation is O(log n) for the array implementation.
Clearly, neither the ordered list nor the sorted list meets our performance objectives. The
essential problem is that a search, either linear or binary, is always necessary. In the ordered
list, the find operation uses a linear search to locate the item. In the sorted list, a binary
search can be used to locate the item because the data is sorted. However, in order to keep
the data sorted, insertion becomes O(n).
In order to meet the performance objective of constant time insert and find operations. we
need a way to do them without performing a search. That is, given an item x, we need to be
able to determine directly from x the array position where it is to be stored.
Hash Functions: It is the job of the hash function to map keys to integers. A good hash
function:
1. Is cheap to evaluate
3. Tends to put similar keys in different parts of the tables (Remember the Shifletts!!)
The first step is usually to map the key to a big integer, for example
k=wth
1=0
This last number must be reduced to an integer whose size is between 1 and the size of our
hash table. One way is by h(k) = k mod M where M is best a large prime not too close to 2i -1,
which would just mask off the high bits. This works on the same principle as a roulette wheel!
#include<stdio.h>
#include <process.h>
#define ST ACK_SIZE 5
struct stack
int items[STACK_SIZE];
int top;
};
if ( is_full(s) )
printf("Stack Overflown");
return;
int item;
if ( is_ empty(s) )
printf("Stack Underflown");
return 0;
void display(STACK s)
int i;
if ( is_empty(&s) )
printf("Stack is emptyn");
return 0;
printf("%dn ",s.items[i];
void main()
for (;;)
scanf("%d",&choice);
switch(choice)
case 1:
scanf("%d",& item);
break;
case 2:
item = pop(&s);
if (item != 0)
break;
case 3:
display(s);
break;
default: exit(0);
}
5. Describe the theory and applications of Double Ended Queues (Deque) and circular
queues.
Ans: The double-ended queue also called Deque is discussed here. Deque is a special type of
data structure in which insertions and deletions will be done either at the front end or at the
rear end of the queue. The operations that can be performed on deques are
The three operations insert rear, delete front and display and the associated operations to
check for an underflow and overflow of queue have already been discussed in ‘ordinary
queue’. In this section, other two operations i.e., insert an item at the front end and delete an
item from the rear end are discussed.
Consider queue shown in above fig (a). Observe that, the front end identified by f is 0 and
rear end identified by r is -1. Here, an item can be inserted first by incrementing r by 1 and
then insert an item. If the front pointer f is not equal to 0 as shown in above fig. (b), an item
can be inserted by decrementing the front pointer .f by 1 and then inserting an item at that
position. Except for these conditions, it is not possible to insert an item at the front end. For
example, consider the queue shown in above figure (c). Here, an item 10 is already present in
the first position identified by f and so, it is not possible to insert an item. The complete C
function to insert an item is shown in below example. Example 1: Function to insert an item at
the front end
To delete an element from the rear end, first access the rear element and then decrement
rear end identified by r. As an element is deleted, queue may become empty. If the queue is
empty, reset the front pointer f to 0 and rear pointer r to -1 as has been done in an ordinary
queue. We delete an element only if queue is not empty. The complete C function to delete
an item from the rear end is shown in below example.
#include <stdio.h>
#include <process.h>
#define QUEUE_SIZE 5
q[++(*r)] = item;
else if ( *f ! = 0)
q[--(*f)]=item;
else
printf("Queue overflown");
return;
if ( qempty(*f, *r) )
printf("Queue underflown");
return;
if(*f> *r)
*f=O,*r=-l;
if ( qempty(*f,*r) )
printf("Queue underflown");
return;
*f = 0, *r = -1 ;
int i;
if ( qempty(f,r) )
printf("Queue is emptyn");
return;
for(i=f;i<= r; i+ +)
printf(" %dn",q[i]);
void main()
f=0; r = -1;
for (;;)
scanf("%d" ,&choice );
switch ( choice )
case 1:
scanf("%d",& item);
break;
case 2:
scanf("%d",& item);
insert_rear(item, q, &r);
break; case 3:
break;
case 4:
break;
cases 5:
display(q, f, r);
break;
default: .
exit(0);
Circular Queue: In an ordinary queue, as an item is inserted, the rear end identified by r is
incremented by 1. Once r reaches QUEUE_SIZE -1, we say queue is full. Note that even if
some elements are deleted from queue, because the rear end identified by r is still equal to
QUEUE_SIZE-l, item cannot be inserted. Pot details refer in Disadvantage of ordinary queue.
This disadvantage is overcome using circular queue. The pictorial representation of a circular
queue and its equivalent representation using an array are given side by side in below fig in
next page.
Assume that circular queue contains only one item as shown in below fig. (a). In this case, the
rear end identified by r is 0 and front end identified by f is also 0. Since rear end is
incremented while insertion, just before inserting the first item, the value ‘of r should be -1
(Note: An item is inserted only at the rear end and so, only r is incremented by 1 and not f) so
that after insertion, f and r points to an item 10. So, naturally, the initial values of f and r
should be 0 and -1.
The configuration shown in below fig. (b) is obtained after inserting 20 and 30. To insert an
item, the rear pointer r has to be incremented first. For this, any of the two statements shown
below can be used.
r = r + l or r = (r + 1) %QUEUE_SIZE
Both statements will increment r by 1. But, we prefer the second statement. We see why this
method is preferred instead of a simple statement
r= r+1
The queue shown in fig.(c) is obtained after inserting 40 and 50. Note that at this point, the
queue is full. Suppose we delete two items 10 and 20 one after the other. The resulting queue
is shown in fig. (d). Now try to insert an item 60. If the statement
r= r+1
is used to increment rear pointer, the value of r will be 5. But because this is a circular queue r
should point to 0. This can be achieved using the statement
r = (r + 1) % QUEUE_SIZE
After execution of the above statement r will be 0. If this approach is used to check for
overflow or underflow, we use a variable count that contains the number of items in the queue
at any instant. So as an item is inserted, increment count by 1 and as an item is deleted
decrement count by 1. By this it is ensured that at any point of time, count always contains the
total number of elements in the queue. So, if queue is empty, count will be 0 and if queue is
full, count will be QUEUE_SIZE. Thus we can easily implement the two functions qfull( ) and
qempty( ) and these functions are shown in below examples 1 and 2 respectively.
if ( qfull(*count) )
printf("Overflow of queuen");
return;
Note that insertion is done only when queue is not full. So, if queue is not full, to insert an
item, increment rear end identified by r by 1 and then insert. Also, as an item is inserted
update the value of count by 1. The variable count is used to check for overflow or underflow.
The function to insert an item into the queue is shown in the above example 3.
As in an ordinary queue, the element at the front end of the queue has to be deleted. ‘So,
access an item which is at the front end by specifying q[f] and update the front end identified f
to point to next front item. The front end identified by f can be incremented using the following
statement
f= (f+ 1) % QUEUE_SIZE;
As an item is deleted from a queue, the count should be decremented by 1. The complete C,
function to delete an element from the circular queue is shown in below example 4.
if ( qempty(*count) )
printf("Underflow of queuen");
return;
If queue is not empty, elements in the queue should be displayed from the front end identified
by f to the rear end identified by r. The total number of items to be displayed can be obtained
from the variable count. This can be achieved by initializing the index variable i to the front
end identified by f and incrementing i each time using the statement
i= (i + 1)% QUEUE_SIZE;
count number of times. As the index variable i point to the each item in the queue, the queue
contents can be accessed and displayed one by one. The function to display the contents of
circular queue is shown in below example 5.
6. With the help of a suitable numerical example, describe the following concepts of a
Binary Search Tree:
A) Analysis of BST
Ans: It is a directed tree in which outdegree of each node is less than or equal to two i.e., each
node in the tree can have 0, or 2 children. An empty tree is also a binary tree. A binary tree
can also be defined recursively as follows:
1. The first subset contains only one element and it is called root of the tree. If root contains
NULL it is called empty binary tree.
2. The second subset is a binary tree called left sub tree. The left sub tree can be empty.
3. The third subset is a binary tree called right sub tree. The right sub tree can be empty.
A binary tree is a tree in which no node can have more than two subtrees. In other words, a
node can have zero, one, or two sub trees. In other words A tree in which every parent has
one or two children (but not more than that) is called as binary tree.
The “root” component of binary tree is the forefother of all children. But it can have only up to
two children one “right” child and “left” child. These children can become fathers and each can
produce only two children. In fact a child can become a father, grandfather, great grandfather
and son. Fig shows five binary trees all with three nodes.
Là left Rà Right
“A child cannot have more than one father. If it is so then the tree is not a binary tree. A binary
tree node cannot have more than two subtrees.”
If the outdegree of every node in a tree is either 0 or 2, then the tree is said to be strictly
binary tree i.e., each node can have maximum two children or empty left and empty right
child. The trees shown in fig. 6.2.e and fig. 6.2.f are strictly binary trees.
Example:
A binary tree is said to be strictly binary if every non-leaf node has non-empty left and right
subtrees. Fig shows a strictly binary tree.
=>The binary tree in the above fig is not strictly binary because the non-leaf node E has no
right sub-tree and the non-leaf node C has no left sub-tree.
A strictly binary tree in which the number of nodes at any level i is 2i-1, then the tree is said to
be a complete binary tree. The tree shown in fig. 6.2.f is a strictly binary tree and at the same
time it is a complete binary tree.
Example:
……………………………………
……………………………………
……………………………………
It is clear from the figure that all the nodes in the final level d are leaf nodes and the total
number of leaf nodes is 2d. In a complete binary tree, we can easily find the number of non-
leaf nodes. Now, let us find the number of non-leaf nodes in a complete binary tree. Total
number of nodes in the complete binary tree =
2° + 21 + 22 + ………….2d.
S = a( rn- 1) 1( r- 1)
where a = 1, n = d+ 1 and r = 2
Nodes at level d are all leaf nodes. So, number of non-leaf nodes is given by 2d+1 – 1 –2d
which is equal to 2d – 1.
To insert an item
Let ‘d’ be an array, which contains only the directions where the node temp has to be
inserted. If ‘d’ contains ‘LRLR’, from the root node first moves towards left(L), then right(R),
then left(L) and finally move towards right(R). Finally if the pointer points to NULL, at that
position, node temp can be inserted otherwise, node temp can not be inserted.
To achieve this, one has to start from the root node. Let us use two pointers prev and cur
where prev always points to parent node and cur points to child node. Initially cur points to
root node and prev points to NULL. To start with, one can write the following statements.
prev = NULL
cur = root
Now keep updating the node pointed to by cur towards left if the direction is (’L ‘) otherwise,
update towards right. The pointer variable prev always points to the parent node and cur
points to the child node. Once all directions are over, if cur points to NULL, insert the node
temp towards left or right based on the last direction. Otherwise, display an error message. In
the following algorithm, an index variable i is used to access the directions. The C function to
insert a node is shown in below example
if ( root = = NULL ) return temp; /* Node is inserted for the first time */
scanf("%s", direction);
prev = NULL;
cur = root;
cur = cur->llink;
cur = cur->rlink;
freenode(temp);
`return root;
prev->llink = temp;
else
return root;
7. Explain the Bellman Ford algorithm with respect to Minimum Spanning Trees.
Ans: Spanning Trees: A spanning tree of a graph is an undirected tree consisting of only those
edges necessary to connect all the nodes in the original graph. For any pair of nodes there
exists only one path between them and the insertion of any edge to a spanning tree forms a
unique cycle. Those edges left out of the Spanning tree that were present in the original graph
connect paths together in the tree.
If a DFS is used, those edges traversed by the algorithm form the edges of the tree, referred
to as depth first spanning tree. If a BFS is used, the spanning tree is formed from those edges
traversed during the search, producing a breadth first spanning tree.
Examples:
Network: A network is a graph that has weights or costs associated with its edges. It is also
called weighted graph.
Eg.:
Minimum spanning tree: This is a spanning tree that covers all vertices of a network such
that the sum of the costs of its edges is minimum. There are two algorithms for finding the
minimum spanning tree, given a network.
Step 1: Arrange all edges in ascending order of their cost to form an input set.
Step 2: From this input set, take each edge and if it does not form a cycle, include it in the
output set, which forms the minimum spanning tree. The sum of the costs of the
edges in the output set is the least.
Note: If a vertex u is reachable from vertex w and w is reachable from u, then the path
between u and w is called a cycle. Eg. in fig. 7.10 above, the set [(1, 2) (2, 3), (3, 4),
(4, 1)] is a cycle and the superset [(1, 2) (2, 5) (5, 6) (6, 4) (4, 1)] also is a cycle.
Step 1: Input set = { (1, 3), (4, 6), (2, 5), (3, 6), (2, 3), (3, 4), (1, 4), (1, 2), (3, 5), (5, 6)}
Step 2: Output set = { (1, 3) (4, 6) (2, 5), (3, 6), (2, 3)}
initialize_single_source(G,s)
relax(u,v,w)
return FALSE
return TRUE
A) Telecommunication problem
Ans: A graph is a collection of vertices V and a collection of edges E consisting of pairs of vertices.
Think of vertices as locations. The set of vertices is the set of all the possible locations. In this
analogy, edges represent paths between pairs of those locations. The set E contains all the
paths between the locations.
Representation
The graph is normally represented using that analogy. Vertices are points or circles, edges
are lines between them.
V = {1, 2, 3, 4, 5, 6}
Each edge is a member of the set E. Note that some vertices might not be the end point of
any edge. Such vertices are termed isolated.
Sometimes, numerical values are associated with edges, specifying lengths or costs; such
graphs are called edge-weighted graphs (or weighted graphs). The value associated with an
edge is called the weight of the edge. A similar definition holds for node-weighted graphs.
Telecommunication: Given a set of computers and a set of wires running between pairs of
computers, what is the minimum number of machines whose crash causes two given
machines to be unable to communicate? (The two given machines will not crash.)
Graph: The vertices of the graph are the computers. The edges are the wires between the
computers. Graph problem: minimum dominating sub-graph.
B) Knight Moves
Ans: Given: Two squares on an 8×8 chessboard. Determine the shortest sequence of knight
moves from one square to the other.
Graph: The graph here is harder to see. Each location on the chessboard represents a
vertex. There is an edge between two positions if it is a legal knight move. Graph Problem:
Single Source Shortest Path.