You are on page 1of 12

July 2011 Master of Computer Science (MSCCS) Semester 1 MC0068 Data Structures using C 4 Credits (Book ID: B0701

01 & B0702) Assignment Set 2 (40 Marks)


Answer all Questions Book ID: B0701 Q.1) Explain the double ended queue with the help of suitable example. Each Question carries Ten Marks

Double-ended queue is an abstract data structure that implements a queue for which elements can only be added to or removed from the front (head) or back (tail). It is also often called a head-tail linked list. There are at least two common ways to efficiently implement a deque: with a modified dynamic array or with a doubly linked list. The dynamic array approach uses a variant of a dynamic array that can grow from both ends, sometimes called array deques. These array deques have all the properties of a dynamic array, such as constant time random access, good locality of reference, and inefficient insertion/removal in the middle, with the addition of amortized constant time insertion/removal at both ends, instead of just one end. Three common implementations include: Storing deque contents in a circular buffer, and only resizing when the buffer becomes completely full. Allocating deque contents from the center of the underlying array, and resizing the underlying array

This decreases the frequency of resizing, but requires an expensive branch instruction for indexing. when either end is reached. This approach may require more frequent resizing and waste more space, particularly when elements are only inserted at one end. Storing contents in multiple smaller arrays, allocating additional arrays at the beginning or end as needed. Indexing is implemented by keeping a dynamic array containing pointers to each of the smaller arrays. Distinctions and sub-types This differs from the queue abstract data type or First-In-First-Out List (FIFO), where elements can only be added to one end and removed from the other. This general data class has some possible sub-types: An input-restricted deque is one where deletion can be made from both ends, but insertion can only be An output-restricted deque is one where insertion can be made at both ends, but deletion can be made made at one end. from one end only. Both the basic and most common list types in computing, queues and stacks can be considered specializations of deques, and can be implemented using deques. Operations The following operations are possible on a deque: operation insert element at back insert element at front remove last element remove first element C push_back push_front pop_back pop_front

Page 1 of 12

Roll No. 521126647

July 2011 Master of Computer Science (MSCCS) Semester 1 MC0068 Data Structures using C 4 Credits (Book ID: B0701 & B0702) Assignment Set 2 (40 Marks)
examine last element examine first element Applications One example where a deque can be used is the A-Steal job scheduling algorithm. This algorithm implements task scheduling for several processors. A separate deque with threads to be executed is maintained for each processor. To execute the next thread, the processor gets the first element from the deque (using the "remove first element" deque operation). If the current thread forks, it is put back to the front of the deque ("insert element at front") and a new thread is executed. When one of the processors finishes execution of its own threads (i.e. its deque is empty), it can "steal" a thread from another processor: it gets the last element from the deque of another processor ("remove last element") and executes it. back front

Example : C program to Implement double-ended queue


#include <stdio.h> #include <process.h> #define QUEUE_SIZE 5 int qfull(int r) { /* returns true if queue is full otherwise false */ return ( r == QUEUE_SIZE-1 ) ? 1: 0; } int qempty(int f, int r) { return ( f > r) ? 1 : 0; /* returns true if queue is empty otherwise returns false */ } void insert_rear (int item, int q[], int *r) { if ( qfull(*r) ) /* Is queue full ? */ { printf("Queue overflow\n"); return; } /* Queue is not full */

Page 2 of 12

Roll No. 521126647

