Part 2 book “Data structures and problem solving using C++” has contents: Simulation, graphs and paths, stacks and queues, linked lists, trees, binary search trees, hash tables, a priority queue - The binary heap, splay trees, merging priority queues, the disjoint set class,… and other contents.
Chapter 14 Simulation An important use of computers is for simulation, in which the computer is used to emulate the operation of a real system and gather statistics For example, we might want to simulate the operation of a bank with k tellers to determine the minimum value of k that gives reasonable service time Using a computer for this task has many advantages First the information would be gathered without involving real customers Second, a simulation by computer can be faster than the actual implementation because of the speed of the computer Third the simulation could be easily replicated In many cases, the proper choice of data structures can help us improve the efficiency of the simulation In this chapter, we show: An important use of computers is simulation, in which the computer is used to emulate the operation of a real system and gather statistics how to simulate a game modeled on the Joseph~lsproblern, and how to simulate the operation of a computer modem bank 14.1 The Josephus Problem The Josephus problem is the following game: N people, numbered to N, are sitting in a circle; starting at person I , a hot potato is passed; after M passes, the person holding the hot potato is eliminated, the circle closes ranks and the game continues with the person who was sitting after the eliminated person picking up the hot potato; the last remaining person wins A common assumption is that M is a constant, although a random number generator can be used to change M after each elimination The Josephus problem arose in the first century ~ in a cave on a mountain in Israel where Jewish zealots were being besieged by Roman soldiers The historian Josephus was among them To Josephus's consternation the zealots voted to enter into a suicide pact rather than surrender to the Romans He suggested the game that now bears his name The hot potato In the Josephus problem, a hot potato is repeatedly passed; when passing terminates, the player holding the potato is eliminated; the game continues, and the last remaining player wins - - - Simulation Figure 14.1 The Josephus problem: At each step, the darkest circle represents the initial holder and the lightly shaded circle represents the player who receives the hot potato (and is eliminated) Passes are made clockwise was the sentence of death to the person next to the one who got the potato Josephus rigged the game to get the last lot and convinced the remaining intended victim that the two of them should surrender That is how we know about this game; in effect, Josephus cheated.' If M = 0, the players are eliminated in order, and the last player always wins For other values of M, things are not so obvious Figure 14.1 shows that if N = and M = I, the players are eliminated in the order 2, 4, I , In this case, player wins The steps are as follows At the start, the potato is at player After one pass it is at player 2 Player is eliminated Player picks up the potato, and after one pass, it is at player Player is eliminated Player picks up the potato and passes it to player I Player I is eliminated Player picks up the potato and passes it to player 5 Player is eliminated, so player wins First, we write a program that simulates, pass for pass, a game for any values of N and M The running time of the simulation is O(MN), which is acceptable if the number of passes is small Each step takes O(M) time because it performs M passes We then show how to implement each step in O(log N) time, regardless of the number of passes performed The running time of the simulation becomes O(N log N) Thanks to David Teague for relaying this story The version that we solve differs from the historical description In Exercise 14.12 you are asked to solve the historical version - The Josephus Problem 14.1.I The Simple Solution The passing stage in the Josephus problem suggests that we represent the players in a linked list We create a linked list in which the elements 1, 2, , N are inserted in order We then set an iterator to the front element Each pass of the potato corresponds to a + + operation on the iterator At the last player (currently remaining) in the list we implement the pass by resetting the iterator to the first element This action mimics the circle When we have finished passing, we remove the element on which the iterator has landed An implementation is shown in Figure 14.2 The linked list and iterator are declared at lines and 9, respectively We construct the initial list by using the loop at lines 14 and 15 In Figure 14.2, the code at lines 20 to 33 plays one step of the algorithm by passing the potato (lines 20 to 25) and then eliminating a player (lines 30-33) This procedure is repeated until the test at line 18 tells us that only one player remains At that point we return the player's number at line 36 The running time of this routine is O ( M N ) because that is exactly the number of passes that occur during the algorithm For small M, this running time is acceptable, although we should mention that the case M = does not yield a running time of O ( ) ;obviously the running time is O(N).We not merely multiply by zero when trying to interpret a Big-Oh expression We can represent the players by a linked list and use the iterator to the passing 14.1.2 A More Efficient Algorithm A more efficient algorithm can be obtained if we use a data structure that supports accessing the kth smallest item (in logarithmic time) Doing so allows us to implement each round of passing in a single operation Figure 14.1 shows why Suppose that we have N players remaining and are currently at player P from the front Initially N is the total number of players and P is After M passes, a calculation tells us that we are at player ( ( P + M ) mod N) from the front, except if that would give us player , in which case, we go to player N The calculation is fairly tricky, but the concept is not Applying this calculation to Figure 14.1, we observe that M is 1, N is initially 5, and P is initially So the new value of P is After the deletion, N drops to 4, but we are still at position 2, as part (b) of the figure suggests The next value of P is 3, also shown in part (b), so the third element in the list is deleted and N falls to The next value of P is mod 3, or 1, so we are back at the first player in the remaining list, as shown in part (c) This player is removed and N becomes At this point, we add M to P, obtaining Because mod is , we set P to player N, and thus the last player in the list is the one that is removed This action agrees with part (d) After the removal, N is and we are done If we implement each round of passing in a single logarithmic operation, the simulation will be faster The calculation is tricky because of the circle 10 11 12 13 14 15 16 17 18 #include using namespace std; / / Return the winner in the Josephus problem / / STL list implementation int josephus( int people, int passes list thelist; list::iterator itr; list::iterator next; int i; / / Construct the list for( i = 1; i