Download Answers to Selected Exercises

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

Lattice model (finance) wikipedia , lookup

Linked list wikipedia , lookup

B-tree wikipedia , lookup

Array data structure wikipedia , lookup

Binary search tree wikipedia , lookup

Transcript
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.
4.
7.
10.
14.
17.
20.
23.
Software engineering is a disciplined approach to the creation and maintenance
of computer programs throughout their whole life cycle.
Some software tools used in developing computer programs are text editors,
compilers, assemblers, operating systems, and debugging programs.
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).
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.
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.
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.
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.
(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
Initialize
Fraction is proper
-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
2
0 0
execute and print
0 0
0
no output
execute and print
50
50x50 matrix
execute and print
of zeros
StoreValue
MakeEmpty(2)
1,1,2
store
1,2,3
store
2,2,4
store
2 3
print
0 4
Add
General Case
1 2
Create a second matrix
3 4
3 5
Add to first one created and print
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
End Case (size 0)
Subtract two size 0 matrices and print
End Case (size 50)
Subtract all ones from all twos
Copy
Copy first and print
Copy a size 0 matrix and print
Copy a size 50 matrix of twos and print
-1 -1
3 0
no output
50x50 of ones
2 3
0 4
no output
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
int value;
value = 500;
char* charPtr;
char string[10] = "Good luck";
charPtr = string;
cout << &value;
// question
cout << value;
// question
cout << &charPtr; // question
cout << charPtr;
// question
What is
printed?
value is assigned to location
200
charPtr is at location 202
string[0] is at location 300
19
20
21
22
& means "the address of"
& means "the address of"
200
500
202
Good
l
u
c
k
cout << *charPtr; // question 23
cout << string[2]; // question 24
G
o
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.
3.
5.
8.
(a) Yes
(b) No
(c) Yes
(d) No
(e) Yes
(f) No
(g) No
(h) Yes
(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)
stack.Push(letter);
letter
X
letter
X
stack.top
4
stack.top
4
.overFlow
.overFlow
T
.underFlow
.underFlow
.items
A
B
C
D
E
.items
A
B
C
D
E
[0 [1 [2 [3 [4
[0 [1 [2 [3 [4
]
]
]
]
]
]
]
(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]
(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.
....
[197]
[198]
[199]
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:
Precondition:
Postcondition:
Determines whether the stack is full.
Stack has been initialized.
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
J
letter
J
queue.front
.rear
.overFlow
.underFlow
.items
4
3
queue.front
.rear
.overFlow
.underFlow
.items
4
3
T
V
W
X
Y
Z
[0 [1 [2 [3 [4
]
]
27. queue.Dequeue(letter);
letter
queue.front
.rear
.overFlow
.underFlow
.items
4
2
V
W
X
Y
Z
[0 [1 [2 [3 [4
]
]
]
]
]
V
W
X
Y
Z
[0 [1 [2 [3 [4
]
]
letter
V
queue.front
.rear
.overFlow
.underFlow
.items
0
2
]
]
]
F
V
W
X
Y
Z
[0 [1 [2 [3 [4
]
]
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.
6.
Member functions Enqueue and Dequeue would have to be changed.
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)
17
4
25
(c)
free
list
nodes
3
1
.info
17
4
25
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
.next
2
0
NUL
.back
1
NUL
0
.next
3
2
NUL
.back
(d)
free
list
nodes
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
0
1
.info
17
4
25
1
NUL
1
[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.
5.
10.
13.
14.
17.
19.
(c) is the correct answer
(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)
Show what order the nodes in the tree are processed by
(a) BDJKMNPQRTWY
(b) BJDNPMKRWYTQ
(c) QKDBJMPNTRYW
(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.
(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
(a) False
(b) False
(c) True
(d) False
(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]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
[10]
[11]
[12]
[13]
[14]
[15]
26
14
38
1
-1
33
50
-1
7
-1
35
44
60
?
?
?
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.
8.
(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(log2N) 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.
(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]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
F
F
F
T
F
F
T
F
F
F
F
F
F
F
F
F
F
T
F
T
F
F
F
F
F
T
T
F
T
F
T
F
F
F
F
F
F
F
F
F
F
F
F
F
F
F
T
F
F
T
F
F
T
F
F
F
F
F
F
T
T
F
T
F
T
F
F
F
F
F
F
T
F
F
F
F
F
F
F
F
F
F
T
F
F
F
F
F
F
T
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]
[4]
[5]
New York
Oregon
Texas
-> 2
/
-- -> 3
-
-- -> 5
-
-- -> 6
-
/
-- -> 0
-
/
[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
[0]
[1]
[2]
[3]
(b) SelectionSort
4
5
7
10
[0]
[1]
[2]
[3]
(c) InsertionSort
7
10
23
43
[0]
[1]
[2]
[3]
43
[4]
14
[5]
18
[6]
23
[7]
19
[8]
66
[9]
18
[4]
43
[5]
19
[6]
23
[7]
66
[8]
14
[9]
18
[4]
4
[5]
19
[6]
5
[7]
66
[8]
14
[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
[0]
[1]
95
[2]
12
[3]
26
[4]
5
[5]
33
[6]
15
[7]
9
[8]
99
[9]
sortedValues
5
9
[0]
[1]
12
[2]
14
[3]
15
[4]
26
[5]
27
[6]
33
[7]
95
[8]
99
[9]
Search
dataValues
sequentially
8
10
1
6
10
10
1
Values
15
17
14
5
99
100
0010
Search
sortedValues
sequentially
5
6
4
1
10
10
3
BinarySearch
sortedValues
1
3
4
3
4
4
3
Search
tree
31.
HashTable
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
90
140
153
393
145
66
47
467
285
126
87
735
620
395
566
177
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.
4
4
1
3
4
4