• No results found

The method getFrequencyOf also searches an array, much as getIndexOf does, but unlike getIndexOf , getFrequencyOf must examine every entry in the array. That is, the search does not end if an array entry matches the entry we seek.

Suppose that searchIndex is the index of the next array element to examine. A recursive defi ni- tion for this search has only one base case: If searchIndex equals itemCount , we are done. However, we have two recursive steps:

If items[searchIndex] is the entry we seek, the frequency of occurrence of this entry is one more than its frequency of occurrence in the rest of the array.

If items[searchIndex] is not the entry we seek, the frequency of occurrence of the entry is the same as its frequency of occurrence in the rest of the array.

Just as we had to add another parameter to getIndexOf , the recursive method here needs searchIndex as a parameter. However, getFrequencyOf is a public method, so we cannot change its signature. Instead, getFrequencyOf must call a private method that accomplishes the recursive search. Thus, let’s add the following declaration to the private portion of the header fi le:

int countFrequency(const ItemType& target, int searchIndex) const;

The method of getFrequencyOf simply calls this private method, so its defi nition is as follows: template<class ItemType>

int ArrayBag<ItemType>::getFrequencyOf(const ItemType& anEntry) const {

return countFrequency(anEntry, 0); } // end getFrequencyOf

The recursive defi nition of the private method countFrequency is template<class ItemType>

