Você está na página 1de 8

CPSC 490

Input
Input will always arrive on stdin. You may assume input is well-formed with respect to the problem specication;
inappropriate input (e.g. text where a number was specied, number out of range, string too long) may be handled
by crashing. Normally you want to read input a word at a time:
C++ Java
#i nc l ude <i ostream>
#i nc l ude <s t r i ng >
us i ng namespace std ;
. . .
i nt i ; s t r i ng s ; doubl e d ;
ci n >> i >> s >> d ;
// Check f o r endof f i l e
i f ( ci n >> var ) // read OK
e l s e // EOF
i mport j ava . u t i l . ;
. . .
Scanner s c = new Scanner ( System . i n ) ;
i nt i = s c . next I nt ( ) ;
St r i ng s = s c . next ( ) ;
doubl e d = s c . nextDoubl e ( ) ;
// Check f o r endof f i l e
i f ( s c . hasNext ( ) ) // can read
e l s e // EOF
Occasionally you want to deal with a line at a time instead (e.g. dealing with strings that might have whitespace in
them or variable numbers of words without counts specied):
C++ Java
#i nc l ude <i ostream>
#i nc l ude <s t r i ng >
us i ng namespace std ;
. . .
s t r i ng l i n e ;
g e t l i ne ( ci n , l i n e ) ;
i mport j ava . u t i l . ;
. . .
Scanner s c = new Scanner ( System . i n ) ;
St r i ng l i n e = s c . nextLi ne ( ) ;
NOTE: If you use both word-based and line-based functions in the same program, if you reach the end of a line using
the word-based functions, the line-based functions will see an empty line before the following line. Therefore, if you
do this, call the line function one extra time and discard its output. For example, given the following input le:
17
The qui ck brown f ox jumps over the l azy dog .
the following code will parse it properly:
C++ Java
#i nc l ude <i ostream>
#i nc l ude <s t r i ng >
us i ng namespace std ;
. . .
i nt number ;
s t r i ng s ent ence ;
ci n >> number ;
// Di scard the pseudol i n e
g e t l i ne ( ci n , s ent ence ) ;
// Read the r e a l l i n e
g e t l i ne ( ci n , s ent ence ) ;
i mport j ava . u t i l . ;
. . .
Scanner s c = new Scanner ( System . i n ) ;
i nt number = s c . next I nt ( ) ;
// Di scard the pseudol i n e
s c . nextLi ne ( ) ;
// Read the r e a l l i n e
St r i ng s ent ence = s c . nextLi ne ( ) ;
1
Output
Output always goes to stdout. For most problems, the output your program generates must be exactly byte-for-byte
identical to the correct output. This means the following will result in errors:
wrong answers
incorrect spelling
incorrect capitalization
incorrect number of decimal places
incorrect use of whitespace, including blanks at end of line
confusing a blank line between test cases with a blank line after each test case
The following example prints out the following (excluding the braces): {$1234 hello world 27.35} and then moves
to the next line.
C++ Java
#i nc l ude <i ostream>
us i ng namespace std ;
. . .
i nt do l l a r s = 1234;
doubl e f oo = 2 7. 35;
s t r i ng word = he l l o ;
// # deci mal pl ac e s f o r doubl es &
// f l o a t s
cout << f i xe d << s e t pr e c i s i o n ( 2 ) ;
cout << $ << do l l a r s <<
<< word << worl d << f oo << endl ;
i mport j ava . u t i l . ;
. . .
i nt do l l a r s = 1234;
doubl e f oo = 27. 35;
St r i ng word = he l l o ;
// # deci mal pl ac e s f or doubl es & f l o a t s
// i ns i de f ormat s t r i ng
System . out . pr i nt f ( $%d he l l o %s %.2 f \n ,
dol l ar s , word , f oo ) ;
2
Containers: Lists
A list stores a collection of items (of the same type) in an order specied as the items are added. Each item has
a position in the list, and is normally identied by its position (positions are counted starting from zero). Lists
generally allow duplicates.
If you have a reasonable upper bound on the amount of data and you dont need to store the exact size (e.g. because
its implied by other parts of the problem), consider using a simple array declared to be the maximum size. In Java,
dynamically allocating arrays with sizes not known at compile time can be useful; in C++ you have to remember to
free such arrays manually so vectors are often a better choice.
One more advanced list is the vector, which is implemented on top of an array which is reallocated as needed. Vectors
are fast for nding an element by its position and adding and removing elements at the end of the list, but slow for
nding an element by its value and adding and removing elements other than at the end of the list.
C++ Java
#i nc l ude <vector >
us i ng namespace std ;
. . .
vector <i nt > numbers ;
numbers . push back ( 5 ) ;
numbers . push back ( 7 ) ;
// I ns e r t i n the mi ddl e (SLOW! ) :
numbers . i ns e r t ( numbers . begi n ( ) + 1 , 6 ) ;
a s s e r t ( numbers . s i z e ( ) == 3 ) ;
a s s e r t ( numbers [ 0 ] == 5 ) ;
a s s e r t ( numbers [ 1 ] == 6 ) ;
a s s e r t ( numbers [ 2 ] == 7 ) ;
numbers . c l e a r ( ) ;
a s s e r t ( numbers . empty ( ) ) ;
i mport j ava . u t i l . ;
. . .
Li s t <I nt eger > numbers =
new ArrayLi st <I nt eger >();
numbers . add ( 5 ) ;
numbers . add ( 7 ) ;
// I ns e r t i n the mi ddl e (SLOW! ) :
numbers . add ( 1 , 6 ) ;
a s s e r t ( numbers . s i z e ( ) == 3 ) ;
a s s e r t ( numbers . get ( 0) == 5 ) ;
a s s e r t ( numbers . get ( 1) == 6 ) ;
a s s e r t ( numbers . get ( 2) == 7 ) ;
numbers . c l e a r ( ) ;
3
Another type of list is the linked list, which is implemented as a string of nodes each of which knows how to nd the
node before and after itself. Linked lists are fast for inserting and removing elements anywhere (at the beginning or
end or any location at which one holds an iterator) and iterating forward or backwards through all elements, but
slow for nding an element by its position or value.
C++ Java
#i nc l ude <l i s t >
us i ng namespace std ;
. . .
l i s t <i nt > numbers ;
numbers . push back ( 7 ) ;
numbers . pus h f r ont ( 5 ) ;
// Get i t e r a t o r by po s i t i o n (SLOW! ) :
l i s t <i nt >: : i t e r a t o r i t e r
= numbers . begi n ( ) + 1;
a s s e r t ( i t e r == 7 ) ;
// I ns e r t be f or e i t e r a t o r ( f a s t ) :
numbers . i ns e r t ( i t e r , 6 ) ;
a s s e r t ( numbers . s i z e ( ) == 3 ) ;
// Get el ements by po s i t i o n (SLOW! ) :
a s s e r t ( ( numbers . begi n ( ) + 0) == 5 ) ;
a s s e r t ( ( numbers . begi n ( ) + 1) == 6 ) ;
a s s e r t ( ( numbers . begi n ( ) + 2) == 7 ) ;
i mport j ava . u t i l . ;
. . .
Li s t <I nt eger > numbers =
new Li nkedLi st <I nt eger >();
numbers . add ( 7 ) ; // at end
numbers . add ( 0 , 5 ) ; // at s t a r t
// Get i t e r a t o r by pos i t i on (SLOW! ) :
Li s t I t e r a t o r <I nt eger > i t e r =
numbers . l i s t I t e r a t o r ( 1 ) ;
a s s e r t ( i t e r . next ( ) == 7 ) ;
// The i t e r a t o r moved . Move i t back .
i t e r . pr evi ous ( ) ;
// I ns e r t be f or e i t e r a t o r ( f a s t ) :
i t e r . add ( 6 ) ;
a s s e r t ( numbers . s i z e ( ) = 3 ) ;
// Get el ements by pos i t i on (SLOW! ) :
a s s e r t ( numbers . get ( 0) == 5 ) ;
a s s e r t ( numbers . get ( 1) == 6 ) ;
a s s e r t ( numbers . get ( 2) == 7 ) ;
These are the general-purpose lists. There is also a deque, or double-ended queue, which provides slightly dierent
services in C++ and in Java. In C++, deque acts very like a vector except allowing fast adding and removing of
elements at both ends (not only the back). In Java, ArrayDeque (added in version 1.6.0) also allows adding and
removing elements at both ends, but does not allow eciently accessing an element by its position. In this course,
deques may be used in certain special cases where the front-and-back semantics are required, but we will not be
accessing elements by position.
C++ Java
#i nc l ude <deque>
us i ng namespace std ;
. . .
deque<i nt > numbers ;
numbers . push back ( 7 ) ;
numbers . push back ( 8 ) ;
numbers . pus h f r ont ( 6 ) ;
numbers . pus h f r ont ( 5 ) ;
a s s e r t ( numbers . s i z e ( ) == 4 ) ;
f or ( i nt i = 5; i <= 8; i ++) {
a s s e r t ( numbers . f r ont ( ) == i ) ;
numbers . pop f r ont ( ) ;
}
i mport j ava . u t i l . ;
. . .
Deque<I nt eger > numbers =
new ArrayDeque<I nt eger >();
numbers . addLast ( 7 ) ;
numbers . addLast ( 8 ) ;
numbers . addFi r s t ( 6 ) ;
numbers . addFi r s t ( 5 ) ;
a s s e r t ( numbers . s i z e ( ) == 4 ) ;
f or ( i nt i = 5; i <= 8; i ++) {
a s s e r t ( numbers . pe ekFi r s t ( ) == i ) ;
numbers . removeFi rst ( ) ;
}
4
Finally, there is the queue, which is similar to a deque but is intended for use in situations where all elements are
added at one end and removed at the otherin other words, a FIFO. In C++, queue is a class which uses a template
parameter to choose which implementation to use (typical choices are list and deque, with deque being the default).
In Java, Queue is an interface implemented by both LinkedList and ArrayDeque.
C++ Java
#i nc l ude <queue>
us i ng namespace std ;
. . .
queue<i nt > numbers ;
numbers . push ( 5 ) ;
numbers . push ( 6 ) ;
numbers . push ( 7 ) ;
numbers . push ( 8 ) ;
a s s e r t ( numbers . s i z e ( ) == 4 ) ;
f or ( i nt i = 5; i <= 8; i ++) {
a s s e r t ( numbers . f r ont ( ) == i ) ;
numbers . pop ( ) ;
}
i mport j ava . u t i l . ;
. . .
Queue<I nt eger > numbers =
new ArrayDeque<I nt eger >();
numbers . add ( 5 ) ;
numbers . add ( 6 ) ;
numbers . add ( 7 ) ;
numbers . add ( 8 ) ;
a s s e r t ( numbers . s i z e ( ) == 4 ) ;
f or ( i nt i = 5; i <= 8; i ++) {
a s s e r t ( numbers . peek ( ) == i ) ;
numbers . remove ( ) ;
}
5
Containers: Maps
Maps are collections of key-value pairs, optimized for looking up the value associated with a known key. There are
two variants: hashtables perform most operations faster (many in constant time) but do not keep their keys in sorted
order, while trees are slower (performing most operations in logarithmic time) but keep their keys sorted, which
may be useful for iteration. Maps normally do not allow duplicate keys. In general trees are fast enough for most
purposes, and dening hash functions in C++ is somewhat nonintuitive. Therefore, we will use trees in this class:
C++ Java
#i nc l ude <map>
us i ng namespace std ;
. . .
map<s t r i ng , i nt > days ;
// Add el ements :
days [ Monday] = 1;
days [ Tuesday ] = 2;
days [ Wednesday ] = 3;
days [ Thursday ] = 4;
days [ Fri day ] = 5;
days [ Saturday ] = 6;
days [ Sunday ] = 7;
// Check pr es ence :
a s s e r t ( days . count (Monday) == 1 ) ;
a s s e r t ( days . count (NotADay) == 0 ) ;
// Get val ues :
a s s e r t ( days [ Monday] == 1 ) ;
a s s e r t ( days [ Tuesday ] == 2 ) ;
// I t e r a t e keys i n or der of <:
map<s t r i ng , i nt >: : i t e r a t o r i , i end ;
f or ( i = days . begi n ( ) ,
i end = days . end ( ) ; i != i end ; ++i ) {
s t r i ng key = i >f i r s t ;
i nt val ue = i >second ;
}
// Erase by key .
days . e r as e ( Tuesday ) ;
i mport j ava . u t i l . ;
. . .
Map<St ri ng , I nt eger > days =
new TreeMap<St ri ng , I nt eger >();
// Add el ements :
days . put (Monday , 1 ) ;
days . put ( Tuesday , 2 ) ;
days . put (Wednesday , 3 ) ;
days . put ( Thursday , 4 ) ;
days . put ( Fri day , 5 ) ;
days . put ( Saturday , 6 ) ;
days . put ( Sunday , 7 ) ;
// Check pr es ence :
a s s e r t ( days . contai nsKey (Monday ) ) ;
a s s e r t ( ! days . contai nsKey (NotADay ) ) ;
// Get val ues :
a s s e r t ( days . get (Monday) == 1 ) ;
a s s e r t ( days . get ( Tuesday ) == 2 ) ;
// I t e r a t e keys i n or der of Comparable :
f or (Map. Entry<St ri ng , I nt eger > i
: days . ent r ySet ( ) ) {
St r i ng key = i . getKey ( ) ;
i nt val ue = i . getVal ue ( ) ;
}
// Erase by key .
days . remove ( Tuesday ) ;
6
Containers: Sets
A set is a map without values: its only purpose is to contain values (not allowing duplicates) and permit ecient
checking of whether or not a value is contained in the set. As with maps, typical implementations are hashtable-based
or tree-based. Again, hashtables keep their values unordered but are faster, while tree-based sets keep their values
in their natural order, and we will use tree sets in most cases for this class to avoid dening hash functions.
C++ Java
#i nc l ude <set >
us i ng namespace std ;
. . .
set <s t r i ng > words ;
// Add el ements :
words . i ns e r t (Foo ) ;
words . i ns e r t ( Bar ) ;
words . i ns e r t (Baz ) ;
// Check pr es ence :
a s s e r t ( words . count (Foo) == 1 ) ;
a s s e r t ( words . count (Quux) == 0 ) ;
// I t e r a t e el ements i n or der of <:
set <s t r i ng >: : i t e r a t o r i , i end ;
f or ( i = words . begi n ( ) ,
i end = words . end ( ) ;
i != i end ; ++i ) {
s t r i ng elem = i ;
}
// Erase by el ement .
days . e r as e (Baz ) ;
i mport j ava . u t i l . ;
. . .
Set<St ri ng> words =
new TreeSet<St ri ng >();
// Add el ements :
words . add(Foo ) ;
words . add( Bar ) ;
words . add(Baz ) ;
// Check pr es ence :
a s s e r t ( days . cont ai ns (Foo ) ) ;
a s s e r t ( ! days . cont ai ns (Quux ) ) ;
// I t e r a t e el ements i n or der of
// Comparable :
f or ( St r i ng elem : words ) {
// . . .
}
// Erase by el ement .
words . remove (Baz ) ;
7
Sorting: Natural and Custom Orders
Every data type can have a natural ordering, which is used to determine in which order objects of that type should
be sorted. Data types can also have any number of custom orderings, which can be explicitly used to sort objects in
a dierent order. Functions are available in the standard libraries to eciently sort arrays and vectors (quicksort).
C++ Java
#i nc l ude <set >
#i nc l ude <map>
#i nc l ude <vector >
#i nc l ude <al gori thm>
#i nc l ude <s t r i ng >
us i ng namespace std ;
. . .
// Def i ne a custom type :
c l a s s mytype {
publ i c :
i nt f oo ;
s t r i ng bar ;
};
// Natural or der i ng :
// Returns t r ue i f x < y ,
// f a l s e i f x >= y .
bool operator <( cons t mytype &x ,
cons t mytype &y) {
i f ( x . f oo != y . f oo )
r et ur n x . f oo < y . f oo ;
e l s e r et ur n x . bar < y . bar ;
}
// Custom or der i ng :
bool ot her or der ( cons t mytype &x ,
cons t mytype &y) {
i f ( x . bar != y . bar )
r et ur n x . bar < y . bar ;
e l s e r et ur n x . f oo < y . f oo ;
}
// Custom or der s e t /map:
set <mytype , t ypeof (&ot her or der )>
s(&ot her or der ) ;
map<mytype , s t r i ng ,
t ypeof (&ot her or der )> m(&ot her or der ) ;
// Sor t i ng :
vector <mytype> vec ;
mytype ary [ 2 7 ] ;
s or t ( v . begi n ( ) , v . end ( ) ) ;
s or t ( v . begi n ( ) , v . end ( ) , &ot her or der ) ;
s or t ( ary , ary + 27) ;
s or t ( ary , ary + 27 , &ot her or der ) ;
i mport j ava . u t i l . ;
. . .
// Def i ne a custom type :
c l a s s MyType i mpl ements Comparable {
publ i c i nt f oo ;
publ i c St r i ng bar ;
// Natural or der i ng : r e t ur ns >0 f o r >,
// 0 f or =, <0 f o r <
publ i c i nt compareTo (MyType ot her ) {
i f ( f oo != ot her . f oo )
r et ur n f oo ot her . f oo ;
e l s e
r et ur n bar . compareTo ( ot her . bar ) ;
}
}
// Custom or der i ng :
c l a s s OtherOrder i mpl ements
Comparator<MyType> {
publ i c i nt compare (MyType x , MyType y)
{
i f ( ! x . bar . equal s ( y . bar ) )
r et ur n x . bar . compareTo ( y . bar ) ;
e l s e
r et ur n x . f oo y . f oo ;
}
}
// Custom or der s e t /map:
new TreeSet<MyType>(new OtherOrder ( ) ) ;
new TreeMap<MyType , Stri ng >(
new OtherOrder ( ) ) ;
// Sor t i ng :
Li s t <MyType> vec ;
MyType [ ] ary ;
Co l l e c t i o ns . s or t ( vec ) ;
Co l l e c t i o ns . s or t ( vec , new OtherOrder ( ) ) ;
Arrays . s or t ( ary ) ;
Arrays . s or t ( ary , new OtherOrder ( ) ) ;
8

Você também pode gostar