July 2011 Master of Computer Science (MSCCS) Semester 1 MC0068 Data Structures using C 4 Credits (Book ID: B0701 & B0702) Assignment Set 2 (40 Marks)
q[+ +(*r)] = item; /* Update rear pointer and insert a item */ } void delete_front(int q[], int *f, int *r) { if ( qempty(*f, *r) ) { printf("Queue underflow\n"); return; } printf("The element deleted is %d\n", q[(*f)+ +]); if(*f> *r) { *f=O,*r=-l; } } void display(int q[], int f, int r) { int i; if ( qempty(f,r) ) { printf("Queue is empty\n"); return; } printf("Contents of queue is\n"); for(i=f;i<= r; i+ +) printf(" %d\n",q[i]); } void insert_front(int item, int q[ ], int *f, int *r) { if( *f= = 0 && *r = = -1) q[++(*r)] = item; else if ( *f ! = 0) q[--(*f)]=item;

Page 3 of 12

Roll No. 521126647

July 2011 Master of Computer Science (MSCCS) Semester 1 MC0068 Data Structures using C 4 Credits (Book ID: B0701 & B0702) Assignment Set 2 (40 Marks)
else printf("Front insertion not possible\n"); } void delete_rear(int q[],int *f, int *r) { if ( qempty(*f,*r) ) { printf("Queue underflow\n"); return; } printf("The element deleted is %d\n".q[(*r)--]); if (*f > *r) { *f = 0, *r = -1 ; } } void main() { int choice,item,f,r,q [10]; f=0; r = -1; for (;;) { printf(" 1:Insert_front 2:lnsert_rear\n"); printf("3: Delete_front 4: Delete_rear\n" ); printf("5: Display 6:Exit\n"); printf("Enter the choice\n"); scanf("%d" ,&choice ); switch ( choice ) { case 1: printf("Enter the item to be inserted\n"); scanf("%d",& item); insert_ front(item, q, &f, &r); break;

Page 4 of 12

Roll No. 521126647

July 2011 Master of Computer Science (MSCCS) Semester 1 MC0068 Data Structures using C 4 Credits (Book ID: B0701 & B0702) Assignment Set 2 (40 Marks)
case 2: printf("Enter the item to be inserted\n"); scanf("%d",& item); insert_rear(item, q, &r); break; case 3: delete _front(q, &f, &r); break; case 4: delete_rear(q, &f, &r); break; cases 5: display(q, f, r); break; default: . exit(0); } } } Q.2) Explain Insert/Delete a node at the rear, front end from circular singly linked list. The list contains 4 nodes and a pointer variable last contains address of the last node contains address of the last node.

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 as shown in dotted lines in above fig. (b). This can be accomplished using the following statements temp = getnode( );

Page 5 of 12

Roll No. 521126647

July 2011 Master of Computer Science (MSCCS) Semester 1 MC0068 Data Structures using C 4 Credits (Book ID: B0701 & B0702) Assignment Set 2 (40 Marks)
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 that the list already exists. If the list is empty, make temp it 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. The C function to insert an item at the front of the circular linked list is shown in below example. Function to insert an item at the front end of the list. NODE insert_ front (int item, NODE last) { NODE temp; temp = getnode( ); /* Create a new node to be inserted */ temp->info = item; if (last = = NULL) /* Make temp as the first node */ last = temp; else temp->link = last->link; last->link = temp; /* link last node to first node */ return last; /* Return the last node */ } Insert a node at the rear end Consider the list shown in below fig. (a). This list contains 4 nodes and last is a pointer variable that contains the address of the last node. Let us insert the item 80 at the end of this list. After successfully inserting 80, the list shown in fig.(c) is obtained.

Following steps shown below to insert an item at the rear end of the list.

Page 6 of 12

Roll No. 521126647

July 2011 Master of Computer Science (MSCCS) Semester 1 MC0068 Data Structures using C 4 Credits (Book ID: B0701 & B0702) Assignment Set 2 (40 Marks)
Step 1: Obtain a free node temp from the availability list and store the item in info field as shown in dotted lines in fig. (b). 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; /* make new node as the last node */ These steps have been designed by assuming the list is already existing. If the list is empty make temp itself as the-first node as well as the last node. The C function for this is shown in below example. Function to insert an item at the rear end of the list NODE insert_ rear (int item, NODE last) { NODE temp; temp = getnode( ); /* Create a new node to be inserted */ temp->info = item; if ( last == NULL) /* Make temp as the first node */ Data Structures using C Unit 5 Sikkim Manipal University Page No.: 153 last = temp; else /*Insert at the rear end */ temp->link = last->link; last->link = temp; /* link last node to first node */ return temp; /* Make the new node as the last node */ } Note: Compare the functions insert_ front( ) and insert_ rear( ). All statements in both the functions are same except that in insert_front( )function, address of last node is returned and in the function insert_rear( ) address of the new node is returned. Delete a node from the front end Consider the list shown in below figure. This list contains 5 nodes and last is a pointer variable that contains the address of the last node. To delete the front node (see the sequence of numbers 1,2,3 shown in above fig. ), the steps to be followed are

