






Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
This is solution manual provided by Muhammad Uzair at University of Engineering and Technology Lahore. It related to Data Structures and Algorithms course. Its main points are: Lists, Stacks, Queues, Amount, Abstractness, Running, TIme, Linked, Code, Intersect
Typology: Exercises
1 / 10
This page cannot be seen from the preview
Don't miss anything!







By:
Muhammad Uzair
05-E-
U.E.T. Lahore
Pakistan
Preface
Included in this manual are answers to most of the exercises in the textbook Data Structures and Algorithm Analysis in C, second edition, published by Addison-Wesley. These answers reflect the state of the book in the first printing.
Specifically omitted are likely programming assignments and any question whose solu- tion is pointed to by a reference at the end of the chapter. Solutions vary in degree of complete- ness; generally, minor details are left to the reader. For clarity, programs are meant to be pseudo-C rather than completely perfect code.
Errors can be reported to [email protected]. Thanks to Grigori Schwarz and Brian Harvey for pointing out errors in previous incarnations of this manual.
3.2 The comments for Exercise 3.4 regarding the amount of abstractness used apply here. The running time of the procedure in Fig. 3.1 is O O( L O + P O).
void PrintLots( List L, List P ) { int Counter; Position Lpos, Ppos;
Lpos = First( L ); Ppos = First( P ); Counter = 1; while( Lpos != NULL && Ppos != NULL ) { if( Ppos->Element == Counter++ ) { printf( "%? ", Lpos->Element ); Ppos = Next( Ppos, P ); } Lpos = Next( Lpos, L ); } } Fig. 3.1.
3.3 (a) For singly linked lists, the code is shown in Fig. 3.2.
/* BeforeP is the cell before the two adjacent cells that are to be swapped. / / Error checks are omitted for clarity. */
void SwapWithNext( Position BeforeP, List L ) { Position P, AfterP;
P = BeforeP->Next; AfterP = P->Next; /* Both P and AfterP assumed not NULL. */
P->Next = AfterP->Next; BeforeP->Next = AfterP; AfterP->Next = P; } Fig. 3.2.
(b) For doubly linked lists, the code is shown in Fig. 3.3.
/* P and AfterP are cells to be switched. Error checks as before. */
void SwapWithNext( Position P, List L ) { Position BeforeP, AfterP;
BeforeP = P->Prev; AfterP = P->Next;
P->Next = AfterP->Next; BeforeP->Next = AfterP; AfterP->Next = P; P->Next->Prev = P; P->Prev = AfterP; AfterP->Prev = BeforeP; } Fig. 3.3.
3.4 Intersect O is shown on page 9.
List Union( List L1, List L2 ) { List Result; ElementType InsertElement; Position L1Pos, L2Pos, ResultPos;
L1Pos = First( L1 ); L2Pos = First( L2 ); Result = MakeEmpty( NULL ); ResultPos = First( Result ); while ( L1Pos != NULL && L2Pos != NULL ) { if( L1Pos->Element < L2Pos->Element ) { InsertElement = L1Pos->Element; L1Pos = Next( L1Pos, L1 ); } else if( L1Pos->Element > L2Pos->Element ) { InsertElement = L2Pos->Element; L2Pos = Next( L2Pos, L2 ); } else { InsertElement = L1Pos->Element; L1Pos = Next( L1Pos, L1 ); L2Pos = Next( L2Pos, L2 ); } Insert( InsertElement, Result, ResultPos ); ResultPos = Next( ResultPos, Result ); } /* Flush out remaining list */ while( L1Pos != NULL ) { Insert( L1Pos->Element, Result, ResultPos ); L1Pos = Next( L1Pos, L1 ); ResultPos = Next( ResultPos, Result ); } while( L2Pos != NULL ) { Insert( L2Pos->Element, Result, ResultPos ); L2Pos = Next( L2Pos, L2 ); ResultPos = Next( ResultPos, Result ); } return Result; } Fig. 3.4.
3.8 One can use the Pow O function in Chapter 2, adapted for polynomial multiplication. If P O is small, a standard method that uses O O( P O) multiplies instead of O O(log P O) might be better because the multiplies would involve a large number with a small number, which is good for the multiplication routine in part (b).
3.10 This is a standard programming project. The algorithm can be sped up by setting M' O = M O mod O N O, so that the hot potato never goes around the circle more than once, and
then if M' O > N O / 2, passing the potato appropriately in the alternative direction. This requires a doubly linked list. The worst-case running time is clearly O O( N O min O( M O, N O)), although when these heuristics are used, and M O and N O are comparable, the algorithm might be significantly faster. If M O = 1, the algorithm is clearly linear. The VAX/VMS C compiler’s memory management routines do poorly with the particular pattern of P free Os in this case, causing O O( N Olog N O) behavior.
3.12 Reversal of a singly linked list can be done nonrecursively by using a stack, but this requires O O( N O) extra space. The solution in Fig. 3.5 is similar to strategies employed in gar- bage collection algorithms. At the top of the while O loop, the list from the start to Pre- viousPos O is already reversed, whereas the rest of the list, from CurrentPos O to the end, is normal. This algorithm uses only constant extra space.
/* Assuming no header and L is not empty. */
List ReverseList( List L ) { Position CurrentPos, NextPos, PreviousPos;
PreviousPos = NULL; CurrentPos = L; NextPos = L->Next; while( NextPos != NULL ) { CurrentPos->Next = PreviousPos; PreviousPos = CurrentPos; CurrentPos = NextPos; NextPos = NextPos->Next; } CurrentPos->Next = PreviousPos; return CurrentPos; } Fig. 3.5.
3.15 (a) The code is shown in Fig. 3.6.
(b) See Fig. 3.7.
(c) This follows from well-known statistical theorems. See Sleator and Tarjan’s paper in the Chapter 11 references.
3.16 (c) Delete O takes O O( N O) and is in two nested for loops each of size N O, giving an obvious O O( N O^3 ) bound. A better bound of O O( N O^2 ) is obtained by noting that only N O elements can be deleted from a list of size N O, hence O O( N O^2 ) is spent performing deletes. The remainder of the routine is O O( N O^2 ), so the bound follows. (d) O O( N O^2 ).
/* Assuming a header. */
Position Find( ElementType X, List L ) { Position PrevPos, XPos;
PrevPos = FindPrevious( X, L ); if( PrevPos->Next != NULL ) /* Found. */ { XPos = PrevPos ->Next; PrevPos->Next = XPos->Next; XPos->Next = L->Next; L->Next = XPos; return XPos; } else return NULL; } Fig. 3.7.
3.23 Three stacks can be implemented by having one grow from the bottom up, another from the top down, and a third somewhere in the middle growing in some (arbitrary) direction. If the third stack collides with either of the other two, it needs to be moved. A reasonable strategy is to move it so that its center (at the time of the move) is halfway between the tops of the other two stacks.
3.24 Stack space will not run out because only 49 calls will be stacked. However, the running time is exponential, as shown in Chapter 2, and thus the routine will not terminate in a rea- sonable amount of time.
3.25 The queue data structure consists of pointers Q->Front O and Q->Rear, O which point to the beginning and end of a linked list. The programming details are left as an exercise because it is a likely programming assignment.
3.26 (a) This is a straightforward modification of the queue routines. It is also a likely program- ming assignment, so we do not provide a solution.