0% found this document useful (0 votes)
95 views30 pages

MC0068

The document is an assignment for a data structures course asking students to answer questions about pointers in C, queues, and binary search trees. It provides four questions, each worth 10 marks, that ask students to describe concepts related to the topics and provide code examples to demonstrate the concepts. For each question, it gives partial or full answers providing explanations and code samples.

Uploaded by

karanpuri6
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
95 views30 pages

MC0068

The document is an assignment for a data structures course asking students to answer questions about pointers in C, queues, and binary search trees. It provides four questions, each worth 10 marks, that ask students to describe concepts related to the topics and provide code examples to demonstrate the concepts. For each question, it gives partial or full answers providing explanations and code samples.

Uploaded by

karanpuri6
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 30

Master of Computer Application (MCA) Semester 2 MC0068 Data Structures using C 4 Credits (Book ID: B0701 & B0702)

2) Assignment Set 1 (40 Marks) Answer all Questions Each Question Carries TEN Marks

1. Describe the following with respect to pointers in C language: a. Pointers and Arrays b. Usage of Pointers in functions c. Usage of Pointers in Arrays. Write programs in C to demonstrate the above concepts.
Ans:1 a. Pointers and Arrays There is a close association between pointers and arrays, array elements can be accessed using pointers. Example: #include <iostream.h> #include <conio.h> #include <iomanip.h> main ( ) { int a[10], *arpt, i; clrscr( ); printf( Enter arry valuesn); for (i = 0; i < 10; i + +) MC0068 Data Structures using C Name : SHIV PANKAJ Roll No.571121488

scanf(%d n ,&a[i]); /* arpt points to array */ arpt = a; /* printing by technique 1 */ for (i = 0; i < 10; i + +) printf(%d n arpt +i); /*printing by technique 2 */ for (i = 0; i < 10; i + +) printf(%d , *(arpt + +); } b. Usage of Pointers in functions Regarding their syntax, there are two different types of function pointers: On the one hand there are pointers to ordinary C functions or to static C++ member functions. On the other hand there are pointers to non-static C++ member functions. The basic difference is that all pointers to non-static member functions need a hidden argument: The this-pointer to an instance of the class. Always keep in mind: These two types of function pointers are incompatible with each other. Since a function pointer is nothing else than a variable, it must be defined as usual. In the following example we define three function pointers named pt2Function, pt2Member and pt2ConstMember. They point to functions, which take one float and two char and return an int. In the C++ example it is assumed, that the functions, our pointers point to, are (nonstatic) member functions of TMyClass. Example: int (*pt2Function)(float, char, char) = NULL; if(pt2Function >0){ if(pt2Function == &DoIt) printf("Pointer points to DoIt\n"); } else printf("Pointer not initialized!!\n"); MC0068 Data Structures using C Name : SHIV PANKAJ Roll No.571121488

c. Usage of Pointers in Arrays 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 : 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

MC0068 Data Structures using C

Name : SHIV PANKAJ Roll No.571121488

2. Describe the following with respect to queues with suitable programming examples: a. Queues and its basic operations b. Double ended queues c. Circular Queues
Ans:2 a. Queues and its basic operations b. Double Ended Queues Double Ended Queues (Deque):- Like an ordinary queue, a double-ended queue is a container. It supports the following operations: enq_front, enq_back, deq_front, deq_back, and empty. By choosing a subset of these operations, you can make the double-ended queue behave like a stack or like a queue. For instance, if you use only enq_front and deq_front you get a stack, and if you use only enq_front and deq_back you get a queue. By now, the reader should be used to using header objects in order to obtain uniform reference semantics. We will therefore go directly to a version of the double-ended queue with a separate header file and implementation file. Example:#include "dqueue.h" #include "dlist.h" #include < stdlib.h> struct dqueue { dlist head; dlist tail; }; dqueue dq_create(void) { dqueue q = malloc(sizeof(struct dqueue)); q -> head = q -> tail = NULL; return q; } MC0068 Data Structures using C Name : SHIV PANKAJ Roll No.571121488