Page 7 of 12

Roll No. 521126647

July 2011 Master of Computer Science (MSCCS) Semester 1 MC0068 Data Structures using C 4 Credits (Book ID: B0701 & B0702) Assignment Set 2 (40 Marks)

Step 1: first = last->link; /* obtain address of the first node */ Step 2: last->link = first->link; /* link the last node and new first node */ Step 3: printf ("The item deleted is %d\n", first->info); Freenode (first); /*delete the old first node */ Now, the node identified as first node is deleted. These steps have been designed by assuming the list already exists. If there is only one node, delete that node and assign NULL to last indicating the list is empty. The code corresponding to this is can be /* If there is only one node, delete it */ if ( last->link = = last ) { printf ("The item deleted is %d\n", last->info); freenode(last); last = NULL; return last; } All these steps designed so far have to be executed provided the list is not empty. If the list is empty, display the appropriate message. The complete code to delete an item from the front end is shown in below example. Function to delete an item from the front end NODE delete_ front(NODE last) { NODE temp, first; if ( last = = NULL ) { printf("List is empty\n"); return NULL; } if ( last->link = = last) /* Only one node is present */ { printf("The item deleted is %d\n", last->info); freenode (last); return NULL; } /* List contains more than one node */ first = last->link; /* obtain node to be deleted */

Page 8 of 12

Roll No. 521126647

July 2011 Master of Computer Science (MSCCS) Semester 1 MC0068 Data Structures using C 4 Credits (Book ID: B0701 & B0702) Assignment Set 2 (40 Marks)
last->link = last->link; /*Store new first node in link of last */ printf ("The item deleted is %d\n", first->info); freenode (first); /* delete the old first node */ return last; } Delete a node from the rear end To delete a node from the rear end, it is required to obtain the address of the predecessor of the node to be deleted. Consider the list shown in fig. where the pointer variable last contains the, address of the last node.

To delete a node from the rear end To delete the node pointed to by last, the steps to be followed are: Step 1: Obtain the address of the predecessor of the node to be deleted. This can be accomplished by traversing from the first node till the link field of a node contains address of the last node. The code corresponding to this is prev = last->link; while ( prev->link != last ) { prev = prev->link; } Step 2: The first node and the last but one node (i.e., prev) are linked. This can be accomplished using the statement prev->link ='last->link; Step 3: The last node can be deleted using the statement freenode (last); After executing these statements, return the node pointed to by prev as the new last node using the statement return(prev); All these steps have been designed by assuming that the list already exists. If there is only one node, delete that node and assign NULL to the pointer variable last indicating that the list is empty. If the list is empty in the beginning display the appropriate message. The C function to delete an item from the rear end of circular list is shown in below example. Function to delete an item from the rear end NODE delete_ rear (NODE last) { NODE prev; if ( last = = NULL ) {

Page 9 of 12

Roll No. 521126647

July 2011 Master of Computer Science (MSCCS) Semester 1 MC0068 Data Structures using C 4 Credits (Book ID: B0701 & B0702) Assignment Set 2 (40 Marks)
printf("List is empty\n"); return NULL; } if ( last->link = = last) /* Only one node is present */ { printf("The item deleted is %d\n", last->info); freenode(last); return NULL; } /* Obtain address of previous node */ Data Structures using C Unit 5 Sikkim Manipal University Page No.: 157 prev = last->link; while( prev->link != last ) { prev = prev->link; } prev->link = last->link; /* prev node is made the last node */ printf("The item deleted is %d\n", last->info); freenode(last); /* delete the old last node */ return prev; /* return the new last node */ }

Page 10 of 12

Roll No. 521126647

