You are on page 1of 30

Answers to Selected Exercises

Chapter 1
Many of the questions in this chapter's exercise are "thought questions." The answers
given here are typical or suggested responses, but are not the only possible answers.

1. Software engineering is a disciplined approach to the creation and maintenance


of computer programs throughout their whole life cycle.
4. Some software tools used in developing computer programs are text editors,
compilers, assemblers, operating systems, and debugging programs.
7. Goal 4 says, "Quality software is completed on time and within budget."
(a) When a student does not complete a programming assignment on time, it
usually hurts his or her grade. Also, some concepts that were to be learned in
preparation for the next programming assignment may not be mastered in time
to be put into practice.
(b) When a team developing a highly competitive new software product does
not complete its work on time, the company must continue to pay salaries, office
rent, etc., increasing the "development cost" of the product. The product may go
on the market late, after competing products have been released, hurting its
sales. This may have an effect on the team members' professional evaluations
(like a student's grade).
10. An object is an individual while a class is a description of a group of objects with
similar properties and behaviors. Labrador dogs is an example of a class and
Maggie is an example of an object.
14. An expert understanding of your programming language saves you time and
debugging because (a) you can avoid syntax errors, (b) you can more quickly
identify and correct those syntax errors that occur, and (c) you can avoid errors
caused by a misunderstanding of the way the language works.
17. The body of the While loop is not in brackets.
The comments include the call to Increment.
The parameter to Increment is not a reference parameter.
20. Unit testing is the testing of a single unit of the program (for instance, a function).
Integration testing is the testing of groups of already tested units to make sure that
they interact correctly and that the whole program works according to its
specification.
23. (a) The functional domain consists of the whole numbers from 0 to 100.
(b) It is possible to carry out exhaustive data coverage for this program.
(c) Devise a test plan for this program.
Input: All values from 1 to 100.
Expected Output: For input 0-59 F
For input 60-69 D
For input 70-79 C
For input 80-89 B
For input 90-100 A
26. Life-cycle verification refers to the idea that program verification activities can be
performed throughout the program's life cycle, not just by testing the program
after it is coded.
29. (a) num and denom are both just integer values. Each can be either negative or
positive. In a fraction the numerator carries the sign. The denominator should
always be positive.
(b) IsNotProper needs to be changed to use the absolute value of the
numerator. Function Initialize (or any constructor) should check to be sure the
denominator is strictly positive and throw an exception if this is not the case.
(c) The following tests need to be added to the test plan.
Operation to Be Tested and Description of Input  Expected Output
Action Values
Initialize ­3,4 Numerator: ­3
Denominator: 4
IsNotProper Fraction is proper

Initialize ­13,4 Numerator: ­13


Denominator: 4
IsNotProper Fraction is improper

ConvertToProper Whole number is 3
Numerator is ­1
Denominator is 4

Chapter 2
2. Data encapsulation is the separation of the physical representation of data from
the applications that use the data at a logical (abstract) level. When data
abstraction is protected through encapsulation, the data user can deal with the
data abstraction but cannot access its implementation, which is encapsulated.
The data user accesses data that is encapsulated through a set of operations
specified to create, access, and change the data. Data encapsulation is
accomplished through a programming language feature.
5. array, struct, union, and classes
8. The syntax of the component selector is the array name followed by the index of
the desired item:
array-name[index-expression]
11. (a)
typedef WeatherType WeatherListType[12];
WeatherListType yearlyWeather;
(b) yearlyWeather[6].actualRain = 1.05;
(c) 238
14. Member-length-offset table for StudentRecord.
Field Length Offset
firstName 10 0
lastName 10 10
id 1 20
gpa 2 21
currentHours 1 23
totalHours 1 24
17. (a) A square two-dimensional array
(b) struct or class
(c) struct or class containing two data members: the number of quotations and
an array of strings that holds them
(d)a one-dimensional integer array
(e) a two-dimensional integer array
(f) a three-dimensional integer array
(g) an array of structs or classes
(h) a one-dimensional integer array
20. The members of a class are private unless specified as public. Client code cannot
access private members.
23. Classes can relate to one another through inheritance, containment
(composition), and not at all.
28. (a)
SquareMatrix ADT Specification

Structure: An NxN square integer matrix.

Operations :
MakeEmpty(int n)
Function: Initializes the size of the matrix to n and sets the values
to zero.
Precondition: n is less than or equal to 10.
Postconditions: Matrix contains all zero values.

StoreValue(int i, int j, int value)


Function: Stores value into the i,jth position in the matrix.
Preconditions Matrix has been initialized; i and j are between 0 and the
size minus 1.
Postconditions: value has been stored into the i,jth position of the
matrix.

Add(SquareMatrixType one, SquareMatrixType two, SquareMatrixType


result)
Function: Adds matrix one and matrix two and stores the result
in result.
Precondition: one and two have been initialized and are the same
size.
Postcondition: result = one + two.

Subtract(SquareMatrixType one, SquareMatrixType two,


SquareMatrixType result)
Function: Subtracts two from one and stores the result in result.
Precondition: one and two have been initialized and are the same
size.
Postcondition: result = one - two.

Print(SquareMatrixType one)
Function: Prints the matrix on the screen.
Precondition: Matrix has been initialized.
Postcondition: The values in the matrix have been printed by row on
the screen.

Copy(SquareMatrixType one, SquareMatrixType two)


Function: Copies two into one.
Precondition: two has been initialized.
Postcondition: one = two.

(b)
The following declaration contains only additional pre/post conditions required
by the implementation.
    class SquareMatrixType
    {
    public:
        void MakeEmpty(int n);
        // Pre:  n is less than or equal to 50.
        // Post: n has been stored into size.
        void StoreValue(int i, int j, int value);
        // Pre:  i and j are less than or equal to size.
        void Add(SquareMatrixType two, SquareMatrixType 
result);
        // Post: result = self + two.
        void Subtract(SquareMatrixType two, SquareMatrixType 
result);
        // Post: result = self ­ two.
        void Print();
        // Post: The values in self have been printed by row on
the screen.
        void Copy(SquareMatrixType two);
        // Post: self = two
    private:
        int size; // Dimension of the matrix.
        int matrix[10][10];
    };
(c)
    void SquareMatrixType::MakeEmpty(int n)
    {
        size = n;
        for (int row = 0; row < size; row++)
            for (int col = 0; col < size; col++)
                matrix[row][col] = 0;
    }
    
    void SquareMatrixType::StoreValue(int i, int j, int value)
    {
        matrix[i][i] = value;
    }
    
    void SquareMatrixType::Add(SquareMatrixType two, SquareMatrixType
result)
    {
        
       for (int row = 0; row < size; row++)
           for (int col = 0; col < size; col++)
               result.matrix[row][col] = matrix[row][col] + 
two.matrix[row][col];
    }
                
    void SquareMatrixType::Subtract(SquareMatrixType two, 
SquareMatrixType result)
    {            
         for (int row = 0; row < size; row++)
             for (int col = 0; col < size; col++)
                 result.matrix[row][col] = matrix[row][col] ­ 
two.matrix[row][col];
    }
    
    void SquareMatrixType::Print()
    {
         for (int row = 0; row < size; row++)
             for (int col = 0; col < size; col++)
                 cout  << matrix[row][col];
    }
    
    void SquareMatrixType::Copy(SquareMatrixType two) 
    {
         for (int row = 0; row < size; row++)
             for (int col = 0; col < size; col++)
                 matrix[row][col] = two.matrix[row][col];
    }
(d)
This test plan is a black box strategy with data values representing the end cases
and a general case. For matrix operations, the end cases represent the size of the
matrices, not the values stored in them. We assume that integer addition and
subtraction are correct.
Operation to be Tested and Description of Action Input  Expected 
Values Output
MakeEmpty
execute and print 2 0 0
0 0
execute and print
0 no output
50 50x50 matrix of
execute and print
zeros
StoreValue
MakeEmpty(2)
store 1,1,2
store 1,2,3
2,2,4
store
2 3
print 0 4
Add
   General Case
Create a second matrix  1 2
3 4
Add to first one created and print 3 5
3 8
   End Case (size 0)
no output
Add two empty matrices and print
   End Case (size 50)
Create a 50x50 matrix of ones
Create a 50x50 matrix of twos
50x50 of threes
Add and print
Subtract
   General Case
Subtract the first from the second and print ­1 ­1
     3  0
   End Case (size 0)
Subtract two size 0 matrices and print no output
   End Case (size 50)
Subtract all ones from all twos 50x50 of ones
Copy
Copy first and print 2 3
0 4
      Copy a size 0 matrix and print no output
Copy a size 50 matrix of twos and print 50x50 of twos

31. If functions GetMonthAsString and Adjust are called frequently, then the
first version is more efficient because access to the string or number of days
would be O(1). On the other hand, if these functions are called only once, it
would be better to calculate these values and store them. The second alternative
would require two new class variables, one to hold the string and one to hold the
number of days, but the auxiliary arrays would no longer be need.

Chapter 3
1. (a)
Boolean IsThere(ItemType item)
Function: Determines if item is in the list.
Precondition: List has been initialized.
Postcondition: Function value = there exist an item in the list whose key
is the same as item's.
(b)
bool IsThere(ItemType item) const;
(d) O(N) where N is the number of items in the list.
5. (a)
DeleteItem (ItemType item )
Function: Deletes the element whose key matches item's key.
Preconditions: List has been initialized.
Key member of item is initialized.
At most one element in list has a key matching item's key.
Postcondition: If an element in list had a key matching item's key, the
item has been removed; otherwise, the list is unchanged.
(c)
DeleteItem (ItemType item )
Function: Deletes the element whose key matches item's key.
Preconditions: List has been initialized.
Key member of item is initialized.
Postcondition: No element in list has a key matching item's key.
8. (a) True
(b) True
(c) False. A linked list is not a random-access structure.
(d) False. A sequential list may be stored in a statically allocated or a
dynamically allocated structure.
(e) True
(f) False. A queue is not a random-access structure; access is always to the first
one stored.
10. (a) true
(b) false
(c) false
(d) true
12. (a) listData = ptr1­>next;
(b) ptr2 = ptr2­>next;
(c) listData = NULL
(d) ptr1->next->info = 60
Answers for the table:
Statements Memory allocated What is
printed?
int value; value is assigned to location
200
value = 500;
char* charPtr; charPtr is at location 202
char string[10] = "Good luck"; string[0] is at location 300
charPtr = string;
cout << &value;    // question 19 & means "the address of"
cout << value;     // question 20
cout << &charPtr;  // question 21 & means "the address of"
cout << charPtr;   // question 22
cout << *charPtr;  // question 23
cout << string[2]; // question 24
16. None of the changes in Exercises 9 and 10 change the Big-O from that discussed
in the chapter. Each of the delete operations still have order O(N).

Chapter 4
1.
(a)
Boolean IsThere(ItemType item)
Function: Determines if item is in the list.
Precondition: List has been initialized.
Postcondition: Function value = there exist an item in the list whose key is the same as
item's.
(b)
bool IsThere(ItemType item) const;
(c)
bool SortedType::IsThere(ItemType item)
{
  int midPoint;
  int first = 0;
  int last = length ­ 1;
  bool moreToSearch = first <= last;
  bool found = false;

  while (moreToSearch && !found)
  {
    midPoint = (first + last) / 2;
    switch (item.ComparedTo(info[midPoint])
    {
      case LESS    : last = midPoint ­ 1;
                     moreToSearch = first <= last;
                     break;
      case GREATER : first = midPoint + 1;
                     moreToSearch = first <= last;
                     break;
      case EQUAL   : found = true;
                     break;
    }
  }
  return found;
}
(d) O(log2N) where N is the number of items in the list.

3. (a)
Boolean IsThere(ItemType item, UnsortedType list)
Function: Determines if item is in the list.
Precondition: list has been initialized.
Postcondition: Function value = there exist an item in the list whose key is the same as
item's.
(b)
bool IsThere(SortedType list, ItemType item)
{
  int length;
  bool found = false;
  int counter = 1;
  ItemType listItem;
   
  length = list.LengthIs();
  list.ResetList();
  while (!found && counter <= length)
  {
    list.GetNextItem(listItem);
    if (listItem.ComparedTo(item) == EQUAL)
      found = true;
    counter++;
  }
  return found;
}  

or

bool IsThere(SortedType list, ItemType item)
{
  bool found;
  list.RetrieveItem(item, found);
  return found;
}
(c) The client code does not have access to the array containing the data values,
so the binary search algorithm could not be used.
(d) The version that iterates through the items is O(N); the version that uses
RetrieveItem would have the same complexity as RetrieveItem.
(e) The member function has access to the array holding the values, so the
binary search algorithm can be used. Therefore, the complexity if O(log 2N)
rather O(N).
4. (a)
void MergeLists(SortedType list1, SortedType list2, 
   SortedType& result);
(b)
void MergeLists(SortedType list1, SortedType list2, 
   SortedType& result)
{
  int length1;
  int length2;
  int counter1 = 1;
  int counter2 = 1;
  ItemType item1;
  ItemType item2;

  length1 = list1.LengthIs();
  length2 = list2.LengthIs();
  list1.ResetList();
  list2.ResetList();
  list1.GetNextItem(item1);
  list2.GetNextItem(item2);
  result.MakeEmpty();

  while (counter1 <= length1 && counter2 <= length2)
    switch (item1.ComparedTo(item2))
    {
      case LESS   : result.InsertItem(item1);
                    if (counter1 < length1)
                      list1.GetNextItem(item1);
                    counter1++;
                    break;
      case GREATER: result.InsertItem(item2);
                    if (counter2 < length2)
                      list2.GetNextItem(item2);
                    counter2++;
                    break;
    }
  for (; counter1 <= length1; counter1++)
  {
    result.InsertItem(item1);
    if (counter1 < length1) 
      list1.GetNextItem(item1);
  }
  for (; counter2 <= length2; counter2++)
  {
    result.InsertItem(item2);
    if (counter2 < length2)
      list2.GetNextItem(item2);
  }
}

(c) Because the lists that are being merged are sorted, the complexity is O(N)
times the complexity of the InsertItem operation.

Chapter 5
1.
(a) Yes
(b) No
(c) Yes
(d) No
(e) Yes
(f) No
(g) No
(h) Yes
3. (a)
3 5 4 (on one line)
5 16 1 0 (each on a separate line)
(b)
0 5 6 5 (each on a separate line)
5 4 0 (on one line)
5. stack.Push(letter);
letter letter

stack.top stack.top
   .overFlow    .overFlow
   .underFlow    .underFlow
   .items    .items
[0 [0
] ]
8. (a) Set secondElement to the second element in the stack, leaving the stack
without its original top two elements.
{
  stack.Pop(secondElement);
  stack.Pop(secondElement);
}
(b) Set bottom equal to the bottom element in the stack, leaving the stack
empty.
{
  while (!stack.IsEmpty())
    stack.Pop(bottom);
}
(c) Set bottom equal to the bottom element in the stack, leaving the stack
unchanged.
{
  StackType tempStack;
  ItemType tempItem;

  while (!stack.IsEmpty())
  {
    stack.Pop(tempItem);
    tempStack.Push(tempItem);
  }
  bottom = tempItem;
  // restore stack
  while (!tempStack.IsEmpty())
  {
    tempStack.Pop(tempItem);
    stack.Push(tempItem);
  }
}
(d) Make a copy of the stack, leaving the stack unchanged.
{
  StackType tempStack;
  ItemType tempItem;
  while (!stack.IsEmpty())
  {
    stack.Pop(tempItem);
    tempStack.Push(tempItem);
  }

  // restore stack
  while (!stack.IsEmpty())
  {
    tempStack.Pop(tempItem);
    stack.Push(tempItem);
    copy.Push(tempItem)
  }
}
12. (a) Draw a diagram of how the stack might look.
smallTop: top for the stack of small values, initialized to -1 and incremented.
largeTop: top for the stack of large values, initialized to 200 and decremented.

[0] [1] [2] [3] .... [197] [198] [199]

(b)
class DStack
{
public:
  DStack();
  void Push(int item);
  void PopLarge(int& item);
  void PopSmall(int& item);
private:
   int smallTop;
   int largeTop;
   int items[200];

(c)
void Push(int item)
{
  if (item <= 1000)
  {
    small++;
    items[small] = item;
  }
  else
  {
    large­­;
    items[large] = item;
  }
}
15.
void (StackType& stack, ItemType oldItem, ItemType newItem)
{
  StackType tempStack;
  ItemType tempItem;
  while (!stack.IsEmpty())
  {
    stack.Pop(tempItem);
    if (tempItem.ComparedTo(oldItem) == EQUAL)
      tempStack.Push(newItem);
    else
      tempStack.Push(tempItem);
  }
  // restore stack
  while (!stack.IsEmpty())
  {
    tempStack.Pop(tempItem);
    stack.Push(tempItem);
  }
}
17.
Stack ADT Specification
Structure: Elements are added to and removed from the top of the stack.

Definitions (provided by user):


MAX_ITEMS: Maximum number of items that might be on the stack.
ItemType: Data type of the items on the stack.

Operations (provided by the ADT):


MakeEmpty
Function: Sets stack to an empty state.
Precondition: None
Postcondition: Stack is empty.

Boolean IsEmpty
Function: Determines whether the stack is empty.
Precondition: Stack has been initialized.
Postcondition: Function value = (stack is empty)

Boolean IsFull
Function: Determines whether the stack is full.
Precondition: Stack has been initialized.
Postcondition: Function value = (stack is full)

Push(ItemType newItem, Boolean& error)


Function: Adds newItem to the top of the stack.
Precondition: Stack has been initialized.
Postcondition: If stack is not full, newItem is at the top of the stack and error is
false;
otherwise, error is true and the stack is unchanged.

Pop(ItemType& item, Boolean& error)


Function: Removes top item from Stack and returns it in item.
Preconditions: Stack has been initialized and is not empty.
Postcondition: If the stack is not empty, the top element has been removed from
stack, item is a copy of removed item, and error is false;
otherwise, error is true and the stack is
unchanged.
(b) None
(c) None
An alternative implementation would add an error data member to the class.
This error flag would be set if underflow or overflow occurred and the operation
would not be performed. A member function would have to be added to the
class to allow the user to check the error flag.
20. Yes, this sequence is possible.
22. (a)
1 0 4 
5 16 0 3 
(b)
6 4 6 0 
6 5 5
24. queue.Enqueue(letter);

letter letter

queue.front queue.front
   .rear    .rear
   .overFlow    .overFlow
   .underFlow    .underFlow
   .items    .items

27. queue.Dequeue(letter);

letter letter

queue.front queue.front
   .rear    .rear
   .overFlow    .overFlow
   .underFlow    .underFlow
   .items    .items

30. (a) Set secondElement to the second element in the queue, leaving the queue
without its original front two elements.
{
  queue.Dequeue(secondElement);
  queue.Dequeue(secondElement);
}
(b) Set last equal to the rear element in the queue, leaving the queue empty.
{
  while (!queue.IsEmpty())
    queue.Dequeue(last);
}
(c) Set last equal to the rear element in the queue, leaving the queue
unchanged.
{
  QueType tempQ;
  ItemType item;

  while (!queue.IsEmpty())
  {
    queue.Dequeue(last);
    tempQ.Enqueue(last);
  }
  while (!tempQ.IsEmpty())
  {
    tempQ.Dequeue(item);
    ueue.Enqueue(item);
  }
}
(d) A copy of the queue, leaving the queue unchanged.
{
  QueType<ItemType> tempQ;
  ItemType item;

  while (!queue.IsEmpty())
  {
    queue.Dequeue(item);
    tempQ.Enqueue(item);
  }
  while (!tempQ.IsEmpty())
  {
    tempQ.Dequeue(item);
    queue.Enqueue(item);
    copy.Enqueue(item);
  }
}
32. The correct answer for the first statement is (d); the correct answer for the second
statement is (a).
35. (a) No
(b) Yes
(c) No
(d) No
(e) Yes
(f) Yes
(g) No
(h) Yes
(i) No
37.
int Length(QueType<ItemType> queue)
{
  QueType<ItemType> tempQ;
  ItemType item;
  int length = 0;

  while (!queue.IsEmpty())
  {
    queue.Dequeue(item);
    tempQ.Enqueue(item);
  }
  while (!tempQ.IsEmpty())
  {
    tempQ.Dequeue(item);
    queue.Enqueue(item);
    length++;
  }
  return length;
}
39. The second else-clause is only executed if both queues are not empty, but one
had to be empty for the loop to be exited, so only one can be empty. Therefore,
string1 can only be assigned a value from one queue or the other but not both.
42. No, this sequence is not possible.
44.
#include "StackType.h"
#include <iostream>
bool IsOpen(char symbol);
bool IsClosed(char symbol);
bool Matches(char symbol, char openSymbol);

int main()
{
  using namespace std;
  char symbol;
  StackType stack;
  bool balanced = true;
  char openSymbol;
  try
  {
    cout << "Enter an expression and press return." 
         << endl;
    cin.get(symbol); 
    while (symbol != '\n' && balanced)
    {
      if (IsOpen(symbol))
      stack.Push(symbol);

      else if (IsClosed(symbol))
      {
        if (stack.IsEmpty())
          balanced = false;
        else
        {
          openSymbol = stack.Top();
          stack.Pop();
          balanced = Matches(symbol, openSymbol);
        }
      }
      cin.get(symbol);
    }
  }
  catch (FullStack error)
  {
      cout << "Push called when the stack is full." <<
endl;
    return 1;
  }
  catch (EmptyStack error)
  {
    cout << "Top or Pop called when stack is empty." 
      << endl;
 return 1;
  }

  if (balanced)
  cout << "Expression is well formed." << endl;
  else
  cout << "Expression is not well formed."  << endl;
  return 0;
}
  
bool IsOpen(char symbol)
{
  if ((symbol == '(') || (symbol == '{') || (symbol ==
'['))
    return true;
  else
    return false;
}    

bool IsClosed(char symbol)
{
  if ((symbol == ')') || (symbol == '}') || (symbol ==
']'))
    return true;
  else
    return false;
}    

bool Matches(char symbol, char openSymbol)
{
  return  (((openSymbol == '(') && symbol == ')')
    || ((openSymbol == '{') && symbol == '}')
    || ((openSymbol == '[') && symbol == ']'));
}    

Chapter 6
3. Member functions Enqueue and Dequeue would have to be changed.
6. No, the class definition would not have to be changed. Only the definition of
NodeType would have to be changed.
9. Write a member function Copy of the Stack ADT, assuming that self is copied
into the stack named in the parameter list.
template <class ItemType>
void StackType<ItemType>::Copy(StackType<ItemType>& anotherStack)
{
  NodeType<ItemType>* ptr1;
  NodeType<ItemType>* ptr2;
  
  if (topPtr == NULL)
    anotherStack.topPtr = NULL;
  else
  {
    anotherStack.topPtr = new NodeType<ItemType>;
    anotherStack.topPtr­>info = topPtr­>info;
    ptr1 = topPtr­>next;
    ptr2 = anotherStack.topPtr;
    while (ptr1 != NULL)
    {
      ptr2­>next = new NodeType<ItemType>;
      ptr2 = ptr2­>next;
      ptr2­>info = ptr1­>info;
      ptr1 = ptr1­>next;
    }
    ptr2­>next = NULL;
  }  
}
12. (a) Doubly linked
(b) Circular
(c) List with header and trailer
15. (b)

4 17 25
(c)
free 3
list 1
nodes
.info .next .back
[0] 17 2 1
[1] 4 0 NUL
[2] 25 NUL 0
[3]
[4]
[5]
[6]
[7]
[8]
[9]
(d)
free 0
list 1
nodes
.info .next .back
[0] 17 3 1
[1] 4 2 NUL
[2] 25 NUL 1
[3]
[4]
[5]
[6]
[7]
[8]
[9]

17. Static binding is the determination of which function to call at compile time;
dynamic binding is the determination of which function to call at run tim

Chapter 7
1. (a) The base case is a nonrecursive exit from the recursive routine.
(b) The general (or recursive) case is a path that includes a recursive call to the
routine, to solve a smaller version of the original problem.
(c) The run-time stack is a structure that keeps track of the activation records at
run time, in order to preserve the values of parameters, return addresses,
registers, and so on.
(d) Binding time refers to the point in the compile/execution cycle when variable
names are associated with addresses in memory.
(e) Tail recursion occurs when the recursive call is the last statement executed in
a recursive function.
4. Answering yes to Question 1 provides us with a base case that works correctly.
In answering Question 3, we make an assumption that the function works for
some artibary case. We can then show that applying the function to the next
value results in the correct answer in the general case.
7. (a) The base cases are return ­1 and return 1.
(b) The general case is return base*Puzzle(base+1, limit).
10. (a)
int Power(int base, int exponent)
// Returns the base raised to the exponent
{
  if (exponent == 0)
    return 1; // base case
  else
    return base * Power(base, exponent­1); // general case
}
(b)
int Factorial(int number)
// Returns the factorial of number (number!)
{
  if (num > 0)
    return num * Factorial(num ­ 1); // general case
  else
    if (num == 0)
      return 1; // base case
}  
(c)
void Sort(int values[], int fromIndex, int toIndex)
// Sorts values from values[fromIndex] .. values[toIndex].
// The maximum value left in the unsorted portion is put into 
its 
// proper place on each call.
{
  int maxIndex;

  if (fromIndex != toIndex)
  { // general case
    maxIndex =  MaxPosition(values, fromIndex, toIndex);
    Swap(values[maxIndex], values[toIndex]);
    Sort(values, fromIndex, toIndex ­ 1);
  }
// base case is when fromIndex equals toIndex:  do nothing
}
13. (a)
int Fibonacci(int number)
{
  if (number <= 1)
    return number;
  else
    return Fibonacci(number ­ 2) + Fibonacci(number ­ 1);
}
(b)
int Fibonacci(int number)
{
  int current;
  int previous;
  int temp;

  if (number <= 1)
    return 1;
  else
  {
    previous = 0;
    current = 1;
    for (int count = 2; count <= number; count++)
    {
      temp = previous;
      previous = current;
      current = temp + previous;
    }
    return current;
  }
}
(c)
#include <iostream>
int Fibonacci(int number);
int main()
{
  using namespace std;
  int number;
  cout << "Input the fibonacci number you wish." << endl;
     << "Input a negative number to quit."  << endl;
  cin  >> number;
  while (number >= 0)
  {
    cout  << "number: "  << number  << endl;
        << "Fibonacci number: "  << Fibonacci(number)  << endl;
    cout << "Input the fibonacci number you wish." << endl;
       << "Input a negative number to quit."  << endl;
    cin  >> number;
  }
  return 0;
}
// Put the function version you are testing here.
(d) The recursive solution is inefficient because some of the intermediate values
are calculated more than once.
(e) The following version, which uses an auxiliary recursive function, is more
efficient. Note that the recursive parameters are used to keep track of the current
and previous numbers, rather than recalculating them.
int Fibonacci(int number)
{
  return Fib(number, 1, 1);
}
int Fib(int number, int previous, int current)
{
  if (number == 0)
    return previous;
  else
    return Fib(number ­ 1, current, current + previous)
}
16. (a)
// corrected version
int NumPaths(int row, int col, int n)
{
  if (row == n || col == n)
    return 1
  else
    return NumPaths(row + 1, col, n) + NumPaths(row, col + 1, 
n);
}.
(b) The algorithm is inefficient because it calculates some of the intermediate
values of NumPaths more than once.
(c)
const int MAX = 10;
int table[MAX][MAX];
.
.
.
int NumPaths2(int row, int col, int n)
{
  if (row == n || col == n)
    table[row][col] = 1;
  else if (table[row][col] == 0)
    table[row][col] = NumPaths2(row+1, col, n) +
      NumPaths2(row, col+1, n)
  return table[row][col];

(d)
// initialize table
  for (int i = 0; i < MAX; i++)
    for (int j = 0; j < MAX, j++)
      table[i][j] = 0;
// solve problem
  answer = NumPaths2(l, l, MAX);
(e) The second version is more efficent in terms of execution time, but requires
additional space for an N x N array of integers.

19. Binding time refers to the point in the compile/execute cycle when variable
names are associated with addresses in memory. For recursion to be possible,
parameters must be bound to addresses at run time, not at compile time.
22. (a) False. Recursive solutions are often less efficient in terms of computing time.
(b) True
(c) False. Recursive solutions generally require more space in the run-time
stack.
(d) True. (Don't you want a good grade in this course?)

Chapter 8
2. (c) is the correct answer
5. (a) 30 (5 different shapes with 6 different combinations of values for each)
(b) 5 (5 different shapes with one legal combinations of values for each)
10. Show what order the nodes in the tree are processed by
(a) BDJKMNPQRTWY
(b) BJDNPMKRWYTQ
(c) QKDBJMPNTRYW
13. (a) The path would go through the nodes containing 56, 69, 59, 62, and 61.
(b) The path would go through the nodes containing 56, 47, 22, 29, and 23,
before determining that 28 is not in the tree.
14. (a) 11 22 23 29 30 47 49 56 59 61 62 64 69
(b) 11 23 30 29 22 49 47 61 64 62 59 69 56
(c) 56 47 22 11 29 23 30 49 69 59 62 61 64
17. (a) False
(b) False
(c) True
(d) False
19. (a) Elements inserted in random order:
Linked list: O(N)
Binary search tree: O(log2N)
(b) Elements inserted in order:
Linked list: O(N)
Binary search tree: O(N)
22
template<class ItemType>
void DeleteNode(TreeNode<ItemType>*& tree)
// Deletes the node pointed to by tree.
// Post: The user's data in the node pointed to by tree is no 
//     longer in the tree.  If tree is a leaf node or has one 
NULL 
//     child pointer
//     the node pointed to by tree is deleted; otherwise, the 
//     user's data is replaced by its logical successor and the
//     successor's node is deleted.
{
  TreeNode<ItemType>* tempPtr;
  ItemType data;

  tempPtr = tree;
  if (tree­>left == NULL)
    tree = tree­>right;
  else if (tree­>right == NULL)
    tree = tree­>left;
  else
  {
    tempPtr = PtrToSuccessor(tree);
    tree­>info = tempPtr­>data;
  }
  delete tempPtr;

24. 1. The Base-Case Question: Yes. The base case occurs when the node to be deleted
has been found, when item equals tree­>info. In this case we call the
DeleteNode function; no further recursive calls are made.
2. The Smaller-Caller Question: Yes. In each of the two general cases, a recursive
call is made to delete the element from a subtree, left or right, of the current tree.
Deleting from a subtree is a smaller version of the problem.
3. The General Case Question: Yes. If item is less than tree­>info, then we
know that the node to be deleted is in tree's left subtree. Assuming that the
recursive call successfully deletes from the left subtree, the problem is solved
correctly. Otherwise, if item is greater than tree­>info, we know that the
node to be deleted is in tree's right subtree. Again, assuming that the recursive
call successfully deletes from the right subtree, the problem is solved correctly.
27.
template<class ItemType>
void PrintAncestors(TreeNode<NodeType>* tree, ItemType value) 
const;
// prototype
template<class ItemType>
void TreeType<ItemType>::Ancestors(ItemType value) const
// Calls recursive function PrintAncestors to print the 
ancestors.
{
  PrintAncestors(root, value);
}

template<class ItemType>
void PrintAncestors(TreeNode<NodeType>* tree, ItemType value) 
const
{
  if (tree­>info != value)
  {
    std::cout << tree­>info << endl;
    if (tree­>info < value)
      PrintAncestors(tree­>right, value);
    else
      PrintAncestors(tree­>left, value);
  }
}
30.
int LeafCount(); // prototype
// Post: Function value = number of leaf nodes in the tree.
template<class ItemType>
int Count(TreeNode<ItemType>* tree); // prototype

template<class ItemType>
int TreeType<ItemType>::LeafCount()
// Calls recursive function Count to count the number 
//  of leaf nodes.
{
  return Count(root);
}

template<class ItemType>
int Count(TreeNode<ItemType>* tree)
{
  if (tree == NULL)
    return 0;
  else if (tree­>left == NULL) && (tree­>right == NULL)
    return 1;
  else
    return Count(tree­>left) + Count(tree­>right);
}
33. (a)
bool SimilarTrees(TreeType<ItemType> otherTree); // 
prototype
// Post: True is returned if self and otherTree are similar; 
false 
//     is returned otherwise.
template<class ItemType>
bool Similar(TreeType<ItemType>* tree1, TreeType<ItemType>* 
tree2);
// prototype
// Recursive function to determine if two trees are similar.
(b)
template<class ItemType>
bool TreeType<ItemType>::SimilarTrees(TreeType<ItemType> 
otherTree)
{
  return Similar(root, otherTree.root);
}
template<class ItemType>
bool Similar(TreeNode<ItemType>* tree1, TreeNode<ItemType>* 
tree2);
{
  if (tree1 == NULL && tree2 == NULL)
    return true;
  else if (tree1 == NULL && tree2 != NULL) ||
    (tree1 != NULL && tree2 == NULL)
    return false;
  else
    return Similar(tree1­>left, tree2­>left) &&
     Similar(tree2­>right, tree2­>right);
}
35.
template<class ItemType>
void MakeTree(TreeType<ItemType>& tree, int info[], int length)
// Creates a binary tree from a sorted array.
{
  tree.MakeEmpty();
  AddElements(tree, info, 0, length­1);
}

template<class ItemType>
void AddElements(TreeType<ItemType>& tree, ItemType info[], 
   int fromIndex, int toIndex)
{
  int midIndex;

  if (fromIndex <= toIndex)
  {
  midIndex = (fromIndex + toIndex) / 2;
  tree.InsertItem(info[midIndex]);
  AddElements(tree, info, fromIndex, midIndex ­ 1);
  // Complete the left subtree.
  AddElements(tree, info, midIndex+1, toIndex);
  // Complete the right subtree.
  }
}
38. Either the value in node 5 or the value in node 6.
40. Preorder
43. (a) Any negative number can be used as a dummy value.
(b) Assume that the dummy value is -1.0.
tree
.numElements 13

.nodes [0] 26
[1] 14
[2] 38
[3]  1
[4] ­1
[5] 33
[6] 50
[7] ­1
[8]  7
[9] ­1
[10] 35
[11] 44
[12] 60
[13] ?
[14] ?
[15] ?

Chapter 9
2. The relational operator <= should be replaced with >=.
5. (a) The member functions would not change, but the private data members
would change. The only data member would be a pointer to a linked lists.
(b) The code for SortedType::InsertItem (linked implementation) can be
used directly with the relational operator reversed.
(c) The code is identical to StackType::Pop.
(d) Dequeue for a priority queue implemented as a linked list (ordered from
highest to lowest priority) is very simple and efficient; we have direct access to
the largest element. There is less work involved in fixing the structure after the
largest element is removed, because the next-largest element immediately
follows it. Thus the operation is 0(1). In the heap implementation we have
immediate access to the largest element, but we have to perform a reheap
operation to fix the structure, resulting in an O(log 2N) operation. The linked list
implementation is more efficient, in terms of Big O.
When the priority queue is implemented as a linked list, the efficiency of
Enqueue varies according to the position that the new element occupies in the
list. If the new element belongs in the last position, the whole list is searched
before the insert place is found. Thus the operation is O(N). Using heaps, the
insertion operation is O(log2N). The linked list implementation might be better if
the elements were inserted in largely sorted order from smallest to largest value.
8. (a) The highest-priority element is the one with the largest time stamp. (This
assumes that the time stamp never reaches INT_MAX.
(b)
Push

Assign the next largest time stamp to the new element


Put new element in the stack (position is unimportant)

Pop

Find the element with the largest time stamp


Assign this element to item (to be returned)
Remove the element
(c) The Push operation has O(1) because it doesn't matter where the item is stored in
the structure. The Pop operation has O(N), because the item with the largest
time stamp must be searched for.
Therefore, Push is the same in both implementations, but Pop is not. If the
priority queue is implemented using a heap with largest value the highest
priority, Pop and Push have O(log2N).
12.
EmployeeGraph
..vertices
.numVertices
.vertexList
[0] Brent
[1] Darlene
[2] Fran
[3] Fred
[4] Jean
[5] John
[6] Lance
[7] Mike
[8] Sander
[9] Susan
  .Edges
[0] F F F T F F T F F F
[1] F F F F F F F T F T
[2] F F F F F T T F T F
[3] T F F F F F F F F F
[4] F F F F F F T F F T
[5] F F T F F F F F F T
[6] T F T F T F F F F F
[7] F T F F F F F F F F
[8] F F T F F F F F F T
[9] F T F F T T F F T F
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]
14. "works with" is the best description of the relationship represented by the edges
between vertices in EmployeeGraph, because it is an undirected graph. The
other relationships listed have an order implicit in them.
17. The correct answer is (b). For example, a dalmatian is an example of a dog.
20. (a)
StateGraph
..vertices
.numVertices 7
.vertexList
[0] Alaska
[1] Californi
a
[2] Hawaii
[3] New York
[4] Oregon
[5] Texas
[6] Vermont
  .Edges
[0] F F F F T F F
[1] F F F F F F F
[2] T T F T F T F
[3] F F F F F F F
[4] F F F F F F F
[5] F F T F F F T
[6] T T F T F F F
[0] [1] [2] [3] [4] [5] [6]

(b)
..vertices
.numVertices 7
.vertexList
[0] Alaska ­> 4 /
[1] Californi
a
[2] Hawaii ­> 1 ­­ ­> 3 ­­ ­> 5 ­­ ­> 0 /
­ ­ ­
[3] New York
[4] Oregon
[5] Texas ­> 2 ­­ ­> 6 /
­
[6] Vermont ­> 0 ­­ ­> 1 ­­ ­> 3 /
­ ­

23. Deleting a vertex is more complicated than deleting an edge for two reasons.
First, in addition to removing the vertex from the set of vertices, we must also
remove the edges to all its adjacent vertices in the set of edges. Second, we must
dedecide what to do about the now unused vertex number. The best solution is
to keep a list of returned vertex numbers and assign new numbers from there
first.
25. Implicit set representations represent those items that are present in an instance
of a set explicitly; those items that are not represented are not in the set. Explicit
set representations associate a place (bit or Boolean flag) for each item in the base
type in the instance of each set . The place for an item is true if the item is in the
set and false if the item is not in the set.
Chapter 10
1.
(a) BubbleSort
4 5 7 10 43 14 18 23 19 66
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]
(b) SelectionSort
4 5 7 10 18 43 19 23 66 14
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]
(c) InsertionSort
7 10 23 43 18 4 19 5 66 14
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

4. (a) bubble sort


(b) selection sort
(c) insertion sort
7. The correct answer is (c).
10. (a) Bubble sort is O(N) if the values are already sorted, and if the algorithm stop
processing when the sorting is complete (like ShortBubble).
(b) None.
(c) QuickSort is O(N 2) if the values are already sorted and the split algorithm
causes the array to be split into one element and the rest of the array.
13. (a) True
(b) False. HeapSort is better for nearly sorted data than QuickSort.
(c) True
16. The correct answer is (b).
19. The code is identical to the one in the book with the relational operator in the
comparison changed.
22. Declare an array indexed from 0 through 99. Use the slots in the array as
counters for that percentile score; that is, the slot indexed by 0 is the counter for
percentile scores of 0; the slot indexed by 2 is the counter for percintile scores of
2; and so on. To produce the required output, go through the array from 99
down to 0, printing the loop counter as many times as there are values in that
slot.
25. (a) for the best case. O(1)
(b) for the worst case. O(N2)
28.
dataValues
14 27 95 12 26 5 33 15 9 99
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]

sortedValues
5 9 12 14 15 26 27 33 95 99
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]
Search  Search Binary­
dataValues sortedValues Search
sequentially sequentially sortedValues
8 5 1 4
10 6 3 4
  14 1 4 4 1
6 1 3 3
10 10 4 4
10 10 4 4
1 3 3

31.
HashTable
[0] 90 140 620
[1]
[2]
[3] 153 393
[4]
[5] 145 285 395
[6] 66 126 566
[7] 47 87 177
[8] 467 735

34. The correct answer is (a)


37. (a) 50
(b) 50
(c) 50.
40. The correct answer is (c).
43. No. Simply substituting the StackADT for the QueueADT would not work. The
elements would be gathered in the wrong order.

You might also like