int dq_empty(dqueue q) { return q -> head == NULL; } void dq_enq_front(dqueue q, void *element) { if(dq_empty(q)) q -> head = q -> tail = dcons(element, NULL, NULL); else { q -> head -> prev = dcons(element, NULL, q -> head); q -> head -> prev -> next = q -> head; q -> head = q -> head -> prev; } } void dq_enq_back(dqueue q, void *element) { if(dq_empty(q)) q -> head = q -> tail = dcons(element, NULL, NULL); else { q -> tail -> next = dcons(element, q -> tail, NULL); q -> tail -> next -> prev = q -> tail; q -> tail = q -> tail -> next; } } void * dq_deq_front(dqueue q) { assert(!empty(q)); { dqueue temp = q -> head; void *element = temp -> element; q -> head = q -> head -> next; free(temp); if(q -> head == NULL) q -> tail = NULL; else q -> head -> prev = NULL; MC0068 Data Structures using C Name : SHIV PANKAJ Roll No.571121488

return element;

void * dq_deq_back(dqueue q) { assert(!empty(q)); { dqueue temp = q -> tail; void *element = temp -> element; q -> tail = q -> tail -> prev; free(temp); if(q -> tail == NULL) q -> head = NULL; else q -> tail -> next = NULL; return element; } } c. circular queues circular queues:- A circular queue is a particular implementation of a queue. It is very efficient. It is also quite useful in low level code, because insertion and deletion are totally independant, which means that you don't have to worry about an interrupt handler trying to do an insertion at the same time as your main code is doing a deletion. Example:#include <stdio.h> #include <stdlib.h> #define MAX 10 void insert(int queue[], int *rear, int front, int value) { *rear= (*rear +1) % MAX; if(*rear == front) { printf("The queue is full can not insert a value\n"); exit(0); } queue[*rear] = value; } MC0068 Data Structures using C Name : SHIV PANKAJ Roll No.571121488

void delete(int queue[], int *front, int rear, int * value) { if(*front == rear) { printf("The queue is empty can not delete a value\n"); exit(0); } *front = (*front + 1) % MAX; *value = queue[*front]; } void main() { int queue[MAX]; int front,rear; int n,value; front=0; rear=0; insert(queue,&rear,front,1); insert(queue,&rear,front,2); insert(queue,&rear,front,3); insert(queue,&rear,front,4); delete(queue,&front,rear,&value); printf("The value deleted is %d\n",value); delete(queue,&front,rear,&value); printf("The value deleted is %d\n",value); delete(queue,&front,rear,&value); printf("The value deleted is %d\n",value);

3. Describe the following with respect to a Binary Search Tree (BST): a. Analyzing the BST Search Algorithm b. Inserting Nodes into a BST c. The Order of Insertion Determines the BST's Topology d. Deleting Nodes from a BST
Ans:3 a. Analyzing the BST Search Algorithm MC0068 Data Structures using C Name : SHIV PANKAJ Roll No.571121488

carry out an Analysis of this method to determine its time complexity. Since there are no for loops, we can not use summations to express the total number of operations. Let us examine the operations for a specific case, where the number of elements in the array n is 64. When n= 64 BinarySearch is called to reduce size to n=32 When n= 32 BinarySearch is called to reduce size to n=16 When n= 16 BinarySearch is called to reduce size to n=8 When n= 8 BinarySearch is called to reduce size to n=4 When n= 4 BinarySearch is called to reduce size to n=2 When n= 2 BinarySearch is called to reduce size to n=1 int BinarySearch (int A[ ], int n, int K) { int L=0, Mid, R= n-1; while (L<=R) { Mid = (L +R)/2; if ( K= =A[Mid] ) return Mid; else if ( K > A[Mid] ) L = Mid + 1; else R = Mid 1 ; } return 1 ; } b. Inserting Nodes into a BST:- To insert a node into a BST 1. find a leaf set the appropriate place and 2. connect the node to the parent of the leaf. TREE-INSERT (T, z) y NIL x root [T] while x NIL do yx if key [z] < key[x] then x left[x] else x right[x] p[z] y if y = NIL then root [T] z else if key [z] < key [y] MC0068 Data Structures using C Name : SHIV PANKAJ Roll No.571121488

then left [y] z else right [y] z Like other primitive operations on search trees, this algorithm begins at the root of the tree and traces a path downward. Clearly, it runs in O(h) time on a tree of height h. d. Deleting Nodes from a BST Remove operation on binary search tree is more complicated, than add and search. There are Two possible cases to consider:

Deleting a leaf (node with no children): Deleting a leaf is easy, as we can simply remove it from the tree. Deleting a node with one child: Delete it and replace it with its child. Deleting a node with two children.

As with all binary trees, a node's in-order successor is the left-most child of its right subtree, and a node's in-order predecessor is the right-most child of its left subtree. In either case, this node will have zero or one children. Delete it according to one of the two simpler cases above. 1. Node to be removed has no children. This case is quite simple. Algorithm sets corresponding link of the parent to NULL and disposes the node. Example. Remove -4 from a BST.

2. Node to be removed has one child. 3. It this case, node is cut from the tree and algorithm links single child (with it's subtree) directly to the parent of the removed node. Example. Remove 18 from a BST. MC0068 Data Structures using C Name : SHIV PANKAJ Roll No.571121488

4. Node to be removed has two children.

MC0068 Data Structures using C

Name : SHIV PANKAJ Roll No.571121488

This is the most complex case. To solve it, let us see one useful BST property first. We are going to use the idea, that the same set of values may be represented as different binary-search trees. For example those BSTs:

contains the same values {5, 19, 21, 25}. To transform first tree into second one, we can do following: 1. choose minimum element from the right subtree (19 in the example); 2. replace 5 by 19; 3. hang 5 as a left child. The same approach can be utilized to remove a node, which has two children: 4. find a minimum value in the right subtree; 5. replace value of the node to be removed with found minimum. Now, right subtree contains a duplicate! 6. apply remove to the right subtree to remove a duplicate. Notice, that the node with minimum value has no left child and, therefore, it's removal may result in first or second cases only. 1. Example. Remove 12 from a BST.

MC0068 Data Structures using C

Name : SHIV PANKAJ Roll No.571121488

Find minimum element in the right subtree of the node to be removed. In current example it is 19.

Replace 12 with 19. Notice, that only values are replaced, not nodes. Now we have two nodes with the same value.

MC0068 Data Structures using C

Name : SHIV PANKAJ Roll No.571121488

Remove 19 from the left subtree.

4. Discuss the following with respect to Splay Trees: a. Balance Theorem b. Strong Access Lemma c. Static Optimality Theorem d. Static Finger Theorem
Ans:4 MC0068 Data Structures using C Name : SHIV PANKAJ Roll No.571121488

a. Balance Theorem BALANCE THEOREM: The total access time is O(m + (n+m) log(n)) PROOF: Assign a weight of 1/n to each item. Then the total weight is 1 and the rank of the root is 0. So the access lemma bounds the amortized cost of an access by 3log(n)+1. Summing this over all accesses gives O(m + m log(n)). For any node i: 0 >= r(i) >= log(1/n) Write this as: 0 <= -r(i) <= log(n) Thus, the net decrease in the potential is at most log(n) per node, and totals to n log(n). QED. b. Strong Access Lemma Strong Access Lemma: The number of rotations done when splaying node x in a tree with root t is at most 3(r(t)-r(x))+1.Here r(t) and r(x) denote the continuous definition of rank. The bound in this lemma is approximately a factor of two tighter than the previous one. Throughout these notes, we'll use the strong access lemma and the continuous definition of rank. The main advantage here is simply that it means we can stop writing floors, because in these notes we're only trying to prove big-oh bounds. Let's rewrite the access lemma a bit. Let w(x) be the weight of a nodex. r(x) is log(w(x) + total weight of other descendants of x). Since the weight of the descendants of x is a positive number we have: r(x) >= log(w(x)) So the amortized cost of a splay is bounded by 3(r(t) - log(w(x))) + 1. The theorems below concern bounds on the running times of sequences of accesses in splay trees. (The set of nodes in these trees is static.)We'll use the rotation bound of the strong access lemma as our measure ofthe running time of a sequence of operations. Recall the following consequence of the definition of amortized cost: total real cost = total amortized cost + initial potential - final potential To bound the cost of a sequence, we'll bound the total amortized cost (using the access lemma) and bound the total decrease in potential that could result from the sequence. NOTATION: There will be n items in the tree, numbered 1...n. MC0068 Data Structures using C Name : SHIV PANKAJ Roll No.571121488

The letter i will indicate an index into this list of items. We'll be considering a sequence of m accesses, and the index j will refer to one of these acceses. Let i[j] refer to the index of the jth access. c. Static Optimality Theorem STATIC OPTIMALITY THEOREM: Let q(i) be the number of times item i is accessed. Let m = Sum q(i) be the number of accesses. Assume that q(i) > 0 for each i. Then the total cost of the sequence is: m O(m + Sum log ------- ) j q(i[j]) PROOF: Choose w(i) (the weight of item i) to be q(i)/m. The total weight of all items is 1. So the amortized cost of an access to element i is at most: 3(r(root) - log(w(i))) + 1 = 3 (- log(q(i)/m)) +1 = 3 log(m/q(i))+1 Summing this, we see that the amortized cost satisfies the bound stated in the theorem. It remains to bound the decrease in potential. Each item contributes its rank to the potential. We have the following bounds on ranks: 0 >= r(i) = log(size(i)) >= log(w(i)) Rewriting this: 0 <= -r(i) <= log(1/w(i)) The the maximum amount that a node's potential can decrease is just log(1/w(i)), which is log(m/q(i)). Summing this we see: total potential decrease <= Sum log(m/q(i)) i Since each element is accessed at least once, the terms in this summation are a subset of the terms in the bound we're tryig to prove in the theorem. So this additional cost can be absorbed into the big-oh. QED. NOTE 1: The reason we need to assume that each element is accessed at least once is to guard against the possibility that we start out with a very bad tree which contains millions of elements near the top of the tree that are never accessed, and we are forced to incur a cost to get by them.

MC0068 Data Structures using C

Name : SHIV PANKAJ Roll No.571121488

NOTE 2: This is called the static optimatilty theorem because the static tree that is constructed to be optimal for this specific access sequence will incur a cost of (log(m/q(i))) to access the item i. d. Static Finger Theorem STATIC FINGER THEOREM: Let f be a specific element called the finger. Then the following is a bound on the cost of splaying a sequence: O(m + n log(n) + Sum log (|f - i[j]| + 1)) j NOTE: |f-i| is the distance in the symmetric ordering of the items between the finger and item i. PROOF: Assign the weights w(i) as follows: 1 w(i) = ---------------2 (|f-i| + 1) Since Sum 1/n^2 (n from 1 to infinity) is a constant (pi^2/6) we see that the sum of all the weights is bouned by a constant (at most twice this). Let's look at the amortized cost of an access. Recall: 3(r(t) - log(w(x))) + 1. The term r(t), meaning the rank of the root, is just bounded by a constant, and sums to O(m). The 1 term also sums to O(m). The -log(w(x)) term can be written: 1 -log ( ---------------- ) 2 (|f-i| + 1) = 2 log (|f-i|+1) Combining these estimates shows that the amortized cost is bounded by the summation stated in the theorem. It remains to bound the decrease in potential. What bound can we put on the rank of an item i? 2 pi^2 1 log( ------ ) >= r(i) >= 2 log (-------) 6 |f-i|+1 MC0068 Data Structures using C Name : SHIV PANKAJ Roll No.571121488

Negating this we get: 2 pi^2 - log( ------ ) <= -r(i) <= 2 log (|f-i|+1) 6 So the potential change of a node is bounded by O(log n).This contributes O(n log n) to the total real cost. QED.

MC0068 Data Structures using C

Name : SHIV PANKAJ Roll No.571121488

Master of Computer Application (MCA) Semester 2 MC0068 Data Structures using C 4 Credits (Book ID: B0701 & B0702) Assignment Set 2 (40 Marks) Answer all Questions Each Question Carries TEN Marks

1. Describe the following operations with programming examples for a Single circular linked list: a. Insert a node at the front end b. Insert a node at the rear end c. Delete a node from the front end d. Delete a node from the rear end
Ans:1 A singly linked circular list is a linked list where the last node in the list points to the first node in the list. A circular list does not contain NULL pointers. With a circular list, a pointer to the last node gives easy access also to the first node, by following one link. Thus, in applications that require access to both ends of the list (e.g., in the implementation of a queue), a circular structure allows one to handle the structure by a single pointer, instead of two. A circular list can be split into two circular lists, in constant time, by giving the addresses of the last node of each piece. The operation consists in swapping the contents of the link fields of those two nodes. Applying the same operation to any two nodes in two distinct lists joins the two list into one. This property greatly simplifies some algorithms and data structures, such as the quad-edge and face-edge. The simplest representation for an empty circular list (when such a thing makes sense) is a null pointer, indicating that the list has no nodes. With this choice, many algorithms have to test for this special case, and handle it separately. By contrast, the use of null to denote an empty linear list is more natural and often creates fewer special cases.

MC0068 Data Structures using C

Name : SHIV PANKAJ Roll No.571121488

Insert a node at the front end: Consider the list contains 4 nodes and a pointer variable last contains address of the last node.

20

45

10

80

Step 1: To insert an item 50 at the front of the list, obtain a free node temp from the availability list and store the item in info field. This can be accomplished using the following statements Temp=getnode(); Temp->info=item; Step 2: Copy the address of the first node(i.e. last->link) into link field of newly obtained node temp and the statement to accomplish this task is Temp->link=last->link. Step 3: Establish a link between the newly created node temp and the last node. This is achieved by copying the address of the node temp into link field of last node. The corresponding code for this is Last->link=temp; Now, an item is successfully inserted at the front of the list. All these steps have been designed by assuming the list is already existing. If the list is empty, make temp itself as the last node and establish a link between the first node and the last node. Repeatedly insert the items using the above procedure to create a list. Function to insert an item at the front end of the list. NODE insert_front(int item, NODE last) { NODE temp; Temp=getnode(); Temp->info=item; If(last==NULL) Last=temp; Else temp->link=last->link; Last->link=temp; Return last; } Insert a node at the rear end: Consider the list contains 4 nodes and last is a pointer variable that contains the address of the last node. MC0068 Data Structures 50 20 using C 45 10 Name : SHIV PANKAJ Roll No.571121488

Let us insert the item 80 at the end of this list. Step 1:Obtain a free node temp from the availability list and store the item in info field. This can be accomplished using the following statements Temp=getnode(); Temp->info=item; Step 2: Copy the address of the first node(i.e. last->link) into link field of newly obtained node temp and the statement to accomplish this task is Temp-> link=last->link Step 3: Establish a link between the newly created node temp and the last node. This is achieved by copying the address of the node temp into link field of last node. The corresponding code for this is Last->link=temp; Step 4: The new node is made as the last node using the statement: Return temp; These steps have designed by assuming the list already exists. Function to insert an item at the rear end of the list. NODE insert_rear(int item, NODE last) { NODE temp; Temp=getnode(); Temp->info=item; If(last==NULL) Last=temp; Else Emp->link=last->link; Last->link=temp; Retrun temp; }

2. Write functions in C to find the minimum cost spanning tree using the following algorithms: a. Prims algorithm b. Kruskals Algorithm
Ans:2

a. Prims algorithm
MC0068 Data Structures using C Name : SHIV PANKAJ Roll No.571121488

#define MAX 10 #define TEMP 0 #define PERM 1 #define FALSE 0 #define TRUE 1 #define infinity 9999 struct node { int predecessor; int dist; /*Distance from predecessor */ int status; }; struct edge { int u; int v; }; int adj[MAX][MAX]; int n; main() { int i,j; int path[MAX]; int wt_tree,count; struct edge tree[MAX]; create_graph(); printf("Adjacency matrix is :\n"); display(); count = maketree(tree,&wt_tree); printf("Weight of spanning tree is : %d\n", wt_tree); printf("Edges to be included in spanning tree are : \n"); for(i=1;i<=count;i++) { printf("%d->",tree[i].u); printf("%d\n",tree[i].v); } }/*End of main()*/ MC0068 Data Structures using C Name : SHIV PANKAJ Roll No.571121488

create_graph() { int i,max_edges,origin,destin,wt; printf("Enter number of vertices : "); scanf("%d",&n); max_edges=n*(n-1)/2; for(i=1;i<=max_edges;i++) { printf("Enter edge %d(0 0 to quit) : ",i); scanf("%d %d",&origin,&destin); if((origin==0) && (destin==0)) break; printf("Enter weight for this edge : "); scanf("%d",&wt); if( origin > n || destin > n || origin<=0 || destin<=0) { printf("Invalid edge!\n"); i--; } else { adj[origin][destin]=wt; adj[destin][origin]=wt; } }/*End of for*/ if(i { printf("Spanning tree is not possible\n"); exit(1); } }/*End of create_graph()*/ display() { int i,j; for(i=1;i<=n;i++) { for(j=1;j<=n;j++) printf("%3d",adj[i][j]); printf("\n"); } }/*End of display()*/ MC0068 Data Structures using C Name : SHIV PANKAJ Roll No.571121488

int maketree(struct edge tree[MAX],int *weight) { struct node state[MAX]; int i,k,min,count,current,newdist; int m; int u1,v1; *weight=0; /*Make all nodes temporary*/ for(i=1;i<=n;i++) { state[i].predecessor=0; state[i].dist = infinity; state[i].status = TEMP; } /*Make first node permanent*/ state[1].predecessor=0; state[1].dist = 0; state[1].status = PERM; /*Start from first node*/ current=1; count=0; /*count represents number of nodes in tree */ while( all_perm(state) != TRUE ) /*Loop till all the nodes become PERM*/ { for(i=1;i<=n;i++) { if ( adj[current][i] > 0 && state[i].status == TEMP ) { if( adj[current][i] < state[i].dist ) { state[i].predecessor = current; state[i].dist = adj[current][i]; } } }/*End of for*/ /*Search for temporary node with minimum distance and make it current node*/ min=infinity; for(i=1;i<=n;i++) { if(state[i].status == TEMP && state[i].dist < min) { min = state[i].dist; MC0068 Data Structures using C Name : SHIV PANKAJ Roll No.571121488

current=i; } }/*End of for*/ state[current].status=PERM; /*Insert this edge(u1,v1) into the tree */ u1=state[current].predecessor; v1=current; count++; tree[count].u=u1; tree[count].v=v1; /*Add wt on this edge to weight of tree */ *weight=*weight+adj[u1][v1]; }/*End of while*/ return (count); }/*End of maketree()*/ /*This function returns TRUE if all nodes are permanent*/ int all_perm(struct node state[MAX] ) { int i; for(i=1;i<=n;i++) if( state[i].status == TEMP ) return FALSE; return TRUE; }/*End of all_perm()*/

b. Kruskals Algorithm
#include #include #include #define ESIZE 20 #define VSIZE 40 typedef struct node { int sv,dv,wt; }edgelist; edgelist graphmat[ESIZE]; edgelist ktree[ESIZE]; int nvertex,nedges,oedges,adjmat[VSIZE][VSIZE],parent[VSIZE]; int checkdir(); void creategraph(); void sortgraph(edgelist graphmat[ESIZE],int nedges); MC0068 Data Structures using C Name : SHIV PANKAJ Roll No.571121488

int viewsortgraph(edgelist graphmat[ESIZE],int nedges); int viewsortgraph1(edgelist graphmat[ESIZE],int nedges); void kruskal(edgelist graphmat[ESIZE],edgelist ktree[ESIZE]); void converttograph(int adjmat[VSIZE][VSIZE],int n,edgelist graphmat[ESIZE]); void main() { int wt; clrscr(); cout<<"\n\n\t\t KRUSKAL ALGORITHM"; cout<<"\n\n\t\t *****************\n\n\n"; creategraph(); converttograph(adjmat,nvertex,graphmat); viewsortgraph1(graphmat,nedges); sortgraph(graphmat,nedges); viewsortgraph1(graphmat,nedges); kruskal(graphmat,ktree); cout<<"\n\n Final kruskal tree "; cout<<"\n ~~~~~~~~~~~~~~~~~~\n\n\n"; wt=viewsortgraph(ktree,oedges); cout<<"\n\n Weight of the spanning tree is:"< getch(); } void creategraph() { int r,c; cout<<"\n\n\n Enter the no. of vertices of weighted graph:"; cin>>nvertex; cout<<"\n Enter the cost matrix\n\n"; for(r=0;r for(c=0;c cin>>adjmat[r][c]; } int checkdir() { int r,c; for(r=0;r for(c=0;c if(adjmat[r][c]!=adjmat[c][r]) return 1; return 0; } void converttograph(int adjmat[VSIZE][VSIZE],int n,edgelist graphmat[ESIZE]) { int r,c; nedges=0; MC0068 Data Structures using C Name : SHIV PANKAJ Roll No.571121488

for(r=0;r for(c=(checkdir()?0:r+1);c if(adjmat[r][c]!=0) { graphmat[nedges].sv=r+1; graphmat[nedges].dv=c+1; graphmat[nedges].wt=adjmat[r][c]; nedges++; } } void sortgraph(edgelist graphmat[ESIZE],int nedges) { int i,j; edgelist te; for(i=0;i for(j=i+1;j if(graphmat[i].wt>graphmat[j].wt) { te=graphmat[i]; graphmat[i]=graphmat[j]; graphmat[j]=te; } } int viewsortgraph1(edgelist graphmat[ESIZE],int nedges) { int ed,wt=0; for(ed=0;ed { wt=wt+graphmat[ed].wt; } return wt; } int viewsortgraph(edgelist graphmat[ESIZE],int nedges) { int ed,wt=0; for(ed=0;ed { cout<<"\n v"<<<"to v"<<<" -->"< wt=wt+graphmat[ed].wt; } return wt; } void kruskal(edgelist graphmat[ESIZE],edgelist ktree[ESIZE]) { int ed=0,v,v1,v2,pv1,pv2; MC0068 Data Structures using C Name : SHIV PANKAJ Roll No.571121488

while(oedges { v1=graphmat[ed].sv; v2=graphmat[ed].dv; while(v1!=0) { pv1=v1; v1=parent[v1]; } while(v2!=0) { pv2=v2; v2=parent[v2]; } if(pv1!=pv2) { ktree[oedges++]=graphmat[ed]; parent[pv2]=pv1; } ed++; } }

3. Discuss the following with respect to Special Graphs: a. Rooted tree b. Forest c. Complete Graph d. Bipartite Graph
Ans:3 a. Rooted tree In a rooted tree, the vertices adjacent to the root vertex are called its children. The children of the root are said to be on level 1. The root vertex is the parent vertex of the vertices on level 1. In the same way, if a vertex v is at level i, then the vertices other than the parent vertex of v that are adjacent to v are the children of v. The children of v are at level i+1 and v is their parent vertex. Note that the number of levels depends on which vertex is chosen to be the root. The number of levels is the height of the tree. Vertices that have no children are called leaves. The vertices that are not leaves are said to be internal vertices. The root counts as an internal vertex. If all the internal vertices of a tree have the same number, say n, of vertices then it is an nary tree. A n-ary tree with n=2 is called a binary tree. Figure 32.1 shows a binary tree with three levels. The leaves of the tree are vertices 8, 9, 5, 6, 10, 11. MC0068 Data Structures using C Name : SHIV PANKAJ Roll No.571121488

b. Forest A forest is an undirected graph, all of whose connected components are trees; in other words, the graph consists of a disjoint union of trees. Equivalently, a forest is an undirected cycle-free graph. As special cases, an empty graph, a single tree, and the discrete graph on a set of vertices (that is, the graph with these vertices that has no edges), all are examples of forests. The term hedge sometimes refers to an ordered sequence of trees. c. Complete Graph A complete graph is a graph where every vertex is adjacent to every other vertex. A complete graph on n vertices is denoted by Kn (or sometimes by K(n)). So, for example, figure 4.1 is the graph K5.

d. Bipartite Graph A bipartite graph is a graph G whose vertex set V can be partitioned into two non empty sets V1 and V2 in such a way that every edge of G joins a vertex in V1 to a vertex in V2. An alternative way of thinking about it is that if you were to color the vertices in V1 one color and those in V2 another color then adjacent vertex would have different colors. A non-null graph is bipartite if and only if its chromatic number is 2. A null graph with more than one vertex is trivially bipartite as you can partition the vertex set any way you lik MC0068 Data Structures using C Name : SHIV PANKAJ Roll No.571121488

4. Discuss the following theorems with respect to Splay Trees: a. Balance Theorem b. Dynamic Finger Theorem
Ans:4 A splay tree is a self-balancing binary search tree with the additional property that recently accessed elements are quick to access again. It performs basic operations such as insertion, look-up and removal in O(log(n)) amortized time. For many non-uniform sequences of operations, splay trees perform better than other search trees, even when the specific pattern of the sequence is unknown. The splay tree was invented by Daniel Sleator and Robert Tarjan. All normal operations on a binary search tree are combined with one basic operation, called splaying. Splaying the tree for a certain element rearranges the tree so that the element is placed at the root of the tree. One way to do this is to first perform a standard binary tree search for the element in question, and then use tree rotations in a specific fashion to bring the element to the top. Alternatively, a top-down algorithm can combine the search and the tree reorganization into a single phase. Good performance for a splay tree depends on the fact that it is self-balancing, and indeed self optimizing, in that frequently accessed nodes will move nearer to the root where they can be accessed more quickly. This is an advantage for nearly all practical applications, and is particularly useful for implementing caches and garbage collection algorithms; however it is important to note that for uniform access, a splay tree's performance will be considerably (although not asymptotically) worse than a somewhat balanced simple binary search tree. Splay trees also have the advantage of being considerably simpler to implement than other self-balancing binary search trees, such as red-black trees or AVL trees, while their average-case performance is just as efficient. Also, splay trees do not need to store any bookkeeping data, thus minimizing memory requirements. However, these other data structures provide worst-case time guarantees, and can be more efficient in practice for uniform access. One worst case issue with the basic splay tree algorithm is that of sequentially accessing all the elements of the tree in the sorted order. This leaves the tree completely unbalanced (this takes n accesses - each a O(log n) operation). Re-accessing the first item triggers an operation that takes O(n) operations to rebalance the tree before returning the first item. This is a significant delay for that final operation, although the amortized performance over the entire sequence is actually O(log n). However, recent research shows that randomly rebalancing the tree can avoid this unbalancing effect and give similar performance to the other self-balancing algorithms. MC0068 Data Structures using C Name : SHIV PANKAJ Roll No.571121488

a. Balance Theorem The cost of performing the sequence S is O(m(logn + 1) + nlogn). In other words, splay trees perform as well as static balanced binary search trees on sequences of at least n accesses. b. Dynamic Finger Theorem Dynamic Finger Theorem :- A simple amortized analysis of static splay trees can be carried out using the potential method. Suppose that size(r) is the number of nodes in the subtree rooted at r (including r) and rank(r) = log2(size(r)). Then the potential function P(t) for a splay tree t is the sum of the ranks of all the nodes in the tree. This will tend to be high for poorly-balanced trees, and low for well-balanced trees. We can bound the amortized cost of any zig-zig or zig-zag operation by: amortized cost = cost + P(tf) - P(ti) 3(rankf(x) - ranki(x)), where x is the node being moved towards the root, and the subscripts "f" and "i" indicate after and before the operation, respectively. When summed over the entire splay operation, this telescopes to 3(rank(root)) which is O(log n). Since there's at most one zig operation, this only adds a constant. Dynamic Finger Theorem: The cost of performing S is O(m+n log n + m/i=1 log( |I,j+1 I,j + 1 )).

MC0068 Data Structures using C

Name : SHIV PANKAJ Roll No.571121488

You might also like