July 2011 Master of Computer Science (MSCCS) Semester 1 MC0068 Data Structures using C 4 Credits (Book ID: B0701 & B0702) Assignment Set 2 (40 Marks)
Book ID: B0702 Q.3) Answer the following Questions: a. Compare and contrast DFS and BFS and DFS+ID approaches Description: BFS 1. A simple strategy in which the root is expanded first then all the root successors are expanded next then their successors. 2. Order in which nodes are expanded. DFS DFS progresses by expanding the first child node of the search tree that appears and thus going deeper and deeper until a goal node is found, or until it hits a node that has no children. Then the search backtracks, returning to the most recent node it hasnt finished exploring. Order in which nodes are expanded. DFS+ID It is a search strategy resulting when you combine BFS and DFS, thus combining the advantages of each strategy, taking the completeness and optimality of BFS and the modest memory requirements of DFS. IDS works by looking for the best search depth d, thus starting with depth limit 0 and make a BFS and if the search failed it increase the depth limit by 1 and try a BFS again with depth 1 and so on first d = 0, then 1 then 2 and so on until a depth d is reached where a goal is found. IDS is like BFS, is complete when the branching factor b is finite.

Completeness: it is easy to see that breadth first search is complete that it visit all levels given that d factor is finite, so in some d it will find a solution.

Optimality:

breadth-first search is not optimal until all actions have the same cost.

DFS is not complete, to convince yourself consider that our search start expanding the left sub tree of the root for so long path (may be infinite) when different choice near the root could lead to a solution, now suppose that the left sub tree of the root has no solution, and it is unbounded, then the search will continue going deep infinitely, in this case we say that DFS is not complete. Consider the scenario that there is more than one goal node, and our search decided to first expand the left sub tree of the root where there is a solution at a very deep level of this left sub tree, in the same time the right sub tree of the root has a solution near the root, here comes the nonoptimality of DFS that it is

IDS is also like BFS optimal when the steps are of the same cost.

Page 11 of 12

Roll No. 521126647

July 2011 Master of Computer Science (MSCCS) Semester 1 MC0068 Data Structures using C 4 Credits (Book ID: B0701 & B0702) Assignment Set 2 (40 Marks)
not guaranteed that the first goal to find is the optimal one, so we conclude that DFS is not optimal. DFS may suffer from nontermination when the length of a path in the search tree is infinite, so we perform DFS to a limited depth which is called Depth-limited Search.

Conclusion:

We see that space complexity is the biggest problem for BFS than its exponential execution time.

1. We can conclude that IDS is a hybrid search strategy between BFS and DFS inheriting their advantages. 2. IDS is faster than BFS and DFS. 3. It is said that IDS is the preferred uniformed search method when there is a large search space and the depth of the solution is not known.

b. Discuss how Splay Tree differs from a Binary Tree? Justify your answer with appropriate example. Answer: 3(b) The splay tree, a self-adjusting form of binary search tree, is developed and analyzed. The binary search tree is a data structure for representing tables and lists so that accessing, inserting, and deleting items is easy. On an n-node splay tree, all the standard search tree operations have an amortized time bound of O(log n) per operation, where by amortized time is meant the time per operation averaged over a worst-case sequence of operations. Thus splay trees are as efficient as balanced trees when total running time is the measure of interest. In addition, for sufficiently long access sequences, splay trees are as efficient, to within a constant factor, as static optimum search trees. The efficiency of splay trees comes not from an explicit structural constraint, as with balanced trees, but from applying a simple restructuring heuristic, called splaying, whenever the tree is accessed. Extensions of splaying give simplified forms of two other data structures: lexicographic or multidimensional search trees and link/cut trees. Self-adjusting data structures have several possible advantages over balanced or otherwise explicitly constrained structures: a) In an amortized sense, ignoring constant factors, they are never much worse than constrained structures, and since they adjust according to usage, they can be much more efficient if the usage pattern is skewed. b) They need less space, since no balance or other constraint information is stored. c) Their access and update algorithms are conceptually simple and easy to implement. Self-adjusting structures have two potential disadvantages: d) They require more local adjustments, especially during accesses (look-up operations). (Explicitly constrained structures need adjusting only during updates, not during accesses.) e) Individual operations within a sequence can be expensive, which may be a drawback in real-time applications.

Page 12 of 12

Roll No. 521126647

You might also like