int ArrayBag<ItemType>::countFrequency(const ItemType& target, int searchIndex)const {

if (searchIndex < itemCount) {

if (items[searchIndex] == target) {

return 1 + countFrequency(target, searchIndex + 1); }

else {

return countFrequency(target, searchIndex + 1); } // end if

} else

return 0; // Base case } // end countFrequency

Stylistically, we prefer to have only one exit from a method. To revise countFrequency so that it has onereturn statement instead of three, we defi ne a local variable, frequency , to contain the return value. The method then has the following defi nition. Note that the base case is implicit.

template<class ItemType>

int ArrayBag<ItemType>::countFrequency(const ItemType& target, int searchIndex)const

{ int frequency = 0; if (searchIndex < itemCount) { if (items[searchIndex] == target) {

frequency = 1 + countFrequency(target, searchIndex + 1); }

else {

frequency = countFrequency(target, searchIndex + 1); } // end if

} // end if

return frequency; } // end countFrequency

1. By using a class to implement an ADT, you encapsulate the ADT’s data and operations. In this way, you can hide implementation details from the program that uses the ADT. In particular, by making the class’s data members private, you can change the class’s implementation without affecting the client.

2. Given an interface that specifi es an ADT in an implementation-independent way, derive a class from the inter- face and declare the class within a header fi le. Choose a data structure to contain the ADT’s data. Then imple- ment the class’s methods within an implementation fi le.

3. You should make a class’s data members private so that you can control how a client can access or change the data.

4. An array-based implementation of an ADT stores the ADT’s data in an array.

5. Generally, you should not defi ne an entire class and then attempt to test it. Instead, you should identify a group of core methods to both implement and test before continuing with the rest of the class defi nition.

6. Stubs are incomplete defi nitions of a class’s methods. By using stubs for some methods, you can begin testing before the class is completely defi ned.

7. A client must use the operations of an ADT to manipulate the ADT’s data.

E

XERCISES

1. Consider a bag of integers. Write a client function that computes the sum of the integers in the bag aBag .

2. Write a client function replace that replaces a given item in a given bag with another given item. The function should return a boolean value to indicate whether the replacement was successful.

3. The previous exercise describes the function replace . This operation exists outside of the ADT bag; that is, it is not an ADT bag operation. Instead, its implementation is written in terms of the ADT bag’s operations.

a. What is an advantage and a disadvantage of the way that replace is implemented?

b. What is an advantage and a disadvantage of adding the operation replace to the ADT bag?

Programming Problems 115

P

ROGRAMMING

P

ROBLEMS

4. Design and implement an ADT that represents a rectangle. Include typical operations, such as setting and retrieving the dimensions of the rectangle, and fi nding the area and the perimeter of the rectangle.

5. Design and implement an ADT that represents a triangle. The data for the ADT should include the three sides of the triangle but could also include the triangle’s three angles. This data should be in the private section of the class that implements the ADT.

Include at least two initialization operations: one that provides default values for the ADT’s data, and another that sets this data to client-supplied values. These operations are the class’s constructors. The ADT also should include operations that look at the values of the ADT’s data; change the values of the ADT’s data; com- pute the triangle’s area; and determine whether the triangle is a right triangle, an equilateral triangle, or an isosceles triangle.

6. Write a recursive array-based implementation of the method toVector for the class ArrayBag .

7. Write a client function that merges two bags into a new third bag. Do not destroy the original two bags.

8. Specify and defi ne a method for ArrayBag that removes a random entry from the bag.

9. Add a constructor to the class ArrayBag that creates a bag from a given array of entries.

1. Design and implement an ADT that represents the time of day. Represent the time as hours and minutes on a 24-hour clock. The hours and minutes are the private data members of the class that implements the ADT. Include at least two initialization operations: one that provides a default value for the time, and another that sets the time to a client-supplied value. These operations are the class’s constructors. Also include operations that set the time, increase the present time by a number of minutes, and display the time in 12-hour and 24-hour notations.

2. Design and implement an ADT that represents a calendar date. You can represent a date’s month, day, and year as integers (for example, 4/1/2014). Include operations that advance the date by one day and display the date by using either numbers or words for the months. As an enhancement, include the name of the day.

3. Design and implement an ADT that represents a price in U.S. currency as dollars and cents. After you complete the implementation, write a client function that computes the change due a customer who pays x for an item whose price is y .

4. Design and implement an ADT that represents a bank account. The data of the ADT should include the cus- tomer name, the account number, and the account balance. The initialization operation should set the data to client-supplied values. Include operations for a deposit and a withdrawal, the addition of interest to the balance, and the display of the statistics of the account.

5. Add the methods union , intersection , and difference to the class ArrayBag . Exercises 6, 7, and 8 of Chapter 1 describe these operations.

6. Implement the ADT set that you specifi ed in Programming Problem 5 of Chapter 1 by using an array.

7. Implement the ADT pile that you specifi ed in Programming Problem 6 of Chapter 1 by using an array.

9. Implement the ADT appointment book, described in Section 1.4.1 of Chapter 1 . Write a program that demon- strates your new class.

10. Specify and implement an ADT for fractions. Provide operations that add, subtract, multiply, and divide these numbers. The results of all arithmetic operations should be in lowest terms, so include a private method reduc- eToLowestTerms. Exercise 23 in Chapter 2 will help you with the details of this method. To simplify the deter- mination of a fraction’s sign, you can assume that the denominator of the fraction is positive.

11. Specify and implement an ADT for mixed numbers, each of which contains an integer portion and a fractional portion in lowest terms. Assume the existence of the ADT fraction, as described in the previous problem. Pro- vide operations that add, subtract, multiply, and divide mixed numbers. The results of all arithmetic operations should have fractional portions that are in lowest terms. Also include an operation that converts a fraction to a mixed number.

12. Implement the ADT recipe book as described in Section 1.4.2 of Chapter 1 . In doing so, implement the ADT measurement. Add operations as necessary. For example, you should add an operation to the recipe book to scale a recipe.

13. You can use either a set or a bag to create a spell checker. The set or bag serves as a dictionary and contains a collection of correctly spelled words. To see whether a word is spelled correctly, you see whether it is contained in the dictionary. Use this scheme to create a spell checker for the words in an external fi le. To simplify your task, restrict your dictionary to a manageable size.

14. Repeat the previous project to create a spell checker, but instead place the words whose spelling you want to check into a bag. The difference between the dictionary (the set or bag containing the correctly spelled words) and the bag of words to be checked is a bag of incorrectly spelled words.

Pointers,