Documentos de Académico
Documentos de Profesional
Documentos de Cultura
R 8.3
B::B(3)
B::B();
B::B(-3)
D::D(3)
private member b gets initialized at output line 2 (it was not in the initializer list)
R 8.4
legal: B is a D
illegal: a D is not necessarily a B
illegal: a D* is not a B*
legal: a B* is a D*
a D is not a D*
legal
illegal: a D is not necessarily a B
R 8.7
b.p();
//
statically
bound
b.q();
//
statically
bound
d.p();
//
statically
bound
d.q();
//
statically
bound
pb->p();
//
dynamically
bound
pb->q();
//
statically
bound
pb->q();
//
statically
bound
pd->p();
//
dynamically
bound
pd->q();
//
statically
bound
pd2->p();
//
dynamically
bound
pd2->q();
//
statically
bound
Chapter 9 Streams (pp. 402-409)
R 9.1
#include<iostream>
#include<fstream>
#include<string>
using
namespace
std;
int
main(){
ofstream
out(Hello.txt);
out
<<
Hello
World!\n;
out.close();
string
message;
ifstream
in(Hello.txt);
getline(in,
message);
return
0;
}
R 9.8
#include<sstream>
#include<string>
using
namespace
std;
string
convert(double
d){
ostringstream
oss;
oss
<<
d;
return
oss.str();
}
double
convert(string
s){
double
d;
istringstream
iss(s);
iss
>>
d;
return
d;
}
int
main(){
double
x
=
convert(3.14);
string
s
=
convert(3.14);
return
0;
}
Chapter 10 Recursion (pp. 437-442)
R 10.7
#include<assert.h>
using
namespace
std;
double
raise(double
x,
unsigned
int
n){
assert(x
>
=
0);
//
base
case
if(n
==
0)
return
1;
else{
return
x*raise(x,
n-1);
}
}
P 10.7
#include<iostream>
#include<vector>
#include<assert.h>
using
namespace
std;
int
maximum(vector<int>
values){
assert(values.size()
>
0);
//
base
case
if(values.size()
==
1)
return
values[0];
else{
//
recursive
case
int
last
=
values.back();
values.pop_back();
int
max_rest
=
maximum(values);
if(last
>
max_rest)
return
last;
else
return
max_rest;
}
}
int
main(){
int
nums[]
=
{1,
4,
2,
9,
8,
5,
0};
//
elements
of
numbers
are
the
values
of
nums
//
arguments
in
vector
constructor
are
pointers
//
to
array
elements
in
nums
(nums+7
is
after
0)
vector<int>
numbers(nums,
nums+7);
cout
<<
maximum(numbers)
<<
endl;
return
0;
}
P 10.10
#include<iostream>
#include<vector>
#include<assert.h>
#include<string>
using
namespace
std;
vector<string>
generate_substrings(string
s){
vector<string>
substrings;
//
base
case
if(s.length()
==
0)
{
substrings.push_back("");
return
substrings;
}
//
recursive
case
else{
for(int
i
=
0;
i
<
s.length();
i++)
substrings.push_back(s.substr(0,
s.length()
-
i));
vector<string>
othersubstrings
=
generate_substrings(s.substr(1,s.length()-1
));
for(int
i
=
0;
i
<
othersubstrings.size();
i++){
substrings.push_back(othersubstrings[i]);
}
return
substrings;
}
}
int
main(){
vector<string>
subs
=
generate_substrings("rum");
for(int
i
=
0;
i
<
subs.size();
i++
){
cout
<<
"\""
<<
subs[i]
<<
"\",
";
}
cout
<<
endl;
return
0;
}
Chapter 11 Sorting and Searching (pp. 466-470)
R 11.3
a.
b.
c.
d.
e.
f.
g.
h.
i.
j.
O(n2)
O(n10)
O(n4)
O(n4)
O(n3)
O(n3)
O(n)
O(n2)
O(2n)
O(n)
R 11.5
T(1000) = 5
T(N) = cN for some c > 0 and for all N sufficiently large.
T(2000)/T(1000) = 2000c/1000c = 2
Thus T(2000) = 2T(1000) = 2(5) = 10 sec
T(10000)/T(1000) = 10000c/1000c = 10
So T(10000) = 10*T(1000) = 10(5) = 50 sec
R 11.6
1000
2000
3000
10000
O(n)
5
10
15
50
O(n2)
5
20
45
500
O(n3)
5
40
135
5000
O(nlogn)
5
11.00343332
17.38560627
66.66666667
O(2n)
5
5(21000)
5(22000)
5(29000)
3 4 4 5 5 7 11 7 11 9
3 4 4 5 5 7 7 11 11 9
3 4 4 5 5 7 7 9 11 11
3 4 4 5 5 7 7 9 11 11
R 11.15
a.
5 11 7 3 5 4 7 11 4 9
5 11 7 3 5
4 7 11 4 9
5 11 7 3 5
4 7 11 4 9
5 11 7
3 5 4 7 11 4 9
5 7 11 3 5
4 7 11 4 9
3 5 5 7 11
4 4 7 9 11
3 4 4 5 5 7 7 9 11 11
R 11.16
a.
-7 1 3 3 4 7 11 13
-7 1 3 3 4 7 11 13
-7 1 3 3 4 7 11 13
-7 1 3 3 4 7 11 13
-7 1 3 3 4 7 11 13
-7 1 3 3 4 7 11 13
b.
-7 2 2 3 4 7 8 11 13
7 8 11 13
c.
-7 1 2 3 5 7 10 13
5 7 10 13
10 13
R 12.7
List advantages over vectors
Adding or removing elements in the middle of a list is more efficient: O(1) time.
Vector advantages over lists
Random access of elements is more efficient: O(1) time.
R 12.8
Due to the large number of lookups, I would use a vector instead of a linked list
since random access of elements is more efficient.
R 12.9
A collection of appointments would have more insertion and removal operations
than lookup operations. Thus I would use a linked list instead of a vector to hold
a collection of appointment objects.
R 12.10
Since cards are removed from the top of the deck, but inserted at the bottom of
the deck, I would use a queue to store the cards.
R 12.12
Inserting an element in the middle of a list is a constant time operation. However,
since you would have to shift vector elements to the right of the inserted element
over by 1, insertion in the middle of a vector at index k is an O(k) algorithm.
R 12.15
Standard Notation (SN) Polish Notation (PN)
3+4
+34
1x2+3
+*12 3
1x (2+3)
*1+23
(2-4) x (3+4)
*-24+34
1+2+3+4
+ + + 12 3 4
R 12.16
The first stack reverses the order of the strings. Starting with Z and ending at
A, these letters are pushed onto a second stack (with A ending on top).
Popping these letters form the second stack will make the strings appear in
alphabetical order.
R 12.17
When implementing a stack using a linked list, push and pop are both constant
time O(1) operations since insertion and removal of a list element are O(1) at the
beginning of the list
R 12.18
When implementing a stack using a vector,
push() (resp pop()) is usually constant time O(1) but occasionally much slower
O(N) since the push_back() (resp pop_back()) function for vector is what will be
used. When the vector does not need to resize itself before inserting (resp
removing) an element, push_back (resp pop_back()) is O(1). However, the
resize operation is O(N) due to the copy of the old dynamic array into the new
larger (resp smaller) dynamic array inside the vector object.
R 12.19
When implementing a queue using a linked list, pop is constant time O(1) since
removal of the first element of a linked list is always O(1).
When implementing a queue using a linked list, push is linear time O(N) since
insertion will be at the end of the list so we have to visit every node in the list with
an iterator to reach the penultimate element. The actual insertion at the end of
the linked list is O(1) provided we already have an iterator to the penultimate
element.
R 12.20
When implementing a queue using a vector, pop is usually constant time O(1) but
occasionally much slower O(N) (see R 12.18).
When implementing a queue using a vector, push is O(N) since we have to add
an element to the end of the vector (vector function push_back is usually O(1) but
occasionally O(N) thus, we say that push_back takes amortized O(1) time
which is written as O(1)+) and then shift all elements one position to the right (a
O(N) operation) before inserting the new element at index 0.
P 12.4
template<typename
T>
list<T>
merge(list<T>&
l1,
list<T>&
l2){
list<T>
merged;
list<T>::iterator
i
=
l1.begin();
list<T>::iterator
j
=
l2.begin();
while(
!(i
==
l1.end()
||
j
==
l2.end()
)
)
{
merged.insert(merged.end(),
*i);
++i;
merged.insert(merged.end(),
*j);
++j;
}
while(
!(i
==
l1.end()
)
){
merged.insert(merged.end(),
*i);
++i;
}
while(
!(j
==
l2.end()
)
)
{
merged.insert(merged.end(),
*j);
++j;
}
return
merged;}
P 12.7
//
using
List
class
defined
on
p.487
void
List::push_front(string
data){
insert(begin(),
data);
}
P 12.9
//
using
List
class
defined
on
p.487
unsigned
int
List::get_size()const{
unsigned
int
size
=
0;
for(Iterator
i
=
begin();
!(i.equals(end()));
i.next())
{
size++;
}
return
size;
}
P 12.11
R 13.1
set
R 13.2
map
R 13.3
multimap
R 13.4
Priority queue
R 13.6
Nodes should store data of type vector<T>
R 13.9
Adam
Eve
Dick
Romeo
Juliet Tom
Harry
P 13.3
P 13.6
P 13.10
Chapter 14 Operator Overloading (pp. 586-588)
R 14.5
When that operator needs access to private data. Certain operators such as the
assignment operator = and the compound assignment operators +=, -=, /=, *=,
%= must be member functions.
R 14.7
The operators << and >> cannot be defined as member functions since the
calling object of a member operator must be the left operand. For operator <<,
the left operand is an ostream object, not an object of your class,
R 14.8
There is a prefix and a postfix version for both the increment ++ and the
decrement -- operators. The function call operator () can also have multiple
versions.
R 14.9
The prefix operator returns a reference. The postfix operator returns a value.
Thus the prefix should be called when you have a choice since returning by
reference is more efficient.
R 14.13
You must override the assignment operator if objects of your class manage
dynamic (heap) memory to avoid a shallow copy. An object manages heap
memory if it contains pointers to variables defined on the heap.
recursion. If b were passed by reference, the copy constructor would not call
itself and thus would not cause an infinite chain of constructor calls.
Chapter 16 Templates (pp. 663-664)
R 16.2
a. Cannot deduce value of type parameter T from the function call
b. Redefinition of type parameter T (it appears twice in the template prefix)
c. Cannot not deduce the template argument from T2 from the function call.
R 16.3
You have to specify type parameters when you instantiate a class template, but
not when you instantiate a function template since template type parameter
values are inferred from the arguments in a template function call.
P 16.1
template<typename
T>
void
selection_sort(T
a[],
const
int
size){
T
smallest;
for(int
i
=
0;
i
<
size-1;
i++){
smallest
=
i;
//
find
the
index
of
the
smallest
unsorted
item
//
(ith
smallest
overall)
for(int
j
=
i+1;
j
<
size;
j++){
if(a[j]
<
a[smallest]){
smallest
=
j;
}
}
//
swap
the
ith
element
with
the
ith
smallest
element
T
temp
=
a[i];
a[i]
=
a[smallest];
a[smallest]
=
temp;
}
}