Use the code from the book (and from my notes) to implement a Stack ADT using a linked list.( https://github.com/IvoIvanov77/-Algorithms/blob/403289d0c471f157049d3279bbfe5917de69b4df/src/fundamentals/Evaluate.java ) Use this Stack to implement Dijkstra’s Two-Stack Algorithm for expression evaluation. This code is also given in the book and in my notes. You will need to change this code so that the algorithm is in a separate method for the evaluation. That is, read the input into a String variable that you pass to your method for evaluation.
To this code, add Junit test to test the Stack methods and to test the evaluate method.
META-INF/MANIFEST.MF
Manifest-Version: 1.0
Created-By: 1.8.0_222 (Oracle Corporation)
COPYING
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program–to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers’ and authors’ protection, the GPL clearly explains
that there is no warranty for this free software. For both users’ and
authors’ sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users’ freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
“This License” refers to version 3 of the GNU General Public License.
“Copyright” also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
“The Program” refers to any copyrightable work licensed under this
License. Each licensee is addressed as “you”. “Licensees” and
“recipients” may be individuals or organizations.
To “modify” a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a “modified version” of the
earlier work or a work “based on” the earlier work.
A “covered work” means either the unmodified Program or a work based
on the Program.
To “propagate” a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To “convey” a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays “Appropriate Legal Notices”
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The “source code” for a work means the preferred form of the work
for making modifications to it. “Object code” means any non-source
form of a work.
A “Standard Interface” means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The “System Libraries” of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
“Major Component”, in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The “Corresponding Source” for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work’s
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users’ Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work’s
users, your or third parties’ legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program’s source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
“keep intact all notices”.
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
“aggregate” if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation’s users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A “User Product” is either (1) a “consumer product”, which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, “normally used” refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
“Installation Information” for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
“Additional permissions” are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered “further
restrictions” within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An “entity transaction” is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party’s predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A “contributor” is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor’s “contributor version”.
A contributor’s “essential patent claims” are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, “control” includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor’s essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a “patent license” is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To “grant” such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. “Knowingly relying” means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient’s use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is “discriminatory” if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others’ Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License “or any later version” applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy’s
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the “copyright” line and a pointer to where the full notice is found.
Copyright (C)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w’.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c’ for details.
The hypothetical commands `show w’ and `show c’ should show the appropriate
parts of the General Public License. Of course, your program’s commands
might be different; for a GUI interface, you would use an “about box”.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a “copyright disclaimer” for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
edu/princeton/cs/algs4/Accumulator.java
edu/princeton/cs/algs4/Accumulator.java
/******************************************************************************
* Compilation: javac Accumulator.java
* Execution: java Accumulator < input.txt * Dependencies: StdOut.java StdIn.java * * Mutable data type that calculates the mean, sample standard * deviation, and sample variance of a stream of real numbers * use a stable, one-pass algorithm. * ******************************************************************************/ package edu . princeton . cs . algs4 ; /** * The { @code Accumulator} class is a data type for computing the running * mean, sample standard deviation, and sample variance of a stream of real * numbers. It provides an example of a mutable data type and a streaming * algorithm. *
* This implementation uses a one-pass algorithm that is less susceptible
* to floating-point roundoff error than the more straightforward
* implementation based on saving the sum of the squares of the numbers.
* This technique is due to
* Each operation takes constant time in the worst case.
* The amount of memory is constant – the data values are not stored.
*
* For additional documentation,
* see Section 1.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Accumulator
{
private
int
n
=
0
;
// number of data values
private
double
sum
=
0.0
;
// sample variance * (n-1)
private
double
mu
=
0.0
;
// sample mean
/**
* Initializes an accumulator.
*/
public
Accumulator
()
{
}
/**
* Adds the specified data value to the accumulator.
*
@param
x the data value
*/
public
void
addDataValue
(
double
x
)
{
n
++
;
double
delta
=
x
–
mu
;
mu
+=
delta
/
n
;
sum
+=
(
double
)
(
n
–
1
)
/
n
*
delta
*
delta
;
}
/**
* Returns the mean of the data values.
*
@return
the mean of the data values
*/
public
double
mean
()
{
return
mu
;
}
/**
* Returns the sample variance of the data values.
*
@return
the sample variance of the data values
*/
public
double
var
()
{
if
(
n
<=
1
)
return
Double
.
NaN
;
return
sum
/
(
n
-
1
);
}
/**
* Returns the sample standard deviation of the data values.
*
@return
the sample standard deviation of the data values
*/
public
double
stddev
()
{
return
Math
.
sqrt
(
this
.
var
());
}
/**
* Returns the number of data values.
*
@return
the number of data values
*/
public
int
count
()
{
return
n
;
}
/**
* Returns a string representation of this accumulator.
*
@return
a string representation of this accumulator
*/
public
String
toString
()
{
return
"n = "
+
n
+
", mean = "
+
mean
()
+
", stddev = "
+
stddev
();
}
/**
* Unit tests the {
@code
Accumulator} data type.
* Reads in a stream of real number from standard input;
* adds them to the accumulator; and prints the mean,
* sample standard deviation, and sample variance to standard
* output.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
Accumulator
stats
=
new
Accumulator
();
while
(
!
StdIn
.
isEmpty
())
{
double
x
=
StdIn
.
readDouble
();
stats
.
addDataValue
(
x
);
}
StdOut
.
printf
(
"n = %d\n"
,
stats
.
count
());
StdOut
.
printf
(
"mean = %.5f\n"
,
stats
.
mean
());
StdOut
.
printf
(
"stddev = %.5f\n"
,
stats
.
stddev
());
StdOut
.
printf
(
"var = %.5f\n"
,
stats
.
var
());
StdOut
.
println
(
stats
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/AcyclicLP.java
edu/princeton/cs/algs4/AcyclicLP.java
/******************************************************************************
* Compilation: javac AcyclicLP.java
* Execution: java AcyclicP V E
* Dependencies: EdgeWeightedDigraph.java DirectedEdge.java Topological.java
* Data files: https://algs4.cs.princeton.edu/44sp/tinyEWDAG.txt
*
* Computes longeset paths in an edge-weighted acyclic digraph.
*
* Remark: should probably check that graph is a DAG before running
*
* % java AcyclicLP tinyEWDAG.txt 5
* 5 to 0 (2.44) 5->1 0.32 1->3 0.29 3->6 0.52 6->4 0.93 4->0 0.38
* 5 to 1 (0.32) 5->1 0.32
* 5 to 2 (2.77) 5->1 0.32 1->3 0.29 3->6 0.52 6->4 0.93 4->7 0.37 7->2 0.34
* 5 to 3 (0.61) 5->1 0.32 1->3 0.29
* 5 to 4 (2.06) 5->1 0.32 1->3 0.29 3->6 0.52 6->4 0.93
* 5 to 5 (0.00)
* 5 to 6 (1.13) 5->1 0.32 1->3 0.29 3->6 0.52
* 5 to 7 (2.43) 5->1 0.32 1->3 0.29 3->6 0.52 6->4 0.93 4->7 0.37
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
AcyclicLP} class represents a data type for solving the
* single-source longest paths problem in edge-weighted directed
* acyclic graphs (DAGs). The edge weights can be positive, negative, or zero.
*
* This implementation uses a topological-sort based algorithm.
* The constructor takes Θ(V + E) time in the
* worst case, where V is the number of vertices and
* E is the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the
* edge-weighted digraph).
*
* For additional documentation,
* see Section 4.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
AcyclicLP
{
private
double
[]
distTo
;
// distTo[v] = distance of longest s->v path
private
DirectedEdge
[]
edgeTo
;
// edgeTo[v] = last edge on longest s->v path
/**
* Computes a longest paths tree from {
@code
s} to every other vertex in
* the directed acyclic graph {
@code
G}.
*
@param
G the acyclic digraph
*
@param
s the source vertex
*
@throws
IllegalArgumentException if the digraph is not acyclic
*
@throws
IllegalArgumentException unless {
@code
0 <= s < V}
*/
public
AcyclicLP
(
EdgeWeightedDigraph
G
,
int
s
)
{
distTo
=
new
double
[
G
.
V
()];
edgeTo
=
new
DirectedEdge
[
G
.
V
()];
validateVertex
(
s
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
distTo
[
v
]
=
Double
.
NEGATIVE_INFINITY
;
distTo
[
s
]
=
0.0
;
// relax vertices in topological order
Topological
topological
=
new
Topological
(
G
);
if
(
!
topological
.
hasOrder
())
throw
new
IllegalArgumentException
(
"Digraph is not acyclic."
);
for
(
int
v
:
topological
.
order
())
{
for
(
DirectedEdge
e
:
G
.
adj
(
v
))
relax
(
e
);
}
}
// relax edge e, but update if you find a *longer* path
private
void
relax
(
DirectedEdge
e
)
{
int
v
=
e
.
from
(),
w
=
e
.
to
();
if
(
distTo
[
w
]
<
distTo
[
v
]
+
e
.
weight
())
{
distTo
[
w
]
=
distTo
[
v
]
+
e
.
weight
();
edgeTo
[
w
]
=
e
;
}
}
/**
* Returns the length of a longest path from the source vertex {
@code
s} to vertex {
@code
v}.
*
@param
v the destination vertex
*
@return
the length of a longest path from the source vertex {
@code
s} to vertex {
@code
v};
* {
@code
Double.NEGATIVE_INFINITY} if no such path
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
double
distTo
(
int
v
)
{
validateVertex
(
v
);
return
distTo
[
v
];
}
/**
* Is there a path from the source vertex {
@code
s} to vertex {
@code
v}?
*
@param
v the destination vertex
*
@return
{
@code
true} if there is a path from the source vertex
* {
@code
s} to vertex {
@code
v}, and {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
boolean
hasPathTo
(
int
v
)
{
validateVertex
(
v
);
return
distTo
[
v
]
>
Double
.
NEGATIVE_INFINITY
;
}
/**
* Returns a longest path from the source vertex {
@code
s} to vertex {
@code
v}.
*
@param
v the destination vertex
*
@return
a longest path from the source vertex {
@code
s} to vertex {
@code
v}
* as an iterable of edges, and {
@code
null} if no such path
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
Iterable
<
DirectedEdge
>
pathTo
(
int
v
)
{
validateVertex
(
v
);
if
(
!
hasPathTo
(
v
))
return
null
;
Stack
<
DirectedEdge
>
path
=
new
Stack
<
DirectedEdge
>
();
for
(
DirectedEdge
e
=
edgeTo
[
v
];
e
!=
null
;
e
=
edgeTo
[
e
.
from
()])
{
path
.
push
(
e
);
}
return
path
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
distTo
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
AcyclicLP} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
int
s
=
Integer
.
parseInt
(
args
[
1
]);
EdgeWeightedDigraph
G
=
new
EdgeWeightedDigraph
(
in
);
AcyclicLP
lp
=
new
AcyclicLP
(
G
,
s
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
lp
.
hasPathTo
(
v
))
{
StdOut
.
printf
(
"%d to %d (%.2f) "
,
s
,
v
,
lp
.
distTo
(
v
));
for
(
DirectedEdge
e
:
lp
.
pathTo
(
v
))
{
StdOut
.
print
(
e
+
" "
);
}
StdOut
.
println
();
}
else
{
StdOut
.
printf
(
"%d to %d no path\n"
,
s
,
v
);
}
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/AcyclicSP.java
edu/princeton/cs/algs4/AcyclicSP.java
/******************************************************************************
* Compilation: javac AcyclicSP.java
* Execution: java AcyclicSP V E
* Dependencies: EdgeWeightedDigraph.java DirectedEdge.java Topological.java
* Data files: https://algs4.cs.princeton.edu/44sp/tinyEWDAG.txt
*
* Computes shortest paths in an edge-weighted acyclic digraph.
*
* % java AcyclicSP tinyEWDAG.txt 5
* 5 to 0 (0.73) 5->4 0.35 4->0 0.38
* 5 to 1 (0.32) 5->1 0.32
* 5 to 2 (0.62) 5->7 0.28 7->2 0.34
* 5 to 3 (0.61) 5->1 0.32 1->3 0.29
* 5 to 4 (0.35) 5->4 0.35
* 5 to 5 (0.00)
* 5 to 6 (1.13) 5->1 0.32 1->3 0.29 3->6 0.52
* 5 to 7 (0.28) 5->7 0.28
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
AcyclicSP} class represents a data type for solving the
* single-source shortest paths problem in edge-weighted directed acyclic
* graphs (DAGs). The edge weights can be positive, negative, or zero.
*
* This implementation uses a topological-sort based algorithm.
* The constructor takes Θ(V + E) time in the
* worst case, where V is the number of vertices and
* E is the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the
* edge-weighted digraph).
*
* For additional documentation,
* see Section 4.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
AcyclicSP
{
private
double
[]
distTo
;
// distTo[v] = distance of shortest s->v path
private
DirectedEdge
[]
edgeTo
;
// edgeTo[v] = last edge on shortest s->v path
/**
* Computes a shortest paths tree from {
@code
s} to every other vertex in
* the directed acyclic graph {
@code
G}.
*
@param
G the acyclic digraph
*
@param
s the source vertex
*
@throws
IllegalArgumentException if the digraph is not acyclic
*
@throws
IllegalArgumentException unless {
@code
0 <= s < V}
*/
public
AcyclicSP
(
EdgeWeightedDigraph
G
,
int
s
)
{
distTo
=
new
double
[
G
.
V
()];
edgeTo
=
new
DirectedEdge
[
G
.
V
()];
validateVertex
(
s
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
distTo
[
v
]
=
Double
.
POSITIVE_INFINITY
;
distTo
[
s
]
=
0.0
;
// visit vertices in topological order
Topological
topological
=
new
Topological
(
G
);
if
(
!
topological
.
hasOrder
())
throw
new
IllegalArgumentException
(
"Digraph is not acyclic."
);
for
(
int
v
:
topological
.
order
())
{
for
(
DirectedEdge
e
:
G
.
adj
(
v
))
relax
(
e
);
}
}
// relax edge e
private
void
relax
(
DirectedEdge
e
)
{
int
v
=
e
.
from
(),
w
=
e
.
to
();
if
(
distTo
[
w
]
>
distTo
[
v
]
+
e
.
weight
())
{
distTo
[
w
]
=
distTo
[
v
]
+
e
.
weight
();
edgeTo
[
w
]
=
e
;
}
}
/**
* Returns the length of a shortest path from the source vertex {
@code
s} to vertex {
@code
v}.
*
@param
v the destination vertex
*
@return
the length of a shortest path from the source vertex {
@code
s} to vertex {
@code
v};
* {
@code
Double.POSITIVE_INFINITY} if no such path
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
double
distTo
(
int
v
)
{
validateVertex
(
v
);
return
distTo
[
v
];
}
/**
* Is there a path from the source vertex {
@code
s} to vertex {
@code
v}?
*
@param
v the destination vertex
*
@return
{
@code
true} if there is a path from the source vertex
* {
@code
s} to vertex {
@code
v}, and {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
boolean
hasPathTo
(
int
v
)
{
validateVertex
(
v
);
return
distTo
[
v
]
<
Double
.
POSITIVE_INFINITY
;
}
/**
* Returns a shortest path from the source vertex {
@code
s} to vertex {
@code
v}.
*
@param
v the destination vertex
*
@return
a shortest path from the source vertex {
@code
s} to vertex {
@code
v}
* as an iterable of edges, and {
@code
null} if no such path
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
Iterable
<
DirectedEdge
>
pathTo
(
int
v
)
{
validateVertex
(
v
);
if
(
!
hasPathTo
(
v
))
return
null
;
Stack
<
DirectedEdge
>
path
=
new
Stack
<
DirectedEdge
>
();
for
(
DirectedEdge
e
=
edgeTo
[
v
];
e
!=
null
;
e
=
edgeTo
[
e
.
from
()])
{
path
.
push
(
e
);
}
return
path
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
distTo
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
AcyclicSP} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
int
s
=
Integer
.
parseInt
(
args
[
1
]);
EdgeWeightedDigraph
G
=
new
EdgeWeightedDigraph
(
in
);
// find shortest path from s to each other vertex in DAG
AcyclicSP
sp
=
new
AcyclicSP
(
G
,
s
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
sp
.
hasPathTo
(
v
))
{
StdOut
.
printf
(
"%d to %d (%.2f) "
,
s
,
v
,
sp
.
distTo
(
v
));
for
(
DirectedEdge
e
:
sp
.
pathTo
(
v
))
{
StdOut
.
print
(
e
+
" "
);
}
StdOut
.
println
();
}
else
{
StdOut
.
printf
(
"%d to %d no path\n"
,
s
,
v
);
}
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/AdjMatrixEdgeWeightedDigraph.java
edu/princeton/cs/algs4/AdjMatrixEdgeWeightedDigraph.java
/******************************************************************************
* Compilation: javac AdjMatrixEdgeWeightedDigraph.java
* Execution: java AdjMatrixEdgeWeightedDigraph V E
* Dependencies: StdOut.java
*
* An edge-weighted digraph, implemented using an adjacency matrix.
* Parallel edges are disallowed; self-loops are allowed.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Iterator
;
import
java
.
util
.
NoSuchElementException
;
/**
* The {
@code
AdjMatrixEdgeWeightedDigraph} class represents a edge-weighted
* digraph of vertices named 0 through V – 1, where each
* directed edge is of type {
@link
DirectedEdge} and has a real-valued weight.
* It supports the following two primary operations: add a directed edge
* to the digraph and iterate over all of edges incident from a given vertex.
* It also provides
* methods for returning the number of vertices V and the number
* of edges E. Parallel edges are disallowed; self-loops are permitted.
*
* This implementation uses an adjacency-matrix representation.
* All operations take constant time (in the worst case) except
* iterating over the edges incident from a given vertex, which takes
* time proportional to V.
*
* For additional documentation,
* see Section 4.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
AdjMatrixEdgeWeightedDigraph
{
private
static
final
String
NEWLINE
=
System
.
getProperty
(
“line.separator”
);
private
final
int
V
;
private
int
E
;
private
DirectedEdge
[][]
adj
;
/**
* Initializes an empty edge-weighted digraph with {
@code
V} vertices and 0 edges.
*
@param
V the number of vertices
*
@throws
IllegalArgumentException if {
@code
V < 0}
*/
public
AdjMatrixEdgeWeightedDigraph
(
int
V
)
{
if
(
V
<
0
)
throw
new
IllegalArgumentException
(
"number of vertices must be nonnegative"
);
this
.
V
=
V
;
this
.
E
=
0
;
this
.
adj
=
new
DirectedEdge
[
V
][
V
];
}
/**
* Initializes a random edge-weighted digraph with {
@code
V} vertices and E edges.
*
@param
V the number of vertices
*
@param
E the number of edges
*
@throws
IllegalArgumentException if {
@code
V < 0}
*
@throws
IllegalArgumentException if {
@code
E < 0}
*/
public
AdjMatrixEdgeWeightedDigraph
(
int
V
,
int
E
)
{
this
(
V
);
if
(
E
<
0
)
throw
new
IllegalArgumentException
(
"number of edges must be nonnegative"
);
if
(
E
>
V
*
V
)
throw
new
IllegalArgumentException
(
“too many edges”
);
// can be inefficient
while
(
this
.
E
!=
E
)
{
int
v
=
StdRandom
.
uniform
(
V
);
int
w
=
StdRandom
.
uniform
(
V
);
double
weight
=
Math
.
round
(
100
*
StdRandom
.
uniform
())
/
100.0
;
addEdge
(
new
DirectedEdge
(
v
,
w
,
weight
));
}
}
/**
* Returns the number of vertices in the edge-weighted digraph.
*
@return
the number of vertices in the edge-weighted digraph
*/
public
int
V
()
{
return
V
;
}
/**
* Returns the number of edges in the edge-weighted digraph.
*
@return
the number of edges in the edge-weighted digraph
*/
public
int
E
()
{
return
E
;
}
/**
* Adds the directed edge {
@code
e} to the edge-weighted digraph (if there
* is not already an edge with the same endpoints).
*
@param
e the edge
*/
public
void
addEdge
(
DirectedEdge
e
)
{
int
v
=
e
.
from
();
int
w
=
e
.
to
();
validateVertex
(
v
);
validateVertex
(
w
);
if
(
adj
[
v
][
w
]
==
null
)
{
E
++
;
adj
[
v
][
w
]
=
e
;
}
}
/**
* Returns the directed edges incident from vertex {
@code
v}.
*
@param
v the vertex
*
@return
the directed edges incident from vertex {
@code
v} as an Iterable
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
Iterable
<
DirectedEdge
>
adj
(
int
v
)
{
validateVertex
(
v
);
return
new
AdjIterator
(
v
);
}
// support iteration over graph vertices
private
class
AdjIterator
implements
Iterator
<
DirectedEdge
>
,
Iterable
<
DirectedEdge
>
{
private
int
v
;
private
int
w
=
0
;
public
AdjIterator
(
int
v
)
{
this
.
v
=
v
;
}
public
Iterator
<
DirectedEdge
>
iterator
()
{
return
this
;
}
public
boolean
hasNext
()
{
while
(
w
<
V
)
{
if
(
adj
[
v
][
w
]
!=
null
)
return
true
;
w
++
;
}
return
false
;
}
public
DirectedEdge
next
()
{
if
(
!
hasNext
())
{
throw
new
NoSuchElementException
();
}
return
adj
[
v
][
w
++
];
}
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
}
/**
* Returns a string representation of the edge-weighted digraph. This method takes
* time proportional to V2.
*
@return
the number of vertices V, followed by the number of edges E,
* followed by the V adjacency lists of edges
*/
public
String
toString
()
{
StringBuilder
s
=
new
StringBuilder
();
s
.
append
(
V
+
” ”
+
E
+
NEWLINE
);
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
s
.
append
(
v
+
": "
);
for
(
DirectedEdge
e
:
adj
(
v
))
{
s
.
append
(
e
+
" "
);
}
s
.
append
(
NEWLINE
);
}
return
s
.
toString
();
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
AdjMatrixEdgeWeightedDigraph} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
V
=
Integer
.
parseInt
(
args
[
0
]);
int
E
=
Integer
.
parseInt
(
args
[
1
]);
AdjMatrixEdgeWeightedDigraph
G
=
new
AdjMatrixEdgeWeightedDigraph
(
V
,
E
);
StdOut
.
println
(
G
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Alphabet.java
edu/princeton/cs/algs4/Alphabet.java
/******************************************************************************
* Compilation: javac Alphabet.java
* Execution: java Alphabet
* Dependencies: StdOut.java
*
* A data type for alphabets, for use with string-processing code
* that must convert between an alphabet of size R and the integers
* 0 through R-1.
*
* Warning: supports only the basic multilingual plane (BMP), i.e,
* Unicode characters between U+0000 and U+FFFF.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
public
class
Alphabet
{
/**
* The binary alphabet { 0, 1 }.
*/
public
static
final
Alphabet
BINARY
=
new
Alphabet
(
“01”
);
/**
* The octal alphabet { 0, 1, 2, 3, 4, 5, 6, 7 }.
*/
public
static
final
Alphabet
OCTAL
=
new
Alphabet
(
“01234567”
);
/**
* The decimal alphabet { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }.
*/
public
static
final
Alphabet
DECIMAL
=
new
Alphabet
(
“0123456789”
);
/**
* The hexadecimal alphabet { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F }.
*/
public
static
final
Alphabet
HEXADECIMAL
=
new
Alphabet
(
“0123456789ABCDEF”
);
/**
* The DNA alphabet { A, C, T, G }.
*/
public
static
final
Alphabet
DNA
=
new
Alphabet
(
“ACGT”
);
/**
* The lowercase alphabet { a, b, c, …, z }.
*/
public
static
final
Alphabet
LOWERCASE
=
new
Alphabet
(
“abcdefghijklmnopqrstuvwxyz”
);
/**
* The uppercase alphabet { A, B, C, …, Z }.
*/
public
static
final
Alphabet
UPPERCASE
=
new
Alphabet
(
“ABCDEFGHIJKLMNOPQRSTUVWXYZ”
);
/**
* The protein alphabet { A, C, D, E, F, G, H, I, K, L, M, N, P, Q, R, S, T, V, W, Y }.
*/
public
static
final
Alphabet
PROTEIN
=
new
Alphabet
(
“ACDEFGHIKLMNPQRSTVWY”
);
/**
* The base-64 alphabet (64 characters).
*/
public
static
final
Alphabet
BASE64
=
new
Alphabet
(
“ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/”
);
/**
* The ASCII alphabet (0-127).
*/
public
static
final
Alphabet
ASCII
=
new
Alphabet
(
128
);
/**
* The extended ASCII alphabet (0-255).
*/
public
static
final
Alphabet
EXTENDED_ASCII
=
new
Alphabet
(
256
);
/**
* The Unicode 16 alphabet (0-65,535).
*/
public
static
final
Alphabet
UNICODE16
=
new
Alphabet
(
65536
);
private
char
[]
alphabet
;
// the characters in the alphabet
private
int
[]
inverse
;
// indices
private
final
int
R
;
// the radix of the alphabet
/**
* Initializes a new alphabet from the given set of characters.
*
*
@param
alpha the set of characters
*/
public
Alphabet
(
String
alpha
)
{
// check that alphabet contains no duplicate chars
boolean
[]
unicode
=
new
boolean
[
Character
.
MAX_VALUE
];
for
(
int
i
=
0
;
i
<
alpha
.
length
();
i
++
)
{
char
c
=
alpha
.
charAt
(
i
);
if
(
unicode
[
c
])
throw
new
IllegalArgumentException
(
"Illegal alphabet: repeated character = '"
+
c
+
"'"
);
unicode
[
c
]
=
true
;
}
alphabet
=
alpha
.
toCharArray
();
R
=
alpha
.
length
();
inverse
=
new
int
[
Character
.
MAX_VALUE
];
for
(
int
i
=
0
;
i
<
inverse
.
length
;
i
++
)
inverse
[
i
]
=
-
1
;
// can't use char since R can be as big as 65,536
for
(
int
c
=
0
;
c
<
R
;
c
++
)
inverse
[
alphabet
[
c
]]
=
c
;
}
/**
* Initializes a new alphabet using characters 0 through R-1.
*
*
@param
radix the number of characters in the alphabet (the radix R)
*/
private
Alphabet
(
int
radix
)
{
this
.
R
=
radix
;
alphabet
=
new
char
[
R
];
inverse
=
new
int
[
R
];
// can't use char since R can be as big as 65,536
for
(
int
i
=
0
;
i
<
R
;
i
++
)
alphabet
[
i
]
=
(
char
)
i
;
for
(
int
i
=
0
;
i
<
R
;
i
++
)
inverse
[
i
]
=
i
;
}
/**
* Initializes a new alphabet using characters 0 through 255.
*/
public
Alphabet
()
{
this
(
256
);
}
/**
* Returns true if the argument is a character in this alphabet.
*
*
@param
c the character
*
@return
{
@code
true} if {
@code
c} is a character in this alphabet;
* {
@code
false} otherwise
*/
public
boolean
contains
(
char
c
)
{
return
inverse
[
c
]
!=
-
1
;
}
/**
* Returns the number of characters in this alphabet (the radix).
*
*
@return
the number of characters in this alphabet
*
@deprecated
Replaced by {
@link
#radix()}.
*/
@
Deprecated
public
int
R
()
{
return
R
;
}
/**
* Returns the number of characters in this alphabet (the radix).
*
*
@return
the number of characters in this alphabet
*/
public
int
radix
()
{
return
R
;
}
/**
* Returns the binary logarithm of the number of characters in this alphabet.
*
*
@return
the binary logarithm (rounded up) of the number of characters in this alphabet
*/
public
int
lgR
()
{
int
lgR
=
0
;
for
(
int
t
=
R
-
1
;
t
>=
1
;
t
/=
2
)
lgR
++
;
return
lgR
;
}
/**
* Returns the index corresponding to the argument character.
*
*
@param
c the character
*
@return
the index corresponding to the character {
@code
c}
*
@throws
IllegalArgumentException unless {
@code
c} is a character in this alphabet
*/
public
int
toIndex
(
char
c
)
{
if
(
c
>=
inverse
.
length
||
inverse
[
c
]
==
–
1
)
{
throw
new
IllegalArgumentException
(
“Character ”
+
c
+
” not in alphabet”
);
}
return
inverse
[
c
];
}
/**
* Returns the indices corresponding to the argument characters.
*
*
@param
s the characters
*
@return
the indices corresponding to the characters {
@code
s}
*
@throws
IllegalArgumentException unless every character in {
@code
s}
* is a character in this alphabet
*/
public
int
[]
toIndices
(
String
s
)
{
char
[]
source
=
s
.
toCharArray
();
int
[]
target
=
new
int
[
s
.
length
()];
for
(
int
i
=
0
;
i
<
source
.
length
;
i
++
)
target
[
i
]
=
toIndex
(
source
[
i
]);
return
target
;
}
/**
* Returns the character corresponding to the argument index.
*
*
@param
index the index
*
@return
the character corresponding to the index {
@code
index}
*
@throws
IllegalArgumentException unless {
@code
0 <= index < R}
*/
public
char
toChar
(
int
index
)
{
if
(
index
<
0
||
index
>=
R
)
{
throw
new
IllegalArgumentException
(
“index must be between 0 and ”
+
R
+
“: ”
+
index
);
}
return
alphabet
[
index
];
}
/**
* Returns the characters corresponding to the argument indices.
*
*
@param
indices the indices
*
@return
the characters corresponding to the indices {
@code
indices}
*
@throws
IllegalArgumentException unless {
@code
0 < indices[i] < R}
* for every {
@code
i}
*/
public
String
toChars
(
int
[]
indices
)
{
StringBuilder
s
=
new
StringBuilder
(
indices
.
length
);
for
(
int
i
=
0
;
i
<
indices
.
length
;
i
++
)
s
.
append
(
toChar
(
indices
[
i
]));
return
s
.
toString
();
}
/**
* Unit tests the {
@code
Alphabet} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
[]
encoded1
=
Alphabet
.
BASE64
.
toIndices
(
"NowIsTheTimeForAllGoodMen"
);
String
decoded1
=
Alphabet
.
BASE64
.
toChars
(
encoded1
);
StdOut
.
println
(
decoded1
);
int
[]
encoded2
=
Alphabet
.
DNA
.
toIndices
(
"AACGAACGGTTTACCCCG"
);
String
decoded2
=
Alphabet
.
DNA
.
toChars
(
encoded2
);
StdOut
.
println
(
decoded2
);
int
[]
encoded3
=
Alphabet
.
DECIMAL
.
toIndices
(
"01234567890123456789"
);
String
decoded3
=
Alphabet
.
DECIMAL
.
toChars
(
encoded3
);
StdOut
.
println
(
decoded3
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/AmericanFlag.java
edu/princeton/cs/algs4/AmericanFlag.java
/******************************************************************************
* Compilation: javac AmericanFlag.java
* Execution: java AmericanFlag < input.txt
* java AmericanFlag int < input-non-negative-ints.txt
* Dependencies: StdIn.java StdOut.java Stack.java
* Data files: https://algs4.cs.princeton.edu/51radix/words3.txt
* https://algs4.cs.princeton.edu/51radix/shells.txt
*
* Sort an array of strings or integers in-place using American flag sort.
*
* % java AmericanFlag < shells.txt
* are
* by
* sea
* seashells
* seashells
* sells
* sells
* she
* she
* shells
* shore
* surely
* the
* the
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
AmericanFlag} class provides static methods for sorting an
* array of extended ASCII strings or integers in-place using
* American flag sort. This is a non-recursive implementation.
*
* For additional documentation,
* see Section 5.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne
* Engineering Radix Sort by McIlroy and Bostic.
* For a version that uses only one auxilary array, see {
@link
AmericanFlagX}.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*
@author
Ivan Pesin
*/
public
class
AmericanFlag
{
private
static
final
int
BITS_PER_BYTE
=
8
;
private
static
final
int
BITS_PER_INT
=
32
;
// each Java int is 32 bits
private
static
final
int
R
=
256
;
// extend ASCII alphabet size
private
static
final
int
CUTOFF
=
15
;
// cutoff to insertion sort
// do not instantiate
private
AmericanFlag
()
{
}
// return dth character of s, -1 if d = length of string
private
static
int
charAt
(
String
s
,
int
d
)
{
assert
d
>=
0
&&
d
<=
s
.
length
();
if
(
d
==
s
.
length
())
return
-
1
;
return
s
.
charAt
(
d
);
}
/**
* Rearranges the array of extended ASCII strings in ascending order.
* This is an unstable sorting algorithm.
*
*
@param
a the array to be sorted
*/
public
static
void
sort
(
String
[]
a
)
{
sort
(
a
,
0
,
a
.
length
-
1
);
}
// sort from a[lo] to a[hi], starting at the dth character
public
static
void
sort
(
String
[]
a
,
int
lo
,
int
hi
)
{
// one-time allocation of data structures
Stack
<
Integer
>
st
=
new
Stack
<
Integer
>
();
int
[]
first
=
new
int
[
R
+
2
];
int
[]
next
=
new
int
[
R
+
2
];
int
d
=
0
;
// character index to sort by
st
.
push
(
lo
);
st
.
push
(
hi
);
st
.
push
(
d
);
while
(
!
st
.
isEmpty
())
{
d
=
st
.
pop
();
hi
=
st
.
pop
();
lo
=
st
.
pop
();
if
(
hi
<=
lo
+
CUTOFF
)
{
insertion
(
a
,
lo
,
hi
,
d
);
continue
;
}
// compute frequency counts
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
{
int
c
=
charAt
(
a
[
i
],
d
)
+
1
;
// account for -1 representing end-of-string
first
[
c
+
1
]
++
;
}
// first[c] = location of first string whose dth character = c
first
[
0
]
=
lo
;
for
(
int
c
=
0
;
c
<=
R
;
c
++
)
{
first
[
c
+
1
]
+=
first
[
c
];
if
(
c
>
0
&&
first
[
c
+
1
]
–
1
>
first
[
c
])
{
// add subproblem for character c (excludes sentinel c == 0)
st
.
push
(
first
[
c
]);
st
.
push
(
first
[
c
+
1
]
–
1
);
st
.
push
(
d
+
1
);
}
}
// next[c] = location to place next string whose dth character = c
for
(
int
c
=
0
;
c
<
R
+
2
;
c
++
)
next
[
c
]
=
first
[
c
];
// permute data in place
for
(
int
k
=
lo
;
k
<=
hi
;
k
++
)
{
int
c
=
charAt
(
a
[
k
],
d
)
+
1
;
while
(
first
[
c
]
>
k
)
{
exch
(
a
,
k
,
next
[
c
]
++
);
c
=
charAt
(
a
[
k
],
d
)
+
1
;
}
next
[
c
]
++
;
}
// clear first[] and next[] arrays
for
(
int
c
=
0
;
c
<
R
+
2
;
c
++
)
{
first
[
c
]
=
0
;
next
[
c
]
=
0
;
}
}
}
// insertion sort a[lo..hi], starting at dth character
private
static
void
insertion
(
String
[]
a
,
int
lo
,
int
hi
,
int
d
)
{
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
for
(
int
j
=
i
;
j
>
lo
&&
less
(
a
[
j
],
a
[
j
–
1
],
d
);
j
—
)
exch
(
a
,
j
,
j
–
1
);
}
// exchange a[i] and a[j]
private
static
void
exch
(
String
[]
a
,
int
i
,
int
j
)
{
String
temp
=
a
[
i
];
a
[
i
]
=
a
[
j
];
a
[
j
]
=
temp
;
}
// is v less than w, starting at character d
private
static
boolean
less
(
String
v
,
String
w
,
int
d
)
{
// assert v.substring(0, d).equals(w.substring(0, d));
for
(
int
i
=
d
;
i
<
Math
.
min
(
v
.
length
(),
w
.
length
());
i
++
)
{
if
(
v
.
charAt
(
i
)
<
w
.
charAt
(
i
))
return
true
;
if
(
v
.
charAt
(
i
)
>
w
.
charAt
(
i
))
return
false
;
}
return
v
.
length
()
<
w
.
length
();
}
/**
* Rearranges the array of 32-bit integers in ascending order.
* Currently assumes that the integers are nonnegative.
*
*
@param
a the array to be sorted
*/
public
static
void
sort
(
int
[]
a
)
{
sort
(
a
,
0
,
a
.
length
-
1
);
}
// MSD sort from a[lo] to a[hi]
private
static
void
sort
(
int
[]
a
,
int
lo
,
int
hi
)
{
// one-time allocation of data structures
Stack
<
Integer
>
st
=
new
Stack
<
Integer
>
();
int
[]
first
=
new
int
[
R
+
1
];
int
[]
next
=
new
int
[
R
+
1
];
int
mask
=
R
–
1
;
// 0xFF;
int
d
=
0
;
// byte to sort by
st
.
push
(
lo
);
st
.
push
(
hi
);
st
.
push
(
d
);
while
(
!
st
.
isEmpty
())
{
d
=
st
.
pop
();
hi
=
st
.
pop
();
lo
=
st
.
pop
();
if
(
hi
<=
lo
+
CUTOFF
)
{
insertion
(
a
,
lo
,
hi
,
d
);
continue
;
}
// compute frequency counts (need R = 256)
int
shift
=
BITS_PER_INT
-
BITS_PER_BYTE
*
d
-
BITS_PER_BYTE
;
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
{
int
c
=
(
a
[
i
]
>>
shift
)
&
mask
;
first
[
c
+
1
]
++
;
}
// first[c] = location of first int whose dth byte = c
first
[
0
]
=
lo
;
for
(
int
c
=
0
;
c
<
R
;
c
++
)
{
first
[
c
+
1
]
+=
first
[
c
];
if
(
d
<
3
&&
first
[
c
+
1
]
-
1
>
first
[
c
])
{
// add subproblem for byte c
st
.
push
(
first
[
c
]);
st
.
push
(
first
[
c
+
1
]
–
1
);
st
.
push
(
d
+
1
);
}
}
// next[c] = location to place next string whose dth byte = c
for
(
int
c
=
0
;
c
<
R
+
1
;
c
++
)
next
[
c
]
=
first
[
c
];
// permute data in place
for
(
int
k
=
lo
;
k
<=
hi
;
k
++
)
{
int
c
=
(
a
[
k
]
>>
shift
)
&
mask
;
while
(
first
[
c
]
>
k
)
{
exch
(
a
,
k
,
next
[
c
]
++
);
c
=
(
a
[
k
]
>>
shift
)
&
mask
;
}
next
[
c
]
++
;
}
// clear first[] and next[] arrays
for
(
int
c
=
0
;
c
<
R
+
1
;
c
++
)
{
first
[
c
]
=
0
;
next
[
c
]
=
0
;
}
}
}
// insertion sort a[lo..hi], starting at dth byte
private
static
void
insertion
(
int
[]
a
,
int
lo
,
int
hi
,
int
d
)
{
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
for
(
int
j
=
i
;
j
>
lo
&&
less
(
a
[
j
],
a
[
j
–
1
],
d
);
j
—
)
exch
(
a
,
j
,
j
–
1
);
}
// exchange a[i] and a[j]
private
static
void
exch
(
int
[]
a
,
int
i
,
int
j
)
{
int
temp
=
a
[
i
];
a
[
i
]
=
a
[
j
];
a
[
j
]
=
temp
;
}
// is v less than w, starting at byte d
private
static
boolean
less
(
int
v
,
int
w
,
int
d
)
{
int
mask
=
R
–
1
;
// 0xFF;
for
(
int
i
=
d
;
i
<
4
;
i
++
)
{
int
shift
=
BITS_PER_INT
-
BITS_PER_BYTE
*
i
-
BITS_PER_BYTE
;
int
a
=
(
v
>>
shift
)
&
mask
;
int
b
=
(
w
>>
shift
)
&
mask
;
if
(
a
<
b
)
return
true
;
if
(
a
>
b
)
return
false
;
}
return
false
;
}
/**
* Reads in a sequence of extended ASCII strings or non-negative ints from standard input;
* American flag sorts them;
* and prints them to standard output in ascending order.
*
*
@param
args the command-line arguments: “int” to read input as non-negative integers
*/
public
static
void
main
(
String
[]
args
)
{
if
(
args
.
length
>
0
&&
args
[
0
].
equals
(
“int”
))
{
int
[]
a
=
StdIn
.
readAllInts
();
sort
(
a
);
// print results
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
StdOut
.
println
(
a
[
i
]);
}
else
{
String
[]
a
=
StdIn
.
readAllStrings
();
sort
(
a
);
// print results
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
StdOut
.
println
(
a
[
i
]);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/AmericanFlagX.java
edu/princeton/cs/algs4/AmericanFlagX.java
/******************************************************************************
* Compilation: javac AmericanFlagX.java
* Execution: java AmericanFlagX < input.txt
* Dependencies: StdIn.java StdOut.java Stack.java
* Data files: https://algs4.cs.princeton.edu/51radix/words3.txt
* https://algs4.cs.princeton.edu/51radix/shells.txt
*
* Sort an array of strings or integers in-place using American Flag sort.
*
* % java AmericanFlagX < shells.txt
* are
* by
* sea
* seashells
* seashells
* sells
* sells
* she
* she
* shells
* shore
* surely
* the
* the
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
AmericanFlagX} class provides static methods for sorting an
* array of extended ASCII strings or integers in-place using
* American Flag sort. This implementation is non-recursive and uses only
* one auxiliary array.
*
* For additional documentation,
* see Section 5.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne
* Engineering Radix Sort by McIlroy and Bostic.
* For a version that uses two auxilary arrays, see {
@link
AmericanFlag}.
*
*
@author
Ivan Pesin
*/
public
class
AmericanFlagX
{
private
static
final
int
R
=
256
;
// extend ASCII alphabet size
private
static
final
int
CUTOFF
=
15
;
// cutoff to insertion sort
// do not instantiate
private
AmericanFlagX
()
{
}
// return dth character of s, -1 if d = length of string
private
static
int
charAt
(
String
s
,
int
d
)
{
assert
d
>=
0
&&
d
<=
s
.
length
();
if
(
d
==
s
.
length
())
return
-
1
;
return
s
.
charAt
(
d
);
}
/**
* Rearranges the array of extended ASCII strings in ascending order.
* This is an unstable in-place sorting algorithm.
*
*
@param
a the array to be sorted
*/
public
static
void
sort
(
String
[]
a
)
{
sort
(
a
,
0
,
a
.
length
-
1
);
}
// sort from a[lo] to a[hi], starting at the dth character
public
static
void
sort
(
String
[]
a
,
int
lo
,
int
hi
)
{
// one-time allocation of data structures
Stack
<
Integer
>
st
=
new
Stack
<
Integer
>
();
int
[]
count
=
new
int
[
R
+
1
];
int
d
=
0
;
// character index to sort by
st
.
push
(
lo
);
st
.
push
(
hi
);
st
.
push
(
d
);
while
(
!
st
.
isEmpty
())
{
d
=
st
.
pop
();
hi
=
st
.
pop
();
lo
=
st
.
pop
();
if
(
hi
<=
lo
+
CUTOFF
)
{
insertion
(
a
,
lo
,
hi
,
d
);
continue
;
}
// compute frequency counts
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
{
int
c
=
charAt
(
a
[
i
],
d
)
+
1
;
// account for -1 representing end-of-string
count
[
c
]
++
;
}
// accumulate counts relative to a[0], so that
// count[c] is the number of keys <= c
count
[
0
]
+=
lo
;
for
(
int
c
=
0
;
c
<
R
;
c
++
)
{
count
[
c
+
1
]
+=
count
[
c
];
if
(
c
>
0
&&
count
[
c
+
1
]
–
1
>
count
[
c
])
{
// add subproblem for character c (excludes sentinel c == 0)
st
.
push
(
count
[
c
]);
st
.
push
(
count
[
c
+
1
]
–
1
);
st
.
push
(
d
+
1
);
}
}
// permute data in place
// for details and proof see Knuth Theorem 5.1.2B and ch 5.2 excercise 13.
for
(
int
r
=
hi
;
r
>=
lo
;
r
—
)
{
// locate element that must be shifted right of r
int
c
=
charAt
(
a
[
r
],
d
)
+
1
;
while
(
r
>=
lo
&&
count
[
c
]
–
1
<=
r
)
{
if
(
count
[
c
]
-
1
==
r
)
count
[
c
]
--
;
r
--
;
if
(
r
>=
lo
)
c
=
charAt
(
a
[
r
],
d
)
+
1
;
}
// if r < lo the subarray is sorted.
if
(
r
<
lo
)
break
;
// permute a[r] until correct element is in place
while
(
--
count
[
c
]
!=
r
)
{
exch
(
a
,
r
,
count
[
c
]);
c
=
charAt
(
a
[
r
],
d
)
+
1
;
}
}
// clear count[] array
for
(
int
c
=
0
;
c
<
R
+
1
;
c
++
)
count
[
c
]
=
0
;
}
}
// insertion sort a[lo..hi], starting at dth character
private
static
void
insertion
(
String
[]
a
,
int
lo
,
int
hi
,
int
d
)
{
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
for
(
int
j
=
i
;
j
>
lo
&&
less
(
a
[
j
],
a
[
j
–
1
],
d
);
j
—
)
exch
(
a
,
j
,
j
–
1
);
}
// exchange a[i] and a[j]
private
static
void
exch
(
String
[]
a
,
int
i
,
int
j
)
{
String
temp
=
a
[
i
];
a
[
i
]
=
a
[
j
];
a
[
j
]
=
temp
;
}
// is v less than w, starting at character d
private
static
boolean
less
(
String
v
,
String
w
,
int
d
)
{
// assert v.substring(0, d).equals(w.substring(0, d));
for
(
int
i
=
d
;
i
<
Math
.
min
(
v
.
length
(),
w
.
length
());
i
++
)
{
if
(
v
.
charAt
(
i
)
<
w
.
charAt
(
i
))
return
true
;
if
(
v
.
charAt
(
i
)
>
w
.
charAt
(
i
))
return
false
;
}
return
v
.
length
()
<
w
.
length
();
}
/**
* Reads in a sequence of extended ASCII strings or non-negative ints from standard input;
* American flag sorts them;
* and prints them to standard output in ascending order.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
[]
a
=
StdIn
.
readAllStrings
();
sort
(
a
);
// print results
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
StdOut
.
println
(
a
[
i
]);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Arbitrage.java
edu/princeton/cs/algs4/Arbitrage.java
/******************************************************************************
* Compilation: javac Arbitrage.java
* Execution: java Arbitrage < input.txt
* Dependencies: EdgeWeightedDigraph.java DirectedEdge.java
* BellmanFordSP.java
* Data file: https://algs4.cs.princeton.edu/44sp/rates.txt
*
* Arbitrage detection.
*
* % more rates.txt
* 5
* USD 1 0.741 0.657 1.061 1.005
* EUR 1.349 1 0.888 1.433 1.366
* GBP 1.521 1.126 1 1.614 1.538
* CHF 0.942 0.698 0.619 1 0.953
* CAD 0.995 0.732 0.650 1.049 1
*
* % java Arbitrage < rates.txt
* 1000.00000 USD = 741.00000 EUR
* 741.00000 EUR = 1012.20600 CAD
* 1012.20600 CAD = 1007.14497 USD
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Arbitrage} class provides a client that finds an arbitrage
* opportunity in a currency exchange table by constructing a
* complete-digraph representation of the exchange table and then finding
* a negative cycle in the digraph.
*
* This implementation uses the Bellman-Ford algorithm to find a
* negative cycle in the complete digraph.
* The running time is proportional to V3 in the
* worst case, where V is the number of currencies.
*
* For additional documentation,
* see Section 4.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Arbitrage
{
// this class cannot be instantiated
private
Arbitrage
()
{
}
/**
* Reads the currency exchange table from standard input and
* prints an arbitrage opportunity to standard output (if one exists).
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// V currencies
int
V
=
StdIn
.
readInt
();
String
[]
name
=
new
String
[
V
];
// create complete network
EdgeWeightedDigraph
G
=
new
EdgeWeightedDigraph
(
V
);
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
name
[
v
]
=
StdIn
.
readString
();
for
(
int
w
=
0
;
w
<
V
;
w
++
)
{
double
rate
=
StdIn
.
readDouble
();
DirectedEdge
e
=
new
DirectedEdge
(
v
,
w
,
-
Math
.
log
(
rate
));
G
.
addEdge
(
e
);
}
}
// find negative cycle
BellmanFordSP
spt
=
new
BellmanFordSP
(
G
,
0
);
if
(
spt
.
hasNegativeCycle
())
{
double
stake
=
1000.0
;
for
(
DirectedEdge
e
:
spt
.
negativeCycle
())
{
StdOut
.
printf
(
"%10.5f %s "
,
stake
,
name
[
e
.
from
()]);
stake
*=
Math
.
exp
(
-
e
.
weight
());
StdOut
.
printf
(
"= %10.5f %s\n"
,
stake
,
name
[
e
.
to
()]);
}
}
else
{
StdOut
.
println
(
"No arbitrage opportunity"
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/AssignmentProblem.java
edu/princeton/cs/algs4/AssignmentProblem.java
/******************************************************************************
* Compilation: javac AssignmentProblem.java
* Execution: java AssignmentProblem n
* Dependencies: DijkstraSP.java DirectedEdge.java
*
* Solve an n-by-n assignment problem in n^3 log n time using the
* successive shortest path algorithm.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
AssignmentProblem} class represents a data type for computing
* an optimal solution to an n-by-n assignment problem.
* The assignment problem is to find a minimum weight matching in an
* edge-weighted complete bipartite graph.
*
* The data type supplies methods for determining the optimal solution
* and the corresponding dual solution.
*
* This implementation uses the successive shortest paths algorithm.
* The order of growth of the running time in the worst case is
* O(n^3 log n) to solve an n-by-n
* instance.
*
* For additional documentation, see
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
AssignmentProblem
{
private
static
final
double
FLOATING_POINT_EPSILON
=
1E-14
;
private
static
final
int
UNMATCHED
=
–
1
;
private
int
n
;
// number of rows and columns
private
double
[][]
weight
;
// the n-by-n cost matrix
private
double
minWeight
;
// minimum value of any weight
private
double
[]
px
;
// px[i] = dual variable for row i
private
double
[]
py
;
// py[j] = dual variable for col j
private
int
[]
xy
;
// xy[i] = j means i-j is a match
private
int
[]
yx
;
// yx[j] = i means i-j is a match
/**
* Determines an optimal solution to the assignment problem.
*
*
@param
weight the n-by-n matrix of weights
*
@throws
IllegalArgumentException unless all weights are nonnegative
*
@throws
IllegalArgumentException if {
@code
weight} is {
@code
null}
*/
public
AssignmentProblem
(
double
[][]
weight
)
{
if
(
weight
==
null
)
throw
new
IllegalArgumentException
(
“constructor argument is null”
);
n
=
weight
.
length
;
this
.
weight
=
new
double
[
n
][
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
if
(
Double
.
isNaN
(
weight
[
i
][
j
]))
throw
new
IllegalArgumentException
(
"weight "
+
i
+
"-"
+
j
+
" is NaN"
);
if
(
weight
[
i
][
j
]
<
minWeight
)
minWeight
=
weight
[
i
][
j
];
this
.
weight
[
i
][
j
]
=
weight
[
i
][
j
];
}
}
// dual variables
px
=
new
double
[
n
];
py
=
new
double
[
n
];
// initial matching is empty
xy
=
new
int
[
n
];
yx
=
new
int
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
xy
[
i
]
=
UNMATCHED
;
for
(
int
j
=
0
;
j
<
n
;
j
++
)
yx
[
j
]
=
UNMATCHED
;
// add n edges to matching
for
(
int
k
=
0
;
k
<
n
;
k
++
)
{
assert
isDualFeasible
();
assert
isComplementarySlack
();
augment
();
}
assert
certifySolution
();
}
// find shortest augmenting path and upate
private
void
augment
()
{
// build residual graph
EdgeWeightedDigraph
G
=
new
EdgeWeightedDigraph
(
2
*
n
+
2
);
int
s
=
2
*
n
,
t
=
2
*
n
+
1
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
if
(
xy
[
i
]
==
UNMATCHED
)
G
.
addEdge
(
new
DirectedEdge
(
s
,
i
,
0.0
));
}
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
if
(
yx
[
j
]
==
UNMATCHED
)
G
.
addEdge
(
new
DirectedEdge
(
n
+
j
,
t
,
py
[
j
]));
}
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
if
(
xy
[
i
]
==
j
)
G
.
addEdge
(
new
DirectedEdge
(
n
+
j
,
i
,
0.0
));
else
G
.
addEdge
(
new
DirectedEdge
(
i
,
n
+
j
,
reducedCost
(
i
,
j
)));
}
}
// compute shortest path from s to every other vertex
DijkstraSP
spt
=
new
DijkstraSP
(
G
,
s
);
// augment along alternating path
for
(
DirectedEdge
e
:
spt
.
pathTo
(
t
))
{
int
i
=
e
.
from
(),
j
=
e
.
to
()
-
n
;
if
(
i
<
n
)
{
xy
[
i
]
=
j
;
yx
[
j
]
=
i
;
}
}
// update dual variables
for
(
int
i
=
0
;
i
<
n
;
i
++
)
px
[
i
]
+=
spt
.
distTo
(
i
);
for
(
int
j
=
0
;
j
<
n
;
j
++
)
py
[
j
]
+=
spt
.
distTo
(
n
+
j
);
}
// reduced cost of i-j
// (subtracting off minWeight reweights all weights to be non-negative)
private
double
reducedCost
(
int
i
,
int
j
)
{
double
reducedCost
=
(
weight
[
i
][
j
]
-
minWeight
)
+
px
[
i
]
-
py
[
j
];
// to avoid issues with floating-point precision
double
magnitude
=
Math
.
abs
(
weight
[
i
][
j
])
+
Math
.
abs
(
px
[
i
])
+
Math
.
abs
(
py
[
j
]);
if
(
Math
.
abs
(
reducedCost
)
<=
FLOATING_POINT_EPSILON
*
magnitude
)
return
0.0
;
assert
reducedCost
>=
0.0
;
return
reducedCost
;
}
/**
* Returns the dual optimal value for the specified row.
*
*
@param
i the row index
*
@return
the dual optimal value for row {
@code
i}
*
@throws
IllegalArgumentException unless {
@code
0 <= i < n}
*
*/
// dual variable for row i
public
double
dualRow
(
int
i
)
{
validate
(
i
);
return
px
[
i
];
}
/**
* Returns the dual optimal value for the specified column.
*
*
@param
j the column index
*
@return
the dual optimal value for column {
@code
j}
*
@throws
IllegalArgumentException unless {
@code
0 <= j < n}
*
*/
public
double
dualCol
(
int
j
)
{
validate
(
j
);
return
py
[
j
];
}
/**
* Returns the column associated with the specified row in the optimal solution.
*
*
@param
i the row index
*
@return
the column matched to row {
@code
i} in the optimal solution
*
@throws
IllegalArgumentException unless {
@code
0 <= i < n}
*
*/
public
int
sol
(
int
i
)
{
validate
(
i
);
return
xy
[
i
];
}
/**
* Returns the total weight of the optimal solution
*
*
@return
the total weight of the optimal solution
*
*/
public
double
weight
()
{
double
total
=
0.0
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
if
(
xy
[
i
]
!=
UNMATCHED
)
total
+=
weight
[
i
][
xy
[
i
]];
}
return
total
;
}
private
void
validate
(
int
i
)
{
if
(
i
<
0
||
i
>=
n
)
throw
new
IllegalArgumentException
(
“index is not between 0 and ”
+
(
n
–
1
)
+
“: ”
+
i
);
}
/**************************************************************************
*
* The code below is solely for testing correctness of the data type.
*
**************************************************************************/
// check that dual variables are feasible
private
boolean
isDualFeasible
()
{
// check that all edges have >= 0 reduced cost
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
if
(
reducedCost
(
i
,
j
)
<
0
)
{
StdOut
.
println
(
"Dual variables are not feasible"
);
return
false
;
}
}
}
return
true
;
}
// check that primal and dual variables are complementary slack
private
boolean
isComplementarySlack
()
{
// check that all matched edges have 0-reduced cost
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
if
((
xy
[
i
]
!=
UNMATCHED
)
&&
(
reducedCost
(
i
,
xy
[
i
])
!=
0
))
{
StdOut
.
println
(
"Primal and dual variables are not complementary slack"
);
return
false
;
}
}
return
true
;
}
// check that primal variables are a perfect matching
private
boolean
isPerfectMatching
()
{
// check that xy[] is a perfect matching
boolean
[]
perm
=
new
boolean
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
if
(
perm
[
xy
[
i
]])
{
StdOut
.
println
(
"Not a perfect matching"
);
return
false
;
}
perm
[
xy
[
i
]]
=
true
;
}
// check that xy[] and yx[] are inverses
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
if
(
xy
[
yx
[
j
]]
!=
j
)
{
StdOut
.
println
(
"xy[] and yx[] are not inverses"
);
return
false
;
}
}
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
if
(
yx
[
xy
[
i
]]
!=
i
)
{
StdOut
.
println
(
"xy[] and yx[] are not inverses"
);
return
false
;
}
}
return
true
;
}
// check optimality conditions
private
boolean
certifySolution
()
{
return
isPerfectMatching
()
&&
isDualFeasible
()
&&
isComplementarySlack
();
}
/**
* Unit tests the {
@code
AssignmentProblem} data type.
* Takes a command-line argument n; creates a random n-by-n matrix;
* solves the n-by-n assignment problem; and prints the optimal
* solution.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// create random n-by-n matrix
int
n
=
Integer
.
parseInt
(
args
[
0
]);
double
[][]
weight
=
new
double
[
n
][
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
weight
[
i
][
j
]
=
StdRandom
.
uniform
(
900
)
+
100
;
// 3 digits
}
}
// solve assignment problem
AssignmentProblem
assignment
=
new
AssignmentProblem
(
weight
);
StdOut
.
printf
(
"weight = %.0f\n"
,
assignment
.
weight
());
StdOut
.
println
();
// print n-by-n matrix and optimal solution
if
(
n
>=
20
)
return
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
if
(
j
==
assignment
.
sol
(
i
))
StdOut
.
printf
(
"*%.0f "
,
weight
[
i
][
j
]);
else
StdOut
.
printf
(
" %.0f "
,
weight
[
i
][
j
]);
}
StdOut
.
println
();
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Average.java
edu/princeton/cs/algs4/Average.java
/******************************************************************************
* Compilation: javac Average.java
* Execution: java Average < data.txt
* Dependencies: StdIn.java StdOut.java
*
* Reads in a sequence of real numbers, and computes their average.
*
* % java Average
* 10.0 5.0 6.0
* 3.0 7.0 32.0
* [Ctrl-d]
* Average is 10.5
*
* Note [Ctrl-d] signifies the end of file on Unix.
* On windows use [Ctrl-z].
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Average} class provides a client for reading in a sequence
* of real numbers and printing out their average.
*
* For additional documentation, see Section 1.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Average
{
// this class should not be instantiated
private
Average
()
{
}
/**
* Reads in a sequence of real numbers from standard input and prints
* out their average to standard output.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
count
=
0
;
// number input values
double
sum
=
0.0
;
// sum of input values
// read data and compute statistics
while
(
!
StdIn
.
isEmpty
())
{
double
value
=
StdIn
.
readDouble
();
sum
+=
value
;
count
++
;
}
// compute the average
double
average
=
sum
/
count
;
// print results
StdOut
.
println
(
“Average is ”
+
average
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/AVLTreeST.java
edu/princeton/cs/algs4/AVLTreeST.java
/******************************************************************************
* Compilation: javac AVLTreeST.java
* Execution: java AVLTreeST < input.txt * Dependencies: StdIn.java StdOut.java * Data files: https://algs4.cs.princeton.edu/33balanced/tinyST.txt * * A symbol table implemented using an AVL tree. * * % more tinyST.txt * S E A R C H E X A M P L E * * % java AVLTreeST < tinyST.txt * A 8 * C 4 * E 12 * H 5 * L 11 * M 9 * P 10 * R 3 * S 0 * X 7 * ******************************************************************************/ package edu . princeton . cs . algs4 ; import java . util . NoSuchElementException ; /** * The { @code AVLTreeST} class represents an ordered symbol table of * generic key-value pairs. It supports the usual put, get,
* contains, delete, size, and is-empty
* methods. It also provides ordered methods for finding the minimum,
* maximum, floor, and ceiling. It also provides a
* keys method for iterating over all of the keys. A symbol table
* implements the associative array abstraction: when associating a
* value with a key that is already in the symbol table, the convention is to
* replace the old value with the new value. Unlike {
@link
java.util.Map}, this
* class uses the convention that values cannot be {
@code
null}
* —setting the value associated with a key to {
@code
null} is
* equivalent to deleting the key from the symbol table.
*
* This symbol table implementation uses internally an
* AVL tree (Georgy
* Adelson-Velsky and Evgenii Landis’ tree) which is a self-balancing BST.
* In an AVL tree, the heights of the two child subtrees of any
* node differ by at most one; if at any time they differ by more than one,
* rebalancing is done to restore this property.
*
* This implementation requires that the key type implements the
* {
@code
Comparable} interface and calls the {
@code
compareTo()} and
* method to compare two keys. It does not call either {
@code
equals()} or
* {
@code
hashCode()}. The put, get, contains,
* delete, minimum, maximum, ceiling, and
* floor operations each take logarithmic time in the worst case. The
* size, and is-empty operations take constant time.
* Construction also takes constant time.
*
* For other implementations of the same API, see {
@link
ST}, {
@link
BinarySearchST},
* {
@link
SequentialSearchST}, {
@link
BST}, {
@link
RedBlackBST},
* {
@link
SeparateChainingHashST}, and {
@link
LinearProbingHashST}.
*
*
@author
Marcelo Silva
*/
public
class
AVLTreeST
<
Key
extends
Comparable
<
Key
>
,
Value
>
{
/**
* The root node.
*/
private
Node
root
;
/**
* This class represents an inner node of the AVL tree.
*/
private
class
Node
{
private
final
Key
key
;
// the key
private
Value
val
;
// the associated value
private
int
height
;
// height of the subtree
private
int
size
;
// number of nodes in subtree
private
Node
left
;
// left subtree
private
Node
right
;
// right subtree
public
Node
(
Key
key
,
Value
val
,
int
height
,
int
size
)
{
this
.
key
=
key
;
this
.
val
=
val
;
this
.
size
=
size
;
this
.
height
=
height
;
}
}
/**
* Initializes an empty symbol table.
*/
public
AVLTreeST
()
{
}
/**
* Checks if the symbol table is empty.
*
*
@return
{
@code
true} if the symbol table is empty.
*/
public
boolean
isEmpty
()
{
return
root
==
null
;
}
/**
* Returns the number key-value pairs in the symbol table.
*
*
@return
the number key-value pairs in the symbol table
*/
public
int
size
()
{
return
size
(
root
);
}
/**
* Returns the number of nodes in the subtree.
*
*
@param
x the subtree
*
*
@return
the number of nodes in the subtree
*/
private
int
size
(
Node
x
)
{
if
(
x
==
null
)
return
0
;
return
x
.
size
;
}
/**
* Returns the height of the internal AVL tree. It is assumed that the
* height of an empty tree is -1 and the height of a tree with just one node
* is 0.
*
*
@return
the height of the internal AVL tree
*/
public
int
height
()
{
return
height
(
root
);
}
/**
* Returns the height of the subtree.
*
*
@param
x the subtree
*
*
@return
the height of the subtree.
*/
private
int
height
(
Node
x
)
{
if
(
x
==
null
)
return
–
1
;
return
x
.
height
;
}
/**
* Returns the value associated with the given key.
*
*
@param
key the key
*
@return
the value associated with the given key if the key is in the
* symbol table and {
@code
null} if the key is not in the
* symbol table
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
Value
get
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to get() is null”
);
Node
x
=
get
(
root
,
key
);
if
(
x
==
null
)
return
null
;
return
x
.
val
;
}
/**
* Returns value associated with the given key in the subtree or
* {
@code
null} if no such key.
*
*
@param
x the subtree
*
@param
key the key
*
@return
value associated with the given key in the subtree or
* {
@code
null} if no such key
*/
private
Node
get
(
Node
x
,
Key
key
)
{
if
(
x
==
null
)
return
null
;
int
cmp
=
key
.
compareTo
(
x
.
key
);
if
(
cmp
<
0
)
return
get
(
x
.
left
,
key
);
else
if
(
cmp
>
0
)
return
get
(
x
.
right
,
key
);
else
return
x
;
}
/**
* Checks if the symbol table contains the given key.
*
*
@param
key the key
*
@return
{
@code
true} if the symbol table contains {
@code
key}
* and {
@code
false} otherwise
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
boolean
contains
(
Key
key
)
{
return
get
(
key
)
!=
null
;
}
/**
* Inserts the specified key-value pair into the symbol table, overwriting
* the old value with the new value if the symbol table already contains the
* specified key. Deletes the specified key (and its associated value) from
* this symbol table if the specified value is {
@code
null}.
*
*
@param
key the key
*
@param
val the value
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
put
(
Key
key
,
Value
val
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“first argument to put() is null”
);
if
(
val
==
null
)
{
delete
(
key
);
return
;
}
root
=
put
(
root
,
key
,
val
);
assert
check
();
}
/**
* Inserts the key-value pair in the subtree. It overrides the old value
* with the new value if the symbol table already contains the specified key
* and deletes the specified key (and its associated value) from this symbol
* table if the specified value is {
@code
null}.
*
*
@param
x the subtree
*
@param
key the key
*
@param
val the value
*
@return
the subtree
*/
private
Node
put
(
Node
x
,
Key
key
,
Value
val
)
{
if
(
x
==
null
)
return
new
Node
(
key
,
val
,
0
,
1
);
int
cmp
=
key
.
compareTo
(
x
.
key
);
if
(
cmp
<
0
)
{
x
.
left
=
put
(
x
.
left
,
key
,
val
);
}
else
if
(
cmp
>
0
)
{
x
.
right
=
put
(
x
.
right
,
key
,
val
);
}
else
{
x
.
val
=
val
;
return
x
;
}
x
.
size
=
1
+
size
(
x
.
left
)
+
size
(
x
.
right
);
x
.
height
=
1
+
Math
.
max
(
height
(
x
.
left
),
height
(
x
.
right
));
return
balance
(
x
);
}
/**
* Restores the AVL tree property of the subtree.
*
*
@param
x the subtree
*
@return
the subtree with restored AVL property
*/
private
Node
balance
(
Node
x
)
{
if
(
balanceFactor
(
x
)
<
-
1
)
{
if
(
balanceFactor
(
x
.
right
)
>
0
)
{
x
.
right
=
rotateRight
(
x
.
right
);
}
x
=
rotateLeft
(
x
);
}
else
if
(
balanceFactor
(
x
)
>
1
)
{
if
(
balanceFactor
(
x
.
left
)
<
0
)
{
x
.
left
=
rotateLeft
(
x
.
left
);
}
x
=
rotateRight
(
x
);
}
return
x
;
}
/**
* Returns the balance factor of the subtree. The balance factor is defined
* as the difference in height of the left subtree and right subtree, in
* this order. Therefore, a subtree with a balance factor of -1, 0 or 1 has
* the AVL property since the heights of the two child subtrees differ by at
* most one.
*
*
@param
x the subtree
*
@return
the balance factor of the subtree
*/
private
int
balanceFactor
(
Node
x
)
{
return
height
(
x
.
left
)
-
height
(
x
.
right
);
}
/**
* Rotates the given subtree to the right.
*
*
@param
x the subtree
*
@return
the right rotated subtree
*/
private
Node
rotateRight
(
Node
x
)
{
Node
y
=
x
.
left
;
x
.
left
=
y
.
right
;
y
.
right
=
x
;
y
.
size
=
x
.
size
;
x
.
size
=
1
+
size
(
x
.
left
)
+
size
(
x
.
right
);
x
.
height
=
1
+
Math
.
max
(
height
(
x
.
left
),
height
(
x
.
right
));
y
.
height
=
1
+
Math
.
max
(
height
(
y
.
left
),
height
(
y
.
right
));
return
y
;
}
/**
* Rotates the given subtree to the left.
*
*
@param
x the subtree
*
@return
the left rotated subtree
*/
private
Node
rotateLeft
(
Node
x
)
{
Node
y
=
x
.
right
;
x
.
right
=
y
.
left
;
y
.
left
=
x
;
y
.
size
=
x
.
size
;
x
.
size
=
1
+
size
(
x
.
left
)
+
size
(
x
.
right
);
x
.
height
=
1
+
Math
.
max
(
height
(
x
.
left
),
height
(
x
.
right
));
y
.
height
=
1
+
Math
.
max
(
height
(
y
.
left
),
height
(
y
.
right
));
return
y
;
}
/**
* Removes the specified key and its associated value from the symbol table
* (if the key is in the symbol table).
*
*
@param
key the key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
delete
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
"argument to delete() is null"
);
if
(
!
contains
(
key
))
return
;
root
=
delete
(
root
,
key
);
assert
check
();
}
/**
* Removes the specified key and its associated value from the given
* subtree.
*
*
@param
x the subtree
*
@param
key the key
*
@return
the updated subtree
*/
private
Node
delete
(
Node
x
,
Key
key
)
{
int
cmp
=
key
.
compareTo
(
x
.
key
);
if
(
cmp
<
0
)
{
x
.
left
=
delete
(
x
.
left
,
key
);
}
else
if
(
cmp
>
0
)
{
x
.
right
=
delete
(
x
.
right
,
key
);
}
else
{
if
(
x
.
left
==
null
)
{
return
x
.
right
;
}
else
if
(
x
.
right
==
null
)
{
return
x
.
left
;
}
else
{
Node
y
=
x
;
x
=
min
(
y
.
right
);
x
.
right
=
deleteMin
(
y
.
right
);
x
.
left
=
y
.
left
;
}
}
x
.
size
=
1
+
size
(
x
.
left
)
+
size
(
x
.
right
);
x
.
height
=
1
+
Math
.
max
(
height
(
x
.
left
),
height
(
x
.
right
));
return
balance
(
x
);
}
/**
* Removes the smallest key and associated value from the symbol table.
*
*
@throws
NoSuchElementException if the symbol table is empty
*/
public
void
deleteMin
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“called deleteMin() with empty symbol table”
);
root
=
deleteMin
(
root
);
assert
check
();
}
/**
* Removes the smallest key and associated value from the given subtree.
*
*
@param
x the subtree
*
@return
the updated subtree
*/
private
Node
deleteMin
(
Node
x
)
{
if
(
x
.
left
==
null
)
return
x
.
right
;
x
.
left
=
deleteMin
(
x
.
left
);
x
.
size
=
1
+
size
(
x
.
left
)
+
size
(
x
.
right
);
x
.
height
=
1
+
Math
.
max
(
height
(
x
.
left
),
height
(
x
.
right
));
return
balance
(
x
);
}
/**
* Removes the largest key and associated value from the symbol table.
*
*
@throws
NoSuchElementException if the symbol table is empty
*/
public
void
deleteMax
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“called deleteMax() with empty symbol table”
);
root
=
deleteMax
(
root
);
assert
check
();
}
/**
* Removes the largest key and associated value from the given subtree.
*
*
@param
x the subtree
*
@return
the updated subtree
*/
private
Node
deleteMax
(
Node
x
)
{
if
(
x
.
right
==
null
)
return
x
.
left
;
x
.
right
=
deleteMax
(
x
.
right
);
x
.
size
=
1
+
size
(
x
.
left
)
+
size
(
x
.
right
);
x
.
height
=
1
+
Math
.
max
(
height
(
x
.
left
),
height
(
x
.
right
));
return
balance
(
x
);
}
/**
* Returns the smallest key in the symbol table.
*
*
@return
the smallest key in the symbol table
*
@throws
NoSuchElementException if the symbol table is empty
*/
public
Key
min
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“called min() with empty symbol table”
);
return
min
(
root
).
key
;
}
/**
* Returns the node with the smallest key in the subtree.
*
*
@param
x the subtree
*
@return
the node with the smallest key in the subtree
*/
private
Node
min
(
Node
x
)
{
if
(
x
.
left
==
null
)
return
x
;
return
min
(
x
.
left
);
}
/**
* Returns the largest key in the symbol table.
*
*
@return
the largest key in the symbol table
*
@throws
NoSuchElementException if the symbol table is empty
*/
public
Key
max
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“called max() with empty symbol table”
);
return
max
(
root
).
key
;
}
/**
* Returns the node with the largest key in the subtree.
*
*
@param
x the subtree
*
@return
the node with the largest key in the subtree
*/
private
Node
max
(
Node
x
)
{
if
(
x
.
right
==
null
)
return
x
;
return
max
(
x
.
right
);
}
/**
* Returns the largest key in the symbol table less than or equal to
* {
@code
key}.
*
*
@param
key the key
*
@return
the largest key in the symbol table less than or equal to
* {
@code
key}
*
@throws
NoSuchElementException if the symbol table is empty
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
Key
floor
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to floor() is null”
);
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“called floor() with empty symbol table”
);
Node
x
=
floor
(
root
,
key
);
if
(
x
==
null
)
return
null
;
else
return
x
.
key
;
}
/**
* Returns the node in the subtree with the largest key less than or equal
* to the given key.
*
*
@param
x the subtree
*
@param
key the key
*
@return
the node in the subtree with the largest key less than or equal
* to the given key
*/
private
Node
floor
(
Node
x
,
Key
key
)
{
if
(
x
==
null
)
return
null
;
int
cmp
=
key
.
compareTo
(
x
.
key
);
if
(
cmp
==
0
)
return
x
;
if
(
cmp
<
0
)
return
floor
(
x
.
left
,
key
);
Node
y
=
floor
(
x
.
right
,
key
);
if
(
y
!=
null
)
return
y
;
else
return
x
;
}
/**
* Returns the smallest key in the symbol table greater than or equal to
* {
@code
key}.
*
*
@param
key the key
*
@return
the smallest key in the symbol table greater than or equal to
* {
@code
key}
*
@throws
NoSuchElementException if the symbol table is empty
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
Key
ceiling
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
"argument to ceiling() is null"
);
if
(
isEmpty
())
throw
new
NoSuchElementException
(
"called ceiling() with empty symbol table"
);
Node
x
=
ceiling
(
root
,
key
);
if
(
x
==
null
)
return
null
;
else
return
x
.
key
;
}
/**
* Returns the node in the subtree with the smallest key greater than or
* equal to the given key.
*
*
@param
x the subtree
*
@param
key the key
*
@return
the node in the subtree with the smallest key greater than or
* equal to the given key
*/
private
Node
ceiling
(
Node
x
,
Key
key
)
{
if
(
x
==
null
)
return
null
;
int
cmp
=
key
.
compareTo
(
x
.
key
);
if
(
cmp
==
0
)
return
x
;
if
(
cmp
>
0
)
return
ceiling
(
x
.
right
,
key
);
Node
y
=
ceiling
(
x
.
left
,
key
);
if
(
y
!=
null
)
return
y
;
else
return
x
;
}
/**
* Returns the kth smallest key in the symbol table.
*
*
@param
k the order statistic
*
@return
the kth smallest key in the symbol table
*
@throws
IllegalArgumentException unless {
@code
k} is between 0 and
* {
@code
size() -1 }
*/
public
Key
select
(
int
k
)
{
if
(
k
<
0
||
k
>=
size
())
throw
new
IllegalArgumentException
(
“k is not in range 0-”
+
(
size
()
–
1
));
Node
x
=
select
(
root
,
k
);
return
x
.
key
;
}
/**
* Returns the node with key the kth smallest key in the subtree.
*
*
@param
x the subtree
*
@param
k the kth smallest key in the subtree
*
@return
the node with key the kth smallest key in the subtree
*/
private
Node
select
(
Node
x
,
int
k
)
{
if
(
x
==
null
)
return
null
;
int
t
=
size
(
x
.
left
);
if
(
t
>
k
)
return
select
(
x
.
left
,
k
);
else
if
(
t
<
k
)
return
select
(
x
.
right
,
k
-
t
-
1
);
else
return
x
;
}
/**
* Returns the number of keys in the symbol table strictly less than
* {
@code
key}.
*
*
@param
key the key
*
@return
the number of keys in the symbol table strictly less than
* {
@code
key}
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
int
rank
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
"argument to rank() is null"
);
return
rank
(
key
,
root
);
}
/**
* Returns the number of keys in the subtree less than key.
*
*
@param
key the key
*
@param
x the subtree
*
@return
the number of keys in the subtree less than key
*/
private
int
rank
(
Key
key
,
Node
x
)
{
if
(
x
==
null
)
return
0
;
int
cmp
=
key
.
compareTo
(
x
.
key
);
if
(
cmp
<
0
)
return
rank
(
key
,
x
.
left
);
else
if
(
cmp
>
0
)
return
1
+
size
(
x
.
left
)
+
rank
(
key
,
x
.
right
);
else
return
size
(
x
.
left
);
}
/**
* Returns all keys in the symbol table.
*
*
@return
all keys in the symbol table
*/
public
Iterable
<
Key
>
keys
()
{
return
keysInOrder
();
}
/**
* Returns all keys in the symbol table following an in-order traversal.
*
*
@return
all keys in the symbol table following an in-order traversal
*/
public
Iterable
<
Key
>
keysInOrder
()
{
Queue
<
Key
>
queue
=
new
Queue
<
Key
>
();
keysInOrder
(
root
,
queue
);
return
queue
;
}
/**
* Adds the keys in the subtree to queue following an in-order traversal.
*
*
@param
x the subtree
*
@param
queue the queue
*/
private
void
keysInOrder
(
Node
x
,
Queue
<
Key
>
queue
)
{
if
(
x
==
null
)
return
;
keysInOrder
(
x
.
left
,
queue
);
queue
.
enqueue
(
x
.
key
);
keysInOrder
(
x
.
right
,
queue
);
}
/**
* Returns all keys in the symbol table following a level-order traversal.
*
*
@return
all keys in the symbol table following a level-order traversal.
*/
public
Iterable
<
Key
>
keysLevelOrder
()
{
Queue
<
Key
>
queue
=
new
Queue
<
Key
>
();
if
(
!
isEmpty
())
{
Queue
<
Node
>
queue2
=
new
Queue
<
Node
>
();
queue2
.
enqueue
(
root
);
while
(
!
queue2
.
isEmpty
())
{
Node
x
=
queue2
.
dequeue
();
queue
.
enqueue
(
x
.
key
);
if
(
x
.
left
!=
null
)
{
queue2
.
enqueue
(
x
.
left
);
}
if
(
x
.
right
!=
null
)
{
queue2
.
enqueue
(
x
.
right
);
}
}
}
return
queue
;
}
/**
* Returns all keys in the symbol table in the given range.
*
*
@param
lo the lowest key
*
@param
hi the highest key
*
@return
all keys in the symbol table between {
@code
lo} (inclusive)
* and {
@code
hi} (exclusive)
*
@throws
IllegalArgumentException if either {
@code
lo} or {
@code
hi}
* is {
@code
null}
*/
public
Iterable
<
Key
>
keys
(
Key
lo
,
Key
hi
)
{
if
(
lo
==
null
)
throw
new
IllegalArgumentException
(
“first argument to keys() is null”
);
if
(
hi
==
null
)
throw
new
IllegalArgumentException
(
“second argument to keys() is null”
);
Queue
<
Key
>
queue
=
new
Queue
<
Key
>
();
keys
(
root
,
queue
,
lo
,
hi
);
return
queue
;
}
/**
* Adds the keys between {
@code
lo} and {
@code
hi} in the subtree
* to the {
@code
queue}.
*
*
@param
x the subtree
*
@param
queue the queue
*
@param
lo the lowest key
*
@param
hi the highest key
*/
private
void
keys
(
Node
x
,
Queue
<
Key
>
queue
,
Key
lo
,
Key
hi
)
{
if
(
x
==
null
)
return
;
int
cmplo
=
lo
.
compareTo
(
x
.
key
);
int
cmphi
=
hi
.
compareTo
(
x
.
key
);
if
(
cmplo
<
0
)
keys
(
x
.
left
,
queue
,
lo
,
hi
);
if
(
cmplo
<=
0
&&
cmphi
>=
0
)
queue
.
enqueue
(
x
.
key
);
if
(
cmphi
>
0
)
keys
(
x
.
right
,
queue
,
lo
,
hi
);
}
/**
* Returns the number of keys in the symbol table in the given range.
*
*
@param
lo minimum endpoint
*
@param
hi maximum endpoint
*
@return
the number of keys in the symbol table between {
@code
lo}
* (inclusive) and {
@code
hi} (exclusive)
*
@throws
IllegalArgumentException if either {
@code
lo} or {
@code
hi}
* is {
@code
null}
*/
public
int
size
(
Key
lo
,
Key
hi
)
{
if
(
lo
==
null
)
throw
new
IllegalArgumentException
(
“first argument to size() is null”
);
if
(
hi
==
null
)
throw
new
IllegalArgumentException
(
“second argument to size() is null”
);
if
(
lo
.
compareTo
(
hi
)
>
0
)
return
0
;
if
(
contains
(
hi
))
return
rank
(
hi
)
–
rank
(
lo
)
+
1
;
else
return
rank
(
hi
)
–
rank
(
lo
);
}
/**
* Checks if the AVL tree invariants are fine.
*
*
@return
{
@code
true} if the AVL tree invariants are fine
*/
private
boolean
check
()
{
if
(
!
isBST
())
StdOut
.
println
(
“Symmetric order not consistent”
);
if
(
!
isAVL
())
StdOut
.
println
(
“AVL property not consistent”
);
if
(
!
isSizeConsistent
())
StdOut
.
println
(
“Subtree counts not consistent”
);
if
(
!
isRankConsistent
())
StdOut
.
println
(
“Ranks not consistent”
);
return
isBST
()
&&
isAVL
()
&&
isSizeConsistent
()
&&
isRankConsistent
();
}
/**
* Checks if AVL property is consistent.
*
*
@return
{
@code
true} if AVL property is consistent.
*/
private
boolean
isAVL
()
{
return
isAVL
(
root
);
}
/**
* Checks if AVL property is consistent in the subtree.
*
*
@param
x the subtree
*
@return
{
@code
true} if AVL property is consistent in the subtree
*/
private
boolean
isAVL
(
Node
x
)
{
if
(
x
==
null
)
return
true
;
int
bf
=
balanceFactor
(
x
);
if
(
bf
>
1
||
bf
<
-
1
)
return
false
;
return
isAVL
(
x
.
left
)
&&
isAVL
(
x
.
right
);
}
/**
* Checks if the symmetric order is consistent.
*
*
@return
{
@code
true} if the symmetric order is consistent
*/
private
boolean
isBST
()
{
return
isBST
(
root
,
null
,
null
);
}
/**
* Checks if the tree rooted at x is a BST with all keys strictly between
* min and max (if min or max is null, treat as empty constraint) Credit:
* Bob Dondero's elegant solution
*
*
@param
x the subtree
*
@param
min the minimum key in subtree
*
@param
max the maximum key in subtree
*
@return
{
@code
true} if if the symmetric order is consistent
*/
private
boolean
isBST
(
Node
x
,
Key
min
,
Key
max
)
{
if
(
x
==
null
)
return
true
;
if
(
min
!=
null
&&
x
.
key
.
compareTo
(
min
)
<=
0
)
return
false
;
if
(
max
!=
null
&&
x
.
key
.
compareTo
(
max
)
>=
0
)
return
false
;
return
isBST
(
x
.
left
,
min
,
x
.
key
)
&&
isBST
(
x
.
right
,
x
.
key
,
max
);
}
/**
* Checks if size is consistent.
*
*
@return
{
@code
true} if size is consistent
*/
private
boolean
isSizeConsistent
()
{
return
isSizeConsistent
(
root
);
}
/**
* Checks if the size of the subtree is consistent.
*
*
@return
{
@code
true} if the size of the subtree is consistent
*/
private
boolean
isSizeConsistent
(
Node
x
)
{
if
(
x
==
null
)
return
true
;
if
(
x
.
size
!=
size
(
x
.
left
)
+
size
(
x
.
right
)
+
1
)
return
false
;
return
isSizeConsistent
(
x
.
left
)
&&
isSizeConsistent
(
x
.
right
);
}
/**
* Checks if rank is consistent.
*
*
@return
{
@code
true} if rank is consistent
*/
private
boolean
isRankConsistent
()
{
for
(
int
i
=
0
;
i
<
size
();
i
++
)
if
(
i
!=
rank
(
select
(
i
)))
return
false
;
for
(
Key
key
:
keys
())
if
(
key
.
compareTo
(
select
(
rank
(
key
)))
!=
0
)
return
false
;
return
true
;
}
/**
* Unit tests the {
@code
AVLTreeST} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
AVLTreeST
<
String
,
Integer
>
st
=
new
AVLTreeST
<
String
,
Integer
>
();
for
(
int
i
=
0
;
!
StdIn
.
isEmpty
();
i
++
)
{
String
key
=
StdIn
.
readString
();
st
.
put
(
key
,
i
);
}
for
(
String
s
:
st
.
keys
())
StdOut
.
println
(
s
+
” ”
+
st
.
get
(
s
));
StdOut
.
println
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Bag.java
edu/princeton/cs/algs4/Bag.java
/******************************************************************************
* Compilation: javac Bag.java
* Execution: java Bag < input.txt * Dependencies: StdIn.java StdOut.java * * A generic bag or multiset, implemented using a singly linked list. * * % more tobe.txt * to be or not to - be - - that - - - is * * % java Bag < tobe.txt * size of bag = 14 * is * - * - * - * that * - * - * be * - * to * not * or * be * to * ******************************************************************************/ package edu . princeton . cs . algs4 ; import java . util . Iterator ; import java . util . NoSuchElementException ; /** * The { @code Bag} class represents a bag (or multiset) of * generic items. It supports insertion and iterating over the * items in arbitrary order. *
* This implementation uses a singly linked list with a static nested class Node.
* See {
@link
LinkedBag} for the version from the
* textbook that uses a non-static nested class.
* See {
@link
ResizingArrayBag} for a version that uses a resizing array.
* The add, isEmpty, and size operations
* take constant time. Iteration takes time proportional to the number of items.
*
* For additional documentation, see Section 1.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*
*
@param
*/
public
class
Bag
<
Item
>
implements
Iterable
<
Item
>
{
private
Node
<
Item
>
first
;
// beginning of bag
private
int
n
;
// number of elements in bag
// helper linked list class
private
static
class
Node
<
Item
>
{
private
Item
item
;
private
Node
<
Item
>
next
;
}
/**
* Initializes an empty bag.
*/
public
Bag
()
{
first
=
null
;
n
=
0
;
}
/**
* Returns true if this bag is empty.
*
*
@return
{
@code
true} if this bag is empty;
* {
@code
false} otherwise
*/
public
boolean
isEmpty
()
{
return
first
==
null
;
}
/**
* Returns the number of items in this bag.
*
*
@return
the number of items in this bag
*/
public
int
size
()
{
return
n
;
}
/**
* Adds the item to this bag.
*
*
@param
item the item to add to this bag
*/
public
void
add
(
Item
item
)
{
Node
<
Item
>
oldfirst
=
first
;
first
=
new
Node
<
Item
>
();
first
.
item
=
item
;
first
.
next
=
oldfirst
;
n
++
;
}
/**
* Returns an iterator that iterates over the items in this bag in arbitrary order.
*
*
@return
an iterator that iterates over the items in this bag in arbitrary order
*/
public
Iterator
<
Item
>
iterator
()
{
return
new
ListIterator
(
first
);
}
// an iterator, doesn’t implement remove() since it’s optional
private
class
ListIterator
implements
Iterator
<
Item
>
{
private
Node
<
Item
>
current
;
public
ListIterator
(
Node
<
Item
>
first
)
{
current
=
first
;
}
public
boolean
hasNext
()
{
return
current
!=
null
;
}
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
public
Item
next
()
{
if
(
!
hasNext
())
throw
new
NoSuchElementException
();
Item
item
=
current
.
item
;
current
=
current
.
next
;
return
item
;
}
}
/**
* Unit tests the {
@code
Bag} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
Bag
<
String
>
bag
=
new
Bag
<
String
>
();
while
(
!
StdIn
.
isEmpty
())
{
String
item
=
StdIn
.
readString
();
bag
.
add
(
item
);
}
StdOut
.
println
(
“size of bag = ”
+
bag
.
size
());
for
(
String
s
:
bag
)
{
StdOut
.
println
(
s
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/BellmanFordSP.java
edu/princeton/cs/algs4/BellmanFordSP.java
/******************************************************************************
* Compilation: javac BellmanFordSP.java
* Execution: java BellmanFordSP filename.txt s
* Dependencies: EdgeWeightedDigraph.java DirectedEdge.java Queue.java
* EdgeWeightedDirectedCycle.java
* Data files: https://algs4.cs.princeton.edu/44sp/tinyEWDn.txt
* https://algs4.cs.princeton.edu/44sp/mediumEWDnc.txt
*
* Bellman-Ford shortest path algorithm. Computes the shortest path tree in
* edge-weighted digraph G from vertex s, or finds a negative cost cycle
* reachable from s.
*
* % java BellmanFordSP tinyEWDn.txt 0
* 0 to 0 ( 0.00)
* 0 to 1 ( 0.93) 0->2 0.26 2->7 0.34 7->3 0.39 3->6 0.52 6->4 -1.25 4->5 0.35 5->1 0.32
* 0 to 2 ( 0.26) 0->2 0.26
* 0 to 3 ( 0.99) 0->2 0.26 2->7 0.34 7->3 0.39
* 0 to 4 ( 0.26) 0->2 0.26 2->7 0.34 7->3 0.39 3->6 0.52 6->4 -1.25
* 0 to 5 ( 0.61) 0->2 0.26 2->7 0.34 7->3 0.39 3->6 0.52 6->4 -1.25 4->5 0.35
* 0 to 6 ( 1.51) 0->2 0.26 2->7 0.34 7->3 0.39 3->6 0.52
* 0 to 7 ( 0.60) 0->2 0.26 2->7 0.34
*
* % java BellmanFordSP tinyEWDnc.txt 0
* 4->5 0.35
* 5->4 -0.66
*
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
BellmanFordSP} class represents a data type for solving the
* single-source shortest paths problem in edge-weighted digraphs with
* no negative cycles.
* The edge weights can be positive, negative, or zero.
* This class finds either a shortest path from the source vertex s
* to every other vertex or a negative cycle reachable from the source vertex.
*
* This implementation uses a queue-based implementation of
* the Bellman-Ford-Moore algorithm.
* The constructor takes Θ(V (V + E)) time
* in the worst case, where V is the number of vertices and
* E is the number of edges. In practice, it performs much better.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the
* edge-weighted digraph).
*
* For additional documentation,
* see Section 4.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
BellmanFordSP
{
private
double
[]
distTo
;
// distTo[v] = distance of shortest s->v path
private
DirectedEdge
[]
edgeTo
;
// edgeTo[v] = last edge on shortest s->v path
private
boolean
[]
onQueue
;
// onQueue[v] = is v currently on the queue?
private
Queue
<
Integer
>
queue
;
// queue of vertices to relax
private
int
cost
;
// number of calls to relax()
private
Iterable
<
DirectedEdge
>
cycle
;
// negative cycle (or null if no such cycle)
/**
* Computes a shortest paths tree from {
@code
s} to every other vertex in
* the edge-weighted digraph {
@code
G}.
*
@param
G the acyclic digraph
*
@param
s the source vertex
*
@throws
IllegalArgumentException unless {
@code
0 <= s < V}
*/
public
BellmanFordSP
(
EdgeWeightedDigraph
G
,
int
s
)
{
distTo
=
new
double
[
G
.
V
()];
edgeTo
=
new
DirectedEdge
[
G
.
V
()];
onQueue
=
new
boolean
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
distTo
[
v
]
=
Double
.
POSITIVE_INFINITY
;
distTo
[
s
]
=
0.0
;
// Bellman-Ford algorithm
queue
=
new
Queue
<
Integer
>
();
queue
.
enqueue
(
s
);
onQueue
[
s
]
=
true
;
while
(
!
queue
.
isEmpty
()
&&
!
hasNegativeCycle
())
{
int
v
=
queue
.
dequeue
();
onQueue
[
v
]
=
false
;
relax
(
G
,
v
);
}
assert
check
(
G
,
s
);
}
// relax vertex v and put other endpoints on queue if changed
private
void
relax
(
EdgeWeightedDigraph
G
,
int
v
)
{
for
(
DirectedEdge
e
:
G
.
adj
(
v
))
{
int
w
=
e
.
to
();
if
(
distTo
[
w
]
>
distTo
[
v
]
+
e
.
weight
())
{
distTo
[
w
]
=
distTo
[
v
]
+
e
.
weight
();
edgeTo
[
w
]
=
e
;
if
(
!
onQueue
[
w
])
{
queue
.
enqueue
(
w
);
onQueue
[
w
]
=
true
;
}
}
if
(
++
cost
%
G
.
V
()
==
0
)
{
findNegativeCycle
();
if
(
hasNegativeCycle
())
return
;
// found a negative cycle
}
}
}
/**
* Is there a negative cycle reachable from the source vertex {
@code
s}?
*
@return
{
@code
true} if there is a negative cycle reachable from the
* source vertex {
@code
s}, and {
@code
false} otherwise
*/
public
boolean
hasNegativeCycle
()
{
return
cycle
!=
null
;
}
/**
* Returns a negative cycle reachable from the source vertex {
@code
s}, or {
@code
null}
* if there is no such cycle.
*
@return
a negative cycle reachable from the soruce vertex {
@code
s}
* as an iterable of edges, and {
@code
null} if there is no such cycle
*/
public
Iterable
<
DirectedEdge
>
negativeCycle
()
{
return
cycle
;
}
// by finding a cycle in predecessor graph
private
void
findNegativeCycle
()
{
int
V
=
edgeTo
.
length
;
EdgeWeightedDigraph
spt
=
new
EdgeWeightedDigraph
(
V
);
for
(
int
v
=
0
;
v
<
V
;
v
++
)
if
(
edgeTo
[
v
]
!=
null
)
spt
.
addEdge
(
edgeTo
[
v
]);
EdgeWeightedDirectedCycle
finder
=
new
EdgeWeightedDirectedCycle
(
spt
);
cycle
=
finder
.
cycle
();
}
/**
* Returns the length of a shortest path from the source vertex {
@code
s} to vertex {
@code
v}.
*
@param
v the destination vertex
*
@return
the length of a shortest path from the source vertex {
@code
s} to vertex {
@code
v};
* {
@code
Double.POSITIVE_INFINITY} if no such path
*
@throws
UnsupportedOperationException if there is a negative cost cycle reachable
* from the source vertex {
@code
s}
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
double
distTo
(
int
v
)
{
validateVertex
(
v
);
if
(
hasNegativeCycle
())
throw
new
UnsupportedOperationException
(
"Negative cost cycle exists"
);
return
distTo
[
v
];
}
/**
* Is there a path from the source {
@code
s} to vertex {
@code
v}?
*
@param
v the destination vertex
*
@return
{
@code
true} if there is a path from the source vertex
* {
@code
s} to vertex {
@code
v}, and {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
boolean
hasPathTo
(
int
v
)
{
validateVertex
(
v
);
return
distTo
[
v
]
<
Double
.
POSITIVE_INFINITY
;
}
/**
* Returns a shortest path from the source {
@code
s} to vertex {
@code
v}.
*
@param
v the destination vertex
*
@return
a shortest path from the source {
@code
s} to vertex {
@code
v}
* as an iterable of edges, and {
@code
null} if no such path
*
@throws
UnsupportedOperationException if there is a negative cost cycle reachable
* from the source vertex {
@code
s}
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
Iterable
<
DirectedEdge
>
pathTo
(
int
v
)
{
validateVertex
(
v
);
if
(
hasNegativeCycle
())
throw
new
UnsupportedOperationException
(
“Negative cost cycle exists”
);
if
(
!
hasPathTo
(
v
))
return
null
;
Stack
<
DirectedEdge
>
path
=
new
Stack
<
DirectedEdge
>
();
for
(
DirectedEdge
e
=
edgeTo
[
v
];
e
!=
null
;
e
=
edgeTo
[
e
.
from
()])
{
path
.
push
(
e
);
}
return
path
;
}
// check optimality conditions: either
// (i) there exists a negative cycle reacheable from s
// or
// (ii) for all edges e = v->w: distTo[w] <= distTo[v] + e.weight()
// (ii') for all edges e = v->w on the SPT: distTo[w] == distTo[v] + e.weight()
private
boolean
check
(
EdgeWeightedDigraph
G
,
int
s
)
{
// has a negative cycle
if
(
hasNegativeCycle
())
{
double
weight
=
0.0
;
for
(
DirectedEdge
e
:
negativeCycle
())
{
weight
+=
e
.
weight
();
}
if
(
weight
>=
0.0
)
{
System
.
err
.
println
(
“error: weight of negative cycle = ”
+
weight
);
return
false
;
}
}
// no negative cycle reachable from source
else
{
// check that distTo[v] and edgeTo[v] are consistent
if
(
distTo
[
s
]
!=
0.0
||
edgeTo
[
s
]
!=
null
)
{
System
.
err
.
println
(
“distanceTo[s] and edgeTo[s] inconsistent”
);
return
false
;
}
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
v
==
s
)
continue
;
if
(
edgeTo
[
v
]
==
null
&&
distTo
[
v
]
!=
Double
.
POSITIVE_INFINITY
)
{
System
.
err
.
println
(
"distTo[] and edgeTo[] inconsistent"
);
return
false
;
}
}
// check that all edges e = v->w satisfy distTo[w] <= distTo[v] + e.weight()
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
for
(
DirectedEdge
e
:
G
.
adj
(
v
))
{
int
w
=
e
.
to
();
if
(
distTo
[
v
]
+
e
.
weight
()
<
distTo
[
w
])
{
System
.
err
.
println
(
"edge "
+
e
+
" not relaxed"
);
return
false
;
}
}
}
// check that all edges e = v->w on SPT satisfy distTo[w] == distTo[v] + e.weight()
for
(
int
w
=
0
;
w
<
G
.
V
();
w
++
)
{
if
(
edgeTo
[
w
]
==
null
)
continue
;
DirectedEdge
e
=
edgeTo
[
w
];
int
v
=
e
.
from
();
if
(
w
!=
e
.
to
())
return
false
;
if
(
distTo
[
v
]
+
e
.
weight
()
!=
distTo
[
w
])
{
System
.
err
.
println
(
"edge "
+
e
+
" on shortest path not tight"
);
return
false
;
}
}
}
StdOut
.
println
(
"Satisfies optimality conditions"
);
StdOut
.
println
();
return
true
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
distTo
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
BellmanFordSP} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
int
s
=
Integer
.
parseInt
(
args
[
1
]);
EdgeWeightedDigraph
G
=
new
EdgeWeightedDigraph
(
in
);
BellmanFordSP
sp
=
new
BellmanFordSP
(
G
,
s
);
// print negative cycle
if
(
sp
.
hasNegativeCycle
())
{
for
(
DirectedEdge
e
:
sp
.
negativeCycle
())
StdOut
.
println
(
e
);
}
// print shortest paths
else
{
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
sp
.
hasPathTo
(
v
))
{
StdOut
.
printf
(
"%d to %d (%5.2f) "
,
s
,
v
,
sp
.
distTo
(
v
));
for
(
DirectedEdge
e
:
sp
.
pathTo
(
v
))
{
StdOut
.
print
(
e
+
" "
);
}
StdOut
.
println
();
}
else
{
StdOut
.
printf
(
"%d to %d no path\n"
,
s
,
v
);
}
}
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/BinaryDump.java
edu/princeton/cs/algs4/BinaryDump.java
/******************************************************************************
* Compilation: javac BinaryDump.java
* Execution: java BinaryDump n < file
* Dependencies: BinaryStdIn.java
* Data file: https://introcs.cs.princeton.edu/stdlib/abra.txt
*
* Reads in a binary file and writes out the bits, n per line.
*
* % more abra.txt
* ABRACADABRA!
*
* % java BinaryDump 16 < abra.txt
* 0100000101000010
* 0101001001000001
* 0100001101000001
* 0100010001000001
* 0100001001010010
* 0100000100100001
* 96 bits
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
BinaryDump} class provides a client for displaying the contents
* of a binary file in binary.
*
* For more full-featured versions, see the Unix utilities
* {
@code
od} (octal dump) and {
@code
hexdump} (hexadecimal dump).
*
* For additional documentation,
* see Section 5.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* See also {
@link
HexDump} and {
@link
PictureDump}.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
BinaryDump
{
// Do not instantiate.
private
BinaryDump
()
{
}
/**
* Reads in a sequence of bytes from standard input and writes
* them to standard output in binary, k bits per line,
* where k is given as a command-line integer (defaults
* to 16 if no integer is specified); also writes the number
* of bits.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
bitsPerLine
=
16
;
if
(
args
.
length
==
1
)
{
bitsPerLine
=
Integer
.
parseInt
(
args
[
0
]);
}
int
count
;
for
(
count
=
0
;
!
BinaryStdIn
.
isEmpty
();
count
++
)
{
if
(
bitsPerLine
==
0
)
{
BinaryStdIn
.
readBoolean
();
continue
;
}
else
if
(
count
!=
0
&&
count
%
bitsPerLine
==
0
)
StdOut
.
println
();
if
(
BinaryStdIn
.
readBoolean
())
StdOut
.
print
(
1
);
else
StdOut
.
print
(
0
);
}
if
(
bitsPerLine
!=
0
)
StdOut
.
println
();
StdOut
.
println
(
count
+
” bits”
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/BinaryIn.java
edu/princeton/cs/algs4/BinaryIn.java
/******************************************************************************
* Compilation: javac BinaryIn.java
* Execution: java BinaryIn input output
* Dependencies: none
*
* This library is for reading binary data from an input stream.
*
* % java BinaryIn https://introcs.cs.princeton.edu/java/cover output
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
io
.
BufferedInputStream
;
import
java
.
io
.
File
;
import
java
.
io
.
FileInputStream
;
import
java
.
io
.
IOException
;
import
java
.
io
.
InputStream
;
import
java
.
net
.
Socket
;
import
java
.
net
.
URL
;
import
java
.
net
.
URLConnection
;
import
java
.
util
.
NoSuchElementException
;
/**
* Binary input. This class provides methods for reading
* in bits from a binary input stream, either
* one bit at a time (as a {
@code
boolean}),
* 8 bits at a time (as a {
@code
byte} or {
@code
char}),
* 16 bits at a time (as a {
@code
short}),
* 32 bits at a time (as an {
@code
int} or {
@code
float}), or
* 64 bits at a time (as a {
@code
double} or {
@code
long}).
*
* The binary input stream can be from standard input, a filename,
* a URL name, a Socket, or an InputStream.
*
* All primitive types are assumed to be represented using their
* standard Java representations, in big-endian (most significant
* byte first) order.
*
* The client should not intermix calls to {
@code
BinaryIn} with calls
* to {
@code
In}; otherwise unexpected behavior will result.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
BinaryIn
{
private
static
final
int
EOF
=
–
1
;
// end of file
private
BufferedInputStream
in
;
// the input stream
private
int
buffer
;
// one character buffer
private
int
n
;
// number of bits left in buffer
/**
* Initializes a binary input stream from standard input.
*/
public
BinaryIn
()
{
in
=
new
BufferedInputStream
(
System
.
in
);
fillBuffer
();
}
/**
* Initializes a binary input stream from an {
@code
InputStream}.
*
*
@param
is the {
@code
InputStream} object
*/
public
BinaryIn
(
InputStream
is
)
{
in
=
new
BufferedInputStream
(
is
);
fillBuffer
();
}
/**
* Initializes a binary input stream from a socket.
*
*
@param
socket the socket
*/
public
BinaryIn
(
Socket
socket
)
{
try
{
InputStream
is
=
socket
.
getInputStream
();
in
=
new
BufferedInputStream
(
is
);
fillBuffer
();
}
catch
(
IOException
ioe
)
{
System
.
err
.
println
(
“Could not open ”
+
socket
);
}
}
/**
* Initializes a binary input stream from a URL.
*
*
@param
url the URL
*/
public
BinaryIn
(
URL url
)
{
try
{
URLConnection
site
=
url
.
openConnection
();
InputStream
is
=
site
.
getInputStream
();
in
=
new
BufferedInputStream
(
is
);
fillBuffer
();
}
catch
(
IOException
ioe
)
{
System
.
err
.
println
(
“Could not open ”
+
url
);
}
}
/**
* Initializes a binary input stream from a filename or URL name.
*
*
@param
name the name of the file or URL
*/
public
BinaryIn
(
String
name
)
{
try
{
// first try to read file from local file system
File
file
=
new
File
(
name
);
if
(
file
.
exists
())
{
FileInputStream
fis
=
new
FileInputStream
(
file
);
in
=
new
BufferedInputStream
(
fis
);
fillBuffer
();
return
;
}
// next try for files included in jar
URL url
=
getClass
().
getResource
(
name
);
// or URL from web
if
(
url
==
null
)
{
url
=
new
URL
(
name
);
}
URLConnection
site
=
url
.
openConnection
();
InputStream
is
=
site
.
getInputStream
();
in
=
new
BufferedInputStream
(
is
);
fillBuffer
();
}
catch
(
IOException
ioe
)
{
System
.
err
.
println
(
“Could not open ”
+
name
);
}
}
private
void
fillBuffer
()
{
try
{
buffer
=
in
.
read
();
n
=
8
;
}
catch
(
IOException
e
)
{
System
.
err
.
println
(
“EOF”
);
buffer
=
EOF
;
n
=
–
1
;
}
}
/**
* Returns true if this binary input stream exists.
*
*
@return
{
@code
true} if this binary input stream exists;
* {
@code
false} otherwise
*/
public
boolean
exists
()
{
return
in
!=
null
;
}
/**
* Returns true if this binary input stream is empty.
*
*
@return
{
@code
true} if this binary input stream is empty;
* {
@code
false} otherwise
*/
public
boolean
isEmpty
()
{
return
buffer
==
EOF
;
}
/**
* Reads the next bit of data from this binary input stream and return as a boolean.
*
*
@return
the next bit of data from this binary input stream as a {
@code
boolean}
*
@throws
NoSuchElementException if this binary input stream is empty
*/
public
boolean
readBoolean
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Reading from empty input stream”
);
n
—
;
boolean
bit
=
((
buffer
>>
n
)
&
1
)
==
1
;
if
(
n
==
0
)
fillBuffer
();
return
bit
;
}
/**
* Reads the next 8 bits from this binary input stream and return as an 8-bit char.
*
*
@return
the next 8 bits of data from this binary input stream as a {
@code
char}
*
@throws
NoSuchElementException if there are fewer than 8 bits available
*/
public
char
readChar
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Reading from empty input stream”
);
// special case when aligned byte
if
(
n
==
8
)
{
int
x
=
buffer
;
fillBuffer
();
return
(
char
)
(
x
&
0xff
);
}
// combine last N bits of current buffer with first 8-N bits of new buffer
int
x
=
buffer
;
x
<<=
(
8
-
n
);
int
oldN
=
n
;
fillBuffer
();
if
(
isEmpty
())
throw
new
NoSuchElementException
(
"Reading from empty input stream"
);
n
=
oldN
;
x
|=
(
buffer
>>>
n
);
return
(
char
)
(
x
&
0xff
);
// the above code doesn’t quite work for the last character if N = 8
// because buffer will be -1
}
/**
* Reads the next r bits from this binary input stream and return as an r-bit character.
*
*
@param
r number of bits to read
*
@return
the next {
@code
r} bits of data from this binary input streamt as a {
@code
char}
*
@throws
NoSuchElementException if there are fewer than {
@code
r} bits available
*
@throws
IllegalArgumentException unless {
@code
1 <= r <= 16}
*/
public
char
readChar
(
int
r
)
{
if
(
r
<
1
||
r
>
16
)
throw
new
IllegalArgumentException
(
“Illegal value of r = ”
+
r
);
// optimize r = 8 case
if
(
r
==
8
)
return
readChar
();
char
x
=
0
;
for
(
int
i
=
0
;
i
<
r
;
i
++
)
{
x
<<=
1
;
boolean
bit
=
readBoolean
();
if
(
bit
)
x
|=
1
;
}
return
x
;
}
/**
* Reads the remaining bytes of data from this binary input stream and return as a string.
*
*
@return
the remaining bytes of data from this binary input stream as a {
@code
String}
*
@throws
NoSuchElementException if this binary input stream is empty or if the number of bits
* available is not a multiple of 8 (byte-aligned)
*/
public
String
readString
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
"Reading from empty input stream"
);
StringBuilder
sb
=
new
StringBuilder
();
while
(
!
isEmpty
())
{
char
c
=
readChar
();
sb
.
append
(
c
);
}
return
sb
.
toString
();
}
/**
* Reads the next 16 bits from this binary input stream and return as a 16-bit short.
*
*
@return
the next 16 bits of data from this binary input stream as a {
@code
short}
*
@throws
NoSuchElementException if there are fewer than 16 bits available
*/
public
short
readShort
()
{
short
x
=
0
;
for
(
int
i
=
0
;
i
<
2
;
i
++
)
{
char
c
=
readChar
();
x
<<=
8
;
x
|=
c
;
}
return
x
;
}
/**
* Reads the next 32 bits from this binary input stream and return as a 32-bit int.
*
*
@return
the next 32 bits of data from this binary input stream as a {
@code
int}
*
@throws
NoSuchElementException if there are fewer than 32 bits available
*/
public
int
readInt
()
{
int
x
=
0
;
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
char
c
=
readChar
();
x
<<=
8
;
x
|=
c
;
}
return
x
;
}
/**
* Reads the next r bits from this binary input stream return as an r-bit int.
*
*
@param
r number of bits to read
*
@return
the next {
@code
r} bits of data from this binary input stream as a {
@code
int}
*
@throws
NoSuchElementException if there are fewer than r bits available
*
@throws
IllegalArgumentException unless {
@code
1 <= r <= 32}
*/
public
int
readInt
(
int
r
)
{
if
(
r
<
1
||
r
>
32
)
throw
new
IllegalArgumentException
(
“Illegal value of r = ”
+
r
);
// optimize r = 32 case
if
(
r
==
32
)
return
readInt
();
int
x
=
0
;
for
(
int
i
=
0
;
i
<
r
;
i
++
)
{
x
<<=
1
;
boolean
bit
=
readBoolean
();
if
(
bit
)
x
|=
1
;
}
return
x
;
}
/**
* Reads the next 64 bits from this binary input stream and return as a 64-bit long.
*
*
@return
the next 64 bits of data from this binary input stream as a {
@code
long}
*
@throws
NoSuchElementException if there are fewer than 64 bits available
*/
public
long
readLong
()
{
long
x
=
0
;
for
(
int
i
=
0
;
i
<
8
;
i
++
)
{
char
c
=
readChar
();
x
<<=
8
;
x
|=
c
;
}
return
x
;
}
/**
* Reads the next 64 bits from this binary input stream and return as a 64-bit double.
*
*
@return
the next 64 bits of data from this binary input stream as a {
@code
double}
*
@throws
NoSuchElementException if there are fewer than 64 bits available
*/
public
double
readDouble
()
{
return
Double
.
longBitsToDouble
(
readLong
());
}
/**
* Reads the next 32 bits from this binary input stream and return as a 32-bit float.
*
*
@return
the next 32 bits of data from this binary input stream as a {
@code
float}
*
@throws
NoSuchElementException if there are fewer than 32 bits available
*/
public
float
readFloat
()
{
return
Float
.
intBitsToFloat
(
readInt
());
}
/**
* Reads the next 8 bits from this binary input stream and return as an 8-bit byte.
*
*
@return
the next 8 bits of data from this binary input stream as a {
@code
byte}
*
@throws
NoSuchElementException if there are fewer than 8 bits available
*/
public
byte
readByte
()
{
char
c
=
readChar
();
return
(
byte
)
(
c
&
0xff
);
}
/**
* Unit tests the {
@code
BinaryIn} data type.
* Reads the name of a file or URL (first command-line argument)
* and writes it to a file (second command-line argument).
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
BinaryIn
in
=
new
BinaryIn
(
args
[
0
]);
BinaryOut
out
=
new
BinaryOut
(
args
[
1
]);
// read one 8-bit char at a time
while
(
!
in
.
isEmpty
())
{
char
c
=
in
.
readChar
();
out
.
write
(
c
);
}
out
.
flush
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/BinaryInsertion.java
edu/princeton/cs/algs4/BinaryInsertion.java
/******************************************************************************
* Compilation: javac BinaryInsertion.java
* Execution: java BinaryInsertion < input.txt
* Dependencies: StdOut.java StdIn.java
* Data files: https://algs4.cs.princeton.edu/21elementary/tiny.txt
* https://algs4.cs.princeton.edu/21elementary/words3.txt
*
* Sorts a sequence of strings from standard input using
* binary insertion sort with half exchanges.
*
* % more tiny.txt
* S O R T E X A M P L E
*
* % java BinaryInsertion < tiny.txt
* A E E L M O P R S T X [ one string per line ]
*
* % more words3.txt
* bed bug dad yes zoo ... all bad yet
*
* % java BinaryInsertion < words3.txt
* all bad bed bug dad ... yes yet zoo [ one string per line ]
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
BinaryInsertion} class provides a static method for sorting an
* array using an optimized binary insertion sort with half exchanges.
*
* In the worst case, this implementation makes
* ~ n log2n compares to sort an array of length
* n. However, in the worst case, the running time is
* Θ(n2) because the number of array accesses
* can be quadratic.
* As such, it is not suitable for sorting large arrays
* (unless the number of inversions is small).
*
* This sorting algorithm is stable.
* It uses Θ(1) extra memory (not including the input array).
*
* For additional documentation,
* see Section 2.1
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Ivan Pesin
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
BinaryInsertion
{
// This class should not be instantiated.
private
BinaryInsertion
()
{
}
/**
* Rearranges the array in ascending order, using the natural order.
*
@param
a the array to be sorted
*/
public
static
void
sort
(
Comparable
[]
a
)
{
int
n
=
a
.
length
;
for
(
int
i
=
1
;
i
<
n
;
i
++
)
{
// binary search to determine index j at which to insert a[i]
Comparable
v
=
a
[
i
];
int
lo
=
0
,
hi
=
i
;
while
(
lo
<
hi
)
{
int
mid
=
lo
+
(
hi
-
lo
)
/
2
;
if
(
less
(
v
,
a
[
mid
]))
hi
=
mid
;
else
lo
=
mid
+
1
;
}
// insetion sort with "half exchanges"
// (insert a[i] at index j and shift a[j], ..., a[i-1] to right)
for
(
int
j
=
i
;
j
>
lo
;
—
j
)
a
[
j
]
=
a
[
j
–
1
];
a
[
lo
]
=
v
;
}
assert
isSorted
(
a
);
}
/***************************************************************************
* Helper sorting function.
***************************************************************************/
// is v < w ?
private
static
boolean
less
(
Comparable
v
,
Comparable
w
)
{
return
v
.
compareTo
(
w
)
<
0
;
}
/***************************************************************************
* Check if array is sorted - useful for debugging.
***************************************************************************/
private
static
boolean
isSorted
(
Comparable
[]
a
)
{
return
isSorted
(
a
,
0
,
a
.
length
-
1
);
}
// is the array sorted from a[lo] to a[hi]
private
static
boolean
isSorted
(
Comparable
[]
a
,
int
lo
,
int
hi
)
{
for
(
int
i
=
lo
+
1
;
i
<=
hi
;
i
++
)
if
(
less
(
a
[
i
],
a
[
i
-
1
]))
return
false
;
return
true
;
}
// print array to standard output
private
static
void
show
(
Comparable
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
StdOut
.
println
(
a
[
i
]);
}
}
/**
* Reads in a sequence of strings from standard input; insertion sorts them;
* and prints them to standard output in ascending order.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
[]
a
=
StdIn
.
readAllStrings
();
BinaryInsertion
.
sort
(
a
);
show
(
a
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/BinaryOut.java
edu/princeton/cs/algs4/BinaryOut.java
/******************************************************************************
* Compilation: javac BinaryOut.java
* Execution: java BinaryOut
* Dependencies: none
*
* Write binary data to an output stream, either one 1-bit boolean,
* one 8-bit char, one 32-bit int, one 64-bit double, one 32-bit float,
* or one 64-bit long at a time. The output stream can be standard
* output, a file, an OutputStream or a Socket.
*
* The bytes written are not aligned.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
io
.
BufferedOutputStream
;
import
java
.
io
.
FileOutputStream
;
import
java
.
io
.
IOException
;
import
java
.
io
.
OutputStream
;
import
java
.
net
.
Socket
;
/**
* Binary output. This class provides methods for converting
* primtive type variables ({
@code
boolean}, {
@code
byte}, {
@code
char},
* {
@code
int}, {
@code
long}, {
@code
float}, and {
@code
double})
* to sequences of bits and writing them to an output stream.
* The output stream can be standard output, a file, an OutputStream or a Socket.
* Uses big-endian (most-significant byte first).
*
* The client must {
@code
flush()} the output stream when finished writing bits.
*
* The client should not intermix calls to {
@code
BinaryOut} with calls
* to {
@code
Out}; otherwise unexpected behavior will result.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
BinaryOut
{
private
BufferedOutputStream
out
;
// the output stream
private
int
buffer
;
// 8-bit buffer of bits to write out
private
int
n
;
// number of bits remaining in buffer
/**
* Initializes a binary output stream from standard output.
*/
public
BinaryOut
()
{
out
=
new
BufferedOutputStream
(
System
.
out
);
}
/**
* Initializes a binary output stream from an {
@code
OutputStream}.
*
@param
os the {
@code
OutputStream}
*/
public
BinaryOut
(
OutputStream
os
)
{
out
=
new
BufferedOutputStream
(
os
);
}
/**
* Initializes a binary output stream from a file.
*
@param
filename the name of the file
*/
public
BinaryOut
(
String
filename
)
{
try
{
OutputStream
os
=
new
FileOutputStream
(
filename
);
out
=
new
BufferedOutputStream
(
os
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
/**
* Initializes a binary output stream from a socket.
*
@param
socket the socket
*/
public
BinaryOut
(
Socket
socket
)
{
try
{
OutputStream
os
=
socket
.
getOutputStream
();
out
=
new
BufferedOutputStream
(
os
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
/**
* Writes the specified bit to the binary output stream.
*
@param
x the bit
*/
private
void
writeBit
(
boolean
x
)
{
// add bit to buffer
buffer
<<=
1
;
if
(
x
)
buffer
|=
1
;
// if buffer is full (8 bits), write out as a single byte
n
++
;
if
(
n
==
8
)
clearBuffer
();
}
/**
* Writes the 8-bit byte to the binary output stream.
*
@param
x the byte
*/
private
void
writeByte
(
int
x
)
{
assert
x
>=
0
&&
x
<
256
;
// optimized if byte-aligned
if
(
n
==
0
)
{
try
{
out
.
write
(
x
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
return
;
}
// otherwise write one bit at a time
for
(
int
i
=
0
;
i
<
8
;
i
++
)
{
boolean
bit
=
((
x
>>>
(
8
–
i
–
1
))
&
1
)
==
1
;
writeBit
(
bit
);
}
}
// write out any remaining bits in buffer to the binary output stream, padding with 0s
private
void
clearBuffer
()
{
if
(
n
==
0
)
return
;
if
(
n
>
0
)
buffer
<<=
(
8
-
n
);
try
{
out
.
write
(
buffer
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
n
=
0
;
buffer
=
0
;
}
/**
* Flushes the binary output stream, padding 0s if number of bits written so far
* is not a multiple of 8.
*/
public
void
flush
()
{
clearBuffer
();
try
{
out
.
flush
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
/**
* Flushes and closes the binary output stream.
* Once it is closed, bits can no longer be written.
*/
public
void
close
()
{
flush
();
try
{
out
.
close
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
/**
* Writes the specified bit to the binary output stream.
*
@param
x the {
@code
boolean} to write
*/
public
void
write
(
boolean
x
)
{
writeBit
(
x
);
}
/**
* Writes the 8-bit byte to the binary output stream.
*
@param
x the {
@code
byte} to write.
*/
public
void
write
(
byte
x
)
{
writeByte
(
x
&
0xff
);
}
/**
* Writes the 32-bit int to the binary output stream.
*
@param
x the {
@code
int} to write
*/
public
void
write
(
int
x
)
{
writeByte
((
x
>>>
24
)
&
0xff
);
writeByte
((
x
>>>
16
)
&
0xff
);
writeByte
((
x
>>>
8
)
&
0xff
);
writeByte
((
x
>>>
0
)
&
0xff
);
}
/**
* Writes the r-bit int to the binary output stream.
*
*
@param
x the {
@code
int} to write
*
@param
r the number of relevant bits in the char
*
@throws
IllegalArgumentException unless {
@code
r} is between 1 and 32
*
@throws
IllegalArgumentException unless {
@code
x} is between 0 and 2r – 1
*/
public
void
write
(
int
x
,
int
r
)
{
if
(
r
==
32
)
{
write
(
x
);
return
;
}
if
(
r
<
1
||
r
>
32
)
throw
new
IllegalArgumentException
(
“Illegal value for r = ”
+
r
);
if
(
x
>=
(
1
<<
r
))
throw
new
IllegalArgumentException
(
"Illegal "
+
r
+
"-bit char = "
+
x
);
for
(
int
i
=
0
;
i
<
r
;
i
++
)
{
boolean
bit
=
((
x
>>>
(
r
–
i
–
1
))
&
1
)
==
1
;
writeBit
(
bit
);
}
}
/**
* Writes the 64-bit double to the binary output stream.
*
@param
x the {
@code
double} to write
*/
public
void
write
(
double
x
)
{
write
(
Double
.
doubleToRawLongBits
(
x
));
}
/**
* Writes the 64-bit long to the binary output stream.
*
@param
x the {
@code
long} to write
*/
public
void
write
(
long
x
)
{
writeByte
((
int
)
((
x
>>>
56
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
48
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
40
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
32
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
24
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
16
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
8
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
0
)
&
0xff
));
}
/**
* Writes the 32-bit float to the binary output stream.
*
@param
x the {
@code
float} to write
*/
public
void
write
(
float
x
)
{
write
(
Float
.
floatToRawIntBits
(
x
));
}
/**
* Write the 16-bit int to the binary output stream.
*
@param
x the {
@code
short} to write.
*/
public
void
write
(
short
x
)
{
writeByte
((
x
>>>
8
)
&
0xff
);
writeByte
((
x
>>>
0
)
&
0xff
);
}
/**
* Writes the 8-bit char to the binary output stream.
*
*
@param
x the {
@code
char} to write
*
@throws
IllegalArgumentException unless {
@code
x} is betwen 0 and 255
*/
public
void
write
(
char
x
)
{
if
(
x
<
0
||
x
>=
256
)
throw
new
IllegalArgumentException
(
“Illegal 8-bit char = ”
+
x
);
writeByte
(
x
);
}
/**
* Writes the r-bit char to the binary output stream.
*
*
@param
x the {
@code
char} to write
*
@param
r the number of relevant bits in the char
*
@throws
IllegalArgumentException unless {
@code
r} is between 1 and 16
*
@throws
IllegalArgumentException unless {
@code
x} is between 0 and 2r – 1
*/
public
void
write
(
char
x
,
int
r
)
{
if
(
r
==
8
)
{
write
(
x
);
return
;
}
if
(
r
<
1
||
r
>
16
)
throw
new
IllegalArgumentException
(
“Illegal value for r = ”
+
r
);
if
(
x
>=
(
1
<<
r
))
throw
new
IllegalArgumentException
(
"Illegal "
+
r
+
"-bit char = "
+
x
);
for
(
int
i
=
0
;
i
<
r
;
i
++
)
{
boolean
bit
=
((
x
>>>
(
r
–
i
–
1
))
&
1
)
==
1
;
writeBit
(
bit
);
}
}
/**
* Writes the string of 8-bit characters to the binary output stream.
*
*
@param
s the {
@code
String} to write
*
@throws
IllegalArgumentException if any character in the string is not
* between 0 and 255
*/
public
void
write
(
String
s
)
{
for
(
int
i
=
0
;
i
<
s
.
length
();
i
++
)
write
(
s
.
charAt
(
i
));
}
/**
* Writes the string of r-bit characters to the binary output stream.
*
@param
s the {
@code
String} to write
*
@param
r the number of relevants bits in each character
*
@throws
IllegalArgumentException unless r is between 1 and 16
*
@throws
IllegalArgumentException if any character in the string is not
* between 0 and 2r – 1
*/
public
void
write
(
String
s
,
int
r
)
{
for
(
int
i
=
0
;
i
<
s
.
length
();
i
++
)
write
(
s
.
charAt
(
i
),
r
);
}
/**
* Test client. Read bits from standard input and write to the file
* specified on command line.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// create binary output stream to write to file
String
filename
=
args
[
0
];
BinaryOut
out
=
new
BinaryOut
(
filename
);
BinaryIn
in
=
new
BinaryIn
();
// read from standard input and write to file
while
(
!
in
.
isEmpty
())
{
char
c
=
in
.
readChar
();
out
.
write
(
c
);
}
out
.
flush
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/BinarySearch.java
edu/princeton/cs/algs4/BinarySearch.java
/******************************************************************************
* Compilation: javac BinarySearch.java
* Execution: java BinarySearch whitelist.txt < input.txt
* Dependencies: In.java StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/11model/tinyW.txt
* https://algs4.cs.princeton.edu/11model/tinyT.txt
* https://algs4.cs.princeton.edu/11model/largeW.txt
* https://algs4.cs.princeton.edu/11model/largeT.txt
*
* % java BinarySearch tinyW.txt < tinyT.txt
* 50
* 99
* 13
*
* % java BinarySearch largeW.txt < largeT.txt | more
* 499569
* 984875
* 295754
* 207807
* 140925
* 161828
* [367,966 total values]
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Arrays
;
/**
* The {
@code
BinarySearch} class provides a static method for binary
* searching for an integer in a sorted array of integers.
*
* The indexOf operations takes logarithmic time in the worst case.
*
* For additional documentation, see Section 1.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
BinarySearch
{
/**
* This class should not be instantiated.
*/
private
BinarySearch
()
{
}
/**
* Returns the index of the specified key in the specified array.
*
*
@param
a the array of integers, must be sorted in ascending order
*
@param
key the search key
*
@return
index of key in array {
@code
a} if present; {
@code
-1} otherwise
*/
public
static
int
indexOf
(
int
[]
a
,
int
key
)
{
int
lo
=
0
;
int
hi
=
a
.
length
–
1
;
while
(
lo
<=
hi
)
{
// Key is in a[lo..hi] or not present.
int
mid
=
lo
+
(
hi
-
lo
)
/
2
;
if
(
key
<
a
[
mid
])
hi
=
mid
-
1
;
else
if
(
key
>
a
[
mid
])
lo
=
mid
+
1
;
else
return
mid
;
}
return
–
1
;
}
/**
* Returns the index of the specified key in the specified array.
* This function is poorly named because it does not give the rank
* if the array has duplicate keys or if the key is not in the array.
*
*
@param
key the search key
*
@param
a the array of integers, must be sorted in ascending order
*
@return
index of key in array {
@code
a} if present; {
@code
-1} otherwise
*
@deprecated
Replaced by {
@link
#indexOf(int[], int)}.
*/
@
Deprecated
public
static
int
rank
(
int
key
,
int
[]
a
)
{
return
indexOf
(
a
,
key
);
}
/**
* Reads in a sequence of integers from the whitelist file, specified as
* a command-line argument; reads in integers from standard input;
* prints to standard output those integers that do not appear in the file.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// read the integers from a file
In
in
=
new
In
(
args
[
0
]);
int
[]
whitelist
=
in
.
readAllInts
();
// sort the array
Arrays
.
sort
(
whitelist
);
// read integer key from standard input; print if not in whitelist
while
(
!
StdIn
.
isEmpty
())
{
int
key
=
StdIn
.
readInt
();
if
(
BinarySearch
.
indexOf
(
whitelist
,
key
)
==
–
1
)
StdOut
.
println
(
key
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/BinarySearchST.java
edu/princeton/cs/algs4/BinarySearchST.java
/******************************************************************************
* Compilation: javac BinarySearchST.java
* Execution: java BinarySearchST
* Dependencies: StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/31elementary/tinyST.txt
*
* Symbol table implementation with binary search in an ordered array.
*
* % more tinyST.txt
* S E A R C H E X A M P L E
*
* % java BinarySearchST < tinyST.txt * A 8 * C 4 * E 12 * H 5 * L 11 * M 9 * P 10 * R 3 * S 0 * X 7 * ******************************************************************************/ package edu . princeton . cs . algs4 ; import java . util . NoSuchElementException ; /** * The { @code BST} class represents an ordered symbol table of generic * key-value pairs. * It supports the usual put, get, contains,
* delete, size, and is-empty methods.
* It also provides ordered methods for finding the minimum,
* maximum, floor, select, and ceiling.
* It also provides a keys method for iterating over all of the keys.
* A symbol table implements the associative array abstraction:
* when associating a value with a key that is already in the symbol table,
* the convention is to replace the old value with the new value.
* Unlike {
@link
java.util.Map}, this class uses the convention that
* values cannot be {
@code
null}—setting the
* value associated with a key to {
@code
null} is equivalent to deleting the key
* from the symbol table.
*
* It requires that
* the key type implements the {
@code
Comparable} interface and calls the
* {
@code
compareTo()} and method to compare two keys. It does not call either
* {
@code
equals()} or {
@code
hashCode()}.
*
* This implementation uses a sorted array.
* The put and remove operations take Θ(n)
* time in the worst case.
* The contains, ceiling, floor,
* and rank operations take Θ(log n) time in the worst
* case.
* The size, is-empty, minimum, maximum,
* and select operations take Θ(1) time.
* Construction takes Θ(1) time.
*
* For alternative implementations of the symbol table API,
* see {
@link
ST}, {
@link
BST}, {
@link
SequentialSearchST}, {
@link
RedBlackBST},
* {
@link
SeparateChainingHashST}, and {
@link
LinearProbingHashST},
* For additional documentation,
* see Section 3.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*/
public
class
BinarySearchST
<
Key
extends
Comparable
<
Key
>
,
Value
>
{
private
static
final
int
INIT_CAPACITY
=
2
;
private
Key
[]
keys
;
private
Value
[]
vals
;
private
int
n
=
0
;
/**
* Initializes an empty symbol table.
*/
public
BinarySearchST
()
{
this
(
INIT_CAPACITY
);
}
/**
* Initializes an empty symbol table with the specified initial capacity.
*
@param
capacity the maximum capacity
*/
public
BinarySearchST
(
int
capacity
)
{
keys
=
(
Key
[])
new
Comparable
[
capacity
];
vals
=
(
Value
[])
new
Object
[
capacity
];
}
// resize the underlying arrays
private
void
resize
(
int
capacity
)
{
assert
capacity
>=
n
;
Key
[]
tempk
=
(
Key
[])
new
Comparable
[
capacity
];
Value
[]
tempv
=
(
Value
[])
new
Object
[
capacity
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
tempk
[
i
]
=
keys
[
i
];
tempv
[
i
]
=
vals
[
i
];
}
vals
=
tempv
;
keys
=
tempk
;
}
/**
* Returns the number of key-value pairs in this symbol table.
*
*
@return
the number of key-value pairs in this symbol table
*/
public
int
size
()
{
return
n
;
}
/**
* Returns true if this symbol table is empty.
*
*
@return
{
@code
true} if this symbol table is empty;
* {
@code
false} otherwise
*/
public
boolean
isEmpty
()
{
return
size
()
==
0
;
}
/**
* Does this symbol table contain the given key?
*
*
@param
key the key
*
@return
{
@code
true} if this symbol table contains {
@code
key} and
* {
@code
false} otherwise
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
boolean
contains
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
"argument to contains() is null"
);
return
get
(
key
)
!=
null
;
}
/**
* Returns the value associated with the given key in this symbol table.
*
*
@param
key the key
*
@return
the value associated with the given key if the key is in the symbol table
* and {
@code
null} if the key is not in the symbol table
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
Value
get
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
"argument to get() is null"
);
if
(
isEmpty
())
return
null
;
int
i
=
rank
(
key
);
if
(
i
<
n
&&
keys
[
i
].
compareTo
(
key
)
==
0
)
return
vals
[
i
];
return
null
;
}
/**
* Returns the number of keys in this symbol table strictly less than {
@code
key}.
*
*
@param
key the key
*
@return
the number of keys in the symbol table strictly less than {
@code
key}
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
int
rank
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
"argument to rank() is null"
);
int
lo
=
0
,
hi
=
n
-
1
;
while
(
lo
<=
hi
)
{
int
mid
=
lo
+
(
hi
-
lo
)
/
2
;
int
cmp
=
key
.
compareTo
(
keys
[
mid
]);
if
(
cmp
<
0
)
hi
=
mid
-
1
;
else
if
(
cmp
>
0
)
lo
=
mid
+
1
;
else
return
mid
;
}
return
lo
;
}
/**
* Inserts the specified key-value pair into the symbol table, overwriting the old
* value with the new value if the symbol table already contains the specified key.
* Deletes the specified key (and its associated value) from this symbol table
* if the specified value is {
@code
null}.
*
*
@param
key the key
*
@param
val the value
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
put
(
Key
key
,
Value
val
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“first argument to put() is null”
);
if
(
val
==
null
)
{
delete
(
key
);
return
;
}
int
i
=
rank
(
key
);
// key is already in table
if
(
i
<
n
&&
keys
[
i
].
compareTo
(
key
)
==
0
)
{
vals
[
i
]
=
val
;
return
;
}
// insert new key-value pair
if
(
n
==
keys
.
length
)
resize
(
2
*
keys
.
length
);
for
(
int
j
=
n
;
j
>
i
;
j
—
)
{
keys
[
j
]
=
keys
[
j
–
1
];
vals
[
j
]
=
vals
[
j
–
1
];
}
keys
[
i
]
=
key
;
vals
[
i
]
=
val
;
n
++
;
assert
check
();
}
/**
* Removes the specified key and associated value from this symbol table
* (if the key is in the symbol table).
*
*
@param
key the key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
delete
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to delete() is null”
);
if
(
isEmpty
())
return
;
// compute rank
int
i
=
rank
(
key
);
// key not in table
if
(
i
==
n
||
keys
[
i
].
compareTo
(
key
)
!=
0
)
{
return
;
}
for
(
int
j
=
i
;
j
<
n
-
1
;
j
++
)
{
keys
[
j
]
=
keys
[
j
+
1
];
vals
[
j
]
=
vals
[
j
+
1
];
}
n
--
;
keys
[
n
]
=
null
;
// to avoid loitering
vals
[
n
]
=
null
;
// resize if 1/4 full
if
(
n
>
0
&&
n
==
keys
.
length
/
4
)
resize
(
keys
.
length
/
2
);
assert
check
();
}
/**
* Removes the smallest key and associated value from this symbol table.
*
*
@throws
NoSuchElementException if the symbol table is empty
*/
public
void
deleteMin
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Symbol table underflow error”
);
delete
(
min
());
}
/**
* Removes the largest key and associated value from this symbol table.
*
*
@throws
NoSuchElementException if the symbol table is empty
*/
public
void
deleteMax
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Symbol table underflow error”
);
delete
(
max
());
}
/***************************************************************************
* Ordered symbol table methods.
***************************************************************************/
/**
* Returns the smallest key in this symbol table.
*
*
@return
the smallest key in this symbol table
*
@throws
NoSuchElementException if this symbol table is empty
*/
public
Key
min
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“called min() with empty symbol table”
);
return
keys
[
0
];
}
/**
* Returns the largest key in this symbol table.
*
*
@return
the largest key in this symbol table
*
@throws
NoSuchElementException if this symbol table is empty
*/
public
Key
max
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“called max() with empty symbol table”
);
return
keys
[
n
–
1
];
}
/**
* Return the kth smallest key in this symbol table.
*
*
@param
k the order statistic
*
@return
the {
@code
k}th smallest key in this symbol table
*
@throws
IllegalArgumentException unless {
@code
k} is between 0 and
* n–1
*/
public
Key
select
(
int
k
)
{
if
(
k
<
0
||
k
>=
size
())
{
throw
new
IllegalArgumentException
(
“called select() with invalid argument: ”
+
k
);
}
return
keys
[
k
];
}
/**
* Returns the largest key in this symbol table less than or equal to {
@code
key}.
*
*
@param
key the key
*
@return
the largest key in this symbol table less than or equal to {
@code
key}
*
@throws
NoSuchElementException if there is no such key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
Key
floor
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to floor() is null”
);
int
i
=
rank
(
key
);
if
(
i
<
n
&&
key
.
compareTo
(
keys
[
i
])
==
0
)
return
keys
[
i
];
if
(
i
==
0
)
return
null
;
else
return
keys
[
i
-
1
];
}
/**
* Returns the smallest key in this symbol table greater than or equal to {
@code
key}.
*
*
@param
key the key
*
@return
the smallest key in this symbol table greater than or equal to {
@code
key}
*
@throws
NoSuchElementException if there is no such key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
Key
ceiling
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
"argument to ceiling() is null"
);
int
i
=
rank
(
key
);
if
(
i
==
n
)
return
null
;
else
return
keys
[
i
];
}
/**
* Returns the number of keys in this symbol table in the specified range.
*
*
@param
lo minimum endpoint
*
@param
hi maximum endpoint
*
@return
the number of keys in this symbol table between {
@code
lo}
* (inclusive) and {
@code
hi} (inclusive)
*
@throws
IllegalArgumentException if either {
@code
lo} or {
@code
hi}
* is {
@code
null}
*/
public
int
size
(
Key
lo
,
Key
hi
)
{
if
(
lo
==
null
)
throw
new
IllegalArgumentException
(
"first argument to size() is null"
);
if
(
hi
==
null
)
throw
new
IllegalArgumentException
(
"second argument to size() is null"
);
if
(
lo
.
compareTo
(
hi
)
>
0
)
return
0
;
if
(
contains
(
hi
))
return
rank
(
hi
)
–
rank
(
lo
)
+
1
;
else
return
rank
(
hi
)
–
rank
(
lo
);
}
/**
* Returns all keys in this symbol table as an {
@code
Iterable}.
* To iterate over all of the keys in the symbol table named {
@code
st},
* use the foreach notation: {
@code
for (Key key : st.keys())}.
*
*
@return
all keys in this symbol table
*/
public
Iterable
<
Key
>
keys
()
{
return
keys
(
min
(),
max
());
}
/**
* Returns all keys in this symbol table in the given range,
* as an {
@code
Iterable}.
*
*
@param
lo minimum endpoint
*
@param
hi maximum endpoint
*
@return
all keys in this symbol table between {
@code
lo}
* (inclusive) and {
@code
hi} (inclusive)
*
@throws
IllegalArgumentException if either {
@code
lo} or {
@code
hi}
* is {
@code
null}
*/
public
Iterable
<
Key
>
keys
(
Key
lo
,
Key
hi
)
{
if
(
lo
==
null
)
throw
new
IllegalArgumentException
(
“first argument to keys() is null”
);
if
(
hi
==
null
)
throw
new
IllegalArgumentException
(
“second argument to keys() is null”
);
Queue
<
Key
>
queue
=
new
Queue
<
Key
>
();
if
(
lo
.
compareTo
(
hi
)
>
0
)
return
queue
;
for
(
int
i
=
rank
(
lo
);
i
<
rank
(
hi
);
i
++
)
queue
.
enqueue
(
keys
[
i
]);
if
(
contains
(
hi
))
queue
.
enqueue
(
keys
[
rank
(
hi
)]);
return
queue
;
}
/***************************************************************************
* Check internal invariants.
***************************************************************************/
private
boolean
check
()
{
return
isSorted
()
&&
rankCheck
();
}
// are the items in the array in ascending order?
private
boolean
isSorted
()
{
for
(
int
i
=
1
;
i
<
size
();
i
++
)
if
(
keys
[
i
].
compareTo
(
keys
[
i
-
1
])
<
0
)
return
false
;
return
true
;
}
// check that rank(select(i)) = i
private
boolean
rankCheck
()
{
for
(
int
i
=
0
;
i
<
size
();
i
++
)
if
(
i
!=
rank
(
select
(
i
)))
return
false
;
for
(
int
i
=
0
;
i
<
size
();
i
++
)
if
(
keys
[
i
].
compareTo
(
select
(
rank
(
keys
[
i
])))
!=
0
)
return
false
;
return
true
;
}
/**
* Unit tests the {
@code
BinarySearchST} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
BinarySearchST
<
String
,
Integer
>
st
=
new
BinarySearchST
<
String
,
Integer
>
();
for
(
int
i
=
0
;
!
StdIn
.
isEmpty
();
i
++
)
{
String
key
=
StdIn
.
readString
();
st
.
put
(
key
,
i
);
}
for
(
String
s
:
st
.
keys
())
StdOut
.
println
(
s
+
” ”
+
st
.
get
(
s
));
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/BinaryStdIn.java
edu/princeton/cs/algs4/BinaryStdIn.java
/******************************************************************************
* Compilation: javac BinaryStdIn.java
* Execution: java BinaryStdIn < input > output
* Dependencies: none
*
* Supports reading binary data from standard input.
*
* % java BinaryStdIn < input > output
* % diff input output
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
io
.
BufferedInputStream
;
import
java
.
io
.
IOException
;
import
java
.
util
.
NoSuchElementException
;
/**
* Binary standard input. This class provides methods for reading
* in bits from standard input, either one bit at a time (as a {
@code
boolean}),
* 8 bits at a time (as a {
@code
byte} or {
@code
char}),
* 16 bits at a time (as a {
@code
short}), 32 bits at a time
* (as an {
@code
int} or {
@code
float}), or 64 bits at a time (as a
* {
@code
double} or {
@code
long}).
*
* All primitive types are assumed to be represented using their
* standard Java representations, in big-endian (most significant
* byte first) order.
*
* The client should not intermix calls to {
@code
BinaryStdIn} with calls
* to {
@code
StdIn} or {
@code
System.in};
* otherwise unexpected behavior will result.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
BinaryStdIn
{
private
static
final
int
EOF
=
–
1
;
// end of file
private
static
BufferedInputStream
in
;
// input stream
private
static
int
buffer
;
// one character buffer
private
static
int
n
;
// number of bits left in buffer
private
static
boolean
isInitialized
;
// has BinaryStdIn been called for first time?
// don’t instantiate
private
BinaryStdIn
()
{
}
// fill buffer
private
static
void
initialize
()
{
in
=
new
BufferedInputStream
(
System
.
in
);
buffer
=
0
;
n
=
0
;
fillBuffer
();
isInitialized
=
true
;
}
private
static
void
fillBuffer
()
{
try
{
buffer
=
in
.
read
();
n
=
8
;
}
catch
(
IOException
e
)
{
System
.
out
.
println
(
“EOF”
);
buffer
=
EOF
;
n
=
–
1
;
}
}
/**
* Close this input stream and release any associated system resources.
*/
public
static
void
close
()
{
if
(
!
isInitialized
)
initialize
();
try
{
in
.
close
();
isInitialized
=
false
;
}
catch
(
IOException
ioe
)
{
throw
new
IllegalStateException
(
“Could not close BinaryStdIn”
,
ioe
);
}
}
/**
* Returns true if standard input is empty.
*
@return
true if and only if standard input is empty
*/
public
static
boolean
isEmpty
()
{
if
(
!
isInitialized
)
initialize
();
return
buffer
==
EOF
;
}
/**
* Reads the next bit of data from standard input and return as a boolean.
*
*
@return
the next bit of data from standard input as a {
@code
boolean}
*
@throws
NoSuchElementException if standard input is empty
*/
public
static
boolean
readBoolean
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Reading from empty input stream”
);
n
—
;
boolean
bit
=
((
buffer
>>
n
)
&
1
)
==
1
;
if
(
n
==
0
)
fillBuffer
();
return
bit
;
}
/**
* Reads the next 8 bits from standard input and return as an 8-bit char.
* Note that {
@code
char} is a 16-bit type;
* to read the next 16 bits as a char, use {
@code
readChar(16)}.
*
*
@return
the next 8 bits of data from standard input as a {
@code
char}
*
@throws
NoSuchElementException if there are fewer than 8 bits available on standard input
*/
public
static
char
readChar
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Reading from empty input stream”
);
// special case when aligned byte
if
(
n
==
8
)
{
int
x
=
buffer
;
fillBuffer
();
return
(
char
)
(
x
&
0xff
);
}
// combine last n bits of current buffer with first 8-n bits of new buffer
int
x
=
buffer
;
x
<<=
(
8
-
n
);
int
oldN
=
n
;
fillBuffer
();
if
(
isEmpty
())
throw
new
NoSuchElementException
(
"Reading from empty input stream"
);
n
=
oldN
;
x
|=
(
buffer
>>>
n
);
return
(
char
)
(
x
&
0xff
);
// the above code doesn’t quite work for the last character if n = 8
// because buffer will be -1, so there is a special case for aligned byte
}
/**
* Reads the next r bits from standard input and return as an r-bit character.
*
*
@param
r number of bits to read.
*
@return
the next r bits of data from standard input as a {
@code
char}
*
@throws
NoSuchElementException if there are fewer than {
@code
r} bits available on standard input
*
@throws
IllegalArgumentException unless {
@code
1 <= r <= 16}
*/
public
static
char
readChar
(
int
r
)
{
if
(
r
<
1
||
r
>
16
)
throw
new
IllegalArgumentException
(
“Illegal value of r = ”
+
r
);
// optimize r = 8 case
if
(
r
==
8
)
return
readChar
();
char
x
=
0
;
for
(
int
i
=
0
;
i
<
r
;
i
++
)
{
x
<<=
1
;
boolean
bit
=
readBoolean
();
if
(
bit
)
x
|=
1
;
}
return
x
;
}
/**
* Reads the remaining bytes of data from standard input and return as a string.
*
*
@return
the remaining bytes of data from standard input as a {
@code
String}
*
@throws
NoSuchElementException if standard input is empty or if the number of bits
* available on standard input is not a multiple of 8 (byte-aligned)
*/
public
static
String
readString
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
"Reading from empty input stream"
);
StringBuilder
sb
=
new
StringBuilder
();
while
(
!
isEmpty
())
{
char
c
=
readChar
();
sb
.
append
(
c
);
}
return
sb
.
toString
();
}
/**
* Reads the next 16 bits from standard input and return as a 16-bit short.
*
*
@return
the next 16 bits of data from standard input as a {
@code
short}
*
@throws
NoSuchElementException if there are fewer than 16 bits available on standard input
*/
public
static
short
readShort
()
{
short
x
=
0
;
for
(
int
i
=
0
;
i
<
2
;
i
++
)
{
char
c
=
readChar
();
x
<<=
8
;
x
|=
c
;
}
return
x
;
}
/**
* Reads the next 32 bits from standard input and return as a 32-bit int.
*
*
@return
the next 32 bits of data from standard input as a {
@code
int}
*
@throws
NoSuchElementException if there are fewer than 32 bits available on standard input
*/
public
static
int
readInt
()
{
int
x
=
0
;
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
char
c
=
readChar
();
x
<<=
8
;
x
|=
c
;
}
return
x
;
}
/**
* Reads the next r bits from standard input and return as an r-bit int.
*
*
@param
r number of bits to read.
*
@return
the next r bits of data from standard input as a {
@code
int}
*
@throws
NoSuchElementException if there are fewer than {
@code
r} bits available on standard input
*
@throws
IllegalArgumentException unless {
@code
1 <= r <= 32}
*/
public
static
int
readInt
(
int
r
)
{
if
(
r
<
1
||
r
>
32
)
throw
new
IllegalArgumentException
(
“Illegal value of r = ”
+
r
);
// optimize r = 32 case
if
(
r
==
32
)
return
readInt
();
int
x
=
0
;
for
(
int
i
=
0
;
i
<
r
;
i
++
)
{
x
<<=
1
;
boolean
bit
=
readBoolean
();
if
(
bit
)
x
|=
1
;
}
return
x
;
}
/**
* Reads the next 64 bits from standard input and return as a 64-bit long.
*
*
@return
the next 64 bits of data from standard input as a {
@code
long}
*
@throws
NoSuchElementException if there are fewer than 64 bits available on standard input
*/
public
static
long
readLong
()
{
long
x
=
0
;
for
(
int
i
=
0
;
i
<
8
;
i
++
)
{
char
c
=
readChar
();
x
<<=
8
;
x
|=
c
;
}
return
x
;
}
/**
* Reads the next 64 bits from standard input and return as a 64-bit double.
*
*
@return
the next 64 bits of data from standard input as a {
@code
double}
*
@throws
NoSuchElementException if there are fewer than 64 bits available on standard input
*/
public
static
double
readDouble
()
{
return
Double
.
longBitsToDouble
(
readLong
());
}
/**
* Reads the next 32 bits from standard input and return as a 32-bit float.
*
*
@return
the next 32 bits of data from standard input as a {
@code
float}
*
@throws
NoSuchElementException if there are fewer than 32 bits available on standard input
*/
public
static
float
readFloat
()
{
return
Float
.
intBitsToFloat
(
readInt
());
}
/**
* Reads the next 8 bits from standard input and return as an 8-bit byte.
*
*
@return
the next 8 bits of data from standard input as a {
@code
byte}
*
@throws
NoSuchElementException if there are fewer than 8 bits available on standard input
*/
public
static
byte
readByte
()
{
char
c
=
readChar
();
return
(
byte
)
(
c
&
0xff
);
}
/**
* Test client. Reads in a binary input file from standard input and writes
* it to standard output.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// read one 8-bit char at a time
while
(
!
BinaryStdIn
.
isEmpty
())
{
char
c
=
BinaryStdIn
.
readChar
();
BinaryStdOut
.
write
(
c
);
}
BinaryStdOut
.
flush
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/BinaryStdOut.java
edu/princeton/cs/algs4/BinaryStdOut.java
/******************************************************************************
* Compilation: javac BinaryStdOut.java
* Execution: java BinaryStdOut
* Dependencies: none
*
* Write binary data to standard output, either one 1-bit boolean,
* one 8-bit char, one 32-bit int, one 64-bit double, one 32-bit float,
* or one 64-bit long at a time.
*
* The bytes written are not aligned.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
io
.
BufferedOutputStream
;
import
java
.
io
.
IOException
;
/**
* Binary standard output. This class provides methods for converting
* primtive type variables ({
@code
boolean}, {
@code
byte}, {
@code
char},
* {
@code
int}, {
@code
long}, {
@code
float}, and {
@code
double})
* to sequences of bits and writing them to standard output.
* Uses big-endian (most-significant byte first).
*
* The client must {
@code
flush()} the output stream when finished writing bits.
*
* The client should not intermix calls to {
@code
BinaryStdOut} with calls
* to {
@code
StdOut} or {
@code
System.out}; otherwise unexpected behavior
* will result.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
BinaryStdOut
{
private
static
BufferedOutputStream
out
;
// output stream (standard output)
private
static
int
buffer
;
// 8-bit buffer of bits to write
private
static
int
n
;
// number of bits remaining in buffer
private
static
boolean
isInitialized
;
// has BinaryStdOut been called for first time?
// don’t instantiate
private
BinaryStdOut
()
{
}
// initialize BinaryStdOut
private
static
void
initialize
()
{
out
=
new
BufferedOutputStream
(
System
.
out
);
buffer
=
0
;
n
=
0
;
isInitialized
=
true
;
}
/**
* Writes the specified bit to standard output.
*/
private
static
void
writeBit
(
boolean
bit
)
{
if
(
!
isInitialized
)
initialize
();
// add bit to buffer
buffer
<<=
1
;
if
(
bit
)
buffer
|=
1
;
// if buffer is full (8 bits), write out as a single byte
n
++
;
if
(
n
==
8
)
clearBuffer
();
}
/**
* Writes the 8-bit byte to standard output.
*/
private
static
void
writeByte
(
int
x
)
{
if
(
!
isInitialized
)
initialize
();
assert
x
>=
0
&&
x
<
256
;
// optimized if byte-aligned
if
(
n
==
0
)
{
try
{
out
.
write
(
x
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
return
;
}
// otherwise write one bit at a time
for
(
int
i
=
0
;
i
<
8
;
i
++
)
{
boolean
bit
=
((
x
>>>
(
8
–
i
–
1
))
&
1
)
==
1
;
writeBit
(
bit
);
}
}
// write out any remaining bits in buffer to standard output, padding with 0s
private
static
void
clearBuffer
()
{
if
(
!
isInitialized
)
initialize
();
if
(
n
==
0
)
return
;
if
(
n
>
0
)
buffer
<<=
(
8
-
n
);
try
{
out
.
write
(
buffer
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
n
=
0
;
buffer
=
0
;
}
/**
* Flushes standard output, padding 0s if number of bits written so far
* is not a multiple of 8.
*/
public
static
void
flush
()
{
clearBuffer
();
try
{
out
.
flush
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
/**
* Flushes and closes standard output. Once standard output is closed, you can no
* longer write bits to it.
*/
public
static
void
close
()
{
flush
();
try
{
out
.
close
();
isInitialized
=
false
;
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
/**
* Writes the specified bit to standard output.
*
@param
x the {
@code
boolean} to write.
*/
public
static
void
write
(
boolean
x
)
{
writeBit
(
x
);
}
/**
* Writes the 8-bit byte to standard output.
*
@param
x the {
@code
byte} to write.
*/
public
static
void
write
(
byte
x
)
{
writeByte
(
x
&
0xff
);
}
/**
* Writes the 32-bit int to standard output.
*
@param
x the {
@code
int} to write.
*/
public
static
void
write
(
int
x
)
{
writeByte
((
x
>>>
24
)
&
0xff
);
writeByte
((
x
>>>
16
)
&
0xff
);
writeByte
((
x
>>>
8
)
&
0xff
);
writeByte
((
x
>>>
0
)
&
0xff
);
}
/**
* Writes the r-bit int to standard output.
*
@param
x the {
@code
int} to write.
*
@param
r the number of relevant bits in the char.
*
@throws
IllegalArgumentException if {
@code
r} is not between 1 and 32.
*
@throws
IllegalArgumentException if {
@code
x} is not between 0 and 2r – 1.
*/
public
static
void
write
(
int
x
,
int
r
)
{
if
(
r
==
32
)
{
write
(
x
);
return
;
}
if
(
r
<
1
||
r
>
32
)
throw
new
IllegalArgumentException
(
“Illegal value for r = ”
+
r
);
if
(
x
<
0
||
x
>=
(
1
<<
r
))
throw
new
IllegalArgumentException
(
"Illegal "
+
r
+
"-bit char = "
+
x
);
for
(
int
i
=
0
;
i
<
r
;
i
++
)
{
boolean
bit
=
((
x
>>>
(
r
–
i
–
1
))
&
1
)
==
1
;
writeBit
(
bit
);
}
}
/**
* Writes the 64-bit double to standard output.
*
@param
x the {
@code
double} to write.
*/
public
static
void
write
(
double
x
)
{
write
(
Double
.
doubleToRawLongBits
(
x
));
}
/**
* Writes the 64-bit long to standard output.
*
@param
x the {
@code
long} to write.
*/
public
static
void
write
(
long
x
)
{
writeByte
((
int
)
((
x
>>>
56
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
48
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
40
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
32
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
24
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
16
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
8
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
0
)
&
0xff
));
}
/**
* Writes the 32-bit float to standard output.
*
@param
x the {
@code
float} to write.
*/
public
static
void
write
(
float
x
)
{
write
(
Float
.
floatToRawIntBits
(
x
));
}
/**
* Writes the 16-bit int to standard output.
*
@param
x the {
@code
short} to write.
*/
public
static
void
write
(
short
x
)
{
writeByte
((
x
>>>
8
)
&
0xff
);
writeByte
((
x
>>>
0
)
&
0xff
);
}
/**
* Writes the 8-bit char to standard output.
*
@param
x the {
@code
char} to write.
*
@throws
IllegalArgumentException if {
@code
x} is not betwen 0 and 255.
*/
public
static
void
write
(
char
x
)
{
if
(
x
<
0
||
x
>=
256
)
throw
new
IllegalArgumentException
(
“Illegal 8-bit char = ”
+
x
);
writeByte
(
x
);
}
/**
* Writes the r-bit char to standard output.
*
@param
x the {
@code
char} to write.
*
@param
r the number of relevant bits in the char.
*
@throws
IllegalArgumentException if {
@code
r} is not between 1 and 16.
*
@throws
IllegalArgumentException if {
@code
x} is not between 0 and 2r – 1.
*/
public
static
void
write
(
char
x
,
int
r
)
{
if
(
r
==
8
)
{
write
(
x
);
return
;
}
if
(
r
<
1
||
r
>
16
)
throw
new
IllegalArgumentException
(
“Illegal value for r = ”
+
r
);
if
(
x
>=
(
1
<<
r
))
throw
new
IllegalArgumentException
(
"Illegal "
+
r
+
"-bit char = "
+
x
);
for
(
int
i
=
0
;
i
<
r
;
i
++
)
{
boolean
bit
=
((
x
>>>
(
r
–
i
–
1
))
&
1
)
==
1
;
writeBit
(
bit
);
}
}
/**
* Writes the string of 8-bit characters to standard output.
*
@param
s the {
@code
String} to write.
*
@throws
IllegalArgumentException if any character in the string is not
* between 0 and 255.
*/
public
static
void
write
(
String
s
)
{
for
(
int
i
=
0
;
i
<
s
.
length
();
i
++
)
write
(
s
.
charAt
(
i
));
}
/**
* Writes the string of r-bit characters to standard output.
*
@param
s the {
@code
String} to write.
*
@param
r the number of relevants bits in each character.
*
@throws
IllegalArgumentException if r is not between 1 and 16.
*
@throws
IllegalArgumentException if any character in the string is not
* between 0 and 2r – 1.
*/
public
static
void
write
(
String
s
,
int
r
)
{
for
(
int
i
=
0
;
i
<
s
.
length
();
i
++
)
write
(
s
.
charAt
(
i
),
r
);
}
/**
* Tests the methods in this class.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
m
=
Integer
.
parseInt
(
args
[
0
]);
// write n integers to binary standard output
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
BinaryStdOut
.
write
(
i
);
}
BinaryStdOut
.
flush
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/BinomialMinPQ.java
edu/princeton/cs/algs4/BinomialMinPQ.java
/******************************************************************************
* Compilation: javac BinomialMinPQ.java
* Execution:
*
* A binomial heap.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Iterator
;
import
java
.
util
.
Comparator
;
import
java
.
util
.
NoSuchElementException
;
/**
* The BinomialMinPQ class represents a priority queue of generic keys.
* It supports the usual insert and delete-the-minimum operations,
* along with the merging of two heaps together.
* It also supports methods for peeking at the minimum key,
* testing if the priority queue is empty, and iterating through
* the keys.
* It is possible to build the priority queue using a Comparator.
* If not, the natural order relation between the keys will be used.
*
* This implementation uses a binomial heap.
* The insert, delete-the-minimum, union, min-key
* and size operations take logarithmic time.
* The is-empty and constructor operations take constant time.
*
*
@author
Tristan Claverie
*/
public
class
BinomialMinPQ
<
Key
>
implements
Iterable
<
Key
>
{
private
Node
head
;
//head of the list of roots
private
final
Comparator
<
Key
>
comp
;
//Comparator over the keys
//Represents a Node of a Binomial Tree
private
class
Node
{
Key
key
;
//Key contained by the Node
int
order
;
//The order of the Binomial Tree rooted by this Node
Node
child
,
sibling
;
//child and sibling of this Node
}
/**
* Initializes an empty priority queue
* Worst case is O(1)
*/
public
BinomialMinPQ
()
{
comp
=
new
MyComparator
();
}
/**
* Initializes an empty priority queue using the given Comparator
* Worst case is O(1)
*
@param
C a comparator over the keys
*/
public
BinomialMinPQ
(
Comparator
<
Key
>
C
)
{
comp
=
C
;
}
/**
* Initializes a priority queue with given keys
* Worst case is O(n*log(n))
*
@param
a an array of keys
*/
public
BinomialMinPQ
(
Key
[]
a
)
{
comp
=
new
MyComparator
();
for
(
Key
k
:
a
)
insert
(
k
);
}
/**
* Initializes a priority queue with given keys using the given Comparator
* Worst case is O(n*log(n))
*
@param
C a comparator over the keys
*
@param
a an array of keys
*/
public
BinomialMinPQ
(
Comparator
<
Key
>
C
,
Key
[]
a
)
{
comp
=
C
;
for
(
Key
k
:
a
)
insert
(
k
);
}
/**
* Whether the priority queue is empty
* Worst case is O(1)
*
@return
true if the priority queue is empty, false if not
*/
public
boolean
isEmpty
()
{
return
head
==
null
;
}
/**
* Number of elements currently on the priority queue
* Worst case is O(log(n))
*
@throws
java.lang.ArithmeticException if there are more than 2^63-1 elements in the queue
*
@return
the number of elements on the priority queue
*/
public
int
size
()
{
int
result
=
0
,
tmp
;
for
(
Node
node
=
head
;
node
!=
null
;
node
=
node
.
sibling
)
{
if
(
node
.
order
>
30
)
{
throw
new
ArithmeticException
(
“The number of elements cannot be evaluated, but the priority queue is still valid.”
);
}
tmp
=
1
<<
node
.
order
;
result
|=
tmp
;
}
return
result
;
}
/**
* Puts a Key in the heap
* Worst case is O(log(n))
*
@param
key a Key
*/
public
void
insert
(
Key
key
)
{
Node
x
=
new
Node
();
x
.
key
=
key
;
x
.
order
=
0
;
BinomialMinPQ
<
Key
>
H
=
new
BinomialMinPQ
<
Key
>
();
//The Comparator oh the H heap is not used
H
.
head
=
x
;
this
.
head
=
this
.
union
(
H
).
head
;
}
/**
* Get the minimum key currently in the queue
* Worst case is O(log(n))
*
@throws
java.util.NoSuchElementException if the priority queue is empty
*
@return
the minimum key currently in the priority queue
*/
public
Key
minKey
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Priority queue is empty”
);
Node
min
=
head
;
Node
current
=
head
;
while
(
current
.
sibling
!=
null
)
{
min
=
(
greater
(
min
.
key
,
current
.
sibling
.
key
))
?
current
:
min
;
current
=
current
.
sibling
;
}
return
min
.
key
;
}
/**
* Deletes the minimum key
* Worst case is O(log(n))
*
@throws
java.util.NoSuchElementException if the priority queue is empty
*
@return
the minimum key
*/
public
Key
delMin
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Priority queue is empty”
);
Node
min
=
eraseMin
();
Node
x
=
(
min
.
child
==
null
)
?
min
:
min
.
child
;
if
(
min
.
child
!=
null
)
{
min
.
child
=
null
;
Node
prevx
=
null
,
nextx
=
x
.
sibling
;
while
(
nextx
!=
null
)
{
x
.
sibling
=
prevx
;
prevx
=
x
;
x
=
nextx
;
nextx
=
nextx
.
sibling
;
}
x
.
sibling
=
prevx
;
BinomialMinPQ
<
Key
>
H
=
new
BinomialMinPQ
<
Key
>
();
H
.
head
=
x
;
head
=
union
(
H
).
head
;
}
return
min
.
key
;
}
/**
* Merges two Binomial heaps together
* This operation is destructive
* Worst case is O(log(n))
*
@param
heap a Binomial Heap to be merged with the current heap
*
@throws
java.lang.IllegalArgumentException if the heap in parameter is null
*
@return
the union of two heaps
*/
public
BinomialMinPQ
<
Key
>
union
(
BinomialMinPQ
<
Key
>
heap
)
{
if
(
heap
==
null
)
throw
new
IllegalArgumentException
(
“Cannot merge a Binomial Heap with null”
);
this
.
head
=
merge
(
new
Node
(),
this
.
head
,
heap
.
head
).
sibling
;
Node
x
=
this
.
head
;
Node
prevx
=
null
,
nextx
=
x
.
sibling
;
while
(
nextx
!=
null
)
{
if
(
x
.
order
<
nextx
.
order
||
(
nextx
.
sibling
!=
null
&&
nextx
.
sibling
.
order
==
x
.
order
))
{
prevx
=
x
;
x
=
nextx
;
}
else
if
(
greater
(
nextx
.
key
,
x
.
key
))
{
x
.
sibling
=
nextx
.
sibling
;
link
(
nextx
,
x
);
}
else
{
if
(
prevx
==
null
)
{
this
.
head
=
nextx
;
}
else
{
prevx
.
sibling
=
nextx
;
}
link
(
x
,
nextx
);
x
=
nextx
;
}
nextx
=
x
.
sibling
;
}
return
this
;
}
/*************************************************
* General helper functions
************************************************/
//Compares two keys
private
boolean
greater
(
Key
n
,
Key
m
)
{
if
(
n
==
null
)
return
false
;
if
(
m
==
null
)
return
true
;
return
comp
.
compare
(
n
,
m
)
>
0
;
}
//Assuming root1 holds a greater key than root2, root2 becomes the new root
private
void
link
(
Node
root1
,
Node
root2
)
{
root1
.
sibling
=
root2
.
child
;
root2
.
child
=
root1
;
root2
.
order
++
;
}
//Deletes and return the node containing the minimum key
private
Node
eraseMin
()
{
Node
min
=
head
;
Node
previous
=
null
;
Node
current
=
head
;
while
(
current
.
sibling
!=
null
)
{
if
(
greater
(
min
.
key
,
current
.
sibling
.
key
))
{
previous
=
current
;
min
=
current
.
sibling
;
}
current
=
current
.
sibling
;
}
previous
.
sibling
=
min
.
sibling
;
if
(
min
==
head
)
head
=
min
.
sibling
;
return
min
;
}
/**************************************************
* Functions for inserting a key in the heap
*************************************************/
//Merges two root lists into one, there can be up to 2 Binomial Trees of same order
private
Node
merge
(
Node
h
,
Node
x
,
Node
y
)
{
if
(
x
==
null
&&
y
==
null
)
return
h
;
else
if
(
x
==
null
)
h
.
sibling
=
merge
(
y
,
null
,
y
.
sibling
);
else
if
(
y
==
null
)
h
.
sibling
=
merge
(
x
,
x
.
sibling
,
null
);
else
if
(
x
.
order
<
y
.
order
)
h
.
sibling
=
merge
(
x
,
x
.
sibling
,
y
);
else
h
.
sibling
=
merge
(
y
,
x
,
y
.
sibling
);
return
h
;
}
/******************************************************************
* Iterator
*****************************************************************/
/**
* Gets an Iterator over the keys in the priority queue in ascending order
* The Iterator does not implement the remove() method
* iterator() : Worst case is O(n)
* next() : Worst case is O(log(n))
* hasNext() : Worst case is O(1)
*
@return
an Iterator over the keys in the priority queue in ascending order
*/
public
Iterator
<
Key
>
iterator
()
{
return
new
MyIterator
();
}
private
class
MyIterator
implements
Iterator
<
Key
>
{
BinomialMinPQ
<
Key
>
data
;
//Constructor clones recursively the elements in the queue
//It takes linear time
public
MyIterator
()
{
data
=
new
BinomialMinPQ
<
Key
>
(
comp
);
data
.
head
=
clone
(
head
,
null
);
}
private
Node
clone
(
Node
x
,
Node
parent
)
{
if
(
x
==
null
)
return
null
;
Node
node
=
new
Node
();
node
.
key
=
x
.
key
;
node
.
sibling
=
clone
(
x
.
sibling
,
parent
);
node
.
child
=
clone
(
x
.
child
,
node
);
return
node
;
}
public
boolean
hasNext
()
{
return
!
data
.
isEmpty
();
}
public
Key
next
()
{
if
(
!
hasNext
())
throw
new
NoSuchElementException
();
return
data
.
delMin
();
}
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
}
/***************************
* Comparator
**************************/
//default Comparator
private
class
MyComparator
implements
Comparator
<
Key
>
{
@
Override
public
int
compare
(
Key
key1
,
Key
key2
)
{
return
((
Comparable
<
Key
>
)
key1
).
compareTo
(
key2
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Bipartite.java
edu/princeton/cs/algs4/Bipartite.java
/******************************************************************************
* Compilation: javac Bipartite.java
* Execution: java Bipartite V E F
* Dependencies: Graph.java
* Data files: https://algs4.cs.princeton.edu/41graph/tinyG.txt
* https://algs4.cs.princeton.edu/41graph/mediumG.txt
* https://algs4.cs.princeton.edu/41graph/largeG.txt
*
* Given a graph, find either (i) a bipartition or (ii) an odd-length cycle.
* Runs in O(E + V) time.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Bipartite} class represents a data type for
* determining whether an undirected graph is bipartite or whether
* it has an odd-length cycle.
* A graph is bipartite if and only if it has no odd-length cycle.
* The isBipartite operation determines whether the graph is
* bipartite. If so, the color operation determines a
* bipartition; if not, the oddCycle operation determines a
* cycle with an odd number of edges.
*
* This implementation uses depth-first search.
* The constructor takes Θ(V + E) time in
* the worst case, where V is the number of vertices and E
* is the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the graph).
* See {
@link
BipartiteX} for a nonrecursive version that uses breadth-first
* search.
*
* For additional documentation, see Section 4.1
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Bipartite
{
private
boolean
isBipartite
;
// is the graph bipartite?
private
boolean
[]
color
;
// color[v] gives vertices on one side of bipartition
private
boolean
[]
marked
;
// marked[v] = true iff v has been visited in DFS
private
int
[]
edgeTo
;
// edgeTo[v] = last edge on path to v
private
Stack
<
Integer
>
cycle
;
// odd-length cycle
/**
* Determines whether an undirected graph is bipartite and finds either a
* bipartition or an odd-length cycle.
*
*
@param
G the graph
*/
public
Bipartite
(
Graph
G
)
{
isBipartite
=
true
;
color
=
new
boolean
[
G
.
V
()];
marked
=
new
boolean
[
G
.
V
()];
edgeTo
=
new
int
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
!
marked
[
v
])
{
dfs
(
G
,
v
);
}
}
assert
check
(
G
);
}
private
void
dfs
(
Graph
G
,
int
v
)
{
marked
[
v
]
=
true
;
for
(
int
w
:
G
.
adj
(
v
))
{
// short circuit if odd-length cycle found
if
(
cycle
!=
null
)
return
;
// found uncolored vertex, so recur
if
(
!
marked
[
w
])
{
edgeTo
[
w
]
=
v
;
color
[
w
]
=
!
color
[
v
];
dfs
(
G
,
w
);
}
// if v-w create an odd-length cycle, find it
else
if
(
color
[
w
]
==
color
[
v
])
{
isBipartite
=
false
;
cycle
=
new
Stack
<
Integer
>
();
cycle
.
push
(
w
);
// don’t need this unless you want to include start vertex twice
for
(
int
x
=
v
;
x
!=
w
;
x
=
edgeTo
[
x
])
{
cycle
.
push
(
x
);
}
cycle
.
push
(
w
);
}
}
}
/**
* Returns true if the graph is bipartite.
*
*
@return
{
@code
true} if the graph is bipartite; {
@code
false} otherwise
*/
public
boolean
isBipartite
()
{
return
isBipartite
;
}
/**
* Returns the side of the bipartite that vertex {
@code
v} is on.
*
*
@param
v the vertex
*
@return
the side of the bipartition that vertex {
@code
v} is on; two vertices
* are in the same side of the bipartition if and only if they have the
* same color
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*
@throws
UnsupportedOperationException if this method is called when the graph
* is not bipartite
*/
public
boolean
color
(
int
v
)
{
validateVertex
(
v
);
if
(
!
isBipartite
)
throw
new
UnsupportedOperationException
(
"graph is not bipartite"
);
return
color
[
v
];
}
/**
* Returns an odd-length cycle if the graph is not bipartite, and
* {
@code
null} otherwise.
*
*
@return
an odd-length cycle if the graph is not bipartite
* (and hence has an odd-length cycle), and {
@code
null}
* otherwise
*/
public
Iterable
<
Integer
>
oddCycle
()
{
return
cycle
;
}
private
boolean
check
(
Graph
G
)
{
// graph is bipartite
if
(
isBipartite
)
{
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
color
[
v
]
==
color
[
w
])
{
System
.
err
.
printf
(
"edge %d-%d with %d and %d in same side of bipartition\n"
,
v
,
w
,
v
,
w
);
return
false
;
}
}
}
}
// graph has an odd-length cycle
else
{
// verify cycle
int
first
=
-
1
,
last
=
-
1
;
for
(
int
v
:
oddCycle
())
{
if
(
first
==
-
1
)
first
=
v
;
last
=
v
;
}
if
(
first
!=
last
)
{
System
.
err
.
printf
(
"cycle begins with %d and ends with %d\n"
,
first
,
last
);
return
false
;
}
}
return
true
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
marked
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
Bipartite} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
V1
=
Integer
.
parseInt
(
args
[
0
]);
int
V2
=
Integer
.
parseInt
(
args
[
1
]);
int
E
=
Integer
.
parseInt
(
args
[
2
]);
int
F
=
Integer
.
parseInt
(
args
[
3
]);
// create random bipartite graph with V1 vertices on left side,
// V2 vertices on right side, and E edges; then add F random edges
Graph
G
=
GraphGenerator
.
bipartite
(
V1
,
V2
,
E
);
for
(
int
i
=
0
;
i
<
F
;
i
++
)
{
int
v
=
StdRandom
.
uniform
(
V1
+
V2
);
int
w
=
StdRandom
.
uniform
(
V1
+
V2
);
G
.
addEdge
(
v
,
w
);
}
StdOut
.
println
(
G
);
Bipartite
b
=
new
Bipartite
(
G
);
if
(
b
.
isBipartite
())
{
StdOut
.
println
(
"Graph is bipartite"
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
StdOut
.
println
(
v
+
": "
+
b
.
color
(
v
));
}
}
else
{
StdOut
.
print
(
"Graph has an odd-length cycle: "
);
for
(
int
x
:
b
.
oddCycle
())
{
StdOut
.
print
(
x
+
" "
);
}
StdOut
.
println
();
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/BipartiteMatching.java
edu/princeton/cs/algs4/BipartiteMatching.java
/******************************************************************************
* Compilation: javac BipartiteMatching.java
* Execution: java BipartiteMatching V1 V2 E
* Dependencies: BipartiteX.java
*
* Find a maximum cardinality matching (and minimum cardinality vertex cover)
* in a bipartite graph using the alternating path algorithm.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
BipartiteMatching} class represents a data type for computing a
* maximum (cardinality) matching and a
* minimum (cardinality) vertex cover in a bipartite graph.
* A bipartite graph in a graph whose vertices can be partitioned
* into two disjoint sets such that every edge has one endpoint in either set.
* A matching in a graph is a subset of its edges with no common
* vertices. A maximum matching is a matching with the maximum number
* of edges.
* A perfect matching is a matching which matches all vertices in the graph.
* A vertex cover in a graph is a subset of its vertices such that
* every edge is incident to at least one vertex. A minimum vertex cover
* is a vertex cover with the minimum number of vertices.
* By Konig’s theorem, in any biparite
* graph, the maximum number of edges in matching equals the minimum number
* of vertices in a vertex cover.
* The maximum matching problem in nonbipartite graphs is
* also important, but all known algorithms for this more general problem
* are substantially more complicated.
*
* This implementation uses the alternating-path algorithm.
* It is equivalent to reducing to the maximum-flow problem and running
* the augmenting-path algorithm on the resulting flow network, but it
* does so with less overhead.
* The constructor takes O((E + V) V)
* time, where E is the number of edges and V is the
* number of vertices in the graph.
* It uses Θ(V) extra space (not including the graph).
*
* See also {
@link
HopcroftKarp}, which solves the problem in
* O(E sqrt(V)) using the Hopcroft-Karp
* algorithm and
* which solves the problem in O((E + V) V)
* time via a reduction to maxflow.
*
* For additional documentation, see
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
BipartiteMatching
{
private
static
final
int
UNMATCHED
=
–
1
;
private
final
int
V
;
// number of vertices in the graph
private
BipartiteX
bipartition
;
// the bipartition
private
int
cardinality
;
// cardinality of current matching
private
int
[]
mate
;
// mate[v] = w if v-w is an edge in current matching
// = -1 if v is not in current matching
private
boolean
[]
inMinVertexCover
;
// inMinVertexCover[v] = true iff v is in min vertex cover
private
boolean
[]
marked
;
// marked[v] = true iff v is reachable via alternating path
private
int
[]
edgeTo
;
// edgeTo[v] = last edge on alternating path to v
/**
* Determines a maximum matching (and a minimum vertex cover)
* in a bipartite graph.
*
*
@param
G the bipartite graph
*
@throws
IllegalArgumentException if {
@code
G} is not bipartite
*/
public
BipartiteMatching
(
Graph
G
)
{
bipartition
=
new
BipartiteX
(
G
);
if
(
!
bipartition
.
isBipartite
())
{
throw
new
IllegalArgumentException
(
“graph is not bipartite”
);
}
this
.
V
=
G
.
V
();
// initialize empty matching
mate
=
new
int
[
V
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
mate
[
v
]
=
UNMATCHED
;
// alternating path algorithm
while
(
hasAugmentingPath
(
G
))
{
// find one endpoint t in alternating path
int
t
=
-
1
;
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
!
isMatched
(
v
)
&&
edgeTo
[
v
]
!=
-
1
)
{
t
=
v
;
break
;
}
}
// update the matching according to alternating path in edgeTo[] array
for
(
int
v
=
t
;
v
!=
-
1
;
v
=
edgeTo
[
edgeTo
[
v
]])
{
int
w
=
edgeTo
[
v
];
mate
[
v
]
=
w
;
mate
[
w
]
=
v
;
}
cardinality
++
;
}
// find min vertex cover from marked[] array
inMinVertexCover
=
new
boolean
[
V
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
if
(
bipartition
.
color
(
v
)
&&
!
marked
[
v
])
inMinVertexCover
[
v
]
=
true
;
if
(
!
bipartition
.
color
(
v
)
&&
marked
[
v
])
inMinVertexCover
[
v
]
=
true
;
}
assert
certifySolution
(
G
);
}
/*
* is there an augmenting path?
* - if so, upon termination adj[] contains the level graph;
* - if not, upon termination marked[] specifies those vertices reachable via an alternating
* path from one side of the bipartition
*
* an alternating path is a path whose edges belong alternately to the matching and not
* to the matching
*
* an augmenting path is an alternating path that starts and ends at unmatched vertices
*
* this implementation finds a shortest augmenting path (fewest number of edges), though there
* is no particular advantage to do so here
*/
private
boolean
hasAugmentingPath
(
Graph
G
)
{
marked
=
new
boolean
[
V
];
edgeTo
=
new
int
[
V
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
edgeTo
[
v
]
=
-
1
;
// breadth-first search (starting from all unmatched vertices on one side of bipartition)
Queue
<
Integer
>
queue
=
new
Queue
<
Integer
>
();
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
if
(
bipartition
.
color
(
v
)
&&
!
isMatched
(
v
))
{
queue
.
enqueue
(
v
);
marked
[
v
]
=
true
;
}
}
// run BFS, stopping as soon as an alternating path is found
while
(
!
queue
.
isEmpty
())
{
int
v
=
queue
.
dequeue
();
for
(
int
w
:
G
.
adj
(
v
))
{
// either (1) forward edge not in matching or (2) backward edge in matching
if
(
isResidualGraphEdge
(
v
,
w
)
&&
!
marked
[
w
])
{
edgeTo
[
w
]
=
v
;
marked
[
w
]
=
true
;
if
(
!
isMatched
(
w
))
return
true
;
queue
.
enqueue
(
w
);
}
}
}
return
false
;
}
// is the edge v-w a forward edge not in the matching or a reverse edge in the matching?
private
boolean
isResidualGraphEdge
(
int
v
,
int
w
)
{
if
((
mate
[
v
]
!=
w
)
&&
bipartition
.
color
(
v
))
return
true
;
if
((
mate
[
v
]
==
w
)
&&
!
bipartition
.
color
(
v
))
return
true
;
return
false
;
}
/**
* Returns the vertex to which the specified vertex is matched in
* the maximum matching computed by the algorithm.
*
*
@param
v the vertex
*
@return
the vertex to which vertex {
@code
v} is matched in the
* maximum matching; {
@code
-1} if the vertex is not matched
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*
*/
public
int
mate
(
int
v
)
{
validate
(
v
);
return
mate
[
v
];
}
/**
* Returns true if the specified vertex is matched in the maximum matching
* computed by the algorithm.
*
*
@param
v the vertex
*
@return
{
@code
true} if vertex {
@code
v} is matched in maximum matching;
* {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*
*/
public
boolean
isMatched
(
int
v
)
{
validate
(
v
);
return
mate
[
v
]
!=
UNMATCHED
;
}
/**
* Returns the number of edges in a maximum matching.
*
*
@return
the number of edges in a maximum matching
*/
public
int
size
()
{
return
cardinality
;
}
/**
* Returns true if the graph contains a perfect matching.
* That is, the number of edges in a maximum matching is equal to one half
* of the number of vertices in the graph (so that every vertex is matched).
*
*
@return
{
@code
true} if the graph contains a perfect matching;
* {
@code
false} otherwise
*/
public
boolean
isPerfect
()
{
return
cardinality
*
2
==
V
;
}
/**
* Returns true if the specified vertex is in the minimum vertex cover
* computed by the algorithm.
*
*
@param
v the vertex
*
@return
{
@code
true} if vertex {
@code
v} is in the minimum vertex cover;
* {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
boolean
inMinVertexCover
(
int
v
)
{
validate
(
v
);
return
inMinVertexCover
[
v
];
}
private
void
validate
(
int
v
)
{
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**************************************************************************
*
* The code below is solely for testing correctness of the data type.
*
**************************************************************************/
// check that mate[] and inVertexCover[] define a max matching and min vertex cover, respectively
private
boolean
certifySolution
(
Graph
G
)
{
// check that mate(v) = w iff mate(w) = v
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
if
(
mate
(
v
)
==
-
1
)
continue
;
if
(
mate
(
mate
(
v
))
!=
v
)
return
false
;
}
// check that size() is consistent with mate()
int
matchedVertices
=
0
;
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
if
(
mate
(
v
)
!=
-
1
)
matchedVertices
++
;
}
if
(
2
*
size
()
!=
matchedVertices
)
return
false
;
// check that size() is consistent with minVertexCover()
int
sizeOfMinVertexCover
=
0
;
for
(
int
v
=
0
;
v
<
V
;
v
++
)
if
(
inMinVertexCover
(
v
))
sizeOfMinVertexCover
++
;
if
(
size
()
!=
sizeOfMinVertexCover
)
return
false
;
// check that mate() uses each vertex at most once
boolean
[]
isMatched
=
new
boolean
[
V
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
int
w
=
mate
[
v
];
if
(
w
==
-
1
)
continue
;
if
(
v
==
w
)
return
false
;
if
(
v
>=
w
)
continue
;
if
(
isMatched
[
v
]
||
isMatched
[
w
])
return
false
;
isMatched
[
v
]
=
true
;
isMatched
[
w
]
=
true
;
}
// check that mate() uses only edges that appear in the graph
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
if
(
mate
(
v
)
==
-
1
)
continue
;
boolean
isEdge
=
false
;
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
mate
(
v
)
==
w
)
isEdge
=
true
;
}
if
(
!
isEdge
)
return
false
;
}
// check that inMinVertexCover() is a vertex cover
for
(
int
v
=
0
;
v
<
V
;
v
++
)
for
(
int
w
:
G
.
adj
(
v
))
if
(
!
inMinVertexCover
(
v
)
&&
!
inMinVertexCover
(
w
))
return
false
;
return
true
;
}
/**
* Unit tests the {
@code
HopcroftKarp} data type.
* Takes three command-line arguments {
@code
V1}, {
@code
V2}, and {
@code
E};
* creates a random bipartite graph with {
@code
V1} + {
@code
V2} vertices
* and {
@code
E} edges; computes a maximum matching and minimum vertex cover;
* and prints the results.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
V1
=
Integer
.
parseInt
(
args
[
0
]);
int
V2
=
Integer
.
parseInt
(
args
[
1
]);
int
E
=
Integer
.
parseInt
(
args
[
2
]);
Graph
G
=
GraphGenerator
.
bipartite
(
V1
,
V2
,
E
);
if
(
G
.
V
()
<
1000
)
StdOut
.
println
(
G
);
BipartiteMatching
matching
=
new
BipartiteMatching
(
G
);
// print maximum matching
StdOut
.
printf
(
"Number of edges in max matching = %d\n"
,
matching
.
size
());
StdOut
.
printf
(
"Number of vertices in min vertex cover = %d\n"
,
matching
.
size
());
StdOut
.
printf
(
"Graph has a perfect matching = %b\n"
,
matching
.
isPerfect
());
StdOut
.
println
();
if
(
G
.
V
()
>=
1000
)
return
;
StdOut
.
print
(
“Max matching: ”
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
int
w
=
matching
.
mate
(
v
);
if
(
matching
.
isMatched
(
v
)
&&
v
<
w
)
// print each edge only once
StdOut
.
print
(
v
+
"-"
+
w
+
" "
);
}
StdOut
.
println
();
// print minimum vertex cover
StdOut
.
print
(
"Min vertex cover: "
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
matching
.
inMinVertexCover
(
v
))
StdOut
.
print
(
v
+
" "
);
StdOut
.
println
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/BipartiteX.java
edu/princeton/cs/algs4/BipartiteX.java
/******************************************************************************
* Compilation: javac BipartiteX.java
* Execution: java Bipartite V E F
* Dependencies: Graph.java
*
* Given a graph, find either (i) a bipartition or (ii) an odd-length cycle.
* Runs in O(E + V) time.
*
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
BipartiteX} class represents a data type for
* determining whether an undirected graph is bipartite or whether
* it has an odd-length cycle.
* A graph is bipartite if and only if it has no odd-length cycle.
* The isBipartite operation determines whether the graph is
* bipartite. If so, the color operation determines a
* bipartition; if not, the oddCycle operation determines a
* cycle with an odd number of edges.
*
* This implementation uses breadth-first search and is nonrecursive.
* The constructor takes Θ(V + E) time in
* in the worst case, where V is the number of vertices
* and E is the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the graph).
* See {
@link
Bipartite} for a recursive version that uses depth-first search.
*
* For additional documentation,
* see Section 4.1
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
BipartiteX
{
private
static
final
boolean
WHITE
=
false
;
private
static
final
boolean
BLACK
=
true
;
private
boolean
isBipartite
;
// is the graph bipartite?
private
boolean
[]
color
;
// color[v] gives vertices on one side of bipartition
private
boolean
[]
marked
;
// marked[v] = true iff v has been visited in DFS
private
int
[]
edgeTo
;
// edgeTo[v] = last edge on path to v
private
Queue
<
Integer
>
cycle
;
// odd-length cycle
/**
* Determines whether an undirected graph is bipartite and finds either a
* bipartition or an odd-length cycle.
*
*
@param
G the graph
*/
public
BipartiteX
(
Graph
G
)
{
isBipartite
=
true
;
color
=
new
boolean
[
G
.
V
()];
marked
=
new
boolean
[
G
.
V
()];
edgeTo
=
new
int
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
()
&&
isBipartite
;
v
++
)
{
if
(
!
marked
[
v
])
{
bfs
(
G
,
v
);
}
}
assert
check
(
G
);
}
private
void
bfs
(
Graph
G
,
int
s
)
{
Queue
<
Integer
>
q
=
new
Queue
<
Integer
>
();
color
[
s
]
=
WHITE
;
marked
[
s
]
=
true
;
q
.
enqueue
(
s
);
while
(
!
q
.
isEmpty
())
{
int
v
=
q
.
dequeue
();
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
!
marked
[
w
])
{
marked
[
w
]
=
true
;
edgeTo
[
w
]
=
v
;
color
[
w
]
=
!
color
[
v
];
q
.
enqueue
(
w
);
}
else
if
(
color
[
w
]
==
color
[
v
])
{
isBipartite
=
false
;
// to form odd cycle, consider s-v path and s-w path
// and let x be closest node to v and w common to two paths
// then (w-x path) + (x-v path) + (edge v-w) is an odd-length cycle
// Note: distTo[v] == distTo[w];
cycle
=
new
Queue
<
Integer
>
();
Stack
<
Integer
>
stack
=
new
Stack
<
Integer
>
();
int
x
=
v
,
y
=
w
;
while
(
x
!=
y
)
{
stack
.
push
(
x
);
cycle
.
enqueue
(
y
);
x
=
edgeTo
[
x
];
y
=
edgeTo
[
y
];
}
stack
.
push
(
x
);
while
(
!
stack
.
isEmpty
())
cycle
.
enqueue
(
stack
.
pop
());
cycle
.
enqueue
(
w
);
return
;
}
}
}
}
/**
* Returns true if the graph is bipartite.
*
*
@return
{
@code
true} if the graph is bipartite; {
@code
false} otherwise
*/
public
boolean
isBipartite
()
{
return
isBipartite
;
}
/**
* Returns the side of the bipartite that vertex {
@code
v} is on.
*
*
@param
v the vertex
*
@return
the side of the bipartition that vertex {
@code
v} is on; two vertices
* are in the same side of the bipartition if and only if they have the
* same color
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*
@throws
UnsupportedOperationException if this method is called when the graph
* is not bipartite
*/
public
boolean
color
(
int
v
)
{
validateVertex
(
v
);
if
(
!
isBipartite
)
throw
new
UnsupportedOperationException
(
"Graph is not bipartite"
);
return
color
[
v
];
}
/**
* Returns an odd-length cycle if the graph is not bipartite, and
* {
@code
null} otherwise.
*
*
@return
an odd-length cycle if the graph is not bipartite
* (and hence has an odd-length cycle), and {
@code
null}
* otherwise
*/
public
Iterable
<
Integer
>
oddCycle
()
{
return
cycle
;
}
private
boolean
check
(
Graph
G
)
{
// graph is bipartite
if
(
isBipartite
)
{
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
color
[
v
]
==
color
[
w
])
{
System
.
err
.
printf
(
"edge %d-%d with %d and %d in same side of bipartition\n"
,
v
,
w
,
v
,
w
);
return
false
;
}
}
}
}
// graph has an odd-length cycle
else
{
// verify cycle
int
first
=
-
1
,
last
=
-
1
;
for
(
int
v
:
oddCycle
())
{
if
(
first
==
-
1
)
first
=
v
;
last
=
v
;
}
if
(
first
!=
last
)
{
System
.
err
.
printf
(
"cycle begins with %d and ends with %d\n"
,
first
,
last
);
return
false
;
}
}
return
true
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
marked
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
BipartiteX} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
V1
=
Integer
.
parseInt
(
args
[
0
]);
int
V2
=
Integer
.
parseInt
(
args
[
1
]);
int
E
=
Integer
.
parseInt
(
args
[
2
]);
int
F
=
Integer
.
parseInt
(
args
[
3
]);
// create random bipartite graph with V1 vertices on left side,
// V2 vertices on right side, and E edges; then add F random edges
Graph
G
=
GraphGenerator
.
bipartite
(
V1
,
V2
,
E
);
for
(
int
i
=
0
;
i
<
F
;
i
++
)
{
int
v
=
StdRandom
.
uniform
(
V1
+
V2
);
int
w
=
StdRandom
.
uniform
(
V1
+
V2
);
G
.
addEdge
(
v
,
w
);
}
StdOut
.
println
(
G
);
BipartiteX
b
=
new
BipartiteX
(
G
);
if
(
b
.
isBipartite
())
{
StdOut
.
println
(
"Graph is bipartite"
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
StdOut
.
println
(
v
+
": "
+
b
.
color
(
v
));
}
}
else
{
StdOut
.
print
(
"Graph has an odd-length cycle: "
);
for
(
int
x
:
b
.
oddCycle
())
{
StdOut
.
print
(
x
+
" "
);
}
StdOut
.
println
();
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/BlackFilter.java
edu/princeton/cs/algs4/BlackFilter.java
/******************************************************************************
* Compilation: javac BlackFilter.java
* Execution: java BlackFilter blacklist.txt < input.txt
* Dependencies: SET In.java StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/35applications/tinyTale.txt
* https://algs4.cs.princeton.edu/35applications/list.txt
*
* Read in a blacklist of words from a file. Then read in a list of
* words from standard input and print out all those words that
* are not in the first file.
*
* % more tinyTale.txt
* it was the best of times it was the worst of times
* it was the age of wisdom it was the age of foolishness
* it was the epoch of belief it was the epoch of incredulity
* it was the season of light it was the season of darkness
* it was the spring of hope it was the winter of despair
*
* % more list.txt
* was it the of
*
* % java BlackFilter list.txt < tinyTale.txt
* best times worst times
* age wisdom age foolishness
* epoch belief epoch incredulity
* season light season darkness
* spring hope winter despair
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
BlackFilter} class provides a client for reading in a blacklist
* of words from a file; then, reading in a sequence of words from standard input,
* printing out each word that does not appear in the file.
* It is useful as a test client for various symbol table implementations.
*
* For additional documentation, see Section 3.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
BlackFilter
{
// Do not instantiate.
private
BlackFilter
()
{
}
public
static
void
main
(
String
[]
args
)
{
SET
<
String
>
set
=
new
SET
<
String
>
();
// read in strings and add to set
In
in
=
new
In
(
args
[
0
]);
while
(
!
in
.
isEmpty
())
{
String
word
=
in
.
readString
();
set
.
add
(
word
);
}
// read in string from standard input, printing out all exceptions
while
(
!
StdIn
.
isEmpty
())
{
String
word
=
StdIn
.
readString
();
if
(
!
set
.
contains
(
word
))
StdOut
.
println
(
word
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/BoruvkaMST.java
edu/princeton/cs/algs4/BoruvkaMST.java
/******************************************************************************
* Compilation: javac BoruvkaMST.java
* Execution: java BoruvkaMST filename.txt
* Dependencies: EdgeWeightedGraph.java Edge.java Bag.java
* UF.java In.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/43mst/tinyEWG.txt
* https://algs4.cs.princeton.edu/43mst/mediumEWG.txt
* https://algs4.cs.princeton.edu/43mst/largeEWG.txt
*
* Compute a minimum spanning forest using Boruvka’s algorithm.
*
* % java BoruvkaMST tinyEWG.txt
* 0-2 0.26000
* 6-2 0.40000
* 5-7 0.28000
* 4-5 0.35000
* 2-3 0.17000
* 1-7 0.19000
* 0-7 0.16000
* 1.81000
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
BoruvkaMST} class represents a data type for computing a
* minimum spanning tree in an edge-weighted graph.
* The edge weights can be positive, zero, or negative and need not
* be distinct. If the graph is not connected, it computes a minimum
* spanning forest, which is the union of minimum spanning trees
* in each connected component. The {
@code
weight()} method returns the
* weight of a minimum spanning tree and the {
@code
edges()} method
* returns its edges.
*
* This implementation uses Boruvka’s algorithm and the union-find
* data type.
* The constructor takes Θ(E log V) time in
* the worst case, where V is the number of vertices and
* E is the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the
* edge-weighted graph).
*
* For additional documentation,
* see Section 4.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
* For alternate implementations, see {
@link
LazyPrimMST}, {
@link
PrimMST},
* and {
@link
KruskalMST}.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
BoruvkaMST
{
private
static
final
double
FLOATING_POINT_EPSILON
=
1E-12
;
private
Bag
<
Edge
>
mst
=
new
Bag
<
Edge
>
();
// edges in MST
private
double
weight
;
// weight of MST
/**
* Compute a minimum spanning tree (or forest) of an edge-weighted graph.
*
@param
G the edge-weighted graph
*/
public
BoruvkaMST
(
EdgeWeightedGraph
G
)
{
UF uf
=
new
UF
(
G
.
V
());
// repeat at most log V times or until we have V-1 edges
for
(
int
t
=
1
;
t
<
G
.
V
()
&&
mst
.
size
()
<
G
.
V
()
-
1
;
t
=
t
+
t
)
{
// foreach tree in forest, find closest edge
// if edge weights are equal, ties are broken in favor of first edge in G.edges()
Edge
[]
closest
=
new
Edge
[
G
.
V
()];
for
(
Edge
e
:
G
.
edges
())
{
int
v
=
e
.
either
(),
w
=
e
.
other
(
v
);
int
i
=
uf
.
find
(
v
),
j
=
uf
.
find
(
w
);
if
(
i
==
j
)
continue
;
// same tree
if
(
closest
[
i
]
==
null
||
less
(
e
,
closest
[
i
]))
closest
[
i
]
=
e
;
if
(
closest
[
j
]
==
null
||
less
(
e
,
closest
[
j
]))
closest
[
j
]
=
e
;
}
// add newly discovered edges to MST
for
(
int
i
=
0
;
i
<
G
.
V
();
i
++
)
{
Edge
e
=
closest
[
i
];
if
(
e
!=
null
)
{
int
v
=
e
.
either
(),
w
=
e
.
other
(
v
);
// don't add the same edge twice
if
(
uf
.
find
(
v
)
!=
uf
.
find
(
w
))
{
mst
.
add
(
e
);
weight
+=
e
.
weight
();
uf
.
union
(
v
,
w
);
}
}
}
}
// check optimality conditions
assert
check
(
G
);
}
/**
* Returns the edges in a minimum spanning tree (or forest).
*
@return
the edges in a minimum spanning tree (or forest) as
* an iterable of edges
*/
public
Iterable
<
Edge
>
edges
()
{
return
mst
;
}
/**
* Returns the sum of the edge weights in a minimum spanning tree (or forest).
*
@return
the sum of the edge weights in a minimum spanning tree (or forest)
*/
public
double
weight
()
{
return
weight
;
}
// is the weight of edge e strictly less than that of edge f?
private
static
boolean
less
(
Edge
e
,
Edge
f
)
{
return
e
.
compareTo
(
f
)
<
0
;
}
// check optimality conditions (takes time proportional to E V lg* V)
private
boolean
check
(
EdgeWeightedGraph
G
)
{
// check weight
double
totalWeight
=
0.0
;
for
(
Edge
e
:
edges
())
{
totalWeight
+=
e
.
weight
();
}
if
(
Math
.
abs
(
totalWeight
-
weight
())
>
FLOATING_POINT_EPSILON
)
{
System
.
err
.
printf
(
“Weight of edges does not equal weight(): %f vs. %f\n”
,
totalWeight
,
weight
());
return
false
;
}
// check that it is acyclic
UF uf
=
new
UF
(
G
.
V
());
for
(
Edge
e
:
edges
())
{
int
v
=
e
.
either
(),
w
=
e
.
other
(
v
);
if
(
uf
.
find
(
v
)
==
uf
.
find
(
w
))
{
System
.
err
.
println
(
“Not a forest”
);
return
false
;
}
uf
.
union
(
v
,
w
);
}
// check that it is a spanning forest
for
(
Edge
e
:
G
.
edges
())
{
int
v
=
e
.
either
(),
w
=
e
.
other
(
v
);
if
(
uf
.
find
(
v
)
!=
uf
.
find
(
w
))
{
System
.
err
.
println
(
“Not a spanning forest”
);
return
false
;
}
}
// check that it is a minimal spanning forest (cut optimality conditions)
for
(
Edge
e
:
edges
())
{
// all edges in MST except e
uf
=
new
UF
(
G
.
V
());
for
(
Edge
f
:
mst
)
{
int
x
=
f
.
either
(),
y
=
f
.
other
(
x
);
if
(
f
!=
e
)
uf
.
union
(
x
,
y
);
}
// check that e is min weight edge in crossing cut
for
(
Edge
f
:
G
.
edges
())
{
int
x
=
f
.
either
(),
y
=
f
.
other
(
x
);
if
(
uf
.
find
(
x
)
!=
uf
.
find
(
y
))
{
if
(
f
.
weight
()
<
e
.
weight
())
{
System
.
err
.
println
(
"Edge "
+
f
+
" violates cut optimality conditions"
);
return
false
;
}
}
}
}
return
true
;
}
/**
* Unit tests the {
@code
BoruvkaMST} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
EdgeWeightedGraph
G
=
new
EdgeWeightedGraph
(
in
);
BoruvkaMST
mst
=
new
BoruvkaMST
(
G
);
for
(
Edge
e
:
mst
.
edges
())
{
StdOut
.
println
(
e
);
}
StdOut
.
printf
(
"%.5f\n"
,
mst
.
weight
());
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/BoyerMoore.java
edu/princeton/cs/algs4/BoyerMoore.java
/******************************************************************************
* Compilation: javac BoyerMoore.java
* Execution: java BoyerMoore pattern text
* Dependencies: StdOut.java
*
* Reads in two strings, the pattern and the input text, and
* searches for the pattern in the input text using the
* bad-character rule part of the Boyer-Moore algorithm.
* (does not implement the strong good suffix rule)
*
* % java BoyerMoore abracadabra abacadabrabracabracadabrabrabracad
* text: abacadabrabracabracadabrabrabracad
* pattern: abracadabra
*
* % java BoyerMoore rab abacadabrabracabracadabrabrabracad
* text: abacadabrabracabracadabrabrabracad
* pattern: rab
*
* % java BoyerMoore bcara abacadabrabracabracadabrabrabracad
* text: abacadabrabracabracadabrabrabracad
* pattern: bcara
*
* % java BoyerMoore rabrabracad abacadabrabracabracadabrabrabracad
* text: abacadabrabracabracadabrabrabracad
* pattern: rabrabracad
*
* % java BoyerMoore abacad abacadabrabracabracadabrabrabracad
* text: abacadabrabracabracadabrabrabracad
* pattern: abacad
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
BoyerMoore} class finds the first occurrence of a pattern string
* in a text string.
*
* This implementation uses the Boyer-Moore algorithm (with the bad-character
* rule, but not the strong good suffix rule).
*
* For additional documentation,
* see Section 5.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*/
public
class
BoyerMoore
{
private
final
int
R
;
// the radix
private
int
[]
right
;
// the bad-character skip array
private
char
[]
pattern
;
// store the pattern as a character array
private
String
pat
;
// or as a string
/**
* Preprocesses the pattern string.
*
*
@param
pat the pattern string
*/
public
BoyerMoore
(
String
pat
)
{
this
.
R
=
256
;
this
.
pat
=
pat
;
// position of rightmost occurrence of c in the pattern
right
=
new
int
[
R
];
for
(
int
c
=
0
;
c
<
R
;
c
++
)
right
[
c
]
=
-
1
;
for
(
int
j
=
0
;
j
<
pat
.
length
();
j
++
)
right
[
pat
.
charAt
(
j
)]
=
j
;
}
/**
* Preprocesses the pattern string.
*
*
@param
pattern the pattern string
*
@param
R the alphabet size
*/
public
BoyerMoore
(
char
[]
pattern
,
int
R
)
{
this
.
R
=
R
;
this
.
pattern
=
new
char
[
pattern
.
length
];
for
(
int
j
=
0
;
j
<
pattern
.
length
;
j
++
)
this
.
pattern
[
j
]
=
pattern
[
j
];
// position of rightmost occurrence of c in the pattern
right
=
new
int
[
R
];
for
(
int
c
=
0
;
c
<
R
;
c
++
)
right
[
c
]
=
-
1
;
for
(
int
j
=
0
;
j
<
pattern
.
length
;
j
++
)
right
[
pattern
[
j
]]
=
j
;
}
/**
* Returns the index of the first occurrrence of the pattern string
* in the text string.
*
*
@param
txt the text string
*
@return
the index of the first occurrence of the pattern string
* in the text string; n if no such match
*/
public
int
search
(
String
txt
)
{
int
m
=
pat
.
length
();
int
n
=
txt
.
length
();
int
skip
;
for
(
int
i
=
0
;
i
<=
n
-
m
;
i
+=
skip
)
{
skip
=
0
;
for
(
int
j
=
m
-
1
;
j
>=
0
;
j
—
)
{
if
(
pat
.
charAt
(
j
)
!=
txt
.
charAt
(
i
+
j
))
{
skip
=
Math
.
max
(
1
,
j
–
right
[
txt
.
charAt
(
i
+
j
)]);
break
;
}
}
if
(
skip
==
0
)
return
i
;
// found
}
return
n
;
// not found
}
/**
* Returns the index of the first occurrrence of the pattern string
* in the text string.
*
*
@param
text the text string
*
@return
the index of the first occurrence of the pattern string
* in the text string; n if no such match
*/
public
int
search
(
char
[]
text
)
{
int
m
=
pattern
.
length
;
int
n
=
text
.
length
;
int
skip
;
for
(
int
i
=
0
;
i
<=
n
-
m
;
i
+=
skip
)
{
skip
=
0
;
for
(
int
j
=
m
-
1
;
j
>=
0
;
j
—
)
{
if
(
pattern
[
j
]
!=
text
[
i
+
j
])
{
skip
=
Math
.
max
(
1
,
j
–
right
[
text
[
i
+
j
]]);
break
;
}
}
if
(
skip
==
0
)
return
i
;
// found
}
return
n
;
// not found
}
/**
* Takes a pattern string and an input string as command-line arguments;
* searches for the pattern string in the text string; and prints
* the first occurrence of the pattern string in the text string.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
pat
=
args
[
0
];
String
txt
=
args
[
1
];
char
[]
pattern
=
pat
.
toCharArray
();
char
[]
text
=
txt
.
toCharArray
();
BoyerMoore
boyermoore1
=
new
BoyerMoore
(
pat
);
BoyerMoore
boyermoore2
=
new
BoyerMoore
(
pattern
,
256
);
int
offset1
=
boyermoore1
.
search
(
txt
);
int
offset2
=
boyermoore2
.
search
(
text
);
// print results
StdOut
.
println
(
“text: ”
+
txt
);
StdOut
.
print
(
“pattern: ”
);
for
(
int
i
=
0
;
i
<
offset1
;
i
++
)
StdOut
.
print
(
" "
);
StdOut
.
println
(
pat
);
StdOut
.
print
(
"pattern: "
);
for
(
int
i
=
0
;
i
<
offset2
;
i
++
)
StdOut
.
print
(
" "
);
StdOut
.
println
(
pat
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/BreadthFirstDirectedPaths.java
edu/princeton/cs/algs4/BreadthFirstDirectedPaths.java
/******************************************************************************
* Compilation: javac BreadthFirstDirectedPaths.java
* Execution: java BreadthFirstDirectedPaths digraph.txt s
* Dependencies: Digraph.java Queue.java Stack.java
* Data files: https://algs4.cs.princeton.edu/42digraph/tinyDG.txt
* https://algs4.cs.princeton.edu/42digraph/mediumDG.txt
* https://algs4.cs.princeton.edu/42digraph/largeDG.txt
*
* Run breadth-first search on a digraph.
* Runs in O(E + V) time.
*
* % java BreadthFirstDirectedPaths tinyDG.txt 3
* 3 to 0 (2): 3->2->0
* 3 to 1 (3): 3->2->0->1
* 3 to 2 (1): 3->2
* 3 to 3 (0): 3
* 3 to 4 (2): 3->5->4
* 3 to 5 (1): 3->5
* 3 to 6 (-): not connected
* 3 to 7 (-): not connected
* 3 to 8 (-): not connected
* 3 to 9 (-): not connected
* 3 to 10 (-): not connected
* 3 to 11 (-): not connected
* 3 to 12 (-): not connected
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
BreadthDirectedFirstPaths} class represents a data type for
* finding shortest paths (number of edges) from a source vertex s
* (or set of source vertices) to every other vertex in the digraph.
*
* This implementation uses breadth-first search.
* The constructor takes Θ(V + E) time in the
* worst case, where V is the number of vertices and E is
* the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the digraph).
*
* For additional documentation,
* see Section 4.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
BreadthFirstDirectedPaths
{
private
static
final
int
INFINITY
=
Integer
.
MAX_VALUE
;
private
boolean
[]
marked
;
// marked[v] = is there an s->v path?
private
int
[]
edgeTo
;
// edgeTo[v] = last edge on shortest s->v path
private
int
[]
distTo
;
// distTo[v] = length of shortest s->v path
/**
* Computes the shortest path from {
@code
s} and every other vertex in graph {
@code
G}.
*
@param
G the digraph
*
@param
s the source vertex
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
BreadthFirstDirectedPaths
(
Digraph
G
,
int
s
)
{
marked
=
new
boolean
[
G
.
V
()];
distTo
=
new
int
[
G
.
V
()];
edgeTo
=
new
int
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
distTo
[
v
]
=
INFINITY
;
validateVertex
(
s
);
bfs
(
G
,
s
);
}
/**
* Computes the shortest path from any one of the source vertices in {
@code
sources}
* to every other vertex in graph {
@code
G}.
*
@param
G the digraph
*
@param
sources the source vertices
*
@throws
IllegalArgumentException unless each vertex {
@code
v} in
* {
@code
sources} satisfies {
@code
0 <= v < V}
*/
public
BreadthFirstDirectedPaths
(
Digraph
G
,
Iterable
<
Integer
>
sources
)
{
marked
=
new
boolean
[
G
.
V
()];
distTo
=
new
int
[
G
.
V
()];
edgeTo
=
new
int
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
distTo
[
v
]
=
INFINITY
;
validateVertices
(
sources
);
bfs
(
G
,
sources
);
}
// BFS from single source
private
void
bfs
(
Digraph
G
,
int
s
)
{
Queue
<
Integer
>
q
=
new
Queue
<
Integer
>
();
marked
[
s
]
=
true
;
distTo
[
s
]
=
0
;
q
.
enqueue
(
s
);
while
(
!
q
.
isEmpty
())
{
int
v
=
q
.
dequeue
();
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
!
marked
[
w
])
{
edgeTo
[
w
]
=
v
;
distTo
[
w
]
=
distTo
[
v
]
+
1
;
marked
[
w
]
=
true
;
q
.
enqueue
(
w
);
}
}
}
}
// BFS from multiple sources
private
void
bfs
(
Digraph
G
,
Iterable
<
Integer
>
sources
)
{
Queue
<
Integer
>
q
=
new
Queue
<
Integer
>
();
for
(
int
s
:
sources
)
{
marked
[
s
]
=
true
;
distTo
[
s
]
=
0
;
q
.
enqueue
(
s
);
}
while
(
!
q
.
isEmpty
())
{
int
v
=
q
.
dequeue
();
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
!
marked
[
w
])
{
edgeTo
[
w
]
=
v
;
distTo
[
w
]
=
distTo
[
v
]
+
1
;
marked
[
w
]
=
true
;
q
.
enqueue
(
w
);
}
}
}
}
/**
* Is there a directed path from the source {
@code
s} (or sources) to vertex {
@code
v}?
*
@param
v the vertex
*
@return
{
@code
true} if there is a directed path, {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
boolean
hasPathTo
(
int
v
)
{
validateVertex
(
v
);
return
marked
[
v
];
}
/**
* Returns the number of edges in a shortest path from the source {
@code
s}
* (or sources) to vertex {
@code
v}?
*
@param
v the vertex
*
@return
the number of edges in a shortest path
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
int
distTo
(
int
v
)
{
validateVertex
(
v
);
return
distTo
[
v
];
}
/**
* Returns a shortest path from {
@code
s} (or sources) to {
@code
v}, or
* {
@code
null} if no such path.
*
@param
v the vertex
*
@return
the sequence of vertices on a shortest path, as an Iterable
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
Iterable
<
Integer
>
pathTo
(
int
v
)
{
validateVertex
(
v
);
if
(
!
hasPathTo
(
v
))
return
null
;
Stack
<
Integer
>
path
=
new
Stack
<
Integer
>
();
int
x
;
for
(
x
=
v
;
distTo
[
x
]
!=
0
;
x
=
edgeTo
[
x
])
path
.
push
(
x
);
path
.
push
(
x
);
return
path
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
marked
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertices
(
Iterable
<
Integer
>
vertices
)
{
if
(
vertices
==
null
)
{
throw
new
IllegalArgumentException
(
“argument is null”
);
}
int
V
=
marked
.
length
;
for
(
int
v
:
vertices
)
{
if
(
v
<
0
||
v
>=
V
)
{
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
}
}
/**
* Unit tests the {
@code
BreadthFirstDirectedPaths} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
Digraph
G
=
new
Digraph
(
in
);
// StdOut.println(G);
int
s
=
Integer
.
parseInt
(
args
[
1
]);
BreadthFirstDirectedPaths
bfs
=
new
BreadthFirstDirectedPaths
(
G
,
s
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
bfs
.
hasPathTo
(
v
))
{
StdOut
.
printf
(
"%d to %d (%d): "
,
s
,
v
,
bfs
.
distTo
(
v
));
for
(
int
x
:
bfs
.
pathTo
(
v
))
{
if
(
x
==
s
)
StdOut
.
print
(
x
);
else
StdOut
.
print
(
"->”
+
x
);
}
StdOut
.
println
();
}
else
{
StdOut
.
printf
(
“%d to %d (-): not connected\n”
,
s
,
v
);
}
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/BreadthFirstPaths.java
edu/princeton/cs/algs4/BreadthFirstPaths.java
/******************************************************************************
* Compilation: javac BreadthFirstPaths.java
* Execution: java BreadthFirstPaths G s
* Dependencies: Graph.java Queue.java Stack.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/41graph/tinyCG.txt
* https://algs4.cs.princeton.edu/41graph/tinyG.txt
* https://algs4.cs.princeton.edu/41graph/mediumG.txt
* https://algs4.cs.princeton.edu/41graph/largeG.txt
*
* Run breadth first search on an undirected graph.
* Runs in O(E + V) time.
*
* % java Graph tinyCG.txt
* 6 8
* 0: 2 1 5
* 1: 0 2
* 2: 0 1 3 4
* 3: 5 4 2
* 4: 3 2
* 5: 3 0
*
* % java BreadthFirstPaths tinyCG.txt 0
* 0 to 0 (0): 0
* 0 to 1 (1): 0-1
* 0 to 2 (1): 0-2
* 0 to 3 (2): 0-2-3
* 0 to 4 (2): 0-2-4
* 0 to 5 (1): 0-5
*
* % java BreadthFirstPaths largeG.txt 0
* 0 to 0 (0): 0
* 0 to 1 (418): 0-932942-474885-82707-879889-971961-…
* 0 to 2 (323): 0-460790-53370-594358-780059-287921-…
* 0 to 3 (168): 0-713461-75230-953125-568284-350405-…
* 0 to 4 (144): 0-460790-53370-310931-440226-380102-…
* 0 to 5 (566): 0-932942-474885-82707-879889-971961-…
* 0 to 6 (349): 0-932942-474885-82707-879889-971961-…
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
BreadthFirstPaths} class represents a data type for finding
* shortest paths (number of edges) from a source vertex s
* (or a set of source vertices)
* to every other vertex in an undirected graph.
*
* This implementation uses breadth-first search.
* The constructor takes Θ(V + E) time in the
* worst case, where V is the number of vertices and E
* is the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the graph).
*
* For additional documentation,
* see Section 4.1
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
BreadthFirstPaths
{
private
static
final
int
INFINITY
=
Integer
.
MAX_VALUE
;
private
boolean
[]
marked
;
// marked[v] = is there an s-v path
private
int
[]
edgeTo
;
// edgeTo[v] = previous edge on shortest s-v path
private
int
[]
distTo
;
// distTo[v] = number of edges shortest s-v path
/**
* Computes the shortest path between the source vertex {
@code
s}
* and every other vertex in the graph {
@code
G}.
*
@param
G the graph
*
@param
s the source vertex
*
@throws
IllegalArgumentException unless {
@code
0 <= s < V}
*/
public
BreadthFirstPaths
(
Graph
G
,
int
s
)
{
marked
=
new
boolean
[
G
.
V
()];
distTo
=
new
int
[
G
.
V
()];
edgeTo
=
new
int
[
G
.
V
()];
validateVertex
(
s
);
bfs
(
G
,
s
);
assert
check
(
G
,
s
);
}
/**
* Computes the shortest path between any one of the source vertices in {
@code
sources}
* and every other vertex in graph {
@code
G}.
*
@param
G the graph
*
@param
sources the source vertices
*
@throws
IllegalArgumentException unless {
@code
0 <= s < V} for each vertex
* {
@code
s} in {
@code
sources}
*/
public
BreadthFirstPaths
(
Graph
G
,
Iterable
<
Integer
>
sources
)
{
marked
=
new
boolean
[
G
.
V
()];
distTo
=
new
int
[
G
.
V
()];
edgeTo
=
new
int
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
distTo
[
v
]
=
INFINITY
;
validateVertices
(
sources
);
bfs
(
G
,
sources
);
}
// breadth-first search from a single source
private
void
bfs
(
Graph
G
,
int
s
)
{
Queue
<
Integer
>
q
=
new
Queue
<
Integer
>
();
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
distTo
[
v
]
=
INFINITY
;
distTo
[
s
]
=
0
;
marked
[
s
]
=
true
;
q
.
enqueue
(
s
);
while
(
!
q
.
isEmpty
())
{
int
v
=
q
.
dequeue
();
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
!
marked
[
w
])
{
edgeTo
[
w
]
=
v
;
distTo
[
w
]
=
distTo
[
v
]
+
1
;
marked
[
w
]
=
true
;
q
.
enqueue
(
w
);
}
}
}
}
// breadth-first search from multiple sources
private
void
bfs
(
Graph
G
,
Iterable
<
Integer
>
sources
)
{
Queue
<
Integer
>
q
=
new
Queue
<
Integer
>
();
for
(
int
s
:
sources
)
{
marked
[
s
]
=
true
;
distTo
[
s
]
=
0
;
q
.
enqueue
(
s
);
}
while
(
!
q
.
isEmpty
())
{
int
v
=
q
.
dequeue
();
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
!
marked
[
w
])
{
edgeTo
[
w
]
=
v
;
distTo
[
w
]
=
distTo
[
v
]
+
1
;
marked
[
w
]
=
true
;
q
.
enqueue
(
w
);
}
}
}
}
/**
* Is there a path between the source vertex {
@code
s} (or sources) and vertex {
@code
v}?
*
@param
v the vertex
*
@return
{
@code
true} if there is a path, and {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
boolean
hasPathTo
(
int
v
)
{
validateVertex
(
v
);
return
marked
[
v
];
}
/**
* Returns the number of edges in a shortest path between the source vertex {
@code
s}
* (or sources) and vertex {
@code
v}?
*
@param
v the vertex
*
@return
the number of edges in a shortest path
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
int
distTo
(
int
v
)
{
validateVertex
(
v
);
return
distTo
[
v
];
}
/**
* Returns a shortest path between the source vertex {
@code
s} (or sources)
* and {
@code
v}, or {
@code
null} if no such path.
*
@param
v the vertex
*
@return
the sequence of vertices on a shortest path, as an Iterable
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
Iterable
<
Integer
>
pathTo
(
int
v
)
{
validateVertex
(
v
);
if
(
!
hasPathTo
(
v
))
return
null
;
Stack
<
Integer
>
path
=
new
Stack
<
Integer
>
();
int
x
;
for
(
x
=
v
;
distTo
[
x
]
!=
0
;
x
=
edgeTo
[
x
])
path
.
push
(
x
);
path
.
push
(
x
);
return
path
;
}
// check optimality conditions for single source
private
boolean
check
(
Graph
G
,
int
s
)
{
// check that the distance of s = 0
if
(
distTo
[
s
]
!=
0
)
{
StdOut
.
println
(
“distance of source ”
+
s
+
” to itself = ”
+
distTo
[
s
]);
return
false
;
}
// check that for each edge v-w dist[w] <= dist[v] + 1
// provided v is reachable from s
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
hasPathTo
(
v
)
!=
hasPathTo
(
w
))
{
StdOut
.
println
(
"edge "
+
v
+
"-"
+
w
);
StdOut
.
println
(
"hasPathTo("
+
v
+
") = "
+
hasPathTo
(
v
));
StdOut
.
println
(
"hasPathTo("
+
w
+
") = "
+
hasPathTo
(
w
));
return
false
;
}
if
(
hasPathTo
(
v
)
&&
(
distTo
[
w
]
>
distTo
[
v
]
+
1
))
{
StdOut
.
println
(
“edge ”
+
v
+
“-”
+
w
);
StdOut
.
println
(
“distTo[”
+
v
+
“] = ”
+
distTo
[
v
]);
StdOut
.
println
(
“distTo[”
+
w
+
“] = ”
+
distTo
[
w
]);
return
false
;
}
}
}
// check that v = edgeTo[w] satisfies distTo[w] = distTo[v] + 1
// provided v is reachable from s
for
(
int
w
=
0
;
w
<
G
.
V
();
w
++
)
{
if
(
!
hasPathTo
(
w
)
||
w
==
s
)
continue
;
int
v
=
edgeTo
[
w
];
if
(
distTo
[
w
]
!=
distTo
[
v
]
+
1
)
{
StdOut
.
println
(
"shortest path edge "
+
v
+
"-"
+
w
);
StdOut
.
println
(
"distTo["
+
v
+
"] = "
+
distTo
[
v
]);
StdOut
.
println
(
"distTo["
+
w
+
"] = "
+
distTo
[
w
]);
return
false
;
}
}
return
true
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
marked
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertices
(
Iterable
<
Integer
>
vertices
)
{
if
(
vertices
==
null
)
{
throw
new
IllegalArgumentException
(
“argument is null”
);
}
int
V
=
marked
.
length
;
for
(
int
v
:
vertices
)
{
if
(
v
<
0
||
v
>=
V
)
{
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
}
}
/**
* Unit tests the {
@code
BreadthFirstPaths} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
Graph
G
=
new
Graph
(
in
);
// StdOut.println(G);
int
s
=
Integer
.
parseInt
(
args
[
1
]);
BreadthFirstPaths
bfs
=
new
BreadthFirstPaths
(
G
,
s
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
bfs
.
hasPathTo
(
v
))
{
StdOut
.
printf
(
"%d to %d (%d): "
,
s
,
v
,
bfs
.
distTo
(
v
));
for
(
int
x
:
bfs
.
pathTo
(
v
))
{
if
(
x
==
s
)
StdOut
.
print
(
x
);
else
StdOut
.
print
(
"-"
+
x
);
}
StdOut
.
println
();
}
else
{
StdOut
.
printf
(
"%d to %d (-): not connected\n"
,
s
,
v
);
}
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/BST.java
edu/princeton/cs/algs4/BST.java
/******************************************************************************
* Compilation: javac BST.java
* Execution: java BST
* Dependencies: StdIn.java StdOut.java Queue.java
* Data files: https://algs4.cs.princeton.edu/32bst/tinyST.txt
*
* A symbol table implemented with a binary search tree.
*
* % more tinyST.txt
* S E A R C H E X A M P L E
*
* % java BST < tinyST.txt
* A 8
* C 4
* E 12
* H 5
* L 11
* M 9
* P 10
* R 3
* S 0
* X 7
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
NoSuchElementException
;
/**
* The {
@code
BST} class represents an ordered symbol table of generic
* key-value pairs.
* It supports the usual put, get, contains,
* delete, size, and is-empty methods.
* It also provides ordered methods for finding the minimum,
* maximum, floor, select, ceiling.
* It also provides a keys method for iterating over all of the keys.
* A symbol table implements the associative array abstraction:
* when associating a value with a key that is already in the symbol table,
* the convention is to replace the old value with the new value.
* Unlike {
@link
java.util.Map}, this class uses the convention that
* values cannot be {
@code
null}—setting the
* value associated with a key to {
@code
null} is equivalent to deleting the key
* from the symbol table.
*
* It requires that
* the key type implements the {
@code
Comparable} interface and calls the
* {
@code
compareTo()} and method to compare two keys. It does not call either
* {
@code
equals()} or {
@code
hashCode()}.
*
* This implementation uses an (unbalanced) binary search tree.
* The put, contains, remove, minimum,
* maximum, ceiling, floor, select, and
* rank operations each take Θ(n) time in the worst
* case, where n is the number of key-value pairs.
* The size and is-empty operations take Θ(1) time.
* The keys method takes Θ(n) time in the worst case.
* Construction takes Θ(1) time.
*
* For alternative implementations of the symbol table API, see {
@link
ST},
* {
@link
BinarySearchST}, {
@link
SequentialSearchST}, {
@link
RedBlackBST},
* {
@link
SeparateChainingHashST}, and {
@link
LinearProbingHashST},
* For additional documentation, see
* Section 3.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
BST
<
Key
extends
Comparable
<
Key
>
,
Value
>
{
private
Node
root
;
// root of BST
private
class
Node
{
private
Key
key
;
// sorted by key
private
Value
val
;
// associated data
private
Node
left
,
right
;
// left and right subtrees
private
int
size
;
// number of nodes in subtree
public
Node
(
Key
key
,
Value
val
,
int
size
)
{
this
.
key
=
key
;
this
.
val
=
val
;
this
.
size
=
size
;
}
}
/**
* Initializes an empty symbol table.
*/
public
BST
()
{
}
/**
* Returns true if this symbol table is empty.
*
@return
{
@code
true} if this symbol table is empty; {
@code
false} otherwise
*/
public
boolean
isEmpty
()
{
return
size
()
==
0
;
}
/**
* Returns the number of key-value pairs in this symbol table.
*
@return
the number of key-value pairs in this symbol table
*/
public
int
size
()
{
return
size
(
root
);
}
// return number of key-value pairs in BST rooted at x
private
int
size
(
Node
x
)
{
if
(
x
==
null
)
return
0
;
else
return
x
.
size
;
}
/**
* Does this symbol table contain the given key?
*
*
@param
key the key
*
@return
{
@code
true} if this symbol table contains {
@code
key} and
* {
@code
false} otherwise
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
boolean
contains
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to contains() is null”
);
return
get
(
key
)
!=
null
;
}
/**
* Returns the value associated with the given key.
*
*
@param
key the key
*
@return
the value associated with the given key if the key is in the symbol table
* and {
@code
null} if the key is not in the symbol table
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
Value
get
(
Key
key
)
{
return
get
(
root
,
key
);
}
private
Value
get
(
Node
x
,
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“calls get() with a null key”
);
if
(
x
==
null
)
return
null
;
int
cmp
=
key
.
compareTo
(
x
.
key
);
if
(
cmp
<
0
)
return
get
(
x
.
left
,
key
);
else
if
(
cmp
>
0
)
return
get
(
x
.
right
,
key
);
else
return
x
.
val
;
}
/**
* Inserts the specified key-value pair into the symbol table, overwriting the old
* value with the new value if the symbol table already contains the specified key.
* Deletes the specified key (and its associated value) from this symbol table
* if the specified value is {
@code
null}.
*
*
@param
key the key
*
@param
val the value
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
put
(
Key
key
,
Value
val
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“calls put() with a null key”
);
if
(
val
==
null
)
{
delete
(
key
);
return
;
}
root
=
put
(
root
,
key
,
val
);
assert
check
();
}
private
Node
put
(
Node
x
,
Key
key
,
Value
val
)
{
if
(
x
==
null
)
return
new
Node
(
key
,
val
,
1
);
int
cmp
=
key
.
compareTo
(
x
.
key
);
if
(
cmp
<
0
)
x
.
left
=
put
(
x
.
left
,
key
,
val
);
else
if
(
cmp
>
0
)
x
.
right
=
put
(
x
.
right
,
key
,
val
);
else
x
.
val
=
val
;
x
.
size
=
1
+
size
(
x
.
left
)
+
size
(
x
.
right
);
return
x
;
}
/**
* Removes the smallest key and associated value from the symbol table.
*
*
@throws
NoSuchElementException if the symbol table is empty
*/
public
void
deleteMin
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Symbol table underflow”
);
root
=
deleteMin
(
root
);
assert
check
();
}
private
Node
deleteMin
(
Node
x
)
{
if
(
x
.
left
==
null
)
return
x
.
right
;
x
.
left
=
deleteMin
(
x
.
left
);
x
.
size
=
size
(
x
.
left
)
+
size
(
x
.
right
)
+
1
;
return
x
;
}
/**
* Removes the largest key and associated value from the symbol table.
*
*
@throws
NoSuchElementException if the symbol table is empty
*/
public
void
deleteMax
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Symbol table underflow”
);
root
=
deleteMax
(
root
);
assert
check
();
}
private
Node
deleteMax
(
Node
x
)
{
if
(
x
.
right
==
null
)
return
x
.
left
;
x
.
right
=
deleteMax
(
x
.
right
);
x
.
size
=
size
(
x
.
left
)
+
size
(
x
.
right
)
+
1
;
return
x
;
}
/**
* Removes the specified key and its associated value from this symbol table
* (if the key is in this symbol table).
*
*
@param
key the key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
delete
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“calls delete() with a null key”
);
root
=
delete
(
root
,
key
);
assert
check
();
}
private
Node
delete
(
Node
x
,
Key
key
)
{
if
(
x
==
null
)
return
null
;
int
cmp
=
key
.
compareTo
(
x
.
key
);
if
(
cmp
<
0
)
x
.
left
=
delete
(
x
.
left
,
key
);
else
if
(
cmp
>
0
)
x
.
right
=
delete
(
x
.
right
,
key
);
else
{
if
(
x
.
right
==
null
)
return
x
.
left
;
if
(
x
.
left
==
null
)
return
x
.
right
;
Node
t
=
x
;
x
=
min
(
t
.
right
);
x
.
right
=
deleteMin
(
t
.
right
);
x
.
left
=
t
.
left
;
}
x
.
size
=
size
(
x
.
left
)
+
size
(
x
.
right
)
+
1
;
return
x
;
}
/**
* Returns the smallest key in the symbol table.
*
*
@return
the smallest key in the symbol table
*
@throws
NoSuchElementException if the symbol table is empty
*/
public
Key
min
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“calls min() with empty symbol table”
);
return
min
(
root
).
key
;
}
private
Node
min
(
Node
x
)
{
if
(
x
.
left
==
null
)
return
x
;
else
return
min
(
x
.
left
);
}
/**
* Returns the largest key in the symbol table.
*
*
@return
the largest key in the symbol table
*
@throws
NoSuchElementException if the symbol table is empty
*/
public
Key
max
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“calls max() with empty symbol table”
);
return
max
(
root
).
key
;
}
private
Node
max
(
Node
x
)
{
if
(
x
.
right
==
null
)
return
x
;
else
return
max
(
x
.
right
);
}
/**
* Returns the largest key in the symbol table less than or equal to {
@code
key}.
*
*
@param
key the key
*
@return
the largest key in the symbol table less than or equal to {
@code
key}
*
@throws
NoSuchElementException if there is no such key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
Key
floor
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to floor() is null”
);
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“calls floor() with empty symbol table”
);
Node
x
=
floor
(
root
,
key
);
if
(
x
==
null
)
throw
new
NoSuchElementException
(
“argument to floor() is too small”
);
else
return
x
.
key
;
}
private
Node
floor
(
Node
x
,
Key
key
)
{
if
(
x
==
null
)
return
null
;
int
cmp
=
key
.
compareTo
(
x
.
key
);
if
(
cmp
==
0
)
return
x
;
if
(
cmp
<
0
)
return
floor
(
x
.
left
,
key
);
Node
t
=
floor
(
x
.
right
,
key
);
if
(
t
!=
null
)
return
t
;
else
return
x
;
}
public
Key
floor2
(
Key
key
)
{
Key
x
=
floor2
(
root
,
key
,
null
);
if
(
x
==
null
)
throw
new
NoSuchElementException
(
"argument to floor() is too small"
);
else
return
x
;
}
private
Key
floor2
(
Node
x
,
Key
key
,
Key
best
)
{
if
(
x
==
null
)
return
best
;
int
cmp
=
key
.
compareTo
(
x
.
key
);
if
(
cmp
<
0
)
return
floor2
(
x
.
left
,
key
,
best
);
else
if
(
cmp
>
0
)
return
floor2
(
x
.
right
,
key
,
x
.
key
);
else
return
x
.
key
;
}
/**
* Returns the smallest key in the symbol table greater than or equal to {
@code
key}.
*
*
@param
key the key
*
@return
the smallest key in the symbol table greater than or equal to {
@code
key}
*
@throws
NoSuchElementException if there is no such key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
Key
ceiling
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to ceiling() is null”
);
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“calls ceiling() with empty symbol table”
);
Node
x
=
ceiling
(
root
,
key
);
if
(
x
==
null
)
throw
new
NoSuchElementException
(
“argument to floor() is too large”
);
else
return
x
.
key
;
}
private
Node
ceiling
(
Node
x
,
Key
key
)
{
if
(
x
==
null
)
return
null
;
int
cmp
=
key
.
compareTo
(
x
.
key
);
if
(
cmp
==
0
)
return
x
;
if
(
cmp
<
0
)
{
Node
t
=
ceiling
(
x
.
left
,
key
);
if
(
t
!=
null
)
return
t
;
else
return
x
;
}
return
ceiling
(
x
.
right
,
key
);
}
/**
* Return the key in the symbol table whose rank is {
@code
k}.
* This is the (k+1)st smallest key in the symbol table.
*
*
@param
k the order statistic
*
@return
the key in the symbol table of rank {
@code
k}
*
@throws
IllegalArgumentException unless {
@code
k} is between 0 and
* n–1
*/
public
Key
select
(
int
k
)
{
if
(
k
<
0
||
k
>=
size
())
{
throw
new
IllegalArgumentException
(
“argument to select() is invalid: ”
+
k
);
}
Node
x
=
select
(
root
,
k
);
return
x
.
key
;
}
// Return key of rank k.
private
Node
select
(
Node
x
,
int
k
)
{
if
(
x
==
null
)
return
null
;
int
t
=
size
(
x
.
left
);
if
(
t
>
k
)
return
select
(
x
.
left
,
k
);
else
if
(
t
<
k
)
return
select
(
x
.
right
,
k
-
t
-
1
);
else
return
x
;
}
/**
* Return the number of keys in the symbol table strictly less than {
@code
key}.
*
*
@param
key the key
*
@return
the number of keys in the symbol table strictly less than {
@code
key}
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
int
rank
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
"argument to rank() is null"
);
return
rank
(
key
,
root
);
}
// Number of keys in the subtree less than key.
private
int
rank
(
Key
key
,
Node
x
)
{
if
(
x
==
null
)
return
0
;
int
cmp
=
key
.
compareTo
(
x
.
key
);
if
(
cmp
<
0
)
return
rank
(
key
,
x
.
left
);
else
if
(
cmp
>
0
)
return
1
+
size
(
x
.
left
)
+
rank
(
key
,
x
.
right
);
else
return
size
(
x
.
left
);
}
/**
* Returns all keys in the symbol table as an {
@code
Iterable}.
* To iterate over all of the keys in the symbol table named {
@code
st},
* use the foreach notation: {
@code
for (Key key : st.keys())}.
*
*
@return
all keys in the symbol table
*/
public
Iterable
<
Key
>
keys
()
{
if
(
isEmpty
())
return
new
Queue
<
Key
>
();
return
keys
(
min
(),
max
());
}
/**
* Returns all keys in the symbol table in the given range,
* as an {
@code
Iterable}.
*
*
@param
lo minimum endpoint
*
@param
hi maximum endpoint
*
@return
all keys in the symbol table between {
@code
lo}
* (inclusive) and {
@code
hi} (inclusive)
*
@throws
IllegalArgumentException if either {
@code
lo} or {
@code
hi}
* is {
@code
null}
*/
public
Iterable
<
Key
>
keys
(
Key
lo
,
Key
hi
)
{
if
(
lo
==
null
)
throw
new
IllegalArgumentException
(
“first argument to keys() is null”
);
if
(
hi
==
null
)
throw
new
IllegalArgumentException
(
“second argument to keys() is null”
);
Queue
<
Key
>
queue
=
new
Queue
<
Key
>
();
keys
(
root
,
queue
,
lo
,
hi
);
return
queue
;
}
private
void
keys
(
Node
x
,
Queue
<
Key
>
queue
,
Key
lo
,
Key
hi
)
{
if
(
x
==
null
)
return
;
int
cmplo
=
lo
.
compareTo
(
x
.
key
);
int
cmphi
=
hi
.
compareTo
(
x
.
key
);
if
(
cmplo
<
0
)
keys
(
x
.
left
,
queue
,
lo
,
hi
);
if
(
cmplo
<=
0
&&
cmphi
>=
0
)
queue
.
enqueue
(
x
.
key
);
if
(
cmphi
>
0
)
keys
(
x
.
right
,
queue
,
lo
,
hi
);
}
/**
* Returns the number of keys in the symbol table in the given range.
*
*
@param
lo minimum endpoint
*
@param
hi maximum endpoint
*
@return
the number of keys in the symbol table between {
@code
lo}
* (inclusive) and {
@code
hi} (inclusive)
*
@throws
IllegalArgumentException if either {
@code
lo} or {
@code
hi}
* is {
@code
null}
*/
public
int
size
(
Key
lo
,
Key
hi
)
{
if
(
lo
==
null
)
throw
new
IllegalArgumentException
(
“first argument to size() is null”
);
if
(
hi
==
null
)
throw
new
IllegalArgumentException
(
“second argument to size() is null”
);
if
(
lo
.
compareTo
(
hi
)
>
0
)
return
0
;
if
(
contains
(
hi
))
return
rank
(
hi
)
–
rank
(
lo
)
+
1
;
else
return
rank
(
hi
)
–
rank
(
lo
);
}
/**
* Returns the height of the BST (for debugging).
*
*
@return
the height of the BST (a 1-node tree has height 0)
*/
public
int
height
()
{
return
height
(
root
);
}
private
int
height
(
Node
x
)
{
if
(
x
==
null
)
return
–
1
;
return
1
+
Math
.
max
(
height
(
x
.
left
),
height
(
x
.
right
));
}
/**
* Returns the keys in the BST in level order (for debugging).
*
*
@return
the keys in the BST in level order traversal
*/
public
Iterable
<
Key
>
levelOrder
()
{
Queue
<
Key
>
keys
=
new
Queue
<
Key
>
();
Queue
<
Node
>
queue
=
new
Queue
<
Node
>
();
queue
.
enqueue
(
root
);
while
(
!
queue
.
isEmpty
())
{
Node
x
=
queue
.
dequeue
();
if
(
x
==
null
)
continue
;
keys
.
enqueue
(
x
.
key
);
queue
.
enqueue
(
x
.
left
);
queue
.
enqueue
(
x
.
right
);
}
return
keys
;
}
/*************************************************************************
* Check integrity of BST data structure.
***************************************************************************/
private
boolean
check
()
{
if
(
!
isBST
())
StdOut
.
println
(
“Not in symmetric order”
);
if
(
!
isSizeConsistent
())
StdOut
.
println
(
“Subtree counts not consistent”
);
if
(
!
isRankConsistent
())
StdOut
.
println
(
“Ranks not consistent”
);
return
isBST
()
&&
isSizeConsistent
()
&&
isRankConsistent
();
}
// does this binary tree satisfy symmetric order?
// Note: this test also ensures that data structure is a binary tree since order is strict
private
boolean
isBST
()
{
return
isBST
(
root
,
null
,
null
);
}
// is the tree rooted at x a BST with all keys strictly between min and max
// (if min or max is null, treat as empty constraint)
// Credit: Bob Dondero’s elegant solution
private
boolean
isBST
(
Node
x
,
Key
min
,
Key
max
)
{
if
(
x
==
null
)
return
true
;
if
(
min
!=
null
&&
x
.
key
.
compareTo
(
min
)
<=
0
)
return
false
;
if
(
max
!=
null
&&
x
.
key
.
compareTo
(
max
)
>=
0
)
return
false
;
return
isBST
(
x
.
left
,
min
,
x
.
key
)
&&
isBST
(
x
.
right
,
x
.
key
,
max
);
}
// are the size fields correct?
private
boolean
isSizeConsistent
()
{
return
isSizeConsistent
(
root
);
}
private
boolean
isSizeConsistent
(
Node
x
)
{
if
(
x
==
null
)
return
true
;
if
(
x
.
size
!=
size
(
x
.
left
)
+
size
(
x
.
right
)
+
1
)
return
false
;
return
isSizeConsistent
(
x
.
left
)
&&
isSizeConsistent
(
x
.
right
);
}
// check that ranks are consistent
private
boolean
isRankConsistent
()
{
for
(
int
i
=
0
;
i
<
size
();
i
++
)
if
(
i
!=
rank
(
select
(
i
)))
return
false
;
for
(
Key
key
:
keys
())
if
(
key
.
compareTo
(
select
(
rank
(
key
)))
!=
0
)
return
false
;
return
true
;
}
/**
* Unit tests the {
@code
BST} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
BST
<
String
,
Integer
>
st
=
new
BST
<
String
,
Integer
>
();
for
(
int
i
=
0
;
!
StdIn
.
isEmpty
();
i
++
)
{
String
key
=
StdIn
.
readString
();
st
.
put
(
key
,
i
);
}
for
(
String
s
:
st
.
levelOrder
())
StdOut
.
println
(
s
+
” ”
+
st
.
get
(
s
));
StdOut
.
println
();
for
(
String
s
:
st
.
keys
())
StdOut
.
println
(
s
+
” ”
+
st
.
get
(
s
));
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/BTree.java
edu/princeton/cs/algs4/BTree.java
/******************************************************************************
* Compilation: javac BTree.java
* Execution: java BTree
* Dependencies: StdOut.java
*
* B-tree.
*
* Limitations
* ———–
* – Assumes M is even and M >= 4
* – should b be an array of children or list (it would help with
* casting to make it a list)
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
BTree} class represents an ordered symbol table of generic
* key-value pairs.
* It supports the put, get, contains,
* size, and is-empty methods.
* A symbol table implements the associative array abstraction:
* when associating a value with a key that is already in the symbol table,
* the convention is to replace the old value with the new value.
* Unlike {
@link
java.util.Map}, this class uses the convention that
* values cannot be {
@code
null}—setting the
* value associated with a key to {
@code
null} is equivalent to deleting the key
* from the symbol table.
*
* This implementation uses a B-tree. It requires that
* the key type implements the {
@code
Comparable} interface and calls the
* {
@code
compareTo()} and method to compare two keys. It does not call either
* {
@code
equals()} or {
@code
hashCode()}.
* The get, put, and contains operations
* each make logm(n) probes in the worst case,
* where n is the number of key-value pairs
* and m is the branching factor.
* The size, and is-empty operations take constant time.
* Construction takes constant time.
*
* For additional documentation, see
* Section 6.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*/
public
class
BTree
<
Key
extends
Comparable
<
Key
>
,
Value
>
{
// max children per B-tree node = M-1
// (must be even and greater than 2)
private
static
final
int
M
=
4
;
private
Node
root
;
// root of the B-tree
private
int
height
;
// height of the B-tree
private
int
n
;
// number of key-value pairs in the B-tree
// helper B-tree node data type
private
static
final
class
Node
{
private
int
m
;
// number of children
private
Entry
[]
children
=
new
Entry
[
M
];
// the array of children
// create a node with k children
private
Node
(
int
k
)
{
m
=
k
;
}
}
// internal nodes: only use key and next
// external nodes: only use key and value
private
static
class
Entry
{
private
Comparable
key
;
private
final
Object
val
;
private
Node
next
;
// helper field to iterate over array entries
public
Entry
(
Comparable
key
,
Object
val
,
Node
next
)
{
this
.
key
=
key
;
this
.
val
=
val
;
this
.
next
=
next
;
}
}
/**
* Initializes an empty B-tree.
*/
public
BTree
()
{
root
=
new
Node
(
0
);
}
/**
* Returns true if this symbol table is empty.
*
@return
{
@code
true} if this symbol table is empty; {
@code
false} otherwise
*/
public
boolean
isEmpty
()
{
return
size
()
==
0
;
}
/**
* Returns the number of key-value pairs in this symbol table.
*
@return
the number of key-value pairs in this symbol table
*/
public
int
size
()
{
return
n
;
}
/**
* Returns the height of this B-tree (for debugging).
*
*
@return
the height of this B-tree
*/
public
int
height
()
{
return
height
;
}
/**
* Returns the value associated with the given key.
*
*
@param
key the key
*
@return
the value associated with the given key if the key is in the symbol table
* and {
@code
null} if the key is not in the symbol table
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
Value
get
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to get() is null”
);
return
search
(
root
,
key
,
height
);
}
private
Value
search
(
Node
x
,
Key
key
,
int
ht
)
{
Entry
[]
children
=
x
.
children
;
// external node
if
(
ht
==
0
)
{
for
(
int
j
=
0
;
j
<
x
.
m
;
j
++
)
{
if
(
eq
(
key
,
children
[
j
].
key
))
return
(
Value
)
children
[
j
].
val
;
}
}
// internal node
else
{
for
(
int
j
=
0
;
j
<
x
.
m
;
j
++
)
{
if
(
j
+
1
==
x
.
m
||
less
(
key
,
children
[
j
+
1
].
key
))
return
search
(
children
[
j
].
next
,
key
,
ht
-
1
);
}
}
return
null
;
}
/**
* Inserts the key-value pair into the symbol table, overwriting the old value
* with the new value if the key is already in the symbol table.
* If the value is {
@code
null}, this effectively deletes the key from the symbol table.
*
*
@param
key the key
*
@param
val the value
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
put
(
Key
key
,
Value
val
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
"argument key to put() is null"
);
Node
u
=
insert
(
root
,
key
,
val
,
height
);
n
++
;
if
(
u
==
null
)
return
;
// need to split root
Node
t
=
new
Node
(
2
);
t
.
children
[
0
]
=
new
Entry
(
root
.
children
[
0
].
key
,
null
,
root
);
t
.
children
[
1
]
=
new
Entry
(
u
.
children
[
0
].
key
,
null
,
u
);
root
=
t
;
height
++
;
}
private
Node
insert
(
Node
h
,
Key
key
,
Value
val
,
int
ht
)
{
int
j
;
Entry
t
=
new
Entry
(
key
,
val
,
null
);
// external node
if
(
ht
==
0
)
{
for
(
j
=
0
;
j
<
h
.
m
;
j
++
)
{
if
(
less
(
key
,
h
.
children
[
j
].
key
))
break
;
}
}
// internal node
else
{
for
(
j
=
0
;
j
<
h
.
m
;
j
++
)
{
if
((
j
+
1
==
h
.
m
)
||
less
(
key
,
h
.
children
[
j
+
1
].
key
))
{
Node
u
=
insert
(
h
.
children
[
j
++
].
next
,
key
,
val
,
ht
-
1
);
if
(
u
==
null
)
return
null
;
t
.
key
=
u
.
children
[
0
].
key
;
t
.
next
=
u
;
break
;
}
}
}
for
(
int
i
=
h
.
m
;
i
>
j
;
i
—
)
h
.
children
[
i
]
=
h
.
children
[
i
–
1
];
h
.
children
[
j
]
=
t
;
h
.
m
++
;
if
(
h
.
m
<
M
)
return
null
;
else
return
split
(
h
);
}
// split node in half
private
Node
split
(
Node
h
)
{
Node
t
=
new
Node
(
M
/
2
);
h
.
m
=
M
/
2
;
for
(
int
j
=
0
;
j
<
M
/
2
;
j
++
)
t
.
children
[
j
]
=
h
.
children
[
M
/
2
+
j
];
return
t
;
}
/**
* Returns a string representation of this B-tree (for debugging).
*
*
@return
a string representation of this B-tree.
*/
public
String
toString
()
{
return
toString
(
root
,
height
,
""
)
+
"\n"
;
}
private
String
toString
(
Node
h
,
int
ht
,
String
indent
)
{
StringBuilder
s
=
new
StringBuilder
();
Entry
[]
children
=
h
.
children
;
if
(
ht
==
0
)
{
for
(
int
j
=
0
;
j
<
h
.
m
;
j
++
)
{
s
.
append
(
indent
+
children
[
j
].
key
+
" "
+
children
[
j
].
val
+
"\n"
);
}
}
else
{
for
(
int
j
=
0
;
j
<
h
.
m
;
j
++
)
{
if
(
j
>
0
)
s
.
append
(
indent
+
“(”
+
children
[
j
].
key
+
“)\n”
);
s
.
append
(
toString
(
children
[
j
].
next
,
ht
–
1
,
indent
+
” ”
));
}
}
return
s
.
toString
();
}
// comparison functions – make Comparable instead of Key to avoid casts
private
boolean
less
(
Comparable
k1
,
Comparable
k2
)
{
return
k1
.
compareTo
(
k2
)
<
0
;
}
private
boolean
eq
(
Comparable
k1
,
Comparable
k2
)
{
return
k1
.
compareTo
(
k2
)
==
0
;
}
/**
* Unit tests the {
@code
BTree} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
BTree
<
String
,
String
>
st
=
new
BTree
<
String
,
String
>
();
st
.
put
(
“www.cs.princeton.edu”
,
“128.112.136.12”
);
st
.
put
(
“www.cs.princeton.edu”
,
“128.112.136.11”
);
st
.
put
(
“www.princeton.edu”
,
“128.112.128.15”
);
st
.
put
(
“www.yale.edu”
,
“130.132.143.21”
);
st
.
put
(
“www.simpsons.com”
,
“209.052.165.60”
);
st
.
put
(
“www.apple.com”
,
“17.112.152.32”
);
st
.
put
(
“www.amazon.com”
,
“207.171.182.16”
);
st
.
put
(
“www.ebay.com”
,
“66.135.192.87”
);
st
.
put
(
“www.cnn.com”
,
“64.236.16.20”
);
st
.
put
(
“www.google.com”
,
“216.239.41.99”
);
st
.
put
(
“www.nytimes.com”
,
“199.239.136.200”
);
st
.
put
(
“www.microsoft.com”
,
“207.126.99.140”
);
st
.
put
(
“www.dell.com”
,
“143.166.224.230”
);
st
.
put
(
“www.slashdot.org”
,
“66.35.250.151”
);
st
.
put
(
“www.espn.com”
,
“199.181.135.201”
);
st
.
put
(
“www.weather.com”
,
“63.111.66.11”
);
st
.
put
(
“www.yahoo.com”
,
“216.109.118.65”
);
StdOut
.
println
(
“cs.princeton.edu: ”
+
st
.
get
(
“www.cs.princeton.edu”
));
StdOut
.
println
(
“hardvardsucks.com: ”
+
st
.
get
(
“www.harvardsucks.com”
));
StdOut
.
println
(
“simpsons.com: ”
+
st
.
get
(
“www.simpsons.com”
));
StdOut
.
println
(
“apple.com: ”
+
st
.
get
(
“www.apple.com”
));
StdOut
.
println
(
“ebay.com: ”
+
st
.
get
(
“www.ebay.com”
));
StdOut
.
println
(
“dell.com: ”
+
st
.
get
(
“www.dell.com”
));
StdOut
.
println
();
StdOut
.
println
(
“size: ”
+
st
.
size
());
StdOut
.
println
(
“height: ”
+
st
.
height
());
StdOut
.
println
(
st
);
StdOut
.
println
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Cat.java
edu/princeton/cs/algs4/Cat.java
/******************************************************************************
* Compilation: javac Cat.java
* Execution: java Cat input0.txt input1.txt … output.txt
* Dependencies: In.java Out.java
* Data files: https://algs4.cs.princeton.edu/11model/in1.txt
* https://algs4.cs.princeton.edu/11model/in2.txt
*
* Reads in text files specified as the first command-line
* arguments, concatenates them, and writes the result to
* filename specified as the last command-line arguments.
*
* % more in1.txt
* This is
*
* % more in2.txt
* a tiny
* test.
*
* % java Cat in1.txt in2.txt out.txt
*
* % more out.txt
* This is
* a tiny
* test.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Cat} class provides a client for concatenating the results
* of several text files.
*
* For additional documentation, see Section 1.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Cat
{
// this class should not be instantiated
private
Cat
()
{
}
/**
* Reads in a sequence of text files specified as the first command-line
* arguments, concatenates them, and writes the results to the file
* specified as the last command-line argument.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
Out
out
=
new
Out
(
args
[
args
.
length
–
1
]);
for
(
int
i
=
0
;
i
<
args
.
length
-
1
;
i
++
)
{
In
in
=
new
In
(
args
[
i
]);
String
s
=
in
.
readAll
();
out
.
println
(
s
);
in
.
close
();
}
out
.
close
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/CC.java
edu/princeton/cs/algs4/CC.java
/******************************************************************************
* Compilation: javac CC.java
* Execution: java CC filename.txt
* Dependencies: Graph.java StdOut.java Queue.java
* Data files: https://algs4.cs.princeton.edu/41graph/tinyG.txt
* https://algs4.cs.princeton.edu/41graph/mediumG.txt
* https://algs4.cs.princeton.edu/41graph/largeG.txt
*
* Compute connected components using depth first search.
* Runs in O(E + V) time.
*
* % java CC tinyG.txt
* 3 components
* 0 1 2 3 4 5 6
* 7 8
* 9 10 11 12
*
* % java CC mediumG.txt
* 1 components
* 0 1 2 3 4 5 6 7 8 9 10 ...
*
* % java -Xss50m CC largeG.txt
* 1 components
* 0 1 2 3 4 5 6 7 8 9 10 ...
*
* Note: This implementation uses a recursive DFS. To avoid needing
* a potentially very large stack size, replace with a non-recurisve
* DFS ala NonrecursiveDFS.java.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
CC} class represents a data type for
* determining the connected components in an undirected graph.
* The id operation determines in which connected component
* a given vertex lies; the connected operation
* determines whether two vertices are in the same connected component;
* the count operation determines the number of connected
* components; and the size operation determines the number
* of vertices in the connect component containing a given vertex.
* The component identifier of a connected component is one of the
* vertices in the connected component: two vertices have the same component
* identifier if and only if they are in the same connected component.
*
* This implementation uses depth-first search.
* The constructor takes Θ(V + E) time,
* where V is the number of vertices and E is the
* number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the graph).
*
* For additional documentation, see
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
CC
{
private
boolean
[]
marked
;
// marked[v] = has vertex v been marked?
private
int
[]
id
;
// id[v] = id of connected component containing v
private
int
[]
size
;
// size[id] = number of vertices in given component
private
int
count
;
// number of connected components
/**
* Computes the connected components of the undirected graph {
@code
G}.
*
*
@param
G the undirected graph
*/
public
CC
(
Graph
G
)
{
marked
=
new
boolean
[
G
.
V
()];
id
=
new
int
[
G
.
V
()];
size
=
new
int
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
!
marked
[
v
])
{
dfs
(
G
,
v
);
count
++
;
}
}
}
/**
* Computes the connected components of the edge-weighted graph {
@code
G}.
*
*
@param
G the edge-weighted graph
*/
public
CC
(
EdgeWeightedGraph
G
)
{
marked
=
new
boolean
[
G
.
V
()];
id
=
new
int
[
G
.
V
()];
size
=
new
int
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
!
marked
[
v
])
{
dfs
(
G
,
v
);
count
++
;
}
}
}
// depth-first search for a Graph
private
void
dfs
(
Graph
G
,
int
v
)
{
marked
[
v
]
=
true
;
id
[
v
]
=
count
;
size
[
count
]
++
;
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
!
marked
[
w
])
{
dfs
(
G
,
w
);
}
}
}
// depth-first search for an EdgeWeightedGraph
private
void
dfs
(
EdgeWeightedGraph
G
,
int
v
)
{
marked
[
v
]
=
true
;
id
[
v
]
=
count
;
size
[
count
]
++
;
for
(
Edge
e
:
G
.
adj
(
v
))
{
int
w
=
e
.
other
(
v
);
if
(
!
marked
[
w
])
{
dfs
(
G
,
w
);
}
}
}
/**
* Returns the component id of the connected component containing vertex {
@code
v}.
*
*
@param
v the vertex
*
@return
the component id of the connected component containing vertex {
@code
v}
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
int
id
(
int
v
)
{
validateVertex
(
v
);
return
id
[
v
];
}
/**
* Returns the number of vertices in the connected component containing vertex {
@code
v}.
*
*
@param
v the vertex
*
@return
the number of vertices in the connected component containing vertex {
@code
v}
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
int
size
(
int
v
)
{
validateVertex
(
v
);
return
size
[
id
[
v
]];
}
/**
* Returns the number of connected components in the graph {
@code
G}.
*
*
@return
the number of connected components in the graph {
@code
G}
*/
public
int
count
()
{
return
count
;
}
/**
* Returns true if vertices {
@code
v} and {
@code
w} are in the same
* connected component.
*
*
@param
v one vertex
*
@param
w the other vertex
*
@return
{
@code
true} if vertices {
@code
v} and {
@code
w} are in the same
* connected component; {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*
@throws
IllegalArgumentException unless {
@code
0 <= w < V}
*/
public
boolean
connected
(
int
v
,
int
w
)
{
validateVertex
(
v
);
validateVertex
(
w
);
return
id
(
v
)
==
id
(
w
);
}
/**
* Returns true if vertices {
@code
v} and {
@code
w} are in the same
* connected component.
*
*
@param
v one vertex
*
@param
w the other vertex
*
@return
{
@code
true} if vertices {
@code
v} and {
@code
w} are in the same
* connected component; {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*
@throws
IllegalArgumentException unless {
@code
0 <= w < V}
*
@deprecated
Replaced by {
@link
#connected(int, int)}.
*/
@
Deprecated
public
boolean
areConnected
(
int
v
,
int
w
)
{
validateVertex
(
v
);
validateVertex
(
w
);
return
id
(
v
)
==
id
(
w
);
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
marked
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
CC} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
Graph
G
=
new
Graph
(
in
);
CC cc
=
new
CC
(
G
);
// number of connected components
int
m
=
cc
.
count
();
StdOut
.
println
(
m
+
” components”
);
// compute list of vertices in each connected component
Queue
<
Integer
>
[]
components
=
(
Queue
<
Integer
>
[])
new
Queue
[
m
];
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
components
[
i
]
=
new
Queue
<
Integer
>
();
}
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
components
[
cc
.
id
(
v
)].
enqueue
(
v
);
}
// print results
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
for
(
int
v
:
components
[
i
])
{
StdOut
.
print
(
v
+
" "
);
}
StdOut
.
println
();
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/ClosestPair.java
edu/princeton/cs/algs4/ClosestPair.java
/******************************************************************************
* Compilation: javac ClosestPair.java
* Execution: java ClosestPair < input.txt
* Dependencies: Point2D.java
* Data files: https://algs4.cs.princeton.edu/99hull/rs1423.txt
* https://algs4.cs.princeton.edu/99hull/kw1260.txt
*
* Given n points in the plane, find the closest pair in n log n time.
*
* Note: could speed it up by comparing square of Euclidean distances
* instead of Euclidean distances.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Arrays
;
/**
* The {
@code
ClosestPair} data type computes a closest pair of points
* in a set of n points in the plane and provides accessor methods
* for getting the closest pair of points and the distance between them.
* The distance between two points is their Euclidean distance.
*
* This implementation uses a divide-and-conquer algorithm.
* It runs in O(n log n) time in the worst case and uses
* O(n) extra space.
*
* See also {
@link
FarthestPair}.
*
* For additional documentation, see Section 9.9 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
ClosestPair
{
// closest pair of points and their Euclidean distance
private
Point2D
best1
,
best2
;
private
double
bestDistance
=
Double
.
POSITIVE_INFINITY
;
/**
* Computes the closest pair of points in the specified array of points.
*
*
@param
points the array of points
*
@throws
IllegalArgumentException if {
@code
points} is {
@code
null} or if any
* entry in {
@code
points[]} is {
@code
null}
*/
public
ClosestPair
(
Point2D
[]
points
)
{
if
(
points
==
null
)
throw
new
IllegalArgumentException
(
“constructor argument is null”
);
for
(
int
i
=
0
;
i
<
points
.
length
;
i
++
)
{
if
(
points
[
i
]
==
null
)
throw
new
IllegalArgumentException
(
"array element "
+
i
+
" is null"
);
}
int
n
=
points
.
length
;
if
(
n
<=
1
)
return
;
// sort by x-coordinate (breaking ties by y-coordinate)
Point2D
[]
pointsByX
=
new
Point2D
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
pointsByX
[
i
]
=
points
[
i
];
Arrays
.
sort
(
pointsByX
,
Point2D
.
X_ORDER
);
// check for coincident points
for
(
int
i
=
0
;
i
<
n
-
1
;
i
++
)
{
if
(
pointsByX
[
i
].
equals
(
pointsByX
[
i
+
1
]))
{
bestDistance
=
0.0
;
best1
=
pointsByX
[
i
];
best2
=
pointsByX
[
i
+
1
];
return
;
}
}
// sort by y-coordinate (but not yet sorted)
Point2D
[]
pointsByY
=
new
Point2D
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
pointsByY
[
i
]
=
pointsByX
[
i
];
// auxiliary array
Point2D
[]
aux
=
new
Point2D
[
n
];
closest
(
pointsByX
,
pointsByY
,
aux
,
0
,
n
-
1
);
}
// find closest pair of points in pointsByX[lo..hi]
// precondition: pointsByX[lo..hi] and pointsByY[lo..hi] are the same sequence of points
// precondition: pointsByX[lo..hi] sorted by x-coordinate
// postcondition: pointsByY[lo..hi] sorted by y-coordinate
private
double
closest
(
Point2D
[]
pointsByX
,
Point2D
[]
pointsByY
,
Point2D
[]
aux
,
int
lo
,
int
hi
)
{
if
(
hi
<=
lo
)
return
Double
.
POSITIVE_INFINITY
;
int
mid
=
lo
+
(
hi
-
lo
)
/
2
;
Point2D
median
=
pointsByX
[
mid
];
// compute closest pair with both endpoints in left subarray or both in right subarray
double
delta1
=
closest
(
pointsByX
,
pointsByY
,
aux
,
lo
,
mid
);
double
delta2
=
closest
(
pointsByX
,
pointsByY
,
aux
,
mid
+
1
,
hi
);
double
delta
=
Math
.
min
(
delta1
,
delta2
);
// merge back so that pointsByY[lo..hi] are sorted by y-coordinate
merge
(
pointsByY
,
aux
,
lo
,
mid
,
hi
);
// aux[0..m-1] = sequence of points closer than delta, sorted by y-coordinate
int
m
=
0
;
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
{
if
(
Math
.
abs
(
pointsByY
[
i
].
x
()
-
median
.
x
())
<
delta
)
aux
[
m
++
]
=
pointsByY
[
i
];
}
// compare each point to its neighbors with y-coordinate closer than delta
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
// a geometric packing argument shows that this loop iterates at most 7 times
for
(
int
j
=
i
+
1
;
(
j
<
m
)
&&
(
aux
[
j
].
y
()
-
aux
[
i
].
y
()
<
delta
);
j
++
)
{
double
distance
=
aux
[
i
].
distanceTo
(
aux
[
j
]);
if
(
distance
<
delta
)
{
delta
=
distance
;
if
(
distance
<
bestDistance
)
{
bestDistance
=
delta
;
best1
=
aux
[
i
];
best2
=
aux
[
j
];
// StdOut.println("better distance = " + delta + " from " + best1 + " to " + best2);
}
}
}
}
return
delta
;
}
/**
* Returns one of the points in the closest pair of points.
*
*
@return
one of the two points in the closest pair of points;
* {
@code
null} if no such point (because there are fewer than 2 points)
*/
public
Point2D
either
()
{
return
best1
;
}
/**
* Returns the other point in the closest pair of points.
*
*
@return
the other point in the closest pair of points
* {
@code
null} if no such point (because there are fewer than 2 points)
*/
public
Point2D
other
()
{
return
best2
;
}
/**
* Returns the Eucliden distance between the closest pair of points.
*
*
@return
the Euclidean distance between the closest pair of points
* {
@code
Double.POSITIVE_INFINITY} if no such pair of points
* exist (because there are fewer than 2 points)
*/
public
double
distance
()
{
return
bestDistance
;
}
// is v < w ?
private
static
boolean
less
(
Comparable
v
,
Comparable
w
)
{
return
v
.
compareTo
(
w
)
<
0
;
}
// stably merge a[lo .. mid] with a[mid+1 ..hi] using aux[lo .. hi]
// precondition: a[lo .. mid] and a[mid+1 .. hi] are sorted subarrays
private
static
void
merge
(
Comparable
[]
a
,
Comparable
[]
aux
,
int
lo
,
int
mid
,
int
hi
)
{
// copy to aux[]
for
(
int
k
=
lo
;
k
<=
hi
;
k
++
)
{
aux
[
k
]
=
a
[
k
];
}
// merge back to a[]
int
i
=
lo
,
j
=
mid
+
1
;
for
(
int
k
=
lo
;
k
<=
hi
;
k
++
)
{
if
(
i
>
mid
)
a
[
k
]
=
aux
[
j
++
];
else
if
(
j
>
hi
)
a
[
k
]
=
aux
[
i
++
];
else
if
(
less
(
aux
[
j
],
aux
[
i
]))
a
[
k
]
=
aux
[
j
++
];
else
a
[
k
]
=
aux
[
i
++
];
}
}
/**
* Unit tests the {
@code
ClosestPair} data type.
* Reads in an integer {
@code
n} and {
@code
n} points (specified by
* their x– and y-coordinates) from standard input;
* computes a closest pair of points; and prints the pair to standard
* output.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
n
=
StdIn
.
readInt
();
Point2D
[]
points
=
new
Point2D
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
double
x
=
StdIn
.
readDouble
();
double
y
=
StdIn
.
readDouble
();
points
[
i
]
=
new
Point2D
(
x
,
y
);
}
ClosestPair
closest
=
new
ClosestPair
(
points
);
StdOut
.
println
(
closest
.
distance
()
+
" from "
+
closest
.
either
()
+
" to "
+
closest
.
other
());
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/CollisionSystem.java
edu/princeton/cs/algs4/CollisionSystem.java
/******************************************************************************
* Compilation: javac CollisionSystem.java
* Execution: java CollisionSystem n (n random particles)
* java CollisionSystem < input.txt (from a file)
* Dependencies: StdDraw.java Particle.java MinPQ.java
* Data files: https://algs4.cs.princeton.edu/61event/diffusion.txt
* https://algs4.cs.princeton.edu/61event/diffusion2.txt
* https://algs4.cs.princeton.edu/61event/diffusion3.txt
* https://algs4.cs.princeton.edu/61event/brownian.txt
* https://algs4.cs.princeton.edu/61event/brownian2.txt
* https://algs4.cs.princeton.edu/61event/billiards5.txt
* https://algs4.cs.princeton.edu/61event/pendulum.txt
*
* Creates n random particles and simulates their motion according
* to the laws of elastic collisions.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
awt
.
Color
;
/**
* The {
@code
CollisionSystem} class represents a collection of particles
* moving in the unit box, according to the laws of elastic collision.
* This event-based simulation relies on a priority queue.
*
* For additional documentation,
* see Section 6.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
CollisionSystem
{
private
static
final
double
HZ
=
0.5
;
// number of redraw events per clock tick
private
MinPQ
<
Event
>
pq
;
// the priority queue
private
double
t
=
0.0
;
// simulation clock time
private
Particle
[]
particles
;
// the array of particles
/**
* Initializes a system with the specified collection of particles.
* The individual particles will be mutated during the simulation.
*
*
@param
particles the array of particles
*/
public
CollisionSystem
(
Particle
[]
particles
)
{
this
.
particles
=
particles
.
clone
();
// defensive copy
}
// updates priority queue with all new events for particle a
private
void
predict
(
Particle
a
,
double
limit
)
{
if
(
a
==
null
)
return
;
// particle-particle collisions
for
(
int
i
=
0
;
i
<
particles
.
length
;
i
++
)
{
double
dt
=
a
.
timeToHit
(
particles
[
i
]);
if
(
t
+
dt
<=
limit
)
pq
.
insert
(
new
Event
(
t
+
dt
,
a
,
particles
[
i
]));
}
// particle-wall collisions
double
dtX
=
a
.
timeToHitVerticalWall
();
double
dtY
=
a
.
timeToHitHorizontalWall
();
if
(
t
+
dtX
<=
limit
)
pq
.
insert
(
new
Event
(
t
+
dtX
,
a
,
null
));
if
(
t
+
dtY
<=
limit
)
pq
.
insert
(
new
Event
(
t
+
dtY
,
null
,
a
));
}
// redraw all particles
private
void
redraw
(
double
limit
)
{
StdDraw
.
clear
();
for
(
int
i
=
0
;
i
<
particles
.
length
;
i
++
)
{
particles
[
i
].
draw
();
}
StdDraw
.
show
();
StdDraw
.
pause
(
20
);
if
(
t
<
limit
)
{
pq
.
insert
(
new
Event
(
t
+
1.0
/
HZ
,
null
,
null
));
}
}
/**
* Simulates the system of particles for the specified amount of time.
*
*
@param
limit the amount of time
*/
public
void
simulate
(
double
limit
)
{
// initialize PQ with collision events and redraw event
pq
=
new
MinPQ
<
Event
>
();
for
(
int
i
=
0
;
i
<
particles
.
length
;
i
++
)
{
predict
(
particles
[
i
],
limit
);
}
pq
.
insert
(
new
Event
(
0
,
null
,
null
));
// redraw event
// the main event-driven simulation loop
while
(
!
pq
.
isEmpty
())
{
// get impending event, discard if invalidated
Event
e
=
pq
.
delMin
();
if
(
!
e
.
isValid
())
continue
;
Particle
a
=
e
.
a
;
Particle
b
=
e
.
b
;
// physical collision, so update positions, and then simulation clock
for
(
int
i
=
0
;
i
<
particles
.
length
;
i
++
)
particles
[
i
].
move
(
e
.
time
-
t
);
t
=
e
.
time
;
// process event
if
(
a
!=
null
&&
b
!=
null
)
a
.
bounceOff
(
b
);
// particle-particle collision
else
if
(
a
!=
null
&&
b
==
null
)
a
.
bounceOffVerticalWall
();
// particle-wall collision
else
if
(
a
==
null
&&
b
!=
null
)
b
.
bounceOffHorizontalWall
();
// particle-wall collision
else
if
(
a
==
null
&&
b
==
null
)
redraw
(
limit
);
// redraw event
// update the priority queue with new collisions involving a or b
predict
(
a
,
limit
);
predict
(
b
,
limit
);
}
}
/***************************************************************************
* An event during a particle collision simulation. Each event contains
* the time at which it will occur (assuming no supervening actions)
* and the particles a and b involved.
*
* - a and b both null: redraw event
* - a null, b not null: collision with vertical wall
* - a not null, b null: collision with horizontal wall
* - a and b both not null: binary collision between a and b
*
***************************************************************************/
private
static
class
Event
implements
Comparable
<
Event
>
{
private
final
double
time
;
// time that event is scheduled to occur
private
final
Particle
a
,
b
;
// particles involved in event, possibly null
private
final
int
countA
,
countB
;
// collision counts at event creation
// create a new event to occur at time t involving a and b
public
Event
(
double
t
,
Particle
a
,
Particle
b
)
{
this
.
time
=
t
;
this
.
a
=
a
;
this
.
b
=
b
;
if
(
a
!=
null
)
countA
=
a
.
count
();
else
countA
=
–
1
;
if
(
b
!=
null
)
countB
=
b
.
count
();
else
countB
=
–
1
;
}
// compare times when two events will occur
public
int
compareTo
(
Event
that
)
{
return
Double
.
compare
(
this
.
time
,
that
.
time
);
}
// has any collision occurred between when event was created and now?
public
boolean
isValid
()
{
if
(
a
!=
null
&&
a
.
count
()
!=
countA
)
return
false
;
if
(
b
!=
null
&&
b
.
count
()
!=
countB
)
return
false
;
return
true
;
}
}
/**
* Unit tests the {
@code
CollisionSystem} data type.
* Reads in the particle collision system from a standard input
* (or generates {
@code
N} random particles if a command-line integer
* is specified); simulates the system.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
StdDraw
.
setCanvasSize
(
600
,
600
);
// enable double buffering
StdDraw
.
enableDoubleBuffering
();
// the array of particles
Particle
[]
particles
;
// create n random particles
if
(
args
.
length
==
1
)
{
int
n
=
Integer
.
parseInt
(
args
[
0
]);
particles
=
new
Particle
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
particles
[
i
]
=
new
Particle
();
}
// or read from standard input
else
{
int
n
=
StdIn
.
readInt
();
particles
=
new
Particle
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
double
rx
=
StdIn
.
readDouble
();
double
ry
=
StdIn
.
readDouble
();
double
vx
=
StdIn
.
readDouble
();
double
vy
=
StdIn
.
readDouble
();
double
radius
=
StdIn
.
readDouble
();
double
mass
=
StdIn
.
readDouble
();
int
r
=
StdIn
.
readInt
();
int
g
=
StdIn
.
readInt
();
int
b
=
StdIn
.
readInt
();
Color
color
=
new
Color
(
r
,
g
,
b
);
particles
[
i
]
=
new
Particle
(
rx
,
ry
,
vx
,
vy
,
radius
,
mass
,
color
);
}
}
// create collision system and simulate
CollisionSystem
system
=
new
CollisionSystem
(
particles
);
system
.
simulate
(
10000
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Complex.java
edu/princeton/cs/algs4/Complex.java
/******************************************************************************
* Compilation: javac Complex.java
* Execution: java Complex
* Dependencies: StdOut.java
*
* Data type for complex numbers.
*
* The data type is "immutable" so once you create and initialize
* a Complex object, you cannot change it. The "final" keyword
* when declaring re and im enforces this rule, making it a
* compile-time error to change the .re or .im fields after
* they've been initialized.
*
* % java Complex
* a = 5.0 + 6.0i
* b = -3.0 + 4.0i
* Re(a) = 5.0
* Im(a) = 6.0
* b + a = 2.0 + 10.0i
* a - b = 8.0 + 2.0i
* a * b = -39.0 + 2.0i
* b * a = -39.0 + 2.0i
* a / b = 0.36 - 1.52i
* (a / b) * b = 5.0 + 6.0i
* conj(a) = 5.0 - 6.0i
* |a| = 7.810249675906654
* tan(a) = -6.685231390246571E-6 + 1.0000103108981198i
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Complex} class represents a complex number.
* Complex numbers are immutable: their values cannot be changed after they
* are created.
* It includes methods for addition, subtraction, multiplication, division,
* conjugation, and other common functions on complex numbers.
*
* For additional documentation, see Section 9.9 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Complex
{
private
final
double
re
;
// the real part
private
final
double
im
;
// the imaginary part
/**
* Initializes a complex number from the specified real and imaginary parts.
*
*
@param
real the real part
*
@param
imag the imaginary part
*/
public
Complex
(
double
real
,
double
imag
)
{
re
=
real
;
im
=
imag
;
}
/**
* Returns a string representation of this complex number.
*
*
@return
a string representation of this complex number,
* of the form 34 – 56i.
*/
public
String
toString
()
{
if
(
im
==
0
)
return
re
+
“”
;
if
(
re
==
0
)
return
im
+
“i”
;
if
(
im
<
0
)
return
re
+
" - "
+
(
-
im
)
+
"i"
;
return
re
+
" + "
+
im
+
"i"
;
}
/**
* Returns the absolute value of this complex number.
* This quantity is also known as the modulus or magnitude.
*
*
@return
the absolute value of this complex number
*/
public
double
abs
()
{
return
Math
.
hypot
(
re
,
im
);
}
/**
* Returns the phase of this complex number.
* This quantity is also known as the angle or argument.
*
*
@return
the phase of this complex number, a real number between -pi and pi
*/
public
double
phase
()
{
return
Math
.
atan2
(
im
,
re
);
}
/**
* Returns the sum of this complex number and the specified complex number.
*
*
@param
that the other complex number
*
@return
the complex number whose value is {
@code
(this + that)}
*/
public
Complex
plus
(
Complex
that
)
{
double
real
=
this
.
re
+
that
.
re
;
double
imag
=
this
.
im
+
that
.
im
;
return
new
Complex
(
real
,
imag
);
}
/**
* Returns the result of subtracting the specified complex number from
* this complex number.
*
*
@param
that the other complex number
*
@return
the complex number whose value is {
@code
(this – that)}
*/
public
Complex
minus
(
Complex
that
)
{
double
real
=
this
.
re
–
that
.
re
;
double
imag
=
this
.
im
–
that
.
im
;
return
new
Complex
(
real
,
imag
);
}
/**
* Returns the product of this complex number and the specified complex number.
*
*
@param
that the other complex number
*
@return
the complex number whose value is {
@code
(this * that)}
*/
public
Complex
times
(
Complex
that
)
{
double
real
=
this
.
re
*
that
.
re
–
this
.
im
*
that
.
im
;
double
imag
=
this
.
re
*
that
.
im
+
this
.
im
*
that
.
re
;
return
new
Complex
(
real
,
imag
);
}
/**
* Returns the product of this complex number and the specified scalar.
*
*
@param
alpha the scalar
*
@return
the complex number whose value is {
@code
(alpha * this)}
*/
public
Complex
scale
(
double
alpha
)
{
return
new
Complex
(
alpha
*
re
,
alpha
*
im
);
}
/**
* Returns the product of this complex number and the specified scalar.
*
*
@param
alpha the scalar
*
@return
the complex number whose value is {
@code
(alpha * this)}
*
@deprecated
Replaced by {
@link
#scale(double)}.
*/
@
Deprecated
public
Complex
times
(
double
alpha
)
{
return
new
Complex
(
alpha
*
re
,
alpha
*
im
);
}
/**
* Returns the complex conjugate of this complex number.
*
*
@return
the complex conjugate of this complex number
*/
public
Complex
conjugate
()
{
return
new
Complex
(
re
,
–
im
);
}
/**
* Returns the reciprocal of this complex number.
*
*
@return
the complex number whose value is {
@code
(1 / this)}
*/
public
Complex
reciprocal
()
{
double
scale
=
re
*
re
+
im
*
im
;
return
new
Complex
(
re
/
scale
,
–
im
/
scale
);
}
/**
* Returns the real part of this complex number.
*
*
@return
the real part of this complex number
*/
public
double
re
()
{
return
re
;
}
/**
* Returns the imaginary part of this complex number.
*
*
@return
the imaginary part of this complex number
*/
public
double
im
()
{
return
im
;
}
/**
* Returns the result of dividing the specified complex number into
* this complex number.
*
*
@param
that the other complex number
*
@return
the complex number whose value is {
@code
(this / that)}
*/
public
Complex
divides
(
Complex
that
)
{
return
this
.
times
(
that
.
reciprocal
());
}
/**
* Returns the complex exponential of this complex number.
*
*
@return
the complex exponential of this complex number
*/
public
Complex
exp
()
{
return
new
Complex
(
Math
.
exp
(
re
)
*
Math
.
cos
(
im
),
Math
.
exp
(
re
)
*
Math
.
sin
(
im
));
}
/**
* Returns the complex sine of this complex number.
*
*
@return
the complex sine of this complex number
*/
public
Complex
sin
()
{
return
new
Complex
(
Math
.
sin
(
re
)
*
Math
.
cosh
(
im
),
Math
.
cos
(
re
)
*
Math
.
sinh
(
im
));
}
/**
* Returns the complex cosine of this complex number.
*
*
@return
the complex cosine of this complex number
*/
public
Complex
cos
()
{
return
new
Complex
(
Math
.
cos
(
re
)
*
Math
.
cosh
(
im
),
–
Math
.
sin
(
re
)
*
Math
.
sinh
(
im
));
}
/**
* Returns the complex tangent of this complex number.
*
*
@return
the complex tangent of this complex number
*/
public
Complex
tan
()
{
return
sin
().
divides
(
cos
());
}
/**
* Unit tests the {
@code
Complex} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
Complex
a
=
new
Complex
(
5.0
,
6.0
);
Complex
b
=
new
Complex
(
–
3.0
,
4.0
);
StdOut
.
println
(
“a = ”
+
a
);
StdOut
.
println
(
“b = ”
+
b
);
StdOut
.
println
(
“Re(a) = ”
+
a
.
re
());
StdOut
.
println
(
“Im(a) = ”
+
a
.
im
());
StdOut
.
println
(
“b + a = ”
+
b
.
plus
(
a
));
StdOut
.
println
(
“a – b = ”
+
a
.
minus
(
b
));
StdOut
.
println
(
“a * b = ”
+
a
.
times
(
b
));
StdOut
.
println
(
“b * a = ”
+
b
.
times
(
a
));
StdOut
.
println
(
“a / b = ”
+
a
.
divides
(
b
));
StdOut
.
println
(
“(a / b) * b = ”
+
a
.
divides
(
b
).
times
(
b
));
StdOut
.
println
(
“conj(a) = ”
+
a
.
conjugate
());
StdOut
.
println
(
“|a| = ”
+
a
.
abs
());
StdOut
.
println
(
“tan(a) = ”
+
a
.
tan
());
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Counter.java
edu/princeton/cs/algs4/Counter.java
/******************************************************************************
* Compilation: javac Counter.java
* Execution: java Counter n trials
* Dependencies: StdRandom.java StdOut.java
*
* A mutable data type for an integer counter.
*
* The test clients create n counters and performs trials increment
* operations on random counters.
*
* java Counter 6 600000
* 100140 counter0
* 100273 counter1
* 99848 counter2
* 100129 counter3
* 99973 counter4
* 99637 counter5
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Counter} class is a mutable data type to encapsulate a counter.
*
* For additional documentation,
* see Section 1.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Counter
implements
Comparable
<
Counter
>
{
private
final
String
name
;
// counter name
private
int
count
=
0
;
// current value
/**
* Initializes a new counter starting at 0, with the given id.
*
*
@param
id the name of the counter
*/
public
Counter
(
String
id
)
{
name
=
id
;
}
/**
* Increments the counter by 1.
*/
public
void
increment
()
{
count
++
;
}
/**
* Returns the current value of this counter.
*
*
@return
the current value of this counter
*/
public
int
tally
()
{
return
count
;
}
/**
* Returns a string representation of this counter.
*
*
@return
a string representation of this counter
*/
public
String
toString
()
{
return
count
+
” ”
+
name
;
}
/**
* Compares this counter to the specified counter.
*
*
@param
that the other counter
*
@return
{
@code
0} if the value of this counter equals
* the value of that counter; a negative integer if
* the value of this counter is less than the value of
* that counter; and a positive integer if the value
* of this counter is greater than the value of that
* counter
*/
@
Override
public
int
compareTo
(
Counter
that
)
{
if
(
this
.
count
<
that
.
count
)
return
-
1
;
else
if
(
this
.
count
>
that
.
count
)
return
+
1
;
else
return
0
;
}
/**
* Reads two command-line integers n and trials; creates n counters;
* increments trials counters at random; and prints results.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
n
=
Integer
.
parseInt
(
args
[
0
]);
int
trials
=
Integer
.
parseInt
(
args
[
1
]);
// create n counters
Counter
[]
hits
=
new
Counter
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
hits
[
i
]
=
new
Counter
(
"counter"
+
i
);
}
// increment trials counters at random
for
(
int
t
=
0
;
t
<
trials
;
t
++
)
{
hits
[
StdRandom
.
uniform
(
n
)].
increment
();
}
// print results
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
StdOut
.
println
(
hits
[
i
]);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Count.java
edu/princeton/cs/algs4/Count.java
/******************************************************************************
* Compilation: javac Count.java
* Execution: java Count alpha < input.txt
* Dependencies: Alphabet.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/50strings/abra.txt
* https://algs4.cs.princeton.edu/50strings/pi.txt
*
* Create an alphabet specified on the command line, read in a
* sequence of characters over that alphabet (ignoring characters
* not in the alphabet), computes the frequency of occurrence of
* each character, and print out the results.
*
* % java Count ABCDR < abra.txt
* A 5
* B 2
* C 1
* D 1
* R 2
*
* % java Count 0123456789 < pi.txt
* 0 99959
* 1 99757
* 2 100026
* 3 100230
* 4 100230
* 5 100359
* 6 99548
* 7 99800
* 8 99985
* 9 100106
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Count} class provides an {
@link
Alphabet} client for reading
* in a piece of text and computing the frequency of occurrence of each
* character over a given alphabet.
*
* For additional documentation,
* see Section 5.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Count
{
// Do not instantiate.
private
Count
()
{
}
/**
* Reads in text from standard input; calculates the frequency of
* occurrence of each character over the alphabet specified as a
* commmand-line argument; and prints the frequencies to standard
* output.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
Alphabet
alphabet
=
new
Alphabet
(
args
[
0
]);
final
int
R
=
alphabet
.
radix
();
int
[]
count
=
new
int
[
R
];
while
(
StdIn
.
hasNextChar
())
{
char
c
=
StdIn
.
readChar
();
if
(
alphabet
.
contains
(
c
))
count
[
alphabet
.
toIndex
(
c
)]
++
;
}
for
(
int
c
=
0
;
c
<
R
;
c
++
)
StdOut
.
println
(
alphabet
.
toChar
(
c
)
+
" "
+
count
[
c
]);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/CPM.java
edu/princeton/cs/algs4/CPM.java
/******************************************************************************
* Compilation: javac CPM.java
* Execution: java CPM < input.txt
* Dependencies: EdgeWeightedDigraph.java AcyclicDigraphLP.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/44sp/jobsPC.txt
*
* Critical path method.
*
* % java CPM < jobsPC.txt
* job start finish
* --------------------
* 0 0.0 41.0
* 1 41.0 92.0
* 2 123.0 173.0
* 3 91.0 127.0
* 4 70.0 108.0
* 5 0.0 45.0
* 6 70.0 91.0
* 7 41.0 73.0
* 8 91.0 123.0
* 9 41.0 70.0
* Finish time: 173.0
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
CPM} class provides a client that solves the
* parallel precedence-constrained job scheduling problem
* via the critical path method. It reduces the problem
* to the longest-paths problem in edge-weighted DAGs.
* It builds an edge-weighted digraph (which must be a DAG)
* from the job-scheduling problem specification,
* finds the longest-paths tree, and computes the longest-paths
* lengths (which are precisely the start times for each job).
*
* This implementation uses {
@link
AcyclicLP} to find a longest
* path in a DAG.
* The program takes Θ(V + E) time in
* the worst case, where V is the number of jobs and
* E is the number of precedence constraints.
*
* For additional documentation,
* see Section 4.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
CPM
{
// this class cannot be instantiated
private
CPM
()
{
}
/**
* Reads the precedence constraints from standard input
* and prints a feasible schedule to standard output.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// number of jobs
int
n
=
StdIn
.
readInt
();
// source and sink
int
source
=
2
*
n
;
int
sink
=
2
*
n
+
1
;
// build network
EdgeWeightedDigraph
G
=
new
EdgeWeightedDigraph
(
2
*
n
+
2
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
double
duration
=
StdIn
.
readDouble
();
G
.
addEdge
(
new
DirectedEdge
(
source
,
i
,
0.0
));
G
.
addEdge
(
new
DirectedEdge
(
i
+
n
,
sink
,
0.0
));
G
.
addEdge
(
new
DirectedEdge
(
i
,
i
+
n
,
duration
));
// precedence constraints
int
m
=
StdIn
.
readInt
();
for
(
int
j
=
0
;
j
<
m
;
j
++
)
{
int
precedent
=
StdIn
.
readInt
();
G
.
addEdge
(
new
DirectedEdge
(
n
+
i
,
precedent
,
0.0
));
}
}
// compute longest path
AcyclicLP
lp
=
new
AcyclicLP
(
G
,
source
);
// print results
StdOut
.
println
(
" job start finish"
);
StdOut
.
println
(
"--------------------"
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
StdOut
.
printf
(
"%4d %7.1f %7.1f\n"
,
i
,
lp
.
distTo
(
i
),
lp
.
distTo
(
i
+
n
));
}
StdOut
.
printf
(
"Finish time: %7.1f\n"
,
lp
.
distTo
(
sink
));
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Cycle.java
edu/princeton/cs/algs4/Cycle.java
/******************************************************************************
* Compilation: javac Cycle.java
* Execution: java Cycle filename.txt
* Dependencies: Graph.java Stack.java In.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/41graph/tinyG.txt
* https://algs4.cs.princeton.edu/41graph/mediumG.txt
* https://algs4.cs.princeton.edu/41graph/largeG.txt
*
* Identifies a cycle.
* Runs in O(E + V) time.
*
* % java Cycle tinyG.txt
* 3 4 5 3
*
* % java Cycle mediumG.txt
* 15 0 225 15
*
* % java Cycle largeG.txt
* 996673 762 840164 4619 785187 194717 996673
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Cycle} class represents a data type for
* determining whether an undirected graph has a simple cycle.
* The hasCycle operation determines whether the graph has
* a cycle and, if so, the cycle operation returns one.
*
* This implementation uses depth-first search.
* The constructor takes Θ(V + E) time in the
* worst case, where V is the number of vertices and
* E is the number of edges.
* (The depth-first search part takes only O(V) time;
* however, checking for self-loops and parallel edges takes
* Θ(V + E) time in the worst case.)
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the graph).
*
*
* For additional documentation, see
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Cycle
{
private
boolean
[]
marked
;
private
int
[]
edgeTo
;
private
Stack
<
Integer
>
cycle
;
/**
* Determines whether the undirected graph {
@code
G} has a cycle and,
* if so, finds such a cycle.
*
*
@param
G the undirected graph
*/
public
Cycle
(
Graph
G
)
{
if
(
hasSelfLoop
(
G
))
return
;
if
(
hasParallelEdges
(
G
))
return
;
marked
=
new
boolean
[
G
.
V
()];
edgeTo
=
new
int
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
!
marked
[
v
])
dfs
(
G
,
-
1
,
v
);
}
// does this graph have a self loop?
// side effect: initialize cycle to be self loop
private
boolean
hasSelfLoop
(
Graph
G
)
{
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
v
==
w
)
{
cycle
=
new
Stack
<
Integer
>
();
cycle
.
push
(
v
);
cycle
.
push
(
v
);
return
true
;
}
}
}
return
false
;
}
// does this graph have two parallel edges?
// side effect: initialize cycle to be two parallel edges
private
boolean
hasParallelEdges
(
Graph
G
)
{
marked
=
new
boolean
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
// check for parallel edges incident to v
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
marked
[
w
])
{
cycle
=
new
Stack
<
Integer
>
();
cycle
.
push
(
v
);
cycle
.
push
(
w
);
cycle
.
push
(
v
);
return
true
;
}
marked
[
w
]
=
true
;
}
// reset so marked[v] = false for all v
for
(
int
w
:
G
.
adj
(
v
))
{
marked
[
w
]
=
false
;
}
}
return
false
;
}
/**
* Returns true if the graph {
@code
G} has a cycle.
*
*
@return
{
@code
true} if the graph has a cycle; {
@code
false} otherwise
*/
public
boolean
hasCycle
()
{
return
cycle
!=
null
;
}
/**
* Returns a cycle in the graph {
@code
G}.
*
@return
a cycle if the graph {
@code
G} has a cycle,
* and {
@code
null} otherwise
*/
public
Iterable
<
Integer
>
cycle
()
{
return
cycle
;
}
private
void
dfs
(
Graph
G
,
int
u
,
int
v
)
{
marked
[
v
]
=
true
;
for
(
int
w
:
G
.
adj
(
v
))
{
// short circuit if cycle already found
if
(
cycle
!=
null
)
return
;
if
(
!
marked
[
w
])
{
edgeTo
[
w
]
=
v
;
dfs
(
G
,
v
,
w
);
}
// check for cycle (but disregard reverse of edge leading to v)
else
if
(
w
!=
u
)
{
cycle
=
new
Stack
<
Integer
>
();
for
(
int
x
=
v
;
x
!=
w
;
x
=
edgeTo
[
x
])
{
cycle
.
push
(
x
);
}
cycle
.
push
(
w
);
cycle
.
push
(
v
);
}
}
}
/**
* Unit tests the {
@code
Cycle} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
Graph
G
=
new
Graph
(
in
);
Cycle
finder
=
new
Cycle
(
G
);
if
(
finder
.
hasCycle
())
{
for
(
int
v
:
finder
.
cycle
())
{
StdOut
.
print
(
v
+
” ”
);
}
StdOut
.
println
();
}
else
{
StdOut
.
println
(
“Graph is acyclic”
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Date.java
edu/princeton/cs/algs4/Date.java
/******************************************************************************
* Compilation: javac Date.java
* Execution: java Date
* Dependencies: StdOut.java
*
* An immutable data type for dates.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Date} class is an immutable data type to encapsulate a
* date (day, month, and year).
*
* For additional documentation,
* see Section 1.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Date
implements
Comparable
<
Date
>
{
private
static
final
int
[]
DAYS
=
{
0
,
31
,
29
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
};
private
final
int
month
;
// month (between 1 and 12)
private
final
int
day
;
// day (between 1 and DAYS[month]
private
final
int
year
;
// year
/**
* Initializes a new date from the month, day, and year.
*
@param
month the month (between 1 and 12)
*
@param
day the day (between 1 and 28-31, depending on the month)
*
@param
year the year
*
@throws
IllegalArgumentException if this date is invalid
*/
public
Date
(
int
month
,
int
day
,
int
year
)
{
if
(
!
isValid
(
month
,
day
,
year
))
throw
new
IllegalArgumentException
(
“Invalid date”
);
this
.
month
=
month
;
this
.
day
=
day
;
this
.
year
=
year
;
}
/**
* Initializes new date specified as a string in form MM/DD/YYYY.
*
@param
date the string representation of this date
*
@throws
IllegalArgumentException if this date is invalid
*/
public
Date
(
String
date
)
{
String
[]
fields
=
date
.
split
(
“/”
);
if
(
fields
.
length
!=
3
)
{
throw
new
IllegalArgumentException
(
“Invalid date”
);
}
month
=
Integer
.
parseInt
(
fields
[
0
]);
day
=
Integer
.
parseInt
(
fields
[
1
]);
year
=
Integer
.
parseInt
(
fields
[
2
]);
if
(
!
isValid
(
month
,
day
,
year
))
throw
new
IllegalArgumentException
(
“Invalid date”
);
}
/**
* Return the month.
*
@return
the month (an integer between 1 and 12)
*/
public
int
month
()
{
return
month
;
}
/**
* Returns the day.
*
@return
the day (an integer between 1 and 31)
*/
public
int
day
()
{
return
day
;
}
/**
* Returns the year.
*
@return
the year
*/
public
int
year
()
{
return
year
;
}
// is the given date valid?
private
static
boolean
isValid
(
int
m
,
int
d
,
int
y
)
{
if
(
m
<
1
||
m
>
12
)
return
false
;
if
(
d
<
1
||
d
>
DAYS
[
m
])
return
false
;
if
(
m
==
2
&&
d
==
29
&&
!
isLeapYear
(
y
))
return
false
;
return
true
;
}
// is y a leap year?
private
static
boolean
isLeapYear
(
int
y
)
{
if
(
y
%
400
==
0
)
return
true
;
if
(
y
%
100
==
0
)
return
false
;
return
y
%
4
==
0
;
}
/**
* Returns the next date in the calendar.
*
*
@return
a date that represents the next day after this day
*/
public
Date
next
()
{
if
(
isValid
(
month
,
day
+
1
,
year
))
return
new
Date
(
month
,
day
+
1
,
year
);
else
if
(
isValid
(
month
+
1
,
1
,
year
))
return
new
Date
(
month
+
1
,
1
,
year
);
else
return
new
Date
(
1
,
1
,
year
+
1
);
}
/**
* Compares two dates chronologically.
*
*
@param
that the other date
*
@return
{
@code
true} if this date is after that date; {
@code
false} otherwise
*/
public
boolean
isAfter
(
Date
that
)
{
return
compareTo
(
that
)
>
0
;
}
/**
* Compares two dates chronologically.
*
*
@param
that the other date
*
@return
{
@code
true} if this date is before that date; {
@code
false} otherwise
*/
public
boolean
isBefore
(
Date
that
)
{
return
compareTo
(
that
)
<
0
;
}
/**
* Compares two dates chronologically.
*
*
@return
the value {
@code
0} if the argument date is equal to this date;
* a negative integer if this date is chronologically less than
* the argument date; and a positive ineger if this date is chronologically
* after the argument date
*/
@
Override
public
int
compareTo
(
Date
that
)
{
if
(
this
.
year
<
that
.
year
)
return
-
1
;
if
(
this
.
year
>
that
.
year
)
return
+
1
;
if
(
this
.
month
<
that
.
month
)
return
-
1
;
if
(
this
.
month
>
that
.
month
)
return
+
1
;
if
(
this
.
day
<
that
.
day
)
return
-
1
;
if
(
this
.
day
>
that
.
day
)
return
+
1
;
return
0
;
}
/**
* Returns a string representation of this date.
*
*
@return
the string representation in the format MM/DD/YYYY
*/
@
Override
public
String
toString
()
{
return
month
+
“/”
+
day
+
“/”
+
year
;
}
/**
* Compares this date to the specified date.
*
*
@param
other the other date
*
@return
{
@code
true} if this date equals {
@code
other}; {
@code
false} otherwise
*/
@
Override
public
boolean
equals
(
Object
other
)
{
if
(
other
==
this
)
return
true
;
if
(
other
==
null
)
return
false
;
if
(
other
.
getClass
()
!=
this
.
getClass
())
return
false
;
Date
that
=
(
Date
)
other
;
return
(
this
.
month
==
that
.
month
)
&&
(
this
.
day
==
that
.
day
)
&&
(
this
.
year
==
that
.
year
);
}
/**
* Returns an integer hash code for this date.
*
*
@return
an integer hash code for this date
*/
@
Override
public
int
hashCode
()
{
return
day
+
31
*
month
+
31
*
12
*
year
;
}
/**
* Unit tests the {
@code
Date} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
Date
today
=
new
Date
(
2
,
25
,
2004
);
StdOut
.
println
(
today
);
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
today
=
today
.
next
();
StdOut
.
println
(
today
);
}
StdOut
.
println
(
today
.
isAfter
(
today
.
next
()));
StdOut
.
println
(
today
.
isAfter
(
today
));
StdOut
.
println
(
today
.
next
().
isAfter
(
today
));
Date
birthday
=
new
Date
(
10
,
16
,
1971
);
StdOut
.
println
(
birthday
);
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
birthday
=
birthday
.
next
();
StdOut
.
println
(
birthday
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/DeDup.java
edu/princeton/cs/algs4/DeDup.java
/******************************************************************************
* Compilation: javac DeDup.java
* Execution: java DeDup < input.txt
* Dependencies: SET StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/35applications/tinyTale.txt
*
* Read in a list of words from standard input and print out
* each word, removing any duplicates.
*
* % more tinyTale.txt
* it was the best of times it was the worst of times
* it was the age of wisdom it was the age of foolishness
* it was the epoch of belief it was the epoch of incredulity
* it was the season of light it was the season of darkness
* it was the spring of hope it was the winter of despair
*
* % java DeDup < tinyTale.txt
* it
* was
* the
* best
* of
* times
* worst
* age
* wisdom
* ...
* winter
* despair
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
DeDup} class provides a client for reading in a sequence of
* words from standard input and printing each word, removing any duplicates.
* It is useful as a test client for various symbol table implementations.
*
* For additional documentation, see Section 3.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
DeDup
{
// Do not instantiate.
private
DeDup
()
{
}
public
static
void
main
(
String
[]
args
)
{
SET
<
String
>
set
=
new
SET
<
String
>
();
// read in strings and add to set
while
(
!
StdIn
.
isEmpty
())
{
String
key
=
StdIn
.
readString
();
if
(
!
set
.
contains
(
key
))
{
set
.
add
(
key
);
StdOut
.
println
(
key
);
}
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/DegreesOfSeparation.java
edu/princeton/cs/algs4/DegreesOfSeparation.java
/******************************************************************************
* Compilation: javac DegreesOfSeparation.java
* Execution: java DegreesOfSeparation filename delimiter source
* Dependencies: SymbolGraph.java Graph.java BreadthFirstPaths.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/41graph/routes.txt
* https://algs4.cs.princeton.edu/41graph/movies.txt
*
*
* % java DegreesOfSeparation routes.txt ” ” “JFK”
* LAS
* JFK
* ORD
* DEN
* LAS
* DFW
* JFK
* ORD
* DFW
* EWR
* Not in database.
*
* % java DegreesOfSeparation movies.txt “/” “Bacon, Kevin”
* Kidman, Nicole
* Bacon, Kevin
* Woodsman, The (2004)
* Grier, David Alan
* Bewitched (2005)
* Kidman, Nicole
* Grant, Cary
* Bacon, Kevin
* Planes, Trains & Automobiles (1987)
* Martin, Steve (I)
* Dead Men Don’t Wear Plaid (1982)
* Grant, Cary
*
* % java DegreesOfSeparation movies.txt “/” “Animal House (1978)”
* Titanic (1997)
* Animal House (1978)
* Allen, Karen (I)
* Raiders of the Lost Ark (1981)
* Taylor, Rocky (I)
* Titanic (1997)
* To Catch a Thief (1955)
* Animal House (1978)
* Vernon, John (I)
* Topaz (1969)
* Hitchcock, Alfred (I)
* To Catch a Thief (1955)
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
DegreesOfSeparation} class provides a client for finding
* the degree of separation between one distinguished individual and
* every other individual in a social network.
* As an example, if the social network consists of actors in which
* two actors are connected by a link if they appeared in the same movie,
* and Kevin Bacon is the distinguished individual, then the client
* computes the Kevin Bacon number of every actor in the network.
*
* The running time is proportional to the number of individuals and
* connections in the network. If the connections are given implicitly,
* as in the movie network example (where every two actors are connected
* if they appear in the same movie), the efficiency of the algorithm
* is improved by allowing both movie and actor vertices and connecting
* each movie to all of the actors that appear in that movie.
*
* For additional documentation,
* see Section 4.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
DegreesOfSeparation
{
// this class cannot be instantiated
private
DegreesOfSeparation
()
{
}
/**
* Reads in a social network from a file, and then repeatedly reads in
* individuals from standard input and prints out their degrees of
* separation.
* Takes three command-line arguments: the name of a file,
* a delimiter, and the name of the distinguished individual.
* Each line in the file contains the name of a vertex, followed by a
* list of the names of the vertices adjacent to that vertex,
* separated by the delimiter.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
filename
=
args
[
0
];
String
delimiter
=
args
[
1
];
String
source
=
args
[
2
];
// StdOut.println(“Source: ” + source);
SymbolGraph
sg
=
new
SymbolGraph
(
filename
,
delimiter
);
Graph
G
=
sg
.
graph
();
if
(
!
sg
.
contains
(
source
))
{
StdOut
.
println
(
source
+
” not in database.”
);
return
;
}
int
s
=
sg
.
indexOf
(
source
);
BreadthFirstPaths
bfs
=
new
BreadthFirstPaths
(
G
,
s
);
while
(
!
StdIn
.
isEmpty
())
{
String
sink
=
StdIn
.
readLine
();
if
(
sg
.
contains
(
sink
))
{
int
t
=
sg
.
indexOf
(
sink
);
if
(
bfs
.
hasPathTo
(
t
))
{
for
(
int
v
:
bfs
.
pathTo
(
t
))
{
StdOut
.
println
(
” ”
+
sg
.
nameOf
(
v
));
}
}
else
{
StdOut
.
println
(
“Not connected”
);
}
}
else
{
StdOut
.
println
(
” Not in database.”
);
}
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/DepthFirstDirectedPaths.java
edu/princeton/cs/algs4/DepthFirstDirectedPaths.java
/******************************************************************************
* Compilation: javac DepthFirstDirectedPaths.java
* Execution: java DepthFirstDirectedPaths digraph.txt s
* Dependencies: Digraph.java Stack.java
* Data files: https://algs4.cs.princeton.edu/42digraph/tinyDG.txt
* https://algs4.cs.princeton.edu/42digraph/mediumDG.txt
* https://algs4.cs.princeton.edu/42digraph/largeDG.txt
*
* Determine reachability in a digraph from a given vertex using
* depth-first search.
* Runs in O(E + V) time.
*
* % java DepthFirstDirectedPaths tinyDG.txt 3
* 3 to 0: 3-5-4-2-0
* 3 to 1: 3-5-4-2-0-1
* 3 to 2: 3-5-4-2
* 3 to 3: 3
* 3 to 4: 3-5-4
* 3 to 5: 3-5
* 3 to 6: not connected
* 3 to 7: not connected
* 3 to 8: not connected
* 3 to 9: not connected
* 3 to 10: not connected
* 3 to 11: not connected
* 3 to 12: not connected
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
DepthFirstDirectedPaths} class represents a data type for
* finding directed paths from a source vertex s to every
* other vertex in the digraph.
*
* This implementation uses depth-first search.
* The constructor takes Θ(V + E) time in the
* worst case, where V is the number of vertices and E
* is the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the digraph).
*
* See {
@link
DepthFirstDirectedPaths} for a nonrecursive implementation.
* For additional documentation,
* see Section 4.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
DepthFirstDirectedPaths
{
private
boolean
[]
marked
;
// marked[v] = true iff v is reachable from s
private
int
[]
edgeTo
;
// edgeTo[v] = last edge on path from s to v
private
final
int
s
;
// source vertex
/**
* Computes a directed path from {
@code
s} to every other vertex in digraph {
@code
G}.
*
@param
G the digraph
*
@param
s the source vertex
*
@throws
IllegalArgumentException unless {
@code
0 <= s < V}
*/
public
DepthFirstDirectedPaths
(
Digraph
G
,
int
s
)
{
marked
=
new
boolean
[
G
.
V
()];
edgeTo
=
new
int
[
G
.
V
()];
this
.
s
=
s
;
validateVertex
(
s
);
dfs
(
G
,
s
);
}
private
void
dfs
(
Digraph
G
,
int
v
)
{
marked
[
v
]
=
true
;
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
!
marked
[
w
])
{
edgeTo
[
w
]
=
v
;
dfs
(
G
,
w
);
}
}
}
/**
* Is there a directed path from the source vertex {
@code
s} to vertex {
@code
v}?
*
@param
v the vertex
*
@return
{
@code
true} if there is a directed path from the source
* vertex {
@code
s} to vertex {
@code
v}, {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
boolean
hasPathTo
(
int
v
)
{
validateVertex
(
v
);
return
marked
[
v
];
}
/**
* Returns a directed path from the source vertex {
@code
s} to vertex {
@code
v}, or
* {
@code
null} if no such path.
*
@param
v the vertex
*
@return
the sequence of vertices on a directed path from the source vertex
* {
@code
s} to vertex {
@code
v}, as an Iterable
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
Iterable
<
Integer
>
pathTo
(
int
v
)
{
validateVertex
(
v
);
if
(
!
hasPathTo
(
v
))
return
null
;
Stack
<
Integer
>
path
=
new
Stack
<
Integer
>
();
for
(
int
x
=
v
;
x
!=
s
;
x
=
edgeTo
[
x
])
path
.
push
(
x
);
path
.
push
(
s
);
return
path
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
marked
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
DepthFirstDirectedPaths} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
Digraph
G
=
new
Digraph
(
in
);
// StdOut.println(G);
int
s
=
Integer
.
parseInt
(
args
[
1
]);
DepthFirstDirectedPaths
dfs
=
new
DepthFirstDirectedPaths
(
G
,
s
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
dfs
.
hasPathTo
(
v
))
{
StdOut
.
printf
(
"%d to %d: "
,
s
,
v
);
for
(
int
x
:
dfs
.
pathTo
(
v
))
{
if
(
x
==
s
)
StdOut
.
print
(
x
);
else
StdOut
.
print
(
"-"
+
x
);
}
StdOut
.
println
();
}
else
{
StdOut
.
printf
(
"%d to %d: not connected\n"
,
s
,
v
);
}
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/DepthFirstOrder.java
edu/princeton/cs/algs4/DepthFirstOrder.java
/******************************************************************************
* Compilation: javac DepthFirstOrder.java
* Execution: java DepthFirstOrder digraph.txt
* Dependencies: Digraph.java Queue.java Stack.java StdOut.java
* EdgeWeightedDigraph.java DirectedEdge.java
* Data files: https://algs4.cs.princeton.edu/42digraph/tinyDAG.txt
* https://algs4.cs.princeton.edu/42digraph/tinyDG.txt
*
* Compute preorder and postorder for a digraph or edge-weighted digraph.
* Runs in O(E + V) time.
*
* % java DepthFirstOrder tinyDAG.txt
* v pre post
* --------------
* 0 0 8
* 1 3 2
* 2 9 10
* 3 10 9
* 4 2 0
* 5 1 1
* 6 4 7
* 7 11 11
* 8 12 12
* 9 5 6
* 10 8 5
* 11 6 4
* 12 7 3
* Preorder: 0 5 4 1 6 9 11 12 10 2 3 7 8
* Postorder: 4 5 1 12 11 10 9 6 0 3 2 7 8
* Reverse postorder: 8 7 2 3 0 6 9 10 11 12 1 5 4
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
DepthFirstOrder} class represents a data type for
* determining depth-first search ordering of the vertices in a digraph
* or edge-weighted digraph, including preorder, postorder, and reverse postorder.
*
* This implementation uses depth-first search.
* Each constructor takes Θ(V + E) time,
* where V is the number of vertices and E is the
* number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the digraph).
*
* For additional documentation,
* see Section 4.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
DepthFirstOrder
{
private
boolean
[]
marked
;
// marked[v] = has v been marked in dfs?
private
int
[]
pre
;
// pre[v] = preorder number of v
private
int
[]
post
;
// post[v] = postorder number of v
private
Queue
<
Integer
>
preorder
;
// vertices in preorder
private
Queue
<
Integer
>
postorder
;
// vertices in postorder
private
int
preCounter
;
// counter or preorder numbering
private
int
postCounter
;
// counter for postorder numbering
/**
* Determines a depth-first order for the digraph {
@code
G}.
*
@param
G the digraph
*/
public
DepthFirstOrder
(
Digraph
G
)
{
pre
=
new
int
[
G
.
V
()];
post
=
new
int
[
G
.
V
()];
postorder
=
new
Queue
<
Integer
>
();
preorder
=
new
Queue
<
Integer
>
();
marked
=
new
boolean
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
!
marked
[
v
])
dfs
(
G
,
v
);
assert
check
();
}
/**
* Determines a depth-first order for the edge-weighted digraph {
@code
G}.
*
@param
G the edge-weighted digraph
*/
public
DepthFirstOrder
(
EdgeWeightedDigraph
G
)
{
pre
=
new
int
[
G
.
V
()];
post
=
new
int
[
G
.
V
()];
postorder
=
new
Queue
<
Integer
>
();
preorder
=
new
Queue
<
Integer
>
();
marked
=
new
boolean
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
!
marked
[
v
])
dfs
(
G
,
v
);
}
// run DFS in digraph G from vertex v and compute preorder/postorder
private
void
dfs
(
Digraph
G
,
int
v
)
{
marked
[
v
]
=
true
;
pre
[
v
]
=
preCounter
++
;
preorder
.
enqueue
(
v
);
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
!
marked
[
w
])
{
dfs
(
G
,
w
);
}
}
postorder
.
enqueue
(
v
);
post
[
v
]
=
postCounter
++
;
}
// run DFS in edge-weighted digraph G from vertex v and compute preorder/postorder
private
void
dfs
(
EdgeWeightedDigraph
G
,
int
v
)
{
marked
[
v
]
=
true
;
pre
[
v
]
=
preCounter
++
;
preorder
.
enqueue
(
v
);
for
(
DirectedEdge
e
:
G
.
adj
(
v
))
{
int
w
=
e
.
to
();
if
(
!
marked
[
w
])
{
dfs
(
G
,
w
);
}
}
postorder
.
enqueue
(
v
);
post
[
v
]
=
postCounter
++
;
}
/**
* Returns the preorder number of vertex {
@code
v}.
*
@param
v the vertex
*
@return
the preorder number of vertex {
@code
v}
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
int
pre
(
int
v
)
{
validateVertex
(
v
);
return
pre
[
v
];
}
/**
* Returns the postorder number of vertex {
@code
v}.
*
@param
v the vertex
*
@return
the postorder number of vertex {
@code
v}
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
int
post
(
int
v
)
{
validateVertex
(
v
);
return
post
[
v
];
}
/**
* Returns the vertices in postorder.
*
@return
the vertices in postorder, as an iterable of vertices
*/
public
Iterable
<
Integer
>
post
()
{
return
postorder
;
}
/**
* Returns the vertices in preorder.
*
@return
the vertices in preorder, as an iterable of vertices
*/
public
Iterable
<
Integer
>
pre
()
{
return
preorder
;
}
/**
* Returns the vertices in reverse postorder.
*
@return
the vertices in reverse postorder, as an iterable of vertices
*/
public
Iterable
<
Integer
>
reversePost
()
{
Stack
<
Integer
>
reverse
=
new
Stack
<
Integer
>
();
for
(
int
v
:
postorder
)
reverse
.
push
(
v
);
return
reverse
;
}
// check that pre() and post() are consistent with pre(v) and post(v)
private
boolean
check
()
{
// check that post(v) is consistent with post()
int
r
=
0
;
for
(
int
v
:
post
())
{
if
(
post
(
v
)
!=
r
)
{
StdOut
.
println
(
“post(v) and post() inconsistent”
);
return
false
;
}
r
++
;
}
// check that pre(v) is consistent with pre()
r
=
0
;
for
(
int
v
:
pre
())
{
if
(
pre
(
v
)
!=
r
)
{
StdOut
.
println
(
“pre(v) and pre() inconsistent”
);
return
false
;
}
r
++
;
}
return
true
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
marked
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
DepthFirstOrder} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
Digraph
G
=
new
Digraph
(
in
);
DepthFirstOrder
dfs
=
new
DepthFirstOrder
(
G
);
StdOut
.
println
(
” v pre post”
);
StdOut
.
println
(
“————–”
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
StdOut
.
printf
(
"%4d %4d %4d\n"
,
v
,
dfs
.
pre
(
v
),
dfs
.
post
(
v
));
}
StdOut
.
print
(
"Preorder: "
);
for
(
int
v
:
dfs
.
pre
())
{
StdOut
.
print
(
v
+
" "
);
}
StdOut
.
println
();
StdOut
.
print
(
"Postorder: "
);
for
(
int
v
:
dfs
.
post
())
{
StdOut
.
print
(
v
+
" "
);
}
StdOut
.
println
();
StdOut
.
print
(
"Reverse postorder: "
);
for
(
int
v
:
dfs
.
reversePost
())
{
StdOut
.
print
(
v
+
" "
);
}
StdOut
.
println
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/DepthFirstPaths.java
edu/princeton/cs/algs4/DepthFirstPaths.java
/******************************************************************************
* Compilation: javac DepthFirstPaths.java
* Execution: java DepthFirstPaths G s
* Dependencies: Graph.java Stack.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/41graph/tinyCG.txt
* https://algs4.cs.princeton.edu/41graph/tinyG.txt
* https://algs4.cs.princeton.edu/41graph/mediumG.txt
* https://algs4.cs.princeton.edu/41graph/largeG.txt
*
* Run depth-first search on an undirected graph.
*
* % java Graph tinyCG.txt
* 6 8
* 0: 2 1 5
* 1: 0 2
* 2: 0 1 3 4
* 3: 5 4 2
* 4: 3 2
* 5: 3 0
*
* % java DepthFirstPaths tinyCG.txt 0
* 0 to 0: 0
* 0 to 1: 0-2-1
* 0 to 2: 0-2
* 0 to 3: 0-2-3
* 0 to 4: 0-2-3-4
* 0 to 5: 0-2-3-5
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
DepthFirstPaths} class represents a data type for finding
* paths from a source vertex s to every other vertex
* in an undirected graph.
*
* This implementation uses depth-first search.
* The constructor takes Θ(V + E) time in the
* worst case, where V is the number of vertices and
* E is the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the graph).
*
* For additional documentation, see
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
DepthFirstPaths
{
private
boolean
[]
marked
;
// marked[v] = is there an s-v path?
private
int
[]
edgeTo
;
// edgeTo[v] = last edge on s-v path
private
final
int
s
;
// source vertex
/**
* Computes a path between {
@code
s} and every other vertex in graph {
@code
G}.
*
@param
G the graph
*
@param
s the source vertex
*
@throws
IllegalArgumentException unless {
@code
0 <= s < V}
*/
public
DepthFirstPaths
(
Graph
G
,
int
s
)
{
this
.
s
=
s
;
edgeTo
=
new
int
[
G
.
V
()];
marked
=
new
boolean
[
G
.
V
()];
validateVertex
(
s
);
dfs
(
G
,
s
);
}
// depth first search from v
private
void
dfs
(
Graph
G
,
int
v
)
{
marked
[
v
]
=
true
;
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
!
marked
[
w
])
{
edgeTo
[
w
]
=
v
;
dfs
(
G
,
w
);
}
}
}
/**
* Is there a path between the source vertex {
@code
s} and vertex {
@code
v}?
*
@param
v the vertex
*
@return
{
@code
true} if there is a path, {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
boolean
hasPathTo
(
int
v
)
{
validateVertex
(
v
);
return
marked
[
v
];
}
/**
* Returns a path between the source vertex {
@code
s} and vertex {
@code
v}, or
* {
@code
null} if no such path.
*
@param
v the vertex
*
@return
the sequence of vertices on a path between the source vertex
* {
@code
s} and vertex {
@code
v}, as an Iterable
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
Iterable
<
Integer
>
pathTo
(
int
v
)
{
validateVertex
(
v
);
if
(
!
hasPathTo
(
v
))
return
null
;
Stack
<
Integer
>
path
=
new
Stack
<
Integer
>
();
for
(
int
x
=
v
;
x
!=
s
;
x
=
edgeTo
[
x
])
path
.
push
(
x
);
path
.
push
(
s
);
return
path
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
marked
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
DepthFirstPaths} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
Graph
G
=
new
Graph
(
in
);
int
s
=
Integer
.
parseInt
(
args
[
1
]);
DepthFirstPaths
dfs
=
new
DepthFirstPaths
(
G
,
s
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
dfs
.
hasPathTo
(
v
))
{
StdOut
.
printf
(
"%d to %d: "
,
s
,
v
);
for
(
int
x
:
dfs
.
pathTo
(
v
))
{
if
(
x
==
s
)
StdOut
.
print
(
x
);
else
StdOut
.
print
(
"-"
+
x
);
}
StdOut
.
println
();
}
else
{
StdOut
.
printf
(
"%d to %d: not connected\n"
,
s
,
v
);
}
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/DepthFirstSearch.java
edu/princeton/cs/algs4/DepthFirstSearch.java
/******************************************************************************
* Compilation: javac DepthFirstSearch.java
* Execution: java DepthFirstSearch filename.txt s
* Dependencies: Graph.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/41graph/tinyG.txt
* https://algs4.cs.princeton.edu/41graph/mediumG.txt
*
* Run depth first search on an undirected graph.
* Runs in O(E + V) time.
*
* % java DepthFirstSearch tinyG.txt 0
* 0 1 2 3 4 5 6
* NOT connected
*
* % java DepthFirstSearch tinyG.txt 9
* 9 10 11 12
* NOT connected
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
DepthFirstSearch} class represents a data type for
* determining the vertices connected to a given source vertex s
* in an undirected graph. For versions that find the paths, see
* {
@link
DepthFirstPaths} and {
@link
BreadthFirstPaths}.
*
* This implementation uses depth-first search.
* See {
@link
NonrecursiveDFS} for a non-recursive version.
* The constructor takes Θ(V + E) time in the worst
* case, where V is the number of vertices and E
* is the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the graph).
*
* For additional documentation, see
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
DepthFirstSearch
{
private
boolean
[]
marked
;
// marked[v] = is there an s-v path?
private
int
count
;
// number of vertices connected to s
/**
* Computes the vertices in graph {
@code
G} that are
* connected to the source vertex {
@code
s}.
*
@param
G the graph
*
@param
s the source vertex
*
@throws
IllegalArgumentException unless {
@code
0 <= s < V}
*/
public
DepthFirstSearch
(
Graph
G
,
int
s
)
{
marked
=
new
boolean
[
G
.
V
()];
validateVertex
(
s
);
dfs
(
G
,
s
);
}
// depth first search from v
private
void
dfs
(
Graph
G
,
int
v
)
{
count
++
;
marked
[
v
]
=
true
;
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
!
marked
[
w
])
{
dfs
(
G
,
w
);
}
}
}
/**
* Is there a path between the source vertex {
@code
s} and vertex {
@code
v}?
*
@param
v the vertex
*
@return
{
@code
true} if there is a path, {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
boolean
marked
(
int
v
)
{
validateVertex
(
v
);
return
marked
[
v
];
}
/**
* Returns the number of vertices connected to the source vertex {
@code
s}.
*
@return
the number of vertices connected to the source vertex {
@code
s}
*/
public
int
count
()
{
return
count
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
marked
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
DepthFirstSearch} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
Graph
G
=
new
Graph
(
in
);
int
s
=
Integer
.
parseInt
(
args
[
1
]);
DepthFirstSearch
search
=
new
DepthFirstSearch
(
G
,
s
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
search
.
marked
(
v
))
StdOut
.
print
(
v
+
" "
);
}
StdOut
.
println
();
if
(
search
.
count
()
!=
G
.
V
())
StdOut
.
println
(
"NOT connected"
);
else
StdOut
.
println
(
"connected"
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/DigraphGenerator.java
edu/princeton/cs/algs4/DigraphGenerator.java
/******************************************************************************
* Compilation: javac DigraphGenerator.java
* Execution: java DigraphGenerator V E
* Dependencies: Digraph.java
*
* A digraph generator.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
DigraphGenerator} class provides static methods for creating
* various digraphs, including Erdos-Renyi random digraphs, random DAGs,
* random rooted trees, random rooted DAGs, random tournaments, path digraphs,
* cycle digraphs, and the complete digraph.
*
* For additional documentation, see Section 4.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
DigraphGenerator
{
private
static
final
class
Edge
implements
Comparable
<
Edge
>
{
private
final
int
v
;
private
final
int
w
;
private
Edge
(
int
v
,
int
w
)
{
this
.
v
=
v
;
this
.
w
=
w
;
}
public
int
compareTo
(
Edge
that
)
{
if
(
this
.
v
<
that
.
v
)
return
-
1
;
if
(
this
.
v
>
that
.
v
)
return
+
1
;
if
(
this
.
w
<
that
.
w
)
return
-
1
;
if
(
this
.
w
>
that
.
w
)
return
+
1
;
return
0
;
}
}
// this class cannot be instantiated
private
DigraphGenerator
()
{
}
/**
* Returns a random simple digraph containing {
@code
V} vertices and {
@code
E} edges.
*
@param
V the number of vertices
*
@param
E the number of vertices
*
@return
a random simple digraph on {
@code
V} vertices, containing a total
* of {
@code
E} edges
*
@throws
IllegalArgumentException if no such simple digraph exists
*/
public
static
Digraph
simple
(
int
V
,
int
E
)
{
if
(
E
>
(
long
)
V
*
(
V
–
1
))
throw
new
IllegalArgumentException
(
“Too many edges”
);
if
(
E
<
0
)
throw
new
IllegalArgumentException
(
"Too few edges"
);
Digraph
G
=
new
Digraph
(
V
);
SET
<
Edge
>
set
=
new
SET
<
Edge
>
();
while
(
G
.
E
()
<
E
)
{
int
v
=
StdRandom
.
uniform
(
V
);
int
w
=
StdRandom
.
uniform
(
V
);
Edge
e
=
new
Edge
(
v
,
w
);
if
((
v
!=
w
)
&&
!
set
.
contains
(
e
))
{
set
.
add
(
e
);
G
.
addEdge
(
v
,
w
);
}
}
return
G
;
}
/**
* Returns a random simple digraph on {
@code
V} vertices, with an
* edge between any two vertices with probability {
@code
p}. This is sometimes
* referred to as the Erdos-Renyi random digraph model.
* This implementations takes time propotional to V^2 (even if {
@code
p} is small).
*
@param
V the number of vertices
*
@param
p the probability of choosing an edge
*
@return
a random simple digraph on {
@code
V} vertices, with an edge between
* any two vertices with probability {
@code
p}
*
@throws
IllegalArgumentException if probability is not between 0 and 1
*/
public
static
Digraph
simple
(
int
V
,
double
p
)
{
if
(
p
<
0.0
||
p
>
1.0
)
throw
new
IllegalArgumentException
(
“Probability must be between 0 and 1”
);
Digraph
G
=
new
Digraph
(
V
);
for
(
int
v
=
0
;
v
<
V
;
v
++
)
for
(
int
w
=
0
;
w
<
V
;
w
++
)
if
(
v
!=
w
)
if
(
StdRandom
.
bernoulli
(
p
))
G
.
addEdge
(
v
,
w
);
return
G
;
}
/**
* Returns the complete digraph on {
@code
V} vertices.
* In a complete digraph, every pair of distinct vertices is connected
* by two antiparallel edges. There are {
@code
V*(V-1)} edges.
*
@param
V the number of vertices
*
@return
the complete digraph on {
@code
V} vertices
*/
public
static
Digraph
complete
(
int
V
)
{
Digraph
G
=
new
Digraph
(
V
);
for
(
int
v
=
0
;
v
<
V
;
v
++
)
for
(
int
w
=
0
;
w
<
V
;
w
++
)
if
(
v
!=
w
)
G
.
addEdge
(
v
,
w
);
return
G
;
}
/**
* Returns a random simple DAG containing {
@code
V} vertices and {
@code
E} edges.
* Note: it is not uniformly selected at random among all such DAGs.
*
@param
V the number of vertices
*
@param
E the number of vertices
*
@return
a random simple DAG on {
@code
V} vertices, containing a total
* of {
@code
E} edges
*
@throws
IllegalArgumentException if no such simple DAG exists
*/
public
static
Digraph
dag
(
int
V
,
int
E
)
{
if
(
E
>
(
long
)
V
*
(
V
–
1
)
/
2
)
throw
new
IllegalArgumentException
(
“Too many edges”
);
if
(
E
<
0
)
throw
new
IllegalArgumentException
(
"Too few edges"
);
Digraph
G
=
new
Digraph
(
V
);
SET
<
Edge
>
set
=
new
SET
<
Edge
>
();
int
[]
vertices
=
new
int
[
V
];
for
(
int
i
=
0
;
i
<
V
;
i
++
)
vertices
[
i
]
=
i
;
StdRandom
.
shuffle
(
vertices
);
while
(
G
.
E
()
<
E
)
{
int
v
=
StdRandom
.
uniform
(
V
);
int
w
=
StdRandom
.
uniform
(
V
);
Edge
e
=
new
Edge
(
v
,
w
);
if
((
v
<
w
)
&&
!
set
.
contains
(
e
))
{
set
.
add
(
e
);
G
.
addEdge
(
vertices
[
v
],
vertices
[
w
]);
}
}
return
G
;
}
/**
* Returns a random tournament digraph on {
@code
V} vertices. A tournament digraph
* is a digraph in which, for every pair of vertices, there is one and only one
* directed edge connecting them. A tournament is an oriented complete graph.
*
@param
V the number of vertices
*
@return
a random tournament digraph on {
@code
V} vertices
*/
public
static
Digraph
tournament
(
int
V
)
{
Digraph
G
=
new
Digraph
(
V
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
for
(
int
w
=
v
+
1
;
w
<
G
.
V
();
w
++
)
{
if
(
StdRandom
.
bernoulli
(
0.5
))
G
.
addEdge
(
v
,
w
);
else
G
.
addEdge
(
w
,
v
);
}
}
return
G
;
}
/**
* Returns a complete rooted-in DAG on {
@code
V} vertices.
* A rooted in-tree is a DAG in which there is a single vertex
* reachable from every other vertex. A complete rooted in-DAG
* has V*(V-1)/2 edges.
*
@param
V the number of vertices
*
@return
a complete rooted-in DAG on {
@code
V} vertices
*/
public
static
Digraph
completeRootedInDAG
(
int
V
)
{
Digraph
G
=
new
Digraph
(
V
);
int
[]
vertices
=
new
int
[
V
];
for
(
int
i
=
0
;
i
<
V
;
i
++
)
vertices
[
i
]
=
i
;
StdRandom
.
shuffle
(
vertices
);
for
(
int
i
=
0
;
i
<
V
;
i
++
)
for
(
int
j
=
i
+
1
;
j
<
V
;
j
++
)
G
.
addEdge
(
vertices
[
i
],
vertices
[
j
]);
return
G
;
}
/**
* Returns a random rooted-in DAG on {
@code
V} vertices and {
@code
E} edges.
* A rooted in-tree is a DAG in which there is a single vertex
* reachable from every other vertex.
* The DAG returned is not chosen uniformly at random among all such DAGs.
*
@param
V the number of vertices
*
@param
E the number of edges
*
@return
a random rooted-in DAG on {
@code
V} vertices and {
@code
E} edges
*/
public
static
Digraph
rootedInDAG
(
int
V
,
int
E
)
{
if
(
E
>
(
long
)
V
*
(
V
–
1
)
/
2
)
throw
new
IllegalArgumentException
(
“Too many edges”
);
if
(
E
<
V
-
1
)
throw
new
IllegalArgumentException
(
"Too few edges"
);
Digraph
G
=
new
Digraph
(
V
);
SET
<
Edge
>
set
=
new
SET
<
Edge
>
();
// fix a topological order
int
[]
vertices
=
new
int
[
V
];
for
(
int
i
=
0
;
i
<
V
;
i
++
)
vertices
[
i
]
=
i
;
StdRandom
.
shuffle
(
vertices
);
// one edge pointing from each vertex, other than the root = vertices[V-1]
for
(
int
v
=
0
;
v
<
V
-
1
;
v
++
)
{
int
w
=
StdRandom
.
uniform
(
v
+
1
,
V
);
Edge
e
=
new
Edge
(
v
,
w
);
set
.
add
(
e
);
G
.
addEdge
(
vertices
[
v
],
vertices
[
w
]);
}
while
(
G
.
E
()
<
E
)
{
int
v
=
StdRandom
.
uniform
(
V
);
int
w
=
StdRandom
.
uniform
(
V
);
Edge
e
=
new
Edge
(
v
,
w
);
if
((
v
<
w
)
&&
!
set
.
contains
(
e
))
{
set
.
add
(
e
);
G
.
addEdge
(
vertices
[
v
],
vertices
[
w
]);
}
}
return
G
;
}
/**
* Returns a complete rooted-out DAG on {
@code
V} vertices.
* A rooted out-tree is a DAG in which every vertex is reachable
* from a single vertex. A complete rooted in-DAG has V*(V-1)/2 edges.
*
@param
V the number of vertices
*
@return
a complete rooted-out DAG on {
@code
V} vertices
*/
public
static
Digraph
completeRootedOutDAG
(
int
V
)
{
Digraph
G
=
new
Digraph
(
V
);
int
[]
vertices
=
new
int
[
V
];
for
(
int
i
=
0
;
i
<
V
;
i
++
)
vertices
[
i
]
=
i
;
StdRandom
.
shuffle
(
vertices
);
for
(
int
i
=
0
;
i
<
V
;
i
++
)
for
(
int
j
=
i
+
1
;
j
<
V
;
j
++
)
G
.
addEdge
(
vertices
[
j
],
vertices
[
i
]);
return
G
;
}
/**
* Returns a random rooted-out DAG on {
@code
V} vertices and {
@code
E} edges.
* A rooted out-tree is a DAG in which every vertex is reachable from a
* single vertex.
* The DAG returned is not chosen uniformly at random among all such DAGs.
*
@param
V the number of vertices
*
@param
E the number of edges
*
@return
a random rooted-out DAG on {
@code
V} vertices and {
@code
E} edges
*/
public
static
Digraph
rootedOutDAG
(
int
V
,
int
E
)
{
if
(
E
>
(
long
)
V
*
(
V
–
1
)
/
2
)
throw
new
IllegalArgumentException
(
“Too many edges”
);
if
(
E
<
V
-
1
)
throw
new
IllegalArgumentException
(
"Too few edges"
);
Digraph
G
=
new
Digraph
(
V
);
SET
<
Edge
>
set
=
new
SET
<
Edge
>
();
// fix a topological order
int
[]
vertices
=
new
int
[
V
];
for
(
int
i
=
0
;
i
<
V
;
i
++
)
vertices
[
i
]
=
i
;
StdRandom
.
shuffle
(
vertices
);
// one edge pointing from each vertex, other than the root = vertices[V-1]
for
(
int
v
=
0
;
v
<
V
-
1
;
v
++
)
{
int
w
=
StdRandom
.
uniform
(
v
+
1
,
V
);
Edge
e
=
new
Edge
(
w
,
v
);
set
.
add
(
e
);
G
.
addEdge
(
vertices
[
w
],
vertices
[
v
]);
}
while
(
G
.
E
()
<
E
)
{
int
v
=
StdRandom
.
uniform
(
V
);
int
w
=
StdRandom
.
uniform
(
V
);
Edge
e
=
new
Edge
(
w
,
v
);
if
((
v
<
w
)
&&
!
set
.
contains
(
e
))
{
set
.
add
(
e
);
G
.
addEdge
(
vertices
[
w
],
vertices
[
v
]);
}
}
return
G
;
}
/**
* Returns a random rooted-in tree on {
@code
V} vertices.
* A rooted in-tree is an oriented tree in which there is a single vertex
* reachable from every other vertex.
* The tree returned is not chosen uniformly at random among all such trees.
*
@param
V the number of vertices
*
@return
a random rooted-in tree on {
@code
V} vertices
*/
public
static
Digraph
rootedInTree
(
int
V
)
{
return
rootedInDAG
(
V
,
V
-
1
);
}
/**
* Returns a random rooted-out tree on {
@code
V} vertices. A rooted out-tree
* is an oriented tree in which each vertex is reachable from a single vertex.
* It is also known as a arborescence or branching.
* The tree returned is not chosen uniformly at random among all such trees.
*
@param
V the number of vertices
*
@return
a random rooted-out tree on {
@code
V} vertices
*/
public
static
Digraph
rootedOutTree
(
int
V
)
{
return
rootedOutDAG
(
V
,
V
–
1
);
}
/**
* Returns a path digraph on {
@code
V} vertices.
*
@param
V the number of vertices in the path
*
@return
a digraph that is a directed path on {
@code
V} vertices
*/
public
static
Digraph
path
(
int
V
)
{
Digraph
G
=
new
Digraph
(
V
);
int
[]
vertices
=
new
int
[
V
];
for
(
int
i
=
0
;
i
<
V
;
i
++
)
vertices
[
i
]
=
i
;
StdRandom
.
shuffle
(
vertices
);
for
(
int
i
=
0
;
i
<
V
-
1
;
i
++
)
{
G
.
addEdge
(
vertices
[
i
],
vertices
[
i
+
1
]);
}
return
G
;
}
/**
* Returns a complete binary tree digraph on {
@code
V} vertices.
*
@param
V the number of vertices in the binary tree
*
@return
a digraph that is a complete binary tree on {
@code
V} vertices
*/
public
static
Digraph
binaryTree
(
int
V
)
{
Digraph
G
=
new
Digraph
(
V
);
int
[]
vertices
=
new
int
[
V
];
for
(
int
i
=
0
;
i
<
V
;
i
++
)
vertices
[
i
]
=
i
;
StdRandom
.
shuffle
(
vertices
);
for
(
int
i
=
1
;
i
<
V
;
i
++
)
{
G
.
addEdge
(
vertices
[
i
],
vertices
[(
i
-
1
)
/
2
]);
}
return
G
;
}
/**
* Returns a cycle digraph on {
@code
V} vertices.
*
@param
V the number of vertices in the cycle
*
@return
a digraph that is a directed cycle on {
@code
V} vertices
*/
public
static
Digraph
cycle
(
int
V
)
{
Digraph
G
=
new
Digraph
(
V
);
int
[]
vertices
=
new
int
[
V
];
for
(
int
i
=
0
;
i
<
V
;
i
++
)
vertices
[
i
]
=
i
;
StdRandom
.
shuffle
(
vertices
);
for
(
int
i
=
0
;
i
<
V
-
1
;
i
++
)
{
G
.
addEdge
(
vertices
[
i
],
vertices
[
i
+
1
]);
}
G
.
addEdge
(
vertices
[
V
-
1
],
vertices
[
0
]);
return
G
;
}
/**
* Returns an Eulerian cycle digraph on {
@code
V} vertices.
*
*
@param
V the number of vertices in the cycle
*
@param
E the number of edges in the cycle
*
@return
a digraph that is a directed Eulerian cycle on {
@code
V} vertices
* and {
@code
E} edges
*
@throws
IllegalArgumentException if either {
@code
V <= 0} or {
@code
E <= 0}
*/
public
static
Digraph
eulerianCycle
(
int
V
,
int
E
)
{
if
(
E
<=
0
)
throw
new
IllegalArgumentException
(
"An Eulerian cycle must have at least one edge"
);
if
(
V
<=
0
)
throw
new
IllegalArgumentException
(
"An Eulerian cycle must have at least one vertex"
);
Digraph
G
=
new
Digraph
(
V
);
int
[]
vertices
=
new
int
[
E
];
for
(
int
i
=
0
;
i
<
E
;
i
++
)
vertices
[
i
]
=
StdRandom
.
uniform
(
V
);
for
(
int
i
=
0
;
i
<
E
-
1
;
i
++
)
{
G
.
addEdge
(
vertices
[
i
],
vertices
[
i
+
1
]);
}
G
.
addEdge
(
vertices
[
E
-
1
],
vertices
[
0
]);
return
G
;
}
/**
* Returns an Eulerian path digraph on {
@code
V} vertices.
*
*
@param
V the number of vertices in the path
*
@param
E the number of edges in the path
*
@return
a digraph that is a directed Eulerian path on {
@code
V} vertices
* and {
@code
E} edges
*
@throws
IllegalArgumentException if either {
@code
V <= 0} or {
@code
E < 0}
*/
public
static
Digraph
eulerianPath
(
int
V
,
int
E
)
{
if
(
E
<
0
)
throw
new
IllegalArgumentException
(
"negative number of edges"
);
if
(
V
<=
0
)
throw
new
IllegalArgumentException
(
"An Eulerian path must have at least one vertex"
);
Digraph
G
=
new
Digraph
(
V
);
int
[]
vertices
=
new
int
[
E
+
1
];
for
(
int
i
=
0
;
i
<
E
+
1
;
i
++
)
vertices
[
i
]
=
StdRandom
.
uniform
(
V
);
for
(
int
i
=
0
;
i
<
E
;
i
++
)
{
G
.
addEdge
(
vertices
[
i
],
vertices
[
i
+
1
]);
}
return
G
;
}
/**
* Returns a random simple digraph on {
@code
V} vertices, {
@code
E}
* edges and (at least) {
@code
c} strong components. The vertices are randomly
* assigned integer labels between {
@code
0} and {
@code
c-1} (corresponding to
* strong components). Then, a strong component is creates among the vertices
* with the same label. Next, random edges (either between two vertices with
* the same labels or from a vetex with a smaller label to a vertex with a
* larger label). The number of components will be equal to the number of
* distinct labels that are assigned to vertices.
*
*
@param
V the number of vertices
*
@param
E the number of edges
*
@param
c the (maximum) number of strong components
*
@return
a random simple digraph on {
@code
V} vertices and
{
@code
E} edges, with (at most) {
@code
c} strong components
*
@throws
IllegalArgumentException if {
@code
c} is larger than {
@code
V}
*/
public
static
Digraph
strong
(
int
V
,
int
E
,
int
c
)
{
if
(
c
>=
V
||
c
<=
0
)
throw
new
IllegalArgumentException
(
"Number of components must be between 1 and V"
);
if
(
E
<=
2
*
(
V
-
c
))
throw
new
IllegalArgumentException
(
"Number of edges must be at least 2(V-c)"
);
if
(
E
>
(
long
)
V
*
(
V
–
1
)
/
2
)
throw
new
IllegalArgumentException
(
“Too many edges”
);
// the digraph
Digraph
G
=
new
Digraph
(
V
);
// edges added to G (to avoid duplicate edges)
SET
<
Edge
>
set
=
new
SET
<
Edge
>
();
int
[]
label
=
new
int
[
V
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
label
[
v
]
=
StdRandom
.
uniform
(
c
);
// make all vertices with label c a strong component by
// combining a rooted in-tree and a rooted out-tree
for
(
int
i
=
0
;
i
<
c
;
i
++
)
{
// how many vertices in component c
int
count
=
0
;
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
label
[
v
]
==
i
)
count
++
;
}
// if (count == 0) System.err.println("less than desired number of strong components");
int
[]
vertices
=
new
int
[
count
];
int
j
=
0
;
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
if
(
label
[
v
]
==
i
)
vertices
[
j
++
]
=
v
;
}
StdRandom
.
shuffle
(
vertices
);
// rooted-in tree with root = vertices[count-1]
for
(
int
v
=
0
;
v
<
count
-
1
;
v
++
)
{
int
w
=
StdRandom
.
uniform
(
v
+
1
,
count
);
Edge
e
=
new
Edge
(
w
,
v
);
set
.
add
(
e
);
G
.
addEdge
(
vertices
[
w
],
vertices
[
v
]);
}
// rooted-out tree with root = vertices[count-1]
for
(
int
v
=
0
;
v
<
count
-
1
;
v
++
)
{
int
w
=
StdRandom
.
uniform
(
v
+
1
,
count
);
Edge
e
=
new
Edge
(
v
,
w
);
set
.
add
(
e
);
G
.
addEdge
(
vertices
[
v
],
vertices
[
w
]);
}
}
while
(
G
.
E
()
<
E
)
{
int
v
=
StdRandom
.
uniform
(
V
);
int
w
=
StdRandom
.
uniform
(
V
);
Edge
e
=
new
Edge
(
v
,
w
);
if
(
!
set
.
contains
(
e
)
&&
v
!=
w
&&
label
[
v
]
<=
label
[
w
])
{
set
.
add
(
e
);
G
.
addEdge
(
v
,
w
);
}
}
return
G
;
}
/**
* Unit tests the {
@code
DigraphGenerator} library.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
V
=
Integer
.
parseInt
(
args
[
0
]);
int
E
=
Integer
.
parseInt
(
args
[
1
]);
StdOut
.
println
(
"complete graph"
);
StdOut
.
println
(
complete
(
V
));
StdOut
.
println
();
StdOut
.
println
(
"simple"
);
StdOut
.
println
(
simple
(
V
,
E
));
StdOut
.
println
();
StdOut
.
println
(
"path"
);
StdOut
.
println
(
path
(
V
));
StdOut
.
println
();
StdOut
.
println
(
"cycle"
);
StdOut
.
println
(
cycle
(
V
));
StdOut
.
println
();
StdOut
.
println
(
"Eulierian path"
);
StdOut
.
println
(
eulerianPath
(
V
,
E
));
StdOut
.
println
();
StdOut
.
println
(
"Eulierian cycle"
);
StdOut
.
println
(
eulerianCycle
(
V
,
E
));
StdOut
.
println
();
StdOut
.
println
(
"binary tree"
);
StdOut
.
println
(
binaryTree
(
V
));
StdOut
.
println
();
StdOut
.
println
(
"tournament"
);
StdOut
.
println
(
tournament
(
V
));
StdOut
.
println
();
StdOut
.
println
(
"DAG"
);
StdOut
.
println
(
dag
(
V
,
E
));
StdOut
.
println
();
StdOut
.
println
(
"rooted-in DAG"
);
StdOut
.
println
(
rootedInDAG
(
V
,
E
));
StdOut
.
println
();
StdOut
.
println
(
"rooted-out DAG"
);
StdOut
.
println
(
rootedOutDAG
(
V
,
E
));
StdOut
.
println
();
StdOut
.
println
(
"rooted-in tree"
);
StdOut
.
println
(
rootedInTree
(
V
));
StdOut
.
println
();
StdOut
.
println
(
"rooted-out DAG"
);
StdOut
.
println
(
rootedOutTree
(
V
));
StdOut
.
println
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Digraph.java
edu/princeton/cs/algs4/Digraph.java
/******************************************************************************
* Compilation: javac Digraph.java
* Execution: java Digraph filename.txt
* Dependencies: Bag.java In.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/42digraph/tinyDG.txt
* https://algs4.cs.princeton.edu/42digraph/mediumDG.txt
* https://algs4.cs.princeton.edu/42digraph/largeDG.txt
*
* A graph, implemented using an array of lists.
* Parallel edges and self-loops are permitted.
*
* % java Digraph tinyDG.txt
* 13 vertices, 22 edges
* 0: 5 1
* 1:
* 2: 0 3
* 3: 5 2
* 4: 3 2
* 5: 4
* 6: 9 4 8 0
* 7: 6 9
* 8: 6
* 9: 11 10
* 10: 12
* 11: 4 12
* 12: 9
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
NoSuchElementException
;
/**
* The {
@code
Digraph} class represents a directed graph of vertices
* named 0 through V – 1.
* It supports the following two primary operations: add an edge to the digraph,
* iterate over all of the vertices adjacent from a given vertex.
* It also provides
* methods for returning the indegree or outdegree of a vertex,
* the number of vertices V in the digraph,
* the number of edges E in the digraph, and the reverse digraph.
* Parallel edges and self-loops are permitted.
*
* This implementation uses an adjacency-lists representation, which
* is a vertex-indexed array of {
@link
Bag} objects.
* It uses Θ(E + V) space, where E is
* the number of edges and V is the number of vertices.
* All instance methods take Θ(1) time. (Though, iterating over
* the vertices returned by {
@link
#adj(int)} takes time proportional
* to the outdegree of the vertex.)
* Constructing an empty digraph with V vertices takes
* Θ(V) time; constructing a digraph with E edges
* and V vertices takes Θ(E + V) time.
*
* For additional documentation,
* see Section 4.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Digraph
{
private
static
final
String
NEWLINE
=
System
.
getProperty
(
“line.separator”
);
private
final
int
V
;
// number of vertices in this digraph
private
int
E
;
// number of edges in this digraph
private
Bag
<
Integer
>
[]
adj
;
// adj[v] = adjacency list for vertex v
private
int
[]
indegree
;
// indegree[v] = indegree of vertex v
/**
* Initializes an empty digraph with V vertices.
*
*
@param
V the number of vertices
*
@throws
IllegalArgumentException if {
@code
V < 0}
*/
public
Digraph
(
int
V
)
{
if
(
V
<
0
)
throw
new
IllegalArgumentException
(
"Number of vertices in a Digraph must be nonnegative"
);
this
.
V
=
V
;
this
.
E
=
0
;
indegree
=
new
int
[
V
];
adj
=
(
Bag
<
Integer
>
[])
new
Bag
[
V
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
adj
[
v
]
=
new
Bag
<
Integer
>
();
}
}
/**
* Initializes a digraph from the specified input stream.
* The format is the number of vertices V,
* followed by the number of edges E,
* followed by E pairs of vertices, with each entry separated by whitespace.
*
*
@param
in the input stream
*
@throws
IllegalArgumentException if {
@code
in} is {
@code
null}
*
@throws
IllegalArgumentException if the endpoints of any edge are not in prescribed range
*
@throws
IllegalArgumentException if the number of vertices or edges is negative
*
@throws
IllegalArgumentException if the input stream is in the wrong format
*/
public
Digraph
(
In
in
)
{
if
(
in
==
null
)
throw
new
IllegalArgumentException
(
“argument is null”
);
try
{
this
.
V
=
in
.
readInt
();
if
(
V
<
0
)
throw
new
IllegalArgumentException
(
"number of vertices in a Digraph must be nonnegative"
);
indegree
=
new
int
[
V
];
adj
=
(
Bag
<
Integer
>
[])
new
Bag
[
V
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
adj
[
v
]
=
new
Bag
<
Integer
>
();
}
int
E
=
in
.
readInt
();
if
(
E
<
0
)
throw
new
IllegalArgumentException
(
"number of edges in a Digraph must be nonnegative"
);
for
(
int
i
=
0
;
i
<
E
;
i
++
)
{
int
v
=
in
.
readInt
();
int
w
=
in
.
readInt
();
addEdge
(
v
,
w
);
}
}
catch
(
NoSuchElementException
e
)
{
throw
new
IllegalArgumentException
(
"invalid input format in Digraph constructor"
,
e
);
}
}
/**
* Initializes a new digraph that is a deep copy of the specified digraph.
*
*
@param
G the digraph to copy
*
@throws
IllegalArgumentException if {
@code
G} is {
@code
null}
*/
public
Digraph
(
Digraph
G
)
{
if
(
G
==
null
)
throw
new
IllegalArgumentException
(
"argument is null"
);
this
.
V
=
G
.
V
();
this
.
E
=
G
.
E
();
if
(
V
<
0
)
throw
new
IllegalArgumentException
(
"Number of vertices in a Digraph must be nonnegative"
);
// update indegrees
indegree
=
new
int
[
V
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
this
.
indegree
[
v
]
=
G
.
indegree
(
v
);
// update adjacency lists
adj
=
(
Bag
<
Integer
>
[])
new
Bag
[
V
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
adj
[
v
]
=
new
Bag
<
Integer
>
();
}
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
// reverse so that adjacency list is in same order as original
Stack
<
Integer
>
reverse
=
new
Stack
<
Integer
>
();
for
(
int
w
:
G
.
adj
[
v
])
{
reverse
.
push
(
w
);
}
for
(
int
w
:
reverse
)
{
adj
[
v
].
add
(
w
);
}
}
}
/**
* Returns the number of vertices in this digraph.
*
*
@return
the number of vertices in this digraph
*/
public
int
V
()
{
return
V
;
}
/**
* Returns the number of edges in this digraph.
*
*
@return
the number of edges in this digraph
*/
public
int
E
()
{
return
E
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Adds the directed edge v→w to this digraph.
*
*
@param
v the tail vertex
*
@param
w the head vertex
*
@throws
IllegalArgumentException unless both {
@code
0 <= v < V} and {
@code
0 <= w < V}
*/
public
void
addEdge
(
int
v
,
int
w
)
{
validateVertex
(
v
);
validateVertex
(
w
);
adj
[
v
].
add
(
w
);
indegree
[
w
]
++
;
E
++
;
}
/**
* Returns the vertices adjacent from vertex {
@code
v} in this digraph.
*
*
@param
v the vertex
*
@return
the vertices adjacent from vertex {
@code
v} in this digraph, as an iterable
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
Iterable
<
Integer
>
adj
(
int
v
)
{
validateVertex
(
v
);
return
adj
[
v
];
}
/**
* Returns the number of directed edges incident from vertex {
@code
v}.
* This is known as the outdegree of vertex {
@code
v}.
*
*
@param
v the vertex
*
@return
the outdegree of vertex {
@code
v}
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
int
outdegree
(
int
v
)
{
validateVertex
(
v
);
return
adj
[
v
].
size
();
}
/**
* Returns the number of directed edges incident to vertex {
@code
v}.
* This is known as the indegree of vertex {
@code
v}.
*
*
@param
v the vertex
*
@return
the indegree of vertex {
@code
v}
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
int
indegree
(
int
v
)
{
validateVertex
(
v
);
return
indegree
[
v
];
}
/**
* Returns the reverse of the digraph.
*
*
@return
the reverse of the digraph
*/
public
Digraph
reverse
()
{
Digraph
reverse
=
new
Digraph
(
V
);
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
for
(
int
w
:
adj
(
v
))
{
reverse
.
addEdge
(
w
,
v
);
}
}
return
reverse
;
}
/**
* Returns a string representation of the graph.
*
*
@return
the number of vertices V, followed by the number of edges E,
* followed by the V adjacency lists
*/
public
String
toString
()
{
StringBuilder
s
=
new
StringBuilder
();
s
.
append
(
V
+
” vertices, ”
+
E
+
” edges ”
+
NEWLINE
);
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
s
.
append
(
String
.
format
(
"%d: "
,
v
));
for
(
int
w
:
adj
[
v
])
{
s
.
append
(
String
.
format
(
"%d "
,
w
));
}
s
.
append
(
NEWLINE
);
}
return
s
.
toString
();
}
/**
* Unit tests the {
@code
Digraph} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
Digraph
G
=
new
Digraph
(
in
);
StdOut
.
println
(
G
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/DijkstraAllPairsSP.java
edu/princeton/cs/algs4/DijkstraAllPairsSP.java
/******************************************************************************
* Compilation: javac DijkstraAllPairsSP.java
* Execution: none
* Dependencies: EdgeWeightedDigraph.java Dijkstra.java
*
* Dijkstra's algorithm run from each vertex.
* Takes time proportional to E V log V and space proportional to EV.
*
* % java DijkstraAllPairsSP tinyEWD.txt
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
DijkstraAllPairsSP} class represents a data type for solving the
* all-pairs shortest paths problem in edge-weighted digraphs
* where the edge weights are nonnegative.
*
* This implementation runs Dijkstra’s algorithm from each vertex.
* The constructor takes Θ(V (E log V)) time
* in the worst case, where V is the number of vertices and
* E is the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V2) extra space (not including the
* edge-weighted digraph).
*
* For additional documentation,
* see Section 4.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
DijkstraAllPairsSP
{
private
DijkstraSP
[]
all
;
/**
* Computes a shortest paths tree from each vertex to to every other vertex in
* the edge-weighted digraph {
@code
G}.
*
@param
G the edge-weighted digraph
*
@throws
IllegalArgumentException if an edge weight is negative
*
@throws
IllegalArgumentException unless {
@code
0 <= s < V}
*/
public
DijkstraAllPairsSP
(
EdgeWeightedDigraph
G
)
{
all
=
new
DijkstraSP
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
all
[
v
]
=
new
DijkstraSP
(
G
,
v
);
}
/**
* Returns a shortest path from vertex {
@code
s} to vertex {
@code
t}.
*
@param
s the source vertex
*
@param
t the destination vertex
*
@return
a shortest path from vertex {
@code
s} to vertex {
@code
t}
* as an iterable of edges, and {
@code
null} if no such path
*
@throws
IllegalArgumentException unless {
@code
0 <= s < V}
*
@throws
IllegalArgumentException unless {
@code
0 <= t < V}
*/
public
Iterable
<
DirectedEdge
>
path
(
int
s
,
int
t
)
{
validateVertex
(
s
);
validateVertex
(
t
);
return
all
[
s
].
pathTo
(
t
);
}
/**
* Is there a path from the vertex {
@code
s} to vertex {
@code
t}?
*
@param
s the source vertex
*
@param
t the destination vertex
*
@return
{
@code
true} if there is a path from vertex {
@code
s}
* to vertex {
@code
t}, and {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= s < V}
*
@throws
IllegalArgumentException unless {
@code
0 <= t < V}
*/
public
boolean
hasPath
(
int
s
,
int
t
)
{
validateVertex
(
s
);
validateVertex
(
t
);
return
dist
(
s
,
t
)
<
Double
.
POSITIVE_INFINITY
;
}
/**
* Returns the length of a shortest path from vertex {
@code
s} to vertex {
@code
t}.
*
@param
s the source vertex
*
@param
t the destination vertex
*
@return
the length of a shortest path from vertex {
@code
s} to vertex {
@code
t};
* {
@code
Double.POSITIVE_INFINITY} if no such path
*
@throws
IllegalArgumentException unless {
@code
0 <= s < V}
*
@throws
IllegalArgumentException unless {
@code
0 <= t < V}
*/
public
double
dist
(
int
s
,
int
t
)
{
validateVertex
(
s
);
validateVertex
(
t
);
return
all
[
s
].
distTo
(
t
);
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
all
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
DijkstraAllPairsSP} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// read edge-weighted digraph
In
in
=
new
In
(
args
[
0
]);
EdgeWeightedDigraph
G
=
new
EdgeWeightedDigraph
(
in
);
// compute shortest paths between all pairs of vertices
DijkstraAllPairsSP
spt
=
new
DijkstraAllPairsSP
(
G
);
// print all-pairs shortest path distances
StdOut
.
printf
(
” ”
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
StdOut
.
printf
(
"%6d "
,
v
);
}
StdOut
.
println
();
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
StdOut
.
printf
(
"%3d: "
,
v
);
for
(
int
w
=
0
;
w
<
G
.
V
();
w
++
)
{
if
(
spt
.
hasPath
(
v
,
w
))
StdOut
.
printf
(
"%6.2f "
,
spt
.
dist
(
v
,
w
));
else
StdOut
.
printf
(
" Inf "
);
}
StdOut
.
println
();
}
StdOut
.
println
();
// print all-pairs shortest paths
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
for
(
int
w
=
0
;
w
<
G
.
V
();
w
++
)
{
if
(
spt
.
hasPath
(
v
,
w
))
{
StdOut
.
printf
(
"%d to %d (%5.2f) "
,
v
,
w
,
spt
.
dist
(
v
,
w
));
for
(
DirectedEdge
e
:
spt
.
path
(
v
,
w
))
StdOut
.
print
(
e
+
" "
);
StdOut
.
println
();
}
else
{
StdOut
.
printf
(
"%d to %d no path\n"
,
v
,
w
);
}
}
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/DijkstraSP.java
edu/princeton/cs/algs4/DijkstraSP.java
/******************************************************************************
* Compilation: javac DijkstraSP.java
* Execution: java DijkstraSP input.txt s
* Dependencies: EdgeWeightedDigraph.java IndexMinPQ.java Stack.java DirectedEdge.java
* Data files: https://algs4.cs.princeton.edu/44sp/tinyEWD.txt
* https://algs4.cs.princeton.edu/44sp/mediumEWD.txt
* https://algs4.cs.princeton.edu/44sp/largeEWD.txt
*
* Dijkstra's algorithm. Computes the shortest path tree.
* Assumes all weights are nonnegative.
*
* % java DijkstraSP tinyEWD.txt 0
* 0 to 0 (0.00)
* 0 to 1 (1.05) 0->4 0.38 4->5 0.35 5->1 0.32
* 0 to 2 (0.26) 0->2 0.26
* 0 to 3 (0.99) 0->2 0.26 2->7 0.34 7->3 0.39
* 0 to 4 (0.38) 0->4 0.38
* 0 to 5 (0.73) 0->4 0.38 4->5 0.35
* 0 to 6 (1.51) 0->2 0.26 2->7 0.34 7->3 0.39 3->6 0.52
* 0 to 7 (0.60) 0->2 0.26 2->7 0.34
*
* % java DijkstraSP mediumEWD.txt 0
* 0 to 0 (0.00)
* 0 to 1 (0.71) 0->44 0.06 44->93 0.07 … 107->1 0.07
* 0 to 2 (0.65) 0->44 0.06 44->231 0.10 … 42->2 0.11
* 0 to 3 (0.46) 0->97 0.08 97->248 0.09 … 45->3 0.12
* 0 to 4 (0.42) 0->44 0.06 44->93 0.07 … 77->4 0.11
* …
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
DijkstraSP} class represents a data type for solving the
* single-source shortest paths problem in edge-weighted digraphs
* where the edge weights are nonnegative.
*
* This implementation uses Dijkstra’s algorithm with a
* binary heap. The constructor takes
* Θ(E log V) time in the worst case,
* where V is the number of vertices and E is
* the number of edges. Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the
* edge-weighted digraph).
*
* For additional documentation,
* see Section 4.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
DijkstraSP
{
private
double
[]
distTo
;
// distTo[v] = distance of shortest s->v path
private
DirectedEdge
[]
edgeTo
;
// edgeTo[v] = last edge on shortest s->v path
private
IndexMinPQ
<
Double
>
pq
;
// priority queue of vertices
/**
* Computes a shortest-paths tree from the source vertex {
@code
s} to every other
* vertex in the edge-weighted digraph {
@code
G}.
*
*
@param
G the edge-weighted digraph
*
@param
s the source vertex
*
@throws
IllegalArgumentException if an edge weight is negative
*
@throws
IllegalArgumentException unless {
@code
0 <= s < V}
*/
public
DijkstraSP
(
EdgeWeightedDigraph
G
,
int
s
)
{
for
(
DirectedEdge
e
:
G
.
edges
())
{
if
(
e
.
weight
()
<
0
)
throw
new
IllegalArgumentException
(
"edge "
+
e
+
" has negative weight"
);
}
distTo
=
new
double
[
G
.
V
()];
edgeTo
=
new
DirectedEdge
[
G
.
V
()];
validateVertex
(
s
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
distTo
[
v
]
=
Double
.
POSITIVE_INFINITY
;
distTo
[
s
]
=
0.0
;
// relax vertices in order of distance from s
pq
=
new
IndexMinPQ
<
Double
>
(
G
.
V
());
pq
.
insert
(
s
,
distTo
[
s
]);
while
(
!
pq
.
isEmpty
())
{
int
v
=
pq
.
delMin
();
for
(
DirectedEdge
e
:
G
.
adj
(
v
))
relax
(
e
);
}
// check optimality conditions
assert
check
(
G
,
s
);
}
// relax edge e and update pq if changed
private
void
relax
(
DirectedEdge
e
)
{
int
v
=
e
.
from
(),
w
=
e
.
to
();
if
(
distTo
[
w
]
>
distTo
[
v
]
+
e
.
weight
())
{
distTo
[
w
]
=
distTo
[
v
]
+
e
.
weight
();
edgeTo
[
w
]
=
e
;
if
(
pq
.
contains
(
w
))
pq
.
decreaseKey
(
w
,
distTo
[
w
]);
else
pq
.
insert
(
w
,
distTo
[
w
]);
}
}
/**
* Returns the length of a shortest path from the source vertex {
@code
s} to vertex {
@code
v}.
*
@param
v the destination vertex
*
@return
the length of a shortest path from the source vertex {
@code
s} to vertex {
@code
v};
* {
@code
Double.POSITIVE_INFINITY} if no such path
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
double
distTo
(
int
v
)
{
validateVertex
(
v
);
return
distTo
[
v
];
}
/**
* Returns true if there is a path from the source vertex {
@code
s} to vertex {
@code
v}.
*
*
@param
v the destination vertex
*
@return
{
@code
true} if there is a path from the source vertex
* {
@code
s} to vertex {
@code
v}; {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
boolean
hasPathTo
(
int
v
)
{
validateVertex
(
v
);
return
distTo
[
v
]
<
Double
.
POSITIVE_INFINITY
;
}
/**
* Returns a shortest path from the source vertex {
@code
s} to vertex {
@code
v}.
*
*
@param
v the destination vertex
*
@return
a shortest path from the source vertex {
@code
s} to vertex {
@code
v}
* as an iterable of edges, and {
@code
null} if no such path
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
Iterable
<
DirectedEdge
>
pathTo
(
int
v
)
{
validateVertex
(
v
);
if
(
!
hasPathTo
(
v
))
return
null
;
Stack
<
DirectedEdge
>
path
=
new
Stack
<
DirectedEdge
>
();
for
(
DirectedEdge
e
=
edgeTo
[
v
];
e
!=
null
;
e
=
edgeTo
[
e
.
from
()])
{
path
.
push
(
e
);
}
return
path
;
}
// check optimality conditions:
// (i) for all edges e: distTo[e.to()] <= distTo[e.from()] + e.weight()
// (ii) for all edge e on the SPT: distTo[e.to()] == distTo[e.from()] + e.weight()
private
boolean
check
(
EdgeWeightedDigraph
G
,
int
s
)
{
// check that edge weights are nonnegative
for
(
DirectedEdge
e
:
G
.
edges
())
{
if
(
e
.
weight
()
<
0
)
{
System
.
err
.
println
(
"negative edge weight detected"
);
return
false
;
}
}
// check that distTo[v] and edgeTo[v] are consistent
if
(
distTo
[
s
]
!=
0.0
||
edgeTo
[
s
]
!=
null
)
{
System
.
err
.
println
(
"distTo[s] and edgeTo[s] inconsistent"
);
return
false
;
}
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
v
==
s
)
continue
;
if
(
edgeTo
[
v
]
==
null
&&
distTo
[
v
]
!=
Double
.
POSITIVE_INFINITY
)
{
System
.
err
.
println
(
"distTo[] and edgeTo[] inconsistent"
);
return
false
;
}
}
// check that all edges e = v->w satisfy distTo[w] <= distTo[v] + e.weight()
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
for
(
DirectedEdge
e
:
G
.
adj
(
v
))
{
int
w
=
e
.
to
();
if
(
distTo
[
v
]
+
e
.
weight
()
<
distTo
[
w
])
{
System
.
err
.
println
(
"edge "
+
e
+
" not relaxed"
);
return
false
;
}
}
}
// check that all edges e = v->w on SPT satisfy distTo[w] == distTo[v] + e.weight()
for
(
int
w
=
0
;
w
<
G
.
V
();
w
++
)
{
if
(
edgeTo
[
w
]
==
null
)
continue
;
DirectedEdge
e
=
edgeTo
[
w
];
int
v
=
e
.
from
();
if
(
w
!=
e
.
to
())
return
false
;
if
(
distTo
[
v
]
+
e
.
weight
()
!=
distTo
[
w
])
{
System
.
err
.
println
(
"edge "
+
e
+
" on shortest path not tight"
);
return
false
;
}
}
return
true
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
distTo
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
DijkstraSP} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
EdgeWeightedDigraph
G
=
new
EdgeWeightedDigraph
(
in
);
int
s
=
Integer
.
parseInt
(
args
[
1
]);
// compute shortest paths
DijkstraSP
sp
=
new
DijkstraSP
(
G
,
s
);
// print shortest path
for
(
int
t
=
0
;
t
<
G
.
V
();
t
++
)
{
if
(
sp
.
hasPathTo
(
t
))
{
StdOut
.
printf
(
"%d to %d (%.2f) "
,
s
,
t
,
sp
.
distTo
(
t
));
for
(
DirectedEdge
e
:
sp
.
pathTo
(
t
))
{
StdOut
.
print
(
e
+
" "
);
}
StdOut
.
println
();
}
else
{
StdOut
.
printf
(
"%d to %d no path\n"
,
s
,
t
);
}
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/DijkstraUndirectedSP.java
edu/princeton/cs/algs4/DijkstraUndirectedSP.java
/******************************************************************************
* Compilation: javac DijkstraUndirectedSP.java
* Execution: java DijkstraUndirectedSP input.txt s
* Dependencies: EdgeWeightedGraph.java IndexMinPQ.java Stack.java Edge.java
* Data files: https://algs4.cs.princeton.edu/43mst/tinyEWG.txt
* https://algs4.cs.princeton.edu/43mst/mediumEWG.txt
* https://algs4.cs.princeton.edu/43mst/largeEWG.txt
*
* Dijkstra's algorithm. Computes the shortest path tree.
* Assumes all weights are nonnegative.
*
* % java DijkstraUndirectedSP tinyEWG.txt 6
* 6 to 0 (0.58) 6-0 0.58000
* 6 to 1 (0.76) 6-2 0.40000 1-2 0.36000
* 6 to 2 (0.40) 6-2 0.40000
* 6 to 3 (0.52) 3-6 0.52000
* 6 to 4 (0.93) 6-4 0.93000
* 6 to 5 (1.02) 6-2 0.40000 2-7 0.34000 5-7 0.28000
* 6 to 6 (0.00)
* 6 to 7 (0.74) 6-2 0.40000 2-7 0.34000
*
* % java DijkstraUndirectedSP mediumEWG.txt 0
* 0 to 0 (0.00)
* 0 to 1 (0.71) 0-44 0.06471 44-93 0.06793 ... 1-107 0.07484
* 0 to 2 (0.65) 0-44 0.06471 44-231 0.10384 ... 2-42 0.11456
* 0 to 3 (0.46) 0-97 0.07705 97-248 0.08598 ... 3-45 0.11902
* ...
*
* % java DijkstraUndirectedSP largeEWG.txt 0
* 0 to 0 (0.00)
* 0 to 1 (0.78) 0-460790 0.00190 460790-696678 0.00173 ... 1-826350 0.00191
* 0 to 2 (0.61) 0-15786 0.00130 15786-53370 0.00113 ... 2-793420 0.00040
* 0 to 3 (0.31) 0-460790 0.00190 460790-752483 0.00194 ... 3-698373 0.00172
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
DijkstraUndirectedSP} class represents a data type for solving
* the single-source shortest paths problem in edge-weighted graphs
* where the edge weights are nonnegative.
*
* This implementation uses Dijkstra’s algorithm with a binary heap.
* The constructor takes Θ(E log V) time in the
* worst case, where V is the number of vertices and
* E is the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the
* edge-weighted graph).
*
* For additional documentation,
* see Section 4.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
* See {
@link
DijkstraSP} for a version on edge-weighted digraphs.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*
@author
Nate Liu
*/
public
class
DijkstraUndirectedSP
{
private
double
[]
distTo
;
// distTo[v] = distance of shortest s->v path
private
Edge
[]
edgeTo
;
// edgeTo[v] = last edge on shortest s->v path
private
IndexMinPQ
<
Double
>
pq
;
// priority queue of vertices
/**
* Computes a shortest-paths tree from the source vertex {
@code
s} to every
* other vertex in the edge-weighted graph {
@code
G}.
*
*
@param
G the edge-weighted digraph
*
@param
s the source vertex
*
@throws
IllegalArgumentException if an edge weight is negative
*
@throws
IllegalArgumentException unless {
@code
0 <= s < V}
*/
public
DijkstraUndirectedSP
(
EdgeWeightedGraph
G
,
int
s
)
{
for
(
Edge
e
:
G
.
edges
())
{
if
(
e
.
weight
()
<
0
)
throw
new
IllegalArgumentException
(
"edge "
+
e
+
" has negative weight"
);
}
distTo
=
new
double
[
G
.
V
()];
edgeTo
=
new
Edge
[
G
.
V
()];
validateVertex
(
s
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
distTo
[
v
]
=
Double
.
POSITIVE_INFINITY
;
distTo
[
s
]
=
0.0
;
// relax vertices in order of distance from s
pq
=
new
IndexMinPQ
<
Double
>
(
G
.
V
());
pq
.
insert
(
s
,
distTo
[
s
]);
while
(
!
pq
.
isEmpty
())
{
int
v
=
pq
.
delMin
();
for
(
Edge
e
:
G
.
adj
(
v
))
relax
(
e
,
v
);
}
// check optimality conditions
assert
check
(
G
,
s
);
}
// relax edge e and update pq if changed
private
void
relax
(
Edge
e
,
int
v
)
{
int
w
=
e
.
other
(
v
);
if
(
distTo
[
w
]
>
distTo
[
v
]
+
e
.
weight
())
{
distTo
[
w
]
=
distTo
[
v
]
+
e
.
weight
();
edgeTo
[
w
]
=
e
;
if
(
pq
.
contains
(
w
))
pq
.
decreaseKey
(
w
,
distTo
[
w
]);
else
pq
.
insert
(
w
,
distTo
[
w
]);
}
}
/**
* Returns the length of a shortest path between the source vertex {
@code
s} and
* vertex {
@code
v}.
*
*
@param
v the destination vertex
*
@return
the length of a shortest path between the source vertex {
@code
s} and
* the vertex {
@code
v}; {
@code
Double.POSITIVE_INFINITY} if no such path
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
double
distTo
(
int
v
)
{
validateVertex
(
v
);
return
distTo
[
v
];
}
/**
* Returns true if there is a path between the source vertex {
@code
s} and
* vertex {
@code
v}.
*
*
@param
v the destination vertex
*
@return
{
@code
true} if there is a path between the source vertex
* {
@code
s} to vertex {
@code
v}; {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
boolean
hasPathTo
(
int
v
)
{
validateVertex
(
v
);
return
distTo
[
v
]
<
Double
.
POSITIVE_INFINITY
;
}
/**
* Returns a shortest path between the source vertex {
@code
s} and vertex {
@code
v}.
*
*
@param
v the destination vertex
*
@return
a shortest path between the source vertex {
@code
s} and vertex {
@code
v};
* {
@code
null} if no such path
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
Iterable
<
Edge
>
pathTo
(
int
v
)
{
validateVertex
(
v
);
if
(
!
hasPathTo
(
v
))
return
null
;
Stack
<
Edge
>
path
=
new
Stack
<
Edge
>
();
int
x
=
v
;
for
(
Edge
e
=
edgeTo
[
v
];
e
!=
null
;
e
=
edgeTo
[
x
])
{
path
.
push
(
e
);
x
=
e
.
other
(
x
);
}
return
path
;
}
// check optimality conditions:
// (i) for all edges e = v-w: distTo[w] <= distTo[v] + e.weight()
// (ii) for all edge e = v-w on the SPT: distTo[w] == distTo[v] + e.weight()
private
boolean
check
(
EdgeWeightedGraph
G
,
int
s
)
{
// check that edge weights are nonnegative
for
(
Edge
e
:
G
.
edges
())
{
if
(
e
.
weight
()
<
0
)
{
System
.
err
.
println
(
"negative edge weight detected"
);
return
false
;
}
}
// check that distTo[v] and edgeTo[v] are consistent
if
(
distTo
[
s
]
!=
0.0
||
edgeTo
[
s
]
!=
null
)
{
System
.
err
.
println
(
"distTo[s] and edgeTo[s] inconsistent"
);
return
false
;
}
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
v
==
s
)
continue
;
if
(
edgeTo
[
v
]
==
null
&&
distTo
[
v
]
!=
Double
.
POSITIVE_INFINITY
)
{
System
.
err
.
println
(
"distTo[] and edgeTo[] inconsistent"
);
return
false
;
}
}
// check that all edges e = v-w satisfy distTo[w] <= distTo[v] + e.weight()
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
for
(
Edge
e
:
G
.
adj
(
v
))
{
int
w
=
e
.
other
(
v
);
if
(
distTo
[
v
]
+
e
.
weight
()
<
distTo
[
w
])
{
System
.
err
.
println
(
"edge "
+
e
+
" not relaxed"
);
return
false
;
}
}
}
// check that all edges e = v-w on SPT satisfy distTo[w] == distTo[v] + e.weight()
for
(
int
w
=
0
;
w
<
G
.
V
();
w
++
)
{
if
(
edgeTo
[
w
]
==
null
)
continue
;
Edge
e
=
edgeTo
[
w
];
if
(
w
!=
e
.
either
()
&&
w
!=
e
.
other
(
e
.
either
()))
return
false
;
int
v
=
e
.
other
(
w
);
if
(
distTo
[
v
]
+
e
.
weight
()
!=
distTo
[
w
])
{
System
.
err
.
println
(
"edge "
+
e
+
" on shortest path not tight"
);
return
false
;
}
}
return
true
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
distTo
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
DijkstraUndirectedSP} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
EdgeWeightedGraph
G
=
new
EdgeWeightedGraph
(
in
);
int
s
=
Integer
.
parseInt
(
args
[
1
]);
// compute shortest paths
DijkstraUndirectedSP
sp
=
new
DijkstraUndirectedSP
(
G
,
s
);
// print shortest path
for
(
int
t
=
0
;
t
<
G
.
V
();
t
++
)
{
if
(
sp
.
hasPathTo
(
t
))
{
StdOut
.
printf
(
"%d to %d (%.2f) "
,
s
,
t
,
sp
.
distTo
(
t
));
for
(
Edge
e
:
sp
.
pathTo
(
t
))
{
StdOut
.
print
(
e
+
" "
);
}
StdOut
.
println
();
}
else
{
StdOut
.
printf
(
"%d to %d no path\n"
,
s
,
t
);
}
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/DirectedCycle.java
edu/princeton/cs/algs4/DirectedCycle.java
/******************************************************************************
* Compilation: javac DirectedCycle.java
* Execution: java DirectedCycle input.txt
* Dependencies: Digraph.java Stack.java StdOut.java In.java
* Data files: https://algs4.cs.princeton.edu/42digraph/tinyDG.txt
* https://algs4.cs.princeton.edu/42digraph/tinyDAG.txt
*
* Finds a directed cycle in a digraph.
*
* % java DirectedCycle tinyDG.txt
* Directed cycle: 3 5 4 3
*
* % java DirectedCycle tinyDAG.txt
* No directed cycle
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
DirectedCycle} class represents a data type for
* determining whether a digraph has a directed cycle.
* The hasCycle operation determines whether the digraph has
* a simple directed cycle and, if so, the cycle operation
* returns one.
*
* This implementation uses depth-first search.
* The constructor takes Θ(V + E) time in the worst
* case, where V is the number of vertices and E is
* the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the digraph).
*
* See {
@link
Topological} to compute a topological order if the
* digraph is acyclic.
*
* For additional documentation,
* see Section 4.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
DirectedCycle
{
private
boolean
[]
marked
;
// marked[v] = has vertex v been marked?
private
int
[]
edgeTo
;
// edgeTo[v] = previous vertex on path to v
private
boolean
[]
onStack
;
// onStack[v] = is vertex on the stack?
private
Stack
<
Integer
>
cycle
;
// directed cycle (or null if no such cycle)
/**
* Determines whether the digraph {
@code
G} has a directed cycle and, if so,
* finds such a cycle.
*
@param
G the digraph
*/
public
DirectedCycle
(
Digraph
G
)
{
marked
=
new
boolean
[
G
.
V
()];
onStack
=
new
boolean
[
G
.
V
()];
edgeTo
=
new
int
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
!
marked
[
v
]
&&
cycle
==
null
)
dfs
(
G
,
v
);
}
// check that algorithm computes either the topological order or finds a directed cycle
private
void
dfs
(
Digraph
G
,
int
v
)
{
onStack
[
v
]
=
true
;
marked
[
v
]
=
true
;
for
(
int
w
:
G
.
adj
(
v
))
{
// short circuit if directed cycle found
if
(
cycle
!=
null
)
return
;
// found new vertex, so recur
else
if
(
!
marked
[
w
])
{
edgeTo
[
w
]
=
v
;
dfs
(
G
,
w
);
}
// trace back directed cycle
else
if
(
onStack
[
w
])
{
cycle
=
new
Stack
<
Integer
>
();
for
(
int
x
=
v
;
x
!=
w
;
x
=
edgeTo
[
x
])
{
cycle
.
push
(
x
);
}
cycle
.
push
(
w
);
cycle
.
push
(
v
);
assert
check
();
}
}
onStack
[
v
]
=
false
;
}
/**
* Does the digraph have a directed cycle?
*
@return
{
@code
true} if the digraph has a directed cycle, {
@code
false} otherwise
*/
public
boolean
hasCycle
()
{
return
cycle
!=
null
;
}
/**
* Returns a directed cycle if the digraph has a directed cycle, and {
@code
null} otherwise.
*
@return
a directed cycle (as an iterable) if the digraph has a directed cycle,
* and {
@code
null} otherwise
*/
public
Iterable
<
Integer
>
cycle
()
{
return
cycle
;
}
// certify that digraph has a directed cycle if it reports one
private
boolean
check
()
{
if
(
hasCycle
())
{
// verify cycle
int
first
=
–
1
,
last
=
–
1
;
for
(
int
v
:
cycle
())
{
if
(
first
==
–
1
)
first
=
v
;
last
=
v
;
}
if
(
first
!=
last
)
{
System
.
err
.
printf
(
“cycle begins with %d and ends with %d\n”
,
first
,
last
);
return
false
;
}
}
return
true
;
}
/**
* Unit tests the {
@code
DirectedCycle} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
Digraph
G
=
new
Digraph
(
in
);
DirectedCycle
finder
=
new
DirectedCycle
(
G
);
if
(
finder
.
hasCycle
())
{
StdOut
.
print
(
“Directed cycle: ”
);
for
(
int
v
:
finder
.
cycle
())
{
StdOut
.
print
(
v
+
” ”
);
}
StdOut
.
println
();
}
else
{
StdOut
.
println
(
“No directed cycle”
);
}
StdOut
.
println
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/DirectedCycleX.java
edu/princeton/cs/algs4/DirectedCycleX.java
/******************************************************************************
* Compilation: javac DirectedCycleX.java
* Execution: java DirectedCycleX V E F
* Dependencies: Queue.java Digraph.java Stack.java
*
* Find a directed cycle in a digraph, using a nonrecursive, queue-based
* algorithm. Runs in O(E + V) time.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
DirectedCycleX} class represents a data type for
* determining whether a digraph has a directed cycle.
* The hasCycle operation determines whether the digraph has
* a simple directed cycle and, if so, the cycle operation
* returns one.
*
* This implementation uses a nonrecursive, queue-based algorithm.
* The constructor takes time proportional to V + E
* (in the worst case),
* where V is the number of vertices and E is the
* number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the digraph).
*
* See {
@link
DirectedCycle} for a recursive version that uses depth-first search.
* See {
@link
Topological} or {
@link
TopologicalX} to compute a topological order
* when the digraph is acyclic.
*
* For additional documentation,
* see Section 4.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
DirectedCycleX
{
private
Stack
<
Integer
>
cycle
;
// the directed cycle; null if digraph is acyclic
public
DirectedCycleX
(
Digraph
G
)
{
// indegrees of remaining vertices
int
[]
indegree
=
new
int
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
indegree
[
v
]
=
G
.
indegree
(
v
);
}
// initialize queue to contain all vertices with indegree = 0
Queue
<
Integer
>
queue
=
new
Queue
<
Integer
>
();
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
indegree
[
v
]
==
0
)
queue
.
enqueue
(
v
);
while
(
!
queue
.
isEmpty
())
{
int
v
=
queue
.
dequeue
();
for
(
int
w
:
G
.
adj
(
v
))
{
indegree
[
w
]
--
;
if
(
indegree
[
w
]
==
0
)
queue
.
enqueue
(
w
);
}
}
// there is a directed cycle in subgraph of vertices with indegree >= 1.
int
[]
edgeTo
=
new
int
[
G
.
V
()];
int
root
=
–
1
;
// any vertex with indegree >= -1
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
indegree
[
v
]
==
0
)
continue
;
else
root
=
v
;
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
indegree
[
w
]
>
0
)
{
edgeTo
[
w
]
=
v
;
}
}
}
if
(
root
!=
–
1
)
{
// find any vertex on cycle
boolean
[]
visited
=
new
boolean
[
G
.
V
()];
while
(
!
visited
[
root
])
{
visited
[
root
]
=
true
;
root
=
edgeTo
[
root
];
}
// extract cycle
cycle
=
new
Stack
<
Integer
>
();
int
v
=
root
;
do
{
cycle
.
push
(
v
);
v
=
edgeTo
[
v
];
}
while
(
v
!=
root
);
cycle
.
push
(
root
);
}
assert
check
();
}
/**
* Returns a directed cycle if the digraph has a directed cycle, and {
@code
null} otherwise.
*
@return
a directed cycle (as an iterable) if the digraph has a directed cycle,
* and {
@code
null} otherwise
*/
public
Iterable
<
Integer
>
cycle
()
{
return
cycle
;
}
/**
* Does the digraph have a directed cycle?
*
@return
{
@code
true} if the digraph has a directed cycle, {
@code
false} otherwise
*/
public
boolean
hasCycle
()
{
return
cycle
!=
null
;
}
// certify that digraph has a directed cycle if it reports one
private
boolean
check
()
{
if
(
hasCycle
())
{
// verify cycle
int
first
=
–
1
,
last
=
–
1
;
for
(
int
v
:
cycle
())
{
if
(
first
==
–
1
)
first
=
v
;
last
=
v
;
}
if
(
first
!=
last
)
{
System
.
err
.
printf
(
“cycle begins with %d and ends with %d\n”
,
first
,
last
);
return
false
;
}
}
return
true
;
}
public
static
void
main
(
String
[]
args
)
{
// create random DAG with V vertices and E edges; then add F random edges
int
V
=
Integer
.
parseInt
(
args
[
0
]);
int
E
=
Integer
.
parseInt
(
args
[
1
]);
int
F
=
Integer
.
parseInt
(
args
[
2
]);
Digraph
G
=
DigraphGenerator
.
dag
(
V
,
E
);
// add F extra edges
for
(
int
i
=
0
;
i
<
F
;
i
++
)
{
int
v
=
StdRandom
.
uniform
(
V
);
int
w
=
StdRandom
.
uniform
(
V
);
G
.
addEdge
(
v
,
w
);
}
StdOut
.
println
(
G
);
DirectedCycleX
finder
=
new
DirectedCycleX
(
G
);
if
(
finder
.
hasCycle
())
{
StdOut
.
print
(
"Directed cycle: "
);
for
(
int
v
:
finder
.
cycle
())
{
StdOut
.
print
(
v
+
" "
);
}
StdOut
.
println
();
}
else
{
StdOut
.
println
(
"No directed cycle"
);
}
StdOut
.
println
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/DirectedDFS.java
edu/princeton/cs/algs4/DirectedDFS.java
/******************************************************************************
* Compilation: javac DirectedDFS.java
* Execution: java DirectedDFS digraph.txt s
* Dependencies: Digraph.java Bag.java In.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/42digraph/tinyDG.txt
* https://algs4.cs.princeton.edu/42digraph/mediumDG.txt
* https://algs4.cs.princeton.edu/42digraph/largeDG.txt
*
* Determine single-source or multiple-source reachability in a digraph
* using depth first search.
* Runs in O(E + V) time.
*
* % java DirectedDFS tinyDG.txt 1
* 1
*
* % java DirectedDFS tinyDG.txt 2
* 0 1 2 3 4 5
*
* % java DirectedDFS tinyDG.txt 1 2 6
* 0 1 2 3 4 5 6 8 9 10 11 12
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
DirectedDFS} class represents a data type for
* determining the vertices reachable from a given source vertex s
* (or set of source vertices) in a digraph. For versions that find the paths,
* see {
@link
DepthFirstDirectedPaths} and {
@link
BreadthFirstDirectedPaths}.
*
* This implementation uses depth-first search.
* The constructor takes time proportional to V + E
* (in the worst case),
* where V is the number of vertices and E is the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the digraph).
*
* For additional documentation,
* see Section 4.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
DirectedDFS
{
private
boolean
[]
marked
;
// marked[v] = true iff v is reachable from source(s)
private
int
count
;
// number of vertices reachable from source(s)
/**
* Computes the vertices in digraph {
@code
G} that are
* reachable from the source vertex {
@code
s}.
*
@param
G the digraph
*
@param
s the source vertex
*
@throws
IllegalArgumentException unless {
@code
0 <= s < V}
*/
public
DirectedDFS
(
Digraph
G
,
int
s
)
{
marked
=
new
boolean
[
G
.
V
()];
validateVertex
(
s
);
dfs
(
G
,
s
);
}
/**
* Computes the vertices in digraph {
@code
G} that are
* connected to any of the source vertices {
@code
sources}.
*
@param
G the graph
*
@param
sources the source vertices
*
@throws
IllegalArgumentException unless {
@code
0 <= s < V}
* for each vertex {
@code
s} in {
@code
sources}
*/
public
DirectedDFS
(
Digraph
G
,
Iterable
<
Integer
>
sources
)
{
marked
=
new
boolean
[
G
.
V
()];
validateVertices
(
sources
);
for
(
int
v
:
sources
)
{
if
(
!
marked
[
v
])
dfs
(
G
,
v
);
}
}
private
void
dfs
(
Digraph
G
,
int
v
)
{
count
++
;
marked
[
v
]
=
true
;
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
!
marked
[
w
])
dfs
(
G
,
w
);
}
}
/**
* Is there a directed path from the source vertex (or any
* of the source vertices) and vertex {
@code
v}?
*
@param
v the vertex
*
@return
{
@code
true} if there is a directed path, {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
boolean
marked
(
int
v
)
{
validateVertex
(
v
);
return
marked
[
v
];
}
/**
* Returns the number of vertices reachable from the source vertex
* (or source vertices).
*
@return
the number of vertices reachable from the source vertex
* (or source vertices)
*/
public
int
count
()
{
return
count
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
marked
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertices
(
Iterable
<
Integer
>
vertices
)
{
if
(
vertices
==
null
)
{
throw
new
IllegalArgumentException
(
“argument is null”
);
}
int
V
=
marked
.
length
;
for
(
int
v
:
vertices
)
{
if
(
v
<
0
||
v
>=
V
)
{
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
}
}
/**
* Unit tests the {
@code
DirectedDFS} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// read in digraph from command-line argument
In
in
=
new
In
(
args
[
0
]);
Digraph
G
=
new
Digraph
(
in
);
// read in sources from command-line arguments
Bag
<
Integer
>
sources
=
new
Bag
<
Integer
>
();
for
(
int
i
=
1
;
i
<
args
.
length
;
i
++
)
{
int
s
=
Integer
.
parseInt
(
args
[
i
]);
sources
.
add
(
s
);
}
// multiple-source reachability
DirectedDFS
dfs
=
new
DirectedDFS
(
G
,
sources
);
// print out vertices reachable from sources
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
dfs
.
marked
(
v
))
StdOut
.
print
(
v
+
" "
);
}
StdOut
.
println
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/DirectedEdge.java
edu/princeton/cs/algs4/DirectedEdge.java
/******************************************************************************
* Compilation: javac DirectedEdge.java
* Execution: java DirectedEdge
* Dependencies: StdOut.java
*
* Immutable weighted directed edge.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
DirectedEdge} class represents a weighted edge in an
* {
@link
EdgeWeightedDigraph}. Each edge consists of two integers
* (naming the two vertices) and a real-value weight. The data type
* provides methods for accessing the two endpoints of the directed edge and
* the weight.
*
* For additional documentation, see Section 4.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
DirectedEdge
{
private
final
int
v
;
private
final
int
w
;
private
final
double
weight
;
/**
* Initializes a directed edge from vertex {
@code
v} to vertex {
@code
w} with
* the given {
@code
weight}.
*
@param
v the tail vertex
*
@param
w the head vertex
*
@param
weight the weight of the directed edge
*
@throws
IllegalArgumentException if either {
@code
v} or {
@code
w}
* is a negative integer
*
@throws
IllegalArgumentException if {
@code
weight} is {
@code
NaN}
*/
public
DirectedEdge
(
int
v
,
int
w
,
double
weight
)
{
if
(
v
<
0
)
throw
new
IllegalArgumentException
(
"Vertex names must be nonnegative integers"
);
if
(
w
<
0
)
throw
new
IllegalArgumentException
(
"Vertex names must be nonnegative integers"
);
if
(
Double
.
isNaN
(
weight
))
throw
new
IllegalArgumentException
(
"Weight is NaN"
);
this
.
v
=
v
;
this
.
w
=
w
;
this
.
weight
=
weight
;
}
/**
* Returns the tail vertex of the directed edge.
*
@return
the tail vertex of the directed edge
*/
public
int
from
()
{
return
v
;
}
/**
* Returns the head vertex of the directed edge.
*
@return
the head vertex of the directed edge
*/
public
int
to
()
{
return
w
;
}
/**
* Returns the weight of the directed edge.
*
@return
the weight of the directed edge
*/
public
double
weight
()
{
return
weight
;
}
/**
* Returns a string representation of the directed edge.
*
@return
a string representation of the directed edge
*/
public
String
toString
()
{
return
v
+
"->”
+
w
+
” ”
+
String
.
format
(
“%5.2f”
,
weight
);
}
/**
* Unit tests the {
@code
DirectedEdge} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
DirectedEdge
e
=
new
DirectedEdge
(
12
,
34
,
5.67
);
StdOut
.
println
(
e
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/DirectedEulerianCycle.java
edu/princeton/cs/algs4/DirectedEulerianCycle.java
/******************************************************************************
* Compilation: javac DirectedEulerianCycle.java
* Execution: java DirectedEulerianCycle V E
* Dependencies: Digraph.java Stack.java StdOut.java
* BreadthFirstPaths.java
* DigraphGenerator.java StdRandom.java
*
* Find an Eulerian cycle in a digraph, if one exists.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Iterator
;
/**
* The {
@code
DirectedEulerianCycle} class represents a data type
* for finding an Eulerian cycle or path in a digraph.
* An Eulerian cycle is a cycle (not necessarily simple) that
* uses every edge in the digraph exactly once.
*
* This implementation uses a nonrecursive depth-first search.
* The constructor takes Θ(E + V) time in the worst
* case, where E is the number of edges and V is the
* number of vertices
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the digraph).
*
* To compute Eulerian paths in digraphs, see {
@link
DirectedEulerianPath}.
* To compute Eulerian cycles and paths in undirected graphs, see
* {
@link
EulerianCycle} and {
@link
EulerianPath}.
*
* For additional documentation,
* see Section 4.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*
@author
Nate Liu
*/
public
class
DirectedEulerianCycle
{
private
Stack
<
Integer
>
cycle
=
null
;
// Eulerian cycle; null if no such cylce
/**
* Computes an Eulerian cycle in the specified digraph, if one exists.
*
*
@param
G the digraph
*/
public
DirectedEulerianCycle
(
Digraph
G
)
{
// must have at least one edge
if
(
G
.
E
()
==
0
)
return
;
// necessary condition: indegree(v) = outdegree(v) for each vertex v
// (without this check, DFS might return a path instead of a cycle)
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
G
.
outdegree
(
v
)
!=
G
.
indegree
(
v
))
return
;
// create local view of adjacency lists, to iterate one vertex at a time
Iterator
<
Integer
>
[]
adj
=
(
Iterator
<
Integer
>
[])
new
Iterator
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
adj
[
v
]
=
G
.
adj
(
v
).
iterator
();
// initialize stack with any non-isolated vertex
int
s
=
nonIsolatedVertex
(
G
);
Stack
<
Integer
>
stack
=
new
Stack
<
Integer
>
();
stack
.
push
(
s
);
// greedily add to putative cycle, depth-first search style
cycle
=
new
Stack
<
Integer
>
();
while
(
!
stack
.
isEmpty
())
{
int
v
=
stack
.
pop
();
while
(
adj
[
v
].
hasNext
())
{
stack
.
push
(
v
);
v
=
adj
[
v
].
next
();
}
// add vertex with no more leaving edges to cycle
cycle
.
push
(
v
);
}
// check if all edges have been used
// (in case there are two or more vertex-disjoint Eulerian cycles)
if
(
cycle
.
size
()
!=
G
.
E
()
+
1
)
cycle
=
null
;
assert
certifySolution
(
G
);
}
/**
* Returns the sequence of vertices on an Eulerian cycle.
*
*
@return
the sequence of vertices on an Eulerian cycle;
* {
@code
null} if no such cycle
*/
public
Iterable
<
Integer
>
cycle
()
{
return
cycle
;
}
/**
* Returns true if the digraph has an Eulerian cycle.
*
*
@return
{
@code
true} if the digraph has an Eulerian cycle;
* {
@code
false} otherwise
*/
public
boolean
hasEulerianCycle
()
{
return
cycle
!=
null
;
}
// returns any non-isolated vertex; -1 if no such vertex
private
static
int
nonIsolatedVertex
(
Digraph
G
)
{
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
G
.
outdegree
(
v
)
>
0
)
return
v
;
return
–
1
;
}
/**************************************************************************
*
* The code below is solely for testing correctness of the data type.
*
**************************************************************************/
// Determines whether a digraph has an Eulerian cycle using necessary
// and sufficient conditions (without computing the cycle itself):
// – at least one edge
// – indegree(v) = outdegree(v) for every vertex
// – the graph is connected, when viewed as an undirected graph
// (ignoring isolated vertices)
private
static
boolean
satisfiesNecessaryAndSufficientConditions
(
Digraph
G
)
{
// Condition 0: at least 1 edge
if
(
G
.
E
()
==
0
)
return
false
;
// Condition 1: indegree(v) == outdegree(v) for every vertex
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
G
.
outdegree
(
v
)
!=
G
.
indegree
(
v
))
return
false
;
// Condition 2: graph is connected, ignoring isolated vertices
Graph
H
=
new
Graph
(
G
.
V
());
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
for
(
int
w
:
G
.
adj
(
v
))
H
.
addEdge
(
v
,
w
);
// check that all non-isolated vertices are conneted
int
s
=
nonIsolatedVertex
(
G
);
BreadthFirstPaths
bfs
=
new
BreadthFirstPaths
(
H
,
s
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
H
.
degree
(
v
)
>
0
&&
!
bfs
.
hasPathTo
(
v
))
return
false
;
return
true
;
}
// check that solution is correct
private
boolean
certifySolution
(
Digraph
G
)
{
// internal consistency check
if
(
hasEulerianCycle
()
==
(
cycle
()
==
null
))
return
false
;
// hashEulerianCycle() returns correct value
if
(
hasEulerianCycle
()
!=
satisfiesNecessaryAndSufficientConditions
(
G
))
return
false
;
// nothing else to check if no Eulerian cycle
if
(
cycle
==
null
)
return
true
;
// check that cycle() uses correct number of edges
if
(
cycle
.
size
()
!=
G
.
E
()
+
1
)
return
false
;
// check that cycle() is a directed cycle of G
// TODO
return
true
;
}
private
static
void
unitTest
(
Digraph
G
,
String
description
)
{
StdOut
.
println
(
description
);
StdOut
.
println
(
“————————————-”
);
StdOut
.
print
(
G
);
DirectedEulerianCycle
euler
=
new
DirectedEulerianCycle
(
G
);
StdOut
.
print
(
“Eulerian cycle: ”
);
if
(
euler
.
hasEulerianCycle
())
{
for
(
int
v
:
euler
.
cycle
())
{
StdOut
.
print
(
v
+
” ”
);
}
StdOut
.
println
();
}
else
{
StdOut
.
println
(
“none”
);
}
StdOut
.
println
();
}
/**
* Unit tests the {
@code
DirectedEulerianCycle} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
V
=
Integer
.
parseInt
(
args
[
0
]);
int
E
=
Integer
.
parseInt
(
args
[
1
]);
// Eulerian cycle
Digraph
G1
=
DigraphGenerator
.
eulerianCycle
(
V
,
E
);
unitTest
(
G1
,
“Eulerian cycle”
);
// Eulerian path
Digraph
G2
=
DigraphGenerator
.
eulerianPath
(
V
,
E
);
unitTest
(
G2
,
“Eulerian path”
);
// empty digraph
Digraph
G3
=
new
Digraph
(
V
);
unitTest
(
G3
,
“empty digraph”
);
// self loop
Digraph
G4
=
new
Digraph
(
V
);
int
v4
=
StdRandom
.
uniform
(
V
);
G4
.
addEdge
(
v4
,
v4
);
unitTest
(
G4
,
“single self loop”
);
// union of two disjoint cycles
Digraph
H1
=
DigraphGenerator
.
eulerianCycle
(
V
/
2
,
E
/
2
);
Digraph
H2
=
DigraphGenerator
.
eulerianCycle
(
V
–
V
/
2
,
E
–
E
/
2
);
int
[]
perm
=
new
int
[
V
];
for
(
int
i
=
0
;
i
<
V
;
i
++
)
perm
[
i
]
=
i
;
StdRandom
.
shuffle
(
perm
);
Digraph
G5
=
new
Digraph
(
V
);
for
(
int
v
=
0
;
v
<
H1
.
V
();
v
++
)
for
(
int
w
:
H1
.
adj
(
v
))
G5
.
addEdge
(
perm
[
v
],
perm
[
w
]);
for
(
int
v
=
0
;
v
<
H2
.
V
();
v
++
)
for
(
int
w
:
H2
.
adj
(
v
))
G5
.
addEdge
(
perm
[
V
/
2
+
v
],
perm
[
V
/
2
+
w
]);
unitTest
(
G5
,
"Union of two disjoint cycles"
);
// random digraph
Digraph
G6
=
DigraphGenerator
.
simple
(
V
,
E
);
unitTest
(
G6
,
"simple digraph"
);
// 4-vertex digraph
Digraph
G7
=
new
Digraph
(
new
In
(
"eulerianD.txt"
));
unitTest
(
G7
,
"4-vertex Eulerian digraph"
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/DirectedEulerianPath.java
edu/princeton/cs/algs4/DirectedEulerianPath.java
/******************************************************************************
* Compilation: javac DirectedEulerianPath.java
* Execution: java DirectedEulerianPath V E
* Dependencies: Digraph.java Stack.java StdOut.java
* BreadthFirstPaths.java
* DigraphGenerator.java StdRandom.java
*
* Find an Eulerian path in a digraph, if one exists.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Iterator
;
/**
* The {
@code
DirectedEulerianPath} class represents a data type
* for finding an Eulerian path in a digraph.
* An Eulerian path is a path (not necessarily simple) that
* uses every edge in the digraph exactly once.
*
* This implementation uses a nonrecursive depth-first search.
* The constructor take Θ(E + V) time
* in the worst case, where E is the number of edges and
* V is the number of vertices.
* It uses Θ(V) extra space (not including the digraph).
*
* To compute Eulerian cycles in digraphs, see {
@link
DirectedEulerianCycle}.
* To compute Eulerian cycles and paths in undirected graphs, see
* {
@link
EulerianCycle} and {
@link
EulerianPath}.
*
* For additional documentation,
* see Section 4.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*
@author
Nate Liu
*/
public
class
DirectedEulerianPath
{
private
Stack
<
Integer
>
path
=
null
;
// Eulerian path; null if no suh path
/**
* Computes an Eulerian path in the specified digraph, if one exists.
*
*
@param
G the digraph
*/
public
DirectedEulerianPath
(
Digraph
G
)
{
// find vertex from which to start potential Eulerian path:
// a vertex v with outdegree(v) > indegree(v) if it exits;
// otherwise a vertex with outdegree(v) > 0
int
deficit
=
0
;
int
s
=
nonIsolatedVertex
(
G
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
G
.
outdegree
(
v
)
>
G
.
indegree
(
v
))
{
deficit
+=
(
G
.
outdegree
(
v
)
–
G
.
indegree
(
v
));
s
=
v
;
}
}
// digraph can’t have an Eulerian path
// (this condition is needed)
if
(
deficit
>
1
)
return
;
// special case for digraph with zero edges (has a degenerate Eulerian path)
if
(
s
==
–
1
)
s
=
0
;
// create local view of adjacency lists, to iterate one vertex at a time
Iterator
<
Integer
>
[]
adj
=
(
Iterator
<
Integer
>
[])
new
Iterator
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
adj
[
v
]
=
G
.
adj
(
v
).
iterator
();
// greedily add to cycle, depth-first search style
Stack
<
Integer
>
stack
=
new
Stack
<
Integer
>
();
stack
.
push
(
s
);
path
=
new
Stack
<
Integer
>
();
while
(
!
stack
.
isEmpty
())
{
int
v
=
stack
.
pop
();
while
(
adj
[
v
].
hasNext
())
{
stack
.
push
(
v
);
v
=
adj
[
v
].
next
();
}
// push vertex with no more available edges to path
path
.
push
(
v
);
}
// check if all edges have been used
if
(
path
.
size
()
!=
G
.
E
()
+
1
)
path
=
null
;
assert
check
(
G
);
}
/**
* Returns the sequence of vertices on an Eulerian path.
*
*
@return
the sequence of vertices on an Eulerian path;
* {
@code
null} if no such path
*/
public
Iterable
<
Integer
>
path
()
{
return
path
;
}
/**
* Returns true if the digraph has an Eulerian path.
*
*
@return
{
@code
true} if the digraph has an Eulerian path;
* {
@code
false} otherwise
*/
public
boolean
hasEulerianPath
()
{
return
path
!=
null
;
}
// returns any non-isolated vertex; -1 if no such vertex
private
static
int
nonIsolatedVertex
(
Digraph
G
)
{
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
G
.
outdegree
(
v
)
>
0
)
return
v
;
return
–
1
;
}
/**************************************************************************
*
* The code below is solely for testing correctness of the data type.
*
**************************************************************************/
// Determines whether a digraph has an Eulerian path using necessary
// and sufficient conditions (without computing the path itself):
// – indegree(v) = outdegree(v) for every vertex,
// except one vertex v may have outdegree(v) = indegree(v) + 1
// (and one vertex v may have indegree(v) = outdegree(v) + 1)
// – the graph is connected, when viewed as an undirected graph
// (ignoring isolated vertices)
private
static
boolean
satisfiesNecessaryAndSufficientConditions
(
Digraph
G
)
{
if
(
G
.
E
()
==
0
)
return
true
;
// Condition 1: indegree(v) == outdegree(v) for every vertex,
// except one vertex may have outdegree(v) = indegree(v) + 1
int
deficit
=
0
;
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
G
.
outdegree
(
v
)
>
G
.
indegree
(
v
))
deficit
+=
(
G
.
outdegree
(
v
)
–
G
.
indegree
(
v
));
if
(
deficit
>
1
)
return
false
;
// Condition 2: graph is connected, ignoring isolated vertices
Graph
H
=
new
Graph
(
G
.
V
());
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
for
(
int
w
:
G
.
adj
(
v
))
H
.
addEdge
(
v
,
w
);
// check that all non-isolated vertices are connected
int
s
=
nonIsolatedVertex
(
G
);
BreadthFirstPaths
bfs
=
new
BreadthFirstPaths
(
H
,
s
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
H
.
degree
(
v
)
>
0
&&
!
bfs
.
hasPathTo
(
v
))
return
false
;
return
true
;
}
private
boolean
check
(
Digraph
G
)
{
// internal consistency check
if
(
hasEulerianPath
()
==
(
path
()
==
null
))
return
false
;
// hashEulerianPath() returns correct value
if
(
hasEulerianPath
()
!=
satisfiesNecessaryAndSufficientConditions
(
G
))
return
false
;
// nothing else to check if no Eulerian path
if
(
path
==
null
)
return
true
;
// check that path() uses correct number of edges
if
(
path
.
size
()
!=
G
.
E
()
+
1
)
return
false
;
// check that path() is a directed path in G
// TODO
return
true
;
}
private
static
void
unitTest
(
Digraph
G
,
String
description
)
{
StdOut
.
println
(
description
);
StdOut
.
println
(
“————————————-”
);
StdOut
.
print
(
G
);
DirectedEulerianPath
euler
=
new
DirectedEulerianPath
(
G
);
StdOut
.
print
(
“Eulerian path: ”
);
if
(
euler
.
hasEulerianPath
())
{
for
(
int
v
:
euler
.
path
())
{
StdOut
.
print
(
v
+
” ”
);
}
StdOut
.
println
();
}
else
{
StdOut
.
println
(
“none”
);
}
StdOut
.
println
();
}
/**
* Unit tests the {
@code
DirectedEulerianPath} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
V
=
Integer
.
parseInt
(
args
[
0
]);
int
E
=
Integer
.
parseInt
(
args
[
1
]);
// Eulerian cycle
Digraph
G1
=
DigraphGenerator
.
eulerianCycle
(
V
,
E
);
unitTest
(
G1
,
“Eulerian cycle”
);
// Eulerian path
Digraph
G2
=
DigraphGenerator
.
eulerianPath
(
V
,
E
);
unitTest
(
G2
,
“Eulerian path”
);
// add one random edge
Digraph
G3
=
new
Digraph
(
G2
);
G3
.
addEdge
(
StdRandom
.
uniform
(
V
),
StdRandom
.
uniform
(
V
));
unitTest
(
G3
,
“one random edge added to Eulerian path”
);
// self loop
Digraph
G4
=
new
Digraph
(
V
);
int
v4
=
StdRandom
.
uniform
(
V
);
G4
.
addEdge
(
v4
,
v4
);
unitTest
(
G4
,
“single self loop”
);
// single edge
Digraph
G5
=
new
Digraph
(
V
);
G5
.
addEdge
(
StdRandom
.
uniform
(
V
),
StdRandom
.
uniform
(
V
));
unitTest
(
G5
,
“single edge”
);
// empty digraph
Digraph
G6
=
new
Digraph
(
V
);
unitTest
(
G6
,
“empty digraph”
);
// random digraph
Digraph
G7
=
DigraphGenerator
.
simple
(
V
,
E
);
unitTest
(
G7
,
“simple digraph”
);
// 4-vertex digraph
Digraph
G8
=
new
Digraph
(
new
In
(
“eulerianD.txt”
));
unitTest
(
G8
,
“4-vertex Eulerian digraph”
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/DoublingRatio.java
edu/princeton/cs/algs4/DoublingRatio.java
/******************************************************************************
* Compilation: javac DoublingRatio.java
* Execution: java DoublingRatio
* Dependencies: ThreeSum.java Stopwatch.java StdRandom.java StdOut.java
*
*
* % java DoublingRatio
* 250 0.0 2.7
* 500 0.0 4.8
* 1000 0.1 6.9
* 2000 0.6 7.7
* 4000 4.5 8.0
* 8000 35.7 8.0
* 4000 3.9 6.6
* …
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
DoublingRatio} class provides a client for measuring
* the running time of a method using a doubling ratio test.
*
* For additional documentation, see Section 1.4
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
DoublingRatio
{
private
static
final
int
MAXIMUM_INTEGER
=
1000000
;
// This class should not be instantiated.
private
DoublingRatio
()
{
}
/**
* Returns the amount of time to call {
@code
ThreeSum.count()} with n
* random 6-digit integers.
*
@param
n the number of integers
*
@return
amount of time (in seconds) to call {
@code
ThreeSum.count()}
* with n random 6-digit integers
*/
public
static
double
timeTrial
(
int
n
)
{
int
[]
a
=
new
int
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
a
[
i
]
=
StdRandom
.
uniform
(
-
MAXIMUM_INTEGER
,
MAXIMUM_INTEGER
);
}
Stopwatch
timer
=
new
Stopwatch
();
ThreeSum
.
count
(
a
);
return
timer
.
elapsedTime
();
}
/**
* Prints table of running times to call {
@code
ThreeSum.count()}
* for arrays of size 250, 500, 1000, 2000, and so forth, along
* with ratios of running times between successive array sizes.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
double
prev
=
timeTrial
(
125
);
for
(
int
n
=
250
;
true
;
n
+=
n
)
{
double
time
=
timeTrial
(
n
);
StdOut
.
printf
(
"%7d %7.1f %5.1f\n"
,
n
,
time
,
time
/
prev
);
prev
=
time
;
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/DoublingTest.java
edu/princeton/cs/algs4/DoublingTest.java
/******************************************************************************
* Compilation: javac DoublingTest.java
* Execution: java DoublingTest
* Dependencies: ThreeSum.java Stopwatch.java StdRandom.java StdOut.java
*
* % java DoublingTest
* 250 0.0
* 500 0.0
* 1000 0.1
* 2000 0.6
* 4000 4.5
* 8000 35.7
* ...
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
DoublingTest} class provides a client for measuring
* the running time of a method using a doubling test.
*
* For additional documentation, see Section 1.4
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
DoublingTest
{
private
static
final
int
MAXIMUM_INTEGER
=
1000000
;
// This class should not be instantiated.
private
DoublingTest
()
{
}
/**
* Returns the amount of time to call {
@code
ThreeSum.count()} with n
* random 6-digit integers.
*
@param
n the number of integers
*
@return
amount of time (in seconds) to call {
@code
ThreeSum.count()}
* with n random 6-digit integers
*/
public
static
double
timeTrial
(
int
n
)
{
int
[]
a
=
new
int
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
a
[
i
]
=
StdRandom
.
uniform
(
-
MAXIMUM_INTEGER
,
MAXIMUM_INTEGER
);
}
Stopwatch
timer
=
new
Stopwatch
();
ThreeSum
.
count
(
a
);
return
timer
.
elapsedTime
();
}
/**
* Prints table of running times to call {
@code
ThreeSum.count()}
* for arrays of size 250, 500, 1000, 2000, and so forth.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
for
(
int
n
=
250
;
true
;
n
+=
n
)
{
double
time
=
timeTrial
(
n
);
StdOut
.
printf
(
"%7d %7.1f\n"
,
n
,
time
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Draw.java
edu/princeton/cs/algs4/Draw.java
/******************************************************************************
* Compilation: javac Draw.java
* Execution: java Draw
* Dependencies: none
*
* Drawing library. This class provides a basic capability for creating
* drawings with your programs. It uses a simple graphics model that
* allows you to create drawings consisting of points, lines, and curves
* in a window on your computer and to save the drawings to a file.
* This is the object-oriented version of standard draw; it supports
* multiple indepedent drawing windows.
*
* Todo
* ----
* - Add support for gradient fill, etc.
*
* Remarks
* -------
* - don't use AffineTransform for rescaling since it inverts
* images and strings
* - careful using setFont in inner loop within an animation -
* it can cause flicker
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
awt
.
BasicStroke
;
import
java
.
awt
.
Color
;
import
java
.
awt
.
Component
;
import
java
.
awt
.
FileDialog
;
import
java
.
awt
.
Font
;
import
java
.
awt
.
FontMetrics
;
import
java
.
awt
.
Graphics
;
import
java
.
awt
.
Graphics2D
;
import
java
.
awt
.
Image
;
import
java
.
awt
.
MediaTracker
;
import
java
.
awt
.
RenderingHints
;
import
java
.
awt
.
Toolkit
;
import
java
.
awt
.
event
.
ActionEvent
;
import
java
.
awt
.
event
.
ActionListener
;
import
java
.
awt
.
event
.
MouseEvent
;
import
java
.
awt
.
event
.
MouseListener
;
import
java
.
awt
.
event
.
MouseMotionListener
;
import
java
.
awt
.
event
.
KeyEvent
;
import
java
.
awt
.
event
.
KeyListener
;
import
java
.
awt
.
geom
.
Arc2D
;
import
java
.
awt
.
geom
.
Ellipse2D
;
import
java
.
awt
.
geom
.
GeneralPath
;
import
java
.
awt
.
geom
.
Line2D
;
import
java
.
awt
.
geom
.
Rectangle2D
;
import
java
.
awt
.
image
.
BufferedImage
;
import
java
.
awt
.
image
.
DirectColorModel
;
import
java
.
awt
.
image
.
WritableRaster
;
import
java
.
io
.
File
;
import
java
.
io
.
IOException
;
import
java
.
net
.
MalformedURLException
;
import
java
.
net
.
URL
;
import
java
.
util
.
ArrayList
;
import
java
.
util
.
LinkedList
;
import
java
.
util
.
TreeSet
;
import
javax
.
imageio
.
ImageIO
;
import
javax
.
swing
.
ImageIcon
;
import
javax
.
swing
.
JFrame
;
import
javax
.
swing
.
JLabel
;
import
javax
.
swing
.
JMenu
;
import
javax
.
swing
.
JMenuBar
;
import
javax
.
swing
.
JMenuItem
;
import
javax
.
swing
.
KeyStroke
;
/**
* Draw. This class provides a basic capability for
* creating drawings with your programs. It uses a simple graphics model that
* allows you to create drawings consisting of points, lines, and curves
* in a window on your computer and to save the drawings to a file.
* This is the object-oriented version of standard draw; it supports
* multiple indepedent drawing windows.
*
* For additional documentation, see
* Section 3.1 of
* Computer Science: An Interdisciplinary Approach by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
Draw
implements
ActionListener
,
MouseListener
,
MouseMotionListener
,
KeyListener
{
/**
* The color black.
*/
public
static
final
Color
BLACK
=
Color
.
BLACK
;
/**
* The color blue.
*/
public
static
final
Color
BLUE
=
Color
.
BLUE
;
/**
* The color cyan.
*/
public
static
final
Color
CYAN
=
Color
.
CYAN
;
/**
* The color dark gray.
*/
public
static
final
Color
DARK_GRAY
=
Color
.
DARK_GRAY
;
/**
* The color gray.
*/
public
static
final
Color
GRAY
=
Color
.
GRAY
;
/**
* The color green.
*/
public
static
final
Color
GREEN
=
Color
.
GREEN
;
/**
* The color light gray.
*/
public
static
final
Color
LIGHT_GRAY
=
Color
.
LIGHT_GRAY
;
/**
* The color magenta.
*/
public
static
final
Color
MAGENTA
=
Color
.
MAGENTA
;
/**
* The color orange.
*/
public
static
final
Color
ORANGE
=
Color
.
ORANGE
;
/**
* The color pink.
*/
public
static
final
Color
PINK
=
Color
.
PINK
;
/**
* The color red.
*/
public
static
final
Color
RED
=
Color
.
RED
;
/**
* The color white.
*/
public
static
final
Color
WHITE
=
Color
.
WHITE
;
/**
* The color yellow.
*/
public
static
final
Color
YELLOW
=
Color
.
YELLOW
;
/**
* Shade of blue used in Introduction to Programming in Java.
* It is Pantone 300U. The RGB values are approximately (9, 90, 166).
*/
public
static
final
Color
BOOK_BLUE
=
new
Color
(
9
,
90
,
166
);
/**
* Shade of light blue used in Introduction to Programming in Java.
* The RGB values are approximately (103, 198, 243).
*/
public
static
final
Color
BOOK_LIGHT_BLUE
=
new
Color
(
103
,
198
,
243
);
/**
* Shade of red used in Algorithms, 4th edition.
* It is Pantone 1805U. The RGB values are approximately (150, 35, 31).
*/
public
static
final
Color
BOOK_RED
=
new
Color
(
150
,
35
,
31
);
/**
* Shade of orange used in Princeton’s identity.
* It is PMS 158. The RGB values are approximately (245, 128, 37).
*/
public
static
final
Color
PRINCETON_ORANGE
=
new
Color
(
245
,
128
,
37
);
// default colors
private
static
final
Color
DEFAULT_PEN_COLOR
=
BLACK
;
private
static
final
Color
DEFAULT_CLEAR_COLOR
=
WHITE
;
// boundary of drawing canvas, 0% border
private
static
final
double
BORDER
=
0.0
;
private
static
final
double
DEFAULT_XMIN
=
0.0
;
private
static
final
double
DEFAULT_XMAX
=
1.0
;
private
static
final
double
DEFAULT_YMIN
=
0.0
;
private
static
final
double
DEFAULT_YMAX
=
1.0
;
// default canvas size is SIZE-by-SIZE
private
static
final
int
DEFAULT_SIZE
=
512
;
// default pen radius
private
static
final
double
DEFAULT_PEN_RADIUS
=
0.002
;
// default font
private
static
final
Font
DEFAULT_FONT
=
new
Font
(
“SansSerif”
,
Font
.
PLAIN
,
16
);
// current pen color
private
Color
penColor
;
// canvas size
private
int
width
=
DEFAULT_SIZE
;
private
int
height
=
DEFAULT_SIZE
;
// current pen radius
private
double
penRadius
;
// show we draw immediately or wait until next show?
private
boolean
defer
=
false
;
private
double
xmin
,
ymin
,
xmax
,
ymax
;
// name of window
private
String
name
=
“Draw”
;
// for synchronization
private
final
Object
mouseLock
=
new
Object
();
private
final
Object
keyLock
=
new
Object
();
// current font
private
Font
font
;
// the JLabel for drawing
private
JLabel
draw
;
// double buffered graphics
private
BufferedImage
offscreenImage
,
onscreenImage
;
private
Graphics2D
offscreen
,
onscreen
;
// the frame for drawing to the screen
private
JFrame
frame
=
new
JFrame
();
// mouse state
private
boolean
isMousePressed
=
false
;
private
double
mouseX
=
0
;
private
double
mouseY
=
0
;
// keyboard state
private
final
LinkedList
<
Character
>
keysTyped
=
new
LinkedList
<
Character
>
();
private
final
TreeSet
<
Integer
>
keysDown
=
new
TreeSet
<
Integer
>
();
// event-based listeners
private
final
ArrayList
<
DrawListener
>
listeners
=
new
ArrayList
<
DrawListener
>
();
/**
* Initializes an empty drawing object with the given name.
*
*
@param
name the title of the drawing window.
*/
public
Draw
(
String
name
)
{
this
.
name
=
name
;
init
();
}
/**
* Initializes an empty drawing object.
*/
public
Draw
()
{
init
();
}
private
void
init
()
{
if
(
frame
!=
null
)
frame
.
setVisible
(
false
);
frame
=
new
JFrame
();
offscreenImage
=
new
BufferedImage
(
2
*
width
,
2
*
height
,
BufferedImage
.
TYPE_INT_ARGB
);
onscreenImage
=
new
BufferedImage
(
2
*
width
,
2
*
height
,
BufferedImage
.
TYPE_INT_ARGB
);
offscreen
=
offscreenImage
.
createGraphics
();
onscreen
=
onscreenImage
.
createGraphics
();
offscreen
.
scale
(
2.0
,
2.0
);
// since we made it 2x as big
setXscale
();
setYscale
();
offscreen
.
setColor
(
DEFAULT_CLEAR_COLOR
);
offscreen
.
fillRect
(
0
,
0
,
width
,
height
);
setPenColor
();
setPenRadius
();
setFont
();
clear
();
// add antialiasing
RenderingHints
hints
=
new
RenderingHints
(
RenderingHints
.
KEY_ANTIALIASING
,
RenderingHints
.
VALUE_ANTIALIAS_ON
);
hints
.
put
(
RenderingHints
.
KEY_RENDERING
,
RenderingHints
.
VALUE_RENDER_QUALITY
);
offscreen
.
addRenderingHints
(
hints
);
// frame stuff
RetinaImageIcon
icon
=
new
RetinaImageIcon
(
onscreenImage
);
draw
=
new
JLabel
(
icon
);
draw
.
addMouseListener
(
this
);
draw
.
addMouseMotionListener
(
this
);
frame
.
setContentPane
(
draw
);
frame
.
addKeyListener
(
this
);
// JLabel cannot get keyboard focus
frame
.
setResizable
(
false
);
// frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // closes all windows
frame
.
setDefaultCloseOperation
(
JFrame
.
DISPOSE_ON_CLOSE
);
// closes only current window
frame
.
setFocusTraversalKeysEnabled
(
false
);
// to recognize VK_TAB with isKeyPressed()
frame
.
setTitle
(
name
);
frame
.
setJMenuBar
(
createMenuBar
());
frame
.
pack
();
frame
.
requestFocusInWindow
();
frame
.
setVisible
(
true
);
}
/**
* Sets the upper-left hand corner of the drawing window to be (x, y), where (0, 0) is upper left.
*
*
@param
x the number of pixels from the left
*
@param
y the number of pixels from the top
*
@throws
IllegalArgumentException if the width or height is 0 or negative
*/
public
void
setLocationOnScreen
(
int
x
,
int
y
)
{
if
(
x
<=
0
||
y
<=
0
)
throw
new
IllegalArgumentException
();
frame
.
setLocation
(
x
,
y
);
}
/**
* Sets the default close operation.
*
*
@param
value the value, typically {
@code
JFrame.EXIT_ON_CLOSE}
* (close all windows) or {
@code
JFrame.DISPOSE_ON_CLOSE}
* (close current window)
*/
public
void
setDefaultCloseOperation
(
int
value
)
{
frame
.
setDefaultCloseOperation
(
value
);
}
/**
* Sets the canvas (drawing area) to be width-by-height pixels.
* This also erases the current drawing and resets the coordinate system, pen radius,
* pen color, and font back to their default values.
* Ordinarly, this method is called once, at the very beginning of a program.
*
*
@param
canvasWidth the width as a number of pixels
*
@param
canvasHeight the height as a number of pixels
*
@throws
IllegalArgumentException unless both {
@code
canvasWidth}
* and {
@code
canvasHeight} are positive
*/
public
void
setCanvasSize
(
int
canvasWidth
,
int
canvasHeight
)
{
if
(
canvasWidth
<
1
||
canvasHeight
<
1
)
{
throw
new
IllegalArgumentException
(
"width and height must be positive"
);
}
width
=
canvasWidth
;
height
=
canvasHeight
;
init
();
}
// create the menu bar (changed to private)
private
JMenuBar
createMenuBar
()
{
JMenuBar
menuBar
=
new
JMenuBar
();
JMenu
menu
=
new
JMenu
(
"File"
);
menuBar
.
add
(
menu
);
JMenuItem
menuItem1
=
new
JMenuItem
(
" Save... "
);
menuItem1
.
addActionListener
(
this
);
// Java 10+: replace getMenuShortcutKeyMask() with getMenuShortcutKeyMaskEx()
menuItem1
.
setAccelerator
(
KeyStroke
.
getKeyStroke
(
KeyEvent
.
VK_S
,
Toolkit
.
getDefaultToolkit
().
getMenuShortcutKeyMask
()));
menu
.
add
(
menuItem1
);
return
menuBar
;
}
/***************************************************************************
* User and screen coordinate systems.
***************************************************************************/
// throw an IllegalArgumentException if x is NaN or infinite
private
static
void
validate
(
double
x
,
String
name
)
{
if
(
Double
.
isNaN
(
x
))
throw
new
IllegalArgumentException
(
name
+
" is NaN"
);
if
(
Double
.
isInfinite
(
x
))
throw
new
IllegalArgumentException
(
name
+
" is infinite"
);
}
// throw an IllegalArgumentException if s is null
private
static
void
validateNonnegative
(
double
x
,
String
name
)
{
if
(
x
<
0
)
throw
new
IllegalArgumentException
(
name
+
" negative"
);
}
// throw an IllegalArgumentException if s is null
private
static
void
validateNotNull
(
Object
x
,
String
name
)
{
if
(
x
==
null
)
throw
new
IllegalArgumentException
(
name
+
" is null"
);
}
/**
* Sets the x-scale to be the default (between 0.0 and 1.0).
*/
public
void
setXscale
()
{
setXscale
(
DEFAULT_XMIN
,
DEFAULT_XMAX
);
}
/**
* Sets the y-scale to be the default (between 0.0 and 1.0).
*/
public
void
setYscale
()
{
setYscale
(
DEFAULT_YMIN
,
DEFAULT_YMAX
);
}
/**
* Sets the x-scale.
*
*
@param
min the minimum value of the x-scale
*
@param
max the maximum value of the x-scale
*
@throws
IllegalArgumentException if {
@code
(max == min)}
*
@throws
IllegalArgumentException if either {
@code
min} or {
@code
max} is either NaN or infinite
*/
public
void
setXscale
(
double
min
,
double
max
)
{
validate
(
min
,
"min"
);
validate
(
max
,
"max"
);
double
size
=
max
-
min
;
if
(
size
==
0.0
)
throw
new
IllegalArgumentException
(
"the min and max are the same"
);
xmin
=
min
-
BORDER
*
size
;
xmax
=
max
+
BORDER
*
size
;
}
/**
* Sets the y-scale.
*
*
@param
min the minimum value of the y-scale
*
@param
max the maximum value of the y-scale
*
@throws
IllegalArgumentException if {
@code
(max == min)}
*
@throws
IllegalArgumentException if either {
@code
min} or {
@code
max} is either NaN or infinite
*/
public
void
setYscale
(
double
min
,
double
max
)
{
validate
(
min
,
"min"
);
validate
(
max
,
"max"
);
double
size
=
max
-
min
;
if
(
size
==
0.0
)
throw
new
IllegalArgumentException
(
"the min and max are the same"
);
ymin
=
min
-
BORDER
*
size
;
ymax
=
max
+
BORDER
*
size
;
}
// helper functions that scale from user coordinates to screen coordinates and back
private
double
scaleX
(
double
x
)
{
return
width
*
(
x
-
xmin
)
/
(
xmax
-
xmin
);
}
private
double
scaleY
(
double
y
)
{
return
height
*
(
ymax
-
y
)
/
(
ymax
-
ymin
);
}
private
double
factorX
(
double
w
)
{
return
w
*
width
/
Math
.
abs
(
xmax
-
xmin
);
}
private
double
factorY
(
double
h
)
{
return
h
*
height
/
Math
.
abs
(
ymax
-
ymin
);
}
private
double
userX
(
double
x
)
{
return
xmin
+
x
*
(
xmax
-
xmin
)
/
width
;
}
private
double
userY
(
double
y
)
{
return
ymax
-
y
*
(
ymax
-
ymin
)
/
height
;
}
/**
* Clears the screen to the default color (white).
*/
public
void
clear
()
{
clear
(
DEFAULT_CLEAR_COLOR
);
}
/**
* Clears the screen to the given color.
*
*
@param
color the color to make the background
*
@throws
IllegalArgumentException if {
@code
color} is {
@code
null}
*/
public
void
clear
(
Color
color
)
{
validateNotNull
(
color
,
"color"
);
offscreen
.
setColor
(
color
);
offscreen
.
fillRect
(
0
,
0
,
width
,
height
);
offscreen
.
setColor
(
penColor
);
draw
();
}
/**
* Gets the current pen radius.
*
*
@return
the current pen radius
*/
public
double
getPenRadius
()
{
return
penRadius
;
}
/**
* Sets the pen size to the default (.002).
*/
public
void
setPenRadius
()
{
setPenRadius
(
DEFAULT_PEN_RADIUS
);
}
/**
* Sets the radius of the pen to the given size.
*
*
@param
radius the radius of the pen
*
@throws
IllegalArgumentException if {
@code
radius} is negative, NaN, or infinite
*/
public
void
setPenRadius
(
double
radius
)
{
validate
(
radius
,
"pen radius"
);
validateNonnegative
(
radius
,
"pen radius"
);
penRadius
=
radius
*
DEFAULT_SIZE
;
BasicStroke
stroke
=
new
BasicStroke
((
float
)
penRadius
,
BasicStroke
.
CAP_ROUND
,
BasicStroke
.
JOIN_ROUND
);
// BasicStroke stroke = new BasicStroke((float) penRadius);
offscreen
.
setStroke
(
stroke
);
}
/**
* Gets the current pen color.
*
*
@return
the current pen color
*/
public
Color
getPenColor
()
{
return
penColor
;
}
/**
* Sets the pen color to the default color (black).
*/
public
void
setPenColor
()
{
setPenColor
(
DEFAULT_PEN_COLOR
);
}
/**
* Sets the pen color to the given color.
*
*
@param
color the color to make the pen
*
@throws
IllegalArgumentException if {
@code
color} is {
@code
null}
*/
public
void
setPenColor
(
Color
color
)
{
validateNotNull
(
color
,
"color"
);
penColor
=
color
;
offscreen
.
setColor
(
penColor
);
}
/**
* Sets the pen color to the given RGB color.
*
*
@param
red the amount of red (between 0 and 255)
*
@param
green the amount of green (between 0 and 255)
*
@param
blue the amount of blue (between 0 and 255)
*
@throws
IllegalArgumentException if {
@code
red}, {
@code
green},
* or {
@code
blue} is outside its prescribed range
*/
public
void
setPenColor
(
int
red
,
int
green
,
int
blue
)
{
if
(
red
<
0
||
red
>=
256
)
throw
new
IllegalArgumentException
(
“red must be between 0 and 255”
);
if
(
green
<
0
||
green
>=
256
)
throw
new
IllegalArgumentException
(
“green must be between 0 and 255”
);
if
(
blue
<
0
||
blue
>=
256
)
throw
new
IllegalArgumentException
(
“blue must be between 0 and 255”
);
setPenColor
(
new
Color
(
red
,
green
,
blue
));
}
/**
* Turns on xor mode.
*/
public
void
xorOn
()
{
offscreen
.
setXORMode
(
DEFAULT_CLEAR_COLOR
);
}
/**
* Turns off xor mode.
*/
public
void
xorOff
()
{
offscreen
.
setPaintMode
();
}
/**
* Gets the current {
@code
JLabel} for use in some other GUI.
*
*
@return
the current {
@code
JLabel}
*/
public
JLabel
getJLabel
()
{
return
draw
;
}
/**
* Gets the current font.
*
*
@return
the current font
*/
public
Font
getFont
()
{
return
font
;
}
/**
* Sets the font to the default font (sans serif, 16 point).
*/
public
void
setFont
()
{
setFont
(
DEFAULT_FONT
);
}
/**
* Sets the font to the given value.
*
*
@param
font the font
*
@throws
IllegalArgumentException if {
@code
font} is {
@code
null}
*/
public
void
setFont
(
Font
font
)
{
validateNotNull
(
font
,
“font”
);
this
.
font
=
font
;
}
/***************************************************************************
* Drawing geometric shapes.
***************************************************************************/
/**
* Draws a line from (x0, y0) to (x1, y1).
*
*
@param
x0 the x-coordinate of the starting point
*
@param
y0 the y-coordinate of the starting point
*
@param
x1 the x-coordinate of the destination point
*
@param
y1 the y-coordinate of the destination point
*
@throws
IllegalArgumentException if any coordinate is either NaN or infinite
*/
public
void
line
(
double
x0
,
double
y0
,
double
x1
,
double
y1
)
{
validate
(
x0
,
“x0”
);
validate
(
y0
,
“y0”
);
validate
(
x1
,
“x1”
);
validate
(
y1
,
“y1”
);
offscreen
.
draw
(
new
Line2D
.
Double
(
scaleX
(
x0
),
scaleY
(
y0
),
scaleX
(
x1
),
scaleY
(
y1
)));
draw
();
}
/**
* Draws one pixel at (x, y).
*
*
@param
x the x-coordinate of the pixel
*
@param
y the y-coordinate of the pixel
*
@throws
IllegalArgumentException if {
@code
x} or {
@code
y} is either NaN or infinite
*/
private
void
pixel
(
double
x
,
double
y
)
{
validate
(
x
,
“x”
);
validate
(
y
,
“y”
);
offscreen
.
fillRect
((
int
)
Math
.
round
(
scaleX
(
x
)),
(
int
)
Math
.
round
(
scaleY
(
y
)),
1
,
1
);
}
/**
* Draws a point at (x, y).
*
*
@param
x the x-coordinate of the point
*
@param
y the y-coordinate of the point
*
@throws
IllegalArgumentException if either {
@code
x} or {
@code
y} is either NaN or infinite
*/
public
void
point
(
double
x
,
double
y
)
{
validate
(
x
,
“x”
);
validate
(
y
,
“y”
);
double
xs
=
scaleX
(
x
);
double
ys
=
scaleY
(
y
);
double
r
=
penRadius
;
// double ws = factorX(2*r);
// double hs = factorY(2*r);
// if (ws <= 1 && hs <= 1) pixel(x, y);
if
(
r
<=
1
)
pixel
(
x
,
y
);
else
offscreen
.
fill
(
new
Ellipse2D
.
Double
(
xs
-
r
/
2
,
ys
-
r
/
2
,
r
,
r
));
draw
();
}
/**
* Draws a circle of the specified radius, centered at (x, y).
*
*
@param
x the x-coordinate of the center of the circle
*
@param
y the y-coordinate of the center of the circle
*
@param
radius the radius of the circle
*
@throws
IllegalArgumentException if {
@code
radius} is negative
*
@throws
IllegalArgumentException if any argument is either NaN or infinite
*/
public
void
circle
(
double
x
,
double
y
,
double
radius
)
{
validate
(
x
,
“x”
);
validate
(
y
,
“y”
);
validate
(
radius
,
“radius”
);
validateNonnegative
(
radius
,
“radius”
);
double
xs
=
scaleX
(
x
);
double
ys
=
scaleY
(
y
);
double
ws
=
factorX
(
2
*
radius
);
double
hs
=
factorY
(
2
*
radius
);
if
(
ws
<=
1
&&
hs
<=
1
)
pixel
(
x
,
y
);
else
offscreen
.
draw
(
new
Ellipse2D
.
Double
(
xs
-
ws
/
2
,
ys
-
hs
/
2
,
ws
,
hs
));
draw
();
}
/**
* Draws a filled circle of the specified radius, centered at (x, y).
*
*
@param
x the x-coordinate of the center of the circle
*
@param
y the y-coordinate of the center of the circle
*
@param
radius the radius of the circle
*
@throws
IllegalArgumentException if {
@code
radius} is negative
*
@throws
IllegalArgumentException if any argument is either NaN or infinite
*/
public
void
filledCircle
(
double
x
,
double
y
,
double
radius
)
{
validate
(
x
,
“x”
);
validate
(
y
,
“y”
);
validate(radius, “radius”);
validateNonnegative(radius, “radius”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*radius);
double hs = factorY(2*radius);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.fill(new Ellipse2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws an ellipse with the specified semimajor and semiminor axes, * centered at (x, y). * * @param x the x-coordinate of the center of the ellipse * @param y the y-coordinate of the center of the ellipse * @param semiMajorAxis is the semimajor axis of the ellipse * @param semiMinorAxis is the semiminor axis of the ellipse * @throws IllegalArgumentException if either {@code semiMajorAxis} * or {@code semiMinorAxis} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public void ellipse(double x, double y, double semiMajorAxis, double semiMinorAxis) {
validate(x, “x”);
validate(y, “y”);
validate(semiMajorAxis, “semimajor axis”);
validate(semiMinorAxis, “semiminor axis”);
validateNonnegative(semiMajorAxis, “semimajor axis”);
validateNonnegative(semiMinorAxis, “semiminor axis”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*semiMajorAxis);
double hs = factorY(2*semiMinorAxis);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.draw(new Ellipse2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws a filled ellipse with the specified semimajor and semiminor axes, * centered at (x, y). * * @param x the x-coordinate of the center of the ellipse * @param y the y-coordinate of the center of the ellipse * @param semiMajorAxis is the semimajor axis of the ellipse * @param semiMinorAxis is the semiminor axis of the ellipse * @throws IllegalArgumentException if either {@code semiMajorAxis} * or {@code semiMinorAxis} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public void filledEllipse(double x, double y, double semiMajorAxis, double semiMinorAxis) {
validate(x, “x”);
validate(y, “y”);
validate(semiMajorAxis, “semimajor axis”);
validate(semiMinorAxis, “semiminor axis”);
validateNonnegative(semiMajorAxis, “semimajor axis”);
validateNonnegative(semiMinorAxis, “semiminor axis”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*semiMajorAxis);
double hs = factorY(2*semiMinorAxis);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.fill(new Ellipse2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws a circular arc of the specified radius, * centered at (x, y), from angle1 to angle2 (in degrees). * * @param x the x-coordinate of the center of the circle * @param y the y-coordinate of the center of the circle * @param radius the radius of the circle * @param angle1 the starting angle. 0 would mean an arc beginning at 3 o’clock. * @param angle2 the angle at the end of the arc. For example, if * you want a 90 degree arc, then angle2 should be angle1 + 90. * @throws IllegalArgumentException if {@code radius} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public void arc(double x, double y, double radius, double angle1, double angle2) {
validate(x, “x”);
validate(y, “y”);
validate(radius, “arc radius”);
validate(angle1, “angle1”);
validate(angle2, “angle2”);
validateNonnegative(radius, “arc radius”);
while (angle2 < angle1) angle2 += 360; double xs = scaleX(x); double ys = scaleY(y); double ws = factorX(2*radius); double hs = factorY(2*radius); if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.draw(new Arc2D.Double(xs - ws/2, ys - hs/2, ws, hs, angle1, angle2 - angle1, Arc2D.OPEN)); draw(); } /** * Draws a square of the specified size, centered at (x, y). * * @param x the x-coordinate of the center of the square * @param y the y-coordinate of the center of the square * @param halfLength one half the length of any side of the square * @throws IllegalArgumentException if {@code halfLength} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public void square(double x, double y, double halfLength) {
validate(x, “x”);
validate(y, “y”);
validate(halfLength, “halfLength”);
validateNonnegative(halfLength, “half length”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*halfLength);
double hs = factorY(2*halfLength);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.draw(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws a square of the specified size, centered at (x, y). * * @param x the x-coordinate of the center of the square * @param y the y-coordinate of the center of the square * @param halfLength one half the length of any side of the square * @throws IllegalArgumentException if {@code halfLength} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public void filledSquare(double x, double y, double halfLength) {
validate(x, “x”);
validate(y, “y”);
validate(halfLength, “halfLength”);
validateNonnegative(halfLength, “half length”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*halfLength);
double hs = factorY(2*halfLength);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.fill(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws a rectangle of the specified size, centered at (x, y). * * @param x the x-coordinate of the center of the rectangle * @param y the y-coordinate of the center of the rectangle * @param halfWidth one half the width of the rectangle * @param halfHeight one half the height of the rectangle * @throws IllegalArgumentException if either {@code halfWidth} or {@code halfHeight} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public void rectangle(double x, double y, double halfWidth, double halfHeight) {
validate(x, “x”);
validate(y, “y”);
validate(halfWidth, “halfWidth”);
validate(halfHeight, “halfHeight”);
validateNonnegative(halfWidth, “half width”);
validateNonnegative(halfHeight, “half height”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*halfWidth);
double hs = factorY(2*halfHeight);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.draw(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws a filled rectangle of the specified size, centered at (x, y). * * @param x the x-coordinate of the center of the rectangle * @param y the y-coordinate of the center of the rectangle * @param halfWidth one half the width of the rectangle * @param halfHeight one half the height of the rectangle * @throws IllegalArgumentException if either {@code halfWidth} or {@code halfHeight} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public void filledRectangle(double x, double y, double halfWidth, double halfHeight) {
validate(x, “x”);
validate(y, “y”);
validate(halfWidth, “halfWidth”);
validate(halfHeight, “halfHeight”);
validateNonnegative(halfWidth, “half width”);
validateNonnegative(halfHeight, “half height”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*halfWidth);
double hs = factorY(2*halfHeight);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.fill(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws a polygon with the vertices * (x0, y0), * (x1, y1), …, * (xn–1, yn–1). * * @param x an array of all the x-coordinates of the polygon * @param y an array of all the y-coordinates of the polygon * @throws IllegalArgumentException unless {@code x[]} and {@code y[]} * are of the same length * @throws IllegalArgumentException if any coordinate is either NaN or infinite * @throws IllegalArgumentException if either {@code x[]} or {@code y[]} is {@code null} */
public void polygon(double[] x, double[] y) {
validateNotNull(x, “x-coordinate array”);
validateNotNull(y, “y-coordinate array”);
for (int i = 0; i < x.length; i++) validate(x[i], "x[" + i + "]"); for (int i = 0; i < y.length; i++) validate(y[i], "y[" + i + "]"); int n1 = x.length; int n2 = y.length; if (n1 != n2) throw new IllegalArgumentException("arrays must be of the same length"); int n = n1; if (n == 0) return; GeneralPath path = new GeneralPath(); path.moveTo((float) scaleX(x[0]), (float) scaleY(y[0])); for (int i = 0; i < n; i++) path.lineTo((float) scaleX(x[i]), (float) scaleY(y[i])); path.closePath(); offscreen.draw(path); draw(); } /** * Draws a filled polygon with the vertices * (x0, y0), * (x1, y1), …, * (xn–1, yn–1). * * @param x an array of all the x-coordinates of the polygon * @param y an array of all the y-coordinates of the polygon * @throws IllegalArgumentException unless {@code x[]} and {@code y[]} * are of the same length * @throws IllegalArgumentException if any coordinate is either NaN or infinite * @throws IllegalArgumentException if either {@code x[]} or {@code y[]} is {@code null} */
public void filledPolygon(double[] x, double[] y) {
validateNotNull(x, “x-coordinate array”);
validateNotNull(y, “y-coordinate array”);
for (int i = 0; i < x.length; i++) validate(x[i], "x[" + i + "]"); for (int i = 0; i < y.length; i++) validate(y[i], "y[" + i + "]"); int n1 = x.length; int n2 = y.length; if (n1 != n2) throw new IllegalArgumentException("arrays must be of the same length"); int n = n1; if (n == 0) return; GeneralPath path = new GeneralPath(); path.moveTo((float) scaleX(x[0]), (float) scaleY(y[0])); for (int i = 0; i < n; i++) path.lineTo((float) scaleX(x[i]), (float) scaleY(y[i])); path.closePath(); offscreen.fill(path); draw(); } /*************************************************************************** * Drawing images. ***************************************************************************/ // get an image from the given filename private static Image getImage(String filename) { if (filename == null) throw new IllegalArgumentException(); // to read from file ImageIcon icon = new ImageIcon(filename); // try to read from URL if ((icon == null) || (icon.getImageLoadStatus() != MediaTracker.COMPLETE)) { try { URL url = new URL(filename); icon = new ImageIcon(url); } catch (MalformedURLException e) { /* not a url */ } } // in case file is inside a .jar (classpath relative to StdDraw) if ((icon == null) || (icon.getImageLoadStatus() != MediaTracker.COMPLETE)) { URL url = StdDraw.class.getResource(filename); if (url != null) icon = new ImageIcon(url); } // in case file is inside a .jar (classpath relative to root of jar) if ((icon == null) || (icon.getImageLoadStatus() != MediaTracker.COMPLETE)) { URL url = Draw.class.getResource("/" + filename); if (url == null) throw new IllegalArgumentException("image " + filename + " not found"); icon = new ImageIcon(url); } return icon.getImage(); } /** * Draws the specified image centered at (x, y). * The supported image formats are JPEG, PNG, and GIF. * As an optimization, the picture is cached, so there is no performance * penalty for redrawing the same image multiple times (e.g., in an animation). * However, if you change the picture file after drawing it, subsequent * calls will draw the original picture. * * @param x the center x-coordinate of the image * @param y the center y-coordinate of the image * @param filename the name of the image/picture, e.g., “ball.gif” * @throws IllegalArgumentException if the image filename is invalid * @throws IllegalArgumentException if either {@code x} or {@code y} is either NaN or infinite */
public void picture(double x, double y, String filename) {
validate(x, “x”);
validate(y, “y”);
validateNotNull(filename, “filename”);
Image image = getImage(filename);
double xs = scaleX(x);
double ys = scaleY(y);
int ws = image.getWidth(null);
int hs = image.getHeight(null);
if (ws < 0 || hs < 0) throw new IllegalArgumentException("image " + filename + " is corrupt"); offscreen.drawImage(image, (int) Math.round(xs - ws/2.0), (int) Math.round(ys - hs/2.0), null); draw(); } /** * Draws the specified image centered at (x, y), * rotated given number of degrees. * The supported image formats are JPEG, PNG, and GIF. * * @param x the center x-coordinate of the image * @param y the center y-coordinate of the image * @param filename the name of the image/picture, e.g., “ball.gif” * @param degrees is the number of degrees to rotate counterclockwise * @throws IllegalArgumentException if the image filename is invalid * @throws IllegalArgumentException if {@code x}, {@code y}, {@code degrees} is NaN or infinite * @throws IllegalArgumentException if {@code filename} is {@code null} */
public void picture(double x, double y, String filename, double degrees) {
validate(x, “x”);
validate(y, “y”);
validate(degrees, “degrees”);
validateNotNull(filename, “filename”);
Image image = getImage(filename);
double xs = scaleX(x);
double ys = scaleY(y);
int ws = image.getWidth(null);
int hs = image.getHeight(null);
if (ws < 0 || hs < 0) throw new IllegalArgumentException("image " + filename + " is corrupt"); offscreen.rotate(Math.toRadians(-degrees), xs, ys); offscreen.drawImage(image, (int) Math.round(xs - ws/2.0), (int) Math.round(ys - hs/2.0), null); offscreen.rotate(Math.toRadians(+degrees), xs, ys); draw(); } /** * Draws the specified image centered at (x, y), * rescaled to the specified bounding box. * The supported image formats are JPEG, PNG, and GIF. * * @param x the center x-coordinate of the image * @param y the center y-coordinate of the image * @param filename the name of the image/picture, e.g., “ball.gif” * @param scaledWidth the width of the scaled image (in screen coordinates) * @param scaledHeight the height of the scaled image (in screen coordinates) * @throws IllegalArgumentException if either {@code scaledWidth} * or {@code scaledHeight} is negative * @throws IllegalArgumentException if the image filename is invalid * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite * @throws IllegalArgumentException if {@code filename} is {@code null} */
public void picture(double x, double y, String filename, double scaledWidth, double scaledHeight) {
validate(x, “x”);
validate(y, “y”);
validate(scaledWidth, “scaled width”);
validate(scaledHeight, “scaled height”);
validateNotNull(filename, “filename”);
validateNonnegative(scaledWidth, “scaled width”);
validateNonnegative(scaledHeight, “scaled height”);
Image image = getImage(filename);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(scaledWidth);
double hs = factorY(scaledHeight);
if (ws < 0 || hs < 0) throw new IllegalArgumentException("image " + filename + " is corrupt"); if (ws <= 1 && hs <= 1) pixel(x, y); else { offscreen.drawImage(image, (int) Math.round(xs - ws/2.0), (int) Math.round(ys - hs/2.0), (int) Math.round(ws), (int) Math.round(hs), null); } draw(); } /** * Draws the specified image centered at (x, y), rotated * given number of degrees, and rescaled to the specified bounding box. * The supported image formats are JPEG, PNG, and GIF. * * @param x the center x-coordinate of the image * @param y the center y-coordinate of the image * @param filename the name of the image/picture, e.g., “ball.gif” * @param scaledWidth the width of the scaled image (in screen coordinates) * @param scaledHeight the height of the scaled image (in screen coordinates) * @param degrees is the number of degrees to rotate counterclockwise * @throws IllegalArgumentException if either {@code scaledWidth} * or {@code scaledHeight} is negative * @throws IllegalArgumentException if the image filename is invalid */
public void picture(double x, double y, String filename, double scaledWidth, double scaledHeight, double degrees) {
validate(x, “x”);
validate(y, “y”);
validate(scaledWidth, “scaled width”);
validate(scaledHeight, “scaled height”);
validate(degrees, “degrees”);
validateNotNull(filename, “filename”);
validateNonnegative(scaledWidth, “scaled width”);
validateNonnegative(scaledHeight, “scaled height”);
Image image = getImage(filename);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(scaledWidth);
double hs = factorY(scaledHeight);
if (ws < 0 || hs < 0) throw new IllegalArgumentException("image " + filename + " is corrupt"); if (ws <= 1 && hs <= 1) pixel(x, y); offscreen.rotate(Math.toRadians(-degrees), xs, ys); offscreen.drawImage(image, (int) Math.round(xs - ws/2.0), (int) Math.round(ys - hs/2.0), (int) Math.round(ws), (int) Math.round(hs), null); offscreen.rotate(Math.toRadians(+degrees), xs, ys); draw(); } /*************************************************************************** * Drawing text. ***************************************************************************/ /** * Writes the given text string in the current font, centered at (x, y). * * @param x the center x-coordinate of the text * @param y the center y-coordinate of the text * @param text the text to write * @throws IllegalArgumentException if {@code text} is {@code null} * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite */
public void text(double x, double y, String text) {
validate(x, “x”);
validate(y, “y”);
validateNotNull(text, “text”);
offscreen.setFont(font);
FontMetrics metrics = offscreen.getFontMetrics();
double xs = scaleX(x);
double ys = scaleY(y);
int ws = metrics.stringWidth(text);
int hs = metrics.getDescent();
offscreen.drawString(text, (float) (xs – ws/2.0), (float) (ys + hs));
draw();
}
/** * Writes the given text string in the current font, centered at (x, y) and * rotated by the specified number of degrees. * @param x the center x-coordinate of the text * @param y the center y-coordinate of the text * @param text the text to write * @param degrees is the number of degrees to rotate counterclockwise * @throws IllegalArgumentException if {@code text} is {@code null} * @throws IllegalArgumentException if {@code x}, {@code y}, or {@code degrees} is either NaN or infinite */
public void text(double x, double y, String text, double degrees) {
validate(x, “x”);
validate(y, “y”);
validate(degrees, “degrees”);
validateNotNull(text, “text”);
double xs = scaleX(x);
double ys = scaleY(y);
offscreen.rotate(Math.toRadians(-degrees), xs, ys);
text(x, y, text);
offscreen.rotate(Math.toRadians(+degrees), xs, ys);
}
/** * Writes the given text string in the current font, left-aligned at (x, y). * @param x the x-coordinate of the text * @param y the y-coordinate of the text * @param text the text * @throws IllegalArgumentException if {@code text} is {@code null} * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite */
public void textLeft(double x, double y, String text) {
validate(x, “x”);
validate(y, “y”);
validateNotNull(text, “text”);
offscreen.setFont(font);
FontMetrics metrics = offscreen.getFontMetrics();
double xs = scaleX(x);
double ys = scaleY(y);
// int ws = metrics.stringWidth(text); int hs = metrics.getDescent();
offscreen.drawString(text, (float) xs, (float) (ys + hs));
draw();
}
/** * Writes the given text string in the current font, right-aligned at (x, y). * * @param x the x-coordinate of the text * @param y the y-coordinate of the text * @param text the text to write * @throws IllegalArgumentException if {@code text} is {@code null} * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite */
public void textRight(double x, double y, String text) {
validate(x, “x”);
validate(y, “y”);
validateNotNull(text, “text”);
offscreen.setFont(font);
FontMetrics metrics = offscreen.getFontMetrics();
double xs = scaleX(x);
double ys = scaleY(y);
int ws = metrics.stringWidth(text);
int hs = metrics.getDescent();
offscreen.drawString(text, (float) (xs – ws), (float) (ys + hs));
draw();
}
/** * Copies the offscreen buffer to the onscreen buffer, pauses for t milliseconds * and enables double buffering. * @param t number of milliseconds * @deprecated replaced by {@link #enableDoubleBuffering()}, {@link #show()}, and {@link #pause(int t)} */
@Deprecated
public void show(int t) {
show();
pause(t);
enableDoubleBuffering();
}
/** * Pause for t milliseconds. This method is intended to support computer animations. * @param t number of milliseconds */
public void pause(int t) {
try {
Thread.sleep(t);
}
catch (InterruptedException e) {
System.out.println(“Error sleeping”);
}
}
/** * Copies offscreen buffer to onscreen buffer. There is no reason to call * this method unless double buffering is enabled. */
public void show() {
onscreen.drawImage(offscreenImage, 0, 0, null);
frame.repaint();
}
// draw onscreen if defer is false private void draw() {
if (!defer) show();
}
/** * Enable double buffering. All subsequent calls to * drawing methods such as {@code line()}, {@code circle()}, * and {@code square()} will be deferred until the next call * to show(). Useful for animations. */
public void enableDoubleBuffering() {
defer = true;
}
/** * Disable double buffering. All subsequent calls to * drawing methods such as {@code line()}, {@code circle()}, * and {@code square()} will be displayed on screen when called. * This is the default. */
public void disableDoubleBuffering() {
defer = false;
}
/** * Saves the drawing to using the specified filename. * The supported image formats are JPEG and PNG; * the filename suffix must be {@code } or {@code }. * * @param filename the name of the file with one of the required suffixes * @throws IllegalArgumentException if {@code filename} is {@code null} */
public void save(String filename) {
validateNotNull(filename, “filename”);
File file = new File(filename);
String suffix = filename.substring(filename.lastIndexOf(‘.’) + 1);
// png files if (“png”.equalsIgnoreCase(suffix)) {
try {
ImageIO.write(offscreenImage, suffix, file);
}
catch (IOException e) {
e.printStackTrace();
}
}
// need to change from ARGB to RGB for jpeg // reference: http://archives.java.sun.com/cgi-bin/wa?A2=ind0404&L=java2d-interest&D=0&P=2727 else if (“jpg”.equalsIgnoreCase(suffix)) {
WritableRaster raster = offscreenImage.getRaster();
WritableRaster newRaster;
newRaster = raster.createWritableChild(0, 0, width, height, 0, 0, new int[] {0, 1, 2});
DirectColorModel cm = (DirectColorModel) offscreenImage.getColorModel();
DirectColorModel newCM = new DirectColorModel(cm.getPixelSize(),
cm.getRedMask(),
cm.getGreenMask(),
cm.getBlueMask());
BufferedImage rgbBuffer = new BufferedImage(newCM, newRaster, false, null);
try {
ImageIO.write(rgbBuffer, suffix, file);
}
catch (IOException e) {
e.printStackTrace();
}
}
else {
System.out.println(“Invalid image file type: ” + suffix);
}
}
/** * This method cannot be called directly. */
@Override
public void actionPerformed(ActionEvent e) {
FileDialog chooser = new FileDialog(frame, “Use a or extension”, FileDialog.SAVE);
chooser.setVisible(true);
String filename = chooser.getFile();
if (filename != null) {
save(chooser.getDirectory() + File.separator + chooser.getFile());
}
}
/*************************************************************************** * Event-based interactions. ***************************************************************************/
/** * Adds a {@link DrawListener} to listen to keyboard and mouse events. * * @param listener the {\tt DrawListener} argument */
public void addListener(DrawListener listener) {
// ensure there is a window for listenting to events show();
listeners.add(listener);
frame.addKeyListener(this);
frame.addMouseListener(this);
frame.addMouseMotionListener(this);
frame.setFocusable(true); }
/*************************************************************************** * Mouse interactions. ***************************************************************************/
/** * Returns true if the mouse is being pressed. * * @return {@code true} if the mouse is being pressed; * {@code false} otherwise */
public boolean isMousePressed() {
synchronized (mouseLock) {
return isMousePressed;
}
}
/** * Returns true if the mouse is being pressed. * * @return {@code true} if the mouse is being pressed; * {@code false} otherwise * @deprecated replaced by {@link #isMousePressed()} */
@Deprecated
public boolean mousePressed() {
synchronized (mouseLock) {
return isMousePressed;
}
}
/** * Returns the x-coordinate of the mouse. * @return the x-coordinate of the mouse */
public double mouseX() {
synchronized (mouseLock) {
return mouseX;
}
}
/** * Returns the y-coordinate of the mouse. * * @return the y-coordinate of the mouse */
public double mouseY() {
synchronized (mouseLock) {
return mouseY;
}
}
/** * This method cannot be called directly. */
@Override
public void mouseEntered(MouseEvent e) {
// this body is intentionally left empty }
/** * This method cannot be called directly. */
@Override
public void mouseExited(MouseEvent e) {
// this body is intentionally left empty }
/** * This method cannot be called directly. */
@Override
public void mousePressed(MouseEvent e) {
synchronized (mouseLock) {
mouseX = userX(e.getX());
mouseY = userY(e.getY());
isMousePressed = true;
}
if (e.getButton() == MouseEvent.BUTTON1) {
for (DrawListener listener : listeners)
listener.mousePressed(userX(e.getX()), userY(e.getY()));
}
}
/** * This method cannot be called directly. */
@Override
public void mouseReleased(MouseEvent e) {
synchronized (mouseLock) {
isMousePressed = false;
}
if (e.getButton() == MouseEvent.BUTTON1) {
for (DrawListener listener : listeners)
listener.mouseReleased(userX(e.getX()), userY(e.getY()));
}
}
/** * This method cannot be called directly. */
@Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
for (DrawListener listener : listeners)
listener.mouseClicked(userX(e.getX()), userY(e.getY()));
}
}
/** * This method cannot be called directly. */
@Override
public void mouseDragged(MouseEvent e) {
synchronized (mouseLock) {
mouseX = userX(e.getX());
mouseY = userY(e.getY());
}
// doesn’t seem to work if a button is specified for (DrawListener listener : listeners)
listener.mouseDragged(userX(e.getX()), userY(e.getY()));
}
/** * This method cannot be called directly. */
@Override
public void mouseMoved(MouseEvent e) {
synchronized (mouseLock) {
mouseX = userX(e.getX());
mouseY = userY(e.getY());
}
}
/*************************************************************************** * Keyboard interactions. ***************************************************************************/
/** * Returns true if the user has typed a key. * * @return {@code true} if the user has typed a key; {@code false} otherwise */
public boolean hasNextKeyTyped() {
synchronized (keyLock) {
return !keysTyped.isEmpty();
}
}
/** * The next key typed by the user. * * @return the next key typed by the user */
public char nextKeyTyped() {
synchronized (keyLock) {
return keysTyped.removeLast();
}
}
/** * Returns true if the keycode is being pressed. *
* This method takes as an argument the keycode (corresponding to a physical key). * It can handle action keys (such as F1 and arrow keys) and modifier keys * (such as shift and control). * See {@link KeyEvent} for a description of key codes. * * @param keycode the keycode to check * @return {@code true} if {@code keycode} is currently being pressed; * {@code false} otherwise */
public boolean isKeyPressed(int keycode) {
synchronized (keyLock) {
return keysDown.contains(keycode);
}
}
/** * This method cannot be called directly. */
@Override
public void keyTyped(KeyEvent e) {
synchronized (keyLock) {
keysTyped.addFirst(e.getKeyChar());
}
// notify all listeners for (DrawListener listener : listeners)
listener.keyTyped(e.getKeyChar());
}
/** * This method cannot be called directly. */
@Override
public void keyPressed(KeyEvent e) {
synchronized (keyLock) {
keysDown.add(e.getKeyCode());
}
// notify all listeners for (DrawListener listener : listeners)
listener.keyPressed(e.getKeyCode());
}
/** * This method cannot be called directly. */
@Override
public void keyReleased(KeyEvent e) {
synchronized (keyLock) {
keysDown.remove(e.getKeyCode());
}
// notify all listeners for (DrawListener listener : listeners)
listener.keyReleased(e.getKeyCode());
}
/*************************************************************************** * For improved resolution on Mac Retina displays. ***************************************************************************/
private static class RetinaImageIcon extends ImageIcon {
public RetinaImageIcon(Image image) {
super(image);
}
public int getIconWidth() {
return super.getIconWidth() / 2;
}
/** * Gets the height of the icon. * * @return the height in pixels of this icon */
public int getIconHeight() {
return super.getIconHeight() / 2;
}
public synchronized void paintIcon(Component c, Graphics g, int x, int y) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2.scale(0.5, 0.5);
super.paintIcon(c, g2, x * 2, y * 2);
g2.dispose();
}
}
/** * Test client. * * @param args the command-line arguments */
public static void main(String[] args) {
// create one drawing window Draw draw1 = new Draw(“Test client 1”);
draw1.square(0.2, 0.8, 0.1);
draw1.filledSquare(0.8, 0.8, 0.2);
draw1.circle(0.8, 0.2, 0.2);
draw1.setPenColor(Draw.MAGENTA);
draw1.setPenRadius(0.02);
draw1.arc(0.8, 0.2, 0.1, 200, 45);
// create another one Draw draw2 = new Draw(“Test client 2”);
draw2.setCanvasSize(900, 200);
// draw a blue diamond draw2.setPenRadius();
draw2.setPenColor(Draw.BLUE);
double[] x = { 0.1, 0.2, 0.3, 0.2 };
double[] y = { 0.2, 0.3, 0.2, 0.1 };
draw2.filledPolygon(x, y);
// text draw2.setPenColor(Draw.BLACK);
draw2.text(0.2, 0.5, “bdfdfdfdlack text”);
draw2.setPenColor(Draw.WHITE);
draw2.text(0.8, 0.8, “white text”);
}
}
/****************************************************************************** * Copyright 2002-2020, Robert Sedgewick and Kevin Wayne. * * This file is part of algs4.jar, which accompanies the textbook * * Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne, * Addison-Wesley Professional, 2011, ISBN 0-321-57351-X. * http://algs4.cs.princeton.edu * * * algs4.jar is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * algs4.jar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with algs4.jar. If not, see http://www.gnu.org/licenses. ******************************************************************************/
edu/princeton/cs/algs4/DrawListener.java
edu/princeton/cs/algs4/DrawListener.java
/******************************************************************************
* Compilation: javac DrawListener.java
* Execution: none
* Dependencies: none
*
* Interface that accompanies Draw.java.
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* DrawListener. This interface provides a basic capability for
* responding to keyboard in mouse events from {
@link
Draw} via callbacks.
* You can see some examples in
* Section 3.6.
*
*
* For additional documentation, see
* Section 3.1 of
* Computer Science: An Interdisciplinary Approach by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
interface
DrawListener
{
/**
* Invoked when the mouse has been pressed.
*
*
@param
x the x-coordinate of the mouse
*
@param
y the y-coordinate of the mouse
*/
void
mousePressed
(
double
x
,
double
y
);
/**
* Invoked when the mouse has been dragged.
*
*
@param
x the x-coordinate of the mouse
*
@param
y the y-coordinate of the mouse
*/
void
mouseDragged
(
double
x
,
double
y
);
/**
* Invoked when the mouse has been released.
*
*
@param
x the x-coordinate of the mouse
*
@param
y the y-coordinate of the mouse
*/
void
mouseReleased
(
double
x
,
double
y
);
/**
* Invoked when the mouse has been clicked (pressed and released).
*
*
@param
x the x-coordinate of the mouse
*
@param
y the y-coordinate of the mouse
*/
void
mouseClicked
(
double
x
,
double
y
);
/**
* Invoked when a key has been typed.
*
*
@param
c the character typed
*/
void
keyTyped
(
char
c
);
/**
* Invoked when a key has been pressed.
*
*
@param
keycode the key combination pressed
*/
void
keyPressed
(
int
keycode
);
/**
* Invoked when a key has been released.
*
*
@param
keycode the key combination released
*/
void
keyReleased
(
int
keycode
);
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Edge.java
edu/princeton/cs/algs4/Edge.java
/******************************************************************************
* Compilation: javac Edge.java
* Execution: java Edge
* Dependencies: StdOut.java
*
* Immutable weighted edge.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Edge} class represents a weighted edge in an
* {
@link
EdgeWeightedGraph}. Each edge consists of two integers
* (naming the two vertices) and a real-value weight. The data type
* provides methods for accessing the two endpoints of the edge and
* the weight. The natural order for this data type is by
* ascending order of weight.
*
* For additional documentation, see Section 4.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Edge
implements
Comparable
<
Edge
>
{
private
final
int
v
;
private
final
int
w
;
private
final
double
weight
;
/**
* Initializes an edge between vertices {
@code
v} and {
@code
w} of
* the given {
@code
weight}.
*
*
@param
v one vertex
*
@param
w the other vertex
*
@param
weight the weight of this edge
*
@throws
IllegalArgumentException if either {
@code
v} or {
@code
w}
* is a negative integer
*
@throws
IllegalArgumentException if {
@code
weight} is {
@code
NaN}
*/
public
Edge
(
int
v
,
int
w
,
double
weight
)
{
if
(
v
<
0
)
throw
new
IllegalArgumentException
(
"vertex index must be a nonnegative integer"
);
if
(
w
<
0
)
throw
new
IllegalArgumentException
(
"vertex index must be a nonnegative integer"
);
if
(
Double
.
isNaN
(
weight
))
throw
new
IllegalArgumentException
(
"Weight is NaN"
);
this
.
v
=
v
;
this
.
w
=
w
;
this
.
weight
=
weight
;
}
/**
* Returns the weight of this edge.
*
*
@return
the weight of this edge
*/
public
double
weight
()
{
return
weight
;
}
/**
* Returns either endpoint of this edge.
*
*
@return
either endpoint of this edge
*/
public
int
either
()
{
return
v
;
}
/**
* Returns the endpoint of this edge that is different from the given vertex.
*
*
@param
vertex one endpoint of this edge
*
@return
the other endpoint of this edge
*
@throws
IllegalArgumentException if the vertex is not one of the
* endpoints of this edge
*/
public
int
other
(
int
vertex
)
{
if
(
vertex
==
v
)
return
w
;
else
if
(
vertex
==
w
)
return
v
;
else
throw
new
IllegalArgumentException
(
"Illegal endpoint"
);
}
/**
* Compares two edges by weight.
* Note that {
@code
compareTo()} is not consistent with {
@code
equals()},
* which uses the reference equality implementation inherited from {
@code
Object}.
*
*
@param
that the other edge
*
@return
a negative integer, zero, or positive integer depending on whether
* the weight of this is less than, equal to, or greater than the
* argument edge
*/
@
Override
public
int
compareTo
(
Edge
that
)
{
return
Double
.
compare
(
this
.
weight
,
that
.
weight
);
}
/**
* Returns a string representation of this edge.
*
*
@return
a string representation of this edge
*/
public
String
toString
()
{
return
String
.
format
(
"%d-%d %.5f"
,
v
,
w
,
weight
);
}
/**
* Unit tests the {
@code
Edge} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
Edge
e
=
new
Edge
(
12
,
34
,
5.67
);
StdOut
.
println
(
e
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/EdgeWeightedDigraph.java
edu/princeton/cs/algs4/EdgeWeightedDigraph.java
/******************************************************************************
* Compilation: javac EdgeWeightedDigraph.java
* Execution: java EdgeWeightedDigraph digraph.txt
* Dependencies: Bag.java DirectedEdge.java
* Data files: https://algs4.cs.princeton.edu/44sp/tinyEWD.txt
* https://algs4.cs.princeton.edu/44sp/mediumEWD.txt
* https://algs4.cs.princeton.edu/44sp/largeEWD.txt
*
* An edge-weighted digraph, implemented using adjacency lists.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
NoSuchElementException
;
/**
* The {
@code
EdgeWeightedDigraph} class represents a edge-weighted
* digraph of vertices named 0 through V – 1, where each
* directed edge is of type {
@link
DirectedEdge} and has a real-valued weight.
* It supports the following two primary operations: add a directed edge
* to the digraph and iterate over all of edges incident from a given vertex.
* It also provides methods for returning the indegree or outdegree of a
* vertex, the number of vertices V in the digraph, and
* the number of edges E in the digraph.
* Parallel edges and self-loops are permitted.
*
* This implementation uses an adjacency-lists representation, which
* is a vertex-indexed array of {
@link
Bag} objects.
* It uses Θ(E + V) space, where E is
* the number of edges and V is the number of vertices.
* All instance methods take Θ(1) time. (Though, iterating over
* the edges returned by {
@link
#adj(int)} takes time proportional
* to the outdegree of the vertex.)
* Constructing an empty edge-weighted digraph with V vertices
* takes Θ(V) time; constructing an edge-weighted digraph
* with E edges and V vertices takes
* Θ(E + V) time.
*
* For additional documentation,
* see Section 4.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
EdgeWeightedDigraph
{
private
static
final
String
NEWLINE
=
System
.
getProperty
(
“line.separator”
);
private
final
int
V
;
// number of vertices in this digraph
private
int
E
;
// number of edges in this digraph
private
Bag
<
DirectedEdge
>
[]
adj
;
// adj[v] = adjacency list for vertex v
private
int
[]
indegree
;
// indegree[v] = indegree of vertex v
/**
* Initializes an empty edge-weighted digraph with {
@code
V} vertices and 0 edges.
*
*
@param
V the number of vertices
*
@throws
IllegalArgumentException if {
@code
V < 0}
*/
public
EdgeWeightedDigraph
(
int
V
)
{
if
(
V
<
0
)
throw
new
IllegalArgumentException
(
"Number of vertices in a Digraph must be nonnegative"
);
this
.
V
=
V
;
this
.
E
=
0
;
this
.
indegree
=
new
int
[
V
];
adj
=
(
Bag
<
DirectedEdge
>
[])
new
Bag
[
V
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
adj
[
v
]
=
new
Bag
<
DirectedEdge
>
();
}
/**
* Initializes a random edge-weighted digraph with {
@code
V} vertices and E edges.
*
*
@param
V the number of vertices
*
@param
E the number of edges
*
@throws
IllegalArgumentException if {
@code
V < 0}
*
@throws
IllegalArgumentException if {
@code
E < 0}
*/
public
EdgeWeightedDigraph
(
int
V
,
int
E
)
{
this
(
V
);
if
(
E
<
0
)
throw
new
IllegalArgumentException
(
"Number of edges in a Digraph must be nonnegative"
);
for
(
int
i
=
0
;
i
<
E
;
i
++
)
{
int
v
=
StdRandom
.
uniform
(
V
);
int
w
=
StdRandom
.
uniform
(
V
);
double
weight
=
0.01
*
StdRandom
.
uniform
(
100
);
DirectedEdge
e
=
new
DirectedEdge
(
v
,
w
,
weight
);
addEdge
(
e
);
}
}
/**
* Initializes an edge-weighted digraph from the specified input stream.
* The format is the number of vertices V,
* followed by the number of edges E,
* followed by E pairs of vertices and edge weights,
* with each entry separated by whitespace.
*
*
@param
in the input stream
*
@throws
IllegalArgumentException if {
@code
in} is {
@code
null}
*
@throws
IllegalArgumentException if the endpoints of any edge are not in prescribed range
*
@throws
IllegalArgumentException if the number of vertices or edges is negative
*/
public
EdgeWeightedDigraph
(
In
in
)
{
if
(
in
==
null
)
throw
new
IllegalArgumentException
(
“argument is null”
);
try
{
this
.
V
=
in
.
readInt
();
if
(
V
<
0
)
throw
new
IllegalArgumentException
(
"number of vertices in a Digraph must be nonnegative"
);
indegree
=
new
int
[
V
];
adj
=
(
Bag
<
DirectedEdge
>
[])
new
Bag
[
V
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
adj
[
v
]
=
new
Bag
<
DirectedEdge
>
();
}
int
E
=
in
.
readInt
();
if
(
E
<
0
)
throw
new
IllegalArgumentException
(
"Number of edges must be nonnegative"
);
for
(
int
i
=
0
;
i
<
E
;
i
++
)
{
int
v
=
in
.
readInt
();
int
w
=
in
.
readInt
();
validateVertex
(
v
);
validateVertex
(
w
);
double
weight
=
in
.
readDouble
();
addEdge
(
new
DirectedEdge
(
v
,
w
,
weight
));
}
}
catch
(
NoSuchElementException
e
)
{
throw
new
IllegalArgumentException
(
"invalid input format in EdgeWeightedDigraph constructor"
,
e
);
}
}
/**
* Initializes a new edge-weighted digraph that is a deep copy of {
@code
G}.
*
*
@param
G the edge-weighted digraph to copy
*/
public
EdgeWeightedDigraph
(
EdgeWeightedDigraph
G
)
{
this
(
G
.
V
());
this
.
E
=
G
.
E
();
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
this
.
indegree
[
v
]
=
G
.
indegree
(
v
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
// reverse so that adjacency list is in same order as original
Stack
<
DirectedEdge
>
reverse
=
new
Stack
<
DirectedEdge
>
();
for
(
DirectedEdge
e
:
G
.
adj
[
v
])
{
reverse
.
push
(
e
);
}
for
(
DirectedEdge
e
:
reverse
)
{
adj
[
v
].
add
(
e
);
}
}
}
/**
* Returns the number of vertices in this edge-weighted digraph.
*
*
@return
the number of vertices in this edge-weighted digraph
*/
public
int
V
()
{
return
V
;
}
/**
* Returns the number of edges in this edge-weighted digraph.
*
*
@return
the number of edges in this edge-weighted digraph
*/
public
int
E
()
{
return
E
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Adds the directed edge {
@code
e} to this edge-weighted digraph.
*
*
@param
e the edge
*
@throws
IllegalArgumentException unless endpoints of edge are between {
@code
0}
* and {
@code
V-1}
*/
public
void
addEdge
(
DirectedEdge
e
)
{
int
v
=
e
.
from
();
int
w
=
e
.
to
();
validateVertex
(
v
);
validateVertex
(
w
);
adj
[
v
].
add
(
e
);
indegree
[
w
]
++
;
E
++
;
}
/**
* Returns the directed edges incident from vertex {
@code
v}.
*
*
@param
v the vertex
*
@return
the directed edges incident from vertex {
@code
v} as an Iterable
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
Iterable
<
DirectedEdge
>
adj
(
int
v
)
{
validateVertex
(
v
);
return
adj
[
v
];
}
/**
* Returns the number of directed edges incident from vertex {
@code
v}.
* This is known as the outdegree of vertex {
@code
v}.
*
*
@param
v the vertex
*
@return
the outdegree of vertex {
@code
v}
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
int
outdegree
(
int
v
)
{
validateVertex
(
v
);
return
adj
[
v
].
size
();
}
/**
* Returns the number of directed edges incident to vertex {
@code
v}.
* This is known as the indegree of vertex {
@code
v}.
*
*
@param
v the vertex
*
@return
the indegree of vertex {
@code
v}
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
int
indegree
(
int
v
)
{
validateVertex
(
v
);
return
indegree
[
v
];
}
/**
* Returns all directed edges in this edge-weighted digraph.
* To iterate over the edges in this edge-weighted digraph, use foreach notation:
* {
@code
for (DirectedEdge e : G.edges())}.
*
*
@return
all edges in this edge-weighted digraph, as an iterable
*/
public
Iterable
<
DirectedEdge
>
edges
()
{
Bag
<
DirectedEdge
>
list
=
new
Bag
<
DirectedEdge
>
();
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
for
(
DirectedEdge
e
:
adj
(
v
))
{
list
.
add
(
e
);
}
}
return
list
;
}
/**
* Returns a string representation of this edge-weighted digraph.
*
*
@return
the number of vertices V, followed by the number of edges E,
* followed by the V adjacency lists of edges
*/
public
String
toString
()
{
StringBuilder
s
=
new
StringBuilder
();
s
.
append
(
V
+
” ”
+
E
+
NEWLINE
);
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
s
.
append
(
v
+
": "
);
for
(
DirectedEdge
e
:
adj
[
v
])
{
s
.
append
(
e
+
" "
);
}
s
.
append
(
NEWLINE
);
}
return
s
.
toString
();
}
/**
* Unit tests the {
@code
EdgeWeightedDigraph} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
EdgeWeightedDigraph
G
=
new
EdgeWeightedDigraph
(
in
);
StdOut
.
println
(
G
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/EdgeWeightedDirectedCycle.java
edu/princeton/cs/algs4/EdgeWeightedDirectedCycle.java
/******************************************************************************
* Compilation: javac EdgeWeightedDirectedCycle.java
* Execution: java EdgeWeightedDirectedCycle V E F
* Dependencies: EdgeWeightedDigraph.java DirectedEdge.java Stack.java
*
* Finds a directed cycle in an edge-weighted digraph.
* Runs in O(E + V) time.
*
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
EdgeWeightedDirectedCycle} class represents a data type for
* determining whether an edge-weighted digraph has a directed cycle.
* The hasCycle operation determines whether the edge-weighted
* digraph has a directed cycle and, if so, the cycle operation
* returns one.
*
* This implementation uses depth-first search.
* The constructor takes Θ(V + E) time in the
* worst case, where V is the number of vertices and
* E is the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the
* edge-weighted digraph).
*
* See {
@link
Topological} to compute a topological order if the
* edge-weighted digraph is acyclic.
*
* For additional documentation,
* see Section 4.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
EdgeWeightedDirectedCycle
{
private
boolean
[]
marked
;
// marked[v] = has vertex v been marked?
private
DirectedEdge
[]
edgeTo
;
// edgeTo[v] = previous edge on path to v
private
boolean
[]
onStack
;
// onStack[v] = is vertex on the stack?
private
Stack
<
DirectedEdge
>
cycle
;
// directed cycle (or null if no such cycle)
/**
* Determines whether the edge-weighted digraph {
@code
G} has a directed cycle and,
* if so, finds such a cycle.
*
@param
G the edge-weighted digraph
*/
public
EdgeWeightedDirectedCycle
(
EdgeWeightedDigraph
G
)
{
marked
=
new
boolean
[
G
.
V
()];
onStack
=
new
boolean
[
G
.
V
()];
edgeTo
=
new
DirectedEdge
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
!
marked
[
v
])
dfs
(
G
,
v
);
// check that digraph has a cycle
assert
check
();
}
// check that algorithm computes either the topological order or finds a directed cycle
private
void
dfs
(
EdgeWeightedDigraph
G
,
int
v
)
{
onStack
[
v
]
=
true
;
marked
[
v
]
=
true
;
for
(
DirectedEdge
e
:
G
.
adj
(
v
))
{
int
w
=
e
.
to
();
// short circuit if directed cycle found
if
(
cycle
!=
null
)
return
;
// found new vertex, so recur
else
if
(
!
marked
[
w
])
{
edgeTo
[
w
]
=
e
;
dfs
(
G
,
w
);
}
// trace back directed cycle
else
if
(
onStack
[
w
])
{
cycle
=
new
Stack
<
DirectedEdge
>
();
DirectedEdge
f
=
e
;
while
(
f
.
from
()
!=
w
)
{
cycle
.
push
(
f
);
f
=
edgeTo
[
f
.
from
()];
}
cycle
.
push
(
f
);
return
;
}
}
onStack
[
v
]
=
false
;
}
/**
* Does the edge-weighted digraph have a directed cycle?
*
@return
{
@code
true} if the edge-weighted digraph has a directed cycle,
* {
@code
false} otherwise
*/
public
boolean
hasCycle
()
{
return
cycle
!=
null
;
}
/**
* Returns a directed cycle if the edge-weighted digraph has a directed cycle,
* and {
@code
null} otherwise.
*
@return
a directed cycle (as an iterable) if the edge-weighted digraph
* has a directed cycle, and {
@code
null} otherwise
*/
public
Iterable
<
DirectedEdge
>
cycle
()
{
return
cycle
;
}
// certify that digraph is either acyclic or has a directed cycle
private
boolean
check
()
{
// edge-weighted digraph is cyclic
if
(
hasCycle
())
{
// verify cycle
DirectedEdge
first
=
null
,
last
=
null
;
for
(
DirectedEdge
e
:
cycle
())
{
if
(
first
==
null
)
first
=
e
;
if
(
last
!=
null
)
{
if
(
last
.
to
()
!=
e
.
from
())
{
System
.
err
.
printf
(
“cycle edges %s and %s not incident\n”
,
last
,
e
);
return
false
;
}
}
last
=
e
;
}
if
(
last
.
to
()
!=
first
.
from
())
{
System
.
err
.
printf
(
“cycle edges %s and %s not incident\n”
,
last
,
first
);
return
false
;
}
}
return
true
;
}
/**
* Unit tests the {
@code
EdgeWeightedDirectedCycle} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// create random DAG with V vertices and E edges; then add F random edges
int
V
=
Integer
.
parseInt
(
args
[
0
]);
int
E
=
Integer
.
parseInt
(
args
[
1
]);
int
F
=
Integer
.
parseInt
(
args
[
2
]);
EdgeWeightedDigraph
G
=
new
EdgeWeightedDigraph
(
V
);
int
[]
vertices
=
new
int
[
V
];
for
(
int
i
=
0
;
i
<
V
;
i
++
)
vertices
[
i
]
=
i
;
StdRandom
.
shuffle
(
vertices
);
for
(
int
i
=
0
;
i
<
E
;
i
++
)
{
int
v
,
w
;
do
{
v
=
StdRandom
.
uniform
(
V
);
w
=
StdRandom
.
uniform
(
V
);
}
while
(
v
>=
w
);
double
weight
=
StdRandom
.
uniform
();
G
.
addEdge
(
new
DirectedEdge
(
v
,
w
,
weight
));
}
// add F extra edges
for
(
int
i
=
0
;
i
<
F
;
i
++
)
{
int
v
=
StdRandom
.
uniform
(
V
);
int
w
=
StdRandom
.
uniform
(
V
);
double
weight
=
StdRandom
.
uniform
(
0.0
,
1.0
);
G
.
addEdge
(
new
DirectedEdge
(
v
,
w
,
weight
));
}
StdOut
.
println
(
G
);
// find a directed cycle
EdgeWeightedDirectedCycle
finder
=
new
EdgeWeightedDirectedCycle
(
G
);
if
(
finder
.
hasCycle
())
{
StdOut
.
print
(
"Cycle: "
);
for
(
DirectedEdge
e
:
finder
.
cycle
())
{
StdOut
.
print
(
e
+
" "
);
}
StdOut
.
println
();
}
// or give topologial sort
else
{
StdOut
.
println
(
"No directed cycle"
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/EdgeWeightedGraph.java
edu/princeton/cs/algs4/EdgeWeightedGraph.java
/******************************************************************************
* Compilation: javac EdgeWeightedGraph.java
* Execution: java EdgeWeightedGraph filename.txt
* Dependencies: Bag.java Edge.java In.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/43mst/tinyEWG.txt
* https://algs4.cs.princeton.edu/43mst/mediumEWG.txt
* https://algs4.cs.princeton.edu/43mst/largeEWG.txt
*
* An edge-weighted undirected graph, implemented using adjacency lists.
* Parallel edges and self-loops are permitted.
*
* % java EdgeWeightedGraph tinyEWG.txt
* 8 16
* 0: 6-0 0.58000 0-2 0.26000 0-4 0.38000 0-7 0.16000
* 1: 1-3 0.29000 1-2 0.36000 1-7 0.19000 1-5 0.32000
* 2: 6-2 0.40000 2-7 0.34000 1-2 0.36000 0-2 0.26000 2-3 0.17000
* 3: 3-6 0.52000 1-3 0.29000 2-3 0.17000
* 4: 6-4 0.93000 0-4 0.38000 4-7 0.37000 4-5 0.35000
* 5: 1-5 0.32000 5-7 0.28000 4-5 0.35000
* 6: 6-4 0.93000 6-0 0.58000 3-6 0.52000 6-2 0.40000
* 7: 2-7 0.34000 1-7 0.19000 0-7 0.16000 5-7 0.28000 4-7 0.37000
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
NoSuchElementException
;
/**
* The {
@code
EdgeWeightedGraph} class represents an edge-weighted
* graph of vertices named 0 through V – 1, where each
* undirected edge is of type {
@link
Edge} and has a real-valued weight.
* It supports the following two primary operations: add an edge to the graph,
* iterate over all of the edges incident to a vertex. It also provides
* methods for returning the degree of a vertex, the number of vertices
* V in the graph, and the number of edges E in the graph.
* Parallel edges and self-loops are permitted.
* By convention, a self-loop v–v appears in the
* adjacency list of v twice and contributes two to the degree
* of v.
*
* This implementation uses an adjacency-lists representation, which
* is a vertex-indexed array of {
@link
Bag} objects.
* It uses Θ(E + V) space, where E is
* the number of edges and V is the number of vertices.
* All instance methods take Θ(1) time. (Though, iterating over
* the edges returned by {
@link
#adj(int)} takes time proportional
* to the degree of the vertex.)
* Constructing an empty edge-weighted graph with V vertices takes
* Θ(V) time; constructing a edge-weighted graph with
* E edges and V vertices takes
* Θ(E + V) time.
*
* For additional documentation,
* see Section 4.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
EdgeWeightedGraph
{
private
static
final
String
NEWLINE
=
System
.
getProperty
(
“line.separator”
);
private
final
int
V
;
private
int
E
;
private
Bag
<
Edge
>
[]
adj
;
/**
* Initializes an empty edge-weighted graph with {
@code
V} vertices and 0 edges.
*
*
@param
V the number of vertices
*
@throws
IllegalArgumentException if {
@code
V < 0}
*/
public
EdgeWeightedGraph
(
int
V
)
{
if
(
V
<
0
)
throw
new
IllegalArgumentException
(
"Number of vertices must be nonnegative"
);
this
.
V
=
V
;
this
.
E
=
0
;
adj
=
(
Bag
<
Edge
>
[])
new
Bag
[
V
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
adj
[
v
]
=
new
Bag
<
Edge
>
();
}
}
/**
* Initializes a random edge-weighted graph with {
@code
V} vertices and E edges.
*
*
@param
V the number of vertices
*
@param
E the number of edges
*
@throws
IllegalArgumentException if {
@code
V < 0}
*
@throws
IllegalArgumentException if {
@code
E < 0}
*/
public
EdgeWeightedGraph
(
int
V
,
int
E
)
{
this
(
V
);
if
(
E
<
0
)
throw
new
IllegalArgumentException
(
"Number of edges must be nonnegative"
);
for
(
int
i
=
0
;
i
<
E
;
i
++
)
{
int
v
=
StdRandom
.
uniform
(
V
);
int
w
=
StdRandom
.
uniform
(
V
);
double
weight
=
Math
.
round
(
100
*
StdRandom
.
uniform
())
/
100.0
;
Edge
e
=
new
Edge
(
v
,
w
,
weight
);
addEdge
(
e
);
}
}
/**
* Initializes an edge-weighted graph from an input stream.
* The format is the number of vertices V,
* followed by the number of edges E,
* followed by E pairs of vertices and edge weights,
* with each entry separated by whitespace.
*
*
@param
in the input stream
*
@throws
IllegalArgumentException if {
@code
in} is {
@code
null}
*
@throws
IllegalArgumentException if the endpoints of any edge are not in prescribed range
*
@throws
IllegalArgumentException if the number of vertices or edges is negative
*/
public
EdgeWeightedGraph
(
In
in
)
{
if
(
in
==
null
)
throw
new
IllegalArgumentException
(
“argument is null”
);
try
{
V
=
in
.
readInt
();
adj
=
(
Bag
<
Edge
>
[])
new
Bag
[
V
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
adj
[
v
]
=
new
Bag
<
Edge
>
();
}
int
E
=
in
.
readInt
();
if
(
E
<
0
)
throw
new
IllegalArgumentException
(
"Number of edges must be nonnegative"
);
for
(
int
i
=
0
;
i
<
E
;
i
++
)
{
int
v
=
in
.
readInt
();
int
w
=
in
.
readInt
();
validateVertex
(
v
);
validateVertex
(
w
);
double
weight
=
in
.
readDouble
();
Edge
e
=
new
Edge
(
v
,
w
,
weight
);
addEdge
(
e
);
}
}
catch
(
NoSuchElementException
e
)
{
throw
new
IllegalArgumentException
(
"invalid input format in EdgeWeightedGraph constructor"
,
e
);
}
}
/**
* Initializes a new edge-weighted graph that is a deep copy of {
@code
G}.
*
*
@param
G the edge-weighted graph to copy
*/
public
EdgeWeightedGraph
(
EdgeWeightedGraph
G
)
{
this
(
G
.
V
());
this
.
E
=
G
.
E
();
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
// reverse so that adjacency list is in same order as original
Stack
<
Edge
>
reverse
=
new
Stack
<
Edge
>
();
for
(
Edge
e
:
G
.
adj
[
v
])
{
reverse
.
push
(
e
);
}
for
(
Edge
e
:
reverse
)
{
adj
[
v
].
add
(
e
);
}
}
}
/**
* Returns the number of vertices in this edge-weighted graph.
*
*
@return
the number of vertices in this edge-weighted graph
*/
public
int
V
()
{
return
V
;
}
/**
* Returns the number of edges in this edge-weighted graph.
*
*
@return
the number of edges in this edge-weighted graph
*/
public
int
E
()
{
return
E
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Adds the undirected edge {
@code
e} to this edge-weighted graph.
*
*
@param
e the edge
*
@throws
IllegalArgumentException unless both endpoints are between {
@code
0} and {
@code
V-1}
*/
public
void
addEdge
(
Edge
e
)
{
int
v
=
e
.
either
();
int
w
=
e
.
other
(
v
);
validateVertex
(
v
);
validateVertex
(
w
);
adj
[
v
].
add
(
e
);
adj
[
w
].
add
(
e
);
E
++
;
}
/**
* Returns the edges incident on vertex {
@code
v}.
*
*
@param
v the vertex
*
@return
the edges incident on vertex {
@code
v} as an Iterable
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
Iterable
<
Edge
>
adj
(
int
v
)
{
validateVertex
(
v
);
return
adj
[
v
];
}
/**
* Returns the degree of vertex {
@code
v}.
*
*
@param
v the vertex
*
@return
the degree of vertex {
@code
v}
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
int
degree
(
int
v
)
{
validateVertex
(
v
);
return
adj
[
v
].
size
();
}
/**
* Returns all edges in this edge-weighted graph.
* To iterate over the edges in this edge-weighted graph, use foreach notation:
* {
@code
for (Edge e : G.edges())}.
*
*
@return
all edges in this edge-weighted graph, as an iterable
*/
public
Iterable
<
Edge
>
edges
()
{
Bag
<
Edge
>
list
=
new
Bag
<
Edge
>
();
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
int
selfLoops
=
0
;
for
(
Edge
e
:
adj
(
v
))
{
if
(
e
.
other
(
v
)
>
v
)
{
list
.
add
(
e
);
}
// add only one copy of each self loop (self loops will be consecutive)
else
if
(
e
.
other
(
v
)
==
v
)
{
if
(
selfLoops
%
2
==
0
)
list
.
add
(
e
);
selfLoops
++
;
}
}
}
return
list
;
}
/**
* Returns a string representation of the edge-weighted graph.
* This method takes time proportional to E + V.
*
*
@return
the number of vertices V, followed by the number of edges E,
* followed by the V adjacency lists of edges
*/
public
String
toString
()
{
StringBuilder
s
=
new
StringBuilder
();
s
.
append
(
V
+
” ”
+
E
+
NEWLINE
);
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
s
.
append
(
v
+
": "
);
for
(
Edge
e
:
adj
[
v
])
{
s
.
append
(
e
+
" "
);
}
s
.
append
(
NEWLINE
);
}
return
s
.
toString
();
}
/**
* Unit tests the {
@code
EdgeWeightedGraph} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
EdgeWeightedGraph
G
=
new
EdgeWeightedGraph
(
in
);
StdOut
.
println
(
G
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/EulerianCycle.java
edu/princeton/cs/algs4/EulerianCycle.java
/******************************************************************************
* Compilation: javac EulerianCycle.java
* Execution: java EulerianCycle V E
* Dependencies: Graph.java Stack.java StdOut.java
*
* Find an Eulerian cycle in a graph, if one exists.
*
* Runs in O(E + V) time.
*
* This implementation is tricker than the one for digraphs because
* when we use edge v-w from v's adjacency list, we must be careful
* not to use the second copy of the edge from w's adjaceny list.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
EulerianCycle} class represents a data type
* for finding an Eulerian cycle or path in a graph.
* An Eulerian cycle is a cycle (not necessarily simple) that
* uses every edge in the graph exactly once.
*
* This implementation uses a nonrecursive depth-first search.
* The constructor takes Θ(E + V) time in the worst
* case, where E is the number of edges and V is the
* number of vertices
* Each instance method takes Θ(1) time.
* It uses Θ(E + V) extra space in the worst case
* (not including the graph).
*
* To compute Eulerian paths in graphs, see {
@link
EulerianPath}.
* To compute Eulerian cycles and paths in digraphs, see
* {
@link
DirectedEulerianCycle} and {
@link
DirectedEulerianPath}.
*
* For additional documentation,
* see Section 4.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*
@author
Nate Liu
*/
public
class
EulerianCycle
{
private
Stack
<
Integer
>
cycle
=
new
Stack
<
Integer
>
();
// Eulerian cycle; null if no such cycle
// an undirected edge, with a field to indicate whether the edge has already been used
private
static
class
Edge
{
private
final
int
v
;
private
final
int
w
;
private
boolean
isUsed
;
public
Edge
(
int
v
,
int
w
)
{
this
.
v
=
v
;
this
.
w
=
w
;
isUsed
=
false
;
}
// returns the other vertex of the edge
public
int
other
(
int
vertex
)
{
if
(
vertex
==
v
)
return
w
;
else
if
(
vertex
==
w
)
return
v
;
else
throw
new
IllegalArgumentException
(
“Illegal endpoint”
);
}
}
/**
* Computes an Eulerian cycle in the specified graph, if one exists.
*
*
@param
G the graph
*/
public
EulerianCycle
(
Graph
G
)
{
// must have at least one edge
if
(
G
.
E
()
==
0
)
return
;
// necessary condition: all vertices have even degree
// (this test is needed or it might find an Eulerian path instead of cycle)
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
G
.
degree
(
v
)
%
2
!=
0
)
return
;
// create local view of adjacency lists, to iterate one vertex at a time
// the helper Edge data type is used to avoid exploring both copies of an edge v-w
Queue
<
Edge
>
[]
adj
=
(
Queue
<
Edge
>
[])
new
Queue
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
adj
[
v
]
=
new
Queue
<
Edge
>
();
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
int
selfLoops
=
0
;
for
(
int
w
:
G
.
adj
(
v
))
{
// careful with self loops
if
(
v
==
w
)
{
if
(
selfLoops
%
2
==
0
)
{
Edge
e
=
new
Edge
(
v
,
w
);
adj
[
v
].
enqueue
(
e
);
adj
[
w
].
enqueue
(
e
);
}
selfLoops
++
;
}
else
if
(
v
<
w
)
{
Edge
e
=
new
Edge
(
v
,
w
);
adj
[
v
].
enqueue
(
e
);
adj
[
w
].
enqueue
(
e
);
}
}
}
// initialize stack with any non-isolated vertex
int
s
=
nonIsolatedVertex
(
G
);
Stack
<
Integer
>
stack
=
new
Stack
<
Integer
>
();
stack
.
push
(
s
);
// greedily search through edges in iterative DFS style
cycle
=
new
Stack
<
Integer
>
();
while
(
!
stack
.
isEmpty
())
{
int
v
=
stack
.
pop
();
while
(
!
adj
[
v
].
isEmpty
())
{
Edge
edge
=
adj
[
v
].
dequeue
();
if
(
edge
.
isUsed
)
continue
;
edge
.
isUsed
=
true
;
stack
.
push
(
v
);
v
=
edge
.
other
(
v
);
}
// push vertex with no more leaving edges to cycle
cycle
.
push
(
v
);
}
// check if all edges are used
if
(
cycle
.
size
()
!=
G
.
E
()
+
1
)
cycle
=
null
;
assert
certifySolution
(
G
);
}
/**
* Returns the sequence of vertices on an Eulerian cycle.
*
*
@return
the sequence of vertices on an Eulerian cycle;
* {
@code
null} if no such cycle
*/
public
Iterable
<
Integer
>
cycle
()
{
return
cycle
;
}
/**
* Returns true if the graph has an Eulerian cycle.
*
*
@return
{
@code
true} if the graph has an Eulerian cycle;
* {
@code
false} otherwise
*/
public
boolean
hasEulerianCycle
()
{
return
cycle
!=
null
;
}
// returns any non-isolated vertex; -1 if no such vertex
private
static
int
nonIsolatedVertex
(
Graph
G
)
{
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
G
.
degree
(
v
)
>
0
)
return
v
;
return
–
1
;
}
/**************************************************************************
*
* The code below is solely for testing correctness of the data type.
*
**************************************************************************/
// Determines whether a graph has an Eulerian cycle using necessary
// and sufficient conditions (without computing the cycle itself):
// – at least one edge
// – degree(v) is even for every vertex v
// – the graph is connected (ignoring isolated vertices)
private
static
boolean
satisfiesNecessaryAndSufficientConditions
(
Graph
G
)
{
// Condition 0: at least 1 edge
if
(
G
.
E
()
==
0
)
return
false
;
// Condition 1: degree(v) is even for every vertex
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
G
.
degree
(
v
)
%
2
!=
0
)
return
false
;
// Condition 2: graph is connected, ignoring isolated vertices
int
s
=
nonIsolatedVertex
(
G
);
BreadthFirstPaths
bfs
=
new
BreadthFirstPaths
(
G
,
s
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
G
.
degree
(
v
)
>
0
&&
!
bfs
.
hasPathTo
(
v
))
return
false
;
return
true
;
}
// check that solution is correct
private
boolean
certifySolution
(
Graph
G
)
{
// internal consistency check
if
(
hasEulerianCycle
()
==
(
cycle
()
==
null
))
return
false
;
// hashEulerianCycle() returns correct value
if
(
hasEulerianCycle
()
!=
satisfiesNecessaryAndSufficientConditions
(
G
))
return
false
;
// nothing else to check if no Eulerian cycle
if
(
cycle
==
null
)
return
true
;
// check that cycle() uses correct number of edges
if
(
cycle
.
size
()
!=
G
.
E
()
+
1
)
return
false
;
// check that cycle() is a cycle of G
// TODO
// check that first and last vertices in cycle() are the same
int
first
=
–
1
,
last
=
–
1
;
for
(
int
v
:
cycle
())
{
if
(
first
==
–
1
)
first
=
v
;
last
=
v
;
}
if
(
first
!=
last
)
return
false
;
return
true
;
}
private
static
void
unitTest
(
Graph
G
,
String
description
)
{
StdOut
.
println
(
description
);
StdOut
.
println
(
“————————————-”
);
StdOut
.
print
(
G
);
EulerianCycle
euler
=
new
EulerianCycle
(
G
);
StdOut
.
print
(
“Eulerian cycle: ”
);
if
(
euler
.
hasEulerianCycle
())
{
for
(
int
v
:
euler
.
cycle
())
{
StdOut
.
print
(
v
+
” ”
);
}
StdOut
.
println
();
}
else
{
StdOut
.
println
(
“none”
);
}
StdOut
.
println
();
}
/**
* Unit tests the {
@code
EulerianCycle} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
V
=
Integer
.
parseInt
(
args
[
0
]);
int
E
=
Integer
.
parseInt
(
args
[
1
]);
// Eulerian cycle
Graph
G1
=
GraphGenerator
.
eulerianCycle
(
V
,
E
);
unitTest
(
G1
,
“Eulerian cycle”
);
// Eulerian path
Graph
G2
=
GraphGenerator
.
eulerianPath
(
V
,
E
);
unitTest
(
G2
,
“Eulerian path”
);
// empty graph
Graph
G3
=
new
Graph
(
V
);
unitTest
(
G3
,
“empty graph”
);
// self loop
Graph
G4
=
new
Graph
(
V
);
int
v4
=
StdRandom
.
uniform
(
V
);
G4
.
addEdge
(
v4
,
v4
);
unitTest
(
G4
,
“single self loop”
);
// union of two disjoint cycles
Graph
H1
=
GraphGenerator
.
eulerianCycle
(
V
/
2
,
E
/
2
);
Graph
H2
=
GraphGenerator
.
eulerianCycle
(
V
–
V
/
2
,
E
–
E
/
2
);
int
[]
perm
=
new
int
[
V
];
for
(
int
i
=
0
;
i
<
V
;
i
++
)
perm
[
i
]
=
i
;
StdRandom
.
shuffle
(
perm
);
Graph
G5
=
new
Graph
(
V
);
for
(
int
v
=
0
;
v
<
H1
.
V
();
v
++
)
for
(
int
w
:
H1
.
adj
(
v
))
G5
.
addEdge
(
perm
[
v
],
perm
[
w
]);
for
(
int
v
=
0
;
v
<
H2
.
V
();
v
++
)
for
(
int
w
:
H2
.
adj
(
v
))
G5
.
addEdge
(
perm
[
V
/
2
+
v
],
perm
[
V
/
2
+
w
]);
unitTest
(
G5
,
"Union of two disjoint cycles"
);
// random digraph
Graph
G6
=
GraphGenerator
.
simple
(
V
,
E
);
unitTest
(
G6
,
"simple graph"
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/EulerianPath.java
edu/princeton/cs/algs4/EulerianPath.java
/******************************************************************************
* Compilation: javac EulerianPath.java
* Execution: java EulerianPath V E
* Dependencies: Graph.java Stack.java StdOut.java
*
* Find an Eulerian path in a graph, if one exists.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
EulerianPath} class represents a data type
* for finding an Eulerian path in a graph.
* An Eulerian path is a path (not necessarily simple) that
* uses every edge in the graph exactly once.
*
* This implementation uses a nonrecursive depth-first search.
* The constructor takes Θ(E + V) time in the worst
* case, where E is the number of edges and V is
* the number of vertices.
* Each instance method takes Θ(1) time.
* It uses Θ(E + V) extra space in the worst case
* (not including the digraph).
*
* To compute Eulerian cycles in graphs, see {
@link
EulerianCycle}.
* To compute Eulerian cycles and paths in digraphs, see
* {
@link
DirectedEulerianCycle} and {
@link
DirectedEulerianPath}.
*
* For additional documentation,
* see Section 4.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*
@author
Nate Liu
*/
public
class
EulerianPath
{
private
Stack
<
Integer
>
path
=
null
;
// Eulerian path; null if no suh path
// an undirected edge, with a field to indicate whether the edge has already been used
private
static
class
Edge
{
private
final
int
v
;
private
final
int
w
;
private
boolean
isUsed
;
public
Edge
(
int
v
,
int
w
)
{
this
.
v
=
v
;
this
.
w
=
w
;
isUsed
=
false
;
}
// returns the other vertex of the edge
public
int
other
(
int
vertex
)
{
if
(
vertex
==
v
)
return
w
;
else
if
(
vertex
==
w
)
return
v
;
else
throw
new
IllegalArgumentException
(
“Illegal endpoint”
);
}
}
/**
* Computes an Eulerian path in the specified graph, if one exists.
*
*
@param
G the graph
*/
public
EulerianPath
(
Graph
G
)
{
// find vertex from which to start potential Eulerian path:
// a vertex v with odd degree(v) if it exits;
// otherwise a vertex with degree(v) > 0
int
oddDegreeVertices
=
0
;
int
s
=
nonIsolatedVertex
(
G
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
G
.
degree
(
v
)
%
2
!=
0
)
{
oddDegreeVertices
++
;
s
=
v
;
}
}
// graph can't have an Eulerian path
// (this condition is needed for correctness)
if
(
oddDegreeVertices
>
2
)
return
;
// special case for graph with zero edges (has a degenerate Eulerian path)
if
(
s
==
–
1
)
s
=
0
;
// create local view of adjacency lists, to iterate one vertex at a time
// the helper Edge data type is used to avoid exploring both copies of an edge v-w
Queue
<
Edge
>
[]
adj
=
(
Queue
<
Edge
>
[])
new
Queue
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
adj
[
v
]
=
new
Queue
<
Edge
>
();
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
int
selfLoops
=
0
;
for
(
int
w
:
G
.
adj
(
v
))
{
// careful with self loops
if
(
v
==
w
)
{
if
(
selfLoops
%
2
==
0
)
{
Edge
e
=
new
Edge
(
v
,
w
);
adj
[
v
].
enqueue
(
e
);
adj
[
w
].
enqueue
(
e
);
}
selfLoops
++
;
}
else
if
(
v
<
w
)
{
Edge
e
=
new
Edge
(
v
,
w
);
adj
[
v
].
enqueue
(
e
);
adj
[
w
].
enqueue
(
e
);
}
}
}
// initialize stack with any non-isolated vertex
Stack
<
Integer
>
stack
=
new
Stack
<
Integer
>
();
stack
.
push
(
s
);
// greedily search through edges in iterative DFS style
path
=
new
Stack
<
Integer
>
();
while
(
!
stack
.
isEmpty
())
{
int
v
=
stack
.
pop
();
while
(
!
adj
[
v
].
isEmpty
())
{
Edge
edge
=
adj
[
v
].
dequeue
();
if
(
edge
.
isUsed
)
continue
;
edge
.
isUsed
=
true
;
stack
.
push
(
v
);
v
=
edge
.
other
(
v
);
}
// push vertex with no more leaving edges to path
path
.
push
(
v
);
}
// check if all edges are used
if
(
path
.
size
()
!=
G
.
E
()
+
1
)
path
=
null
;
assert
certifySolution
(
G
);
}
/**
* Returns the sequence of vertices on an Eulerian path.
*
*
@return
the sequence of vertices on an Eulerian path;
* {
@code
null} if no such path
*/
public
Iterable
<
Integer
>
path
()
{
return
path
;
}
/**
* Returns true if the graph has an Eulerian path.
*
*
@return
{
@code
true} if the graph has an Eulerian path;
* {
@code
false} otherwise
*/
public
boolean
hasEulerianPath
()
{
return
path
!=
null
;
}
// returns any non-isolated vertex; -1 if no such vertex
private
static
int
nonIsolatedVertex
(
Graph
G
)
{
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
G
.
degree
(
v
)
>
0
)
return
v
;
return
–
1
;
}
/**************************************************************************
*
* The code below is solely for testing correctness of the data type.
*
**************************************************************************/
// Determines whether a graph has an Eulerian path using necessary
// and sufficient conditions (without computing the path itself):
// – degree(v) is even for every vertex, except for possibly two
// – the graph is connected (ignoring isolated vertices)
// This method is solely for unit testing.
private
static
boolean
satisfiesNecessaryAndSufficientConditions
(
Graph
G
)
{
if
(
G
.
E
()
==
0
)
return
true
;
// Condition 1: degree(v) is even except for possibly two
int
oddDegreeVertices
=
0
;
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
G
.
degree
(
v
)
%
2
!=
0
)
oddDegreeVertices
++
;
if
(
oddDegreeVertices
>
2
)
return
false
;
// Condition 2: graph is connected, ignoring isolated vertices
int
s
=
nonIsolatedVertex
(
G
);
BreadthFirstPaths
bfs
=
new
BreadthFirstPaths
(
G
,
s
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
G
.
degree
(
v
)
>
0
&&
!
bfs
.
hasPathTo
(
v
))
return
false
;
return
true
;
}
// check that solution is correct
private
boolean
certifySolution
(
Graph
G
)
{
// internal consistency check
if
(
hasEulerianPath
()
==
(
path
()
==
null
))
return
false
;
// hashEulerianPath() returns correct value
if
(
hasEulerianPath
()
!=
satisfiesNecessaryAndSufficientConditions
(
G
))
return
false
;
// nothing else to check if no Eulerian path
if
(
path
==
null
)
return
true
;
// check that path() uses correct number of edges
if
(
path
.
size
()
!=
G
.
E
()
+
1
)
return
false
;
// check that path() is a path in G
// TODO
return
true
;
}
private
static
void
unitTest
(
Graph
G
,
String
description
)
{
StdOut
.
println
(
description
);
StdOut
.
println
(
“————————————-”
);
StdOut
.
print
(
G
);
EulerianPath
euler
=
new
EulerianPath
(
G
);
StdOut
.
print
(
“Eulerian path: ”
);
if
(
euler
.
hasEulerianPath
())
{
for
(
int
v
:
euler
.
path
())
{
StdOut
.
print
(
v
+
” ”
);
}
StdOut
.
println
();
}
else
{
StdOut
.
println
(
“none”
);
}
StdOut
.
println
();
}
/**
* Unit tests the {
@code
EulerianPath} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
V
=
Integer
.
parseInt
(
args
[
0
]);
int
E
=
Integer
.
parseInt
(
args
[
1
]);
// Eulerian cycle
Graph
G1
=
GraphGenerator
.
eulerianCycle
(
V
,
E
);
unitTest
(
G1
,
“Eulerian cycle”
);
// Eulerian path
Graph
G2
=
GraphGenerator
.
eulerianPath
(
V
,
E
);
unitTest
(
G2
,
“Eulerian path”
);
// add one random edge
Graph
G3
=
new
Graph
(
G2
);
G3
.
addEdge
(
StdRandom
.
uniform
(
V
),
StdRandom
.
uniform
(
V
));
unitTest
(
G3
,
“one random edge added to Eulerian path”
);
// self loop
Graph
G4
=
new
Graph
(
V
);
int
v4
=
StdRandom
.
uniform
(
V
);
G4
.
addEdge
(
v4
,
v4
);
unitTest
(
G4
,
“single self loop”
);
// single edge
Graph
G5
=
new
Graph
(
V
);
G5
.
addEdge
(
StdRandom
.
uniform
(
V
),
StdRandom
.
uniform
(
V
));
unitTest
(
G5
,
“single edge”
);
// empty graph
Graph
G6
=
new
Graph
(
V
);
unitTest
(
G6
,
“empty graph”
);
// random graph
Graph
G7
=
GraphGenerator
.
simple
(
V
,
E
);
unitTest
(
G7
,
“simple graph”
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/FarthestPair.java
edu/princeton/cs/algs4/FarthestPair.java
/******************************************************************************
* Compilation: javac FarthestPair.java
* Execution: java FarthestPair < input.txt * Dependencies: GrahamScan.java Point2D.java * Data files: https://algs4.cs.princeton.edu/99hull/rs1423.txt * https://algs4.cs.princeton.edu/99hull/kw1260.txt * * Given a set of n points in the plane, find the farthest pair * (equivalently, compute the diameter of the set of points). * * Computes the convex hull of the set of points and using the * rotating calipers method to find all antipodal point pairs * and the farthest pair. * * % java FarthestPair < input100.txt * 42697.98170874122 from (32011.0, 3140.0) to (822.0, 32301.0) * ******************************************************************************/ package edu . princeton . cs . algs4 ; /** * The { @code FarthestPair} data type computes the farthest pair of points * in a set of n points in the plane and provides accessor methods
* for getting the farthest pair of points and the distance between them.
* The distance between two points is their Euclidean distance.
*
* This implementation computes the convex hull of the set of points and
* uses the rotating calipers method to find all antipodal point pairs
* and the farthest pair.
* It runs in O(n log n) time in the worst case and uses
* O(N) extra space.
* See also {
@link
ClosestPair} and {
@link
GrahamScan}.
*
* For additional documentation, see Section 9.9 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
FarthestPair
{
// farthest pair of points and distance
private
Point2D
best1
,
best2
;
private
double
bestDistanceSquared
=
Double
.
NEGATIVE_INFINITY
;
/**
* Computes the farthest pair of points in the specified array of points.
*
*
@param
points the array of points
*
@throws
IllegalArgumentException if {
@code
points} is {
@code
null} or if any
* entry in {
@code
points[]} is {
@code
null}
*/
public
FarthestPair
(
Point2D
[]
points
)
{
if
(
points
==
null
)
throw
new
IllegalArgumentException
(
“constructor argument is null”
);
for
(
int
i
=
0
;
i
<
points
.
length
;
i
++
)
{
if
(
points
[
i
]
==
null
)
throw
new
IllegalArgumentException
(
"array element "
+
i
+
" is null"
);
}
GrahamScan
graham
=
new
GrahamScan
(
points
);
// single point
if
(
points
.
length
<=
1
)
return
;
// number of points on the hull
int
m
=
0
;
for
(
Point2D
p
:
graham
.
hull
())
m
++
;
// the hull, in counterclockwise order hull[1] to hull[m]
Point2D
[]
hull
=
new
Point2D
[
m
+
1
];
m
=
1
;
for
(
Point2D
p
:
graham
.
hull
())
{
hull
[
m
++
]
=
p
;
}
m
--
;
// all points are equal
if
(
m
==
1
)
return
;
// points are collinear
if
(
m
==
2
)
{
best1
=
hull
[
1
];
best2
=
hull
[
2
];
bestDistanceSquared
=
best1
.
distanceSquaredTo
(
best2
);
return
;
}
// k = farthest vertex from edge from hull[1] to hull[m]
int
k
=
2
;
while
(
Point2D
.
area2
(
hull
[
m
],
hull
[
1
],
hull
[
k
+
1
])
>
Point2D
.
area2
(
hull
[
m
],
hull
[
1
],
hull
[
k
]))
{
k
++
;
}
int
j
=
k
;
for
(
int
i
=
1
;
i
<=
k
&&
j
<=
m
;
i
++
)
{
// StdOut.println("hull[i] + " and " + hull[j] + " are antipodal");
if
(
hull
[
i
].
distanceSquaredTo
(
hull
[
j
])
>
bestDistanceSquared
)
{
best1
=
hull
[
i
];
best2
=
hull
[
j
];
bestDistanceSquared
=
hull
[
i
].
distanceSquaredTo
(
hull
[
j
]);
}
while
((
j
<
m
)
&&
Point2D
.
area2
(
hull
[
i
],
hull
[
i
+
1
],
hull
[
j
+
1
])
>
Point2D
.
area2
(
hull
[
i
],
hull
[
i
+
1
],
hull
[
j
]))
{
j
++
;
// StdOut.println(hull[i] + ” and ” + hull[j] + ” are antipodal”);
double
distanceSquared
=
hull
[
i
].
distanceSquaredTo
(
hull
[
j
]);
if
(
distanceSquared
>
bestDistanceSquared
)
{
best1
=
hull
[
i
];
best2
=
hull
[
j
];
bestDistanceSquared
=
hull
[
i
].
distanceSquaredTo
(
hull
[
j
]);
}
}
}
}
/**
* Returns one of the points in the farthest pair of points.
*
*
@return
one of the two points in the farthest pair of points;
* {
@code
null} if no such point (because there are fewer than 2 points)
*/
public
Point2D
either
()
{
return
best1
;
}
/**
* Returns the other point in the farthest pair of points.
*
*
@return
the other point in the farthest pair of points
* {
@code
null} if no such point (because there are fewer than 2 points)
*/
public
Point2D
other
()
{
return
best2
;
}
/**
* Returns the Eucliden distance between the farthest pair of points.
* This quantity is also known as the diameter of the set of points.
*
*
@return
the Euclidean distance between the farthest pair of points
* {
@code
Double.POSITIVE_INFINITY} if no such pair of points
* exist (because there are fewer than 2 points)
*/
public
double
distance
()
{
return
Math
.
sqrt
(
bestDistanceSquared
);
}
/**
* Unit tests the {
@code
FarthestPair} data type.
* Reads in an integer {
@code
n} and {
@code
n} points (specified by
* their x– and y-coordinates) from standard input;
* computes a farthest pair of points; and prints the pair to standard
* output.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
n
=
StdIn
.
readInt
();
Point2D
[]
points
=
new
Point2D
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
int
x
=
StdIn
.
readInt
();
int
y
=
StdIn
.
readInt
();
points
[
i
]
=
new
Point2D
(
x
,
y
);
}
FarthestPair
farthest
=
new
FarthestPair
(
points
);
StdOut
.
println
(
farthest
.
distance
()
+
" from "
+
farthest
.
either
()
+
" to "
+
farthest
.
other
());
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/FenwickTree.java
edu/princeton/cs/algs4/FenwickTree.java
/******************************************************************************
* Compilation: javac FenwickTree.java
* Execution: java FenwickTree
*
* A Fenwick tree.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
ArrayList
;
import
java
.
util
.
Arrays
;
/**
* Created by ricardodpsx
@gmail
.com on 4/01/15.
*
* In {
@code
Fenwick Tree} structure We arrange the array in an smart way to perform efficient range queries and updates.
* The key point is this: In a fenwick array, each position “responsible” for storing cumulative data of N previous positions (N could be 1)
* For example:
* array[40] stores: array[40] + array[39] … + array[32] (8 positions)
* array[32] stores: array[32] + array[31] … + array[1] (32 positions)
*
* But, how do you know how much positions a given index is “responsible” for?
*
* To know the number of items that a given array position ‘ind’ is responsible for
* We should extract from ‘ind’ the portion up to the first significant one of the binary representation of ‘ind’
* for example, given ind == 40 (101000 in binary), according to Fenwick algorithm
* what We want is to extract 1000(8 in decimal).
*
* This means that array[40] has cumulative information of 8 array items.
* But We still need to know the cumulative data bellow array[40 – 8 = 32]
* 32 is 100000 in binnary, and the portion up to the least significant one is 32 itself!
* So array[32] has information of 32 items, and We are done!
*
* So cummulative data of array[1…40] = array[40] + array[32]
* Because 40 has information of items from 40 to 32, and 32 has information of items from 32 to 1
*
* Memory usage: O(n)
*
*
@author
Ricardo Pacheco
*/
public
class
FenwickTree
{
int
[]
array
;
// 1-indexed array, In this array We save cumulative information to perform efficient range queries and updates
public
FenwickTree
(
int
size
)
{
array
=
new
int
[
size
+
1
];
}
/**
* Range Sum query from 1 to ind
* ind is 1-indexed
*
* Time-Complexity: O(log(n))
*
*
@param
ind index
*
@return
sum
*/
public
int
rsq
(
int
ind
)
{
assert
ind
>
0
;
int
sum
=
0
;
while
(
ind
>
0
)
{
sum
+=
array
[
ind
];
//Extracting the portion up to the first significant one of the binary representation of ‘ind’ and decrementing ind by that number
ind
-=
ind
&
(
–
ind
);
}
return
sum
;
}
/**
* Range Sum Query from a to b.
* Search for the sum from array index from a to b
* a and b are 1-indexed
*
* Time-Complexity: O(log(n))
*
*
@param
a left index
*
@param
b right index
*
@return
sum
*/
public
int
rsq
(
int
a
,
int
b
)
{
assert
b
>=
a
&&
a
>
0
&&
b
>
0
;
return
rsq
(
b
)
–
rsq
(
a
–
1
);
}
/**
* Update the array at ind and all the affected regions above ind.
* ind is 1-indexed
*
* Time-Complexity: O(log(n))
*
*
@param
ind index
*
@param
value value
*/
public
void
update
(
int
ind
,
int
value
)
{
assert
ind
>
0
;
while
(
ind
<
array
.
length
)
{
array
[
ind
]
+=
value
;
//Extracting the portion up to the first significant one of the binary representation of 'ind' and incrementing ind by that number
ind
+=
ind
&
(
-
ind
);
}
}
public
int
size
()
{
return
array
.
length
-
1
;
}
/**
* Read the following commands:
* init n Initializes the array of size n all zeroes
* set a b c Initializes the array with [a, b, c ...]
* rsq a b Range Sum Query for the range [a,b]
* up i v Update the i position of the array with value v.
* exit
*
* The array is 1-indexed
* Example:
* set 1 2 3 4 5 6
* rsq 1 3
* Sum from 1 to 3 = 6
* rmq 1 3
* Min from 1 to 3 = 1
* input up 1 3
* [3,2,3,4,5,6]
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
FenwickTree
ft
=
null
;
String
cmd
=
“cmp”
;
while
(
true
)
{
String
[]
line
=
StdIn
.
readLine
().
split
(
” ”
);
if
(
line
[
0
].
equals
(
“exit”
))
break
;
int
arg1
=
0
,
arg2
=
0
;
if
(
line
.
length
>
1
)
{
arg1
=
Integer
.
parseInt
(
line
[
1
]);
}
if
(
line
.
length
>
2
)
{
arg2
=
Integer
.
parseInt
(
line
[
2
]);
}
if
((
!
line
[
0
].
equals
(
“set”
)
&&
!
line
[
0
].
equals
(
“init”
))
&&
ft
==
null
)
{
StdOut
.
println
(
“FenwickTree not initialized”
);
continue
;
}
if
(
line
[
0
].
equals
(
“init”
))
{
ft
=
new
FenwickTree
(
arg1
);
for
(
int
i
=
1
;
i
<=
ft
.
size
();
i
++
)
{
StdOut
.
print
(
ft
.
rsq
(
i
,
i
)
+
" "
);
}
StdOut
.
println
();
}
else
if
(
line
[
0
].
equals
(
"set"
))
{
ft
=
new
FenwickTree
(
line
.
length
-
1
);
for
(
int
i
=
1
;
i
<=
line
.
length
-
1
;
i
++
)
{
ft
.
update
(
i
,
Integer
.
parseInt
(
line
[
i
]));
}
}
else
if
(
line
[
0
].
equals
(
"up"
))
{
ft
.
update
(
arg1
,
arg2
);
for
(
int
i
=
1
;
i
<=
ft
.
size
();
i
++
)
{
StdOut
.
print
(
ft
.
rsq
(
i
,
i
)
+
" "
);
}
StdOut
.
println
();
}
else
if
(
line
[
0
].
equals
(
"rsq"
))
{
StdOut
.
printf
(
"Sum from %d to %d = %d%n"
,
arg1
,
arg2
,
ft
.
rsq
(
arg1
,
arg2
));
}
else
{
StdOut
.
println
(
"Invalid command"
);
}
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/FFT.java
edu/princeton/cs/algs4/FFT.java
/******************************************************************************
* Compilation: javac FFT.java
* Execution: java FFT n
* Dependencies: Complex.java
*
* Compute the FFT and inverse FFT of a length n complex sequence.
* Bare bones implementation that runs in O(n log n) time. Our goal
* is to optimize the clarity of the code, rather than performance.
*
* Limitations
* -----------
* - assumes n is a power of 2
*
* - not the most memory efficient algorithm (because it uses
* an object type for representing complex numbers and because
* it re-allocates memory for the subarray, instead of doing
* in-place or reusing a single temporary array)
*
*
* % java FFT 4
* x
* -------------------
* -0.03480425839330703
* 0.07910192950176387
* 0.7233322451735928
* 0.1659819820667019
*
* y = fft(x)
* -------------------
* 0.9336118983487516
* -0.7581365035668999 + 0.08688005256493803i
* 0.44344407521182005
* -0.7581365035668999 - 0.08688005256493803i
*
* z = ifft(y)
* -------------------
* -0.03480425839330703
* 0.07910192950176387 + 2.6599344570851287E-18i
* 0.7233322451735928
* 0.1659819820667019 - 2.6599344570851287E-18i
*
* c = cconvolve(x, x)
* -------------------
* 0.5506798633981853
* 0.23461407150576394 - 4.033186818023279E-18i
* -0.016542951108772352
* 0.10288019294318276 + 4.033186818023279E-18i
*
* d = convolve(x, x)
* -------------------
* 0.001211336402308083 - 3.122502256758253E-17i
* -0.005506167987577068 - 5.058885073636224E-17i
* -0.044092969479563274 + 2.1934338938072244E-18i
* 0.10288019294318276 - 3.6147323062478115E-17i
* 0.5494685269958772 + 3.122502256758253E-17i
* 0.240120239493341 + 4.655566391833896E-17i
* 0.02755001837079092 - 2.1934338938072244E-18i
* 4.01805098805014E-17i
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
FFT} class provides methods for computing the
* FFT (Fast-Fourier Transform), inverse FFT, linear convolution,
* and circular convolution of a complex array.
*
* It is a bare-bones implementation that runs in n log n time,
* where n is the length of the complex array. For simplicity,
* n must be a power of 2.
* Our goal is to optimize the clarity of the code, rather than performance.
* It is not the most memory efficient implementation because it uses
* objects to represents complex numbers and it it re-allocates memory
* for the subarray, instead of doing in-place or reusing a single temporary array.
*
*
* For additional documentation, see Section 9.9 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
FFT
{
private
static
final
Complex
ZERO
=
new
Complex
(
0
,
0
);
// Do not instantiate.
private
FFT
()
{
}
/**
* Returns the FFT of the specified complex array.
*
*
@param
x the complex array
*
@return
the FFT of the complex array {
@code
x}
*
@throws
IllegalArgumentException if the length of {
@code
x} is not a power of 2
*/
public
static
Complex
[]
fft
(
Complex
[]
x
)
{
int
n
=
x
.
length
;
// base case
if
(
n
==
1
)
{
return
new
Complex
[]
{
x
[
0
]
};
}
// radix 2 Cooley-Tukey FFT
if
(
n
%
2
!=
0
)
{
throw
new
IllegalArgumentException
(
“n is not a power of 2”
);
}
// fft of even terms
Complex
[]
even
=
new
Complex
[
n
/
2
];
for
(
int
k
=
0
;
k
<
n
/
2
;
k
++
)
{
even
[
k
]
=
x
[
2
*
k
];
}
Complex
[]
q
=
fft
(
even
);
// fft of odd terms
Complex
[]
odd
=
even
;
// reuse the array
for
(
int
k
=
0
;
k
<
n
/
2
;
k
++
)
{
odd
[
k
]
=
x
[
2
*
k
+
1
];
}
Complex
[]
r
=
fft
(
odd
);
// combine
Complex
[]
y
=
new
Complex
[
n
];
for
(
int
k
=
0
;
k
<
n
/
2
;
k
++
)
{
double
kth
=
-
2
*
k
*
Math
.
PI
/
n
;
Complex
wk
=
new
Complex
(
Math
.
cos
(
kth
),
Math
.
sin
(
kth
));
y
[
k
]
=
q
[
k
].
plus
(
wk
.
times
(
r
[
k
]));
y
[
k
+
n
/
2
]
=
q
[
k
].
minus
(
wk
.
times
(
r
[
k
]));
}
return
y
;
}
/**
* Returns the inverse FFT of the specified complex array.
*
*
@param
x the complex array
*
@return
the inverse FFT of the complex array {
@code
x}
*
@throws
IllegalArgumentException if the length of {
@code
x} is not a power of 2
*/
public
static
Complex
[]
ifft
(
Complex
[]
x
)
{
int
n
=
x
.
length
;
Complex
[]
y
=
new
Complex
[
n
];
// take conjugate
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
y
[
i
]
=
x
[
i
].
conjugate
();
}
// compute forward FFT
y
=
fft
(
y
);
// take conjugate again
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
y
[
i
]
=
y
[
i
].
conjugate
();
}
// divide by n
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
y
[
i
]
=
y
[
i
].
scale
(
1.0
/
n
);
}
return
y
;
}
/**
* Returns the circular convolution of the two specified complex arrays.
*
*
@param
x one complex array
*
@param
y the other complex array
*
@return
the circular convolution of {
@code
x} and {
@code
y}
*
@throws
IllegalArgumentException if the length of {
@code
x} does not equal
* the length of {
@code
y} or if the length is not a power of 2
*/
public
static
Complex
[]
cconvolve
(
Complex
[]
x
,
Complex
[]
y
)
{
// should probably pad x and y with 0s so that they have same length
// and are powers of 2
if
(
x
.
length
!=
y
.
length
)
{
throw
new
IllegalArgumentException
(
"Dimensions don't agree"
);
}
int
n
=
x
.
length
;
// compute FFT of each sequence
Complex
[]
a
=
fft
(
x
);
Complex
[]
b
=
fft
(
y
);
// point-wise multiply
Complex
[]
c
=
new
Complex
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
c
[
i
]
=
a
[
i
].
times
(
b
[
i
]);
}
// compute inverse FFT
return
ifft
(
c
);
}
/**
* Returns the linear convolution of the two specified complex arrays.
*
*
@param
x one complex array
*
@param
y the other complex array
*
@return
the linear convolution of {
@code
x} and {
@code
y}
*
@throws
IllegalArgumentException if the length of {
@code
x} does not equal
* the length of {
@code
y} or if the length is not a power of 2
*/
public
static
Complex
[]
convolve
(
Complex
[]
x
,
Complex
[]
y
)
{
Complex
[]
a
=
new
Complex
[
2
*
x
.
length
];
for
(
int
i
=
0
;
i
<
x
.
length
;
i
++
)
a
[
i
]
=
x
[
i
];
for
(
int
i
=
x
.
length
;
i
<
2
*
x
.
length
;
i
++
)
a
[
i
]
=
ZERO
;
Complex
[]
b
=
new
Complex
[
2
*
y
.
length
];
for
(
int
i
=
0
;
i
<
y
.
length
;
i
++
)
b
[
i
]
=
y
[
i
];
for
(
int
i
=
y
.
length
;
i
<
2
*
y
.
length
;
i
++
)
b
[
i
]
=
ZERO
;
return
cconvolve
(
a
,
b
);
}
// display an array of Complex numbers to standard output
private
static
void
show
(
Complex
[]
x
,
String
title
)
{
StdOut
.
println
(
title
);
StdOut
.
println
(
"-------------------"
);
for
(
int
i
=
0
;
i
<
x
.
length
;
i
++
)
{
StdOut
.
println
(
x
[
i
]);
}
StdOut
.
println
();
}
/***************************************************************************
* Test client.
***************************************************************************/
/**
* Unit tests the {
@code
FFT} class.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
n
=
Integer
.
parseInt
(
args
[
0
]);
Complex
[]
x
=
new
Complex
[
n
];
// original data
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
x
[
i
]
=
new
Complex
(
i
,
0
);
x
[
i
]
=
new
Complex
(
StdRandom
.
uniform
(
-
1.0
,
1.0
),
0
);
}
show
(
x
,
"x"
);
// FFT of original data
Complex
[]
y
=
fft
(
x
);
show
(
y
,
"y = fft(x)"
);
// take inverse FFT
Complex
[]
z
=
ifft
(
y
);
show
(
z
,
"z = ifft(y)"
);
// circular convolution of x with itself
Complex
[]
c
=
cconvolve
(
x
,
x
);
show
(
c
,
"c = cconvolve(x, x)"
);
// linear convolution of x with itself
Complex
[]
d
=
convolve
(
x
,
x
);
show
(
d
,
"d = convolve(x, x)"
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/FibonacciMinPQ.java
edu/princeton/cs/algs4/FibonacciMinPQ.java
/******************************************************************************
* Compilation: javac FibonacciMinPQ.java
* Execution:
*
* A Fibonacci heap.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Iterator
;
import
java
.
util
.
HashMap
;
import
java
.
util
.
NoSuchElementException
;
import
java
.
util
.
Comparator
;
/*
* The FibonacciMinPQ class represents a priority queue of generic keys.
* It supports the usual insert and delete-the-minimum operations,
* along with the merging of two heaps together.
* It also supports methods for peeking at the minimum key,
* testing if the priority queue is empty, and iterating through
* the keys.
* It is possible to build the priority queue using a Comparator.
* If not, the natural order relation between the keys will be used.
*
* This implementation uses a Fibonacci heap.
* The delete-the-minimum operation takes amortized logarithmic time.
* The insert, min-key, is-empty, size, union and constructor take constant time.
*
* @author Tristan Claverie
*/
public
class
FibonacciMinPQ
<
Key
>
implements
Iterable
<
Key
>
{
private
Node
head
;
//Head of the circular root list
private
Node
min
;
//Minimum Node of the root list
private
int
size
;
//Number of keys in the heap
private
final
Comparator
<
Key
>
comp
;
//Comparator over the keys
private
HashMap
<
Integer
,
Node
>
table
=
new
HashMap
<
Integer
,
Node
>
();
//Used for the consolidate operation
//Represents a Node of a tree
private
class
Node
{
Key
key
;
//Key of this Node
int
order
;
//Order of the tree rooted by this Node
Node
prev
,
next
;
//Siblings of this Node
Node
child
;
//Child of this Node
}
/**
* Initializes an empty priority queue
* Worst case is O(1)
*
@param
C a Comparator over the Keys
*/
public
FibonacciMinPQ
(
Comparator
<
Key
>
C
)
{
comp
=
C
;
}
/**
* Initializes an empty priority queue
* Worst case is O(1)
*/
public
FibonacciMinPQ
()
{
comp
=
new
MyComparator
();
}
/**
* Initializes a priority queue with given keys
* Worst case is O(n)
*
@param
a an array of keys
*/
public
FibonacciMinPQ
(
Key
[]
a
)
{
comp
=
new
MyComparator
();
for
(
Key
k
:
a
)
insert
(
k
);
}
/**
* Initializes a priority queue with given keys
* Worst case is O(n)
*
@param
C a comparator over the keys
*
@param
a an array of keys
*/
public
FibonacciMinPQ
(
Comparator
<
Key
>
C
,
Key
[]
a
)
{
comp
=
C
;
for
(
Key
k
:
a
)
insert
(
k
);
}
/**
* Whether the priority queue is empty
* Worst case is O(1)
*
@return
true if the priority queue is empty, false if not
*/
public
boolean
isEmpty
()
{
return
size
==
0
;
}
/**
* Number of elements currently on the priority queue
* Worst case is O(1)
*
@return
the number of elements on the priority queue
*/
public
int
size
()
{
return
size
;
}
/**
* Insert a key in the queue
* Worst case is O(1)
*
@param
key a Key
*/
public
void
insert
(
Key
key
)
{
Node
x
=
new
Node
();
x
.
key
=
key
;
size
++
;
head
=
insert
(
x
,
head
);
if
(
min
==
null
)
min
=
head
;
else
min
=
(
greater
(
min
.
key
,
key
))
?
head
:
min
;
}
/**
* Gets the minimum key currently in the queue
* Worst case is O(1)
*
@throws
java.util.NoSuchElementException if the priority queue is empty
*
@return
the minimum key currently in the priority queue
*/
public
Key
minKey
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Priority queue is empty”
);
return
min
.
key
;
}
/**
* Deletes the minimum key
* Worst case is O(log(n)) (amortized)
*
@throws
java.util.NoSuchElementException if the priority queue is empty
*
@return
the minimum key
*/
public
Key
delMin
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Priority queue is empty”
);
head
=
cut
(
min
,
head
);
Node
x
=
min
.
child
;
Key
key
=
min
.
key
;
min
.
key
=
null
;
if
(
x
!=
null
)
{
head
=
meld
(
head
,
x
);
min
.
child
=
null
;
}
size
—
;
if
(
!
isEmpty
())
consolidate
();
else
min
=
null
;
return
key
;
}
/**
* Merges two heaps together
* This operation is destructive
* Worst case is O(1)
*
@param
that a Fibonacci heap
*
@return
the union of the two heaps
*/
public
FibonacciMinPQ
<
Key
>
union
(
FibonacciMinPQ
<
Key
>
that
)
{
this
.
head
=
meld
(
head
,
that
.
head
);
this
.
min
=
(
greater
(
this
.
min
.
key
,
that
.
min
.
key
))
?
that
.
min
:
this
.
min
;
this
.
size
=
this
.
size
+
that
.
size
;
return
this
;
}
/*************************************
* General helper functions
************************************/
//Compares two keys
private
boolean
greater
(
Key
n
,
Key
m
)
{
if
(
n
==
null
)
return
false
;
if
(
m
==
null
)
return
true
;
return
comp
.
compare
(
n
,
m
)
>
0
;
}
//Assuming root1 holds a greater key than root2, root2 becomes the new root
private
void
link
(
Node
root1
,
Node
root2
)
{
root2
.
child
=
insert
(
root1
,
root2
.
child
);
root2
.
order
++
;
}
/*************************************
* Function for consolidating all trees in the root list
************************************/
//Coalesce the roots, thus reshapes the tree
private
void
consolidate
()
{
table
.
clear
();
Node
x
=
head
;
int
maxOrder
=
0
;
min
=
head
;
Node
y
=
null
;
Node
z
=
null
;
do
{
y
=
x
;
x
=
x
.
next
;
z
=
table
.
get
(
y
.
order
);
while
(
z
!=
null
)
{
table
.
remove
(
y
.
order
);
if
(
greater
(
y
.
key
,
z
.
key
))
{
link
(
y
,
z
);
y
=
z
;
}
else
{
link
(
z
,
y
);
}
z
=
table
.
get
(
y
.
order
);
}
table
.
put
(
y
.
order
,
y
);
if
(
y
.
order
>
maxOrder
)
maxOrder
=
y
.
order
;
}
while
(
x
!=
head
);
head
=
null
;
for
(
Node
n
:
table
.
values
())
{
if
(
n
!=
null
)
{
min
=
greater
(
min
.
key
,
n
.
key
)
?
n
:
min
;
head
=
insert
(
n
,
head
);
}
}
}
/*************************************
* General helper functions for manipulating circular lists
************************************/
//Inserts a Node in a circular list containing head, returns a new head
private
Node
insert
(
Node
x
,
Node
head
)
{
if
(
head
==
null
)
{
x
.
prev
=
x
;
x
.
next
=
x
;
}
else
{
head
.
prev
.
next
=
x
;
x
.
next
=
head
;
x
.
prev
=
head
.
prev
;
head
.
prev
=
x
;
}
return
x
;
}
//Removes a tree from the list defined by the head pointer
private
Node
cut
(
Node
x
,
Node
head
)
{
if
(
x
.
next
==
x
)
{
x
.
next
=
null
;
x
.
prev
=
null
;
return
null
;
}
else
{
x
.
next
.
prev
=
x
.
prev
;
x
.
prev
.
next
=
x
.
next
;
Node
res
=
x
.
next
;
x
.
next
=
null
;
x
.
prev
=
null
;
if
(
head
==
x
)
return
res
;
else
return
head
;
}
}
//Merges two root lists together
private
Node
meld
(
Node
x
,
Node
y
)
{
if
(
x
==
null
)
return
y
;
if
(
y
==
null
)
return
x
;
x
.
prev
.
next
=
y
.
next
;
y
.
next
.
prev
=
x
.
prev
;
x
.
prev
=
y
;
y
.
next
=
x
;
return
x
;
}
/*************************************
* Iterator
************************************/
/**
* Gets an Iterator over the Keys in the priority queue in ascending order
* The Iterator does not implement the remove() method
* iterator() : Worst case is O(n)
* next() : Worst case is O(log(n)) (amortized)
* hasNext() : Worst case is O(1)
*
@return
an Iterator over the Keys in the priority queue in ascending order
*/
public
Iterator
<
Key
>
iterator
()
{
return
new
MyIterator
();
}
private
class
MyIterator
implements
Iterator
<
Key
>
{
private
FibonacciMinPQ
<
Key
>
copy
;
//Constructor takes linear time
public
MyIterator
()
{
copy
=
new
FibonacciMinPQ
<
Key
>
(
comp
);
insertAll
(
head
);
}
private
void
insertAll
(
Node
head
)
{
if
(
head
==
null
)
return
;
Node
x
=
head
;
do
{
copy
.
insert
(
x
.
key
);
insertAll
(
x
.
child
);
x
=
x
.
next
;
}
while
(
x
!=
head
);
}
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
public
boolean
hasNext
()
{
return
!
copy
.
isEmpty
();
}
//Takes amortized logarithmic time
public
Key
next
()
{
if
(
!
hasNext
())
throw
new
NoSuchElementException
();
return
copy
.
delMin
();
}
}
/*************************************
* Comparator
************************************/
//default Comparator
private
class
MyComparator
implements
Comparator
<
Key
>
{
@
Override
public
int
compare
(
Key
key1
,
Key
key2
)
{
return
((
Comparable
<
Key
>
)
key1
).
compareTo
(
key2
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/FileIndex.java
edu/princeton/cs/algs4/FileIndex.java
/******************************************************************************
* Compilation: javac FileIndex.java
* Execution: java FileIndex file1.txt file2.txt file3.txt …
* Dependencies: ST.java SET.java In.java StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/35applications/ex1.txt
* https://algs4.cs.princeton.edu/35applications/ex2.txt
* https://algs4.cs.princeton.edu/35applications/ex3.txt
* https://algs4.cs.princeton.edu/35applications/ex4.txt
*
* % java FileIndex ex*.txt
* age
* ex3.txt
* ex4.txt
* best
* ex1.txt
* was
* ex1.txt
* ex2.txt
* ex3.txt
* ex4.txt
*
* % java FileIndex *.txt
*
* % java FileIndex *.java
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
io
.
File
;
/**
* The {
@code
FileIndex} class provides a client for indexing a set of files,
* specified as command-line arguments. It takes queries from standard input
* and prints each file that contains the given query.
*
* For additional documentation, see Section 3.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
FileIndex
{
// Do not instantiate.
private
FileIndex
()
{
}
public
static
void
main
(
String
[]
args
)
{
// key = word, value = set of files containing that word
ST
<
String
,
SET
<
File
>>
st
=
new
ST
<
String
,
SET
<
File
>>
();
// create inverted index of all files
StdOut
.
println
(
“Indexing files”
);
for
(
String
filename
:
args
)
{
StdOut
.
println
(
” ”
+
filename
);
File
file
=
new
File
(
filename
);
In
in
=
new
In
(
file
);
while
(
!
in
.
isEmpty
())
{
String
word
=
in
.
readString
();
if
(
!
st
.
contains
(
word
))
st
.
put
(
word
,
new
SET
<
File
>
());
SET
<
File
>
set
=
st
.
get
(
word
);
set
.
add
(
file
);
}
}
// read queries from standard input, one per line
while
(
!
StdIn
.
isEmpty
())
{
String
query
=
StdIn
.
readString
();
if
(
st
.
contains
(
query
))
{
SET
<
File
>
set
=
st
.
get
(
query
);
for
(
File
file
:
set
)
{
StdOut
.
println
(
” ”
+
file
.
getName
());
}
}
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/FlowEdge.java
edu/princeton/cs/algs4/FlowEdge.java
/******************************************************************************
* Compilation: javac FlowEdge.java
* Execution: java FlowEdge
* Dependencies: StdOut.java
*
* Capacitated edge with a flow in a flow network.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
FlowEdge} class represents a capacitated edge with a
* flow in a {
@link
FlowNetwork}. Each edge consists of two integers
* (naming the two vertices), a real-valued capacity, and a real-valued
* flow. The data type provides methods for accessing the two endpoints
* of the directed edge and the weight. It also provides methods for
* changing the amount of flow on the edge and determining the residual
* capacity of the edge.
*
* For additional documentation, see Section 6.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
FlowEdge
{
// to deal with floating-point roundoff errors
private
static
final
double
FLOATING_POINT_EPSILON
=
1E-10
;
private
final
int
v
;
// from
private
final
int
w
;
// to
private
final
double
capacity
;
// capacity
private
double
flow
;
// flow
/**
* Initializes an edge from vertex {
@code
v} to vertex {
@code
w} with
* the given {
@code
capacity} and zero flow.
*
@param
v the tail vertex
*
@param
w the head vertex
*
@param
capacity the capacity of the edge
*
@throws
IllegalArgumentException if either {
@code
v} or {
@code
w}
* is a negative integer
*
@throws
IllegalArgumentException if {
@code
capacity < 0.0}
*/
public
FlowEdge
(
int
v
,
int
w
,
double
capacity
)
{
if
(
v
<
0
)
throw
new
IllegalArgumentException
(
"vertex index must be a non-negative integer"
);
if
(
w
<
0
)
throw
new
IllegalArgumentException
(
"vertex index must be a non-negative integer"
);
if
(
!
(
capacity
>=
0.0
))
throw
new
IllegalArgumentException
(
“Edge capacity must be non-negative”
);
this
.
v
=
v
;
this
.
w
=
w
;
this
.
capacity
=
capacity
;
this
.
flow
=
0.0
;
}
/**
* Initializes an edge from vertex {
@code
v} to vertex {
@code
w} with
* the given {
@code
capacity} and {
@code
flow}.
*
@param
v the tail vertex
*
@param
w the head vertex
*
@param
capacity the capacity of the edge
*
@param
flow the flow on the edge
*
@throws
IllegalArgumentException if either {
@code
v} or {
@code
w}
* is a negative integer
*
@throws
IllegalArgumentException if {
@code
capacity} is negative
*
@throws
IllegalArgumentException unless {
@code
flow} is between
* {
@code
0.0} and {
@code
capacity}.
*/
public
FlowEdge
(
int
v
,
int
w
,
double
capacity
,
double
flow
)
{
if
(
v
<
0
)
throw
new
IllegalArgumentException
(
"vertex index must be a non-negative integer"
);
if
(
w
<
0
)
throw
new
IllegalArgumentException
(
"vertex index must be a non-negative integer"
);
if
(
!
(
capacity
>=
0.0
))
throw
new
IllegalArgumentException
(
“edge capacity must be non-negative”
);
if
(
!
(
flow
<=
capacity
))
throw
new
IllegalArgumentException
(
"flow exceeds capacity"
);
if
(
!
(
flow
>=
0.0
))
throw
new
IllegalArgumentException
(
“flow must be non-negative”
);
this
.
v
=
v
;
this
.
w
=
w
;
this
.
capacity
=
capacity
;
this
.
flow
=
flow
;
}
/**
* Initializes a flow edge from another flow edge.
*
@param
e the edge to copy
*/
public
FlowEdge
(
FlowEdge
e
)
{
this
.
v
=
e
.
v
;
this
.
w
=
e
.
w
;
this
.
capacity
=
e
.
capacity
;
this
.
flow
=
e
.
flow
;
}
/**
* Returns the tail vertex of the edge.
*
@return
the tail vertex of the edge
*/
public
int
from
()
{
return
v
;
}
/**
* Returns the head vertex of the edge.
*
@return
the head vertex of the edge
*/
public
int
to
()
{
return
w
;
}
/**
* Returns the capacity of the edge.
*
@return
the capacity of the edge
*/
public
double
capacity
()
{
return
capacity
;
}
/**
* Returns the flow on the edge.
*
@return
the flow on the edge
*/
public
double
flow
()
{
return
flow
;
}
/**
* Returns the endpoint of the edge that is different from the given vertex
* (unless the edge represents a self-loop in which case it returns the same vertex).
*
@param
vertex one endpoint of the edge
*
@return
the endpoint of the edge that is different from the given vertex
* (unless the edge represents a self-loop in which case it returns the same vertex)
*
@throws
IllegalArgumentException if {
@code
vertex} is not one of the endpoints
* of the edge
*/
public
int
other
(
int
vertex
)
{
if
(
vertex
==
v
)
return
w
;
else
if
(
vertex
==
w
)
return
v
;
else
throw
new
IllegalArgumentException
(
“invalid endpoint”
);
}
/**
* Returns the residual capacity of the edge in the direction
* to the given {
@code
vertex}.
*
@param
vertex one endpoint of the edge
*
@return
the residual capacity of the edge in the direction to the given vertex
* If {
@code
vertex} is the tail vertex, the residual capacity equals
* {
@code
capacity() – flow()}; if {
@code
vertex} is the head vertex, the
* residual capacity equals {
@code
flow()}.
*
@throws
IllegalArgumentException if {
@code
vertex} is not one of the endpoints of the edge
*/
public
double
residualCapacityTo
(
int
vertex
)
{
if
(
vertex
==
v
)
return
flow
;
// backward edge
else
if
(
vertex
==
w
)
return
capacity
–
flow
;
// forward edge
else
throw
new
IllegalArgumentException
(
“invalid endpoint”
);
}
/**
* Increases the flow on the edge in the direction to the given vertex.
* If {
@code
vertex} is the tail vertex, this increases the flow on the edge by {
@code
delta};
* if {
@code
vertex} is the head vertex, this decreases the flow on the edge by {
@code
delta}.
*
@param
vertex one endpoint of the edge
*
@param
delta amount by which to increase flow
*
@throws
IllegalArgumentException if {
@code
vertex} is not one of the endpoints
* of the edge
*
@throws
IllegalArgumentException if {
@code
delta} makes the flow on
* on the edge either negative or larger than its capacity
*
@throws
IllegalArgumentException if {
@code
delta} is {
@code
NaN}
*/
public
void
addResidualFlowTo
(
int
vertex
,
double
delta
)
{
if
(
!
(
delta
>=
0.0
))
throw
new
IllegalArgumentException
(
“Delta must be nonnegative”
);
if
(
vertex
==
v
)
flow
-=
delta
;
// backward edge
else
if
(
vertex
==
w
)
flow
+=
delta
;
// forward edge
else
throw
new
IllegalArgumentException
(
“invalid endpoint”
);
// round flow to 0 or capacity if within floating-point precision
if
(
Math
.
abs
(
flow
)
<=
FLOATING_POINT_EPSILON
)
flow
=
0
;
if
(
Math
.
abs
(
flow
-
capacity
)
<=
FLOATING_POINT_EPSILON
)
flow
=
capacity
;
if
(
!
(
flow
>=
0.0
))
throw
new
IllegalArgumentException
(
“Flow is negative”
);
if
(
!
(
flow
<=
capacity
))
throw
new
IllegalArgumentException
(
"Flow exceeds capacity"
);
}
/**
* Returns a string representation of the edge.
*
@return
a string representation of the edge
*/
public
String
toString
()
{
return
v
+
"->”
+
w
+
” ”
+
flow
+
“/”
+
capacity
;
}
/**
* Unit tests the {
@code
FlowEdge} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
FlowEdge
e
=
new
FlowEdge
(
12
,
23
,
4.56
);
StdOut
.
println
(
e
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/FlowNetwork.java
edu/princeton/cs/algs4/FlowNetwork.java
/******************************************************************************
* Compilation: javac FlowNetwork.java
* Execution: java FlowNetwork V E
* Dependencies: Bag.java FlowEdge.java
*
* A capacitated flow network, implemented using adjacency lists.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
FlowNetwork} class represents a capacitated network
* with vertices named 0 through V – 1, where each directed
* edge is of type {
@link
FlowEdge} and has a real-valued capacity
* and flow.
* It supports the following two primary operations: add an edge to the network,
* iterate over all of the edges incident to or from a vertex. It also provides
* methods for returning the number of vertices V and the number
* of edges E. Parallel edges and self-loops are permitted.
*
* This implementation uses an adjacency-lists representation, which
* is a vertex-indexed array of {
@link
Bag} objects.
* All operations take constant time (in the worst case) except
* iterating over the edges incident to a given vertex, which takes
* time proportional to the number of such edges.
*
* For additional documentation,
* see Section 6.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
FlowNetwork
{
private
static
final
String
NEWLINE
=
System
.
getProperty
(
“line.separator”
);
private
final
int
V
;
private
int
E
;
private
Bag
<
FlowEdge
>
[]
adj
;
/**
* Initializes an empty flow network with {
@code
V} vertices and 0 edges.
*
@param
V the number of vertices
*
@throws
IllegalArgumentException if {
@code
V < 0}
*/
public
FlowNetwork
(
int
V
)
{
if
(
V
<
0
)
throw
new
IllegalArgumentException
(
"Number of vertices in a Graph must be nonnegative"
);
this
.
V
=
V
;
this
.
E
=
0
;
adj
=
(
Bag
<
FlowEdge
>
[])
new
Bag
[
V
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
adj
[
v
]
=
new
Bag
<
FlowEdge
>
();
}
/**
* Initializes a random flow network with {
@code
V} vertices and E edges.
* The capacities are integers between 0 and 99 and the flow values are zero.
*
@param
V the number of vertices
*
@param
E the number of edges
*
@throws
IllegalArgumentException if {
@code
V < 0}
*
@throws
IllegalArgumentException if {
@code
E < 0}
*/
public
FlowNetwork
(
int
V
,
int
E
)
{
this
(
V
);
if
(
E
<
0
)
throw
new
IllegalArgumentException
(
"Number of edges must be nonnegative"
);
for
(
int
i
=
0
;
i
<
E
;
i
++
)
{
int
v
=
StdRandom
.
uniform
(
V
);
int
w
=
StdRandom
.
uniform
(
V
);
double
capacity
=
StdRandom
.
uniform
(
100
);
addEdge
(
new
FlowEdge
(
v
,
w
,
capacity
));
}
}
/**
* Initializes a flow network from an input stream.
* The format is the number of vertices V,
* followed by the number of edges E,
* followed by E pairs of vertices and edge capacities,
* with each entry separated by whitespace.
*
@param
in the input stream
*
@throws
IllegalArgumentException if the endpoints of any edge are not in prescribed range
*
@throws
IllegalArgumentException if the number of vertices or edges is negative
*/
public
FlowNetwork
(
In
in
)
{
this
(
in
.
readInt
());
int
E
=
in
.
readInt
();
if
(
E
<
0
)
throw
new
IllegalArgumentException
(
"number of edges must be nonnegative"
);
for
(
int
i
=
0
;
i
<
E
;
i
++
)
{
int
v
=
in
.
readInt
();
int
w
=
in
.
readInt
();
validateVertex
(
v
);
validateVertex
(
w
);
double
capacity
=
in
.
readDouble
();
addEdge
(
new
FlowEdge
(
v
,
w
,
capacity
));
}
}
/**
* Returns the number of vertices in the edge-weighted graph.
*
@return
the number of vertices in the edge-weighted graph
*/
public
int
V
()
{
return
V
;
}
/**
* Returns the number of edges in the edge-weighted graph.
*
@return
the number of edges in the edge-weighted graph
*/
public
int
E
()
{
return
E
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Adds the edge {
@code
e} to the network.
*
@param
e the edge
*
@throws
IllegalArgumentException unless endpoints of edge are between
* {
@code
0} and {
@code
V-1}
*/
public
void
addEdge
(
FlowEdge
e
)
{
int
v
=
e
.
from
();
int
w
=
e
.
to
();
validateVertex
(
v
);
validateVertex
(
w
);
adj
[
v
].
add
(
e
);
adj
[
w
].
add
(
e
);
E
++
;
}
/**
* Returns the edges incident on vertex {
@code
v} (includes both edges pointing to
* and from {
@code
v}).
*
@param
v the vertex
*
@return
the edges incident on vertex {
@code
v} as an Iterable
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
Iterable
<
FlowEdge
>
adj
(
int
v
)
{
validateVertex
(
v
);
return
adj
[
v
];
}
// return list of all edges – excludes self loops
public
Iterable
<
FlowEdge
>
edges
()
{
Bag
<
FlowEdge
>
list
=
new
Bag
<
FlowEdge
>
();
for
(
int
v
=
0
;
v
<
V
;
v
++
)
for
(
FlowEdge
e
:
adj
(
v
))
{
if
(
e
.
to
()
!=
v
)
list
.
add
(
e
);
}
return
list
;
}
/**
* Returns a string representation of the flow network.
* This method takes time proportional to E + V.
*
@return
the number of vertices V, followed by the number of edges E,
* followed by the V adjacency lists
*/
public
String
toString
()
{
StringBuilder
s
=
new
StringBuilder
();
s
.
append
(
V
+
” ”
+
E
+
NEWLINE
);
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
s
.
append
(
v
+
": "
);
for
(
FlowEdge
e
:
adj
[
v
])
{
if
(
e
.
to
()
!=
v
)
s
.
append
(
e
+
" "
);
}
s
.
append
(
NEWLINE
);
}
return
s
.
toString
();
}
/**
* Unit tests the {
@code
FlowNetwork} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
FlowNetwork
G
=
new
FlowNetwork
(
in
);
StdOut
.
println
(
G
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/FloydWarshall.java
edu/princeton/cs/algs4/FloydWarshall.java
/******************************************************************************
* Compilation: javac FloydWarshall.java
* Execution: java FloydWarshall V E
* Dependencies: AdjMatrixEdgeWeightedDigraph.java
*
* Floyd-Warshall all-pairs shortest path algorithm.
*
* % java FloydWarshall 100 500
*
* Should check for negative cycles during triple loop; otherwise
* intermediate numbers can get exponentially large.
* Reference: "The Floyd-Warshall algorithm on graphs with negative cycles"
* by Stefan Hougardy
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
FloydWarshall} class represents a data type for solving the
* all-pairs shortest paths problem in edge-weighted digraphs with
* no negative cycles.
* The edge weights can be positive, negative, or zero.
* This class finds either a shortest path between every pair of vertices
* or a negative cycle.
*
* This implementation uses the Floyd-Warshall algorithm.
* The constructor takes Θ(V3) time,
* where V is the number of vertices.
* Each instance method takes Θ(1) time.
* It uses Θ(V2) extra space
* (not including the edge-weighted digraph).
*
* For additional documentation,
* see Section 4.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
FloydWarshall
{
private
boolean
hasNegativeCycle
;
// is there a negative cycle?
private
double
[][]
distTo
;
// distTo[v][w] = length of shortest v->w path
private
DirectedEdge
[][]
edgeTo
;
// edgeTo[v][w] = last edge on shortest v->w path
/**
* Computes a shortest paths tree from each vertex to to every other vertex in
* the edge-weighted digraph {
@code
G}. If no such shortest path exists for
* some pair of vertices, it computes a negative cycle.
*
@param
G the edge-weighted digraph
*/
public
FloydWarshall
(
AdjMatrixEdgeWeightedDigraph
G
)
{
int
V
=
G
.
V
();
distTo
=
new
double
[
V
][
V
];
edgeTo
=
new
DirectedEdge
[
V
][
V
];
// initialize distances to infinity
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
for
(
int
w
=
0
;
w
<
V
;
w
++
)
{
distTo
[
v
][
w
]
=
Double
.
POSITIVE_INFINITY
;
}
}
// initialize distances using edge-weighted digraph's
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
for
(
DirectedEdge
e
:
G
.
adj
(
v
))
{
distTo
[
e
.
from
()][
e
.
to
()]
=
e
.
weight
();
edgeTo
[
e
.
from
()][
e
.
to
()]
=
e
;
}
// in case of self-loops
if
(
distTo
[
v
][
v
]
>=
0.0
)
{
distTo
[
v
][
v
]
=
0.0
;
edgeTo
[
v
][
v
]
=
null
;
}
}
// Floyd-Warshall updates
for
(
int
i
=
0
;
i
<
V
;
i
++
)
{
// compute shortest paths using only 0, 1, ..., i as intermediate vertices
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
if
(
edgeTo
[
v
][
i
]
==
null
)
continue
;
// optimization
for
(
int
w
=
0
;
w
<
V
;
w
++
)
{
if
(
distTo
[
v
][
w
]
>
distTo
[
v
][
i
]
+
distTo
[
i
][
w
])
{
distTo
[
v
][
w
]
=
distTo
[
v
][
i
]
+
distTo
[
i
][
w
];
edgeTo
[
v
][
w
]
=
edgeTo
[
i
][
w
];
}
}
// check for negative cycle
if
(
distTo
[
v
][
v
]
<
0.0
)
{
hasNegativeCycle
=
true
;
return
;
}
}
}
assert
check
(
G
);
}
/**
* Is there a negative cycle?
*
@return
{
@code
true} if there is a negative cycle, and {
@code
false} otherwise
*/
public
boolean
hasNegativeCycle
()
{
return
hasNegativeCycle
;
}
/**
* Returns a negative cycle, or {
@code
null} if there is no such cycle.
*
@return
a negative cycle as an iterable of edges,
* or {
@code
null} if there is no such cycle
*/
public
Iterable
<
DirectedEdge
>
negativeCycle
()
{
for
(
int
v
=
0
;
v
<
distTo
.
length
;
v
++
)
{
// negative cycle in v's predecessor graph
if
(
distTo
[
v
][
v
]
<
0.0
)
{
int
V
=
edgeTo
.
length
;
EdgeWeightedDigraph
spt
=
new
EdgeWeightedDigraph
(
V
);
for
(
int
w
=
0
;
w
<
V
;
w
++
)
if
(
edgeTo
[
v
][
w
]
!=
null
)
spt
.
addEdge
(
edgeTo
[
v
][
w
]);
EdgeWeightedDirectedCycle
finder
=
new
EdgeWeightedDirectedCycle
(
spt
);
assert
finder
.
hasCycle
();
return
finder
.
cycle
();
}
}
return
null
;
}
/**
* Is there a path from the vertex {
@code
s} to vertex {
@code
t}?
*
@param
s the source vertex
*
@param
t the destination vertex
*
@return
{
@code
true} if there is a path from vertex {
@code
s}
* to vertex {
@code
t}, and {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= s < V}
*
@throws
IllegalArgumentException unless {
@code
0 <= t < V}
*/
public
boolean
hasPath
(
int
s
,
int
t
)
{
validateVertex
(
s
);
validateVertex
(
t
);
return
distTo
[
s
][
t
]
<
Double
.
POSITIVE_INFINITY
;
}
/**
* Returns the length of a shortest path from vertex {
@code
s} to vertex {
@code
t}.
*
@param
s the source vertex
*
@param
t the destination vertex
*
@return
the length of a shortest path from vertex {
@code
s} to vertex {
@code
t};
* {
@code
Double.POSITIVE_INFINITY} if no such path
*
@throws
UnsupportedOperationException if there is a negative cost cycle
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
double
dist
(
int
s
,
int
t
)
{
validateVertex
(
s
);
validateVertex
(
t
);
if
(
hasNegativeCycle
())
throw
new
UnsupportedOperationException
(
"Negative cost cycle exists"
);
return
distTo
[
s
][
t
];
}
/**
* Returns a shortest path from vertex {
@code
s} to vertex {
@code
t}.
*
@param
s the source vertex
*
@param
t the destination vertex
*
@return
a shortest path from vertex {
@code
s} to vertex {
@code
t}
* as an iterable of edges, and {
@code
null} if no such path
*
@throws
UnsupportedOperationException if there is a negative cost cycle
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
Iterable
<
DirectedEdge
>
path
(
int
s
,
int
t
)
{
validateVertex
(
s
);
validateVertex
(
t
);
if
(
hasNegativeCycle
())
throw
new
UnsupportedOperationException
(
“Negative cost cycle exists”
);
if
(
!
hasPath
(
s
,
t
))
return
null
;
Stack
<
DirectedEdge
>
path
=
new
Stack
<
DirectedEdge
>
();
for
(
DirectedEdge
e
=
edgeTo
[
s
][
t
];
e
!=
null
;
e
=
edgeTo
[
s
][
e
.
from
()])
{
path
.
push
(
e
);
}
return
path
;
}
// check optimality conditions
private
boolean
check
(
AdjMatrixEdgeWeightedDigraph
G
)
{
// no negative cycle
if
(
!
hasNegativeCycle
())
{
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
for
(
DirectedEdge
e
:
G
.
adj
(
v
))
{
int
w
=
e
.
to
();
for
(
int
i
=
0
;
i
<
G
.
V
();
i
++
)
{
if
(
distTo
[
i
][
w
]
>
distTo
[
i
][
v
]
+
e
.
weight
())
{
System
.
err
.
println
(
“edge ”
+
e
+
” is eligible”
);
return
false
;
}
}
}
}
}
return
true
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
distTo
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
FloydWarshall} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// random graph with V vertices and E edges, parallel edges allowed
int
V
=
Integer
.
parseInt
(
args
[
0
]);
int
E
=
Integer
.
parseInt
(
args
[
1
]);
AdjMatrixEdgeWeightedDigraph
G
=
new
AdjMatrixEdgeWeightedDigraph
(
V
);
for
(
int
i
=
0
;
i
<
E
;
i
++
)
{
int
v
=
StdRandom
.
uniform
(
V
);
int
w
=
StdRandom
.
uniform
(
V
);
double
weight
=
Math
.
round
(
100
*
(
StdRandom
.
uniform
()
-
0.15
))
/
100.0
;
if
(
v
==
w
)
G
.
addEdge
(
new
DirectedEdge
(
v
,
w
,
Math
.
abs
(
weight
)));
else
G
.
addEdge
(
new
DirectedEdge
(
v
,
w
,
weight
));
}
StdOut
.
println
(
G
);
// run Floyd-Warshall algorithm
FloydWarshall
spt
=
new
FloydWarshall
(
G
);
// print all-pairs shortest path distances
StdOut
.
printf
(
" "
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
StdOut
.
printf
(
"%6d "
,
v
);
}
StdOut
.
println
();
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
StdOut
.
printf
(
"%3d: "
,
v
);
for
(
int
w
=
0
;
w
<
G
.
V
();
w
++
)
{
if
(
spt
.
hasPath
(
v
,
w
))
StdOut
.
printf
(
"%6.2f "
,
spt
.
dist
(
v
,
w
));
else
StdOut
.
printf
(
" Inf "
);
}
StdOut
.
println
();
}
// print negative cycle
if
(
spt
.
hasNegativeCycle
())
{
StdOut
.
println
(
"Negative cost cycle:"
);
for
(
DirectedEdge
e
:
spt
.
negativeCycle
())
StdOut
.
println
(
e
);
StdOut
.
println
();
}
// print all-pairs shortest paths
else
{
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
for
(
int
w
=
0
;
w
<
G
.
V
();
w
++
)
{
if
(
spt
.
hasPath
(
v
,
w
))
{
StdOut
.
printf
(
"%d to %d (%5.2f) "
,
v
,
w
,
spt
.
dist
(
v
,
w
));
for
(
DirectedEdge
e
:
spt
.
path
(
v
,
w
))
StdOut
.
print
(
e
+
" "
);
StdOut
.
println
();
}
else
{
StdOut
.
printf
(
"%d to %d no path\n"
,
v
,
w
);
}
}
}
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/FordFulkerson.java
edu/princeton/cs/algs4/FordFulkerson.java
/******************************************************************************
* Compilation: javac FordFulkerson.java
* Execution: java FordFulkerson V E
* Dependencies: FlowNetwork.java FlowEdge.java Queue.java
* Data files: https://algs4.cs.princeton.edu/65maxflow/tinyFN.txt
*
* Ford-Fulkerson algorithm for computing a max flow and
* a min cut using shortest augmenting path rule.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
FordFulkerson} class represents a data type for computing a
* maximum st-flow and minimum st-cut in a flow
* network.
*
* This implementation uses the Ford-Fulkerson algorithm with
* the shortest augmenting path heuristic.
* The constructor takes O(E V (E + V))
* time, where V is the number of vertices and E is
* the number of edges. In practice, the algorithm will run much faster.
* The {
@code
inCut()} and {
@code
value()} methods take Θ(1) time.
* It uses Θ(V) extra space (not including the network).
*
* If the capacities and initial flow values are all integers, then this
* implementation guarantees to compute an integer-valued maximum flow.
* If the capacities are floating-point numbers, then floating-point
* roundoff error can accumulate.
*
* For additional documentation, see
* Section 6.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
FordFulkerson
{
private
static
final
double
FLOATING_POINT_EPSILON
=
1E-11
;
private
final
int
V
;
// number of vertices
private
boolean
[]
marked
;
// marked[v] = true iff s->v path in residual graph
private
FlowEdge
[]
edgeTo
;
// edgeTo[v] = last edge on shortest residual s->v path
private
double
value
;
// current value of max flow
/**
* Compute a maximum flow and minimum cut in the network {
@code
G}
* from vertex {
@code
s} to vertex {
@code
t}.
*
*
@param
G the flow network
*
@param
s the source vertex
*
@param
t the sink vertex
*
@throws
IllegalArgumentException unless {
@code
0 <= s < V}
*
@throws
IllegalArgumentException unless {
@code
0 <= t < V}
*
@throws
IllegalArgumentException if {
@code
s == t}
*
@throws
IllegalArgumentException if initial flow is infeasible
*/
public
FordFulkerson
(
FlowNetwork
G
,
int
s
,
int
t
)
{
V
=
G
.
V
();
validate
(
s
);
validate
(
t
);
if
(
s
==
t
)
throw
new
IllegalArgumentException
(
"Source equals sink"
);
if
(
!
isFeasible
(
G
,
s
,
t
))
throw
new
IllegalArgumentException
(
"Initial flow is infeasible"
);
// while there exists an augmenting path, use it
value
=
excess
(
G
,
t
);
while
(
hasAugmentingPath
(
G
,
s
,
t
))
{
// compute bottleneck capacity
double
bottle
=
Double
.
POSITIVE_INFINITY
;
for
(
int
v
=
t
;
v
!=
s
;
v
=
edgeTo
[
v
].
other
(
v
))
{
bottle
=
Math
.
min
(
bottle
,
edgeTo
[
v
].
residualCapacityTo
(
v
));
}
// augment flow
for
(
int
v
=
t
;
v
!=
s
;
v
=
edgeTo
[
v
].
other
(
v
))
{
edgeTo
[
v
].
addResidualFlowTo
(
v
,
bottle
);
}
value
+=
bottle
;
}
// check optimality conditions
assert
check
(
G
,
s
,
t
);
}
/**
* Returns the value of the maximum flow.
*
*
@return
the value of the maximum flow
*/
public
double
value
()
{
return
value
;
}
/**
* Returns true if the specified vertex is on the {
@code
s} side of the mincut.
*
*
@param
v vertex
*
@return
{
@code
true} if vertex {
@code
v} is on the {
@code
s} side of the micut;
* {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
boolean
inCut
(
int
v
)
{
validate
(
v
);
return
marked
[
v
];
}
// throw an IllegalArgumentException if v is outside prescibed range
private
void
validate
(
int
v
)
{
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
// is there an augmenting path?
// if so, upon termination edgeTo[] will contain a parent-link representation of such a path
// this implementation finds a shortest augmenting path (fewest number of edges),
// which performs well both in theory and in practice
private
boolean
hasAugmentingPath
(
FlowNetwork
G
,
int
s
,
int
t
)
{
edgeTo
=
new
FlowEdge
[
G
.
V
()];
marked
=
new
boolean
[
G
.
V
()];
// breadth-first search
Queue
<
Integer
>
queue
=
new
Queue
<
Integer
>
();
queue
.
enqueue
(
s
);
marked
[
s
]
=
true
;
while
(
!
queue
.
isEmpty
()
&&
!
marked
[
t
])
{
int
v
=
queue
.
dequeue
();
for
(
FlowEdge
e
:
G
.
adj
(
v
))
{
int
w
=
e
.
other
(
v
);
// if residual capacity from v to w
if
(
e
.
residualCapacityTo
(
w
)
>
0
)
{
if
(
!
marked
[
w
])
{
edgeTo
[
w
]
=
e
;
marked
[
w
]
=
true
;
queue
.
enqueue
(
w
);
}
}
}
}
// is there an augmenting path?
return
marked
[
t
];
}
// return excess flow at vertex v
private
double
excess
(
FlowNetwork
G
,
int
v
)
{
double
excess
=
0.0
;
for
(
FlowEdge
e
:
G
.
adj
(
v
))
{
if
(
v
==
e
.
from
())
excess
-=
e
.
flow
();
else
excess
+=
e
.
flow
();
}
return
excess
;
}
// return excess flow at vertex v
private
boolean
isFeasible
(
FlowNetwork
G
,
int
s
,
int
t
)
{
// check that capacity constraints are satisfied
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
for
(
FlowEdge
e
:
G
.
adj
(
v
))
{
if
(
e
.
flow
()
<
-
FLOATING_POINT_EPSILON
||
e
.
flow
()
>
e
.
capacity
()
+
FLOATING_POINT_EPSILON
)
{
System
.
err
.
println
(
“Edge does not satisfy capacity constraints: ”
+
e
);
return
false
;
}
}
}
// check that net flow into a vertex equals zero, except at source and sink
if
(
Math
.
abs
(
value
+
excess
(
G
,
s
))
>
FLOATING_POINT_EPSILON
)
{
System
.
err
.
println
(
“Excess at source = ”
+
excess
(
G
,
s
));
System
.
err
.
println
(
“Max flow = ”
+
value
);
return
false
;
}
if
(
Math
.
abs
(
value
–
excess
(
G
,
t
))
>
FLOATING_POINT_EPSILON
)
{
System
.
err
.
println
(
“Excess at sink = ”
+
excess
(
G
,
t
));
System
.
err
.
println
(
“Max flow = ”
+
value
);
return
false
;
}
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
v
==
s
||
v
==
t
)
continue
;
else
if
(
Math
.
abs
(
excess
(
G
,
v
))
>
FLOATING_POINT_EPSILON
)
{
System
.
err
.
println
(
“Net flow out of ”
+
v
+
” doesn’t equal zero”
);
return
false
;
}
}
return
true
;
}
// check optimality conditions
private
boolean
check
(
FlowNetwork
G
,
int
s
,
int
t
)
{
// check that flow is feasible
if
(
!
isFeasible
(
G
,
s
,
t
))
{
System
.
err
.
println
(
“Flow is infeasible”
);
return
false
;
}
// check that s is on the source side of min cut and that t is not on source side
if
(
!
inCut
(
s
))
{
System
.
err
.
println
(
“source ”
+
s
+
” is not on source side of min cut”
);
return
false
;
}
if
(
inCut
(
t
))
{
System
.
err
.
println
(
“sink ”
+
t
+
” is on source side of min cut”
);
return
false
;
}
// check that value of min cut = value of max flow
double
mincutValue
=
0.0
;
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
for
(
FlowEdge
e
:
G
.
adj
(
v
))
{
if
((
v
==
e
.
from
())
&&
inCut
(
e
.
from
())
&&
!
inCut
(
e
.
to
()))
mincutValue
+=
e
.
capacity
();
}
}
if
(
Math
.
abs
(
mincutValue
-
value
)
>
FLOATING_POINT_EPSILON
)
{
System
.
err
.
println
(
“Max flow value = ”
+
value
+
“, min cut value = ”
+
mincutValue
);
return
false
;
}
return
true
;
}
/**
* Unit tests the {
@code
FordFulkerson} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// create flow network with V vertices and E edges
int
V
=
Integer
.
parseInt
(
args
[
0
]);
int
E
=
Integer
.
parseInt
(
args
[
1
]);
int
s
=
0
,
t
=
V
–
1
;
FlowNetwork
G
=
new
FlowNetwork
(
V
,
E
);
StdOut
.
println
(
G
);
// compute maximum flow and minimum cut
FordFulkerson
maxflow
=
new
FordFulkerson
(
G
,
s
,
t
);
StdOut
.
println
(
“Max flow from ”
+
s
+
” to ”
+
t
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
for
(
FlowEdge
e
:
G
.
adj
(
v
))
{
if
((
v
==
e
.
from
())
&&
e
.
flow
()
>
0
)
StdOut
.
println
(
” ”
+
e
);
}
}
// print min-cut
StdOut
.
print
(
“Min cut: ”
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
maxflow
.
inCut
(
v
))
StdOut
.
print
(
v
+
" "
);
}
StdOut
.
println
();
StdOut
.
println
(
"Max flow value = "
+
maxflow
.
value
());
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/FrequencyCounter.java
edu/princeton/cs/algs4/FrequencyCounter.java
/******************************************************************************
* Compilation: javac FrequencyCounter.java
* Execution: java FrequencyCounter L < input.txt
* Dependencies: ST.java StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/31elementary/tinyTale.txt
* https://algs4.cs.princeton.edu/31elementary/tale.txt
* https://algs4.cs.princeton.edu/31elementary/leipzig100K.txt
* https://algs4.cs.princeton.edu/31elementary/leipzig300K.txt
* https://algs4.cs.princeton.edu/31elementary/leipzig1M.txt
*
* Read in a list of words from standard input and print out
* the most frequently occurring word that has length greater than
* a given threshold.
*
* % java FrequencyCounter 1 < tinyTale.txt
* it 10
*
* % java FrequencyCounter 8 < tale.txt
* business 122
*
* % java FrequencyCounter 10 < leipzig1M.txt
* government 24763
*
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
FrequencyCounter} class provides a client for
* reading in a sequence of words and printing a word (exceeding
* a given length) that occurs most frequently. It is useful as
* a test client for various symbol table implementations.
*
* For additional documentation, see Section 3.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
FrequencyCounter
{
// Do not instantiate.
private
FrequencyCounter
()
{
}
/**
* Reads in a command-line integer and sequence of words from
* standard input and prints out a word (whose length exceeds
* the threshold) that occurs most frequently to standard output.
* It also prints out the number of words whose length exceeds
* the threshold and the number of distinct such words.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
distinct
=
0
,
words
=
0
;
int
minlen
=
Integer
.
parseInt
(
args
[
0
]);
ST
<
String
,
Integer
>
st
=
new
ST
<
String
,
Integer
>
();
// compute frequency counts
while
(
!
StdIn
.
isEmpty
())
{
String
key
=
StdIn
.
readString
();
if
(
key
.
length
()
<
minlen
)
continue
;
words
++
;
if
(
st
.
contains
(
key
))
{
st
.
put
(
key
,
st
.
get
(
key
)
+
1
);
}
else
{
st
.
put
(
key
,
1
);
distinct
++
;
}
}
// find a key with the highest frequency count
String
max
=
""
;
st
.
put
(
max
,
0
);
for
(
String
word
:
st
.
keys
())
{
if
(
st
.
get
(
word
)
>
st
.
get
(
max
))
max
=
word
;
}
StdOut
.
println
(
max
+
” ”
+
st
.
get
(
max
));
StdOut
.
println
(
“distinct = ”
+
distinct
);
StdOut
.
println
(
“words = ”
+
words
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/GabowSCC.java
edu/princeton/cs/algs4/GabowSCC.java
/******************************************************************************
* Compilation: javac GabowSCC.java
* Execution: java GabowSCC V E
* Dependencies: Digraph.java Stack.java TransitiveClosure.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/42digraph/tinyDG.txt
* https://algs4.cs.princeton.edu/42digraph/mediumDG.txt
* https://algs4.cs.princeton.edu/42digraph/largeDG.txt
*
* Compute the strongly-connected components of a digraph using
* Gabow’s algorithm (aka Cheriyan-Mehlhorn algorithm).
*
* Runs in O(E + V) time.
*
* % java GabowSCC tinyDG.txt
* 5 components
* 1
* 0 2 3 4 5
* 9 10 11 12
* 6 8
* 7
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
GabowSCC} class represents a data type for
* determining the strong components in a digraph.
* The id operation determines in which strong component
* a given vertex lies; the areStronglyConnected operation
* determines whether two vertices are in the same strong component;
* and the count operation determines the number of strong
* components.
* The component identifier of a component is one of the
* vertices in the strong component: two vertices have the same component
* identifier if and only if they are in the same strong component.
*
* This implementation uses the Gabow’s algorithm.
* The constructor takes Θ(V + E) time,
* where V is the number of vertices and E is
* the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the digraph).
* For alternative implementations of the same API, see
* {
@link
KosarajuSharirSCC} and {
@link
TarjanSCC}.
*
* For additional documentation,
* see Section 4.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
GabowSCC
{
private
boolean
[]
marked
;
// marked[v] = has v been visited?
private
int
[]
id
;
// id[v] = id of strong component containing v
private
int
[]
preorder
;
// preorder[v] = preorder of v
private
int
pre
;
// preorder number counter
private
int
count
;
// number of strongly-connected components
private
Stack
<
Integer
>
stack1
;
private
Stack
<
Integer
>
stack2
;
/**
* Computes the strong components of the digraph {
@code
G}.
*
@param
G the digraph
*/
public
GabowSCC
(
Digraph
G
)
{
marked
=
new
boolean
[
G
.
V
()];
stack1
=
new
Stack
<
Integer
>
();
stack2
=
new
Stack
<
Integer
>
();
id
=
new
int
[
G
.
V
()];
preorder
=
new
int
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
id
[
v
]
=
-
1
;
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
!
marked
[
v
])
dfs
(
G
,
v
);
}
// check that id[] gives strong components
assert
check
(
G
);
}
private
void
dfs
(
Digraph
G
,
int
v
)
{
marked
[
v
]
=
true
;
preorder
[
v
]
=
pre
++
;
stack1
.
push
(
v
);
stack2
.
push
(
v
);
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
!
marked
[
w
])
dfs
(
G
,
w
);
else
if
(
id
[
w
]
==
-
1
)
{
while
(
preorder
[
stack2
.
peek
()]
>
preorder
[
w
])
stack2
.
pop
();
}
}
// found strong component containing v
if
(
stack2
.
peek
()
==
v
)
{
stack2
.
pop
();
int
w
;
do
{
w
=
stack1
.
pop
();
id
[
w
]
=
count
;
}
while
(
w
!=
v
);
count
++
;
}
}
/**
* Returns the number of strong components.
*
@return
the number of strong components
*/
public
int
count
()
{
return
count
;
}
/**
* Are vertices {
@code
v} and {
@code
w} in the same strong component?
*
@param
v one vertex
*
@param
w the other vertex
*
@return
{
@code
true} if vertices {
@code
v} and {
@code
w} are in the same
* strong component, and {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*
@throws
IllegalArgumentException unless {
@code
0 <= w < V}
*/
public
boolean
stronglyConnected
(
int
v
,
int
w
)
{
validateVertex
(
v
);
validateVertex
(
w
);
return
id
[
v
]
==
id
[
w
];
}
/**
* Returns the component id of the strong component containing vertex {
@code
v}.
*
@param
v the vertex
*
@return
the component id of the strong component containing vertex {
@code
v}
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
int
id
(
int
v
)
{
validateVertex
(
v
);
return
id
[
v
];
}
// does the id[] array contain the strongly connected components?
private
boolean
check
(
Digraph
G
)
{
TransitiveClosure
tc
=
new
TransitiveClosure
(
G
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
for
(
int
w
=
0
;
w
<
G
.
V
();
w
++
)
{
if
(
stronglyConnected
(
v
,
w
)
!=
(
tc
.
reachable
(
v
,
w
)
&&
tc
.
reachable
(
w
,
v
)))
return
false
;
}
}
return
true
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
marked
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
GabowSCC} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
Digraph
G
=
new
Digraph
(
in
);
GabowSCC
scc
=
new
GabowSCC
(
G
);
// number of connected components
int
m
=
scc
.
count
();
StdOut
.
println
(
m
+
” components”
);
// compute list of vertices in each strong component
Queue
<
Integer
>
[]
components
=
(
Queue
<
Integer
>
[])
new
Queue
[
m
];
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
components
[
i
]
=
new
Queue
<
Integer
>
();
}
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
components
[
scc
.
id
(
v
)].
enqueue
(
v
);
}
// print results
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
for
(
int
v
:
components
[
i
])
{
StdOut
.
print
(
v
+
" "
);
}
StdOut
.
println
();
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/GaussianElimination.java
edu/princeton/cs/algs4/GaussianElimination.java
/******************************************************************************
* Compilation: javac GaussianElimination.java
* Execution: java GaussianElimination m n
* Dependencies: StdOut.java
*
* Gaussian elimination with partial pivoting for m-by-n system.
*
* % java GaussianElimination m n
* -1.000000
* 2.000000
* 2.000000
*
* 3.000000
* -1.000000
* -2.000000
*
* System is infeasible
*
* -6.250000
* -4.500000
* 0.000000
* 0.000000
* 1.000000
*
* System is infeasible
*
* -1.375000
* 1.625000
* 0.000000
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
GaussianElimination} data type provides methods
* to solve a linear system of equations Ax = b,
* where A is an m-by-n matrix
* and b is a length n vector.
*
* This is a bare-bones implementation that uses Gaussian elimination
* with partial pivoting.
* See GaussianEliminationLite.java
* for a stripped-down version that assumes the matrix A is square
* and nonsingular. See {
@link
GaussJordanElimination} for an alternate
* implementation that uses Gauss-Jordan elimination.
* For an industrial-strength numerical linear algebra library,
* see JAMA.
*
* For additional documentation, see
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
GaussianElimination
{
private
static
final
double
EPSILON
=
1e-8
;
private
final
int
m
;
// number of rows
private
final
int
n
;
// number of columns
private
double
[][]
a
;
// m-by-(n+1) augmented matrix
/**
* Solves the linear system of equations Ax = b,
* where A is an m-by-n matrix and b
* is a length m vector.
*
*
@param
A the m-by-n constraint matrix
*
@param
b the length m right-hand-side vector
*
@throws
IllegalArgumentException if the dimensions disagree, i.e.,
* the length of {
@code
b} does not equal {
@code
m}
*/
public
GaussianElimination
(
double
[][]
A
,
double
[]
b
)
{
m
=
A
.
length
;
n
=
A
[
0
].
length
;
if
(
b
.
length
!=
m
)
throw
new
IllegalArgumentException
(
“Dimensions disagree”
);
// build augmented matrix
a
=
new
double
[
m
][
n
+
1
];
for
(
int
i
=
0
;
i
<
m
;
i
++
)
for
(
int
j
=
0
;
j
<
n
;
j
++
)
a
[
i
][
j
]
=
A
[
i
][
j
];
for
(
int
i
=
0
;
i
<
m
;
i
++
)
a
[
i
][
n
]
=
b
[
i
];
forwardElimination
();
assert
certifySolution
(
A
,
b
);
}
// forward elimination
private
void
forwardElimination
()
{
for
(
int
p
=
0
;
p
<
Math
.
min
(
m
,
n
);
p
++
)
{
// find pivot row using partial pivoting
int
max
=
p
;
for
(
int
i
=
p
+
1
;
i
<
m
;
i
++
)
{
if
(
Math
.
abs
(
a
[
i
][
p
])
>
Math
.
abs
(
a
[
max
][
p
]))
{
max
=
i
;
}
}
// swap
swap
(
p
,
max
);
// singular or nearly singular
if
(
Math
.
abs
(
a
[
p
][
p
])
<=
EPSILON
)
{
continue
;
}
// pivot
pivot
(
p
);
}
}
// swap row1 and row2
private
void
swap
(
int
row1
,
int
row2
)
{
double
[]
temp
=
a
[
row1
];
a
[
row1
]
=
a
[
row2
];
a
[
row2
]
=
temp
;
}
// pivot on a[p][p]
private
void
pivot
(
int
p
)
{
for
(
int
i
=
p
+
1
;
i
<
m
;
i
++
)
{
double
alpha
=
a
[
i
][
p
]
/
a
[
p
][
p
];
for
(
int
j
=
p
;
j
<=
n
;
j
++
)
{
a
[
i
][
j
]
-=
alpha
*
a
[
p
][
j
];
}
}
}
/**
* Returns a solution to the linear system of equations Ax = b.
*
*
@return
a solution x to the linear system of equations
* Ax = b; {
@code
null} if no such solution
*/
public
double
[]
primal
()
{
// back substitution
double
[]
x
=
new
double
[
n
];
for
(
int
i
=
Math
.
min
(
n
–
1
,
m
–
1
);
i
>=
0
;
i
—
)
{
double
sum
=
0.0
;
for
(
int
j
=
i
+
1
;
j
<
n
;
j
++
)
{
sum
+=
a
[
i
][
j
]
*
x
[
j
];
}
if
(
Math
.
abs
(
a
[
i
][
i
])
>
EPSILON
)
x
[
i
]
=
(
a
[
i
][
n
]
–
sum
)
/
a
[
i
][
i
];
else
if
(
Math
.
abs
(
a
[
i
][
n
]
–
sum
)
>
EPSILON
)
return
null
;
}
// redundant rows
for
(
int
i
=
n
;
i
<
m
;
i
++
)
{
double
sum
=
0.0
;
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
sum
+=
a
[
i
][
j
]
*
x
[
j
];
}
if
(
Math
.
abs
(
a
[
i
][
n
]
-
sum
)
>
EPSILON
)
return
null
;
}
return
x
;
}
/**
* Returns true if there exists a solution to the linear system of
* equations Ax = b.
*
*
@return
{
@code
true} if there exists a solution to the linear system
* of equations Ax = b; {
@code
false} otherwise
*/
public
boolean
isFeasible
()
{
return
primal
()
!=
null
;
}
// check that Ax = b
private
boolean
certifySolution
(
double
[][]
A
,
double
[]
b
)
{
if
(
!
isFeasible
())
return
true
;
double
[]
x
=
primal
();
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
double
sum
=
0.0
;
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
sum
+=
A
[
i
][
j
]
*
x
[
j
];
}
if
(
Math
.
abs
(
sum
-
b
[
i
])
>
EPSILON
)
{
StdOut
.
println
(
“not feasible”
);
StdOut
.
println
(
“b[”
+
i
+
“] = ”
+
b
[
i
]
+
“, sum = ”
+
sum
);
return
false
;
}
}
return
true
;
}
/**
* Unit tests the {
@code
GaussianElimination} data type.
*/
private
static
void
test
(
String
name
,
double
[][]
A
,
double
[]
b
)
{
StdOut
.
println
(
“—————————————————-”
);
StdOut
.
println
(
name
);
StdOut
.
println
(
“—————————————————-”
);
GaussianElimination
gaussian
=
new
GaussianElimination
(
A
,
b
);
double
[]
x
=
gaussian
.
primal
();
if
(
gaussian
.
isFeasible
())
{
for
(
int
i
=
0
;
i
<
x
.
length
;
i
++
)
{
StdOut
.
printf
(
"%.6f\n"
,
x
[
i
]);
}
}
else
{
StdOut
.
println
(
"System is infeasible"
);
}
StdOut
.
println
();
StdOut
.
println
();
}
// 3-by-3 nonsingular system
private
static
void
test1
()
{
double
[][]
A
=
{
{
0
,
1
,
1
},
{
2
,
4
,
-
2
},
{
0
,
3
,
15
}
};
double
[]
b
=
{
4
,
2
,
36
};
test
(
"test 1 (3-by-3 system, nonsingular)"
,
A
,
b
);
}
// 3-by-3 nonsingular system
private
static
void
test2
()
{
double
[][]
A
=
{
{
1
,
-
3
,
1
},
{
2
,
-
8
,
8
},
{
-
6
,
3
,
-
15
}
};
double
[]
b
=
{
4
,
-
2
,
9
};
test
(
"test 2 (3-by-3 system, nonsingular)"
,
A
,
b
);
}
// 5-by-5 singular: no solutions
private
static
void
test3
()
{
double
[][]
A
=
{
{
2
,
-
3
,
-
1
,
2
,
3
},
{
4
,
-
4
,
-
1
,
4
,
11
},
{
2
,
-
5
,
-
2
,
2
,
-
1
},
{
0
,
2
,
1
,
0
,
4
},
{
-
4
,
6
,
0
,
0
,
7
},
};
double
[]
b
=
{
4
,
4
,
9
,
-
6
,
5
};
test
(
"test 3 (5-by-5 system, no solutions)"
,
A
,
b
);
}
// 5-by-5 singular: infinitely many solutions
private
static
void
test4
()
{
double
[][]
A
=
{
{
2
,
-
3
,
-
1
,
2
,
3
},
{
4
,
-
4
,
-
1
,
4
,
11
},
{
2
,
-
5
,
-
2
,
2
,
-
1
},
{
0
,
2
,
1
,
0
,
4
},
{
-
4
,
6
,
0
,
0
,
7
},
};
double
[]
b
=
{
4
,
4
,
9
,
-
5
,
5
};
test
(
"test 4 (5-by-5 system, infinitely many solutions)"
,
A
,
b
);
}
// 3-by-3 singular: no solutions
private
static
void
test5
()
{
double
[][]
A
=
{
{
2
,
-
1
,
1
},
{
3
,
2
,
-
4
},
{
-
6
,
3
,
-
3
},
};
double
[]
b
=
{
1
,
4
,
2
};
test
(
"test 5 (3-by-3 system, no solutions)"
,
A
,
b
);
}
// 3-by-3 singular: infinitely many solutions
private
static
void
test6
()
{
double
[][]
A
=
{
{
1
,
-
1
,
2
},
{
4
,
4
,
-
2
},
{
-
2
,
2
,
-
4
},
};
double
[]
b
=
{
-
3
,
1
,
6
};
test
(
"test 6 (3-by-3 system, infinitely many solutions)"
,
A
,
b
);
}
// 4-by-3 full rank and feasible system
private
static
void
test7
()
{
double
[][]
A
=
{
{
0
,
1
,
1
},
{
2
,
4
,
-
2
},
{
0
,
3
,
15
},
{
2
,
8
,
14
}
};
double
[]
b
=
{
4
,
2
,
36
,
42
};
test
(
"test 7 (4-by-3 system, full rank)"
,
A
,
b
);
}
// 4-by-3 full rank and infeasible system
private
static
void
test8
()
{
double
[][]
A
=
{
{
0
,
1
,
1
},
{
2
,
4
,
-
2
},
{
0
,
3
,
15
},
{
2
,
8
,
14
}
};
double
[]
b
=
{
4
,
2
,
36
,
40
};
test
(
"test 8 (4-by-3 system, no solution)"
,
A
,
b
);
}
// 3-by-4 full rank system
private
static
void
test9
()
{
double
[][]
A
=
{
{
1
,
-
3
,
1
,
1
},
{
2
,
-
8
,
8
,
2
},
{
-
6
,
3
,
-
15
,
3
}
};
double
[]
b
=
{
4
,
-
2
,
9
};
test
(
"test 9 (3-by-4 system, full rank)"
,
A
,
b
);
}
/**
* Unit tests the {
@code
GaussianElimination} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
test1
();
test2
();
test3
();
test4
();
test5
();
test6
();
test7
();
test8
();
test9
();
// n-by-n random system
int
n
=
Integer
.
parseInt
(
args
[
0
]);
double
[][]
A
=
new
double
[
n
][
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
for
(
int
j
=
0
;
j
<
n
;
j
++
)
A
[
i
][
j
]
=
StdRandom
.
uniform
(
1000
);
double
[]
b
=
new
double
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
b
[
i
]
=
StdRandom
.
uniform
(
1000
);
test
(
n
+
"-by-"
+
n
+
" (probably nonsingular)"
,
A
,
b
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/GaussJordanElimination.java
edu/princeton/cs/algs4/GaussJordanElimination.java
/******************************************************************************
* Compilation: javac GaussJordanElimination.java
* Execution: java GaussJordanElimination n
* Dependencies: StdOut.java
*
* Finds a solutions to Ax = b using Gauss-Jordan elimination with partial
* pivoting. If no solution exists, find a solution to yA = 0, yb != 0,
* which serves as a certificate of infeasibility.
*
* % java GaussJordanElimination
* -1.000000
* 2.000000
* 2.000000
*
* 3.000000
* -1.000000
* -2.000000
*
* System is infeasible
*
* -6.250000
* -4.500000
* 0.000000
* 0.000000
* 1.000000
*
* System is infeasible
*
* -1.375000
* 1.625000
* 0.000000
*
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
GaussJordanElimination} data type provides methods
* to solve a linear system of equations Ax = b,
* where A is an n-by-n matrix
* and b is a length n vector.
* If no solution exists, it finds a solution y to
* yA = 0, yb ≠ 0, which
* which serves as a certificate of infeasibility.
*
* This implementation uses Gauss-Jordan elimination with partial pivoting.
* See {
@link
GaussianElimination} for an implementation that uses
* Gaussian elimination (but does not provide the certificate of infeasibility).
* For an industrial-strength numerical linear algebra library,
* see JAMA.
*
* For additional documentation, see
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
GaussJordanElimination
{
private
static
final
double
EPSILON
=
1e-8
;
private
final
int
n
;
// n-by-n system
private
double
[][]
a
;
// n-by-(n+1) augmented matrix
// Gauss-Jordan elimination with partial pivoting
/**
* Solves the linear system of equations Ax = b,
* where A is an n-by-n matrix and b
* is a length n vector.
*
*
@param
A the n-by-n constraint matrix
*
@param
b the length n right-hand-side vector
*/
public
GaussJordanElimination
(
double
[][]
A
,
double
[]
b
)
{
n
=
b
.
length
;
// build augmented matrix
a
=
new
double
[
n
][
n
+
n
+
1
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
for
(
int
j
=
0
;
j
<
n
;
j
++
)
a
[
i
][
j
]
=
A
[
i
][
j
];
// only needed if you want to find certificate of infeasibility (or compute inverse)
for
(
int
i
=
0
;
i
<
n
;
i
++
)
a
[
i
][
n
+
i
]
=
1.0
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
a
[
i
][
n
+
n
]
=
b
[
i
];
solve
();
assert
certifySolution
(
A
,
b
);
}
private
void
solve
()
{
// Gauss-Jordan elimination
for
(
int
p
=
0
;
p
<
n
;
p
++
)
{
// show();
// find pivot row using partial pivoting
int
max
=
p
;
for
(
int
i
=
p
+
1
;
i
<
n
;
i
++
)
{
if
(
Math
.
abs
(
a
[
i
][
p
])
>
Math
.
abs
(
a
[
max
][
p
]))
{
max
=
i
;
}
}
// exchange row p with row max
swap
(
p
,
max
);
// singular or nearly singular
if
(
Math
.
abs
(
a
[
p
][
p
])
<=
EPSILON
)
{
continue
;
// throw new ArithmeticException("Matrix is singular or nearly singular");
}
// pivot
pivot
(
p
,
p
);
}
// show();
}
// swap row1 and row2
private
void
swap
(
int
row1
,
int
row2
)
{
double
[]
temp
=
a
[
row1
];
a
[
row1
]
=
a
[
row2
];
a
[
row2
]
=
temp
;
}
// pivot on entry (p, q) using Gauss-Jordan elimination
private
void
pivot
(
int
p
,
int
q
)
{
// everything but row p and column q
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
double
alpha
=
a
[
i
][
q
]
/
a
[
p
][
q
];
for
(
int
j
=
0
;
j
<=
n
+
n
;
j
++
)
{
if
(
i
!=
p
&&
j
!=
q
)
a
[
i
][
j
]
-=
alpha
*
a
[
p
][
j
];
}
}
// zero out column q
for
(
int
i
=
0
;
i
<
n
;
i
++
)
if
(
i
!=
p
)
a
[
i
][
q
]
=
0.0
;
// scale row p (ok to go from q+1 to n, but do this for consistency with simplex pivot)
for
(
int
j
=
0
;
j
<=
n
+
n
;
j
++
)
if
(
j
!=
q
)
a
[
p
][
j
]
/=
a
[
p
][
q
];
a
[
p
][
q
]
=
1.0
;
}
/**
* Returns a solution to the linear system of equations Ax = b.
*
*
@return
a solution x to the linear system of equations
* Ax = b; {
@code
null} if no such solution
*/
public
double
[]
primal
()
{
double
[]
x
=
new
double
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
if
(
Math
.
abs
(
a
[
i
][
i
])
>
EPSILON
)
x
[
i
]
=
a
[
i
][
n
+
n
]
/
a
[
i
][
i
];
else
if
(
Math
.
abs
(
a
[
i
][
n
+
n
])
>
EPSILON
)
return
null
;
}
return
x
;
}
/**
* Returns a solution to the linear system of equations yA = 0,
* yb ≠ 0.
*
*
@return
a solution y to the linear system of equations
* yA = 0, yb ≠ 0; {
@code
null} if no such solution
*/
public
double
[]
dual
()
{
double
[]
y
=
new
double
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
if
((
Math
.
abs
(
a
[
i
][
i
])
<=
EPSILON
)
&&
(
Math
.
abs
(
a
[
i
][
n
+
n
])
>
EPSILON
))
{
for
(
int
j
=
0
;
j
<
n
;
j
++
)
y
[
j
]
=
a
[
i
][
n
+
j
];
return
y
;
}
}
return
null
;
}
/**
* Returns true if there exists a solution to the linear system of
* equations Ax = b.
*
*
@return
{
@code
true} if there exists a solution to the linear system
* of equations Ax = b; {
@code
false} otherwise
*/
public
boolean
isFeasible
()
{
return
primal
()
!=
null
;
}
// print the tableaux
private
void
show
()
{
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
StdOut
.
printf
(
"%8.3f "
,
a
[
i
][
j
]);
}
StdOut
.
printf
(
"| "
);
for
(
int
j
=
n
;
j
<
n
+
n
;
j
++
)
{
StdOut
.
printf
(
"%8.3f "
,
a
[
i
][
j
]);
}
StdOut
.
printf
(
"| %8.3f\n"
,
a
[
i
][
n
+
n
]);
}
StdOut
.
println
();
}
// check that Ax = b or yA = 0, yb != 0
private
boolean
certifySolution
(
double
[][]
A
,
double
[]
b
)
{
// check that Ax = b
if
(
isFeasible
())
{
double
[]
x
=
primal
();
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
double
sum
=
0.0
;
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
sum
+=
A
[
i
][
j
]
*
x
[
j
];
}
if
(
Math
.
abs
(
sum
-
b
[
i
])
>
EPSILON
)
{
StdOut
.
println
(
“not feasible”
);
StdOut
.
printf
(
“b[%d] = %8.3f, sum = %8.3f\n”
,
i
,
b
[
i
],
sum
);
return
false
;
}
}
return
true
;
}
// or that yA = 0, yb != 0
else
{
double
[]
y
=
dual
();
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
double
sum
=
0.0
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
sum
+=
A
[
i
][
j
]
*
y
[
i
];
}
if
(
Math
.
abs
(
sum
)
>
EPSILON
)
{
StdOut
.
println
(
“invalid certificate of infeasibility”
);
StdOut
.
printf
(
“sum = %8.3f\n”
,
sum
);
return
false
;
}
}
double
sum
=
0.0
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
sum
+=
y
[
i
]
*
b
[
i
];
}
if
(
Math
.
abs
(
sum
)
<
EPSILON
)
{
StdOut
.
println
(
"invalid certificate of infeasibility"
);
StdOut
.
printf
(
"yb = %8.3f\n"
,
sum
);
return
false
;
}
return
true
;
}
}
private
static
void
test
(
String
name
,
double
[][]
A
,
double
[]
b
)
{
StdOut
.
println
(
"----------------------------------------------------"
);
StdOut
.
println
(
name
);
StdOut
.
println
(
"----------------------------------------------------"
);
GaussJordanElimination
gaussian
=
new
GaussJordanElimination
(
A
,
b
);
if
(
gaussian
.
isFeasible
())
{
StdOut
.
println
(
"Solution to Ax = b"
);
double
[]
x
=
gaussian
.
primal
();
for
(
int
i
=
0
;
i
<
x
.
length
;
i
++
)
{
StdOut
.
printf
(
"%10.6f\n"
,
x
[
i
]);
}
}
else
{
StdOut
.
println
(
"Certificate of infeasibility"
);
double
[]
y
=
gaussian
.
dual
();
for
(
int
j
=
0
;
j
<
y
.
length
;
j
++
)
{
StdOut
.
printf
(
"%10.6f\n"
,
y
[
j
]);
}
}
StdOut
.
println
();
StdOut
.
println
();
}
// 3-by-3 nonsingular system
private
static
void
test1
()
{
double
[][]
A
=
{
{
0
,
1
,
1
},
{
2
,
4
,
-
2
},
{
0
,
3
,
15
}
};
double
[]
b
=
{
4
,
2
,
36
};
test
(
"test 1"
,
A
,
b
);
}
// 3-by-3 nonsingular system
private
static
void
test2
()
{
double
[][]
A
=
{
{
1
,
-
3
,
1
},
{
2
,
-
8
,
8
},
{
-
6
,
3
,
-
15
}
};
double
[]
b
=
{
4
,
-
2
,
9
};
test
(
"test 2"
,
A
,
b
);
}
// 5-by-5 singular: no solutions
// y = [ -1, 0, 1, 1, 0 ]
private
static
void
test3
()
{
double
[][]
A
=
{
{
2
,
-
3
,
-
1
,
2
,
3
},
{
4
,
-
4
,
-
1
,
4
,
11
},
{
2
,
-
5
,
-
2
,
2
,
-
1
},
{
0
,
2
,
1
,
0
,
4
},
{
-
4
,
6
,
0
,
0
,
7
},
};
double
[]
b
=
{
4
,
4
,
9
,
-
6
,
5
};
test
(
"test 3"
,
A
,
b
);
}
// 5-by-5 singluar: infinitely many solutions
private
static
void
test4
()
{
double
[][]
A
=
{
{
2
,
-
3
,
-
1
,
2
,
3
},
{
4
,
-
4
,
-
1
,
4
,
11
},
{
2
,
-
5
,
-
2
,
2
,
-
1
},
{
0
,
2
,
1
,
0
,
4
},
{
-
4
,
6
,
0
,
0
,
7
},
};
double
[]
b
=
{
4
,
4
,
9
,
-
5
,
5
};
test
(
"test 4"
,
A
,
b
);
}
// 3-by-3 singular: no solutions
// y = [ 1, 0, 1/3 ]
private
static
void
test5
()
{
double
[][]
A
=
{
{
2
,
-
1
,
1
},
{
3
,
2
,
-
4
},
{
-
6
,
3
,
-
3
},
};
double
[]
b
=
{
1
,
4
,
2
};
test
(
"test 5"
,
A
,
b
);
}
// 3-by-3 singular: infinitely many solutions
private
static
void
test6
()
{
double
[][]
A
=
{
{
1
,
-
1
,
2
},
{
4
,
4
,
-
2
},
{
-
2
,
2
,
-
4
},
};
double
[]
b
=
{
-
3
,
1
,
6
};
test
(
"test 6 (infinitely many solutions)"
,
A
,
b
);
}
/**
* Unit tests the {
@code
GaussJordanElimination} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
test1
();
test2
();
test3
();
test4
();
test5
();
test6
();
// n-by-n random system (likely full rank)
int
n
=
Integer
.
parseInt
(
args
[
0
]);
double
[][]
A
=
new
double
[
n
][
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
for
(
int
j
=
0
;
j
<
n
;
j
++
)
A
[
i
][
j
]
=
StdRandom
.
uniform
(
1000
);
double
[]
b
=
new
double
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
b
[
i
]
=
StdRandom
.
uniform
(
1000
);
test
(
"random "
+
n
+
"-by-"
+
n
+
" (likely full rank)"
,
A
,
b
);
// n-by-n random system (likely infeasible)
A
=
new
double
[
n
][
n
];
for
(
int
i
=
0
;
i
<
n
-
1
;
i
++
)
for
(
int
j
=
0
;
j
<
n
;
j
++
)
A
[
i
][
j
]
=
StdRandom
.
uniform
(
1000
);
for
(
int
i
=
0
;
i
<
n
-
1
;
i
++
)
{
double
alpha
=
StdRandom
.
uniform
(
11
)
-
5.0
;
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
A
[
n
-
1
][
j
]
+=
alpha
*
A
[
i
][
j
];
}
}
b
=
new
double
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
b
[
i
]
=
StdRandom
.
uniform
(
1000
);
test
(
"random "
+
n
+
"-by-"
+
n
+
" (likely infeasible)"
,
A
,
b
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Genome.java
edu/princeton/cs/algs4/Genome.java
/******************************************************************************
* Compilation: javac Genome.java
* Execution: java Genome - < input.txt (compress)
* Execution: java Genome + < input.txt (expand)
* Dependencies: BinaryIn.java BinaryOut.java
* Data files: https://algs4.cs.princeton.edu/55compression/genomeTiny.txt
*
* Compress or expand a genomic sequence using a 2-bit code.
*
* % more genomeTiny.txt
* ATAGATGCATAGCGCATAGCTAGATGTGCTAGC
*
* % java Genome - < genomeTiny.txt | java Genome +
* ATAGATGCATAGCGCATAGCTAGATGTGCTAGC
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Genome} class provides static methods for compressing
* and expanding a genomic sequence using a 2-bit code.
*
* For additional documentation,
* see Section 5.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Genome
{
// Do not instantiate.
private
Genome
()
{
}
/**
* Reads a sequence of 8-bit extended ASCII characters over the alphabet
* { A, C, T, G } from standard input; compresses them using two bits per
* character; and writes the results to standard output.
*/
public
static
void
compress
()
{
Alphabet
DNA
=
Alphabet
.
DNA
;
String
s
=
BinaryStdIn
.
readString
();
int
n
=
s
.
length
();
BinaryStdOut
.
write
(
n
);
// Write two-bit code for char.
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
int
d
=
DNA
.
toIndex
(
s
.
charAt
(
i
));
BinaryStdOut
.
write
(
d
,
2
);
}
BinaryStdOut
.
close
();
}
/**
* Reads a binary sequence from standard input; converts each two bits
* to an 8-bit extended ASCII character over the alphabet { A, C, T, G };
* and writes the results to standard output.
*/
public
static
void
expand
()
{
Alphabet
DNA
=
Alphabet
.
DNA
;
int
n
=
BinaryStdIn
.
readInt
();
// Read two bits; write char.
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
char
c
=
BinaryStdIn
.
readChar
(
2
);
BinaryStdOut
.
write
(
DNA
.
toChar
(
c
),
8
);
}
BinaryStdOut
.
close
();
}
/**
* Sample client that calls {
@code
compress()} if the command-line
* argument is "-" an {
@code
expand()} if it is "+".
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
if
(
args
[
0
].
equals
(
"-"
))
compress
();
else
if
(
args
[
0
].
equals
(
"+"
))
expand
();
else
throw
new
IllegalArgumentException
(
"Illegal command line argument"
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/GlobalMincut.java
edu/princeton/cs/algs4/GlobalMincut.java
/******************************************************************************
* Compilation: javac GlobalMincut.java
* Execution: java GlobalMincut filename.txt
* Dependencies: EdgeWeightedGraph.java Edge.java UF.java
* IndexMaxPQ.java FlowNetwork.java FlowEdge.java
* FordFulkerson.java In.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/43mst/tinyEWG.txt
* https://algs4.cs.princeton.edu/43mst/mediumEWG.txt
*
* Computes a minimum cut using Stoer-Wagner's algorithm.
*
* % java GlobalMincut tinyEWG.txt
* Min cut: 5
* Min cut weight = 0.9500000000000001
*
* % java GlobalMincut mediumEWG.txt
* Min cut: 25 60 63 96 199 237
* Min cut weight = 0.14021
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
GlobalMincut} class represents a data type for computing a
* global minimum cut in a graph with non-negative edge weights.
* A cut is a partition of the vertices into two nonempty subsets.
* An edge that has one
* endpoint in each subset of a cut is a crossing edge. The weight
* of a cut is the sum of the weights of its crossing edges.
* A global minimum cut whose weight is no larger than the weight
* of any other cut.
*
* This is an implementation of Stoer-Wagner’s algorithm.
* The constructor takes
* O(V (V + E) log V) time,
* where V is the number of vertices and E is the
* number of edges.
* The weight and isCut methods take Θ(1) time.
* It uses Θ(V) extra space (not including the graph).
*
* For additional documentation, see
*
*
* the ACM
, 44(4):585-591.*
*
*
@author
Marcelo Silva
*/
public
class
GlobalMincut
{
private
static
final
double
FLOATING_POINT_EPSILON
=
1E-11
;
// the weight of the minimum cut
private
double
weight
=
Double
.
POSITIVE_INFINITY
;
// cut[v] = true if v is on the first subset of vertices of the minimum cut;
// or false if v is on the second subset
private
boolean
[]
cut
;
// number of vertices
private
int
V
;
/**
* This helper class represents the cut-of-the-phase. The
* cut-of-the-phase is a minimum s-t-cut in the current graph,
* where {
@code
s} and {
@code
t} are the two vertices added last in the
* phase.
*/
private
class
CutPhase
{
private
double
weight
;
// the weight of the minimum s-t cut
private
int
s
;
// the vertex s
private
int
t
;
// the vertex t
public
CutPhase
(
double
weight
,
int
s
,
int
t
)
{
this
.
weight
=
weight
;
this
.
s
=
s
;
this
.
t
=
t
;
}
}
/**
* Computes a minimum cut in an edge-weighted graph.
*
*
@param
G the edge-weighted graph
*
@throws
IllegalArgumentException if the number of vertices of {
@code
G}
* is less than {
@code
2}.
*
@throws
IllegalArgumentException if any edge weight is negative
*/
public
GlobalMincut
(
EdgeWeightedGraph
G
)
{
V
=
G
.
V
();
validate
(
G
);
minCut
(
G
,
0
);
assert
check
(
G
);
}
/**
* Validates the edge-weighted graph.
*
*
@param
G the edge-weighted graph
*
@throws
IllegalArgumentException if the number of vertices of {
@code
G}
* is less than {
@code
2} or if any edge weight is negative
*/
private
void
validate
(
EdgeWeightedGraph
G
)
{
if
(
G
.
V
()
<
2
)
throw
new
IllegalArgumentException
(
"number of vertices of G is less than 2"
);
for
(
Edge
e
:
G
.
edges
())
{
if
(
e
.
weight
()
<
0
)
throw
new
IllegalArgumentException
(
"edge "
+
e
+
" has negative weight"
);
}
}
/**
* Returns the weight of the minimum cut.
*
*
@return
the weight of the minimum cut
*/
public
double
weight
()
{
return
weight
;
}
/**
* Returns {
@code
true} if the vertex {
@code
v} is one side of the
* mincut and {
@code
false} otherwise. An edge v–w
* crosses the mincut if and only if v and w have
* opposite parity.
*
*
@param
v the vertex to check
*
@return
{
@code
true} if the vertex {
@code
v} is on the first subset of
* vertices of the minimum cut; or {
@code
false} if the vertex
* {
@code
v} is on the second subset.
*
@throws
IllegalArgumentException unless vertex {
@code
v} is between
* {
@code
0 <= v < V}
*/
public
boolean
cut
(
int
v
)
{
validateVertex
(
v
);
return
cut
[
v
];
}
/**
* Makes a cut for the current edge-weighted graph by partitioning its
* vertices into two nonempty subsets. The vertices connected to the
* vertex {
@code
t} belong to the first subset. Other vertices not connected
* to {
@code
t} belong to the second subset.
*
*
@param
t the vertex {
@code
t}
*
@param
uf the union-find data type
*/
private
void
makeCut
(
int
t
,
UF uf
)
{
for
(
int
v
=
0
;
v
<
cut
.
length
;
v
++
)
{
cut
[
v
]
=
(
uf
.
find
(
v
)
==
uf
.
find
(
t
));
}
}
/**
* Computes a minimum cut of the edge-weighted graph. Precisely, it computes
* the lightest of the cuts-of-the-phase which yields the desired minimum
* cut.
*
*
@param
G the edge-weighted graph
*
@param
a the starting vertex
*/
private
void
minCut
(
EdgeWeightedGraph
G
,
int
a
)
{
UF uf
=
new
UF
(
G
.
V
());
boolean
[]
marked
=
new
boolean
[
G
.
V
()];
cut
=
new
boolean
[
G
.
V
()];
CutPhase
cp
=
new
CutPhase
(
0.0
,
a
,
a
);
for
(
int
v
=
G
.
V
();
v
>
1
;
v
—
)
{
cp
=
minCutPhase
(
G
,
marked
,
cp
);
if
(
cp
.
weight
<
weight
)
{
weight
=
cp
.
weight
;
makeCut
(
cp
.
t
,
uf
);
}
G
=
contractEdge
(
G
,
cp
.
s
,
cp
.
t
);
marked
[
cp
.
t
]
=
true
;
uf
.
union
(
cp
.
s
,
cp
.
t
);
}
}
/**
* Returns the cut-of-the-phase. The cut-of-the-phase is a minimum s-t-cut
* in the current graph, where {
@code
s} and {
@code
t} are the two vertices
* added last in the phase. This algorithm is known in the literature as
* maximum adjacency search or maximum cardinality search.
*
*
@param
G the edge-weighted graph
*
@param
marked the array of contracted vertices, where {
@code
marked[v]}
* is {
@code
true} if the vertex {
@code
v} was already
* contracted; or {
@code
false} otherwise
*
@param
cp the previous cut-of-the-phase
*
@return
the cut-of-the-phase
*/
private
CutPhase
minCutPhase
(
EdgeWeightedGraph
G
,
boolean
[]
marked
,
CutPhase
cp
)
{
IndexMaxPQ
<
Double
>
pq
=
new
IndexMaxPQ
<
Double
>
(
G
.
V
());
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
v
!=
cp
.
s
&&
!
marked
[
v
])
pq
.
insert
(
v
,
0.0
);
}
pq
.
insert
(
cp
.
s
,
Double
.
POSITIVE_INFINITY
);
while
(
!
pq
.
isEmpty
())
{
int
v
=
pq
.
delMax
();
cp
.
s
=
cp
.
t
;
cp
.
t
=
v
;
for
(
Edge
e
:
G
.
adj
(
v
))
{
int
w
=
e
.
other
(
v
);
if
(
pq
.
contains
(
w
))
pq
.
increaseKey
(
w
,
pq
.
keyOf
(
w
)
+
e
.
weight
());
}
}
cp
.
weight
=
0.0
;
for
(
Edge
e
:
G
.
adj
(
cp
.
t
))
{
cp
.
weight
+=
e
.
weight
();
}
return
cp
;
}
/**
* Contracts the edges incidents on the vertices {
@code
s} and {
@code
t} of
* the given edge-weighted graph.
*
*
@param
G the edge-weighted graph
*
@param
s the vertex {
@code
s}
*
@param
t the vertex {
@code
t}
*
@return
a new edge-weighted graph for which the edges incidents on the
* vertices {
@code
s} and {
@code
t} were contracted
*/
private
EdgeWeightedGraph
contractEdge
(
EdgeWeightedGraph
G
,
int
s
,
int
t
)
{
EdgeWeightedGraph
H
=
new
EdgeWeightedGraph
(
G
.
V
());
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
for
(
Edge
e
:
G
.
adj
(
v
))
{
int
w
=
e
.
other
(
v
);
if
(
v
==
s
&&
w
==
t
||
v
==
t
&&
w
==
s
)
continue
;
if
(
v
<
w
)
{
if
(
w
==
t
)
H
.
addEdge
(
new
Edge
(
v
,
s
,
e
.
weight
()));
else
if
(
v
==
t
)
H
.
addEdge
(
new
Edge
(
w
,
s
,
e
.
weight
()));
else
H
.
addEdge
(
new
Edge
(
v
,
w
,
e
.
weight
()));
}
}
}
return
H
;
}
/**
* Checks optimality conditions.
*
*
@param
G the edge-weighted graph
*
@return
{
@code
true} if optimality conditions are fine
*/
private
boolean
check
(
EdgeWeightedGraph
G
)
{
// compute min st-cut for all pairs s and t
// shortcut: s must appear on one side of global mincut,
// so it suffices to try all pairs s-v for some fixed s
double
value
=
Double
.
POSITIVE_INFINITY
;
for
(
int
s
=
0
,
t
=
1
;
t
<
G
.
V
();
t
++
)
{
FlowNetwork
F
=
new
FlowNetwork
(
G
.
V
());
for
(
Edge
e
:
G
.
edges
())
{
int
v
=
e
.
either
(),
w
=
e
.
other
(
v
);
F
.
addEdge
(
new
FlowEdge
(
v
,
w
,
e
.
weight
()));
F
.
addEdge
(
new
FlowEdge
(
w
,
v
,
e
.
weight
()));
}
FordFulkerson
maxflow
=
new
FordFulkerson
(
F
,
s
,
t
);
value
=
Math
.
min
(
value
,
maxflow
.
value
());
}
if
(
Math
.
abs
(
weight
-
value
)
>
FLOATING_POINT_EPSILON
)
{
System
.
err
.
println
(
“Min cut weight = ”
+
weight
+
” , max flow value = ”
+
value
);
return
false
;
}
return
true
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
GlobalMincut} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
EdgeWeightedGraph
G
=
new
EdgeWeightedGraph
(
in
);
GlobalMincut
mc
=
new
GlobalMincut
(
G
);
StdOut
.
print
(
“Min cut: ”
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
mc
.
cut
(
v
))
StdOut
.
print
(
v
+
" "
);
}
StdOut
.
println
();
StdOut
.
println
(
"Min cut weight = "
+
mc
.
weight
());
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/GrahamScan.java
edu/princeton/cs/algs4/GrahamScan.java
/******************************************************************************
* Compilation: javac GrahamaScan.java
* Execution: java GrahamScan < input.txt
* Dependencies: Point2D.java
* Data files: https://algs4.cs.princeton.edu/99hull/rs1423.txt
* https://algs4.cs.princeton.edu/99hull/kw1260.txt
*
* Create points from standard input and compute the convex hull using
* Graham scan algorithm.
*
* May be floating-point issues if x- and y-coordinates are not integers.
*
* % java GrahamScan < input100.txt
* (7486.0, 422.0)
* (29413.0, 596.0)
* (32011.0, 3140.0)
* (30875.0, 28560.0)
* (28462.0, 32343.0)
* (15731.0, 32661.0)
* (822.0, 32301.0)
* (823.0, 15895.0)
* (1444.0, 10362.0)
* (4718.0, 4451.0)
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Arrays
;
/**
* The {
@code
GrahamScan} data type provides methods for computing the
* convex hull of a set of n points in the plane.
*
* The implementation uses the Graham-Scan convex hull algorithm.
* It runs in O(n log n) time in the worst case
* and uses O(n) extra memory.
*
* For additional documentation, see Section 9.9 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
GrahamScan
{
private
Stack
<
Point2D
>
hull
=
new
Stack
<
Point2D
>
();
/**
* Computes the convex hull of the specified array of points.
*
*
@param
points the array of points
*
@throws
IllegalArgumentException if {
@code
points} is {
@code
null}
*
@throws
IllegalArgumentException if any entry in {
@code
points[]} is {
@code
null}
*
@throws
IllegalArgumentException if {
@code
points.length} is {
@code
0}
*/
public
GrahamScan
(
Point2D
[]
points
)
{
if
(
points
==
null
)
throw
new
IllegalArgumentException
(
“argument is null”
);
if
(
points
.
length
==
0
)
throw
new
IllegalArgumentException
(
“array is of length 0”
);
// defensive copy
int
n
=
points
.
length
;
Point2D
[]
a
=
new
Point2D
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
if
(
points
[
i
]
==
null
)
throw
new
IllegalArgumentException
(
"points["
+
i
+
"] is null"
);
a
[
i
]
=
points
[
i
];
}
// preprocess so that a[0] has lowest y-coordinate; break ties by x-coordinate
// a[0] is an extreme point of the convex hull
// (alternatively, could do easily in linear time)
Arrays
.
sort
(
a
);
// sort by polar angle with respect to base point a[0],
// breaking ties by distance to a[0]
Arrays
.
sort
(
a
,
1
,
n
,
a
[
0
].
polarOrder
());
hull
.
push
(
a
[
0
]);
// a[0] is first extreme point
// find index k1 of first point not equal to a[0]
int
k1
;
for
(
k1
=
1
;
k1
<
n
;
k1
++
)
if
(
!
a
[
0
].
equals
(
a
[
k1
]))
break
;
if
(
k1
==
n
)
return
;
// all points equal
// find index k2 of first point not collinear with a[0] and a[k1]
int
k2
;
for
(
k2
=
k1
+
1
;
k2
<
n
;
k2
++
)
if
(
Point2D
.
ccw
(
a
[
0
],
a
[
k1
],
a
[
k2
])
!=
0
)
break
;
hull
.
push
(
a
[
k2
-
1
]);
// a[k2-1] is second extreme point
// Graham scan; note that a[n-1] is extreme point different from a[0]
for
(
int
i
=
k2
;
i
<
n
;
i
++
)
{
Point2D
top
=
hull
.
pop
();
while
(
Point2D
.
ccw
(
hull
.
peek
(),
top
,
a
[
i
])
<=
0
)
{
top
=
hull
.
pop
();
}
hull
.
push
(
top
);
hull
.
push
(
a
[
i
]);
}
assert
isConvex
();
}
/**
* Returns the extreme points on the convex hull in counterclockwise order.
*
*
@return
the extreme points on the convex hull in counterclockwise order
*/
public
Iterable
<
Point2D
>
hull
()
{
Stack
<
Point2D
>
s
=
new
Stack
<
Point2D
>
();
for
(
Point2D
p
:
hull
)
s
.
push
(
p
);
return
s
;
}
// check that boundary of hull is strictly convex
private
boolean
isConvex
()
{
int
n
=
hull
.
size
();
if
(
n
<=
2
)
return
true
;
Point2D
[]
points
=
new
Point2D
[
n
];
int
k
=
0
;
for
(
Point2D
p
:
hull
())
{
points
[
k
++
]
=
p
;
}
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
if
(
Point2D
.
ccw
(
points
[
i
],
points
[(
i
+
1
)
%
n
],
points
[(
i
+
2
)
%
n
])
<=
0
)
{
return
false
;
}
}
return
true
;
}
/**
* Unit tests the {
@code
GrahamScan} data type.
* Reads in an integer {
@code
n} and {
@code
n} points (specified by
* their x– and y-coordinates) from standard input;
* computes their convex hull; and prints out the points on the
* convex hull to standard output.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
n
=
StdIn
.
readInt
();
Point2D
[]
points
=
new
Point2D
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
int
x
=
StdIn
.
readInt
();
int
y
=
StdIn
.
readInt
();
points
[
i
]
=
new
Point2D
(
x
,
y
);
}
GrahamScan
graham
=
new
GrahamScan
(
points
);
for
(
Point2D
p
:
graham
.
hull
())
StdOut
.
println
(
p
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/GraphGenerator.java
edu/princeton/cs/algs4/GraphGenerator.java
/******************************************************************************
* Compilation: javac GraphGenerator.java
* Execution: java GraphGenerator V E
* Dependencies: Graph.java
*
* A graph generator.
*
* For many more graph generators, see
* http://networkx.github.io/documentation/latest/reference/generators.html
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
GraphGenerator} class provides static methods for creating
* various graphs, including Erdos-Renyi random graphs, random bipartite
* graphs, random k-regular graphs, and random rooted trees.
*
* For additional documentation, see Section 4.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
GraphGenerator
{
private
static
final
class
Edge
implements
Comparable
<
Edge
>
{
private
int
v
;
private
int
w
;
private
Edge
(
int
v
,
int
w
)
{
if
(
v
<
w
)
{
this
.
v
=
v
;
this
.
w
=
w
;
}
else
{
this
.
v
=
w
;
this
.
w
=
v
;
}
}
public
int
compareTo
(
Edge
that
)
{
if
(
this
.
v
<
that
.
v
)
return
-
1
;
if
(
this
.
v
>
that
.
v
)
return
+
1
;
if
(
this
.
w
<
that
.
w
)
return
-
1
;
if
(
this
.
w
>
that
.
w
)
return
+
1
;
return
0
;
}
}
// this class cannot be instantiated
private
GraphGenerator
()
{
}
/**
* Returns a random simple graph containing {
@code
V} vertices and {
@code
E} edges.
*
@param
V the number of vertices
*
@param
E the number of vertices
*
@return
a random simple graph on {
@code
V} vertices, containing a total
* of {
@code
E} edges
*
@throws
IllegalArgumentException if no such simple graph exists
*/
public
static
Graph
simple
(
int
V
,
int
E
)
{
if
(
E
>
(
long
)
V
*
(
V
–
1
)
/
2
)
throw
new
IllegalArgumentException
(
“Too many edges”
);
if
(
E
<
0
)
throw
new
IllegalArgumentException
(
"Too few edges"
);
Graph
G
=
new
Graph
(
V
);
SET
<
Edge
>
set
=
new
SET
<
Edge
>
();
while
(
G
.
E
()
<
E
)
{
int
v
=
StdRandom
.
uniform
(
V
);
int
w
=
StdRandom
.
uniform
(
V
);
Edge
e
=
new
Edge
(
v
,
w
);
if
((
v
!=
w
)
&&
!
set
.
contains
(
e
))
{
set
.
add
(
e
);
G
.
addEdge
(
v
,
w
);
}
}
return
G
;
}
/**
* Returns a random simple graph on {
@code
V} vertices, with an
* edge between any two vertices with probability {
@code
p}. This is sometimes
* referred to as the Erdos-Renyi random graph model.
*
@param
V the number of vertices
*
@param
p the probability of choosing an edge
*
@return
a random simple graph on {
@code
V} vertices, with an edge between
* any two vertices with probability {
@code
p}
*
@throws
IllegalArgumentException if probability is not between 0 and 1
*/
public
static
Graph
simple
(
int
V
,
double
p
)
{
if
(
p
<
0.0
||
p
>
1.0
)
throw
new
IllegalArgumentException
(
“Probability must be between 0 and 1”
);
Graph
G
=
new
Graph
(
V
);
for
(
int
v
=
0
;
v
<
V
;
v
++
)
for
(
int
w
=
v
+
1
;
w
<
V
;
w
++
)
if
(
StdRandom
.
bernoulli
(
p
))
G
.
addEdge
(
v
,
w
);
return
G
;
}
/**
* Returns the complete graph on {
@code
V} vertices.
*
@param
V the number of vertices
*
@return
the complete graph on {
@code
V} vertices
*/
public
static
Graph
complete
(
int
V
)
{
return
simple
(
V
,
1.0
);
}
/**
* Returns a complete bipartite graph on {
@code
V1} and {
@code
V2} vertices.
*
@param
V1 the number of vertices in one partition
*
@param
V2 the number of vertices in the other partition
*
@return
a complete bipartite graph on {
@code
V1} and {
@code
V2} vertices
*
@throws
IllegalArgumentException if probability is not between 0 and 1
*/
public
static
Graph
completeBipartite
(
int
V1
,
int
V2
)
{
return
bipartite
(
V1
,
V2
,
V1
*
V2
);
}
/**
* Returns a random simple bipartite graph on {
@code
V1} and {
@code
V2} vertices
* with {
@code
E} edges.
*
@param
V1 the number of vertices in one partition
*
@param
V2 the number of vertices in the other partition
*
@param
E the number of edges
*
@return
a random simple bipartite graph on {
@code
V1} and {
@code
V2} vertices,
* containing a total of {
@code
E} edges
*
@throws
IllegalArgumentException if no such simple bipartite graph exists
*/
public
static
Graph
bipartite
(
int
V1
,
int
V2
,
int
E
)
{
if
(
E
>
(
long
)
V1
*
V2
)
throw
new
IllegalArgumentException
(
“Too many edges”
);
if
(
E
<
0
)
throw
new
IllegalArgumentException
(
"Too few edges"
);
Graph
G
=
new
Graph
(
V1
+
V2
);
int
[]
vertices
=
new
int
[
V1
+
V2
];
for
(
int
i
=
0
;
i
<
V1
+
V2
;
i
++
)
vertices
[
i
]
=
i
;
StdRandom
.
shuffle
(
vertices
);
SET
<
Edge
>
set
=
new
SET
<
Edge
>
();
while
(
G
.
E
()
<
E
)
{
int
i
=
StdRandom
.
uniform
(
V1
);
int
j
=
V1
+
StdRandom
.
uniform
(
V2
);
Edge
e
=
new
Edge
(
vertices
[
i
],
vertices
[
j
]);
if
(
!
set
.
contains
(
e
))
{
set
.
add
(
e
);
G
.
addEdge
(
vertices
[
i
],
vertices
[
j
]);
}
}
return
G
;
}
/**
* Returns a random simple bipartite graph on {
@code
V1} and {
@code
V2} vertices,
* containing each possible edge with probability {
@code
p}.
*
@param
V1 the number of vertices in one partition
*
@param
V2 the number of vertices in the other partition
*
@param
p the probability that the graph contains an edge with one endpoint in either side
*
@return
a random simple bipartite graph on {
@code
V1} and {
@code
V2} vertices,
* containing each possible edge with probability {
@code
p}
*
@throws
IllegalArgumentException if probability is not between 0 and 1
*/
public
static
Graph
bipartite
(
int
V1
,
int
V2
,
double
p
)
{
if
(
p
<
0.0
||
p
>
1.0
)
throw
new
IllegalArgumentException
(
“Probability must be between 0 and 1”
);
int
[]
vertices
=
new
int
[
V1
+
V2
];
for
(
int
i
=
0
;
i
<
V1
+
V2
;
i
++
)
vertices
[
i
]
=
i
;
StdRandom
.
shuffle
(
vertices
);
Graph
G
=
new
Graph
(
V1
+
V2
);
for
(
int
i
=
0
;
i
<
V1
;
i
++
)
for
(
int
j
=
0
;
j
<
V2
;
j
++
)
if
(
StdRandom
.
bernoulli
(
p
))
G
.
addEdge
(
vertices
[
i
],
vertices
[
V1
+
j
]);
return
G
;
}
/**
* Returns a path graph on {
@code
V} vertices.
*
@param
V the number of vertices in the path
*
@return
a path graph on {
@code
V} vertices
*/
public
static
Graph
path
(
int
V
)
{
Graph
G
=
new
Graph
(
V
);
int
[]
vertices
=
new
int
[
V
];
for
(
int
i
=
0
;
i
<
V
;
i
++
)
vertices
[
i
]
=
i
;
StdRandom
.
shuffle
(
vertices
);
for
(
int
i
=
0
;
i
<
V
-
1
;
i
++
)
{
G
.
addEdge
(
vertices
[
i
],
vertices
[
i
+
1
]);
}
return
G
;
}
/**
* Returns a complete binary tree graph on {
@code
V} vertices.
*
@param
V the number of vertices in the binary tree
*
@return
a complete binary tree graph on {
@code
V} vertices
*/
public
static
Graph
binaryTree
(
int
V
)
{
Graph
G
=
new
Graph
(
V
);
int
[]
vertices
=
new
int
[
V
];
for
(
int
i
=
0
;
i
<
V
;
i
++
)
vertices
[
i
]
=
i
;
StdRandom
.
shuffle
(
vertices
);
for
(
int
i
=
1
;
i
<
V
;
i
++
)
{
G
.
addEdge
(
vertices
[
i
],
vertices
[(
i
-
1
)
/
2
]);
}
return
G
;
}
/**
* Returns a cycle graph on {
@code
V} vertices.
*
@param
V the number of vertices in the cycle
*
@return
a cycle graph on {
@code
V} vertices
*/
public
static
Graph
cycle
(
int
V
)
{
Graph
G
=
new
Graph
(
V
);
int
[]
vertices
=
new
int
[
V
];
for
(
int
i
=
0
;
i
<
V
;
i
++
)
vertices
[
i
]
=
i
;
StdRandom
.
shuffle
(
vertices
);
for
(
int
i
=
0
;
i
<
V
-
1
;
i
++
)
{
G
.
addEdge
(
vertices
[
i
],
vertices
[
i
+
1
]);
}
G
.
addEdge
(
vertices
[
V
-
1
],
vertices
[
0
]);
return
G
;
}
/**
* Returns an Eulerian cycle graph on {
@code
V} vertices.
*
*
@param
V the number of vertices in the cycle
*
@param
E the number of edges in the cycle
*
@return
a graph that is an Eulerian cycle on {
@code
V} vertices
* and {
@code
E} edges
*
@throws
IllegalArgumentException if either {
@code
V <= 0} or {
@code
E <= 0}
*/
public
static
Graph
eulerianCycle
(
int
V
,
int
E
)
{
if
(
E
<=
0
)
throw
new
IllegalArgumentException
(
"An Eulerian cycle must have at least one edge"
);
if
(
V
<=
0
)
throw
new
IllegalArgumentException
(
"An Eulerian cycle must have at least one vertex"
);
Graph
G
=
new
Graph
(
V
);
int
[]
vertices
=
new
int
[
E
];
for
(
int
i
=
0
;
i
<
E
;
i
++
)
vertices
[
i
]
=
StdRandom
.
uniform
(
V
);
for
(
int
i
=
0
;
i
<
E
-
1
;
i
++
)
{
G
.
addEdge
(
vertices
[
i
],
vertices
[
i
+
1
]);
}
G
.
addEdge
(
vertices
[
E
-
1
],
vertices
[
0
]);
return
G
;
}
/**
* Returns an Eulerian path graph on {
@code
V} vertices.
*
*
@param
V the number of vertices in the path
*
@param
E the number of edges in the path
*
@return
a graph that is an Eulerian path on {
@code
V} vertices
* and {
@code
E} edges
*
@throws
IllegalArgumentException if either {
@code
V <= 0} or {
@code
E < 0}
*/
public
static
Graph
eulerianPath
(
int
V
,
int
E
)
{
if
(
E
<
0
)
throw
new
IllegalArgumentException
(
"negative number of edges"
);
if
(
V
<=
0
)
throw
new
IllegalArgumentException
(
"An Eulerian path must have at least one vertex"
);
Graph
G
=
new
Graph
(
V
);
int
[]
vertices
=
new
int
[
E
+
1
];
for
(
int
i
=
0
;
i
<
E
+
1
;
i
++
)
vertices
[
i
]
=
StdRandom
.
uniform
(
V
);
for
(
int
i
=
0
;
i
<
E
;
i
++
)
{
G
.
addEdge
(
vertices
[
i
],
vertices
[
i
+
1
]);
}
return
G
;
}
/**
* Returns a wheel graph on {
@code
V} vertices.
*
@param
V the number of vertices in the wheel
*
@return
a wheel graph on {
@code
V} vertices: a single vertex connected to
* every vertex in a cycle on {
@code
V-1} vertices
*/
public
static
Graph
wheel
(
int
V
)
{
if
(
V
<=
1
)
throw
new
IllegalArgumentException
(
"Number of vertices must be at least 2"
);
Graph
G
=
new
Graph
(
V
);
int
[]
vertices
=
new
int
[
V
];
for
(
int
i
=
0
;
i
<
V
;
i
++
)
vertices
[
i
]
=
i
;
StdRandom
.
shuffle
(
vertices
);
// simple cycle on V-1 vertices
for
(
int
i
=
1
;
i
<
V
-
1
;
i
++
)
{
G
.
addEdge
(
vertices
[
i
],
vertices
[
i
+
1
]);
}
G
.
addEdge
(
vertices
[
V
-
1
],
vertices
[
1
]);
// connect vertices[0] to every vertex on cycle
for
(
int
i
=
1
;
i
<
V
;
i
++
)
{
G
.
addEdge
(
vertices
[
0
],
vertices
[
i
]);
}
return
G
;
}
/**
* Returns a star graph on {
@code
V} vertices.
*
@param
V the number of vertices in the star
*
@return
a star graph on {
@code
V} vertices: a single vertex connected to
* every other vertex
*/
public
static
Graph
star
(
int
V
)
{
if
(
V
<=
0
)
throw
new
IllegalArgumentException
(
"Number of vertices must be at least 1"
);
Graph
G
=
new
Graph
(
V
);
int
[]
vertices
=
new
int
[
V
];
for
(
int
i
=
0
;
i
<
V
;
i
++
)
vertices
[
i
]
=
i
;
StdRandom
.
shuffle
(
vertices
);
// connect vertices[0] to every other vertex
for
(
int
i
=
1
;
i
<
V
;
i
++
)
{
G
.
addEdge
(
vertices
[
0
],
vertices
[
i
]);
}
return
G
;
}
/**
* Returns a uniformly random {
@code
k}-regular graph on {
@code
V} vertices
* (not necessarily simple). The graph is simple with probability only about e^(-k^2/4),
* which is tiny when k = 14.
*
*
@param
V the number of vertices in the graph
*
@param
k degree of each vertex
*
@return
a uniformly random {
@code
k}-regular graph on {
@code
V} vertices.
*/
public
static
Graph
regular
(
int
V
,
int
k
)
{
if
(
V
*
k
%
2
!=
0
)
throw
new
IllegalArgumentException
(
"Number of vertices * k must be even"
);
Graph
G
=
new
Graph
(
V
);
// create k copies of each vertex
int
[]
vertices
=
new
int
[
V
*
k
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
for
(
int
j
=
0
;
j
<
k
;
j
++
)
{
vertices
[
v
+
V
*
j
]
=
v
;
}
}
// pick a random perfect matching
StdRandom
.
shuffle
(
vertices
);
for
(
int
i
=
0
;
i
<
V
*
k
/
2
;
i
++
)
{
G
.
addEdge
(
vertices
[
2
*
i
],
vertices
[
2
*
i
+
1
]);
}
return
G
;
}
// http://www.proofwiki.org/wiki/Labeled_Tree_from_Prüfer_Sequence
// http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.36.6484&rep=rep1&type=pdf
/**
* Returns a uniformly random tree on {
@code
V} vertices.
* This algorithm uses a Prufer sequence and takes time proportional to V log V.
*
@param
V the number of vertices in the tree
*
@return
a uniformly random tree on {
@code
V} vertices
*/
public
static
Graph
tree
(
int
V
)
{
Graph
G
=
new
Graph
(
V
);
// special case
if
(
V
==
1
)
return
G
;
// Cayley’s theorem: there are V^(V-2) labeled trees on V vertices
// Prufer sequence: sequence of V-2 values between 0 and V-1
// Prufer’s proof of Cayley’s theorem: Prufer sequences are in 1-1
// with labeled trees on V vertices
int
[]
prufer
=
new
int
[
V
–
2
];
for
(
int
i
=
0
;
i
<
V
-
2
;
i
++
)
prufer
[
i
]
=
StdRandom
.
uniform
(
V
);
// degree of vertex v = 1 + number of times it appers in Prufer sequence
int
[]
degree
=
new
int
[
V
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
degree
[
v
]
=
1
;
for
(
int
i
=
0
;
i
<
V
-
2
;
i
++
)
degree
[
prufer
[
i
]]
++
;
// pq contains all vertices of degree 1
MinPQ
<
Integer
>
pq
=
new
MinPQ
<
Integer
>
();
for
(
int
v
=
0
;
v
<
V
;
v
++
)
if
(
degree
[
v
]
==
1
)
pq
.
insert
(
v
);
// repeatedly delMin() degree 1 vertex that has the minimum index
for
(
int
i
=
0
;
i
<
V
-
2
;
i
++
)
{
int
v
=
pq
.
delMin
();
G
.
addEdge
(
v
,
prufer
[
i
]);
degree
[
v
]
--
;
degree
[
prufer
[
i
]]
--
;
if
(
degree
[
prufer
[
i
]]
==
1
)
pq
.
insert
(
prufer
[
i
]);
}
G
.
addEdge
(
pq
.
delMin
(),
pq
.
delMin
());
return
G
;
}
/**
* Unit tests the {
@code
GraphGenerator} library.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
V
=
Integer
.
parseInt
(
args
[
0
]);
int
E
=
Integer
.
parseInt
(
args
[
1
]);
int
V1
=
V
/
2
;
int
V2
=
V
-
V1
;
StdOut
.
println
(
"complete graph"
);
StdOut
.
println
(
complete
(
V
));
StdOut
.
println
();
StdOut
.
println
(
"simple"
);
StdOut
.
println
(
simple
(
V
,
E
));
StdOut
.
println
();
StdOut
.
println
(
"Erdos-Renyi"
);
double
p
=
(
double
)
E
/
(
V
*
(
V
-
1
)
/
2.0
);
StdOut
.
println
(
simple
(
V
,
p
));
StdOut
.
println
();
StdOut
.
println
(
"complete bipartite"
);
StdOut
.
println
(
completeBipartite
(
V1
,
V2
));
StdOut
.
println
();
StdOut
.
println
(
"bipartite"
);
StdOut
.
println
(
bipartite
(
V1
,
V2
,
E
));
StdOut
.
println
();
StdOut
.
println
(
"Erdos Renyi bipartite"
);
double
q
=
(
double
)
E
/
(
V1
*
V2
);
StdOut
.
println
(
bipartite
(
V1
,
V2
,
q
));
StdOut
.
println
();
StdOut
.
println
(
"path"
);
StdOut
.
println
(
path
(
V
));
StdOut
.
println
();
StdOut
.
println
(
"cycle"
);
StdOut
.
println
(
cycle
(
V
));
StdOut
.
println
();
StdOut
.
println
(
"binary tree"
);
StdOut
.
println
(
binaryTree
(
V
));
StdOut
.
println
();
StdOut
.
println
(
"tree"
);
StdOut
.
println
(
tree
(
V
));
StdOut
.
println
();
StdOut
.
println
(
"4-regular"
);
StdOut
.
println
(
regular
(
V
,
4
));
StdOut
.
println
();
StdOut
.
println
(
"star"
);
StdOut
.
println
(
star
(
V
));
StdOut
.
println
();
StdOut
.
println
(
"wheel"
);
StdOut
.
println
(
wheel
(
V
));
StdOut
.
println
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Graph.java
edu/princeton/cs/algs4/Graph.java
/******************************************************************************
* Compilation: javac Graph.java
* Execution: java Graph input.txt
* Dependencies: Bag.java Stack.java In.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/41graph/tinyG.txt
* https://algs4.cs.princeton.edu/41graph/mediumG.txt
* https://algs4.cs.princeton.edu/41graph/largeG.txt
*
* A graph, implemented using an array of sets.
* Parallel edges and self-loops allowed.
*
* % java Graph tinyG.txt
* 13 vertices, 13 edges
* 0: 6 2 1 5
* 1: 0
* 2: 0
* 3: 5 4
* 4: 5 6 3
* 5: 3 4 0
* 6: 0 4
* 7: 8
* 8: 7
* 9: 11 10 12
* 10: 9
* 11: 9 12
* 12: 11 9
*
* % java Graph mediumG.txt
* 250 vertices, 1273 edges
* 0: 225 222 211 209 204 202 191 176 163 160 149 114 97 80 68 59 58 49 44 24 15
* 1: 220 203 200 194 189 164 150 130 107 72
* 2: 141 110 108 86 79 51 42 18 14
* ...
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
NoSuchElementException
;
/**
* The {
@code
Graph} class represents an undirected graph of vertices
* named 0 through V – 1.
* It supports the following two primary operations: add an edge to the graph,
* iterate over all of the vertices adjacent to a vertex. It also provides
* methods for returning the degree of a vertex, the number of vertices
* V in the graph, and the number of edges E in the graph.
* Parallel edges and self-loops are permitted.
* By convention, a self-loop v–v appears in the
* adjacency list of v twice and contributes two to the degree
* of v.
*
* This implementation uses an adjacency-lists representation, which
* is a vertex-indexed array of {
@link
Bag} objects.
* It uses Θ(E + V) space, where E is
* the number of edges and V is the number of vertices.
* All instance methods take Θ(1) time. (Though, iterating over
* the vertices returned by {
@link
#adj(int)} takes time proportional
* to the degree of the vertex.)
* Constructing an empty graph with V vertices takes
* Θ(V) time; constructing a graph with E edges
* and V vertices takes Θ(E + V) time.
*
* For additional documentation, see
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Graph
{
private
static
final
String
NEWLINE
=
System
.
getProperty
(
“line.separator”
);
private
final
int
V
;
private
int
E
;
private
Bag
<
Integer
>
[]
adj
;
/**
* Initializes an empty graph with {
@code
V} vertices and 0 edges.
* param V the number of vertices
*
*
@param
V number of vertices
*
@throws
IllegalArgumentException if {
@code
V < 0}
*/
public
Graph
(
int
V
)
{
if
(
V
<
0
)
throw
new
IllegalArgumentException
(
"Number of vertices must be nonnegative"
);
this
.
V
=
V
;
this
.
E
=
0
;
adj
=
(
Bag
<
Integer
>
[])
new
Bag
[
V
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
adj
[
v
]
=
new
Bag
<
Integer
>
();
}
}
/**
* Initializes a graph from the specified input stream.
* The format is the number of vertices V,
* followed by the number of edges E,
* followed by E pairs of vertices, with each entry separated by whitespace.
*
*
@param
in the input stream
*
@throws
IllegalArgumentException if {
@code
in} is {
@code
null}
*
@throws
IllegalArgumentException if the endpoints of any edge are not in prescribed range
*
@throws
IllegalArgumentException if the number of vertices or edges is negative
*
@throws
IllegalArgumentException if the input stream is in the wrong format
*/
public
Graph
(
In
in
)
{
if
(
in
==
null
)
throw
new
IllegalArgumentException
(
“argument is null”
);
try
{
this
.
V
=
in
.
readInt
();
if
(
V
<
0
)
throw
new
IllegalArgumentException
(
"number of vertices in a Graph must be nonnegative"
);
adj
=
(
Bag
<
Integer
>
[])
new
Bag
[
V
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
adj
[
v
]
=
new
Bag
<
Integer
>
();
}
int
E
=
in
.
readInt
();
if
(
E
<
0
)
throw
new
IllegalArgumentException
(
"number of edges in a Graph must be nonnegative"
);
for
(
int
i
=
0
;
i
<
E
;
i
++
)
{
int
v
=
in
.
readInt
();
int
w
=
in
.
readInt
();
validateVertex
(
v
);
validateVertex
(
w
);
addEdge
(
v
,
w
);
}
}
catch
(
NoSuchElementException
e
)
{
throw
new
IllegalArgumentException
(
"invalid input format in Graph constructor"
,
e
);
}
}
/**
* Initializes a new graph that is a deep copy of {
@code
G}.
*
*
@param
G the graph to copy
*
@throws
IllegalArgumentException if {
@code
G} is {
@code
null}
*/
public
Graph
(
Graph
G
)
{
this
.
V
=
G
.
V
();
this
.
E
=
G
.
E
();
if
(
V
<
0
)
throw
new
IllegalArgumentException
(
"Number of vertices must be nonnegative"
);
// update adjacency lists
adj
=
(
Bag
<
Integer
>
[])
new
Bag
[
V
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
adj
[
v
]
=
new
Bag
<
Integer
>
();
}
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
// reverse so that adjacency list is in same order as original
Stack
<
Integer
>
reverse
=
new
Stack
<
Integer
>
();
for
(
int
w
:
G
.
adj
[
v
])
{
reverse
.
push
(
w
);
}
for
(
int
w
:
reverse
)
{
adj
[
v
].
add
(
w
);
}
}
}
/**
* Returns the number of vertices in this graph.
*
*
@return
the number of vertices in this graph
*/
public
int
V
()
{
return
V
;
}
/**
* Returns the number of edges in this graph.
*
*
@return
the number of edges in this graph
*/
public
int
E
()
{
return
E
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Adds the undirected edge v-w to this graph.
*
*
@param
v one vertex in the edge
*
@param
w the other vertex in the edge
*
@throws
IllegalArgumentException unless both {
@code
0 <= v < V} and {
@code
0 <= w < V}
*/
public
void
addEdge
(
int
v
,
int
w
)
{
validateVertex
(
v
);
validateVertex
(
w
);
E
++
;
adj
[
v
].
add
(
w
);
adj
[
w
].
add
(
v
);
}
/**
* Returns the vertices adjacent to vertex {
@code
v}.
*
*
@param
v the vertex
*
@return
the vertices adjacent to vertex {
@code
v}, as an iterable
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
Iterable
<
Integer
>
adj
(
int
v
)
{
validateVertex
(
v
);
return
adj
[
v
];
}
/**
* Returns the degree of vertex {
@code
v}.
*
*
@param
v the vertex
*
@return
the degree of vertex {
@code
v}
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
int
degree
(
int
v
)
{
validateVertex
(
v
);
return
adj
[
v
].
size
();
}
/**
* Returns a string representation of this graph.
*
*
@return
the number of vertices V, followed by the number of edges E,
* followed by the V adjacency lists
*/
public
String
toString
()
{
StringBuilder
s
=
new
StringBuilder
();
s
.
append
(
V
+
” vertices, ”
+
E
+
” edges ”
+
NEWLINE
);
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
s
.
append
(
v
+
": "
);
for
(
int
w
:
adj
[
v
])
{
s
.
append
(
w
+
" "
);
}
s
.
append
(
NEWLINE
);
}
return
s
.
toString
();
}
/**
* Unit tests the {
@code
Graph} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
Graph
G
=
new
Graph
(
in
);
StdOut
.
println
(
G
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/GrayscalePicture.java
edu/princeton/cs/algs4/GrayscalePicture.java
/******************************************************************************
* Compilation: javac GrayscalePicture.java
* Execution: java GrayscalePicture imagename
* Dependencies: none
*
* Data type for manipulating individual pixels of a grayscale image. The
* original image can be read from a file in JPEG, GIF, or PNG format, or the
* user can create a blank image of a given dimension. Includes methods for
* displaying the image in a window on the screen or saving to a file.
*
* % java GrayscalePicture mandrill
*
* Remarks
* -------
* - pixel (x, y) is column x and row y, where (0, 0) is upper left
*
* - uses BufferedImage.TYPE_INT_RGB because BufferedImage.TYPE_BYTE_GRAY
* seems to do some undesirable olor correction when calling getRGB() and
* setRGB()
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
awt
.
Color
;
import
java
.
awt
.
FileDialog
;
import
java
.
awt
.
Toolkit
;
import
java
.
awt
.
event
.
ActionEvent
;
import
java
.
awt
.
event
.
ActionListener
;
import
java
.
awt
.
event
.
KeyEvent
;
import
java
.
awt
.
image
.
BufferedImage
;
import
java
.
io
.
File
;
import
java
.
io
.
IOException
;
import
java
.
net
.
URL
;
import
javax
.
imageio
.
ImageIO
;
import
javax
.
swing
.
ImageIcon
;
import
javax
.
swing
.
JFrame
;
import
javax
.
swing
.
JLabel
;
import
javax
.
swing
.
JMenu
;
import
javax
.
swing
.
JMenuBar
;
import
javax
.
swing
.
JMenuItem
;
import
javax
.
swing
.
JPanel
;
import
javax
.
swing
.
KeyStroke
;
/**
* This class provides methods for manipulating individual pixels of
* a grayscale image.
* The original image can be read from a {
@code
PNG}, {
@code
GIF},
* or {
@code
JPEG} file or the user can create a blank image of a given dimension.
* This class includes methods for displaying the image in a window on
* the screen or saving it to a file.
*
* Pixel (col, row) is column col and row row.
* By default, the origin (0, 0) is the pixel in the top-left corner,
* which is a common convention in image processing.
* The method {
@link
#setOriginLowerLeft()} change the origin to the lower left.
*
* The {
@code
get()} and {
@code
set()} methods use {
@link
Color} objects to get
* or set the color of the specified pixel. The {
@link
Color} objects are converted
* to grayscale if they have different values for the R, G, and B channels.
* The {
@code
getGrayscale()} and {
@code
setGrayscale()} methods use an
* 8-bit {
@code
int} to encode the grayscale value, thereby avoiding the need to
* create temporary {
@code
Color} objects.
*
* A W-by-H picture uses ~ 4 W H bytes of memory,
* since the color of each pixel is encoded as a 32-bit int
* (even though, in principle, only ~ W H bytes are needed).
*
* For additional documentation, see
* Section 3.1 of
* Computer Science: An Interdisciplinary Approach
* by Robert Sedgewick and Kevin Wayne.
* See {
@link
Picture} for a version that supports 32-bit RGB color images.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
GrayscalePicture
implements
ActionListener
{
private
BufferedImage
image
;
// the rasterized image
private
JFrame
frame
;
// on-screen view
private
String
filename
;
// name of file
private
boolean
isOriginUpperLeft
=
true
;
// location of origin
private
final
int
width
,
height
;
// width and height
/**
* Creates a {
@code
width}-by-{
@code
height} picture, with {
@code
width} columns
* and {
@code
height} rows, where each pixel is black.
*
*
@param
width the width of the picture
*
@param
height the height of the picture
*
@throws
IllegalArgumentException if {
@code
width} is negative
*
@throws
IllegalArgumentException if {
@code
height} is negative
*/
public
GrayscalePicture
(
int
width
,
int
height
)
{
if
(
width
<
0
)
throw
new
IllegalArgumentException
(
"width must be non-negative"
);
if
(
height
<
0
)
throw
new
IllegalArgumentException
(
"height must be non-negative"
);
this
.
width
=
width
;
this
.
height
=
height
;
image
=
new
BufferedImage
(
width
,
height
,
BufferedImage
.
TYPE_INT_RGB
);
}
/**
* Creates a new grayscale picture that is a deep copy of the argument picture.
*
*
@param
picture the picture to copy
*
@throws
IllegalArgumentException if {
@code
picture} is {
@code
null}
*/
public
GrayscalePicture
(
GrayscalePicture
picture
)
{
if
(
picture
==
null
)
throw
new
IllegalArgumentException
(
"constructor argument is null"
);
width
=
picture
.
width
();
height
=
picture
.
height
();
image
=
new
BufferedImage
(
width
,
height
,
BufferedImage
.
TYPE_INT_RGB
);
filename
=
picture
.
filename
;
isOriginUpperLeft
=
picture
.
isOriginUpperLeft
;
for
(
int
col
=
0
;
col
<
width
();
col
++
)
for
(
int
row
=
0
;
row
<
height
();
row
++
)
image
.
setRGB
(
col
,
row
,
picture
.
image
.
getRGB
(
col
,
row
));
}
/**
* Creates a grayscale picture by reading an image from a file or URL.
*
*
@param
name the name of the file ( , .gif, or ) or URL.
*
@throws
IllegalArgumentException if cannot read image
*
@throws
IllegalArgumentException if {
@code
name} is {
@code
null}
*/
public
GrayscalePicture
(
String
name
)
{
if
(
name
==
null
)
throw
new
IllegalArgumentException
(
"constructor argument is null"
);
this
.
filename
=
name
;
try
{
// try to read from file in working directory
File
file
=
new
File
(
name
);
if
(
file
.
isFile
())
{
image
=
ImageIO
.
read
(
file
);
}
else
{
// resource relative to .class file
URL url
=
getClass
().
getResource
(
name
);
// resource relative to classloader root
if
(
url
==
null
)
{
url
=
getClass
().
getClassLoader
().
getResource
(
name
);
}
// or URL from web
if
(
url
==
null
)
{
url
=
new
URL
(
name
);
}
image
=
ImageIO
.
read
(
url
);
}
if
(
image
==
null
)
{
throw
new
IllegalArgumentException
(
"could not read image: "
+
name
);
}
width
=
image
.
getWidth
(
null
);
height
=
image
.
getHeight
(
null
);
// convert to grayscale inplace
for
(
int
col
=
0
;
col
<
width
;
col
++
)
{
for
(
int
row
=
0
;
row
<
height
;
row
++
)
{
Color
color
=
new
Color
(
image
.
getRGB
(
col
,
row
));
Color
gray
=
toGray
(
color
);
image
.
setRGB
(
col
,
row
,
gray
.
getRGB
());
}
}
}
catch
(
IOException
ioe
)
{
throw
new
IllegalArgumentException
(
"could not open image: "
+
name
,
ioe
);
}
}
// Returns a grayscale version of the given color as a Color object.
private
static
Color
toGray
(
Color
color
)
{
int
r
=
color
.
getRed
();
int
g
=
color
.
getGreen
();
int
b
=
color
.
getBlue
();
int
y
=
(
int
)
(
Math
.
round
(
0.299
*
r
+
0.587
*
g
+
0.114
*
b
));
return
new
Color
(
y
,
y
,
y
);
}
/**
* Returns a {
@link
JLabel} containing this picture, for embedding in a {
@link
JPanel},
* {
@link
JFrame} or other GUI widget.
*
*
@return
the {
@code
JLabel}
*/
public
JLabel
getJLabel
()
{
if
(
image
==
null
)
return
null
;
// no image available
ImageIcon
icon
=
new
ImageIcon
(
image
);
return
new
JLabel
(
icon
);
}
/**
* Sets the origin to be the upper left pixel. This is the default.
*/
public
void
setOriginUpperLeft
()
{
isOriginUpperLeft
=
true
;
}
/**
* Sets the origin to be the lower left pixel.
*/
public
void
setOriginLowerLeft
()
{
isOriginUpperLeft
=
false
;
}
/**
* Displays the picture in a window on the screen.
*/
public
void
show
()
{
// create the GUI for viewing the image if needed
if
(
frame
==
null
)
{
frame
=
new
JFrame
();
JMenuBar
menuBar
=
new
JMenuBar
();
JMenu
menu
=
new
JMenu
(
"File"
);
menuBar
.
add
(
menu
);
JMenuItem
menuItem1
=
new
JMenuItem
(
" Save... "
);
menuItem1
.
addActionListener
(
this
);
// use getMenuShortcutKeyMaskEx() in Java 10 (getMenuShortcutKeyMask() deprecated)
menuItem1
.
setAccelerator
(
KeyStroke
.
getKeyStroke
(
KeyEvent
.
VK_S
,
Toolkit
.
getDefaultToolkit
().
getMenuShortcutKeyMask
()));
menu
.
add
(
menuItem1
);
frame
.
setJMenuBar
(
menuBar
);
frame
.
setContentPane
(
getJLabel
());
// f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame
.
setDefaultCloseOperation
(
JFrame
.
DISPOSE_ON_CLOSE
);
if
(
filename
==
null
)
frame
.
setTitle
(
width
+
"-by-"
+
height
);
else
frame
.
setTitle
(
filename
);
frame
.
setResizable
(
false
);
frame
.
pack
();
frame
.
setVisible
(
true
);
}
// draw
frame
.
repaint
();
}
/**
* Returns the height of the picture.
*
*
@return
the height of the picture (in pixels)
*/
public
int
height
()
{
return
height
;
}
/**
* Returns the width of the picture.
*
*
@return
the width of the picture (in pixels)
*/
public
int
width
()
{
return
width
;
}
private
void
validateRowIndex
(
int
row
)
{
if
(
row
<
0
||
row
>=
height
())
throw
new
IllegalArgumentException
(
“row index must be between 0 and ”
+
(
height
()
–
1
)
+
“: ”
+
row
);
}
private
void
validateColumnIndex
(
int
col
)
{
if
(
col
<
0
||
col
>=
width
())
throw
new
IllegalArgumentException
(
“column index must be between 0 and ”
+
(
width
()
–
1
)
+
“: ”
+
col
);
}
private
void
validateGrayscaleValue
(
int
gray
)
{
if
(
gray
<
0
||
gray
>=
256
)
throw
new
IllegalArgumentException
(
“grayscale value must be between 0 and 255”
);
}
/**
* Returns the grayscale value of pixel ({
@code
col}, {
@code
row}) as a {
@link
java.awt.Color}.
*
*
@param
col the column index
*
@param
row the row index
*
@return
the grayscale value of pixel ({
@code
col}, {
@code
row})
*
@throws
IllegalArgumentException unless both {
@code
0 <= col < width} and {
@code
0 <= row < height}
*/
public
Color
get
(
int
col
,
int
row
)
{
validateColumnIndex
(
col
);
validateRowIndex
(
row
);
Color
color
=
new
Color
(
image
.
getRGB
(
col
,
row
));
return
toGray
(
color
);
}
/**
* Returns the grayscale value of pixel ({
@code
col}, {
@code
row}) as an {
@code
int}
* between 0 and 255.
* Using this method can be more efficient than {
@link
#get(int, int)} because
* it does not create a {
@code
Color} object.
*
*
@param
col the column index
*
@param
row the row index
*
@return
the 8-bit integer representation of the grayscale value of pixel ({
@code
col}, {
@code
row})
*
@throws
IllegalArgumentException unless both {
@code
0 <= col < width} and {
@code
0 <= row < height}
*/
public
int
getGrayscale
(
int
col
,
int
row
)
{
validateColumnIndex
(
col
);
validateRowIndex
(
row
);
if
(
isOriginUpperLeft
)
return
image
.
getRGB
(
col
,
row
)
&
0xFF
;
else
return
image
.
getRGB
(
col
,
height
-
row
-
1
)
&
0xFF
;
}
/**
* Sets the color of pixel ({
@code
col}, {
@code
row}) to the given grayscale value.
*
*
@param
col the column index
*
@param
row the row index
*
@param
color the color (converts to grayscale if color is not a shade of gray)
*
@throws
IllegalArgumentException unless both {
@code
0 <= col < width} and {
@code
0 <= row < height}
*
@throws
IllegalArgumentException if {
@code
color} is {
@code
null}
*/
public
void
set
(
int
col
,
int
row
,
Color
color
)
{
validateColumnIndex
(
col
);
validateRowIndex
(
row
);
if
(
color
==
null
)
throw
new
IllegalArgumentException
(
"color argument is null"
);
Color
gray
=
toGray
(
color
);
image
.
setRGB
(
col
,
row
,
gray
.
getRGB
());
}
/**
* Sets the color of pixel ({
@code
col}, {
@code
row}) to the given grayscale value
* between 0 and 255.
*
*
@param
col the column index
*
@param
row the row index
*
@param
gray the 8-bit integer representation of the grayscale value
*
@throws
IllegalArgumentException unless both {
@code
0 <= col < width} and {
@code
0 <= row < height}
*/
public
void
setGrayscale
(
int
col
,
int
row
,
int
gray
)
{
validateColumnIndex
(
col
);
validateRowIndex
(
row
);
validateGrayscaleValue
(
gray
);
int
rgb
=
gray
|
(
gray
<<
8
)
|
(
gray
<<
16
);
if
(
isOriginUpperLeft
)
image
.
setRGB
(
col
,
row
,
rgb
);
else
image
.
setRGB
(
col
,
height
-
row
-
1
,
rgb
);
}
/**
* Returns true if this picture is equal to the argument picture.
*
*
@param
other the other picture
*
@return
{
@code
true} if this picture is the same dimension as {
@code
other}
* and if all pixels have the same color; {
@code
false} otherwise
*/
public
boolean
equals
(
Object
other
)
{
if
(
other
==
this
)
return
true
;
if
(
other
==
null
)
return
false
;
if
(
other
.
getClass
()
!=
this
.
getClass
())
return
false
;
GrayscalePicture
that
=
(
GrayscalePicture
)
other
;
if
(
this
.
width
()
!=
that
.
width
())
return
false
;
if
(
this
.
height
()
!=
that
.
height
())
return
false
;
for
(
int
col
=
0
;
col
<
width
();
col
++
)
for
(
int
row
=
0
;
row
<
height
();
row
++
)
if
(
this
.
getGrayscale
(
col
,
row
)
!=
that
.
getGrayscale
(
col
,
row
))
return
false
;
return
true
;
}
/**
* Returns a string representation of this picture.
* The result is a width
-by-height
matrix of pixels,
* where the grayscale value of a pixel is an integer between 0 and 255.
*
*
@return
a string representation of this picture
*/
public
String
toString
()
{
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
width
+
“-by-”
+
height
+
” grayscale picture (grayscale values given in hex)\n”
);
for
(
int
row
=
0
;
row
<
height
;
row
++
)
{
for
(
int
col
=
0
;
col
<
width
;
col
++
)
{
int
gray
=
0
;
if
(
isOriginUpperLeft
)
gray
=
0xFF
&
image
.
getRGB
(
col
,
row
);
else
gray
=
0xFF
&
image
.
getRGB
(
col
,
height
-
row
-
1
);
sb
.
append
(
String
.
format
(
"%3d "
,
gray
));
}
sb
.
append
(
"\n"
);
}
return
sb
.
toString
().
trim
();
}
/**
* This operation is not supported because pictures are mutable.
*
*
@return
does not return a value
*
@throws
UnsupportedOperationException if called
*/
public
int
hashCode
()
{
throw
new
UnsupportedOperationException
(
"hashCode() is not supported because pictures are mutable"
);
}
/**
* Saves the picture to a file in either PNG or JPEG format.
* The filetype extension must be either or .
*
*
@param
name the name of the file
*
@throws
IllegalArgumentException if {
@code
name} is {
@code
null}
*/
public
void
save
(
String
name
)
{
if
(
name
==
null
)
throw
new
IllegalArgumentException
(
"argument to save() is null"
);
save
(
new
File
(
name
));
filename
=
name
;
}
/**
* Saves the picture to a file in a PNG or JPEG image format.
*
*
@param
file the file
*
@throws
IllegalArgumentException if {
@code
file} is {
@code
null}
*/
public
void
save
(
File
file
)
{
if
(
file
==
null
)
throw
new
IllegalArgumentException
(
"argument to save() is null"
);
filename
=
file
.
getName
();
if
(
frame
!=
null
)
frame
.
setTitle
(
filename
);
String
suffix
=
filename
.
substring
(
filename
.
lastIndexOf
(
'.'
)
+
1
);
if
(
"jpg"
.
equalsIgnoreCase
(
suffix
)
||
"png"
.
equalsIgnoreCase
(
suffix
))
{
try
{
ImageIO
.
write
(
image
,
suffix
,
file
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
else
{
System
.
out
.
println
(
"Error: filename must end in or "
);
}
}
/**
* Opens a save dialog box when the user selects "Save As" from the menu.
*/
@
Override
public
void
actionPerformed
(
ActionEvent
e
)
{
FileDialog
chooser
=
new
FileDialog
(
frame
,
"Use a or extension"
,
FileDialog
.
SAVE
);
chooser
.
setVisible
(
true
);
if
(
chooser
.
getFile
()
!=
null
)
{
save
(
chooser
.
getDirectory
()
+
File
.
separator
+
chooser
.
getFile
());
}
}
/**
* Unit tests this {
@code
Picture} data type.
* Reads a picture specified by the command-line argument,
* and shows it in a window on the screen.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
GrayscalePicture
picture
=
new
GrayscalePicture
(
args
[
0
]);
StdOut
.
printf
(
"%d-by-%d\n"
,
picture
.
width
(),
picture
.
height
());
GrayscalePicture
copy
=
new
GrayscalePicture
(
picture
);
picture
.
show
();
copy
.
show
();
while
(
!
StdIn
.
isEmpty
())
{
int
row
=
StdIn
.
readInt
();
int
col
=
StdIn
.
readInt
();
int
gray
=
StdIn
.
readInt
();
picture
.
setGrayscale
(
row
,
col
,
gray
);
StdOut
.
println
(
picture
.
get
(
row
,
col
));
StdOut
.
println
(
picture
.
getGrayscale
(
row
,
col
));
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/GREP.java
edu/princeton/cs/algs4/GREP.java
/******************************************************************************
* Compilation: javac GREP.java
* Execution: java GREP regexp < input.txt
* Dependencies: NFA.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/54regexp/tinyL.txt
*
* This program takes an RE as a command-line argument and prints
* the lines from standard input having some substring that
* is in the language described by the RE.
*
* % more tinyL.txt
* AC
* AD
* AAA
* ABD
* ADD
* BCD
* ABCCBD
* BABAAA
* BABBAAA
*
* % java GREP "(A*B|AC)D" < tinyL.txt
* ABD
* ABCCBD
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
GREP} class provides a client for reading in a sequence of
* lines from standard input and printing to standard output those lines
* that contain a substring matching a specified regular expression.
*
* For additional documentation, see Section 3.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
GREP
{
// do not instantiate
private
GREP
()
{
}
/**
* Interprets the command-line argument as a regular expression
* (supporting closure, binary or, parentheses, and wildcard)
* reads in lines from standard input; writes to standard output
* those lines that contain a substring matching the regular
* expression.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
regexp
=
“(.*”
+
args
[
0
]
+
“.*)”
;
NFA nfa
=
new
NFA
(
regexp
);
while
(
StdIn
.
hasNextLine
())
{
String
line
=
StdIn
.
readLine
();
if
(
nfa
.
recognizes
(
line
))
{
StdOut
.
println
(
line
);
}
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Heap.java
edu/princeton/cs/algs4/Heap.java
/******************************************************************************
* Compilation: javac Heap.java
* Execution: java Heap < input.txt * Dependencies: StdOut.java StdIn.java * Data files: https://algs4.cs.princeton.edu/24pq/tiny.txt * https://algs4.cs.princeton.edu/24pq/words3.txt * * Sorts a sequence of strings from standard input using heapsort. * * % more tiny.txt * S O R T E X A M P L E * * % java Heap < tiny.txt * A E E L M O P R S T X [ one string per line ] * * % more words3.txt * bed bug dad yes zoo ... all bad yet * * % java Heap < words3.txt * all bad bed bug dad ... yes yet zoo [ one string per line ] * ******************************************************************************/ package edu . princeton . cs . algs4 ; /** * The { @code Heap} class provides a static method to sort an array * using heapsort.
*
* This implementation takes Θ(n log n) time
* to sort any array of length n (assuming comparisons
* take constant time). It makes at most
* 2 n log2 n compares.
*
* This sorting algorithm is not stable.
* It uses Θ(1) extra memory (not including the input array).
*
* For additional documentation, see
* Section 2.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Heap
{
// This class should not be instantiated.
private
Heap
()
{
}
/**
* Rearranges the array in ascending order, using the natural order.
*
@param
pq the array to be sorted
*/
public
static
void
sort
(
Comparable
[]
pq
)
{
int
n
=
pq
.
length
;
for
(
int
k
=
n
/
2
;
k
>=
1
;
k
—
)
sink
(
pq
,
k
,
n
);
while
(
n
>
1
)
{
exch
(
pq
,
1
,
n
—
);
sink
(
pq
,
1
,
n
);
}
}
/***************************************************************************
* Helper functions to restore the heap invariant.
***************************************************************************/
private
static
void
sink
(
Comparable
[]
pq
,
int
k
,
int
n
)
{
while
(
2
*
k
<=
n
)
{
int
j
=
2
*
k
;
if
(
j
<
n
&&
less
(
pq
,
j
,
j
+
1
))
j
++
;
if
(
!
less
(
pq
,
k
,
j
))
break
;
exch
(
pq
,
k
,
j
);
k
=
j
;
}
}
/***************************************************************************
* Helper functions for comparisons and swaps.
* Indices are "off-by-one" to support 1-based indexing.
***************************************************************************/
private
static
boolean
less
(
Comparable
[]
pq
,
int
i
,
int
j
)
{
return
pq
[
i
-
1
].
compareTo
(
pq
[
j
-
1
])
<
0
;
}
private
static
void
exch
(
Object
[]
pq
,
int
i
,
int
j
)
{
Object
swap
=
pq
[
i
-
1
];
pq
[
i
-
1
]
=
pq
[
j
-
1
];
pq
[
j
-
1
]
=
swap
;
}
// print array to standard output
private
static
void
show
(
Comparable
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
StdOut
.
println
(
a
[
i
]);
}
}
/**
* Reads in a sequence of strings from standard input; heapsorts them;
* and prints them to standard output in ascending order.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
[]
a
=
StdIn
.
readAllStrings
();
Heap
.
sort
(
a
);
show
(
a
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/HexDump.java
edu/princeton/cs/algs4/HexDump.java
/******************************************************************************
* Compilation: javac HexDump.java
* Execution: java HexDump < file
* Dependencies: BinaryStdIn.java StdOut.java
* Data file: https://algs4.cs.princeton.edu/55compression/abra.txt
*
* Reads in a binary file and writes out the bytes in hex, 16 per line.
*
* % more abra.txt
* ABRACADABRA!
*
* % java HexDump 16 < abra.txt
* 41 42 52 41 43 41 44 41 42 52 41 21
* 96 bits
*
*
* Remark
* --------------------------
* - Similar to the Unix utilities od (octal dump) or hexdump (hexadecimal dump).
*
* % od -t x1 < abra.txt
* 0000000 41 42 52 41 43 41 44 41 42 52 41 21
* 0000014
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
HexDump} class provides a client for displaying the contents
* of a binary file in hexadecimal.
*
* For additional documentation,
* see Section 5.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* See also {
@link
BinaryDump} and {
@link
PictureDump}.
* For more full-featured versions, see the Unix utilities
* {
@code
od} (octal dump) and {
@code
hexdump} (hexadecimal dump).
*
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
HexDump
{
// Do not instantiate.
private
HexDump
()
{
}
/**
* Reads in a sequence of bytes from standard input and writes
* them to standard output using hexademical notation, k hex digits
* per line, where k is given as a command-line integer (defaults
* to 16 if no integer is specified); also writes the number
* of bits.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
bytesPerLine
=
16
;
if
(
args
.
length
==
1
)
{
bytesPerLine
=
Integer
.
parseInt
(
args
[
0
]);
}
int
i
;
for
(
i
=
0
;
!
BinaryStdIn
.
isEmpty
();
i
++
)
{
if
(
bytesPerLine
==
0
)
{
BinaryStdIn
.
readChar
();
continue
;
}
if
(
i
==
0
)
StdOut
.
printf
(
“”
);
else
if
(
i
%
bytesPerLine
==
0
)
StdOut
.
printf
(
“\n”
,
i
);
else
StdOut
.
print
(
” ”
);
char
c
=
BinaryStdIn
.
readChar
();
StdOut
.
printf
(
“%02x”
,
c
&
0xff
);
}
if
(
bytesPerLine
!=
0
)
StdOut
.
println
();
StdOut
.
println
((
i
*
8
)
+
” bits”
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/HopcroftKarp.java
edu/princeton/cs/algs4/HopcroftKarp.java
/******************************************************************************
* Compilation: javac HopcroftKarp.java
* Execution: java HopcroftKarp V1 V2 E
* Dependencies: FordFulkerson.java FlowNetwork.java FlowEdge.java
* BipartiteX.java
*
* Find a maximum cardinality matching (and minimum cardinality vertex cover)
* in a bipartite graph using Hopcroft-Karp algorithm.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Iterator
;
/**
* The {
@code
HopcroftKarp} class represents a data type for computing a
* maximum (cardinality) matching and a
* minimum (cardinality) vertex cover in a bipartite graph.
* A bipartite graph in a graph whose vertices can be partitioned
* into two disjoint sets such that every edge has one endpoint in either set.
* A matching in a graph is a subset of its edges with no common
* vertices. A maximum matching is a matching with the maximum number
* of edges.
* A perfect matching is a matching which matches all vertices in the graph.
* A vertex cover in a graph is a subset of its vertices such that
* every edge is incident to at least one vertex. A minimum vertex cover
* is a vertex cover with the minimum number of vertices.
* By Konig’s theorem, in any biparite
* graph, the maximum number of edges in matching equals the minimum number
* of vertices in a vertex cover.
* The maximum matching problem in nonbipartite graphs is
* also important, but all known algorithms for this more general problem
* are substantially more complicated.
*
* This implementation uses the Hopcroft-Karp algorithm.
* The order of growth of the running time in the worst case is
* (E + V) sqrt(V),
* where E is the number of edges and V is the number
* of vertices in the graph. It uses extra space (not including the graph)
* proportional to V.
*
* See also {
@link
BipartiteMatching}, which solves the problem in
* O(E V) time using the alternating path algorithm
* and BipartiteMatchingToMaxflow,
* which solves the problem in O(E V) time via a reduction
* to the maxflow problem.
*
* For additional documentation, see
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
HopcroftKarp
{
private
static
final
int
UNMATCHED
=
–
1
;
private
final
int
V
;
// number of vertices in the graph
private
BipartiteX
bipartition
;
// the bipartition
private
int
cardinality
;
// cardinality of current matching
private
int
[]
mate
;
// mate[v] = w if v-w is an edge in current matching
// = -1 if v is not in current matching
private
boolean
[]
inMinVertexCover
;
// inMinVertexCover[v] = true iff v is in min vertex cover
private
boolean
[]
marked
;
// marked[v] = true iff v is reachable via alternating path
private
int
[]
distTo
;
// distTo[v] = number of edges on shortest path to v
/**
* Determines a maximum matching (and a minimum vertex cover)
* in a bipartite graph.
*
*
@param
G the bipartite graph
*
@throws
IllegalArgumentException if {
@code
G} is not bipartite
*/
public
HopcroftKarp
(
Graph
G
)
{
bipartition
=
new
BipartiteX
(
G
);
if
(
!
bipartition
.
isBipartite
())
{
throw
new
IllegalArgumentException
(
“graph is not bipartite”
);
}
// initialize empty matching
this
.
V
=
G
.
V
();
mate
=
new
int
[
V
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
mate
[
v
]
=
UNMATCHED
;
// the call to hasAugmentingPath() provides enough info to reconstruct level graph
while
(
hasAugmentingPath
(
G
))
{
// to be able to iterate over each adjacency list, keeping track of which
// vertex in each adjacency list needs to be explored next
Iterator
<
Integer
>
[]
adj
=
(
Iterator
<
Integer
>
[])
new
Iterator
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
adj
[
v
]
=
G
.
adj
(
v
).
iterator
();
// for each unmatched vertex s on one side of bipartition
for
(
int
s
=
0
;
s
<
V
;
s
++
)
{
if
(
isMatched
(
s
)
||
!
bipartition
.
color
(
s
))
continue
;
// or use distTo[s] == 0
// find augmenting path from s using nonrecursive DFS
Stack
<
Integer
>
path
=
new
Stack
<
Integer
>
();
path
.
push
(
s
);
while
(
!
path
.
isEmpty
())
{
int
v
=
path
.
peek
();
// retreat, no more edges in level graph leaving v
if
(
!
adj
[
v
].
hasNext
())
path
.
pop
();
// advance
else
{
// process edge v-w only if it is an edge in level graph
int
w
=
adj
[
v
].
next
();
if
(
!
isLevelGraphEdge
(
v
,
w
))
continue
;
// add w to augmenting path
path
.
push
(
w
);
// augmenting path found: update the matching
if
(
!
isMatched
(
w
))
{
// StdOut.println(“augmenting path: ” + toString(path));
while
(
!
path
.
isEmpty
())
{
int
x
=
path
.
pop
();
int
y
=
path
.
pop
();
mate
[
x
]
=
y
;
mate
[
y
]
=
x
;
}
cardinality
++
;
}
}
}
}
}
// also find a min vertex cover
inMinVertexCover
=
new
boolean
[
V
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
if
(
bipartition
.
color
(
v
)
&&
!
marked
[
v
])
inMinVertexCover
[
v
]
=
true
;
if
(
!
bipartition
.
color
(
v
)
&&
marked
[
v
])
inMinVertexCover
[
v
]
=
true
;
}
assert
certifySolution
(
G
);
}
// string representation of augmenting path (chop off last vertex)
private
static
String
toString
(
Iterable
<
Integer
>
path
)
{
StringBuilder
sb
=
new
StringBuilder
();
for
(
int
v
:
path
)
sb
.
append
(
v
+
“-”
);
String
s
=
sb
.
toString
();
s
=
s
.
substring
(
0
,
s
.
lastIndexOf
(
‘-‘
));
return
s
;
}
// is the edge v-w in the level graph?
private
boolean
isLevelGraphEdge
(
int
v
,
int
w
)
{
return
(
distTo
[
w
]
==
distTo
[
v
]
+
1
)
&&
isResidualGraphEdge
(
v
,
w
);
}
// is the edge v-w a forward edge not in the matching or a reverse edge in the matching?
private
boolean
isResidualGraphEdge
(
int
v
,
int
w
)
{
if
((
mate
[
v
]
!=
w
)
&&
bipartition
.
color
(
v
))
return
true
;
if
((
mate
[
v
]
==
w
)
&&
!
bipartition
.
color
(
v
))
return
true
;
return
false
;
}
/*
* is there an augmenting path?
* – if so, upon termination adj[] contains the level graph;
* – if not, upon termination marked[] specifies those vertices reachable via an alternating
* path from one side of the bipartition
*
* an alternating path is a path whose edges belong alternately to the matching and not
* to the matching
*
* an augmenting path is an alternating path that starts and ends at unmatched vertices
*/
private
boolean
hasAugmentingPath
(
Graph
G
)
{
// shortest path distances
marked
=
new
boolean
[
V
];
distTo
=
new
int
[
V
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
distTo
[
v
]
=
Integer
.
MAX_VALUE
;
// breadth-first search (starting from all unmatched vertices on one side of bipartition)
Queue
<
Integer
>
queue
=
new
Queue
<
Integer
>
();
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
if
(
bipartition
.
color
(
v
)
&&
!
isMatched
(
v
))
{
queue
.
enqueue
(
v
);
marked
[
v
]
=
true
;
distTo
[
v
]
=
0
;
}
}
// run BFS until an augmenting path is found
// (and keep going until all vertices at that distance are explored)
boolean
hasAugmentingPath
=
false
;
while
(
!
queue
.
isEmpty
())
{
int
v
=
queue
.
dequeue
();
for
(
int
w
:
G
.
adj
(
v
))
{
// forward edge not in matching or backwards edge in matching
if
(
isResidualGraphEdge
(
v
,
w
))
{
if
(
!
marked
[
w
])
{
distTo
[
w
]
=
distTo
[
v
]
+
1
;
marked
[
w
]
=
true
;
if
(
!
isMatched
(
w
))
hasAugmentingPath
=
true
;
// stop enqueuing vertices once an alternating path has been discovered
// (no vertex on same side will be marked if its shortest path distance longer)
if
(
!
hasAugmentingPath
)
queue
.
enqueue
(
w
);
}
}
}
}
return
hasAugmentingPath
;
}
/**
* Returns the vertex to which the specified vertex is matched in
* the maximum matching computed by the algorithm.
*
*
@param
v the vertex
*
@return
the vertex to which vertex {
@code
v} is matched in the
* maximum matching; {
@code
-1} if the vertex is not matched
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*
*/
public
int
mate
(
int
v
)
{
validate
(
v
);
return
mate
[
v
];
}
/**
* Returns true if the specified vertex is matched in the maximum matching
* computed by the algorithm.
*
*
@param
v the vertex
*
@return
{
@code
true} if vertex {
@code
v} is matched in maximum matching;
* {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*
*/
public
boolean
isMatched
(
int
v
)
{
validate
(
v
);
return
mate
[
v
]
!=
UNMATCHED
;
}
/**
* Returns the number of edges in any maximum matching.
*
*
@return
the number of edges in any maximum matching
*/
public
int
size
()
{
return
cardinality
;
}
/**
* Returns true if the graph contains a perfect matching.
* That is, the number of edges in a maximum matching is equal to one half
* of the number of vertices in the graph (so that every vertex is matched).
*
*
@return
{
@code
true} if the graph contains a perfect matching;
* {
@code
false} otherwise
*/
public
boolean
isPerfect
()
{
return
cardinality
*
2
==
V
;
}
/**
* Returns true if the specified vertex is in the minimum vertex cover
* computed by the algorithm.
*
*
@param
v the vertex
*
@return
{
@code
true} if vertex {
@code
v} is in the minimum vertex cover;
* {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
boolean
inMinVertexCover
(
int
v
)
{
validate
(
v
);
return
inMinVertexCover
[
v
];
}
// throw an exception if vertex is invalid
private
void
validate
(
int
v
)
{
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**************************************************************************
*
* The code below is solely for testing correctness of the data type.
*
**************************************************************************/
// check that mate[] and inVertexCover[] define a max matching and min vertex cover, respectively
private
boolean
certifySolution
(
Graph
G
)
{
// check that mate(v) = w iff mate(w) = v
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
if
(
mate
(
v
)
==
-
1
)
continue
;
if
(
mate
(
mate
(
v
))
!=
v
)
return
false
;
}
// check that size() is consistent with mate()
int
matchedVertices
=
0
;
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
if
(
mate
(
v
)
!=
-
1
)
matchedVertices
++
;
}
if
(
2
*
size
()
!=
matchedVertices
)
return
false
;
// check that size() is consistent with minVertexCover()
int
sizeOfMinVertexCover
=
0
;
for
(
int
v
=
0
;
v
<
V
;
v
++
)
if
(
inMinVertexCover
(
v
))
sizeOfMinVertexCover
++
;
if
(
size
()
!=
sizeOfMinVertexCover
)
return
false
;
// check that mate() uses each vertex at most once
boolean
[]
isMatched
=
new
boolean
[
V
];
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
int
w
=
mate
[
v
];
if
(
w
==
-
1
)
continue
;
if
(
v
==
w
)
return
false
;
if
(
v
>=
w
)
continue
;
if
(
isMatched
[
v
]
||
isMatched
[
w
])
return
false
;
isMatched
[
v
]
=
true
;
isMatched
[
w
]
=
true
;
}
// check that mate() uses only edges that appear in the graph
for
(
int
v
=
0
;
v
<
V
;
v
++
)
{
if
(
mate
(
v
)
==
-
1
)
continue
;
boolean
isEdge
=
false
;
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
mate
(
v
)
==
w
)
isEdge
=
true
;
}
if
(
!
isEdge
)
return
false
;
}
// check that inMinVertexCover() is a vertex cover
for
(
int
v
=
0
;
v
<
V
;
v
++
)
for
(
int
w
:
G
.
adj
(
v
))
if
(
!
inMinVertexCover
(
v
)
&&
!
inMinVertexCover
(
w
))
return
false
;
return
true
;
}
/**
* Unit tests the {
@code
HopcroftKarp} data type.
* Takes three command-line arguments {
@code
V1}, {
@code
V2}, and {
@code
E};
* creates a random bipartite graph with {
@code
V1} + {
@code
V2} vertices
* and {
@code
E} edges; computes a maximum matching and minimum vertex cover;
* and prints the results.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
V1
=
Integer
.
parseInt
(
args
[
0
]);
int
V2
=
Integer
.
parseInt
(
args
[
1
]);
int
E
=
Integer
.
parseInt
(
args
[
2
]);
Graph
G
=
GraphGenerator
.
bipartite
(
V1
,
V2
,
E
);
if
(
G
.
V
()
<
1000
)
StdOut
.
println
(
G
);
HopcroftKarp
matching
=
new
HopcroftKarp
(
G
);
// print maximum matching
StdOut
.
printf
(
"Number of edges in max matching = %d\n"
,
matching
.
size
());
StdOut
.
printf
(
"Number of vertices in min vertex cover = %d\n"
,
matching
.
size
());
StdOut
.
printf
(
"Graph has a perfect matching = %b\n"
,
matching
.
isPerfect
());
StdOut
.
println
();
if
(
G
.
V
()
>=
1000
)
return
;
StdOut
.
print
(
“Max matching: ”
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
int
w
=
matching
.
mate
(
v
);
if
(
matching
.
isMatched
(
v
)
&&
v
<
w
)
// print each edge only once
StdOut
.
print
(
v
+
"-"
+
w
+
" "
);
}
StdOut
.
println
();
// print minimum vertex cover
StdOut
.
print
(
"Min vertex cover: "
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
matching
.
inMinVertexCover
(
v
))
StdOut
.
print
(
v
+
" "
);
StdOut
.
println
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Huffman.java
edu/princeton/cs/algs4/Huffman.java
/******************************************************************************
* Compilation: javac Huffman.java
* Execution: java Huffman - < input.txt (compress)
* Execution: java Huffman + < input.txt (expand)
* Dependencies: BinaryIn.java BinaryOut.java
* Data files: https://algs4.cs.princeton.edu/55compression/abra.txt
* https://algs4.cs.princeton.edu/55compression/tinytinyTale.txt
* https://algs4.cs.princeton.edu/55compression/medTale.txt
* https://algs4.cs.princeton.edu/55compression/tale.txt
*
* Compress or expand a binary input stream using the Huffman algorithm.
*
* % java Huffman - < abra.txt | java BinaryDump 60
* 010100000100101000100010010000110100001101010100101010000100
* 000000000000000000000000000110001111100101101000111110010100
* 120 bits
*
* % java Huffman - < abra.txt | java Huffman +
* ABRACADABRA!
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Huffman} class provides static methods for compressing
* and expanding a binary input using Huffman codes over the 8-bit extended
* ASCII alphabet.
*
* For additional documentation,
* see Section 5.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Huffman
{
// alphabet size of extended ASCII
private
static
final
int
R
=
256
;
// Do not instantiate.
private
Huffman
()
{
}
// Huffman trie node
private
static
class
Node
implements
Comparable
<
Node
>
{
private
final
char
ch
;
private
final
int
freq
;
private
final
Node
left
,
right
;
Node
(
char
ch
,
int
freq
,
Node
left
,
Node
right
)
{
this
.
ch
=
ch
;
this
.
freq
=
freq
;
this
.
left
=
left
;
this
.
right
=
right
;
}
// is the node a leaf node?
private
boolean
isLeaf
()
{
assert
((
left
==
null
)
&&
(
right
==
null
))
||
((
left
!=
null
)
&&
(
right
!=
null
));
return
(
left
==
null
)
&&
(
right
==
null
);
}
// compare, based on frequency
public
int
compareTo
(
Node
that
)
{
return
this
.
freq
–
that
.
freq
;
}
}
/**
* Reads a sequence of 8-bit bytes from standard input; compresses them
* using Huffman codes with an 8-bit alphabet; and writes the results
* to standard output.
*/
public
static
void
compress
()
{
// read the input
String
s
=
BinaryStdIn
.
readString
();
char
[]
input
=
s
.
toCharArray
();
// tabulate frequency counts
int
[]
freq
=
new
int
[
R
];
for
(
int
i
=
0
;
i
<
input
.
length
;
i
++
)
freq
[
input
[
i
]]
++
;
// build Huffman trie
Node
root
=
buildTrie
(
freq
);
// build code table
String
[]
st
=
new
String
[
R
];
buildCode
(
st
,
root
,
""
);
// print trie for decoder
writeTrie
(
root
);
// print number of bytes in original uncompressed message
BinaryStdOut
.
write
(
input
.
length
);
// use Huffman code to encode input
for
(
int
i
=
0
;
i
<
input
.
length
;
i
++
)
{
String
code
=
st
[
input
[
i
]];
for
(
int
j
=
0
;
j
<
code
.
length
();
j
++
)
{
if
(
code
.
charAt
(
j
)
==
'0'
)
{
BinaryStdOut
.
write
(
false
);
}
else
if
(
code
.
charAt
(
j
)
==
'1'
)
{
BinaryStdOut
.
write
(
true
);
}
else
throw
new
IllegalStateException
(
"Illegal state"
);
}
}
// close output stream
BinaryStdOut
.
close
();
}
// build the Huffman trie given frequencies
private
static
Node
buildTrie
(
int
[]
freq
)
{
// initialze priority queue with singleton trees
MinPQ
<
Node
>
pq
=
new
MinPQ
<
Node
>
();
for
(
char
c
=
0
;
c
<
R
;
c
++
)
if
(
freq
[
c
]
>
0
)
pq
.
insert
(
new
Node
(
c
,
freq
[
c
],
null
,
null
));
// merge two smallest trees
while
(
pq
.
size
()
>
1
)
{
Node
left
=
pq
.
delMin
();
Node
right
=
pq
.
delMin
();
Node
parent
=
new
Node
(
‘\0’
,
left
.
freq
+
right
.
freq
,
left
,
right
);
pq
.
insert
(
parent
);
}
return
pq
.
delMin
();
}
// write bitstring-encoded trie to standard output
private
static
void
writeTrie
(
Node
x
)
{
if
(
x
.
isLeaf
())
{
BinaryStdOut
.
write
(
true
);
BinaryStdOut
.
write
(
x
.
ch
,
8
);
return
;
}
BinaryStdOut
.
write
(
false
);
writeTrie
(
x
.
left
);
writeTrie
(
x
.
right
);
}
// make a lookup table from symbols and their encodings
private
static
void
buildCode
(
String
[]
st
,
Node
x
,
String
s
)
{
if
(
!
x
.
isLeaf
())
{
buildCode
(
st
,
x
.
left
,
s
+
‘0’
);
buildCode
(
st
,
x
.
right
,
s
+
‘1’
);
}
else
{
st
[
x
.
ch
]
=
s
;
}
}
/**
* Reads a sequence of bits that represents a Huffman-compressed message from
* standard input; expands them; and writes the results to standard output.
*/
public
static
void
expand
()
{
// read in Huffman trie from input stream
Node
root
=
readTrie
();
// number of bytes to write
int
length
=
BinaryStdIn
.
readInt
();
// decode using the Huffman trie
for
(
int
i
=
0
;
i
<
length
;
i
++
)
{
Node
x
=
root
;
while
(
!
x
.
isLeaf
())
{
boolean
bit
=
BinaryStdIn
.
readBoolean
();
if
(
bit
)
x
=
x
.
right
;
else
x
=
x
.
left
;
}
BinaryStdOut
.
write
(
x
.
ch
,
8
);
}
BinaryStdOut
.
close
();
}
private
static
Node
readTrie
()
{
boolean
isLeaf
=
BinaryStdIn
.
readBoolean
();
if
(
isLeaf
)
{
return
new
Node
(
BinaryStdIn
.
readChar
(),
-
1
,
null
,
null
);
}
else
{
return
new
Node
(
'\0'
,
-
1
,
readTrie
(),
readTrie
());
}
}
/**
* Sample client that calls {
@code
compress()} if the command-line
* argument is "-" an {
@code
expand()} if it is "+".
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
if
(
args
[
0
].
equals
(
"-"
))
compress
();
else
if
(
args
[
0
].
equals
(
"+"
))
expand
();
else
throw
new
IllegalArgumentException
(
"Illegal command line argument"
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/IndexBinomialMinPQ.java
edu/princeton/cs/algs4/IndexBinomialMinPQ.java
/******************************************************************************
* Compilation: javac IndexBinomialMinPQ.java
* Execution:
*
* An index binomial heap.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Comparator
;
import
java
.
util
.
Iterator
;
import
java
.
util
.
NoSuchElementException
;
/**
* The IndexBinomialMinPQ class represents an indexed priority queue of generic keys.
* It supports the usual insert and delete-the-minimum operations,
* along with delete and change-the-key methods.
* In order to let the client refer to keys on the priority queue,
* an integer between 0 and N-1 is associated with each key ; the client
* uses this integer to specify which key to delete or change.
* It also supports methods for peeking at the minimum key,
* testing if the priority queue is empty, and iterating through
* the keys.
*
* This implementation uses a binomial heap along with an array to associate
* keys with integers in the given range.
* The insert, delete-the-minimum, delete, change-key, decrease-key,
* increase-key and size operations take logarithmic time.
* The is-empty, min-index, min-key, and key-of operations take constant time.
* Construction takes time proportional to the specified capacity.
*
*
@author
Tristan Claverie
*/
public
class
IndexBinomialMinPQ
<
Key
>
implements
Iterable
<
Integer
>
{
private
Node
<
Key
>
head
;
//Head of the list of roots
private
Node
<
Key
>
[]
nodes
;
//Array of indexed Nodes of the heap
private
int
n
;
//Maximum size of the tree
private
final
Comparator
<
Key
>
comparator
;
//Comparator over the keys
//Represents a node of a Binomial Tree
private
class
Node
<
Key
>
{
Key
key
;
//Key contained by the Node
int
order
;
//The order of the Binomial Tree rooted by this Node
int
index
;
//Index associated with the Key
Node
<
Key
>
parent
;
//parent of this Node
Node
<
Key
>
child
,
sibling
;
//child and sibling of this Node
}
/**
* Initializes an empty indexed priority queue with indices between {
@code
0} to {
@code
N-1}
* Worst case is O(n)
*
@param
N number of keys in the priority queue, index from {
@code
0} to {
@code
N-1}
*
@throws
java.lang.IllegalArgumentException if {
@code
N < 0}
*/
public
IndexBinomialMinPQ
(
int
N
)
{
if
(
N
<
0
)
throw
new
IllegalArgumentException
(
"Cannot create a priority queue of negative size"
);
comparator
=
new
MyComparator
();
nodes
=
(
Node
<
Key
>
[])
new
Node
[
N
];
this
.
n
=
N
;
}
/**
* Initializes an empty indexed priority queue with indices between {
@code
0} to {
@code
N-1}
* Worst case is O(n)
*
@param
N number of keys in the priority queue, index from {
@code
0} to {
@code
N-1}
*
@param
comparator a Comparator over the keys
*
@throws
java.lang.IllegalArgumentException if {
@code
N < 0}
*/
public
IndexBinomialMinPQ
(
int
N
,
Comparator
<
Key
>
comparator
)
{
if
(
N
<
0
)
throw
new
IllegalArgumentException
(
"Cannot create a priority queue of negative size"
);
this
.
comparator
=
comparator
;
nodes
=
(
Node
<
Key
>
[])
new
Node
[
N
];
this
.
n
=
N
;
}
/**
* Whether the priority queue is empty
* Worst case is O(1)
*
@return
true if the priority queue is empty, false if not
*/
public
boolean
isEmpty
()
{
return
head
==
null
;
}
/**
* Does the priority queue contains the index i ?
* Worst case is O(1)
*
@param
i an index
*
@throws
java.lang.IllegalArgumentException if the specified index is invalid
*
@return
true if i is on the priority queue, false if not
*/
public
boolean
contains
(
int
i
)
{
if
(
i
<
0
||
i
>=
n
)
throw
new
IllegalArgumentException
();
else
return
nodes
[
i
]
!=
null
;
}
/**
* Number of elements currently on the priority queue
* Worst case is O(log(n))
*
@return
the number of elements on the priority queue
*/
public
int
size
()
{
int
result
=
0
,
tmp
;
for
(
Node
<
Key
>
node
=
head
;
node
!=
null
;
node
=
node
.
sibling
)
{
if
(
node
.
order
>
30
)
{
throw
new
ArithmeticException
(
“The number of elements cannot be evaluated, but the priority queue is still valid.”
);
}
tmp
=
1
<<
node
.
order
;
result
|=
tmp
;
}
return
result
;
}
/**
* Associates a key with an index
* Worst case is O(log(n))
*
@param
i an index
*
@param
key a Key associated with i
*
@throws
java.lang.IllegalArgumentException if the specified index is invalid
*
@throws
java.lang.IllegalArgumentException if the index is already in the queue
*/
public
void
insert
(
int
i
,
Key
key
)
{
if
(
i
<
0
||
i
>=
n
)
throw
new
IllegalArgumentException
();
if
(
contains
(
i
))
throw
new
IllegalArgumentException
(
“Specified index is already in the queue”
);
Node
<
Key
>
x
=
new
Node
<
Key
>
();
x
.
key
=
key
;
x
.
index
=
i
;
x
.
order
=
0
;
nodes
[
i
]
=
x
;
IndexBinomialMinPQ
<
Key
>
H
=
new
IndexBinomialMinPQ
<
Key
>
();
H
.
head
=
x
;
head
=
union
(
H
).
head
;
}
/**
* Gets the index associated with the minimum key
* Worst case is O(log(n))
*
@throws
java.util.NoSuchElementException if the priority queue is empty
*
@return
the index associated with the minimum key
*/
public
int
minIndex
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Priority queue is empty”
);
Node
<
Key
>
min
=
head
;
Node
<
Key
>
current
=
head
;
while
(
current
.
sibling
!=
null
)
{
min
=
(
greater
(
min
.
key
,
current
.
sibling
.
key
))
?
current
.
sibling
:
min
;
current
=
current
.
sibling
;
}
return
min
.
index
;
}
/**
* Gets the minimum key currently in the queue
* Worst case is O(log(n))
*
@throws
java.util.NoSuchElementException if the priority queue is empty
*
@return
the minimum key currently in the priority queue
*/
public
Key
minKey
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Priority queue is empty”
);
Node
<
Key
>
min
=
head
;
Node
<
Key
>
current
=
head
;
while
(
current
.
sibling
!=
null
)
{
min
=
(
greater
(
min
.
key
,
current
.
sibling
.
key
))
?
current
.
sibling
:
min
;
current
=
current
.
sibling
;
}
return
min
.
key
;
}
/**
* Deletes the minimum key
* Worst case is O(log(n))
*
@throws
java.util.NoSuchElementException if the priority queue is empty
*
@return
the index associated with the minimum key
*/
public
int
delMin
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Priority queue is empty”
);
Node
<
Key
>
min
=
eraseMin
();
Node
<
Key
>
x
=
(
min
.
child
==
null
)
?
min
:
min
.
child
;
if
(
min
.
child
!=
null
)
{
min
.
child
=
null
;
Node
<
Key
>
prevx
=
null
,
nextx
=
x
.
sibling
;
while
(
nextx
!=
null
)
{
x
.
parent
=
null
;
// for garbage collection
x
.
sibling
=
prevx
;
prevx
=
x
;
x
=
nextx
;
nextx
=
nextx
.
sibling
;
}
x
.
parent
=
null
;
x
.
sibling
=
prevx
;
IndexBinomialMinPQ
<
Key
>
H
=
new
IndexBinomialMinPQ
<
Key
>
();
H
.
head
=
x
;
head
=
union
(
H
).
head
;
}
return
min
.
index
;
}
/**
* Gets the key associated with index i
* Worst case is O(1)
*
@param
i an index
*
@throws
java.lang.IllegalArgumentException if the specified index is invalid
*
@throws
java.lang.IllegalArgumentException if the index is not in the queue
*
@return
the key associated with index i
*/
public
Key
keyOf
(
int
i
)
{
if
(
i
<
0
||
i
>=
n
)
throw
new
IllegalArgumentException
();
if
(
!
contains
(
i
))
throw
new
IllegalArgumentException
(
“Specified index is not in the queue”
);
return
nodes
[
i
].
key
;
}
/**
* Changes the key associated with index i to the given key
* Worst case is O(log(n))
*
@param
i an index
*
@param
key the key to associate with i
*
@throws
java.lang.IllegalArgumentException if the specified index is invalid
*
@throws
java.lang.IllegalArgumentException if the index has no key associated with
*/
public
void
changeKey
(
int
i
,
Key
key
)
{
if
(
i
<
0
||
i
>=
n
)
throw
new
IllegalArgumentException
();
if
(
!
contains
(
i
))
throw
new
IllegalArgumentException
(
“Specified index is not in the queue”
);
if
(
greater
(
nodes
[
i
].
key
,
key
))
decreaseKey
(
i
,
key
);
else
increaseKey
(
i
,
key
);
}
/**
* Decreases the key associated with index i to the given key
* Worst case is O(log(n))
*
@param
i an index
*
@param
key the key to associate with i
*
@throws
java.lang.IllegalArgumentException if the specified index is invalid
*
@throws
java.util.NoSuchElementException if the index has no key associated with
*
@throws
java.lang.IllegalArgumentException if the given key is greater than the current key
*/
public
void
decreaseKey
(
int
i
,
Key
key
)
{
if
(
i
<
0
||
i
>=
n
)
throw
new
IllegalArgumentException
();
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
“Specified index is not in the queue”
);
if
(
greater
(
key
,
nodes
[
i
].
key
))
throw
new
IllegalArgumentException
(
“Calling with this argument would not decrease the key”
);
Node
<
Key
>
x
=
nodes
[
i
];
x
.
key
=
key
;
swim
(
i
);
}
/**
* Increases the key associated with index i to the given key
* Worst case is O(log(n))
*
@param
i an index
*
@param
key the key to associate with i
*
@throws
java.lang.IllegalArgumentException if the specified index is invalid
*
@throws
java.util.NoSuchElementException if the index has no key associated with
*
@throws
java.lang.IllegalArgumentException if the given key is lower than the current key
*/
public
void
increaseKey
(
int
i
,
Key
key
)
{
if
(
i
<
0
||
i
>=
n
)
throw
new
IllegalArgumentException
();
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
“Specified index is not in the queue”
);
if
(
greater
(
nodes
[
i
].
key
,
key
))
throw
new
IllegalArgumentException
(
“Calling with this argument would not increase the key”
);
delete
(
i
);
insert
(
i
,
key
);
}
/**
* Deletes the key associated the given index
* Worst case is O(log(n))
*
@param
i an index
*
@throws
java.lang.IllegalArgumentException if the specified index is invalid
*
@throws
java.util.NoSuchElementException if the given index has no key associated with
*/
public
void
delete
(
int
i
)
{
if
(
i
<
0
||
i
>=
n
)
throw
new
IllegalArgumentException
();
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
“Specified index is not in the queue”
);
toTheRoot
(
i
);
Node
<
Key
>
x
=
erase
(
i
);
if
(
x
.
child
!=
null
)
{
Node
<
Key
>
y
=
x
;
x
=
x
.
child
;
y
.
child
=
null
;
Node
<
Key
>
prevx
=
null
,
nextx
=
x
.
sibling
;
while
(
nextx
!=
null
)
{
x
.
parent
=
null
;
x
.
sibling
=
prevx
;
prevx
=
x
;
x
=
nextx
;
nextx
=
nextx
.
sibling
;
}
x
.
parent
=
null
;
x
.
sibling
=
prevx
;
IndexBinomialMinPQ
<
Key
>
H
=
new
IndexBinomialMinPQ
<
Key
>
();
H
.
head
=
x
;
head
=
union
(
H
).
head
;
}
}
/*************************************************
* General helper functions
************************************************/
//Compares two keys
private
boolean
greater
(
Key
n
,
Key
m
)
{
if
(
n
==
null
)
return
false
;
if
(
m
==
null
)
return
true
;
return
comparator
.
compare
(
n
,
m
)
>
0
;
}
//Exchanges the positions of two nodes
private
void
exchange
(
Node
<
Key
>
x
,
Node
<
Key
>
y
)
{
Key
tempKey
=
x
.
key
;
x
.
key
=
y
.
key
;
y
.
key
=
tempKey
;
int
tempInt
=
x
.
index
;
x
.
index
=
y
.
index
;
y
.
index
=
tempInt
;
nodes
[
x
.
index
]
=
x
;
nodes
[
y
.
index
]
=
y
;
}
//Assuming root1 holds a greater key than root2, root2 becomes the new root
private
void
link
(
Node
<
Key
>
root1
,
Node
<
Key
>
root2
)
{
root1
.
sibling
=
root2
.
child
;
root1
.
parent
=
root2
;
root2
.
child
=
root1
;
root2
.
order
++
;
}
/*************************************************
* Functions for moving upward
************************************************/
//Moves a Node upward
private
void
swim
(
int
i
)
{
Node
<
Key
>
x
=
nodes
[
i
];
Node
<
Key
>
parent
=
x
.
parent
;
if
(
parent
!=
null
&&
greater
(
parent
.
key
,
x
.
key
))
{
exchange
(
x
,
parent
);
swim
(
i
);
}
}
//The key associated with i becomes the root of its Binomial Tree,
//regardless of the order relation defined for the keys
private
void
toTheRoot
(
int
i
)
{
Node
<
Key
>
x
=
nodes
[
i
];
Node
<
Key
>
parent
=
x
.
parent
;
if
(
parent
!=
null
)
{
exchange
(
x
,
parent
);
toTheRoot
(
i
);
}
}
/**************************************************
* Functions for deleting a key
*************************************************/
//Assuming the key associated with i is in the root list,
//deletes and return the node of index i
private
Node
<
Key
>
erase
(
int
i
)
{
Node
<
Key
>
reference
=
nodes
[
i
];
Node
<
Key
>
x
=
head
;
Node
<
Key
>
previous
=
null
;
while
(
x
!=
reference
)
{
previous
=
x
;
x
=
x
.
sibling
;
}
previous
.
sibling
=
x
.
sibling
;
if
(
x
==
head
)
head
=
head
.
sibling
;
nodes
[
i
]
=
null
;
return
x
;
}
//Deletes and return the node containing the minimum key
private
Node
<
Key
>
eraseMin
()
{
Node
<
Key
>
min
=
head
;
Node
<
Key
>
previous
=
null
;
Node
<
Key
>
current
=
head
;
while
(
current
.
sibling
!=
null
)
{
if
(
greater
(
min
.
key
,
current
.
sibling
.
key
))
{
previous
=
current
;
min
=
current
.
sibling
;
}
current
=
current
.
sibling
;
}
previous
.
sibling
=
min
.
sibling
;
if
(
min
==
head
)
head
=
min
.
sibling
;
nodes
[
min
.
index
]
=
null
;
return
min
;
}
/**************************************************
* Functions for inserting a key in the heap
*************************************************/
//Merges two root lists into one, there can be up to 2 Binomial Trees of same order
private
Node
<
Key
>
merge
(
Node
<
Key
>
h
,
Node
<
Key
>
x
,
Node
<
Key
>
y
)
{
if
(
x
==
null
&&
y
==
null
)
return
h
;
else
if
(
x
==
null
)
h
.
sibling
=
merge
(
y
,
null
,
y
.
sibling
);
else
if
(
y
==
null
)
h
.
sibling
=
merge
(
x
,
x
.
sibling
,
null
);
else
if
(
x
.
order
<
y
.
order
)
h
.
sibling
=
merge
(
x
,
x
.
sibling
,
y
);
else
h
.
sibling
=
merge
(
y
,
x
,
y
.
sibling
);
return
h
;
}
//Merges two Binomial Heaps together and returns the resulting Binomial Heap
//It destroys the two Heaps in parameter, which should not be used any after.
//To guarantee logarithmic time, this function assumes the arrays are up-to-date
private
IndexBinomialMinPQ
<
Key
>
union
(
IndexBinomialMinPQ
<
Key
>
heap
)
{
this
.
head
=
merge
(
new
Node
<
Key
>
(),
this
.
head
,
heap
.
head
).
sibling
;
Node
<
Key
>
x
=
this
.
head
;
Node
<
Key
>
prevx
=
null
,
nextx
=
x
.
sibling
;
while
(
nextx
!=
null
)
{
if
(
x
.
order
<
nextx
.
order
||
(
nextx
.
sibling
!=
null
&&
nextx
.
sibling
.
order
==
x
.
order
))
{
prevx
=
x
;
x
=
nextx
;
}
else
if
(
greater
(
nextx
.
key
,
x
.
key
))
{
x
.
sibling
=
nextx
.
sibling
;
link
(
nextx
,
x
);
}
else
{
if
(
prevx
==
null
)
{
this
.
head
=
nextx
;
}
else
{
prevx
.
sibling
=
nextx
;
}
link
(
x
,
nextx
);
x
=
nextx
;
}
nextx
=
x
.
sibling
;
}
return
this
;
}
/******************************************************************
* Constructor
*****************************************************************/
//Creates an empty heap
//The comparator is instanciated because it needs to,
//but won't be used by any heap created by this constructor
private
IndexBinomialMinPQ
()
{
comparator
=
null
;
}
/******************************************************************
* Iterator
*****************************************************************/
/**
* Gets an Iterator over the indexes in the priority queue in ascending order
* The Iterator does not implement the remove() method
* iterator() : Worst case is O(n)
* next() : Worst case is O(log(n))
* hasNext() : Worst case is O(1)
*
@return
an Iterator over the indexes in the priority queue in ascending order
*/
public
Iterator
<
Integer
>
iterator
()
{
return
new
MyIterator
();
}
private
class
MyIterator
implements
Iterator
<
Integer
>
{
IndexBinomialMinPQ
<
Key
>
data
;
//Constructor clones recursively the elements in the queue
//It takes linear time
public
MyIterator
()
{
data
=
new
IndexBinomialMinPQ
<
Key
>
(
n
,
comparator
);
data
.
head
=
clone
(
head
,
null
);
}
private
Node
<
Key
>
clone
(
Node
<
Key
>
x
,
Node
<
Key
>
parent
)
{
if
(
x
==
null
)
return
null
;
Node
<
Key
>
node
=
new
Node
<
Key
>
();
node
.
index
=
x
.
index
;
node
.
key
=
x
.
key
;
data
.
nodes
[
node
.
index
]
=
node
;
node
.
parent
=
parent
;
node
.
sibling
=
clone
(
x
.
sibling
,
parent
);
node
.
child
=
clone
(
x
.
child
,
node
);
return
node
;
}
public
boolean
hasNext
()
{
return
!
data
.
isEmpty
();
}
public
Integer
next
()
{
if
(
!
hasNext
())
throw
new
NoSuchElementException
();
return
data
.
delMin
();
}
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
}
/***************************
* Comparator
**************************/
//default Comparator
private
class
MyComparator
implements
Comparator
<
Key
>
{
@
Override
public
int
compare
(
Key
key1
,
Key
key2
)
{
return
((
Comparable
<
Key
>
)
key1
).
compareTo
(
key2
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/IndexFibonacciMinPQ.java
edu/princeton/cs/algs4/IndexFibonacciMinPQ.java
/******************************************************************************
* Compilation: javac IndexFibonacciMinPQ.java
* Execution:
*
* An index Fibonacci heap.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Comparator
;
import
java
.
util
.
Iterator
;
import
java
.
util
.
HashMap
;
import
java
.
util
.
NoSuchElementException
;
/*
* The IndexFibonacciMinPQ class represents an indexed priority queue of generic keys.
* It supports the usual insert and delete-the-minimum operations,
* along with delete and change-the-key methods.
* In order to let the client refer to keys on the priority queue,
* an integer between 0 and N-1 is associated with each key ; the client
* uses this integer to specify which key to delete or change.
* It also supports methods for peeking at the minimum key,
* testing if the priority queue is empty, and iterating through
* the keys.
*
* This implementation uses a Fibonacci heap along with an array to associate
* keys with integers in the given range.
* The insert, size, is-empty, contains, minimum-index, minimum-key
* and key-of take constant time.
* The decrease-key operation takes amortized constant time.
* The delete, increase-key, delete-the-minimum, change-key take amortized logarithmic time.
* Construction takes time proportional to the specified capacity
*
* @author Tristan Claverie
*/
public
class
IndexFibonacciMinPQ
<
Key
>
implements
Iterable
<
Integer
>
{
private
Node
<
Key
>
[]
nodes
;
//Array of Nodes in the heap
private
Node
<
Key
>
head
;
//Head of the circular root list
private
Node
<
Key
>
min
;
//Minimum Node in the heap
private
int
size
;
//Number of keys in the heap
private
int
n
;
//Maximum number of elements in the heap
private
final
Comparator
<
Key
>
comp
;
//Comparator over the keys
private
HashMap
<
Integer
,
Node
<
Key
>>
table
=
new
HashMap
<
Integer
,
Node
<
Key
>>
();
//Used for the consolidate operation
//Represents a Node of a tree
private
class
Node
<
Key
>
{
Key
key
;
//Key of the Node
int
order
;
//The order of the tree rooted by this Node
int
index
;
//Index associated with the key
Node
<
Key
>
prev
,
next
;
//siblings of the Node
Node
<
Key
>
parent
,
child
;
//parent and child of this Node
boolean
mark
;
//Indicates if this Node already lost a child
}
/**
* Initializes an empty indexed priority queue with indices between {
@code
0} and {
@code
N-1}
* Worst case is O(n)
*
@param
N number of keys in the priority queue, index from {
@code
0} to {
@code
N-1}
*
@throws
java.lang.IllegalArgumentException if {
@code
N < 0}
*/
public
IndexFibonacciMinPQ
(
int
N
)
{
if
(
N
<
0
)
throw
new
IllegalArgumentException
(
"Cannot create a priority queue of negative size"
);
n
=
N
;
nodes
=
(
Node
<
Key
>
[])
new
Node
[
n
];
comp
=
new
MyComparator
();
}
/**
* Initializes an empty indexed priority queue with indices between {
@code
0} and {
@code
N-1}
* Worst case is O(n)
*
@param
N number of keys in the priority queue, index from {
@code
0} to {
@code
N-1}
*
@param
C a Comparator over the keys
*
@throws
java.lang.IllegalArgumentException if {
@code
N < 0}
*/
public
IndexFibonacciMinPQ
(
Comparator
<
Key
>
C
,
int
N
)
{
if
(
N
<
0
)
throw
new
IllegalArgumentException
(
"Cannot create a priority queue of negative size"
);
n
=
N
;
nodes
=
(
Node
<
Key
>
[])
new
Node
[
n
];
comp
=
C
;
}
/**
* Whether the priority queue is empty
* Worst case is O(1)
*
@return
true if the priority queue is empty, false if not
*/
public
boolean
isEmpty
()
{
return
size
==
0
;
}
/**
* Does the priority queue contains the index i ?
* Worst case is O(1)
*
@param
i an index
*
@throws
java.lang.IllegalArgumentException if the specified index is invalid
*
@return
true if i is on the priority queue, false if not
*/
public
boolean
contains
(
int
i
)
{
if
(
i
<
0
||
i
>=
n
)
throw
new
IllegalArgumentException
();
else
return
nodes
[
i
]
!=
null
;
}
/**
* Number of elements currently on the priority queue
* Worst case is O(1)
*
@return
the number of elements on the priority queue
*/
public
int
size
()
{
return
size
;
}
/**
* Associates a key with an index
* Worst case is O(1)
*
@param
i an index
*
@param
key a Key associated with i
*
@throws
java.lang.IllegalArgumentException if the specified index is invalid
*
@throws
java.lang.IllegalArgumentException if the index is already in the queue
*/
public
void
insert
(
int
i
,
Key
key
)
{
if
(
i
<
0
||
i
>=
n
)
throw
new
IllegalArgumentException
();
if
(
contains
(
i
))
throw
new
IllegalArgumentException
(
“Specified index is already in the queue”
);
Node
<
Key
>
x
=
new
Node
<
Key
>
();
x
.
key
=
key
;
x
.
index
=
i
;
nodes
[
i
]
=
x
;
size
++
;
head
=
insert
(
x
,
head
);
if
(
min
==
null
)
min
=
head
;
else
min
=
(
greater
(
min
.
key
,
key
))
?
head
:
min
;
}
/**
* Get the index associated with the minimum key
* Worst case is O(1)
*
@throws
java.util.NoSuchElementException if the priority queue is empty
*
@return
the index associated with the minimum key
*/
public
int
minIndex
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Priority queue is empty”
);
return
min
.
index
;
}
/**
* Get the minimum key currently in the queue
* Worst case is O(1)
*
@throws
java.util.NoSuchElementException if the priority queue is empty
*
@return
the minimum key currently in the priority queue
*/
public
Key
minKey
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Priority queue is empty”
);
return
min
.
key
;
}
/**
* Delete the minimum key
* Worst case is O(log(n)) (amortized)
*
@throws
java.util.NoSuchElementException if the priority queue is empty
*
@return
the index associated with the minimum key
*/
public
int
delMin
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Priority queue is empty”
);
head
=
cut
(
min
,
head
);
Node
<
Key
>
x
=
min
.
child
;
int
index
=
min
.
index
;
min
.
key
=
null
;
//For garbage collection
if
(
x
!=
null
)
{
do
{
x
.
parent
=
null
;
x
=
x
.
next
;
}
while
(
x
!=
min
.
child
);
head
=
meld
(
head
,
x
);
min
.
child
=
null
;
//For garbage collection
}
size
—
;
if
(
!
isEmpty
())
consolidate
();
else
min
=
null
;
nodes
[
index
]
=
null
;
return
index
;
}
/**
* Get the key associated with index i
* Worst case is O(1)
*
@param
i an index
*
@throws
java.lang.IllegalArgumentException if the specified index is invalid
*
@throws
java.util.NoSuchElementException if the index is not in the queue
*
@return
the key associated with index i
*/
public
Key
keyOf
(
int
i
)
{
if
(
i
<
0
||
i
>=
n
)
throw
new
IllegalArgumentException
();
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
“Specified index is not in the queue”
);
return
nodes
[
i
].
key
;
}
/**
* Changes the key associated with index i to the given key
* If the given key is greater, Worst case is O(log(n))
* If the given key is lower, Worst case is O(1) (amortized)
*
@param
i an index
*
@param
key the key to associate with i
*
@throws
java.lang.IllegalArgumentException if the specified index is invalid
*
@throws
java.util.NoSuchElementException if the index has no key associated with
*/
public
void
changeKey
(
int
i
,
Key
key
)
{
if
(
i
<
0
||
i
>=
n
)
throw
new
IllegalArgumentException
();
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
“Specified index is not in the queue”
);
if
(
greater
(
key
,
nodes
[
i
].
key
))
increaseKey
(
i
,
key
);
else
decreaseKey
(
i
,
key
);
}
/**
* Decreases the key associated with index i to the given key
* Worst case is O(1) (amortized).
*
@param
i an index
*
@param
key the key to associate with i
*
@throws
java.lang.IllegalArgumentException if the specified index is invalid
*
@throws
java.util.NoSuchElementException if the index has no key associated with
*
@throws
java.lang.IllegalArgumentException if the given key is greater than the current key
*/
public
void
decreaseKey
(
int
i
,
Key
key
)
{
if
(
i
<
0
||
i
>=
n
)
throw
new
IllegalArgumentException
();
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
“Specified index is not in the queue”
);
if
(
greater
(
key
,
nodes
[
i
].
key
))
throw
new
IllegalArgumentException
(
“Calling with this argument would not decrease the key”
);
Node
<
Key
>
x
=
nodes
[
i
];
x
.
key
=
key
;
if
(
greater
(
min
.
key
,
key
))
min
=
x
;
if
(
x
.
parent
!=
null
&&
greater
(
x
.
parent
.
key
,
key
))
{
cut
(
i
);
}
}
/**
* Increases the key associated with index i to the given key
* Worst case is O(log(n))
*
@param
i an index
*
@param
key the key to associate with i
*
@throws
java.lang.IllegalArgumentException if the specified index is invalid
*
@throws
java.util.NoSuchElementException if the index has no key associated with
*
@throws
java.lang.IllegalArgumentException if the given key is lower than the current key
*/
public
void
increaseKey
(
int
i
,
Key
key
)
{
if
(
i
<
0
||
i
>=
n
)
throw
new
IllegalArgumentException
();
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
“Specified index is not in the queue”
);
if
(
greater
(
nodes
[
i
].
key
,
key
))
throw
new
IllegalArgumentException
(
“Calling with this argument would not increase the key”
);
delete
(
i
);
insert
(
i
,
key
);
}
/**
* Deletes the key associated the given index
* Worst case is O(log(n)) (amortized)
*
@param
i an index
*
@throws
java.lang.IllegalArgumentException if the specified index is invalid
*
@throws
java.util.NoSuchElementException if the given index has no key associated with
*/
public
void
delete
(
int
i
)
{
if
(
i
<
0
||
i
>=
n
)
throw
new
IllegalArgumentException
();
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
“Specified index is not in the queue”
);
Node
<
Key
>
x
=
nodes
[
i
];
x
.
key
=
null
;
//For garbage collection
if
(
x
.
parent
!=
null
)
{
cut
(
i
);
}
head
=
cut
(
x
,
head
);
if
(
x
.
child
!=
null
)
{
Node
<
Key
>
child
=
x
.
child
;
x
.
child
=
null
;
//For garbage collection
x
=
child
;
do
{
child
.
parent
=
null
;
child
=
child
.
next
;
}
while
(
child
!=
x
);
head
=
meld
(
head
,
child
);
}
if
(
!
isEmpty
())
consolidate
();
else
min
=
null
;
nodes
[
i
]
=
null
;
size
—
;
}
/*************************************
* General helper functions
************************************/
//Compares two keys
private
boolean
greater
(
Key
n
,
Key
m
)
{
if
(
n
==
null
)
return
false
;
if
(
m
==
null
)
return
true
;
return
comp
.
compare
(
n
,
m
)
>
0
;
}
//Assuming root1 holds a greater key than root2, root2 becomes the new root
private
void
link
(
Node
<
Key
>
root1
,
Node
<
Key
>
root2
)
{
root1
.
parent
=
root2
;
root2
.
child
=
insert
(
root1
,
root2
.
child
);
root2
.
order
++
;
}
/*************************************
* Function for decreasing a key
************************************/
//Removes a Node from its parent’s child list and insert it in the root list
//If the parent Node already lost a child, reshapes the heap accordingly
private
void
cut
(
int
i
)
{
Node
<
Key
>
x
=
nodes
[
i
];
Node
<
Key
>
parent
=
x
.
parent
;
parent
.
child
=
cut
(
x
,
parent
.
child
);
x
.
parent
=
null
;
parent
.
order
—
;
head
=
insert
(
x
,
head
);
parent
.
mark
=
!
parent
.
mark
;
if
(
!
parent
.
mark
&&
parent
.
parent
!=
null
)
{
cut
(
parent
.
index
);}
}
/*************************************
* Function for consolidating all trees in the root list
************************************/
//Coalesces the roots, thus reshapes the heap
//Caching a HashMap improves greatly performances
private
void
consolidate
()
{
table
.
clear
();
Node
<
Key
>
x
=
head
;
int
maxOrder
=
0
;
min
=
head
;
Node
<
Key
>
y
=
null
,
z
=
null
;
do
{
y
=
x
;
x
=
x
.
next
;
z
=
table
.
get
(
y
.
order
);
while
(
z
!=
null
)
{
table
.
remove
(
y
.
order
);
if
(
greater
(
y
.
key
,
z
.
key
))
{
link
(
y
,
z
);
y
=
z
;
}
else
{
link
(
z
,
y
);
}
z
=
table
.
get
(
y
.
order
);
}
table
.
put
(
y
.
order
,
y
);
if
(
y
.
order
>
maxOrder
)
maxOrder
=
y
.
order
;
}
while
(
x
!=
head
);
head
=
null
;
for
(
Node
<
Key
>
n
:
table
.
values
())
{
min
=
greater
(
min
.
key
,
n
.
key
)
?
n
:
min
;
head
=
insert
(
n
,
head
);
}
}
/*************************************
* General helper functions for manipulating circular lists
************************************/
//Inserts a Node in a circular list containing head, returns a new head
private
Node
<
Key
>
insert
(
Node
<
Key
>
x
,
Node
<
Key
>
head
)
{
if
(
head
==
null
)
{
x
.
prev
=
x
;
x
.
next
=
x
;
}
else
{
head
.
prev
.
next
=
x
;
x
.
next
=
head
;
x
.
prev
=
head
.
prev
;
head
.
prev
=
x
;
}
return
x
;
}
//Removes a tree from the list defined by the head pointer
private
Node
<
Key
>
cut
(
Node
<
Key
>
x
,
Node
<
Key
>
head
)
{
if
(
x
.
next
==
x
)
{
x
.
next
=
null
;
x
.
prev
=
null
;
return
null
;
}
else
{
x
.
next
.
prev
=
x
.
prev
;
x
.
prev
.
next
=
x
.
next
;
Node
<
Key
>
res
=
x
.
next
;
x
.
next
=
null
;
x
.
prev
=
null
;
if
(
head
==
x
)
return
res
;
else
return
head
;
}
}
//Merges two lists together.
private
Node
<
Key
>
meld
(
Node
<
Key
>
x
,
Node
<
Key
>
y
)
{
if
(
x
==
null
)
return
y
;
if
(
y
==
null
)
return
x
;
x
.
prev
.
next
=
y
.
next
;
y
.
next
.
prev
=
x
.
prev
;
x
.
prev
=
y
;
y
.
next
=
x
;
return
x
;
}
/*************************************
* Iterator
************************************/
/**
* Get an Iterator over the indexes in the priority queue in ascending order
* The Iterator does not implement the remove() method
* iterator() : Worst case is O(n)
* next() : Worst case is O(log(n)) (amortized)
* hasNext() : Worst case is O(1)
*
@return
an Iterator over the indexes in the priority queue in ascending order
*/
public
Iterator
<
Integer
>
iterator
()
{
return
new
MyIterator
();
}
private
class
MyIterator
implements
Iterator
<
Integer
>
{
private
IndexFibonacciMinPQ
<
Key
>
copy
;
//Constructor takes linear time
public
MyIterator
()
{
copy
=
new
IndexFibonacciMinPQ
<
Key
>
(
comp
,
n
);
for
(
Node
<
Key
>
x
:
nodes
)
{
if
(
x
!=
null
)
copy
.
insert
(
x
.
index
,
x
.
key
);
}
}
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
public
boolean
hasNext
()
{
return
!
copy
.
isEmpty
();
}
//Takes amortized logarithmic time
public
Integer
next
()
{
if
(
!
hasNext
())
throw
new
NoSuchElementException
();
return
copy
.
delMin
();
}
}
/***************************
* Comparator
**************************/
//default Comparator
private
class
MyComparator
implements
Comparator
<
Key
>
{
@
Override
public
int
compare
(
Key
key1
,
Key
key2
)
{
return
((
Comparable
<
Key
>
)
key1
).
compareTo
(
key2
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/IndexMaxPQ.java
edu/princeton/cs/algs4/IndexMaxPQ.java
/******************************************************************************
* Compilation: javac IndexMaxPQ.java
* Execution: java IndexMaxPQ
* Dependencies: StdOut.java
*
* Maximum-oriented indexed PQ implementation using a binary heap.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Iterator
;
import
java
.
util
.
NoSuchElementException
;
/**
* The {
@code
IndexMaxPQ} class represents an indexed priority queue of generic keys.
* It supports the usual insert and delete-the-maximum
* operations, along with delete and change-the-key
* methods. In order to let the client refer to items on the priority queue,
* an integer between {
@code
0} and {
@code
maxN – 1}
* is associated with each key—the client
* uses this integer to specify which key to delete or change.
* It also supports methods for peeking at a maximum key,
* testing if the priority queue is empty, and iterating through
* the keys.
*
* This implementation uses a binary heap along with an
* array to associate keys with integers in the given range.
* The insert, delete-the-maximum, delete,
* change-key, decrease-key, and increase-key
* operations take Θ(log n) time in the worst case,
* where n is the number of elements in the priority queue.
* Construction takes time proportional to the specified capacity.
*
* For additional documentation, see
* Section 2.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*
*
@param
*/
public
class
IndexMaxPQ
<
Key
extends
Comparable
<
Key
>>
implements
Iterable
<
Integer
>
{
private
int
maxN
;
// maximum number of elements on PQ
private
int
n
;
// number of elements on PQ
private
int
[]
pq
;
// binary heap using 1-based indexing
private
int
[]
qp
;
// inverse of pq – qp[pq[i]] = pq[qp[i]] = i
private
Key
[]
keys
;
// keys[i] = priority of i
/**
* Initializes an empty indexed priority queue with indices between {
@code
0}
* and {
@code
maxN – 1}.
*
*
@param
maxN the keys on this priority queue are index from {
@code
0} to {
@code
maxN – 1}
*
@throws
IllegalArgumentException if {
@code
maxN < 0}
*/
public
IndexMaxPQ
(
int
maxN
)
{
if
(
maxN
<
0
)
throw
new
IllegalArgumentException
();
this
.
maxN
=
maxN
;
n
=
0
;
keys
=
(
Key
[])
new
Comparable
[
maxN
+
1
];
// make this of length maxN??
pq
=
new
int
[
maxN
+
1
];
qp
=
new
int
[
maxN
+
1
];
// make this of length maxN??
for
(
int
i
=
0
;
i
<=
maxN
;
i
++
)
qp
[
i
]
=
-
1
;
}
/**
* Returns true if this priority queue is empty.
*
*
@return
{
@code
true} if this priority queue is empty;
* {
@code
false} otherwise
*/
public
boolean
isEmpty
()
{
return
n
==
0
;
}
/**
* Is {
@code
i} an index on this priority queue?
*
*
@param
i an index
*
@return
{
@code
true} if {
@code
i} is an index on this priority queue;
* {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= i < maxN}
*/
public
boolean
contains
(
int
i
)
{
validateIndex
(
i
);
return
qp
[
i
]
!=
-
1
;
}
/**
* Returns the number of keys on this priority queue.
*
*
@return
the number of keys on this priority queue
*/
public
int
size
()
{
return
n
;
}
/**
* Associate key with index i.
*
*
@param
i an index
*
@param
key the key to associate with index {
@code
i}
*
@throws
IllegalArgumentException unless {
@code
0 <= i < maxN}
*
@throws
IllegalArgumentException if there already is an item
* associated with index {
@code
i}
*/
public
void
insert
(
int
i
,
Key
key
)
{
validateIndex
(
i
);
if
(
contains
(
i
))
throw
new
IllegalArgumentException
(
"index is already in the priority queue"
);
n
++
;
qp
[
i
]
=
n
;
pq
[
n
]
=
i
;
keys
[
i
]
=
key
;
swim
(
n
);
}
/**
* Returns an index associated with a maximum key.
*
*
@return
an index associated with a maximum key
*
@throws
NoSuchElementException if this priority queue is empty
*/
public
int
maxIndex
()
{
if
(
n
==
0
)
throw
new
NoSuchElementException
(
"Priority queue underflow"
);
return
pq
[
1
];
}
/**
* Returns a maximum key.
*
*
@return
a maximum key
*
@throws
NoSuchElementException if this priority queue is empty
*/
public
Key
maxKey
()
{
if
(
n
==
0
)
throw
new
NoSuchElementException
(
"Priority queue underflow"
);
return
keys
[
pq
[
1
]];
}
/**
* Removes a maximum key and returns its associated index.
*
*
@return
an index associated with a maximum key
*
@throws
NoSuchElementException if this priority queue is empty
*/
public
int
delMax
()
{
if
(
n
==
0
)
throw
new
NoSuchElementException
(
"Priority queue underflow"
);
int
max
=
pq
[
1
];
exch
(
1
,
n
--
);
sink
(
1
);
assert
pq
[
n
+
1
]
==
max
;
qp
[
max
]
=
-
1
;
// delete
keys
[
max
]
=
null
;
// to help with garbage collection
pq
[
n
+
1
]
=
-
1
;
// not needed
return
max
;
}
/**
* Returns the key associated with index {
@code
i}.
*
*
@param
i the index of the key to return
*
@return
the key associated with index {
@code
i}
*
@throws
IllegalArgumentException unless {
@code
0 <= i < maxN}
*
@throws
NoSuchElementException no key is associated with index {
@code
i}
*/
public
Key
keyOf
(
int
i
)
{
validateIndex
(
i
);
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
"index is not in the priority queue"
);
else
return
keys
[
i
];
}
/**
* Change the key associated with index {
@code
i} to the specified value.
*
*
@param
i the index of the key to change
*
@param
key change the key associated with index {
@code
i} to this key
*
@throws
IllegalArgumentException unless {
@code
0 <= i < maxN}
*/
public
void
changeKey
(
int
i
,
Key
key
)
{
validateIndex
(
i
);
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
"index is not in the priority queue"
);
keys
[
i
]
=
key
;
swim
(
qp
[
i
]);
sink
(
qp
[
i
]);
}
/**
* Change the key associated with index {
@code
i} to the specified value.
*
*
@param
i the index of the key to change
*
@param
key change the key associated with index {
@code
i} to this key
*
@throws
IllegalArgumentException unless {
@code
0 <= i < maxN}
*
@deprecated
Replaced by {
@code
changeKey(int, Key)}.
*/
@
Deprecated
public
void
change
(
int
i
,
Key
key
)
{
validateIndex
(
i
);
changeKey
(
i
,
key
);
}
/**
* Increase the key associated with index {
@code
i} to the specified value.
*
*
@param
i the index of the key to increase
*
@param
key increase the key associated with index {
@code
i} to this key
*
@throws
IllegalArgumentException unless {
@code
0 <= i < maxN}
*
@throws
IllegalArgumentException if {
@code
key <= keyOf(i)}
*
@throws
NoSuchElementException no key is associated with index {
@code
i}
*/
public
void
increaseKey
(
int
i
,
Key
key
)
{
validateIndex
(
i
);
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
"index is not in the priority queue"
);
if
(
keys
[
i
].
compareTo
(
key
)
==
0
)
throw
new
IllegalArgumentException
(
"Calling increaseKey() with a key equal to the key in the priority queue"
);
if
(
keys
[
i
].
compareTo
(
key
)
>
0
)
throw
new
IllegalArgumentException
(
“Calling increaseKey() with a key that is strictly less than the key in the priority queue”
);
keys
[
i
]
=
key
;
swim
(
qp
[
i
]);
}
/**
* Decrease the key associated with index {
@code
i} to the specified value.
*
*
@param
i the index of the key to decrease
*
@param
key decrease the key associated with index {
@code
i} to this key
*
@throws
IllegalArgumentException unless {
@code
0 <= i < maxN}
*
@throws
IllegalArgumentException if {
@code
key >= keyOf(i)}
*
@throws
NoSuchElementException no key is associated with index {
@code
i}
*/
public
void
decreaseKey
(
int
i
,
Key
key
)
{
validateIndex
(
i
);
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
“index is not in the priority queue”
);
if
(
keys
[
i
].
compareTo
(
key
)
==
0
)
throw
new
IllegalArgumentException
(
“Calling decreaseKey() with a key equal to the key in the priority queue”
);
if
(
keys
[
i
].
compareTo
(
key
)
<
0
)
throw
new
IllegalArgumentException
(
"Calling decreaseKey() with a key that is strictly greater than the key in the priority queue"
);
keys
[
i
]
=
key
;
sink
(
qp
[
i
]);
}
/**
* Remove the key on the priority queue associated with index {
@code
i}.
*
*
@param
i the index of the key to remove
*
@throws
IllegalArgumentException unless {
@code
0 <= i < maxN}
*
@throws
NoSuchElementException no key is associated with index {
@code
i}
*/
public
void
delete
(
int
i
)
{
validateIndex
(
i
);
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
"index is not in the priority queue"
);
int
index
=
qp
[
i
];
exch
(
index
,
n
--
);
swim
(
index
);
sink
(
index
);
keys
[
i
]
=
null
;
qp
[
i
]
=
-
1
;
}
// throw an IllegalArgumentException if i is an invalid index
private
void
validateIndex
(
int
i
)
{
if
(
i
<
0
)
throw
new
IllegalArgumentException
(
"index is negative: "
+
i
);
if
(
i
>=
maxN
)
throw
new
IllegalArgumentException
(
“index >= capacity: ”
+
i
);
}
/***************************************************************************
* General helper functions.
***************************************************************************/
private
boolean
less
(
int
i
,
int
j
)
{
return
keys
[
pq
[
i
]].
compareTo
(
keys
[
pq
[
j
]])
<
0
;
}
private
void
exch
(
int
i
,
int
j
)
{
int
swap
=
pq
[
i
];
pq
[
i
]
=
pq
[
j
];
pq
[
j
]
=
swap
;
qp
[
pq
[
i
]]
=
i
;
qp
[
pq
[
j
]]
=
j
;
}
/***************************************************************************
* Heap helper functions.
***************************************************************************/
private
void
swim
(
int
k
)
{
while
(
k
>
1
&&
less
(
k
/
2
,
k
))
{
exch
(
k
,
k
/
2
);
k
=
k
/
2
;
}
}
private
void
sink
(
int
k
)
{
while
(
2
*
k
<=
n
)
{
int
j
=
2
*
k
;
if
(
j
<
n
&&
less
(
j
,
j
+
1
))
j
++
;
if
(
!
less
(
k
,
j
))
break
;
exch
(
k
,
j
);
k
=
j
;
}
}
/**
* Returns an iterator that iterates over the keys on the
* priority queue in descending order.
* The iterator doesn't implement {
@code
remove()} since it's optional.
*
*
@return
an iterator that iterates over the keys in descending order
*/
public
Iterator
<
Integer
>
iterator
()
{
return
new
HeapIterator
();
}
private
class
HeapIterator
implements
Iterator
<
Integer
>
{
// create a new pq
private
IndexMaxPQ
<
Key
>
copy
;
// add all elements to copy of heap
// takes linear time since already in heap order so no keys move
public
HeapIterator
()
{
copy
=
new
IndexMaxPQ
<
Key
>
(
pq
.
length
–
1
);
for
(
int
i
=
1
;
i
<=
n
;
i
++
)
copy
.
insert
(
pq
[
i
],
keys
[
pq
[
i
]]);
}
public
boolean
hasNext
()
{
return
!
copy
.
isEmpty
();
}
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
public
Integer
next
()
{
if
(
!
hasNext
())
throw
new
NoSuchElementException
();
return
copy
.
delMax
();
}
}
/**
* Unit tests the {
@code
IndexMaxPQ} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// insert a bunch of strings
String
[]
strings
=
{
"it"
,
"was"
,
"the"
,
"best"
,
"of"
,
"times"
,
"it"
,
"was"
,
"the"
,
"worst"
};
IndexMaxPQ
<
String
>
pq
=
new
IndexMaxPQ
<
String
>
(
strings
.
length
);
for
(
int
i
=
0
;
i
<
strings
.
length
;
i
++
)
{
pq
.
insert
(
i
,
strings
[
i
]);
}
// print each key using the iterator
for
(
int
i
:
pq
)
{
StdOut
.
println
(
i
+
" "
+
strings
[
i
]);
}
StdOut
.
println
();
// increase or decrease the key
for
(
int
i
=
0
;
i
<
strings
.
length
;
i
++
)
{
if
(
StdRandom
.
uniform
()
<
0.5
)
pq
.
increaseKey
(
i
,
strings
[
i
]
+
strings
[
i
]);
else
pq
.
decreaseKey
(
i
,
strings
[
i
].
substring
(
0
,
1
));
}
// delete and print each key
while
(
!
pq
.
isEmpty
())
{
String
key
=
pq
.
maxKey
();
int
i
=
pq
.
delMax
();
StdOut
.
println
(
i
+
" "
+
key
);
}
StdOut
.
println
();
// reinsert the same strings
for
(
int
i
=
0
;
i
<
strings
.
length
;
i
++
)
{
pq
.
insert
(
i
,
strings
[
i
]);
}
// delete them in random order
int
[]
perm
=
new
int
[
strings
.
length
];
for
(
int
i
=
0
;
i
<
strings
.
length
;
i
++
)
perm
[
i
]
=
i
;
StdRandom
.
shuffle
(
perm
);
for
(
int
i
=
0
;
i
<
perm
.
length
;
i
++
)
{
String
key
=
pq
.
keyOf
(
perm
[
i
]);
pq
.
delete
(
perm
[
i
]);
StdOut
.
println
(
perm
[
i
]
+
" "
+
key
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/IndexMinPQ.java
edu/princeton/cs/algs4/IndexMinPQ.java
/******************************************************************************
* Compilation: javac IndexMinPQ.java
* Execution: java IndexMinPQ
* Dependencies: StdOut.java
*
* Minimum-oriented indexed PQ implementation using a binary heap.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Iterator
;
import
java
.
util
.
NoSuchElementException
;
/**
* The {
@code
IndexMinPQ} class represents an indexed priority queue of generic keys.
* It supports the usual insert and delete-the-minimum
* operations, along with delete and change-the-key
* methods. In order to let the client refer to keys on the priority queue,
* an integer between {
@code
0} and {
@code
maxN – 1}
* is associated with each key—the client uses this integer to specify
* which key to delete or change.
* It also supports methods for peeking at the minimum key,
* testing if the priority queue is empty, and iterating through
* the keys.
*
* This implementation uses a binary heap along with an array to associate
* keys with integers in the given range.
* The insert, delete-the-minimum, delete,
* change-key, decrease-key, and increase-key
* operations take Θ(log n) time in the worst case,
* where n is the number of elements in the priority queue.
* Construction takes time proportional to the specified capacity.
*
* For additional documentation, see
* Section 2.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*
*
@param
*/
public
class
IndexMinPQ
<
Key
extends
Comparable
<
Key
>>
implements
Iterable
<
Integer
>
{
private
int
maxN
;
// maximum number of elements on PQ
private
int
n
;
// number of elements on PQ
private
int
[]
pq
;
// binary heap using 1-based indexing
private
int
[]
qp
;
// inverse of pq – qp[pq[i]] = pq[qp[i]] = i
private
Key
[]
keys
;
// keys[i] = priority of i
/**
* Initializes an empty indexed priority queue with indices between {
@code
0}
* and {
@code
maxN – 1}.
*
@param
maxN the keys on this priority queue are index from {
@code
0}
* {
@code
maxN – 1}
*
@throws
IllegalArgumentException if {
@code
maxN < 0}
*/
public
IndexMinPQ
(
int
maxN
)
{
if
(
maxN
<
0
)
throw
new
IllegalArgumentException
();
this
.
maxN
=
maxN
;
n
=
0
;
keys
=
(
Key
[])
new
Comparable
[
maxN
+
1
];
// make this of length maxN??
pq
=
new
int
[
maxN
+
1
];
qp
=
new
int
[
maxN
+
1
];
// make this of length maxN??
for
(
int
i
=
0
;
i
<=
maxN
;
i
++
)
qp
[
i
]
=
-
1
;
}
/**
* Returns true if this priority queue is empty.
*
*
@return
{
@code
true} if this priority queue is empty;
* {
@code
false} otherwise
*/
public
boolean
isEmpty
()
{
return
n
==
0
;
}
/**
* Is {
@code
i} an index on this priority queue?
*
*
@param
i an index
*
@return
{
@code
true} if {
@code
i} is an index on this priority queue;
* {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= i < maxN}
*/
public
boolean
contains
(
int
i
)
{
validateIndex
(
i
);
return
qp
[
i
]
!=
-
1
;
}
/**
* Returns the number of keys on this priority queue.
*
*
@return
the number of keys on this priority queue
*/
public
int
size
()
{
return
n
;
}
/**
* Associates key with index {
@code
i}.
*
*
@param
i an index
*
@param
key the key to associate with index {
@code
i}
*
@throws
IllegalArgumentException unless {
@code
0 <= i < maxN}
*
@throws
IllegalArgumentException if there already is an item associated
* with index {
@code
i}
*/
public
void
insert
(
int
i
,
Key
key
)
{
validateIndex
(
i
);
if
(
contains
(
i
))
throw
new
IllegalArgumentException
(
"index is already in the priority queue"
);
n
++
;
qp
[
i
]
=
n
;
pq
[
n
]
=
i
;
keys
[
i
]
=
key
;
swim
(
n
);
}
/**
* Returns an index associated with a minimum key.
*
*
@return
an index associated with a minimum key
*
@throws
NoSuchElementException if this priority queue is empty
*/
public
int
minIndex
()
{
if
(
n
==
0
)
throw
new
NoSuchElementException
(
"Priority queue underflow"
);
return
pq
[
1
];
}
/**
* Returns a minimum key.
*
*
@return
a minimum key
*
@throws
NoSuchElementException if this priority queue is empty
*/
public
Key
minKey
()
{
if
(
n
==
0
)
throw
new
NoSuchElementException
(
"Priority queue underflow"
);
return
keys
[
pq
[
1
]];
}
/**
* Removes a minimum key and returns its associated index.
*
@return
an index associated with a minimum key
*
@throws
NoSuchElementException if this priority queue is empty
*/
public
int
delMin
()
{
if
(
n
==
0
)
throw
new
NoSuchElementException
(
"Priority queue underflow"
);
int
min
=
pq
[
1
];
exch
(
1
,
n
--
);
sink
(
1
);
assert
min
==
pq
[
n
+
1
];
qp
[
min
]
=
-
1
;
// delete
keys
[
min
]
=
null
;
// to help with garbage collection
pq
[
n
+
1
]
=
-
1
;
// not needed
return
min
;
}
/**
* Returns the key associated with index {
@code
i}.
*
*
@param
i the index of the key to return
*
@return
the key associated with index {
@code
i}
*
@throws
IllegalArgumentException unless {
@code
0 <= i < maxN}
*
@throws
NoSuchElementException no key is associated with index {
@code
i}
*/
public
Key
keyOf
(
int
i
)
{
validateIndex
(
i
);
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
"index is not in the priority queue"
);
else
return
keys
[
i
];
}
/**
* Change the key associated with index {
@code
i} to the specified value.
*
*
@param
i the index of the key to change
*
@param
key change the key associated with index {
@code
i} to this key
*
@throws
IllegalArgumentException unless {
@code
0 <= i < maxN}
*
@throws
NoSuchElementException no key is associated with index {
@code
i}
*/
public
void
changeKey
(
int
i
,
Key
key
)
{
validateIndex
(
i
);
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
"index is not in the priority queue"
);
keys
[
i
]
=
key
;
swim
(
qp
[
i
]);
sink
(
qp
[
i
]);
}
/**
* Change the key associated with index {
@code
i} to the specified value.
*
*
@param
i the index of the key to change
*
@param
key change the key associated with index {
@code
i} to this key
*
@throws
IllegalArgumentException unless {
@code
0 <= i < maxN}
*
@deprecated
Replaced by {
@code
changeKey(int, Key)}.
*/
@
Deprecated
public
void
change
(
int
i
,
Key
key
)
{
changeKey
(
i
,
key
);
}
/**
* Decrease the key associated with index {
@code
i} to the specified value.
*
*
@param
i the index of the key to decrease
*
@param
key decrease the key associated with index {
@code
i} to this key
*
@throws
IllegalArgumentException unless {
@code
0 <= i < maxN}
*
@throws
IllegalArgumentException if {
@code
key >= keyOf(i)}
*
@throws
NoSuchElementException no key is associated with index {
@code
i}
*/
public
void
decreaseKey
(
int
i
,
Key
key
)
{
validateIndex
(
i
);
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
“index is not in the priority queue”
);
if
(
keys
[
i
].
compareTo
(
key
)
==
0
)
throw
new
IllegalArgumentException
(
“Calling decreaseKey() with a key equal to the key in the priority queue”
);
if
(
keys
[
i
].
compareTo
(
key
)
<
0
)
throw
new
IllegalArgumentException
(
"Calling decreaseKey() with a key strictly greater than the key in the priority queue"
);
keys
[
i
]
=
key
;
swim
(
qp
[
i
]);
}
/**
* Increase the key associated with index {
@code
i} to the specified value.
*
*
@param
i the index of the key to increase
*
@param
key increase the key associated with index {
@code
i} to this key
*
@throws
IllegalArgumentException unless {
@code
0 <= i < maxN}
*
@throws
IllegalArgumentException if {
@code
key <= keyOf(i)}
*
@throws
NoSuchElementException no key is associated with index {
@code
i}
*/
public
void
increaseKey
(
int
i
,
Key
key
)
{
validateIndex
(
i
);
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
"index is not in the priority queue"
);
if
(
keys
[
i
].
compareTo
(
key
)
==
0
)
throw
new
IllegalArgumentException
(
"Calling increaseKey() with a key equal to the key in the priority queue"
);
if
(
keys
[
i
].
compareTo
(
key
)
>
0
)
throw
new
IllegalArgumentException
(
“Calling increaseKey() with a key strictly less than the key in the priority queue”
);
keys
[
i
]
=
key
;
sink
(
qp
[
i
]);
}
/**
* Remove the key associated with index {
@code
i}.
*
*
@param
i the index of the key to remove
*
@throws
IllegalArgumentException unless {
@code
0 <= i < maxN}
*
@throws
NoSuchElementException no key is associated with index {
@code
i}
*/
public
void
delete
(
int
i
)
{
validateIndex
(
i
);
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
"index is not in the priority queue"
);
int
index
=
qp
[
i
];
exch
(
index
,
n
--
);
swim
(
index
);
sink
(
index
);
keys
[
i
]
=
null
;
qp
[
i
]
=
-
1
;
}
// throw an IllegalArgumentException if i is an invalid index
private
void
validateIndex
(
int
i
)
{
if
(
i
<
0
)
throw
new
IllegalArgumentException
(
"index is negative: "
+
i
);
if
(
i
>=
maxN
)
throw
new
IllegalArgumentException
(
“index >= capacity: ”
+
i
);
}
/***************************************************************************
* General helper functions.
***************************************************************************/
private
boolean
greater
(
int
i
,
int
j
)
{
return
keys
[
pq
[
i
]].
compareTo
(
keys
[
pq
[
j
]])
>
0
;
}
private
void
exch
(
int
i
,
int
j
)
{
int
swap
=
pq
[
i
];
pq
[
i
]
=
pq
[
j
];
pq
[
j
]
=
swap
;
qp
[
pq
[
i
]]
=
i
;
qp
[
pq
[
j
]]
=
j
;
}
/***************************************************************************
* Heap helper functions.
***************************************************************************/
private
void
swim
(
int
k
)
{
while
(
k
>
1
&&
greater
(
k
/
2
,
k
))
{
exch
(
k
,
k
/
2
);
k
=
k
/
2
;
}
}
private
void
sink
(
int
k
)
{
while
(
2
*
k
<=
n
)
{
int
j
=
2
*
k
;
if
(
j
<
n
&&
greater
(
j
,
j
+
1
))
j
++
;
if
(
!
greater
(
k
,
j
))
break
;
exch
(
k
,
j
);
k
=
j
;
}
}
/***************************************************************************
* Iterators.
***************************************************************************/
/**
* Returns an iterator that iterates over the keys on the
* priority queue in ascending order.
* The iterator doesn't implement {
@code
remove()} since it's optional.
*
*
@return
an iterator that iterates over the keys in ascending order
*/
public
Iterator
<
Integer
>
iterator
()
{
return
new
HeapIterator
();
}
private
class
HeapIterator
implements
Iterator
<
Integer
>
{
// create a new pq
private
IndexMinPQ
<
Key
>
copy
;
// add all elements to copy of heap
// takes linear time since already in heap order so no keys move
public
HeapIterator
()
{
copy
=
new
IndexMinPQ
<
Key
>
(
pq
.
length
–
1
);
for
(
int
i
=
1
;
i
<=
n
;
i
++
)
copy
.
insert
(
pq
[
i
],
keys
[
pq
[
i
]]);
}
public
boolean
hasNext
()
{
return
!
copy
.
isEmpty
();
}
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
public
Integer
next
()
{
if
(
!
hasNext
())
throw
new
NoSuchElementException
();
return
copy
.
delMin
();
}
}
/**
* Unit tests the {
@code
IndexMinPQ} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// insert a bunch of strings
String
[]
strings
=
{
"it"
,
"was"
,
"the"
,
"best"
,
"of"
,
"times"
,
"it"
,
"was"
,
"the"
,
"worst"
};
IndexMinPQ
<
String
>
pq
=
new
IndexMinPQ
<
String
>
(
strings
.
length
);
for
(
int
i
=
0
;
i
<
strings
.
length
;
i
++
)
{
pq
.
insert
(
i
,
strings
[
i
]);
}
// delete and print each key
while
(
!
pq
.
isEmpty
())
{
int
i
=
pq
.
delMin
();
StdOut
.
println
(
i
+
" "
+
strings
[
i
]);
}
StdOut
.
println
();
// reinsert the same strings
for
(
int
i
=
0
;
i
<
strings
.
length
;
i
++
)
{
pq
.
insert
(
i
,
strings
[
i
]);
}
// print each key using the iterator
for
(
int
i
:
pq
)
{
StdOut
.
println
(
i
+
" "
+
strings
[
i
]);
}
while
(
!
pq
.
isEmpty
())
{
pq
.
delMin
();
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/IndexMultiwayMinPQ.java
edu/princeton/cs/algs4/IndexMultiwayMinPQ.java
/******************************************************************************
* Compilation: javac IndexMultiwayMinPQ.java
* Execution:
*
* An inde multiway heap.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Comparator
;
import
java
.
util
.
Iterator
;
import
java
.
util
.
NoSuchElementException
;
/**
* The IndexMultiwayMinPQ class represents an indexed priority queue of generic keys.
* It supports the usual insert and delete-the-minimum operations,
* along with delete and change-the-key methods.
* In order to let the client refer to keys on the priority queue,
* an integer between 0 and N-1 is associated with each key ; the client
* uses this integer to specify which key to delete or change.
* It also supports methods for peeking at the minimum key,
* testing if the priority queue is empty, and iterating through
* the keys.
*
* This implementation uses a multiway heap along with an array to associate
* keys with integers in the given range.
* For simplified notations, logarithm in base d will be referred as log-d
* The delete-the-minimum, delete, change-key and increase-key operations
* take time proportional to d*log-d(n)
* The insert and decrease-key take time proportional to log-d(n)
* The is-empty, min-index, min-key, size, contains and key-of operations take constant time.
* Construction takes time proportional to the specified capacity.
*
* The arrays used in this structure have the first d indices empty,
* it apparently helps with caching effects.
*
*
@author
Tristan Claverie
*/
public
class
IndexMultiwayMinPQ
<
Key
>
implements
Iterable
<
Integer
>
{
private
final
int
d
;
//Dimension of the heap
private
int
n
;
//Number of keys currently in the queue
private
int
nmax
;
//Maximum number of items in the queue
private
int
[]
pq
;
//Multiway heap
private
int
[]
qp
;
//Inverse of pq : qp[pq[i]] = pq[qp[i]] = i
private
Key
[]
keys
;
//keys[i] = priority of i
private
final
Comparator
<
Key
>
comp
;
//Comparator over the keys
/**
* Initializes an empty indexed priority queue with indices between {
@code
0} to {
@code
N-1}
* Worst case is O(n)
*
@param
N number of keys in the priority queue, index from {
@code
0} to {
@code
N-1}
*
@param
D dimension of the heap
*
@throws
java.lang.IllegalArgumentException if {
@code
N < 0}
*
@throws
java.lang.IllegalArgumentException if {
@code
D < 2}
*/
public
IndexMultiwayMinPQ
(
int
N
,
int
D
)
{
if
(
N
<
0
)
throw
new
IllegalArgumentException
(
"Maximum number of elements cannot be negative"
);
if
(
D
<
2
)
throw
new
IllegalArgumentException
(
"Dimension should be 2 or over"
);
this
.
d
=
D
;
nmax
=
N
;
pq
=
new
int
[
nmax
+
D
];
qp
=
new
int
[
nmax
+
D
];
keys
=
(
Key
[])
new
Comparable
[
nmax
+
D
];
for
(
int
i
=
0
;
i
<
nmax
+
D
;
qp
[
i
++
]
=
-
1
);
comp
=
new
MyComparator
();
}
/**
* Initializes an empty indexed priority queue with indices between {
@code
0} to {
@code
N-1}
* Worst case is O(n)
*
@param
N number of keys in the priority queue, index from {
@code
0} to {
@code
N-1}
*
@param
D dimension of the heap
*
@param
C a Comparator over the keys
*
@throws
java.lang.IllegalArgumentException if {
@code
N < 0}
*
@throws
java.lang.IllegalArgumentException if {
@code
D < 2}
*/
public
IndexMultiwayMinPQ
(
int
N
,
Comparator
<
Key
>
C
,
int
D
)
{
if
(
N
<
0
)
throw
new
IllegalArgumentException
(
"Maximum number of elements cannot be negative"
);
if
(
D
<
2
)
throw
new
IllegalArgumentException
(
"Dimension should be 2 or over"
);
this
.
d
=
D
;
nmax
=
N
;
pq
=
new
int
[
nmax
+
D
];
qp
=
new
int
[
nmax
+
D
];
keys
=
(
Key
[])
new
Comparable
[
nmax
+
D
];
for
(
int
i
=
0
;
i
<
nmax
+
D
;
qp
[
i
++
]
=
-
1
);
comp
=
C
;
}
/**
* Whether the priority queue is empty
* Worst case is O(1)
*
@return
true if the priority queue is empty, false if not
*/
public
boolean
isEmpty
()
{
return
n
==
0
;
}
/**
* Does the priority queue contains the index i ?
* Worst case is O(1)
*
@param
i an index
*
@throws
java.lang.IllegalArgumentException if the specified index is invalid
*
@return
true if i is on the priority queue, false if not
*/
public
boolean
contains
(
int
i
)
{
if
(
i
<
0
||
i
>=
nmax
)
throw
new
IllegalArgumentException
();
return
qp
[
i
+
d
]
!=
–
1
;
}
/**
* Number of elements currently on the priority queue
* Worst case is O(1)
*
@return
the number of elements on the priority queue
*/
public
int
size
()
{
return
n
;
}
/**
* Associates a key with an index
* Worst case is O(log-d(n))
*
@param
i an index
*
@param
key a Key associated with i
*
@throws
java.lang.IllegalArgumentException if the specified index is invalid
*
@throws
java.lang.IllegalArgumentException if the index is already in the queue
*/
public
void
insert
(
int
i
,
Key
key
)
{
if
(
i
<
0
||
i
>=
nmax
)
throw
new
IllegalArgumentException
();
if
(
contains
(
i
))
throw
new
IllegalArgumentException
(
“Index already there”
);
keys
[
i
+
d
]
=
key
;
pq
[
n
+
d
]
=
i
;
qp
[
i
+
d
]
=
n
;
swim
(
n
++
);
}
/**
* Gets the index associated with the minimum key
* Worst case is O(1)
*
@throws
java.util.NoSuchElementException if the priority queue is empty
*
@return
the index associated with the minimum key
*/
public
int
minIndex
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Priority queue is empty”
);
return
pq
[
d
];
}
/**
* Gets the minimum key currently in the queue
* Worst case is O(1)
*
@throws
java.util.NoSuchElementException if the priority queue is empty
*
@return
the minimum key currently in the priority queue
*/
public
Key
minKey
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Priority queue is empty”
);
return
keys
[
pq
[
d
]
+
d
];
}
/**
* Deletes the minimum key
* Worst case is O(d*log-d(n))
*
@throws
java.util.NoSuchElementException if the priority queue is empty
*
@return
the index associated with the minimum key
*/
public
int
delMin
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Priority queue is empty”
);
int
min
=
pq
[
d
];
exch
(
0
,
—
n
);
sink
(
0
);
qp
[
min
+
d
]
=
–
1
;
keys
[
pq
[
n
+
d
]
+
d
]
=
null
;
pq
[
n
+
d
]
=
–
1
;
return
min
;
}
/**
* Gets the key associated with index i
* Worst case is O(1)
*
@param
i an index
*
@throws
java.lang.IllegalArgumentException if the specified index is invalid
*
@throws
java.lang.IllegalArgumentException if the index is not in the queue
*
@return
the key associated with index i
*/
public
Key
keyOf
(
int
i
)
{
if
(
i
<
0
||
i
>=
nmax
)
throw
new
IllegalArgumentException
();
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
“Specified index is not in the queue”
);
return
keys
[
i
+
d
];
}
/**
* Changes the key associated with index i to the given key
* If the given key is greater, Worst case is O(d*log-d(n))
* If the given key is lower, Worst case is O(log-d(n))
*
@param
i an index
*
@param
key the key to associate with i
*
@throws
java.lang.IllegalArgumentException if the specified index is invalid
*
@throws
java.lang.IllegalArgumentException if the index has no key associated with
*/
public
void
changeKey
(
int
i
,
Key
key
)
{
if
(
i
<
0
||
i
>=
nmax
)
throw
new
IllegalArgumentException
();
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
“Specified index is not in the queue”
);
Key
tmp
=
keys
[
i
+
d
];
keys
[
i
+
d
]
=
key
;
if
(
comp
.
compare
(
key
,
tmp
)
<=
0
)
{
swim
(
qp
[
i
+
d
]);}
else
{
sink
(
qp
[
i
+
d
]);}
}
/**
* Decreases the key associated with index i to the given key
* Worst case is O(log-d(n))
*
@param
i an index
*
@param
key the key to associate with i
*
@throws
java.lang.IllegalArgumentException if the specified index is invalid
*
@throws
java.util.NoSuchElementException if the index has no key associated with
*
@throws
java.lang.IllegalArgumentException if the given key is greater than the current key
*/
public
void
decreaseKey
(
int
i
,
Key
key
)
{
if
(
i
<
0
||
i
>=
nmax
)
throw
new
IllegalArgumentException
();
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
“Specified index is not in the queue”
);
if
(
comp
.
compare
(
keys
[
i
+
d
],
key
)
<=
0
)
throw
new
IllegalArgumentException
(
"Calling with this argument would not decrease the Key"
);
keys
[
i
+
d
]
=
key
;
swim
(
qp
[
i
+
d
]);
}
/**
* Increases the key associated with index i to the given key
* Worst case is O(d*log-d(n))
*
@param
i an index
*
@param
key the key to associate with i
*
@throws
java.lang.IllegalArgumentException if the specified index is invalid
*
@throws
java.util.NoSuchElementException if the index has no key associated with
*
@throws
java.lang.IllegalArgumentException if the given key is lower than the current key
*/
public
void
increaseKey
(
int
i
,
Key
key
)
{
if
(
i
<
0
||
i
>=
nmax
)
throw
new
IllegalArgumentException
();
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
“Specified index is not in the queue”
);
if
(
comp
.
compare
(
keys
[
i
+
d
],
key
)
>=
0
)
throw
new
IllegalArgumentException
(
“Calling with this argument would not increase the Key”
);
keys
[
i
+
d
]
=
key
;
sink
(
qp
[
i
+
d
]);
}
/**
* Deletes the key associated to the given index
* Worst case is O(d*log-d(n))
*
@param
i an index
*
@throws
java.lang.IllegalArgumentException if the specified index is invalid
*
@throws
java.util.NoSuchElementException if the given index has no key associated with
*/
public
void
delete
(
int
i
)
{
if
(
i
<
0
||
i
>=
nmax
)
throw
new
IllegalArgumentException
();
if
(
!
contains
(
i
))
throw
new
NoSuchElementException
(
“Specified index is not in the queue”
);
int
idx
=
qp
[
i
+
d
];
exch
(
idx
,
—
n
);
swim
(
idx
);
sink
(
idx
);
keys
[
i
+
d
]
=
null
;
qp
[
i
+
d
]
=
–
1
;
}
/***************************
* General helper functions
**************************/
//Compares two keys
private
boolean
greater
(
int
i
,
int
j
)
{
return
comp
.
compare
(
keys
[
pq
[
i
+
d
]
+
d
],
keys
[
pq
[
j
+
d
]
+
d
])
>
0
;
}
//Exchanges two keys
private
void
exch
(
int
x
,
int
y
)
{
int
i
=
x
+
d
,
j
=
y
+
d
;
int
swap
=
pq
[
i
];
pq
[
i
]
=
pq
[
j
];
pq
[
j
]
=
swap
;
qp
[
pq
[
i
]
+
d
]
=
x
;
qp
[
pq
[
j
]
+
d
]
=
y
;
}
/***************************
* Functions for moving upward or downward
**************************/
//Moves upward
private
void
swim
(
int
i
)
{
if
(
i
>
0
&&
greater
((
i
–
1
)
/
d
,
i
))
{
exch
(
i
,
(
i
–
1
)
/
d
);
swim
((
i
–
1
)
/
d
);
}
}
//Moves downward
private
void
sink
(
int
i
)
{
if
(
d
*
i
+
1
>=
n
)
return
;
int
min
=
minChild
(
i
);
while
(
min
<
n
&&
greater
(
i
,
min
))
{
exch
(
i
,
min
);
i
=
min
;
min
=
minChild
(
i
);
}
}
/***************************
* Deletes the minimum child
**************************/
//Return the minimum child of i
private
int
minChild
(
int
i
)
{
int
loBound
=
d
*
i
+
1
,
hiBound
=
d
*
i
+
d
;
int
min
=
loBound
;
for
(
int
cur
=
loBound
;
cur
<=
hiBound
;
cur
++
)
{
if
(
cur
<
n
&&
greater
(
min
,
cur
))
min
=
cur
;
}
return
min
;
}
/***************************
* Iterator
**************************/
/**
* Gets an Iterator over the indexes in the priority queue in ascending order
* The Iterator does not implement the remove() method
* iterator() : Worst case is O(n)
* next() : Worst case is O(d*log-d(n))
* hasNext() : Worst case is O(1)
*
@return
an Iterator over the indexes in the priority queue in ascending order
*/
public
Iterator
<
Integer
>
iterator
()
{
return
new
MyIterator
();
}
//Constructs an Iterator over the indices in linear time
private
class
MyIterator
implements
Iterator
<
Integer
>
{
IndexMultiwayMinPQ
<
Key
>
clone
;
public
MyIterator
()
{
clone
=
new
IndexMultiwayMinPQ
<
Key
>
(
nmax
,
comp
,
d
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
clone
.
insert
(
pq
[
i
+
d
],
keys
[
pq
[
i
+
d
]
+
d
]);
}
}
public
boolean
hasNext
()
{
return
!
clone
.
isEmpty
();
}
public
Integer
next
()
{
if
(
!
hasNext
())
throw
new
NoSuchElementException
();
return
clone
.
delMin
();
}
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
}
/***************************
* Comparator
**************************/
//default Comparator
private
class
MyComparator
implements
Comparator
<
Key
>
{
@
Override
public
int
compare
(
Key
key1
,
Key
key2
)
{
return
((
Comparable
<
Key
>
)
key1
).
compareTo
(
key2
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/In.java
edu/princeton/cs/algs4/In.java
/******************************************************************************
* Compilation: javac In.java
* Execution: java In (basic test — see source for required files)
* Dependencies: none
*
* Reads in data of various types from standard input, files, and URLs.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
io
.
BufferedInputStream
;
import
java
.
io
.
File
;
import
java
.
io
.
FileInputStream
;
import
java
.
io
.
IOException
;
import
java
.
io
.
InputStream
;
import
java
.
net
.
URL
;
import
java
.
net
.
Socket
;
// import java.net.HttpURLConnection;
import
java
.
net
.
URLConnection
;
import
java
.
util
.
ArrayList
;
import
java
.
util
.
InputMismatchException
;
import
java
.
util
.
Locale
;
import
java
.
util
.
NoSuchElementException
;
import
java
.
util
.
Scanner
;
import
java
.
util
.
regex
.
Pattern
;
/**
* Input. This class provides methods for reading strings
* and numbers from standard input, file input, URLs, and sockets.
*
* The Locale used is: language = English, country = US. This is consistent
* with the formatting conventions with Java floating-point literals,
* command-line arguments (via {
@link
Double#parseDouble(String)})
* and standard output.
*
* For additional documentation, see
* Section 3.1 of
* Computer Science: An Interdisciplinary Approach
* by Robert Sedgewick and Kevin Wayne.
*
* Like {
@link
Scanner}, reading a token also consumes preceding Java
* whitespace, reading a full line consumes
* the following end-of-line delimeter, while reading a character consumes
* nothing extra.
*
* Whitespace is defined in {
@link
Character#isWhitespace(char)}. Newlines
* consist of \n, \r, \r\n, and Unicode hex code points 0x2028, 0x2029, 0x0085;
* Scanner.java (NB: Java 6u23 and earlier uses only \r, \r, \r\n).
*
*
@author
David Pritchard
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
In
{
///// begin: section (1 of 2) of code duplicated from In to StdIn.
// assume Unicode UTF-8 encoding
private
static
final
String
CHARSET_NAME
=
“UTF-8”
;
// assume language = English, country = US for consistency with System.out.
private
static
final
Locale
LOCALE
=
Locale
.
US
;
// the default token separator; we maintain the invariant that this value
// is held by the scanner’s delimiter between calls
private
static
final
Pattern
WHITESPACE_PATTERN
=
Pattern
.
compile
(
“\\p{javaWhitespace}+”
);
// makes whitespace characters significant
private
static
final
Pattern
EMPTY_PATTERN
=
Pattern
.
compile
(
“”
);
// used to read the entire input. source:
// http://weblogs.java.net/blog/pat/archive/2004/10/stupid_scanner_1.html
private
static
final
Pattern
EVERYTHING_PATTERN
=
Pattern
.
compile
(
“\\A”
);
//// end: section (1 of 2) of code duplicated from In to StdIn.
private
Scanner
scanner
;
/**
* Initializes an input stream from standard input.
*/
public
In
()
{
scanner
=
new
Scanner
(
new
BufferedInputStream
(
System
.
in
),
CHARSET_NAME
);
scanner
.
useLocale
(
LOCALE
);
}
/**
* Initializes an input stream from a socket.
*
*
@param
socket the socket
*
@throws
IllegalArgumentException if cannot open {
@code
socket}
*
@throws
IllegalArgumentException if {
@code
socket} is {
@code
null}
*/
public
In
(
Socket
socket
)
{
if
(
socket
==
null
)
throw
new
IllegalArgumentException
(
“socket argument is null”
);
try
{
InputStream
is
=
socket
.
getInputStream
();
scanner
=
new
Scanner
(
new
BufferedInputStream
(
is
),
CHARSET_NAME
);
scanner
.
useLocale
(
LOCALE
);
}
catch
(
IOException
ioe
)
{
throw
new
IllegalArgumentException
(
“Could not open ”
+
socket
,
ioe
);
}
}
/**
* Initializes an input stream from a URL.
*
*
@param
url the URL
*
@throws
IllegalArgumentException if cannot open {
@code
url}
*
@throws
IllegalArgumentException if {
@code
url} is {
@code
null}
*/
public
In
(
URL url
)
{
if
(
url
==
null
)
throw
new
IllegalArgumentException
(
“url argument is null”
);
try
{
URLConnection
site
=
url
.
openConnection
();
InputStream
is
=
site
.
getInputStream
();
scanner
=
new
Scanner
(
new
BufferedInputStream
(
is
),
CHARSET_NAME
);
scanner
.
useLocale
(
LOCALE
);
}
catch
(
IOException
ioe
)
{
throw
new
IllegalArgumentException
(
“Could not open ”
+
url
,
ioe
);
}
}
/**
* Initializes an input stream from a file.
*
*
@param
file the file
*
@throws
IllegalArgumentException if cannot open {
@code
file}
*
@throws
IllegalArgumentException if {
@code
file} is {
@code
null}
*/
public
In
(
File
file
)
{
if
(
file
==
null
)
throw
new
IllegalArgumentException
(
“file argument is null”
);
try
{
// for consistency with StdIn, wrap with BufferedInputStream instead of use
// file as argument to Scanner
FileInputStream
fis
=
new
FileInputStream
(
file
);
scanner
=
new
Scanner
(
new
BufferedInputStream
(
fis
),
CHARSET_NAME
);
scanner
.
useLocale
(
LOCALE
);
}
catch
(
IOException
ioe
)
{
throw
new
IllegalArgumentException
(
“Could not open ”
+
file
,
ioe
);
}
}
/**
* Initializes an input stream from a filename or web page name.
*
*
@param
name the filename or web page name
*
@throws
IllegalArgumentException if cannot open {
@code
name} as
* a file or URL
*
@throws
IllegalArgumentException if {
@code
name} is {
@code
null}
*/
public
In
(
String
name
)
{
if
(
name
==
null
)
throw
new
IllegalArgumentException
(
“argument is null”
);
try
{
// first try to read file from local file system
File
file
=
new
File
(
name
);
if
(
file
.
exists
())
{
// for consistency with StdIn, wrap with BufferedInputStream instead of use
// file as argument to Scanner
FileInputStream
fis
=
new
FileInputStream
(
file
);
scanner
=
new
Scanner
(
new
BufferedInputStream
(
fis
),
CHARSET_NAME
);
scanner
.
useLocale
(
LOCALE
);
return
;
}
// resource relative to .class file
URL url
=
getClass
().
getResource
(
name
);
// resource relative to classloader root
if
(
url
==
null
)
{
url
=
getClass
().
getClassLoader
().
getResource
(
name
);
}
// or URL from web
if
(
url
==
null
)
{
url
=
new
URL
(
name
);
}
URLConnection
site
=
url
.
openConnection
();
// in order to set User-Agent, replace above line with these two
// HttpURLConnection site = (HttpURLConnection) url.openConnection();
// site.addRequestProperty(“User-Agent”, “Mozilla/4.76”);
InputStream
is
=
site
.
getInputStream
();
scanner
=
new
Scanner
(
new
BufferedInputStream
(
is
),
CHARSET_NAME
);
scanner
.
useLocale
(
LOCALE
);
}
catch
(
IOException
ioe
)
{
throw
new
IllegalArgumentException
(
“Could not open ”
+
name
,
ioe
);
}
}
/**
* Initializes an input stream from a given {
@link
Scanner} source; use with
* {
@code
new Scanner(String)} to read from a string.
*
* Note that this does not create a defensive copy, so the
* scanner will be mutated as you read on.
*
*
@param
scanner the scanner
*
@throws
IllegalArgumentException if {
@code
scanner} is {
@code
null}
*/
public
In
(
Scanner
scanner
)
{
if
(
scanner
==
null
)
throw
new
IllegalArgumentException
(
“scanner argument is null”
);
this
.
scanner
=
scanner
;
}
/**
* Returns true if this input stream exists.
*
*
@return
{
@code
true} if this input stream exists; {
@code
false} otherwise
*/
public
boolean
exists
()
{
return
scanner
!=
null
;
}
//// begin: section (2 of 2) of code duplicated from In to StdIn,
//// with all methods changed from “public” to “public static”.
/**
* Returns true if input stream is empty (except possibly whitespace).
* Use this to know whether the next call to {
@link
#readString()},
* {
@link
#readDouble()}, etc will succeed.
*
*
@return
{
@code
true} if this input stream is empty (except possibly whitespace);
* {
@code
false} otherwise
*/
public
boolean
isEmpty
()
{
return
!
scanner
.
hasNext
();
}
/**
* Returns true if this input stream has a next line.
* Use this method to know whether the
* next call to {
@link
#readLine()} will succeed.
* This method is functionally equivalent to {
@link
#hasNextChar()}.
*
*
@return
{
@code
true} if this input stream has more input (including whitespace);
* {
@code
false} otherwise
*/
public
boolean
hasNextLine
()
{
return
scanner
.
hasNextLine
();
}
/**
* Returns true if this input stream has more input (including whitespace).
* Use this method to know whether the next call to {
@link
#readChar()} will succeed.
* This method is functionally equivalent to {
@link
#hasNextLine()}.
*
*
@return
{
@code
true} if this input stream has more input (including whitespace);
* {
@code
false} otherwise
*/
public
boolean
hasNextChar
()
{
scanner
.
useDelimiter
(
EMPTY_PATTERN
);
boolean
result
=
scanner
.
hasNext
();
scanner
.
useDelimiter
(
WHITESPACE_PATTERN
);
return
result
;
}
/**
* Reads and returns the next line in this input stream.
*
*
@return
the next line in this input stream; {
@code
null} if no such line
*/
public
String
readLine
()
{
String
line
;
try
{
line
=
scanner
.
nextLine
();
}
catch
(
NoSuchElementException
e
)
{
line
=
null
;
}
return
line
;
}
/**
* Reads and returns the next character in this input stream.
*
*
@return
the next {
@code
char} in this input stream
*
@throws
NoSuchElementException if the input stream is empty
*/
public
char
readChar
()
{
scanner
.
useDelimiter
(
EMPTY_PATTERN
);
try
{
String
ch
=
scanner
.
next
();
assert
ch
.
length
()
==
1
:
“Internal (Std)In.readChar() error!”
+
” Please contact the authors.”
;
scanner
.
useDelimiter
(
WHITESPACE_PATTERN
);
return
ch
.
charAt
(
0
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attempts to read a ‘char’ value from the input stream, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads and returns the remainder of this input stream, as a string.
*
*
@return
the remainder of this input stream, as a string
*/
public
String
readAll
()
{
if
(
!
scanner
.
hasNextLine
())
return
“”
;
String
result
=
scanner
.
useDelimiter
(
EVERYTHING_PATTERN
).
next
();
// not that important to reset delimeter, since now scanner is empty
scanner
.
useDelimiter
(
WHITESPACE_PATTERN
);
// but let’s do it anyway
return
result
;
}
/**
* Reads the next token from this input stream and returns it as a {
@code
String}.
*
*
@return
the next {
@code
String} in this input stream
*
@throws
NoSuchElementException if the input stream is empty
*/
public
String
readString
()
{
try
{
return
scanner
.
next
();
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attempts to read a ‘String’ value from the input stream, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from this input stream, parses it as a {
@code
int},
* and returns the {
@code
int}.
*
*
@return
the next {
@code
int} in this input stream
*
@throws
NoSuchElementException if the input stream is empty
*
@throws
InputMismatchException if the next token cannot be parsed as an {
@code
int}
*/
public
int
readInt
()
{
try
{
return
scanner
.
nextInt
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read an ‘int’ value from the input stream, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attemps to read an ‘int’ value from the input stream, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from this input stream, parses it as a {
@code
double},
* and returns the {
@code
double}.
*
*
@return
the next {
@code
double} in this input stream
*
@throws
NoSuchElementException if the input stream is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
double}
*/
public
double
readDouble
()
{
try
{
return
scanner
.
nextDouble
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read a ‘double’ value from the input stream, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attemps to read a ‘double’ value from the input stream, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from this input stream, parses it as a {
@code
float},
* and returns the {
@code
float}.
*
*
@return
the next {
@code
float} in this input stream
*
@throws
NoSuchElementException if the input stream is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
float}
*/
public
float
readFloat
()
{
try
{
return
scanner
.
nextFloat
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read a ‘float’ value from the input stream, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attemps to read a ‘float’ value from the input stream, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from this input stream, parses it as a {
@code
long},
* and returns the {
@code
long}.
*
*
@return
the next {
@code
long} in this input stream
*
@throws
NoSuchElementException if the input stream is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
long}
*/
public
long
readLong
()
{
try
{
return
scanner
.
nextLong
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read a ‘long’ value from the input stream, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attemps to read a ‘long’ value from the input stream, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from this input stream, parses it as a {
@code
short},
* and returns the {
@code
short}.
*
*
@return
the next {
@code
short} in this input stream
*
@throws
NoSuchElementException if the input stream is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
short}
*/
public
short
readShort
()
{
try
{
return
scanner
.
nextShort
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read a ‘short’ value from the input stream, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attemps to read a ‘short’ value from the input stream, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from this input stream, parses it as a {
@code
byte},
* and returns the {
@code
byte}.
*
* To read binary data, use {
@link
BinaryIn}.
*
*
@return
the next {
@code
byte} in this input stream
*
@throws
NoSuchElementException if the input stream is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
byte}
*/
public
byte
readByte
()
{
try
{
return
scanner
.
nextByte
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read a ‘byte’ value from the input stream, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attemps to read a ‘byte’ value from the input stream, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from this input stream, parses it as a {
@code
boolean}
* (interpreting either {
@code
“true”} or {
@code
“1”} as {
@code
true},
* and either {
@code
“false”} or {
@code
“0”} as {
@code
false}).
*
*
@return
the next {
@code
boolean} in this input stream
*
@throws
NoSuchElementException if the input stream is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
boolean}
*/
public
boolean
readBoolean
()
{
try
{
String
token
=
readString
();
if
(
“true”
.
equalsIgnoreCase
(
token
))
return
true
;
if
(
“false”
.
equalsIgnoreCase
(
token
))
return
false
;
if
(
“1”
.
equals
(
token
))
return
true
;
if
(
“0”
.
equals
(
token
))
return
false
;
throw
new
InputMismatchException
(
“attempts to read a ‘boolean’ value from the input stream, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attempts to read a ‘boolean’ value from the input stream, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads all remaining tokens from this input stream and returns them as
* an array of strings.
*
*
@return
all remaining tokens in this input stream, as an array of strings
*/
public
String
[]
readAllStrings
()
{
// we could use readAll.trim().split(), but that’s not consistent
// since trim() uses characters 0x00..0x20 as whitespace
String
[]
tokens
=
WHITESPACE_PATTERN
.
split
(
readAll
());
if
(
tokens
.
length
==
0
||
tokens
[
0
].
length
()
>
0
)
return
tokens
;
String
[]
decapitokens
=
new
String
[
tokens
.
length
–
1
];
for
(
int
i
=
0
;
i
<
tokens
.
length
-
1
;
i
++
)
decapitokens
[
i
]
=
tokens
[
i
+
1
];
return
decapitokens
;
}
/**
* Reads all remaining lines from this input stream and returns them as
* an array of strings.
*
*
@return
all remaining lines in this input stream, as an array of strings
*/
public
String
[]
readAllLines
()
{
ArrayList
<
String
>
lines
=
new
ArrayList
<
String
>
();
while
(
hasNextLine
())
{
lines
.
add
(
readLine
());
}
return
lines
.
toArray
(
new
String
[
lines
.
size
()]);
}
/**
* Reads all remaining tokens from this input stream, parses them as integers,
* and returns them as an array of integers.
*
*
@return
all remaining lines in this input stream, as an array of integers
*/
public
int
[]
readAllInts
()
{
String
[]
fields
=
readAllStrings
();
int
[]
vals
=
new
int
[
fields
.
length
];
for
(
int
i
=
0
;
i
<
fields
.
length
;
i
++
)
vals
[
i
]
=
Integer
.
parseInt
(
fields
[
i
]);
return
vals
;
}
/**
* Reads all remaining tokens from this input stream, parses them as longs,
* and returns them as an array of longs.
*
*
@return
all remaining lines in this input stream, as an array of longs
*/
public
long
[]
readAllLongs
()
{
String
[]
fields
=
readAllStrings
();
long
[]
vals
=
new
long
[
fields
.
length
];
for
(
int
i
=
0
;
i
<
fields
.
length
;
i
++
)
vals
[
i
]
=
Long
.
parseLong
(
fields
[
i
]);
return
vals
;
}
/**
* Reads all remaining tokens from this input stream, parses them as doubles,
* and returns them as an array of doubles.
*
*
@return
all remaining lines in this input stream, as an array of doubles
*/
public
double
[]
readAllDoubles
()
{
String
[]
fields
=
readAllStrings
();
double
[]
vals
=
new
double
[
fields
.
length
];
for
(
int
i
=
0
;
i
<
fields
.
length
;
i
++
)
vals
[
i
]
=
Double
.
parseDouble
(
fields
[
i
]);
return
vals
;
}
///// end: section (2 of 2) of code duplicated from In to StdIn */
/**
* Closes this input stream.
*/
public
void
close
()
{
scanner
.
close
();
}
/**
* Reads all integers from a file and returns them as
* an array of integers.
*
*
@param
filename the name of the file
*
@return
the integers in the file
*
@deprecated
Replaced by {
@code
new In(filename)}.{
@link
#readAllInts()}.
*/
@
Deprecated
public
static
int
[]
readInts
(
String
filename
)
{
return
new
In
(
filename
).
readAllInts
();
}
/**
* Reads all doubles from a file and returns them as
* an array of doubles.
*
*
@param
filename the name of the file
*
@return
the doubles in the file
*
@deprecated
Replaced by {
@code
new In(filename)}.{
@link
#readAllDoubles()}.
*/
@
Deprecated
public
static
double
[]
readDoubles
(
String
filename
)
{
return
new
In
(
filename
).
readAllDoubles
();
}
/**
* Reads all strings from a file and returns them as
* an array of strings.
*
*
@param
filename the name of the file
*
@return
the strings in the file
*
@deprecated
Replaced by {
@code
new In(filename)}.{
@link
#readAllStrings()}.
*/
@
Deprecated
public
static
String
[]
readStrings
(
String
filename
)
{
return
new
In
(
filename
).
readAllStrings
();
}
/**
* Reads all integers from standard input and returns them
* an array of integers.
*
*
@return
the integers on standard input
*
@deprecated
Replaced by {
@link
StdIn#readAllInts()}.
*/
@
Deprecated
public
static
int
[]
readInts
()
{
return
new
In
().
readAllInts
();
}
/**
* Reads all doubles from standard input and returns them as
* an array of doubles.
*
*
@return
the doubles on standard input
*
@deprecated
Replaced by {
@link
StdIn#readAllDoubles()}.
*/
@
Deprecated
public
static
double
[]
readDoubles
()
{
return
new
In
().
readAllDoubles
();
}
/**
* Reads all strings from standard input and returns them as
* an array of strings.
*
*
@return
the strings on standard input
*
@deprecated
Replaced by {
@link
StdIn#readAllStrings()}.
*/
@
Deprecated
public
static
String
[]
readStrings
()
{
return
new
In
().
readAllStrings
();
}
/**
* Unit tests the {
@code
In} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
;
String
urlName
=
"https://introcs.cs.princeton.edu/java/stdlib/InTest.txt"
;
// read from a URL
System
.
out
.
println
(
"readAll() from URL "
+
urlName
);
System
.
out
.
println
(
"---------------------------------------------------------------------------"
);
try
{
in = new In(urlName);
System.out.println(in.readAll());
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
// read one line at a time from URL System.out.println("readLine() from URL " + urlName);
System.out.println("---------------------------------------------------------------------------");
try {
in = new In(urlName);
while (!in.isEmpty()) {
String s = in.readLine();
System.out.println(s);
}
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
// read one string at a time from URL System.out.println("readString() from URL " + urlName);
System.out.println("---------------------------------------------------------------------------");
try {
in = new In(urlName);
while (!in.isEmpty()) {
String s = in.readString();
System.out.println(s);
}
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
// read one line at a time from file in current directory System.out.println("readLine() from current directory");
System.out.println("---------------------------------------------------------------------------");
try {
in = new In("./InTest.txt");
while (!in.isEmpty()) {
String s = in.readLine();
System.out.println(s);
}
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
// read one line at a time from file using relative path System.out.println("readLine() from relative path");
System.out.println("---------------------------------------------------------------------------");
try {
in = new In("../stdlib/InTest.txt");
while (!in.isEmpty()) {
String s = in.readLine();
System.out.println(s);
}
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
// read one char at a time System.out.println("readChar() from file");
System.out.println("---------------------------------------------------------------------------");
try {
in = new In("InTest.txt");
while (!in.isEmpty()) {
char c = in.readChar();
System.out.print(c);
}
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
System.out.println();
// read one line at a time from absolute OS X / Linux path System.out.println("readLine() from absolute OS X / Linux path");
System.out.println("---------------------------------------------------------------------------");
try {
in = new In("/n/fs/introcs/www/java/stdlib/InTest.txt");
while (!in.isEmpty()) {
String s = in.readLine();
System.out.println(s);
}
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
// read one line at a time from absolute Windows path System.out.println("readLine() from absolute Windows path");
System.out.println("---------------------------------------------------------------------------");
try {
in = new In("G:\\www\\introcs\\stdlib\\InTest.txt");
while (!in.isEmpty()) {
String s = in.readLine();
System.out.println(s);
}
System.out.println();
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
}
}
/****************************************************************************** * Copyright 2002-2020, Robert Sedgewick and Kevin Wayne. * * This file is part of algs4.jar, which accompanies the textbook * * Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne, * Addison-Wesley Professional, 2011, ISBN 0-321-57351-X. * http://algs4.cs.princeton.edu * * * algs4.jar is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * algs4.jar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with algs4.jar. If not, see http://www.gnu.org/licenses. ******************************************************************************/
edu/princeton/cs/algs4/InplaceMSD.java
edu/princeton/cs/algs4/InplaceMSD.java
/******************************************************************************
* Compilation: javac InplaceMSD.java
* Execution: java InplaceMSD < input.txt
* Dependencies: StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/51radix/words3.txt
* https://algs4.cs.princeton.edu/51radix/shells.txt
*
* Sort an array of strings or integers using in-place MSD radix sort.
*
* % java InplaceMSD < shells.txt
* are
* by
* sea
* seashells
* seashells
* sells
* sells
* she
* she
* shells
* shore
* surely
* the
* the
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
InplaceMSD} class provides static methods for sorting an
* array of extended ASCII strings using in-place MSD radix sort.
*
* For additional documentation,
* see Section 5.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Ivan Pesin
*/
public
class
InplaceMSD
{
private
static
final
int
R
=
256
;
// extended ASCII alphabet size
private
static
final
int
CUTOFF
=
15
;
// cutoff to insertion sort
// do not instantiate
private
InplaceMSD
()
{
}
/**
* Rearranges the array of extended ASCII strings in ascending order.
* This is an unstable sorting algorithm.
*
*
@param
a the array to be sorted
*/
public
static
void
sort
(
String
[]
a
)
{
int
n
=
a
.
length
;
sort
(
a
,
0
,
n
–
1
,
0
);
}
// return dth character of s, -1 if d = length of string
private
static
int
charAt
(
String
s
,
int
d
)
{
assert
d
>=
0
&&
d
<=
s
.
length
();
if
(
d
==
s
.
length
())
return
-
1
;
return
s
.
charAt
(
d
);
}
// sort from a[lo] to a[hi], starting at the dth character
private
static
void
sort
(
String
[]
a
,
int
lo
,
int
hi
,
int
d
)
{
// cutoff to insertion sort for small subarrays
if
(
hi
<=
lo
+
CUTOFF
)
{
insertion
(
a
,
lo
,
hi
,
d
);
return
;
}
// compute frequency counts
int
[]
heads
=
new
int
[
R
+
2
];
int
[]
tails
=
new
int
[
R
+
1
];
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
{
int
c
=
charAt
(
a
[
i
],
d
);
heads
[
c
+
2
]
++
;
}
// transform counts to indices
heads
[
0
]
=
lo
;
for
(
int
r
=
0
;
r
<
R
+
1
;
r
++
)
{
heads
[
r
+
1
]
+=
heads
[
r
];
tails
[
r
]
=
heads
[
r
+
1
];
}
// sort by d-th character in-place
for
(
int
r
=
0
;
r
<
R
+
1
;
r
++
)
{
while
(
heads
[
r
]
<
tails
[
r
])
{
int
c
=
charAt
(
a
[
heads
[
r
]],
d
);
while
(
c
+
1
!=
r
)
{
exch
(
a
,
heads
[
r
],
heads
[
c
+
1
]
++
);
c
=
charAt
(
a
[
heads
[
r
]],
d
);
}
heads
[
r
]
++
;
}
}
// recursively sort for each character (excludes sentinel -1)
for
(
int
r
=
0
;
r
<
R
;
r
++
)
sort
(
a
,
tails
[
r
],
tails
[
r
+
1
]
-
1
,
d
+
1
);
}
// insertion sort a[lo..hi], starting at dth character
private
static
void
insertion
(
String
[]
a
,
int
lo
,
int
hi
,
int
d
)
{
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
for
(
int
j
=
i
;
j
>
lo
&&
less
(
a
[
j
],
a
[
j
–
1
],
d
);
j
—
)
exch
(
a
,
j
,
j
–
1
);
}
// exchange a[i] and a[j]
private
static
void
exch
(
String
[]
a
,
int
i
,
int
j
)
{
String
temp
=
a
[
i
];
a
[
i
]
=
a
[
j
];
a
[
j
]
=
temp
;
}
// is v less than w, starting at character d
private
static
boolean
less
(
String
v
,
String
w
,
int
d
)
{
// assert v.substring(0, d).equals(w.substring(0, d));
for
(
int
i
=
d
;
i
<
Math
.
min
(
v
.
length
(),
w
.
length
());
i
++
)
{
if
(
v
.
charAt
(
i
)
<
w
.
charAt
(
i
))
return
true
;
if
(
v
.
charAt
(
i
)
>
w
.
charAt
(
i
))
return
false
;
}
return
v
.
length
()
<
w
.
length
();
}
/**
* Reads in a sequence of extended ASCII strings from standard input;
* in-place MSD radix sorts them;
* and prints them to standard output in ascending order.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
[]
a
=
StdIn
.
readAllStrings
();
int
n
=
a
.
length
;
sort
(
a
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
StdOut
.
println
(
a
[
i
]);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Insertion.java
edu/princeton/cs/algs4/Insertion.java
/******************************************************************************
* Compilation: javac Insertion.java
* Execution: java Insertion < input.txt
* Dependencies: StdOut.java StdIn.java
* Data files: https://algs4.cs.princeton.edu/21elementary/tiny.txt
* https://algs4.cs.princeton.edu/21elementary/words3.txt
*
* Sorts a sequence of strings from standard input using insertion sort.
*
* % more tiny.txt
* S O R T E X A M P L E
*
* % java Insertion < tiny.txt
* A E E L M O P R S T X [ one string per line ]
*
* % more words3.txt
* bed bug dad yes zoo ... all bad yet
*
* % java Insertion < words3.txt
* all bad bed bug dad ... yes yet zoo [ one string per line ]
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Comparator
;
/**
* The {
@code
Insertion} class provides static methods for sorting an
* array using insertion sort.
*
* In the worst case, this implementation makes ~ ½ n2
* compares and ~ ½ n2 exchanges to sort an array
* of length n. So, it is not suitable for sorting large arbitrary
* arrays. More precisely, the number of exchanges is exactly equal to the
* number of inversions. So, for example, it sorts a partially-sorted array
* in linear time.
*
* This sorting algorithm is stable.
* It uses Θ(1) extra memory (not including the input array).
*
* See InsertionPedantic.java
* for a version that eliminates the compiler warning.
*
* For additional documentation, see Section 2.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Insertion
{
// This class should not be instantiated.
private
Insertion
()
{
}
/**
* Rearranges the array in ascending order, using the natural order.
*
@param
a the array to be sorted
*/
public
static
void
sort
(
Comparable
[]
a
)
{
int
n
=
a
.
length
;
for
(
int
i
=
1
;
i
<
n
;
i
++
)
{
for
(
int
j
=
i
;
j
>
0
&&
less
(
a
[
j
],
a
[
j
–
1
]);
j
—
)
{
exch
(
a
,
j
,
j
–
1
);
}
assert
isSorted
(
a
,
0
,
i
);
}
assert
isSorted
(
a
);
}
/**
* Rearranges the subarray a[lo..hi) in ascending order, using the natural order.
*
@param
a the array to be sorted
*
@param
lo left endpoint (inclusive)
*
@param
hi right endpoint (exclusive)
*/
public
static
void
sort
(
Comparable
[]
a
,
int
lo
,
int
hi
)
{
for
(
int
i
=
lo
+
1
;
i
<
hi
;
i
++
)
{
for
(
int
j
=
i
;
j
>
lo
&&
less
(
a
[
j
],
a
[
j
–
1
]);
j
—
)
{
exch
(
a
,
j
,
j
–
1
);
}
}
assert
isSorted
(
a
,
lo
,
hi
);
}
/**
* Rearranges the array in ascending order, using a comparator.
*
@param
a the array
*
@param
comparator the comparator specifying the order
*/
public
static
void
sort
(
Object
[]
a
,
Comparator
comparator
)
{
int
n
=
a
.
length
;
for
(
int
i
=
1
;
i
<
n
;
i
++
)
{
for
(
int
j
=
i
;
j
>
0
&&
less
(
a
[
j
],
a
[
j
–
1
],
comparator
);
j
—
)
{
exch
(
a
,
j
,
j
–
1
);
}
assert
isSorted
(
a
,
0
,
i
,
comparator
);
}
assert
isSorted
(
a
,
comparator
);
}
/**
* Rearranges the subarray a[lo..hi) in ascending order, using a comparator.
*
@param
a the array
*
@param
lo left endpoint (inclusive)
*
@param
hi right endpoint (exclusive)
*
@param
comparator the comparator specifying the order
*/
public
static
void
sort
(
Object
[]
a
,
int
lo
,
int
hi
,
Comparator
comparator
)
{
for
(
int
i
=
lo
+
1
;
i
<
hi
;
i
++
)
{
for
(
int
j
=
i
;
j
>
lo
&&
less
(
a
[
j
],
a
[
j
–
1
],
comparator
);
j
—
)
{
exch
(
a
,
j
,
j
–
1
);
}
}
assert
isSorted
(
a
,
lo
,
hi
,
comparator
);
}
// return a permutation that gives the elements in a[] in ascending order
// do not change the original array a[]
/**
* Returns a permutation that gives the elements in the array in ascending order.
*
@param
a the array
*
@return
a permutation {
@code
p[]} such that {
@code
a[p[0]]}, {
@code
a[p[1]]},
* …, {
@code
a[p[n-1]]} are in ascending order
*/
public
static
int
[]
indexSort
(
Comparable
[]
a
)
{
int
n
=
a
.
length
;
int
[]
index
=
new
int
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
index
[
i
]
=
i
;
for
(
int
i
=
1
;
i
<
n
;
i
++
)
for
(
int
j
=
i
;
j
>
0
&&
less
(
a
[
index
[
j
]],
a
[
index
[
j
–
1
]]);
j
—
)
exch
(
index
,
j
,
j
–
1
);
return
index
;
}
/***************************************************************************
* Helper sorting functions.
***************************************************************************/
// is v < w ?
private
static
boolean
less
(
Comparable
v
,
Comparable
w
)
{
return
v
.
compareTo
(
w
)
<
0
;
}
// is v < w ?
private
static
boolean
less
(
Object
v
,
Object
w
,
Comparator
comparator
)
{
return
comparator
.
compare
(
v
,
w
)
<
0
;
}
// exchange a[i] and a[j]
private
static
void
exch
(
Object
[]
a
,
int
i
,
int
j
)
{
Object
swap
=
a
[
i
];
a
[
i
]
=
a
[
j
];
a
[
j
]
=
swap
;
}
// exchange a[i] and a[j] (for indirect sort)
private
static
void
exch
(
int
[]
a
,
int
i
,
int
j
)
{
int
swap
=
a
[
i
];
a
[
i
]
=
a
[
j
];
a
[
j
]
=
swap
;
}
/***************************************************************************
* Check if array is sorted - useful for debugging.
***************************************************************************/
private
static
boolean
isSorted
(
Comparable
[]
a
)
{
return
isSorted
(
a
,
0
,
a
.
length
);
}
// is the array a[lo..hi) sorted
private
static
boolean
isSorted
(
Comparable
[]
a
,
int
lo
,
int
hi
)
{
for
(
int
i
=
lo
+
1
;
i
<
hi
;
i
++
)
if
(
less
(
a
[
i
],
a
[
i
-
1
]))
return
false
;
return
true
;
}
private
static
boolean
isSorted
(
Object
[]
a
,
Comparator
comparator
)
{
return
isSorted
(
a
,
0
,
a
.
length
,
comparator
);
}
// is the array a[lo..hi) sorted
private
static
boolean
isSorted
(
Object
[]
a
,
int
lo
,
int
hi
,
Comparator
comparator
)
{
for
(
int
i
=
lo
+
1
;
i
<
hi
;
i
++
)
if
(
less
(
a
[
i
],
a
[
i
-
1
],
comparator
))
return
false
;
return
true
;
}
// print array to standard output
private
static
void
show
(
Comparable
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
StdOut
.
println
(
a
[
i
]);
}
}
/**
* Reads in a sequence of strings from standard input; insertion sorts them;
* and prints them to standard output in ascending order.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
[]
a
=
StdIn
.
readAllStrings
();
Insertion
.
sort
(
a
);
show
(
a
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/InsertionX.java
edu/princeton/cs/algs4/InsertionX.java
/******************************************************************************
* Compilation: javac InsertionX.java
* Execution: java InsertionX < input.txt
* Dependencies: StdOut.java StdIn.java
* Data files: https://algs4.cs.princeton.edu/21elementary/tiny.txt
* https://algs4.cs.princeton.edu/21elementary/words3.txt
*
* Sorts a sequence of strings from standard input using an optimized
* version of insertion sort that uses half exchanges instead of
* full exchanges to reduce data movement..
*
* % more tiny.txt
* S O R T E X A M P L E
*
* % java InsertionX < tiny.txt
* A E E L M O P R S T X [ one string per line ]
*
* % more words3.txt
* bed bug dad yes zoo ... all bad yet
*
* % java InsertionX < words3.txt
* all bad bed bug dad ... yes yet zoo [ one string per line ]
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
InsertionX} class provides static methods for sorting
* an array using an optimized version of insertion sort (with half exchanges
* and a sentinel).
*
* In the worst case, this implementation makes ~ 1/2 n2
* compares to sort an array of length n.
* So, it is not suitable for sorting large arrays
* (unless the number of inversions is small).
*
* This sorting algorithm is stable.
* It uses Θ(1) extra memory (not including the input array).
*
* For additional documentation, see
* Section 2.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
InsertionX
{
// This class should not be instantiated.
private
InsertionX
()
{
}
/**
* Rearranges the array in ascending order, using the natural order.
*
@param
a the array to be sorted
*/
public
static
void
sort
(
Comparable
[]
a
)
{
int
n
=
a
.
length
;
// put smallest element in position to serve as sentinel
int
exchanges
=
0
;
for
(
int
i
=
n
–
1
;
i
>
0
;
i
—
)
{
if
(
less
(
a
[
i
],
a
[
i
–
1
]))
{
exch
(
a
,
i
,
i
–
1
);
exchanges
++
;
}
}
if
(
exchanges
==
0
)
return
;
// insertion sort with half-exchanges
for
(
int
i
=
2
;
i
<
n
;
i
++
)
{
Comparable
v
=
a
[
i
];
int
j
=
i
;
while
(
less
(
v
,
a
[
j
-
1
]))
{
a
[
j
]
=
a
[
j
-
1
];
j
--
;
}
a
[
j
]
=
v
;
}
assert
isSorted
(
a
);
}
/***************************************************************************
* Helper sorting functions.
***************************************************************************/
// is v < w ?
private
static
boolean
less
(
Comparable
v
,
Comparable
w
)
{
return
v
.
compareTo
(
w
)
<
0
;
}
// exchange a[i] and a[j]
private
static
void
exch
(
Object
[]
a
,
int
i
,
int
j
)
{
Object
swap
=
a
[
i
];
a
[
i
]
=
a
[
j
];
a
[
j
]
=
swap
;
}
/***************************************************************************
* Check if array is sorted - useful for debugging.
***************************************************************************/
private
static
boolean
isSorted
(
Comparable
[]
a
)
{
for
(
int
i
=
1
;
i
<
a
.
length
;
i
++
)
if
(
less
(
a
[
i
],
a
[
i
-
1
]))
return
false
;
return
true
;
}
// print array to standard output
private
static
void
show
(
Comparable
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
StdOut
.
println
(
a
[
i
]);
}
}
/**
* Reads in a sequence of strings from standard input; insertion sorts them;
* and prints them to standard output in ascending order.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
[]
a
=
StdIn
.
readAllStrings
();
InsertionX
.
sort
(
a
);
show
(
a
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Interval1D.java
edu/princeton/cs/algs4/Interval1D.java
/******************************************************************************
* Compilation: javac Interval1D.java
* Execution: java Interval1D
* Dependencies: StdOut.java
*
* 1-dimensional interval data type.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Arrays
;
import
java
.
util
.
Comparator
;
/**
* The {
@code
Interval1D} class represents a one-dimensional interval.
* The interval is closed—it contains both endpoints.
* Intervals are immutable: their values cannot be changed after they are created.
* The class {
@code
Interval1D} includes methods for checking whether
* an interval contains a point and determining whether two intervals intersect.
*
* For additional documentation,
* see Section 1.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Interval1D
{
/**
* Compares two intervals by min endpoint.
*/
public
static
final
Comparator
<
Interval1D
>
MIN_ENDPOINT_ORDER
=
new
MinEndpointComparator
();
/**
* Compares two intervals by max endpoint.
*/
public
static
final
Comparator
<
Interval1D
>
MAX_ENDPOINT_ORDER
=
new
MaxEndpointComparator
();
/**
* Compares two intervals by length.
*/
public
static
final
Comparator
<
Interval1D
>
LENGTH_ORDER
=
new
LengthComparator
();
private
final
double
min
;
private
final
double
max
;
/**
* Initializes a closed interval [min, max].
*
*
@param
min the smaller endpoint
*
@param
max the larger endpoint
*
@throws
IllegalArgumentException if the min endpoint is greater than the max endpoint
*
@throws
IllegalArgumentException if either {
@code
min} or {
@code
max}
* is {
@code
Double.NaN}, {
@code
Double.POSITIVE_INFINITY} or
* {
@code
Double.NEGATIVE_INFINITY}
*/
public
Interval1D
(
double
min
,
double
max
)
{
if
(
Double
.
isInfinite
(
min
)
||
Double
.
isInfinite
(
max
))
throw
new
IllegalArgumentException
(
“Endpoints must be finite”
);
if
(
Double
.
isNaN
(
min
)
||
Double
.
isNaN
(
max
))
throw
new
IllegalArgumentException
(
“Endpoints cannot be NaN”
);
// convert -0.0 to +0.0
if
(
min
==
0.0
)
min
=
0.0
;
if
(
max
==
0.0
)
max
=
0.0
;
if
(
min
<=
max
)
{
this
.
min
=
min
;
this
.
max
=
max
;
}
else
throw
new
IllegalArgumentException
(
"Illegal interval"
);
}
/**
* Returns the left endpoint of this interval.
*
*
@return
the left endpoint of this interval
*
@deprecated
Replaced by {
@link
#min()}.
*/
@
Deprecated
public
double
left
()
{
return
min
;
}
/**
* Returns the right endpoint of this interval.
*
@return
the right endpoint of this interval
*
@deprecated
Replaced by {
@link
#max()}.
*/
@
Deprecated
public
double
right
()
{
return
max
;
}
/**
* Returns the min endpoint of this interval.
*
*
@return
the min endpoint of this interval
*/
public
double
min
()
{
return
min
;
}
/**
* Returns the max endpoint of this interval.
*
*
@return
the max endpoint of this interval
*/
public
double
max
()
{
return
max
;
}
/**
* Returns true if this interval intersects the specified interval.
*
*
@param
that the other interval
*
@return
{
@code
true} if this interval intersects the argument interval;
* {
@code
false} otherwise
*/
public
boolean
intersects
(
Interval1D
that
)
{
if
(
this
.
max
<
that
.
min
)
return
false
;
if
(
that
.
max
<
this
.
min
)
return
false
;
return
true
;
}
/**
* Returns true if this interval contains the specified value.
*
*
@param
x the value
*
@return
{
@code
true} if this interval contains the value {
@code
x};
* {
@code
false} otherwise
*/
public
boolean
contains
(
double
x
)
{
return
(
min
<=
x
)
&&
(
x
<=
max
);
}
/**
* Returns the length of this interval.
*
*
@return
the length of this interval (max - min)
*/
public
double
length
()
{
return
max
-
min
;
}
/**
* Returns a string representation of this interval.
*
*
@return
a string representation of this interval in the form [min, max]
*/
public
String
toString
()
{
return
"["
+
min
+
", "
+
max
+
"]"
;
}
/**
* Compares this transaction to the specified object.
*
*
@param
other the other interval
*
@return
{
@code
true} if this interval equals the other interval;
* {
@code
false} otherwise
*/
public
boolean
equals
(
Object
other
)
{
if
(
other
==
this
)
return
true
;
if
(
other
==
null
)
return
false
;
if
(
other
.
getClass
()
!=
this
.
getClass
())
return
false
;
Interval1D
that
=
(
Interval1D
)
other
;
return
this
.
min
==
that
.
min
&&
this
.
max
==
that
.
max
;
}
/**
* Returns an integer hash code for this interval.
*
*
@return
an integer hash code for this interval
*/
public
int
hashCode
()
{
int
hash1
=
((
Double
)
min
).
hashCode
();
int
hash2
=
((
Double
)
max
).
hashCode
();
return
31
*
hash1
+
hash2
;
}
// ascending order of min endpoint, breaking ties by max endpoint
private
static
class
MinEndpointComparator
implements
Comparator
<
Interval1D
>
{
public
int
compare
(
Interval1D
a
,
Interval1D
b
)
{
if
(
a
.
min
<
b
.
min
)
return
-
1
;
else
if
(
a
.
min
>
b
.
min
)
return
+
1
;
else
if
(
a
.
max
<
b
.
max
)
return
-
1
;
else
if
(
a
.
max
>
b
.
max
)
return
+
1
;
else
return
0
;
}
}
// ascending order of max endpoint, breaking ties by min endpoint
private
static
class
MaxEndpointComparator
implements
Comparator
<
Interval1D
>
{
public
int
compare
(
Interval1D
a
,
Interval1D
b
)
{
if
(
a
.
max
<
b
.
max
)
return
-
1
;
else
if
(
a
.
max
>
b
.
max
)
return
+
1
;
else
if
(
a
.
min
<
b
.
min
)
return
-
1
;
else
if
(
a
.
min
>
b
.
min
)
return
+
1
;
else
return
0
;
}
}
// ascending order of length
private
static
class
LengthComparator
implements
Comparator
<
Interval1D
>
{
public
int
compare
(
Interval1D
a
,
Interval1D
b
)
{
double
alen
=
a
.
length
();
double
blen
=
b
.
length
();
if
(
alen
<
blen
)
return
-
1
;
else
if
(
alen
>
blen
)
return
+
1
;
else
return
0
;
}
}
/**
* Unit tests the {
@code
Interval1D} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
Interval1D
[]
intervals
=
new
Interval1D
[
4
];
intervals
[
0
]
=
new
Interval1D
(
15.0
,
33.0
);
intervals
[
1
]
=
new
Interval1D
(
45.0
,
60.0
);
intervals
[
2
]
=
new
Interval1D
(
20.0
,
70.0
);
intervals
[
3
]
=
new
Interval1D
(
46.0
,
55.0
);
StdOut
.
println
(
“Unsorted”
);
for
(
int
i
=
0
;
i
<
intervals
.
length
;
i
++
)
StdOut
.
println
(
intervals
[
i
]);
StdOut
.
println
();
StdOut
.
println
(
"Sort by min endpoint"
);
Arrays
.
sort
(
intervals
,
Interval1D
.
MIN_ENDPOINT_ORDER
);
for
(
int
i
=
0
;
i
<
intervals
.
length
;
i
++
)
StdOut
.
println
(
intervals
[
i
]);
StdOut
.
println
();
StdOut
.
println
(
"Sort by max endpoint"
);
Arrays
.
sort
(
intervals
,
Interval1D
.
MAX_ENDPOINT_ORDER
);
for
(
int
i
=
0
;
i
<
intervals
.
length
;
i
++
)
StdOut
.
println
(
intervals
[
i
]);
StdOut
.
println
();
StdOut
.
println
(
"Sort by length"
);
Arrays
.
sort
(
intervals
,
Interval1D
.
LENGTH_ORDER
);
for
(
int
i
=
0
;
i
<
intervals
.
length
;
i
++
)
StdOut
.
println
(
intervals
[
i
]);
StdOut
.
println
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Interval2D.java
edu/princeton/cs/algs4/Interval2D.java
/******************************************************************************
* Compilation: javac Interval2D.java
* Execution: java Interval2D
* Dependencies: StdOut.java Interval1D.java StdDraw.java
*
* 2-dimensional interval data type.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Interval2D} class represents a closed two-dimensional interval,
* which represents all points (x, y) with both {
@code
xmin <= x <= xmax} and
* {
@code
ymin <= y <= ymax}.
* Two-dimensional intervals are immutable: their values cannot be changed
* after they are created.
* The class {
@code
Interval2D} includes methods for checking whether
* a two-dimensional interval contains a point and determining whether
* two two-dimensional intervals intersect.
*
* For additional documentation,
* see Section 1.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Interval2D
{
private
final
Interval1D
x
;
private
final
Interval1D
y
;
/**
* Initializes a two-dimensional interval.
*
@param
x the one-dimensional interval of x-coordinates
*
@param
y the one-dimensional interval of y-coordinates
*/
public
Interval2D
(
Interval1D
x
,
Interval1D
y
)
{
this
.
x
=
x
;
this
.
y
=
y
;
}
/**
* Does this two-dimensional interval intersect that two-dimensional interval?
*
@param
that the other two-dimensional interval
*
@return
true if this two-dimensional interval intersects
* that two-dimensional interval; false otherwise
*/
public
boolean
intersects
(
Interval2D
that
)
{
if
(
!
this
.
x
.
intersects
(
that
.
x
))
return
false
;
if
(
!
this
.
y
.
intersects
(
that
.
y
))
return
false
;
return
true
;
}
/**
* Does this two-dimensional interval contain the point p?
*
@param
p the two-dimensional point
*
@return
true if this two-dimensional interval contains the point p; false otherwise
*/
public
boolean
contains
(
Point2D
p
)
{
return
x
.
contains
(
p
.
x
())
&&
y
.
contains
(
p
.
y
());
}
/**
* Returns the area of this two-dimensional interval.
*
@return
the area of this two-dimensional interval
*/
public
double
area
()
{
return
x
.
length
()
*
y
.
length
();
}
/**
* Returns a string representation of this two-dimensional interval.
*
@return
a string representation of this two-dimensional interval
* in the form [xmin, xmax] x [ymin, ymax]
*/
public
String
toString
()
{
return
x
+
” x ”
+
y
;
}
/**
* Does this interval equal the other interval?
*
@param
other the other interval
*
@return
true if this interval equals the other interval; false otherwise
*/
public
boolean
equals
(
Object
other
)
{
if
(
other
==
this
)
return
true
;
if
(
other
==
null
)
return
false
;
if
(
other
.
getClass
()
!=
this
.
getClass
())
return
false
;
Interval2D
that
=
(
Interval2D
)
other
;
return
this
.
x
.
equals
(
that
.
x
)
&&
this
.
y
.
equals
(
that
.
y
);
}
/**
* Returns an integer hash code for this interval.
*
@return
an integer hash code for this interval
*/
public
int
hashCode
()
{
int
hash1
=
x
.
hashCode
();
int
hash2
=
y
.
hashCode
();
return
31
*
hash1
+
hash2
;
}
/**
* Draws this two-dimensional interval to standard draw.
*/
public
void
draw
()
{
double
xc
=
(
x
.
min
()
+
x
.
max
())
/
2.0
;
double
yc
=
(
y
.
min
()
+
y
.
max
())
/
2.0
;
StdDraw
.
rectangle
(
xc
,
yc
,
x
.
length
()
/
2.0
,
y
.
length
()
/
2.0
);
}
/**
* Unit tests the {
@code
Interval2D} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
double
xmin
=
Double
.
parseDouble
(
args
[
0
]);
double
xmax
=
Double
.
parseDouble
(
args
[
1
]);
double
ymin
=
Double
.
parseDouble
(
args
[
2
]);
double
ymax
=
Double
.
parseDouble
(
args
[
3
]);
int
trials
=
Integer
.
parseInt
(
args
[
4
]);
Interval1D
xInterval
=
new
Interval1D
(
xmin
,
xmax
);
Interval1D
yInterval
=
new
Interval1D
(
ymin
,
ymax
);
Interval2D
box
=
new
Interval2D
(
xInterval
,
yInterval
);
box
.
draw
();
Counter
counter
=
new
Counter
(
“hits”
);
for
(
int
t
=
0
;
t
<
trials
;
t
++
)
{
double
x
=
StdRandom
.
uniform
(
0.0
,
1.0
);
double
y
=
StdRandom
.
uniform
(
0.0
,
1.0
);
Point2D
point
=
new
Point2D
(
x
,
y
);
if
(
box
.
contains
(
point
))
counter
.
increment
();
else
point
.
draw
();
}
StdOut
.
println
(
counter
);
StdOut
.
printf
(
"box area = %.2f\n"
,
box
.
area
());
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Inversions.java
edu/princeton/cs/algs4/Inversions.java
/******************************************************************************
* Compilation: javac Inversions.java
* Execution: java Inversions < input.txt
* Dependencies: StdIn.java StdOut.java
*
* Read array of n integers and count number of inversions in n log n time.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Inversions} class provides static methods to count the
* number of inversions in either an array of integers or comparables.
* An inversion in an array {
@code
a[]} is a pair of indicies {
@code
i} and
* {
@code
j} such that {
@code
i < j} and {
@code
a[i] > a[j]}.
*
* This implementation uses a generalization of mergesort. The count
* operation takes Θ(n log n) time to count the
* number of inversions in any array of length n (assuming
* comparisons take constant time).
*
* For additional documentation, see
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Inversions
{
// do not instantiate
private
Inversions
()
{
}
// merge and count
private
static
long
merge
(
int
[]
a
,
int
[]
aux
,
int
lo
,
int
mid
,
int
hi
)
{
long
inversions
=
0
;
// copy to aux[]
for
(
int
k
=
lo
;
k
<=
hi
;
k
++
)
{
aux
[
k
]
=
a
[
k
];
}
// merge back to a[]
int
i
=
lo
,
j
=
mid
+
1
;
for
(
int
k
=
lo
;
k
<=
hi
;
k
++
)
{
if
(
i
>
mid
)
a
[
k
]
=
aux
[
j
++
];
else
if
(
j
>
hi
)
a
[
k
]
=
aux
[
i
++
];
else
if
(
aux
[
j
]
<
aux
[
i
])
{
a
[
k
]
=
aux
[
j
++
];
inversions
+=
(
mid
-
i
+
1
);
}
else
a
[
k
]
=
aux
[
i
++
];
}
return
inversions
;
}
// return the number of inversions in the subarray b[lo..hi]
// side effect b[lo..hi] is rearranged in ascending order
private
static
long
count
(
int
[]
a
,
int
[]
b
,
int
[]
aux
,
int
lo
,
int
hi
)
{
long
inversions
=
0
;
if
(
hi
<=
lo
)
return
0
;
int
mid
=
lo
+
(
hi
-
lo
)
/
2
;
inversions
+=
count
(
a
,
b
,
aux
,
lo
,
mid
);
inversions
+=
count
(
a
,
b
,
aux
,
mid
+
1
,
hi
);
inversions
+=
merge
(
b
,
aux
,
lo
,
mid
,
hi
);
assert
inversions
==
brute
(
a
,
lo
,
hi
);
return
inversions
;
}
/**
* Returns the number of inversions in the integer array.
* The argument array is not modified.
*
@param
a the array
*
@return
the number of inversions in the array. An inversion is a pair of
* indicies {
@code
i} and {
@code
j} such that {
@code
i < j}
* and {
@code
a[i] > a[j]}.
*/
public
static
long
count
(
int
[]
a
)
{
int
[]
b
=
new
int
[
a
.
length
];
int
[]
aux
=
new
int
[
a
.
length
];
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
b
[
i
]
=
a
[
i
];
long
inversions
=
count
(
a
,
b
,
aux
,
0
,
a
.
length
-
1
);
return
inversions
;
}
// merge and count (Comparable version)
private
static
<
Key
extends
Comparable
<
Key
>>
long
merge
(
Key
[]
a
,
Key
[]
aux
,
int
lo
,
int
mid
,
int
hi
)
{
long
inversions
=
0
;
// copy to aux[]
for
(
int
k
=
lo
;
k
<=
hi
;
k
++
)
{
aux
[
k
]
=
a
[
k
];
}
// merge back to a[]
int
i
=
lo
,
j
=
mid
+
1
;
for
(
int
k
=
lo
;
k
<=
hi
;
k
++
)
{
if
(
i
>
mid
)
a
[
k
]
=
aux
[
j
++
];
else
if
(
j
>
hi
)
a
[
k
]
=
aux
[
i
++
];
else
if
(
less
(
aux
[
j
],
aux
[
i
]))
{
a
[
k
]
=
aux
[
j
++
];
inversions
+=
(
mid
–
i
+
1
);
}
else
a
[
k
]
=
aux
[
i
++
];
}
return
inversions
;
}
// return the number of inversions in the subarray b[lo..hi]
// side effect b[lo..hi] is rearranged in ascending order
private
static
<
Key
extends
Comparable
<
Key
>>
long
count
(
Key
[]
a
,
Key
[]
b
,
Key
[]
aux
,
int
lo
,
int
hi
)
{
long
inversions
=
0
;
if
(
hi
<=
lo
)
return
0
;
int
mid
=
lo
+
(
hi
-
lo
)
/
2
;
inversions
+=
count
(
a
,
b
,
aux
,
lo
,
mid
);
inversions
+=
count
(
a
,
b
,
aux
,
mid
+
1
,
hi
);
inversions
+=
merge
(
b
,
aux
,
lo
,
mid
,
hi
);
assert
inversions
==
brute
(
a
,
lo
,
hi
);
return
inversions
;
}
/**
* Returns the number of inversions in the comparable array.
* The argument array is not modified.
*
@param
a the array
*
@param
*
@return
the number of inversions in the array. An inversion is a pair of
* indicies {
@code
i} and {
@code
j} such that {
@code
i < j}
* and {
@code
a[i].compareTo(a[j]) > 0}.
*/
public
static
<
Key
extends
Comparable
<
Key
>>
long
count
(
Key
[]
a
)
{
Key
[]
b
=
a
.
clone
();
Key
[]
aux
=
a
.
clone
();
long
inversions
=
count
(
a
,
b
,
aux
,
0
,
a
.
length
–
1
);
return
inversions
;
}
// is v < w ?
private
static
<
Key
extends
Comparable
<
Key
>>
boolean
less
(
Key
v
,
Key
w
)
{
return
(
v
.
compareTo
(
w
)
<
0
);
}
// count number of inversions in a[lo..hi] via brute force (for debugging only)
private
static
<
Key
extends
Comparable
<
Key
>>
long
brute
(
Key
[]
a
,
int
lo
,
int
hi
)
{
long
inversions
=
0
;
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
for
(
int
j
=
i
+
1
;
j
<=
hi
;
j
++
)
if
(
less
(
a
[
j
],
a
[
i
]))
inversions
++
;
return
inversions
;
}
// count number of inversions in a[lo..hi] via brute force (for debugging only)
private
static
long
brute
(
int
[]
a
,
int
lo
,
int
hi
)
{
long
inversions
=
0
;
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
for
(
int
j
=
i
+
1
;
j
<=
hi
;
j
++
)
if
(
a
[
j
]
<
a
[
i
])
inversions
++
;
return
inversions
;
}
/**
* Reads a sequence of integers from standard input and
* prints the number of inversions to standard output.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
[]
a
=
StdIn
.
readAllInts
();
int
n
=
a
.
length
;
Integer
[]
b
=
new
Integer
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
b
[
i
]
=
a
[
i
];
StdOut
.
println
(
Inversions
.
count
(
a
));
StdOut
.
println
(
Inversions
.
count
(
b
));
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/KMP.java
edu/princeton/cs/algs4/KMP.java
/******************************************************************************
* Compilation: javac KMP.java
* Execution: java KMP pattern text
* Dependencies: StdOut.java
*
* Reads in two strings, the pattern and the input text, and
* searches for the pattern in the input text using the
* KMP algorithm.
*
* % java KMP abracadabra abacadabrabracabracadabrabrabracad
* text: abacadabrabracabracadabrabrabracad
* pattern: abracadabra
*
* % java KMP rab abacadabrabracabracadabrabrabracad
* text: abacadabrabracabracadabrabrabracad
* pattern: rab
*
* % java KMP bcara abacadabrabracabracadabrabrabracad
* text: abacadabrabracabracadabrabrabracad
* pattern: bcara
*
* % java KMP rabrabracad abacadabrabracabracadabrabrabracad
* text: abacadabrabracabracadabrabrabracad
* pattern: rabrabracad
*
* % java KMP abacad abacadabrabracabracadabrabrabracad
* text: abacadabrabracabracadabrabrabracad
* pattern: abacad
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
KMP} class finds the first occurrence of a pattern string
* in a text string.
*
* This implementation uses a version of the Knuth-Morris-Pratt substring search
* algorithm. The version takes time proportional to n + m R
* in the worst case, where n is the length of the text string,
* m is the length of the pattern, and R is the alphabet size.
* It uses extra space proportional to m R.
*
* For additional documentation,
* see Section 5.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*/
public
class
KMP
{
private
final
int
R
;
// the radix
private
int
[][]
dfa
;
// the KMP automoton
private
char
[]
pattern
;
// either the character array for the pattern
private
String
pat
;
// or the pattern string
/**
* Preprocesses the pattern string.
*
*
@param
pat the pattern string
*/
public
KMP
(
String
pat
)
{
this
.
R
=
256
;
this
.
pat
=
pat
;
// build DFA from pattern
int
m
=
pat
.
length
();
dfa
=
new
int
[
R
][
m
];
dfa
[
pat
.
charAt
(
0
)][
0
]
=
1
;
for
(
int
x
=
0
,
j
=
1
;
j
<
m
;
j
++
)
{
for
(
int
c
=
0
;
c
<
R
;
c
++
)
dfa
[
c
][
j
]
=
dfa
[
c
][
x
];
// Copy mismatch cases.
dfa
[
pat
.
charAt
(
j
)][
j
]
=
j
+
1
;
// Set match case.
x
=
dfa
[
pat
.
charAt
(
j
)][
x
];
// Update restart state.
}
}
/**
* Preprocesses the pattern string.
*
*
@param
pattern the pattern string
*
@param
R the alphabet size
*/
public
KMP
(
char
[]
pattern
,
int
R
)
{
this
.
R
=
R
;
this
.
pattern
=
new
char
[
pattern
.
length
];
for
(
int
j
=
0
;
j
<
pattern
.
length
;
j
++
)
this
.
pattern
[
j
]
=
pattern
[
j
];
// build DFA from pattern
int
m
=
pattern
.
length
;
dfa
=
new
int
[
R
][
m
];
dfa
[
pattern
[
0
]][
0
]
=
1
;
for
(
int
x
=
0
,
j
=
1
;
j
<
m
;
j
++
)
{
for
(
int
c
=
0
;
c
<
R
;
c
++
)
dfa
[
c
][
j
]
=
dfa
[
c
][
x
];
// Copy mismatch cases.
dfa
[
pattern
[
j
]][
j
]
=
j
+
1
;
// Set match case.
x
=
dfa
[
pattern
[
j
]][
x
];
// Update restart state.
}
}
/**
* Returns the index of the first occurrrence of the pattern string
* in the text string.
*
*
@param
txt the text string
*
@return
the index of the first occurrence of the pattern string
* in the text string; N if no such match
*/
public
int
search
(
String
txt
)
{
// simulate operation of DFA on text
int
m
=
pat
.
length
();
int
n
=
txt
.
length
();
int
i
,
j
;
for
(
i
=
0
,
j
=
0
;
i
<
n
&&
j
<
m
;
i
++
)
{
j
=
dfa
[
txt
.
charAt
(
i
)][
j
];
}
if
(
j
==
m
)
return
i
-
m
;
// found
return
n
;
// not found
}
/**
* Returns the index of the first occurrrence of the pattern string
* in the text string.
*
*
@param
text the text string
*
@return
the index of the first occurrence of the pattern string
* in the text string; N if no such match
*/
public
int
search
(
char
[]
text
)
{
// simulate operation of DFA on text
int
m
=
pattern
.
length
;
int
n
=
text
.
length
;
int
i
,
j
;
for
(
i
=
0
,
j
=
0
;
i
<
n
&&
j
<
m
;
i
++
)
{
j
=
dfa
[
text
[
i
]][
j
];
}
if
(
j
==
m
)
return
i
-
m
;
// found
return
n
;
// not found
}
/**
* Takes a pattern string and an input string as command-line arguments;
* searches for the pattern string in the text string; and prints
* the first occurrence of the pattern string in the text string.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
pat
=
args
[
0
];
String
txt
=
args
[
1
];
char
[]
pattern
=
pat
.
toCharArray
();
char
[]
text
=
txt
.
toCharArray
();
KMP kmp1
=
new
KMP
(
pat
);
int
offset1
=
kmp1
.
search
(
txt
);
KMP kmp2
=
new
KMP
(
pattern
,
256
);
int
offset2
=
kmp2
.
search
(
text
);
// print results
StdOut
.
println
(
"text: "
+
txt
);
StdOut
.
print
(
"pattern: "
);
for
(
int
i
=
0
;
i
<
offset1
;
i
++
)
StdOut
.
print
(
" "
);
StdOut
.
println
(
pat
);
StdOut
.
print
(
"pattern: "
);
for
(
int
i
=
0
;
i
<
offset2
;
i
++
)
StdOut
.
print
(
" "
);
StdOut
.
println
(
pat
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Knuth.java
edu/princeton/cs/algs4/Knuth.java
/******************************************************************************
* Compilation: javac Knuth.java
* Execution: java Knuth < list.txt
* Dependencies: StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/11model/cards.txt
* https://algs4.cs.princeton.edu/11model/cardsUnicode.txt
*
* Reads in a list of strings and prints them in random order.
* The Knuth (or Fisher-Yates) shuffling algorithm guarantees
* to rearrange the elements in uniformly random order, under
* the assumption that Math.random() generates independent and
* uniformly distributed numbers between 0 and 1.
*
* % more cards.txt
* 2C 3C 4C 5C 6C 7C 8C 9C 10C JC QC KC AC
* 2D 3D 4D 5D 6D 7D 8D 9D 10D JD QD KD AD
* 2H 3H 4H 5H 6H 7H 8H 9H 10H JH QH KH AH
* 2S 3S 4S 5S 6S 7S 8S 9S 10S JS QS KS AS
*
* % java Knuth < cards.txt
* 6H
* 9C
* 8H
* 7C
* JS
* ...
* KH
*
* % more cardsUnicode.txt
* 2♣ 3♣ 4♣ 5♣ 6♣ 7♣ 8♣ 9♣ 10♣ J♣ Q♣ K♣ A♣
* 2♦ 3♦ 4♦ 5♦ 6♦ 7♦ 8♦ 9♦ 10♦ J♦ Q♦ K♦ A♦
* 2♥ 3♥ 4♥ 5♥ 6♥ 7♥ 8♥ 9♥ 10♥ J♥ Q♥ K♥ A♥
* 2♠ 3♠ 4♠ 5♠ 6♠ 7♠ 8♠ 9♠ 10♠ J♠ Q♠ K♠ A♠
*
* % java Knuth < cardsUnicode.txt
* 2♠
* K♥
* 6♥
* 5♣
* J♣
* ...
* A♦
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Knuth} class provides a client for reading in a
* sequence of strings and shuffling them using the Knuth (or Fisher-Yates)
* shuffling algorithm. This algorithm guarantees to rearrange the
* elements in uniformly random order, under
* the assumption that Math.random() generates independent and
* uniformly distributed numbers between 0 and 1.
*
* For additional documentation,
* see Section 1.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
* See {
@link
StdRandom} for versions that shuffle arrays and
* subarrays of objects, doubles, and ints.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Knuth
{
// this class should not be instantiated
private
Knuth
()
{
}
/**
* Rearranges an array of objects in uniformly random order
* (under the assumption that {
@code
Math.random()} generates independent
* and uniformly distributed numbers between 0 and 1).
*
@param
a the array to be shuffled
*/
public
static
void
shuffle
(
Object
[]
a
)
{
int
n
=
a
.
length
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
// choose index uniformly in [0, i]
int
r
=
(
int
)
(
Math
.
random
()
*
(
i
+
1
));
Object
swap
=
a
[
r
];
a
[
r
]
=
a
[
i
];
a
[
i
]
=
swap
;
}
}
/**
* Rearranges an array of objects in uniformly random order
* (under the assumption that {
@code
Math.random()} generates independent
* and uniformly distributed numbers between 0 and 1).
*
@param
a the array to be shuffled
*/
public
static
void
shuffleAlternate
(
Object
[]
a
)
{
int
n
=
a
.
length
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
// choose index uniformly in [i, n-1]
int
r
=
i
+
(
int
)
(
Math
.
random
()
*
(
n
-
i
));
Object
swap
=
a
[
r
];
a
[
r
]
=
a
[
i
];
a
[
i
]
=
swap
;
}
}
/**
* Reads in a sequence of strings from standard input, shuffles
* them, and prints out the results.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// read in the data
String
[]
a
=
StdIn
.
readAllStrings
();
// shuffle the array
Knuth
.
shuffle
(
a
);
// print results.
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
StdOut
.
println
(
a
[
i
]);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/KosarajuSharirSCC.java
edu/princeton/cs/algs4/KosarajuSharirSCC.java
/******************************************************************************
* Compilation: javac KosarajuSharirSCC.java
* Execution: java KosarajuSharirSCC filename.txt
* Dependencies: Digraph.java TransitiveClosure.java StdOut.java In.java
* Data files: https://algs4.cs.princeton.edu/42digraph/tinyDG.txt
* https://algs4.cs.princeton.edu/42digraph/mediumDG.txt
* https://algs4.cs.princeton.edu/42digraph/largeDG.txt
*
* Compute the strongly-connected components of a digraph using the
* Kosaraju-Sharir algorithm.
*
* Runs in O(E + V) time.
*
* % java KosarajuSharirSCC tinyDG.txt
* 5 strong components
* 1
* 0 2 3 4 5
* 9 10 11 12
* 6 8
* 7
*
* % java KosarajuSharirSCC mediumDG.txt
* 10 strong components
* 21
* 2 5 6 8 9 11 12 13 15 16 18 19 22 23 25 26 28 29 30 31 32 33 34 35 37 38 39 40 42 43 44 46 47 48 49
* 14
* 3 4 17 20 24 27 36
* 41
* 7
* 45
* 1
* 0
* 10
*
* % java -Xss50m KosarajuSharirSCC mediumDG.txt
* 25 strong components
* 7 11 32 36 61 84 95 116 121 128 230 ...
* 28 73 80 104 115 143 149 164 184 185 ...
* 38 40 200 201 207 218 286 387 418 422 ...
* 12 14 56 78 87 103 216 269 271 272 ...
* 42 48 112 135 160 217 243 246 273 346 ...
* 46 76 96 97 224 237 297 303 308 309 ...
* 9 15 21 22 27 90 167 214 220 225 227 ...
* 74 99 133 146 161 166 202 205 245 262 ...
* 43 83 94 120 125 183 195 206 244 254 ...
* 1 13 54 91 92 93 106 140 156 194 208 ...
* 10 39 67 69 131 144 145 154 168 258 ...
* 6 52 66 113 118 122 139 147 212 213 ...
* 8 127 150 182 203 204 249 367 400 432 ...
* 63 65 101 107 108 136 169 170 171 173 ...
* 55 71 102 155 159 198 228 252 325 419 ...
* 4 25 34 58 70 152 172 196 199 210 226 ...
* 2 44 50 88 109 138 141 178 197 211 ...
* 57 89 129 162 174 179 188 209 238 276 ...
* 33 41 49 119 126 132 148 181 215 221 ...
* 3 18 23 26 35 64 105 124 157 186 251 ...
* 5 16 17 20 31 47 81 98 158 180 187 ...
* 24 29 51 59 75 82 100 114 117 134 151 ...
* 30 45 53 60 72 85 111 130 137 142 163 ...
* 19 37 62 77 79 110 153 352 353 361 ...
* 0 68 86 123 165 176 193 239 289 336 ...
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
KosarajuSharirSCC} class represents a data type for
* determining the strong components in a digraph.
* The id operation determines in which strong component
* a given vertex lies; the areStronglyConnected operation
* determines whether two vertices are in the same strong component;
* and the count operation determines the number of strong
* components.
*
* The component identifier of a component is one of the
* vertices in the strong component: two vertices have the same component
* identifier if and only if they are in the same strong component.
*
* This implementation uses the Kosaraju-Sharir algorithm.
* The constructor takes Θ(V + E) time,
* where V is the number of vertices and E
* is the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the digraph).
* For alternative implementations of the same API, see
* {
@link
TarjanSCC} and {
@link
GabowSCC}.
*
* For additional documentation, see
* Section 4.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
KosarajuSharirSCC
{
private
boolean
[]
marked
;
// marked[v] = has vertex v been visited?
private
int
[]
id
;
// id[v] = id of strong component containing v
private
int
count
;
// number of strongly-connected components
/**
* Computes the strong components of the digraph {
@code
G}.
*
@param
G the digraph
*/
public
KosarajuSharirSCC
(
Digraph
G
)
{
// compute reverse postorder of reverse graph
DepthFirstOrder
dfs
=
new
DepthFirstOrder
(
G
.
reverse
());
// run DFS on G, using reverse postorder to guide calculation
marked
=
new
boolean
[
G
.
V
()];
id
=
new
int
[
G
.
V
()];
for
(
int
v
:
dfs
.
reversePost
())
{
if
(
!
marked
[
v
])
{
dfs
(
G
,
v
);
count
++
;
}
}
// check that id[] gives strong components
assert
check
(
G
);
}
// DFS on graph G
private
void
dfs
(
Digraph
G
,
int
v
)
{
marked
[
v
]
=
true
;
id
[
v
]
=
count
;
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
!
marked
[
w
])
dfs
(
G
,
w
);
}
}
/**
* Returns the number of strong components.
*
@return
the number of strong components
*/
public
int
count
()
{
return
count
;
}
/**
* Are vertices {
@code
v} and {
@code
w} in the same strong component?
*
@param
v one vertex
*
@param
w the other vertex
*
@return
{
@code
true} if vertices {
@code
v} and {
@code
w} are in the same
* strong component, and {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*
@throws
IllegalArgumentException unless {
@code
0 <= w < V}
*/
public
boolean
stronglyConnected
(
int
v
,
int
w
)
{
validateVertex
(
v
);
validateVertex
(
w
);
return
id
[
v
]
==
id
[
w
];
}
/**
* Returns the component id of the strong component containing vertex {
@code
v}.
*
@param
v the vertex
*
@return
the component id of the strong component containing vertex {
@code
v}
*
@throws
IllegalArgumentException unless {
@code
0 <= s < V}
*/
public
int
id
(
int
v
)
{
validateVertex
(
v
);
return
id
[
v
];
}
// does the id[] array contain the strongly connected components?
private
boolean
check
(
Digraph
G
)
{
TransitiveClosure
tc
=
new
TransitiveClosure
(
G
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
for
(
int
w
=
0
;
w
<
G
.
V
();
w
++
)
{
if
(
stronglyConnected
(
v
,
w
)
!=
(
tc
.
reachable
(
v
,
w
)
&&
tc
.
reachable
(
w
,
v
)))
return
false
;
}
}
return
true
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
marked
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
KosarajuSharirSCC} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
Digraph
G
=
new
Digraph
(
in
);
KosarajuSharirSCC
scc
=
new
KosarajuSharirSCC
(
G
);
// number of connected components
int
m
=
scc
.
count
();
StdOut
.
println
(
m
+
” strong components”
);
// compute list of vertices in each strong component
Queue
<
Integer
>
[]
components
=
(
Queue
<
Integer
>
[])
new
Queue
[
m
];
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
components
[
i
]
=
new
Queue
<
Integer
>
();
}
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
components
[
scc
.
id
(
v
)].
enqueue
(
v
);
}
// print results
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
for
(
int
v
:
components
[
i
])
{
StdOut
.
print
(
v
+
" "
);
}
StdOut
.
println
();
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/KruskalMST.java
edu/princeton/cs/algs4/KruskalMST.java
/******************************************************************************
* Compilation: javac KruskalMST.java
* Execution: java KruskalMST filename.txt
* Dependencies: EdgeWeightedGraph.java Edge.java Queue.java MinPQ.java
* UF.java In.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/43mst/tinyEWG.txt
* https://algs4.cs.princeton.edu/43mst/mediumEWG.txt
* https://algs4.cs.princeton.edu/43mst/largeEWG.txt
*
* Compute a minimum spanning forest using Kruskal's algorithm.
*
* % java KruskalMST tinyEWG.txt
* 0-7 0.16000
* 2-3 0.17000
* 1-7 0.19000
* 0-2 0.26000
* 5-7 0.28000
* 4-5 0.35000
* 6-2 0.40000
* 1.81000
*
* % java KruskalMST mediumEWG.txt
* 168-231 0.00268
* 151-208 0.00391
* 7-157 0.00516
* 122-205 0.00647
* 8-152 0.00702
* 156-219 0.00745
* 28-198 0.00775
* 38-126 0.00845
* 10-123 0.00886
* ...
* 10.46351
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
KruskalMST} class represents a data type for computing a
* minimum spanning tree in an edge-weighted graph.
* The edge weights can be positive, zero, or negative and need not
* be distinct. If the graph is not connected, it computes a minimum
* spanning forest, which is the union of minimum spanning trees
* in each connected component. The {
@code
weight()} method returns the
* weight of a minimum spanning tree and the {
@code
edges()} method
* returns its edges.
*
* This implementation uses Krusal’s algorithm and the
* union-find data type.
* The constructor takes Θ(E log E) time in
* the worst case.
* Each instance method takes Θ(1) time.
* It uses Θ(E) extra space (not including the graph).
*
* For additional documentation,
* see Section 4.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
* For alternate implementations, see {
@link
LazyPrimMST}, {
@link
PrimMST},
* and {
@link
BoruvkaMST}.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
KruskalMST
{
private
static
final
double
FLOATING_POINT_EPSILON
=
1E-12
;
private
double
weight
;
// weight of MST
private
Queue
<
Edge
>
mst
=
new
Queue
<
Edge
>
();
// edges in MST
/**
* Compute a minimum spanning tree (or forest) of an edge-weighted graph.
*
@param
G the edge-weighted graph
*/
public
KruskalMST
(
EdgeWeightedGraph
G
)
{
// more efficient to build heap by passing array of edges
MinPQ
<
Edge
>
pq
=
new
MinPQ
<
Edge
>
();
for
(
Edge
e
:
G
.
edges
())
{
pq
.
insert
(
e
);
}
// run greedy algorithm
UF uf
=
new
UF
(
G
.
V
());
while
(
!
pq
.
isEmpty
()
&&
mst
.
size
()
<
G
.
V
()
-
1
)
{
Edge
e
=
pq
.
delMin
();
int
v
=
e
.
either
();
int
w
=
e
.
other
(
v
);
if
(
uf
.
find
(
v
)
!=
uf
.
find
(
w
))
{
// v-w does not create a cycle
uf
.
union
(
v
,
w
);
// merge v and w components
mst
.
enqueue
(
e
);
// add edge e to mst
weight
+=
e
.
weight
();
}
}
// check optimality conditions
assert
check
(
G
);
}
/**
* Returns the edges in a minimum spanning tree (or forest).
*
@return
the edges in a minimum spanning tree (or forest) as
* an iterable of edges
*/
public
Iterable
<
Edge
>
edges
()
{
return
mst
;
}
/**
* Returns the sum of the edge weights in a minimum spanning tree (or forest).
*
@return
the sum of the edge weights in a minimum spanning tree (or forest)
*/
public
double
weight
()
{
return
weight
;
}
// check optimality conditions (takes time proportional to E V lg* V)
private
boolean
check
(
EdgeWeightedGraph
G
)
{
// check total weight
double
total
=
0.0
;
for
(
Edge
e
:
edges
())
{
total
+=
e
.
weight
();
}
if
(
Math
.
abs
(
total
–
weight
())
>
FLOATING_POINT_EPSILON
)
{
System
.
err
.
printf
(
“Weight of edges does not equal weight(): %f vs. %f\n”
,
total
,
weight
());
return
false
;
}
// check that it is acyclic
UF uf
=
new
UF
(
G
.
V
());
for
(
Edge
e
:
edges
())
{
int
v
=
e
.
either
(),
w
=
e
.
other
(
v
);
if
(
uf
.
find
(
v
)
==
uf
.
find
(
w
))
{
System
.
err
.
println
(
“Not a forest”
);
return
false
;
}
uf
.
union
(
v
,
w
);
}
// check that it is a spanning forest
for
(
Edge
e
:
G
.
edges
())
{
int
v
=
e
.
either
(),
w
=
e
.
other
(
v
);
if
(
uf
.
find
(
v
)
!=
uf
.
find
(
w
))
{
System
.
err
.
println
(
“Not a spanning forest”
);
return
false
;
}
}
// check that it is a minimal spanning forest (cut optimality conditions)
for
(
Edge
e
:
edges
())
{
// all edges in MST except e
uf
=
new
UF
(
G
.
V
());
for
(
Edge
f
:
mst
)
{
int
x
=
f
.
either
(),
y
=
f
.
other
(
x
);
if
(
f
!=
e
)
uf
.
union
(
x
,
y
);
}
// check that e is min weight edge in crossing cut
for
(
Edge
f
:
G
.
edges
())
{
int
x
=
f
.
either
(),
y
=
f
.
other
(
x
);
if
(
uf
.
find
(
x
)
!=
uf
.
find
(
y
))
{
if
(
f
.
weight
()
<
e
.
weight
())
{
System
.
err
.
println
(
"Edge "
+
f
+
" violates cut optimality conditions"
);
return
false
;
}
}
}
}
return
true
;
}
/**
* Unit tests the {
@code
KruskalMST} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
EdgeWeightedGraph
G
=
new
EdgeWeightedGraph
(
in
);
KruskalMST
mst
=
new
KruskalMST
(
G
);
for
(
Edge
e
:
mst
.
edges
())
{
StdOut
.
println
(
e
);
}
StdOut
.
printf
(
"%.5f\n"
,
mst
.
weight
());
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/KWIK.java
edu/princeton/cs/algs4/KWIK.java
/******************************************************************************
* Compilation: javac KWIK.java
* Execution: java KWIK file.txt
* Dependencies: StdIn.java StdOut.java In.java SuffixArray.java
* Data files: https://algs4.cs.princeton.edu/63suffix/tale.txt
* https://algs4.cs.princeton.edu/63suffix/mobydick.txt
*
* Keyword-in-context search.
*
* % java KWIK tale.txt 15
* majesty
* most gracious majesty king george th
* rnkeys and the majesty of the law fir
* on against the majesty of the people
* se them to his majestys chief secreta
* h lists of his majestys forces and of
*
* the worst
* w the best and the worst are known to y
* f them give me the worst first there th
* for in case of the worst is a friend in
* e roomdoor and the worst is over then a
* pect mr darnay the worst its the wisest
* is his brother the worst of a bad race
* ss in them for the worst of health for
* you have seen the worst of her agitati
* cumwented into the worst of luck buuust
* n your brother the worst of the bad rac
* full share in the worst of the day pla
* mes to himself the worst of the strife
* f times it was the worst of times it wa
* ould hope that the worst was over well
* urage business the worst will be over i
* clesiastics of the worst world worldly
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
KWIK} class provides a {
@link
SuffixArray} client for computing
* all occurrences of a keyword in a given string, with surrounding context.
* This is known as keyword-in-context search.
*
* For additional documentation,
* see Section 6.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
KWIK
{
// Do not instantiate.
private
KWIK
()
{
}
/**
* Reads a string from a file specified as the first
* command-line argument; read an integer k specified as the
* second command line argument; then repeatedly processes
* use queries, printing all occurrences of the given query
* string in the text string with k characters of surrounding
* context on either side.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
int
context
=
Integer
.
parseInt
(
args
[
1
]);
// read in text
String
text
=
in
.
readAll
().
replaceAll
(
“\\s+”
,
” ”
);
int
n
=
text
.
length
();
// build suffix array
SuffixArray
sa
=
new
SuffixArray
(
text
);
// find all occurrences of queries and give context
while
(
StdIn
.
hasNextLine
())
{
String
query
=
StdIn
.
readLine
();
for
(
int
i
=
sa
.
rank
(
query
);
i
<
n
;
i
++
)
{
int
from1
=
sa
.
index
(
i
);
int
to1
=
Math
.
min
(
n
,
from1
+
query
.
length
());
if
(
!
query
.
equals
(
text
.
substring
(
from1
,
to1
)))
break
;
int
from2
=
Math
.
max
(
0
,
sa
.
index
(
i
)
-
context
);
int
to2
=
Math
.
min
(
n
,
sa
.
index
(
i
)
+
context
+
query
.
length
());
StdOut
.
println
(
text
.
substring
(
from2
,
to2
));
}
StdOut
.
println
();
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/LazyPrimMST.java
edu/princeton/cs/algs4/LazyPrimMST.java
/******************************************************************************
* Compilation: javac LazyPrimMST.java
* Execution: java LazyPrimMST filename.txt
* Dependencies: EdgeWeightedGraph.java Edge.java Queue.java
* MinPQ.java UF.java In.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/43mst/tinyEWG.txt
* https://algs4.cs.princeton.edu/43mst/mediumEWG.txt
* https://algs4.cs.princeton.edu/43mst/largeEWG.txt
*
* Compute a minimum spanning forest using a lazy version of Prim's
* algorithm.
*
* % java LazyPrimMST tinyEWG.txt
* 0-7 0.16000
* 1-7 0.19000
* 0-2 0.26000
* 2-3 0.17000
* 5-7 0.28000
* 4-5 0.35000
* 6-2 0.40000
* 1.81000
*
* % java LazyPrimMST mediumEWG.txt
* 0-225 0.02383
* 49-225 0.03314
* 44-49 0.02107
* 44-204 0.01774
* 49-97 0.03121
* 202-204 0.04207
* 176-202 0.04299
* 176-191 0.02089
* 68-176 0.04396
* 58-68 0.04795
* 10.46351
*
* % java LazyPrimMST largeEWG.txt
* ...
* 647.66307
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
LazyPrimMST} class represents a data type for computing a
* minimum spanning tree in an edge-weighted graph.
* The edge weights can be positive, zero, or negative and need not
* be distinct. If the graph is not connected, it computes a minimum
* spanning forest, which is the union of minimum spanning trees
* in each connected component. The {
@code
weight()} method returns the
* weight of a minimum spanning tree and the {
@code
edges()} method
* returns its edges.
*
* This implementation uses a lazy version of Prim’s algorithm
* with a binary heap of edges.
* The constructor takes Θ(E log E) time in
* the worst case, where V is the number of vertices and
* E is the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(E) extra space in the worst case
* (not including the edge-weighted graph).
*
* For additional documentation,
* see Section 4.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
* For alternate implementations, see {
@link
PrimMST}, {
@link
KruskalMST},
* and {
@link
BoruvkaMST}.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
LazyPrimMST
{
private
static
final
double
FLOATING_POINT_EPSILON
=
1E-12
;
private
double
weight
;
// total weight of MST
private
Queue
<
Edge
>
mst
;
// edges in the MST
private
boolean
[]
marked
;
// marked[v] = true iff v on tree
private
MinPQ
<
Edge
>
pq
;
// edges with one endpoint in tree
/**
* Compute a minimum spanning tree (or forest) of an edge-weighted graph.
*
@param
G the edge-weighted graph
*/
public
LazyPrimMST
(
EdgeWeightedGraph
G
)
{
mst
=
new
Queue
<
Edge
>
();
pq
=
new
MinPQ
<
Edge
>
();
marked
=
new
boolean
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
// run Prim from all vertices to
if
(
!
marked
[
v
])
prim
(
G
,
v
);
// get a minimum spanning forest
// check optimality conditions
assert
check
(
G
);
}
// run Prim's algorithm
private
void
prim
(
EdgeWeightedGraph
G
,
int
s
)
{
scan
(
G
,
s
);
while
(
!
pq
.
isEmpty
())
{
// better to stop when mst has V-1 edges
Edge
e
=
pq
.
delMin
();
// smallest edge on pq
int
v
=
e
.
either
(),
w
=
e
.
other
(
v
);
// two endpoints
assert
marked
[
v
]
||
marked
[
w
];
if
(
marked
[
v
]
&&
marked
[
w
])
continue
;
// lazy, both v and w already scanned
mst
.
enqueue
(
e
);
// add e to MST
weight
+=
e
.
weight
();
if
(
!
marked
[
v
])
scan
(
G
,
v
);
// v becomes part of tree
if
(
!
marked
[
w
])
scan
(
G
,
w
);
// w becomes part of tree
}
}
// add all edges e incident to v onto pq if the other endpoint has not yet been scanned
private
void
scan
(
EdgeWeightedGraph
G
,
int
v
)
{
assert
!
marked
[
v
];
marked
[
v
]
=
true
;
for
(
Edge
e
:
G
.
adj
(
v
))
if
(
!
marked
[
e
.
other
(
v
)])
pq
.
insert
(
e
);
}
/**
* Returns the edges in a minimum spanning tree (or forest).
*
@return
the edges in a minimum spanning tree (or forest) as
* an iterable of edges
*/
public
Iterable
<
Edge
>
edges
()
{
return
mst
;
}
/**
* Returns the sum of the edge weights in a minimum spanning tree (or forest).
*
@return
the sum of the edge weights in a minimum spanning tree (or forest)
*/
public
double
weight
()
{
return
weight
;
}
// check optimality conditions (takes time proportional to E V lg* V)
private
boolean
check
(
EdgeWeightedGraph
G
)
{
// check weight
double
totalWeight
=
0.0
;
for
(
Edge
e
:
edges
())
{
totalWeight
+=
e
.
weight
();
}
if
(
Math
.
abs
(
totalWeight
–
weight
())
>
FLOATING_POINT_EPSILON
)
{
System
.
err
.
printf
(
“Weight of edges does not equal weight(): %f vs. %f\n”
,
totalWeight
,
weight
());
return
false
;
}
// check that it is acyclic
UF uf
=
new
UF
(
G
.
V
());
for
(
Edge
e
:
edges
())
{
int
v
=
e
.
either
(),
w
=
e
.
other
(
v
);
if
(
uf
.
find
(
v
)
==
uf
.
find
(
w
))
{
System
.
err
.
println
(
“Not a forest”
);
return
false
;
}
uf
.
union
(
v
,
w
);
}
// check that it is a spanning forest
for
(
Edge
e
:
G
.
edges
())
{
int
v
=
e
.
either
(),
w
=
e
.
other
(
v
);
if
(
uf
.
find
(
v
)
!=
uf
.
find
(
w
))
{
System
.
err
.
println
(
“Not a spanning forest”
);
return
false
;
}
}
// check that it is a minimal spanning forest (cut optimality conditions)
for
(
Edge
e
:
edges
())
{
// all edges in MST except e
uf
=
new
UF
(
G
.
V
());
for
(
Edge
f
:
mst
)
{
int
x
=
f
.
either
(),
y
=
f
.
other
(
x
);
if
(
f
!=
e
)
uf
.
union
(
x
,
y
);
}
// check that e is min weight edge in crossing cut
for
(
Edge
f
:
G
.
edges
())
{
int
x
=
f
.
either
(),
y
=
f
.
other
(
x
);
if
(
uf
.
find
(
x
)
!=
uf
.
find
(
y
))
{
if
(
f
.
weight
()
<
e
.
weight
())
{
System
.
err
.
println
(
"Edge "
+
f
+
" violates cut optimality conditions"
);
return
false
;
}
}
}
}
return
true
;
}
/**
* Unit tests the {
@code
LazyPrimMST} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
EdgeWeightedGraph
G
=
new
EdgeWeightedGraph
(
in
);
LazyPrimMST
mst
=
new
LazyPrimMST
(
G
);
for
(
Edge
e
:
mst
.
edges
())
{
StdOut
.
println
(
e
);
}
StdOut
.
printf
(
"%.5f\n"
,
mst
.
weight
());
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/LinearProbingHashST.java
edu/princeton/cs/algs4/LinearProbingHashST.java
/******************************************************************************
* Compilation: javac LinearProbingHashST.java
* Execution: java LinearProbingHashST < input.txt
* Dependencies: StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/34hash/tinyST.txt
*
* Symbol-table implementation with linear-probing hash table.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
LinearProbingHashST} class represents a symbol table of generic
* key-value pairs.
* It supports the usual put, get, contains,
* delete, size, and is-empty methods.
* It also provides a keys method for iterating over all of the keys.
* A symbol table implements the associative array abstraction:
* when associating a value with a key that is already in the symbol table,
* the convention is to replace the old value with the new value.
* Unlike {
@link
java.util.Map}, this class uses the convention that
* values cannot be {
@code
null}—setting the
* value associated with a key to {
@code
null} is equivalent to deleting the key
* from the symbol table.
*
* This implementation uses a linear probing hash table. It requires that
* the key type overrides the {
@code
equals()} and {
@code
hashCode()} methods.
* The expected time per put, contains, or remove
* operation is constant, subject to the uniform hashing assumption.
* The size, and is-empty operations take constant time.
* Construction takes constant time.
*
* For additional documentation, see Section 3.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
* For other implementations, see {
@link
ST}, {
@link
BinarySearchST},
* {
@link
SequentialSearchST}, {
@link
BST}, {
@link
RedBlackBST}, and
* {
@link
SeparateChainingHashST},
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
LinearProbingHashST
<
Key
,
Value
>
{
private
static
final
int
INIT_CAPACITY
=
4
;
private
int
n
;
// number of key-value pairs in the symbol table
private
int
m
;
// size of linear probing table
private
Key
[]
keys
;
// the keys
private
Value
[]
vals
;
// the values
/**
* Initializes an empty symbol table.
*/
public
LinearProbingHashST
()
{
this
(
INIT_CAPACITY
);
}
/**
* Initializes an empty symbol table with the specified initial capacity.
*
*
@param
capacity the initial capacity
*/
public
LinearProbingHashST
(
int
capacity
)
{
m
=
capacity
;
n
=
0
;
keys
=
(
Key
[])
new
Object
[
m
];
vals
=
(
Value
[])
new
Object
[
m
];
}
/**
* Returns the number of key-value pairs in this symbol table.
*
*
@return
the number of key-value pairs in this symbol table
*/
public
int
size
()
{
return
n
;
}
/**
* Returns true if this symbol table is empty.
*
*
@return
{
@code
true} if this symbol table is empty;
* {
@code
false} otherwise
*/
public
boolean
isEmpty
()
{
return
size
()
==
0
;
}
/**
* Returns true if this symbol table contains the specified key.
*
*
@param
key the key
*
@return
{
@code
true} if this symbol table contains {
@code
key};
* {
@code
false} otherwise
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
boolean
contains
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to contains() is null”
);
return
get
(
key
)
!=
null
;
}
// hash function for keys – returns value between 0 and M-1
private
int
hash
(
Key
key
)
{
return
(
key
.
hashCode
()
&
0x7fffffff
)
%
m
;
}
// resizes the hash table to the given capacity by re-hashing all of the keys
private
void
resize
(
int
capacity
)
{
LinearProbingHashST
<
Key
,
Value
>
temp
=
new
LinearProbingHashST
<
Key
,
Value
>
(
capacity
);
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
if
(
keys
[
i
]
!=
null
)
{
temp
.
put
(
keys
[
i
],
vals
[
i
]);
}
}
keys
=
temp
.
keys
;
vals
=
temp
.
vals
;
m
=
temp
.
m
;
}
/**
* Inserts the specified key-value pair into the symbol table, overwriting the old
* value with the new value if the symbol table already contains the specified key.
* Deletes the specified key (and its associated value) from this symbol table
* if the specified value is {
@code
null}.
*
*
@param
key the key
*
@param
val the value
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
put
(
Key
key
,
Value
val
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
"first argument to put() is null"
);
if
(
val
==
null
)
{
delete
(
key
);
return
;
}
// double table size if 50% full
if
(
n
>=
m
/
2
)
resize
(
2
*
m
);
int
i
;
for
(
i
=
hash
(
key
);
keys
[
i
]
!=
null
;
i
=
(
i
+
1
)
%
m
)
{
if
(
keys
[
i
].
equals
(
key
))
{
vals
[
i
]
=
val
;
return
;
}
}
keys
[
i
]
=
key
;
vals
[
i
]
=
val
;
n
++
;
}
/**
* Returns the value associated with the specified key.
*
@param
key the key
*
@return
the value associated with {
@code
key};
* {
@code
null} if no such value
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
Value
get
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to get() is null”
);
for
(
int
i
=
hash
(
key
);
keys
[
i
]
!=
null
;
i
=
(
i
+
1
)
%
m
)
if
(
keys
[
i
].
equals
(
key
))
return
vals
[
i
];
return
null
;
}
/**
* Removes the specified key and its associated value from this symbol table
* (if the key is in this symbol table).
*
*
@param
key the key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
delete
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to delete() is null”
);
if
(
!
contains
(
key
))
return
;
// find position i of key
int
i
=
hash
(
key
);
while
(
!
key
.
equals
(
keys
[
i
]))
{
i
=
(
i
+
1
)
%
m
;
}
// delete key and associated value
keys
[
i
]
=
null
;
vals
[
i
]
=
null
;
// rehash all keys in same cluster
i
=
(
i
+
1
)
%
m
;
while
(
keys
[
i
]
!=
null
)
{
// delete keys[i] an vals[i] and reinsert
Key
keyToRehash
=
keys
[
i
];
Value
valToRehash
=
vals
[
i
];
keys
[
i
]
=
null
;
vals
[
i
]
=
null
;
n
—
;
put
(
keyToRehash
,
valToRehash
);
i
=
(
i
+
1
)
%
m
;
}
n
—
;
// halves size of array if it’s 12.5% full or less
if
(
n
>
0
&&
n
<=
m
/
8
)
resize
(
m
/
2
);
assert
check
();
}
/**
* Returns all keys in this symbol table as an {
@code
Iterable}.
* To iterate over all of the keys in the symbol table named {
@code
st},
* use the foreach notation: {
@code
for (Key key : st.keys())}.
*
*
@return
all keys in this symbol table
*/
public
Iterable
<
Key
>
keys
()
{
Queue
<
Key
>
queue
=
new
Queue
<
Key
>
();
for
(
int
i
=
0
;
i
<
m
;
i
++
)
if
(
keys
[
i
]
!=
null
)
queue
.
enqueue
(
keys
[
i
]);
return
queue
;
}
// integrity check - don't check after each put() because
// integrity not maintained during a delete()
private
boolean
check
()
{
// check that hash table is at most 50% full
if
(
m
<
2
*
n
)
{
System
.
err
.
println
(
"Hash table size m = "
+
m
+
"; array size n = "
+
n
);
return
false
;
}
// check that each key in table can be found by get()
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
if
(
keys
[
i
]
==
null
)
continue
;
else
if
(
get
(
keys
[
i
])
!=
vals
[
i
])
{
System
.
err
.
println
(
"get["
+
keys
[
i
]
+
"] = "
+
get
(
keys
[
i
])
+
"; vals[i] = "
+
vals
[
i
]);
return
false
;
}
}
return
true
;
}
/**
* Unit tests the {
@code
LinearProbingHashST} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
LinearProbingHashST
<
String
,
Integer
>
st
=
new
LinearProbingHashST
<
String
,
Integer
>
();
for
(
int
i
=
0
;
!
StdIn
.
isEmpty
();
i
++
)
{
String
key
=
StdIn
.
readString
();
st
.
put
(
key
,
i
);
}
// print keys
for
(
String
s
:
st
.
keys
())
StdOut
.
println
(
s
+
” ”
+
st
.
get
(
s
));
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/LinearProgramming.java
edu/princeton/cs/algs4/LinearProgramming.java
/******************************************************************************
* Compilation: javac LinearProgramming.java
* Execution: java LinearProgramming m n
* Dependencies: StdOut.java
*
* Given an m-by-n matrix A, an m-length vector b, and an
* n-length vector c, solve the LP { max cx : Ax <= b, x >= 0 }.
* Assumes that b >= 0 so that x = 0 is a basic feasible solution.
*
* Creates an (m+1)-by-(n+m+1) simplex tableaux with the
* RHS in column m+n, the objective function in row m, and
* slack variables in columns m through m+n-1.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
LinearProgramming} class represents a data type for solving a
* linear program of the form { max cx : Ax ≤ b, x ≥ 0 }, where A is a m-by-n
* matrix, b is an m-length vector, and c is an n-length vector. For simplicity,
* we assume that A is of full rank and that b ≥ 0 so that x = 0 is a basic
* feasible soution.
*
* The data type supplies methods for determining the optimal primal and
* dual solutions.
*
* This is a bare-bones implementation of the simplex algorithm.
* It uses Bland’s rule to determing the entering and leaving variables.
* It is not suitable for use on large inputs. It is also not robust
* in the presence of floating-point roundoff error.
*
* For additional documentation, see
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
LinearProgramming
{
private
static
final
double
EPSILON
=
1.0E-10
;
private
double
[][]
a
;
// tableaux
private
int
m
;
// number of constraints
private
int
n
;
// number of original variables
private
int
[]
basis
;
// basis[i] = basic variable corresponding to row i
// only needed to print out solution, not book
/**
* Determines an optimal solution to the linear program
* { max cx : Ax ≤ b, x ≥ 0 }, where A is a m-by-n
* matrix, b is an m-length vector, and c is an n-length vector.
*
*
@param
A the m-by-b matrix
*
@param
b the m-length RHS vector
*
@param
c the n-length cost vector
*
@throws
IllegalArgumentException unless {
@code
b[i] >= 0} for each {
@code
i}
*
@throws
ArithmeticException if the linear program is unbounded
*/
public
LinearProgramming
(
double
[][]
A
,
double
[]
b
,
double
[]
c
)
{
m
=
b
.
length
;
n
=
c
.
length
;
for
(
int
i
=
0
;
i
<
m
;
i
++
)
if
(
!
(
b
[
i
]
>=
0
))
throw
new
IllegalArgumentException
(
“RHS must be nonnegative”
);
a
=
new
double
[
m
+
1
][
n
+
m
+
1
];
for
(
int
i
=
0
;
i
<
m
;
i
++
)
for
(
int
j
=
0
;
j
<
n
;
j
++
)
a
[
i
][
j
]
=
A
[
i
][
j
];
for
(
int
i
=
0
;
i
<
m
;
i
++
)
a
[
i
][
n
+
i
]
=
1.0
;
for
(
int
j
=
0
;
j
<
n
;
j
++
)
a
[
m
][
j
]
=
c
[
j
];
for
(
int
i
=
0
;
i
<
m
;
i
++
)
a
[
i
][
m
+
n
]
=
b
[
i
];
basis
=
new
int
[
m
];
for
(
int
i
=
0
;
i
<
m
;
i
++
)
basis
[
i
]
=
n
+
i
;
solve
();
// check optimality conditions
assert
check
(
A
,
b
,
c
);
}
// run simplex algorithm starting from initial BFS
private
void
solve
()
{
while
(
true
)
{
// find entering column q
int
q
=
bland
();
if
(
q
==
-
1
)
break
;
// optimal
// find leaving row p
int
p
=
minRatioRule
(
q
);
if
(
p
==
-
1
)
throw
new
ArithmeticException
(
"Linear program is unbounded"
);
// pivot
pivot
(
p
,
q
);
// update basis
basis
[
p
]
=
q
;
}
}
// lowest index of a non-basic column with a positive cost
private
int
bland
()
{
for
(
int
j
=
0
;
j
<
m
+
n
;
j
++
)
if
(
a
[
m
][
j
]
>
0
)
return
j
;
return
–
1
;
// optimal
}
// index of a non-basic column with most positive cost
private
int
dantzig
()
{
int
q
=
0
;
for
(
int
j
=
1
;
j
<
m
+
n
;
j
++
)
if
(
a
[
m
][
j
]
>
a
[
m
][
q
])
q
=
j
;
if
(
a
[
m
][
q
]
<=
0
)
return
-
1
;
// optimal
else
return
q
;
}
// find row p using min ratio rule (-1 if no such row)
// (smallest such index if there is a tie)
private
int
minRatioRule
(
int
q
)
{
int
p
=
-
1
;
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
// if (a[i][q] <= 0) continue;
if
(
a
[
i
][
q
]
<=
EPSILON
)
continue
;
else
if
(
p
==
-
1
)
p
=
i
;
else
if
((
a
[
i
][
m
+
n
]
/
a
[
i
][
q
])
<
(
a
[
p
][
m
+
n
]
/
a
[
p
][
q
]))
p
=
i
;
}
return
p
;
}
// pivot on entry (p, q) using Gauss-Jordan elimination
private
void
pivot
(
int
p
,
int
q
)
{
// everything but row p and column q
for
(
int
i
=
0
;
i
<=
m
;
i
++
)
for
(
int
j
=
0
;
j
<=
m
+
n
;
j
++
)
if
(
i
!=
p
&&
j
!=
q
)
a
[
i
][
j
]
-=
a
[
p
][
j
]
*
a
[
i
][
q
]
/
a
[
p
][
q
];
// zero out column q
for
(
int
i
=
0
;
i
<=
m
;
i
++
)
if
(
i
!=
p
)
a
[
i
][
q
]
=
0.0
;
// scale row p
for
(
int
j
=
0
;
j
<=
m
+
n
;
j
++
)
if
(
j
!=
q
)
a
[
p
][
j
]
/=
a
[
p
][
q
];
a
[
p
][
q
]
=
1.0
;
}
/**
* Returns the optimal value of this linear program.
*
*
@return
the optimal value of this linear program
*
*/
public
double
value
()
{
return
-
a
[
m
][
m
+
n
];
}
/**
* Returns the optimal primal solution to this linear program.
*
*
@return
the optimal primal solution to this linear program
*/
public
double
[]
primal
()
{
double
[]
x
=
new
double
[
n
];
for
(
int
i
=
0
;
i
<
m
;
i
++
)
if
(
basis
[
i
]
<
n
)
x
[
basis
[
i
]]
=
a
[
i
][
m
+
n
];
return
x
;
}
/**
* Returns the optimal dual solution to this linear program
*
*
@return
the optimal dual solution to this linear program
*/
public
double
[]
dual
()
{
double
[]
y
=
new
double
[
m
];
for
(
int
i
=
0
;
i
<
m
;
i
++
)
y
[
i
]
=
-
a
[
m
][
n
+
i
];
return
y
;
}
// is the solution primal feasible?
private
boolean
isPrimalFeasible
(
double
[][]
A
,
double
[]
b
)
{
double
[]
x
=
primal
();
// check that x >= 0
for
(
int
j
=
0
;
j
<
x
.
length
;
j
++
)
{
if
(
x
[
j
]
<
0.0
)
{
StdOut
.
println
(
"x["
+
j
+
"] = "
+
x
[
j
]
+
" is negative"
);
return
false
;
}
}
// check that Ax <= b
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
double
sum
=
0.0
;
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
sum
+=
A
[
i
][
j
]
*
x
[
j
];
}
if
(
sum
>
b
[
i
]
+
EPSILON
)
{
StdOut
.
println
(
“not primal feasible”
);
StdOut
.
println
(
“b[”
+
i
+
“] = ”
+
b
[
i
]
+
“, sum = ”
+
sum
);
return
false
;
}
}
return
true
;
}
// is the solution dual feasible?
private
boolean
isDualFeasible
(
double
[][]
A
,
double
[]
c
)
{
double
[]
y
=
dual
();
// check that y >= 0
for
(
int
i
=
0
;
i
<
y
.
length
;
i
++
)
{
if
(
y
[
i
]
<
0.0
)
{
StdOut
.
println
(
"y["
+
i
+
"] = "
+
y
[
i
]
+
" is negative"
);
return
false
;
}
}
// check that yA >= c
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
double
sum
=
0.0
;
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
sum
+=
A
[
i
][
j
]
*
y
[
i
];
}
if
(
sum
<
c
[
j
]
-
EPSILON
)
{
StdOut
.
println
(
"not dual feasible"
);
StdOut
.
println
(
"c["
+
j
+
"] = "
+
c
[
j
]
+
", sum = "
+
sum
);
return
false
;
}
}
return
true
;
}
// check that optimal value = cx = yb
private
boolean
isOptimal
(
double
[]
b
,
double
[]
c
)
{
double
[]
x
=
primal
();
double
[]
y
=
dual
();
double
value
=
value
();
// check that value = cx = yb
double
value1
=
0.0
;
for
(
int
j
=
0
;
j
<
x
.
length
;
j
++
)
value1
+=
c
[
j
]
*
x
[
j
];
double
value2
=
0.0
;
for
(
int
i
=
0
;
i
<
y
.
length
;
i
++
)
value2
+=
y
[
i
]
*
b
[
i
];
if
(
Math
.
abs
(
value
-
value1
)
>
EPSILON
||
Math
.
abs
(
value
–
value2
)
>
EPSILON
)
{
StdOut
.
println
(
“value = ”
+
value
+
“, cx = ”
+
value1
+
“, yb = ”
+
value2
);
return
false
;
}
return
true
;
}
private
boolean
check
(
double
[][]
A
,
double
[]
b
,
double
[]
c
)
{
return
isPrimalFeasible
(
A
,
b
)
&&
isDualFeasible
(
A
,
c
)
&&
isOptimal
(
b
,
c
);
}
// print tableaux
private
void
show
()
{
StdOut
.
println
(
“m = ”
+
m
);
StdOut
.
println
(
“n = ”
+
n
);
for
(
int
i
=
0
;
i
<=
m
;
i
++
)
{
for
(
int
j
=
0
;
j
<=
m
+
n
;
j
++
)
{
StdOut
.
printf
(
"%7.2f "
,
a
[
i
][
j
]);
// StdOut.printf("%10.7f ", a[i][j]);
}
StdOut
.
println
();
}
StdOut
.
println
(
"value = "
+
value
());
for
(
int
i
=
0
;
i
<
m
;
i
++
)
if
(
basis
[
i
]
<
n
)
StdOut
.
println
(
"x_"
+
basis
[
i
]
+
" = "
+
a
[
i
][
m
+
n
]);
StdOut
.
println
();
}
private
static
void
test
(
double
[][]
A
,
double
[]
b
,
double
[]
c
)
{
LinearProgramming
lp
;
try
{
lp
=
new
LinearProgramming
(
A
,
b
,
c
);
}
catch
(
ArithmeticException
e
)
{
System
.
out
.
println
(
e
);
return
;
}
StdOut
.
println
(
"value = "
+
lp
.
value
());
double
[]
x
=
lp
.
primal
();
for
(
int
i
=
0
;
i
<
x
.
length
;
i
++
)
StdOut
.
println
(
"x["
+
i
+
"] = "
+
x
[
i
]);
double
[]
y
=
lp
.
dual
();
for
(
int
j
=
0
;
j
<
y
.
length
;
j
++
)
StdOut
.
println
(
"y["
+
j
+
"] = "
+
y
[
j
]);
}
private
static
void
test1
()
{
double
[][]
A
=
{
{
-
1
,
1
,
0
},
{
1
,
4
,
0
},
{
2
,
1
,
0
},
{
3
,
-
4
,
0
},
{
0
,
0
,
1
},
};
double
[]
c
=
{
1
,
1
,
1
};
double
[]
b
=
{
5
,
45
,
27
,
24
,
4
};
test
(
A
,
b
,
c
);
}
// x0 = 12, x1 = 28, opt = 800
private
static
void
test2
()
{
double
[]
c
=
{
13.0
,
23.0
};
double
[]
b
=
{
480.0
,
160.0
,
1190.0
};
double
[][]
A
=
{
{
5.0
,
15.0
},
{
4.0
,
4.0
},
{
35.0
,
20.0
},
};
test
(
A
,
b
,
c
);
}
// unbounded
private
static
void
test3
()
{
double
[]
c
=
{
2.0
,
3.0
,
-
1.0
,
-
12.0
};
double
[]
b
=
{
3.0
,
2.0
};
double
[][]
A
=
{
{
-
2.0
,
-
9.0
,
1.0
,
9.0
},
{
1.0
,
1.0
,
-
1.0
,
-
2.0
},
};
test
(
A
,
b
,
c
);
}
// degenerate - cycles if you choose most positive objective function coefficient
private
static
void
test4
()
{
double
[]
c
=
{
10.0
,
-
57.0
,
-
9.0
,
-
24.0
};
double
[]
b
=
{
0.0
,
0.0
,
1.0
};
double
[][]
A
=
{
{
0.5
,
-
5.5
,
-
2.5
,
9.0
},
{
0.5
,
-
1.5
,
-
0.5
,
1.0
},
{
1.0
,
0.0
,
0.0
,
0.0
},
};
test
(
A
,
b
,
c
);
}
/**
* Unit tests the {
@code
LinearProgramming} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
StdOut
.
println
(
"----- test 1 --------------------"
);
test1
();
StdOut
.
println
();
StdOut
.
println
(
"----- test 2 --------------------"
);
test2
();
StdOut
.
println
();
StdOut
.
println
(
"----- test 3 --------------------"
);
test3
();
StdOut
.
println
();
StdOut
.
println
(
"----- test 4 --------------------"
);
test4
();
StdOut
.
println
();
StdOut
.
println
(
"----- test random ---------------"
);
int
m
=
Integer
.
parseInt
(
args
[
0
]);
int
n
=
Integer
.
parseInt
(
args
[
1
]);
double
[]
c
=
new
double
[
n
];
double
[]
b
=
new
double
[
m
];
double
[][]
A
=
new
double
[
m
][
n
];
for
(
int
j
=
0
;
j
<
n
;
j
++
)
c
[
j
]
=
StdRandom
.
uniform
(
1000
);
for
(
int
i
=
0
;
i
<
m
;
i
++
)
b
[
i
]
=
StdRandom
.
uniform
(
1000
);
for
(
int
i
=
0
;
i
<
m
;
i
++
)
for
(
int
j
=
0
;
j
<
n
;
j
++
)
A
[
i
][
j
]
=
StdRandom
.
uniform
(
100
);
LinearProgramming
lp
=
new
LinearProgramming
(
A
,
b
,
c
);
test
(
A
,
b
,
c
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/LinearRegression.java
edu/princeton/cs/algs4/LinearRegression.java
/******************************************************************************
* Compilation: javac LinearRegression.java
* Execution: java LinearRegression
* Dependencies: none
*
* Compute least squares solution to y = beta * x + alpha.
* Simple linear regression.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
LinearRegression} class performs a simple linear regression
* on an set of n data points (yi, xi).
* That is, it fits a straight line y = α + β x,
* (where y is the response variable, x is the predictor variable,
* α is the y-intercept, and β is the slope)
* that minimizes the sum of squared residuals of the linear regression model.
* It also computes associated statistics, including the coefficient of
* determination R2 and the standard deviation of the
* estimates for the slope and y-intercept.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
LinearRegression
{
private
final
double
intercept
,
slope
;
private
final
double
r2
;
private
final
double
svar0
,
svar1
;
/**
* Performs a linear regression on the data points {
@code
(y[i], x[i])}.
*
*
@param
x the values of the predictor variable
*
@param
y the corresponding values of the response variable
*
@throws
IllegalArgumentException if the lengths of the two arrays are not equal
*/
public
LinearRegression
(
double
[]
x
,
double
[]
y
)
{
if
(
x
.
length
!=
y
.
length
)
{
throw
new
IllegalArgumentException
(
“array lengths are not equal”
);
}
int
n
=
x
.
length
;
// first pass
double
sumx
=
0.0
,
sumy
=
0.0
,
sumx2
=
0.0
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
sumx
+=
x
[
i
];
sumx2
+=
x
[
i
]
*
x
[
i
];
sumy
+=
y
[
i
];
}
double
xbar
=
sumx
/
n
;
double
ybar
=
sumy
/
n
;
// second pass: compute summary statistics
double
xxbar
=
0.0
,
yybar
=
0.0
,
xybar
=
0.0
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
xxbar
+=
(
x
[
i
]
-
xbar
)
*
(
x
[
i
]
-
xbar
);
yybar
+=
(
y
[
i
]
-
ybar
)
*
(
y
[
i
]
-
ybar
);
xybar
+=
(
x
[
i
]
-
xbar
)
*
(
y
[
i
]
-
ybar
);
}
slope
=
xybar
/
xxbar
;
intercept
=
ybar
-
slope
*
xbar
;
// more statistical analysis
double
rss
=
0.0
;
// residual sum of squares
double
ssr
=
0.0
;
// regression sum of squares
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
double
fit
=
slope
*
x
[
i
]
+
intercept
;
rss
+=
(
fit
-
y
[
i
])
*
(
fit
-
y
[
i
]);
ssr
+=
(
fit
-
ybar
)
*
(
fit
-
ybar
);
}
int
degreesOfFreedom
=
n
-
2
;
r2
=
ssr
/
yybar
;
double
svar
=
rss
/
degreesOfFreedom
;
svar1
=
svar
/
xxbar
;
svar0
=
svar
/
n
+
xbar
*
xbar
*
svar1
;
}
/**
* Returns the y-intercept α of the best of the best-fit line y = α + β x.
*
*
@return
the y-intercept α of the best-fit line y = α + β x
*/
public
double
intercept
()
{
return
intercept
;
}
/**
* Returns the slope β of the best of the best-fit line y = α + β x.
*
*
@return
the slope β of the best-fit line y = α + β x
*/
public
double
slope
()
{
return
slope
;
}
/**
* Returns the coefficient of determination R2.
*
*
@return
the coefficient of determination R2,
* which is a real number between 0 and 1
*/
public
double
R2
()
{
return
r2
;
}
/**
* Returns the standard error of the estimate for the intercept.
*
*
@return
the standard error of the estimate for the intercept
*/
public
double
interceptStdErr
()
{
return
Math
.
sqrt
(
svar0
);
}
/**
* Returns the standard error of the estimate for the slope.
*
*
@return
the standard error of the estimate for the slope
*/
public
double
slopeStdErr
()
{
return
Math
.
sqrt
(
svar1
);
}
/**
* Returns the expected response {
@code
y} given the value of the predictor
* variable {
@code
x}.
*
*
@param
x the value of the predictor variable
*
@return
the expected response {
@code
y} given the value of the predictor
* variable {
@code
x}
*/
public
double
predict
(
double
x
)
{
return
slope
*
x
+
intercept
;
}
/**
* Returns a string representation of the simple linear regression model.
*
*
@return
a string representation of the simple linear regression model,
* including the best-fit line and the coefficient of determination
* R2
*/
public
String
toString
()
{
StringBuilder
s
=
new
StringBuilder
();
s
.
append
(
String
.
format
(
“%.2f n + %.2f”
,
slope
(),
intercept
()));
s
.
append
(
” (R^2 = ”
+
String
.
format
(
“%.3f”
,
R2
())
+
“)”
);
return
s
.
toString
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/LinkedBag.java
edu/princeton/cs/algs4/LinkedBag.java
/******************************************************************************
* Compilation: javac LinkedBag.java
* Execution: java LinkedBag < input.txt * Dependencies: StdIn.java StdOut.java * * A generic bag or multiset, implemented using a singly linked list. * * % more tobe.txt * to be or not to - be - - that - - - is * * % java LinkedBag < tobe.txt * size of bag = 14 * is * - * - * - * that * - * - * be * - * to * not * or * be * to * ******************************************************************************/ package edu . princeton . cs . algs4 ; import java . util . Iterator ; import java . util . NoSuchElementException ; /** * The { @code LinkedBag} class represents a bag (or multiset) of * generic items. It supports insertion and iterating over the * items in arbitrary order. *
* This implementation uses a singly linked list with a non-static nested class Node.
* See {
@link
Bag} for a version that uses a static nested class.
* The add, isEmpty, and size operations
* take constant time. Iteration takes time proportional to the number of items.
*
* For additional documentation, see Section 1.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
LinkedBag
<
Item
>
implements
Iterable
<
Item
>
{
private
Node
first
;
// beginning of bag
private
int
n
;
// number of elements in bag
// helper linked list class
private
class
Node
{
private
Item
item
;
private
Node
next
;
}
/**
* Initializes an empty bag.
*/
public
LinkedBag
()
{
first
=
null
;
n
=
0
;
}
/**
* Is this bag empty?
*
@return
true if this bag is empty; false otherwise
*/
public
boolean
isEmpty
()
{
return
first
==
null
;
}
/**
* Returns the number of items in this bag.
*
@return
the number of items in this bag
*/
public
int
size
()
{
return
n
;
}
/**
* Adds the item to this bag.
*
@param
item the item to add to this bag
*/
public
void
add
(
Item
item
)
{
Node
oldfirst
=
first
;
first
=
new
Node
();
first
.
item
=
item
;
first
.
next
=
oldfirst
;
n
++
;
}
/**
* Returns an iterator that iterates over the items in the bag.
*/
public
Iterator
<
Item
>
iterator
()
{
return
new
ListIterator
();
}
// an iterator over a linked list
private
class
ListIterator
implements
Iterator
<
Item
>
{
private
Node
current
;
// creates a new iterator
public
ListIterator
()
{
current
=
first
;
}
// is there a next item in the iterator?
public
boolean
hasNext
()
{
return
current
!=
null
;
}
// this method is optional in Iterator interface
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
// returns the next item in the iterator (and advances the iterator)
public
Item
next
()
{
if
(
!
hasNext
())
throw
new
NoSuchElementException
();
Item
item
=
current
.
item
;
current
=
current
.
next
;
return
item
;
}
}
/**
* Unit tests the {
@code
LinkedBag} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
LinkedBag
<
String
>
bag
=
new
LinkedBag
<
String
>
();
while
(
!
StdIn
.
isEmpty
())
{
String
item
=
StdIn
.
readString
();
bag
.
add
(
item
);
}
StdOut
.
println
(
“size of bag = ”
+
bag
.
size
());
for
(
String
s
:
bag
)
{
StdOut
.
println
(
s
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/LinkedQueue.java
edu/princeton/cs/algs4/LinkedQueue.java
/******************************************************************************
* Compilation: javac LinkedQueue.java
* Execution: java LinkedQueue < input.txt * Dependencies: StdIn.java StdOut.java * Data files: https://algs4.cs.princeton.edu/13stacks/tobe.txt * * A generic queue, implemented using a singly linked list. * * % java Queue < tobe.txt * to be or not to be (2 left on queue) * ******************************************************************************/ package edu . princeton . cs . algs4 ; import java . util . Iterator ; import java . util . NoSuchElementException ; /** * The { @code LinkedQueue} class represents a first-in-first-out (FIFO) * queue of generic items. * It supports the usual enqueue and dequeue
* operations, along with methods for peeking at the first item,
* testing if the queue is empty, and iterating through
* the items in FIFO order.
*
* This implementation uses a singly linked list with a non-static nested class
* for linked-list nodes. See {
@link
Queue} for a version that uses a static nested class.
* The enqueue, dequeue, peek, size, and is-empty
* operations all take constant time in the worst case.
*
* For additional documentation, see Section 1.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
LinkedQueue
<
Item
>
implements
Iterable
<
Item
>
{
private
int
n
;
// number of elements on queue
private
Node
first
;
// beginning of queue
private
Node
last
;
// end of queue
// helper linked list class
private
class
Node
{
private
Item
item
;
private
Node
next
;
}
/**
* Initializes an empty queue.
*/
public
LinkedQueue
()
{
first
=
null
;
last
=
null
;
n
=
0
;
assert
check
();
}
/**
* Is this queue empty?
*
@return
true if this queue is empty; false otherwise
*/
public
boolean
isEmpty
()
{
return
first
==
null
;
}
/**
* Returns the number of items in this queue.
*
@return
the number of items in this queue
*/
public
int
size
()
{
return
n
;
}
/**
* Returns the item least recently added to this queue.
*
@return
the item least recently added to this queue
*
@throws
java.util.NoSuchElementException if this queue is empty
*/
public
Item
peek
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Queue underflow”
);
return
first
.
item
;
}
/**
* Adds the item to this queue.
*
@param
item the item to add
*/
public
void
enqueue
(
Item
item
)
{
Node
oldlast
=
last
;
last
=
new
Node
();
last
.
item
=
item
;
last
.
next
=
null
;
if
(
isEmpty
())
first
=
last
;
else
oldlast
.
next
=
last
;
n
++
;
assert
check
();
}
/**
* Removes and returns the item on this queue that was least recently added.
*
@return
the item on this queue that was least recently added
*
@throws
java.util.NoSuchElementException if this queue is empty
*/
public
Item
dequeue
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Queue underflow”
);
Item
item
=
first
.
item
;
first
=
first
.
next
;
n
—
;
if
(
isEmpty
())
last
=
null
;
// to avoid loitering
assert
check
();
return
item
;
}
/**
* Returns a string representation of this queue.
*
@return
the sequence of items in FIFO order, separated by spaces
*/
public
String
toString
()
{
StringBuilder
s
=
new
StringBuilder
();
for
(
Item
item
:
this
)
s
.
append
(
item
+
” ”
);
return
s
.
toString
();
}
// check internal invariants
private
boolean
check
()
{
if
(
n
<
0
)
{
return
false
;
}
else
if
(
n
==
0
)
{
if
(
first
!=
null
)
return
false
;
if
(
last
!=
null
)
return
false
;
}
else
if
(
n
==
1
)
{
if
(
first
==
null
||
last
==
null
)
return
false
;
if
(
first
!=
last
)
return
false
;
if
(
first
.
next
!=
null
)
return
false
;
}
else
{
if
(
first
==
null
||
last
==
null
)
return
false
;
if
(
first
==
last
)
return
false
;
if
(
first
.
next
==
null
)
return
false
;
if
(
last
.
next
!=
null
)
return
false
;
// check internal consistency of instance variable n
int
numberOfNodes
=
0
;
for
(
Node
x
=
first
;
x
!=
null
&&
numberOfNodes
<=
n
;
x
=
x
.
next
)
{
numberOfNodes
++
;
}
if
(
numberOfNodes
!=
n
)
return
false
;
// check internal consistency of instance variable last
Node
lastNode
=
first
;
while
(
lastNode
.
next
!=
null
)
{
lastNode
=
lastNode
.
next
;
}
if
(
last
!=
lastNode
)
return
false
;
}
return
true
;
}
/**
* Returns an iterator that iterates over the items in this queue in FIFO order.
*
@return
an iterator that iterates over the items in this queue in FIFO order
*/
public
Iterator
<
Item
>
iterator
()
{
return
new
ListIterator
();
}
// an iterator, doesn’t implement remove() since it’s optional
private
class
ListIterator
implements
Iterator
<
Item
>
{
private
Node
current
=
first
;
public
boolean
hasNext
()
{
return
current
!=
null
;
}
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
public
Item
next
()
{
if
(
!
hasNext
())
throw
new
NoSuchElementException
();
Item
item
=
current
.
item
;
current
=
current
.
next
;
return
item
;
}
}
/**
* Unit tests the {
@code
LinkedQueue} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
LinkedQueue
<
String
>
queue
=
new
LinkedQueue
<
String
>
();
while
(
!
StdIn
.
isEmpty
())
{
String
item
=
StdIn
.
readString
();
if
(
!
item
.
equals
(
“-”
))
queue
.
enqueue
(
item
);
else
if
(
!
queue
.
isEmpty
())
StdOut
.
print
(
queue
.
dequeue
()
+
” ”
);
}
StdOut
.
println
(
“(”
+
queue
.
size
()
+
” left on queue)”
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/LinkedStack.java
edu/princeton/cs/algs4/LinkedStack.java
/******************************************************************************
* Compilation: javac LinkedStack.java
* Execution: java LinkedStack < input.txt * Dependencies: StdIn.java StdOut.java * Data files: https://algs4.cs.princeton.edu/13stacks/tobe.txt * * A generic stack, implemented using a linked list. Each stack * element is of type Item. * * % more tobe.txt * to be or not to - be - - that - - - is * * % java LinkedStack < tobe.txt * to be not that or be (2 left on stack) * ******************************************************************************/ package edu . princeton . cs . algs4 ; import java . util . Iterator ; import java . util . NoSuchElementException ; /** * The { @code LinkedStack} class represents a last-in-first-out (LIFO) stack of * generic items. * It supports the usual push and pop operations, along with methods
* for peeking at the top item, testing if the stack is empty, and iterating through
* the items in LIFO order.
*
* This implementation uses a singly linked list with a non-static nested class for
* linked-list nodes. See {
@link
Stack} for a version that uses a static nested class.
* The push, pop, peek, size, and is-empty
* operations all take constant time in the worst case.
*
* For additional documentation,
* see Section 1.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
LinkedStack
<
Item
>
implements
Iterable
<
Item
>
{
private
int
n
;
// size of the stack
private
Node
first
;
// top of stack
// helper linked list class
private
class
Node
{
private
Item
item
;
private
Node
next
;
}
/**
* Initializes an empty stack.
*/
public
LinkedStack
()
{
first
=
null
;
n
=
0
;
assert
check
();
}
/**
* Is this stack empty?
*
@return
true if this stack is empty; false otherwise
*/
public
boolean
isEmpty
()
{
return
first
==
null
;
}
/**
* Returns the number of items in the stack.
*
@return
the number of items in the stack
*/
public
int
size
()
{
return
n
;
}
/**
* Adds the item to this stack.
*
@param
item the item to add
*/
public
void
push
(
Item
item
)
{
Node
oldfirst
=
first
;
first
=
new
Node
();
first
.
item
=
item
;
first
.
next
=
oldfirst
;
n
++
;
assert
check
();
}
/**
* Removes and returns the item most recently added to this stack.
*
@return
the item most recently added
*
@throws
java.util.NoSuchElementException if this stack is empty
*/
public
Item
pop
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Stack underflow”
);
Item
item
=
first
.
item
;
// save item to return
first
=
first
.
next
;
// delete first node
n
—
;
assert
check
();
return
item
;
// return the saved item
}
/**
* Returns (but does not remove) the item most recently added to this stack.
*
@return
the item most recently added to this stack
*
@throws
java.util.NoSuchElementException if this stack is empty
*/
public
Item
peek
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Stack underflow”
);
return
first
.
item
;
}
/**
* Returns a string representation of this stack.
*
@return
the sequence of items in the stack in LIFO order, separated by spaces
*/
public
String
toString
()
{
StringBuilder
s
=
new
StringBuilder
();
for
(
Item
item
:
this
)
s
.
append
(
item
+
” ”
);
return
s
.
toString
();
}
/**
* Returns an iterator to this stack that iterates through the items in LIFO order.
*
@return
an iterator to this stack that iterates through the items in LIFO order.
*/
public
Iterator
<
Item
>
iterator
()
{
return
new
ListIterator
();
}
// an iterator, doesn’t implement remove() since it’s optional
private
class
ListIterator
implements
Iterator
<
Item
>
{
private
Node
current
=
first
;
public
boolean
hasNext
()
{
return
current
!=
null
;
}
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
public
Item
next
()
{
if
(
!
hasNext
())
throw
new
NoSuchElementException
();
Item
item
=
current
.
item
;
current
=
current
.
next
;
return
item
;
}
}
// check internal invariants
private
boolean
check
()
{
// check a few properties of instance variable ‘first’
if
(
n
<
0
)
{
return
false
;
}
if
(
n
==
0
)
{
if
(
first
!=
null
)
return
false
;
}
else
if
(
n
==
1
)
{
if
(
first
==
null
)
return
false
;
if
(
first
.
next
!=
null
)
return
false
;
}
else
{
if
(
first
==
null
)
return
false
;
if
(
first
.
next
==
null
)
return
false
;
}
// check internal consistency of instance variable n
int
numberOfNodes
=
0
;
for
(
Node
x
=
first
;
x
!=
null
&&
numberOfNodes
<=
n
;
x
=
x
.
next
)
{
numberOfNodes
++
;
}
if
(
numberOfNodes
!=
n
)
return
false
;
return
true
;
}
/**
* Unit tests the {
@code
LinkedStack} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
LinkedStack
<
String
>
stack
=
new
LinkedStack
<
String
>
();
while
(
!
StdIn
.
isEmpty
())
{
String
item
=
StdIn
.
readString
();
if
(
!
item
.
equals
(
“-”
))
stack
.
push
(
item
);
else
if
(
!
stack
.
isEmpty
())
StdOut
.
print
(
stack
.
pop
()
+
” ”
);
}
StdOut
.
println
(
“(”
+
stack
.
size
()
+
” left on stack)”
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/LongestCommonSubstring.java
edu/princeton/cs/algs4/LongestCommonSubstring.java
/******************************************************************************
* Compilation: javac LongestCommonSubstring.java
* Execution: java LongestCommonSubstring file1.txt file2.txt
* Dependencies: SuffixArray.java In.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/63suffix/tale.txt
* https://algs4.cs.princeton.edu/63suffix/mobydick.txt
*
* Read in two text files and find the longest substring that
* appears in both texts.
*
* % java LongestCommonSubstring tale.txt mobydick.txt
* ‘ seemed on the point of being ‘
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
LongestCommonSubstring} class provides a {
@link
SuffixArray}
* client for computing the longest common substring that appears in two
* given strings.
*
* This implementation computes the suffix array of each string and applies a
* merging operation to determine the longest common substring.
* For an alternate implementation, see
* LongestCommonSubstringConcatenate.java.
*
* For additional documentation,
* see Section 6.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
LongestCommonSubstring
{
// Do not instantiate.
private
LongestCommonSubstring
()
{
}
// return the longest common prefix of suffix s[p..] and suffix t[q..]
private
static
String
lcp
(
String
s
,
int
p
,
String
t
,
int
q
)
{
int
n
=
Math
.
min
(
s
.
length
()
–
p
,
t
.
length
()
–
q
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
if
(
s
.
charAt
(
p
+
i
)
!=
t
.
charAt
(
q
+
i
))
return
s
.
substring
(
p
,
p
+
i
);
}
return
s
.
substring
(
p
,
p
+
n
);
}
// compare suffix s[p..] and suffix t[q..]
private
static
int
compare
(
String
s
,
int
p
,
String
t
,
int
q
)
{
int
n
=
Math
.
min
(
s
.
length
()
-
p
,
t
.
length
()
-
q
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
if
(
s
.
charAt
(
p
+
i
)
!=
t
.
charAt
(
q
+
i
))
return
s
.
charAt
(
p
+
i
)
-
t
.
charAt
(
q
+
i
);
}
if
(
s
.
length
()
-
p
<
t
.
length
()
-
q
)
return
-
1
;
else
if
(
s
.
length
()
-
p
>
t
.
length
()
–
q
)
return
+
1
;
else
return
0
;
}
/**
* Returns the longest common string of the two specified strings.
*
*
@param
s one string
*
@param
t the other string
*
@return
the longest common string that appears as a substring
* in both {
@code
s} and {
@code
t}; the empty string
* if no such string
*/
public
static
String
lcs
(
String
s
,
String
t
)
{
SuffixArray
suffix1
=
new
SuffixArray
(
s
);
SuffixArray
suffix2
=
new
SuffixArray
(
t
);
// find longest common substring by “merging” sorted suffixes
String
lcs
=
“”
;
int
i
=
0
,
j
=
0
;
while
(
i
<
s
.
length
()
&&
j
<
t
.
length
())
{
int
p
=
suffix1
.
index
(
i
);
int
q
=
suffix2
.
index
(
j
);
String
x
=
lcp
(
s
,
p
,
t
,
q
);
if
(
x
.
length
()
>
lcs
.
length
())
lcs
=
x
;
if
(
compare
(
s
,
p
,
t
,
q
)
<
0
)
i
++
;
else
j
++
;
}
return
lcs
;
}
/**
* Unit tests the {
@code
lcs()} method.
* Reads in two strings from files specified as command-line arguments;
* computes the longest common substring; and prints the results to
* standard output.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in1
=
new
In
(
args
[
0
]);
In
in2
=
new
In
(
args
[
1
]);
String
s
=
in1
.
readAll
().
trim
().
replaceAll
(
"\\s+"
,
" "
);
String
t
=
in2
.
readAll
().
trim
().
replaceAll
(
"\\s+"
,
" "
);
StdOut
.
println
(
"'"
+
lcs
(
s
,
t
)
+
"'"
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/LongestRepeatedSubstring.java
edu/princeton/cs/algs4/LongestRepeatedSubstring.java
/******************************************************************************
* Compilation: javac LongestRepeatedSubstring.java
* Execution: java LongestRepeatedSubstring < file.txt
* Dependencies: StdIn.java SuffixArray.java
* Data files: https://algs4.cs.princeton.edu/63suffix/tale.txt
* https://algs4.cs.princeton.edu/63suffix/tinyTale.txt
* https://algs4.cs.princeton.edu/63suffix/mobydick.txt
*
* Reads a text string from stdin, replaces all consecutive blocks of
* whitespace with a single space, and then computes the longest
* repeated substring in that text using a suffix array.
*
* % java LongestRepeatedSubstring < tinyTale.txt
* 'st of times it was the '
*
* % java LongestRepeatedSubstring < mobydick.txt
* ',- Such a funny, sporty, gamy, jesty, joky, hoky-poky lad, is the Ocean, oh! Th'
*
* % java LongestRepeatedSubstring
* aaaaaaaaa
* 'aaaaaaaa'
*
* % java LongestRepeatedSubstring
* abcdefg
* ''
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
LongestRepeatedSubstring} class provides a {
@link
SuffixArray}
* client for computing the longest repeated substring of a string that
* appears at least twice. The repeated substrings may overlap (but must
* be distinct).
*
* For additional documentation,
* see Section 6.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* See also {
@link
LongestCommonSubstring}.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
LongestRepeatedSubstring
{
// Do not instantiate.
private
LongestRepeatedSubstring
()
{
}
/**
* Returns the longest common string of the two specified strings.
*
*
@param
s one string
*
@param
t the other string
*
@return
the longest common string that appears as a substring
*/
/**
* Returns the longest repeated substring of the specified string.
*
*
@param
text the string
*
@return
the longest repeated substring that appears in {
@code
text};
* the empty string if no such string
*/
public
static
String
lrs
(
String
text
)
{
int
n
=
text
.
length
();
SuffixArray
sa
=
new
SuffixArray
(
text
);
String
lrs
=
“”
;
for
(
int
i
=
1
;
i
<
n
;
i
++
)
{
int
length
=
sa
.
lcp
(
i
);
if
(
length
>
lrs
.
length
())
{
// lrs = sa.select(i).substring(0, length);
lrs
=
text
.
substring
(
sa
.
index
(
i
),
sa
.
index
(
i
)
+
length
);
}
}
return
lrs
;
}
/**
* Unit tests the {
@code
lrs()} method.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
text
=
StdIn
.
readAll
().
replaceAll
(
“\\s+”
,
” ”
);
StdOut
.
println
(
“‘”
+
lrs
(
text
)
+
“‘”
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/LookupCSV.java
edu/princeton/cs/algs4/LookupCSV.java
/******************************************************************************
* Compilation: javac LookupCSV.java
* Execution: java LookupCSV file.csv keyField valField
* Dependencies: ST.java In.java StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/35applications/DJIA.csv
* https://algs4.cs.princeton.edu/35applications/UPC.csv
* https://algs4.cs.princeton.edu/35applications/amino.csv
* https://algs4.cs.princeton.edu/35applications/elements.csv
* https://algs4.cs.princeton.edu/35applications/ip.csv
* https://algs4.cs.princeton.edu/35applications/morse.csv
*
* Reads in a set of key-value pairs from a two-column CSV file
* specified on the command line; then, reads in keys from standard
* input and prints out corresponding values.
*
* % java LookupCSV amino.csv 0 3 % java LookupCSV ip.csv 0 1
* TTA www.google.com
* Leucine 216.239.41.99
* ABC
* Not found % java LookupCSV ip.csv 1 0
* TCT 216.239.41.99
* Serine www.google.com
*
* % java LookupCSV amino.csv 3 0 % java LookupCSV DJIA.csv 0 1
* Glycine 29-Oct-29
* GGG 252.38
* 20-Oct-87
* 1738.74
*
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
LookupCSV} class provides a data-driven client for reading in a
* key-value pairs from a file; then, printing the values corresponding to the
* keys found on standard input. Both keys and values are strings.
* The fields to serve as the key and value are taken as command-line arguments.
*
* For additional documentation, see Section 3.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
LookupCSV
{
// Do not instantiate.
private
LookupCSV
()
{
}
public
static
void
main
(
String
[]
args
)
{
int
keyField
=
Integer
.
parseInt
(
args
[
1
]);
int
valField
=
Integer
.
parseInt
(
args
[
2
]);
// symbol table
ST
<
String
,
String
>
st
=
new
ST
<
String
,
String
>
();
// read in the data from csv file
In
in
=
new
In
(
args
[
0
]);
while
(
in
.
hasNextLine
())
{
String
line
=
in
.
readLine
();
String
[]
tokens
=
line
.
split
(
“,”
);
String
key
=
tokens
[
keyField
];
String
val
=
tokens
[
valField
];
st
.
put
(
key
,
val
);
}
while
(
!
StdIn
.
isEmpty
())
{
String
s
=
StdIn
.
readString
();
if
(
st
.
contains
(
s
))
StdOut
.
println
(
st
.
get
(
s
));
else
StdOut
.
println
(
“Not found”
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/LookupIndex.java
edu/princeton/cs/algs4/LookupIndex.java
/******************************************************************************
* Compilation: javac LookupIndex.java
* Execution: java LookupIndex movies.txt “/”
* Dependencies: ST.java Queue.java In.java StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/35applications/aminoI.csv
* https://algs4.cs.princeton.edu/35applications/movies.txt
*
* % java LookupIndex aminoI.csv “,”
* Serine
* TCT
* TCA
* TCG
* AGT
* AGC
* TCG
* Serine
*
* % java LookupIndex movies.txt “/”
* Bacon, Kevin
* Animal House (1978)
* Apollo 13 (1995)
* Beauty Shop (2005)
* Diner (1982)
* Few Good Men, A (1992)
* Flatliners (1990)
* Footloose (1984)
* Friday the 13th (1980)
* …
* Tin Men (1987)
* DeBoy, David
* Blumenfeld, Alan
* …
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
LookupIndex} class provides a data-driven client for reading in a
* key-value pairs from a file; then, printing the values corresponding to the
* keys found on standard input. Keys are strings; values are lists of strings.
* The separating delimiter is taken as a command-line argument. This client
* is sometimes known as an inverted index.
*
* For additional documentation, see Section 3.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
LookupIndex
{
// Do not instantiate.
private
LookupIndex
()
{
}
public
static
void
main
(
String
[]
args
)
{
String
filename
=
args
[
0
];
String
separator
=
args
[
1
];
In
in
=
new
In
(
filename
);
ST
<
String
,
Queue
<
String
>>
st
=
new
ST
<
String
,
Queue
<
String
>>
();
ST
<
String
,
Queue
<
String
>>
ts
=
new
ST
<
String
,
Queue
<
String
>>
();
while
(
in
.
hasNextLine
())
{
String
line
=
in
.
readLine
();
String
[]
fields
=
line
.
split
(
separator
);
String
key
=
fields
[
0
];
for
(
int
i
=
1
;
i
<
fields
.
length
;
i
++
)
{
String
val
=
fields
[
i
];
if
(
!
st
.
contains
(
key
))
st
.
put
(
key
,
new
Queue
<
String
>
());
if
(
!
ts
.
contains
(
val
))
ts
.
put
(
val
,
new
Queue
<
String
>
());
st
.
get
(
key
).
enqueue
(
val
);
ts
.
get
(
val
).
enqueue
(
key
);
}
}
StdOut
.
println
(
“Done indexing”
);
// read queries from standard input, one per line
while
(
!
StdIn
.
isEmpty
())
{
String
query
=
StdIn
.
readLine
();
if
(
st
.
contains
(
query
))
for
(
String
vals
:
st
.
get
(
query
))
StdOut
.
println
(
” ”
+
vals
);
if
(
ts
.
contains
(
query
))
for
(
String
keys
:
ts
.
get
(
query
))
StdOut
.
println
(
” ”
+
keys
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/LSD.java
edu/princeton/cs/algs4/LSD.java
/******************************************************************************
* Compilation: javac LSD.java
* Execution: java LSD < input.txt * Dependencies: StdIn.java StdOut.java * Data files: https://algs4.cs.princeton.edu/51radix/words3.txt * * LSD radix sort * * - Sort a String[] array of n extended ASCII strings (R = 256), each of length w. * * - Sort an int[] array of n 32-bit integers, treating each integer as * a sequence of w = 4 bytes (R = 256). * * Uses extra space proportional to n + R. * * * % java LSD < words3.txt * all * bad * bed * bug * dad * ... * yes * yet * zoo * ******************************************************************************/ package edu . princeton . cs . algs4 ; /** * The { @code LSD} class provides static methods for sorting an * array of w-character strings or 32-bit integers using LSD radix sort.
*
* For additional documentation,
* see Section 5.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
LSD
{
private
static
final
int
BITS_PER_BYTE
=
8
;
// do not instantiate
private
LSD
()
{
}
/**
* Rearranges the array of w-character strings in ascending order.
*
*
@param
a the array to be sorted
*
@param
w the number of characters per string
*/
public
static
void
sort
(
String
[]
a
,
int
w
)
{
int
n
=
a
.
length
;
int
R
=
256
;
// extend ASCII alphabet size
String
[]
aux
=
new
String
[
n
];
for
(
int
d
=
w
–
1
;
d
>=
0
;
d
—
)
{
// sort by key-indexed counting on dth character
// compute frequency counts
int
[]
count
=
new
int
[
R
+
1
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
count
[
a
[
i
].
charAt
(
d
)
+
1
]
++
;
// compute cumulates
for
(
int
r
=
0
;
r
<
R
;
r
++
)
count
[
r
+
1
]
+=
count
[
r
];
// move data
for
(
int
i
=
0
;
i
<
n
;
i
++
)
aux
[
count
[
a
[
i
].
charAt
(
d
)]
++
]
=
a
[
i
];
// copy back
for
(
int
i
=
0
;
i
<
n
;
i
++
)
a
[
i
]
=
aux
[
i
];
}
}
/**
* Rearranges the array of 32-bit integers in ascending order.
* This is about 2-3x faster than Arrays.sort().
*
*
@param
a the array to be sorted
*/
public
static
void
sort
(
int
[]
a
)
{
final
int
BITS
=
32
;
// each int is 32 bits
final
int
R
=
1
<<
BITS_PER_BYTE
;
// each bytes is between 0 and 255
final
int
MASK
=
R
-
1
;
// 0xFF
final
int
w
=
BITS
/
BITS_PER_BYTE
;
// each int is 4 bytes
int
n
=
a
.
length
;
int
[]
aux
=
new
int
[
n
];
for
(
int
d
=
0
;
d
<
w
;
d
++
)
{
// compute frequency counts
int
[]
count
=
new
int
[
R
+
1
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
int
c
=
(
a
[
i
]
>>
BITS_PER_BYTE
*
d
)
&
MASK
;
count
[
c
+
1
]
++
;
}
// compute cumulates
for
(
int
r
=
0
;
r
<
R
;
r
++
)
count
[
r
+
1
]
+=
count
[
r
];
// for most significant byte, 0x80-0xFF comes before 0x00-0x7F
if
(
d
==
w
-
1
)
{
int
shift1
=
count
[
R
]
-
count
[
R
/
2
];
int
shift2
=
count
[
R
/
2
];
for
(
int
r
=
0
;
r
<
R
/
2
;
r
++
)
count
[
r
]
+=
shift1
;
for
(
int
r
=
R
/
2
;
r
<
R
;
r
++
)
count
[
r
]
-=
shift2
;
}
// move data
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
int
c
=
(
a
[
i
]
>>
BITS_PER_BYTE
*
d
)
&
MASK
;
aux
[
count
[
c
]
++
]
=
a
[
i
];
}
// copy back
for
(
int
i
=
0
;
i
<
n
;
i
++
)
a
[
i
]
=
aux
[
i
];
}
}
/**
* Reads in a sequence of fixed-length strings from standard input;
* LSD radix sorts them;
* and prints them to standard output in ascending order.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
[]
a
=
StdIn
.
readAllStrings
();
int
n
=
a
.
length
;
// check that strings have fixed length
int
w
=
a
[
0
].
length
();
for
(
int
i
=
0
;
i
<
n
;
i
++
)
assert
a
[
i
].
length
()
==
w
:
"Strings must have fixed length"
;
// sort the strings
sort
(
a
,
w
);
// print results
for
(
int
i
=
0
;
i
<
n
;
i
++
)
StdOut
.
println
(
a
[
i
]);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/LZW.java
edu/princeton/cs/algs4/LZW.java
/******************************************************************************
* Compilation: javac LZW.java
* Execution: java LZW - < input.txt (compress)
* Execution: java LZW + < input.txt (expand)
* Dependencies: BinaryIn.java BinaryOut.java
* Data files: https://algs4.cs.princeton.edu/55compression/abraLZW.txt
* https://algs4.cs.princeton.edu/55compression/ababLZW.txt
*
* Compress or expand binary input from standard input using LZW.
*
* WARNING: STARTING WITH ORACLE JAVA 6, UPDATE 7 the SUBSTRING
* METHOD TAKES TIME AND SPACE LINEAR IN THE SIZE OF THE EXTRACTED
* SUBSTRING (INSTEAD OF CONSTANT SPACE AND TIME AS IN EARLIER
* IMPLEMENTATIONS).
*
* See this article
* for more details.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
LZW} class provides static methods for compressing
* and expanding a binary input using LZW compression over the 8-bit extended
* ASCII alphabet with 12-bit codewords.
*
* For additional documentation,
* see Section 5.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
LZW
{
private
static
final
int
R
=
256
;
// number of input chars
private
static
final
int
L
=
4096
;
// number of codewords = 2^W
private
static
final
int
W
=
12
;
// codeword width
// Do not instantiate.
private
LZW
()
{
}
/**
* Reads a sequence of 8-bit bytes from standard input; compresses
* them using LZW compression with 12-bit codewords; and writes the results
* to standard output.
*/
public
static
void
compress
()
{
String
input
=
BinaryStdIn
.
readString
();
TST
<
Integer
>
st
=
new
TST
<
Integer
>
();
for
(
int
i
=
0
;
i
<
R
;
i
++
)
st
.
put
(
""
+
(
char
)
i
,
i
);
int
code
=
R
+
1
;
// R is codeword for EOF
while
(
input
.
length
()
>
0
)
{
String
s
=
st
.
longestPrefixOf
(
input
);
// Find max prefix match s.
BinaryStdOut
.
write
(
st
.
get
(
s
),
W
);
// Print s’s encoding.
int
t
=
s
.
length
();
if
(
t
<
input
.
length
()
&&
code
<
L
)
// Add s to symbol table.
st
.
put
(
input
.
substring
(
0
,
t
+
1
),
code
++
);
input
=
input
.
substring
(
t
);
// Scan past s in input.
}
BinaryStdOut
.
write
(
R
,
W
);
BinaryStdOut
.
close
();
}
/**
* Reads a sequence of bit encoded using LZW compression with
* 12-bit codewords from standard input; expands them; and writes
* the results to standard output.
*/
public
static
void
expand
()
{
String
[]
st
=
new
String
[
L
];
int
i
;
// next available codeword value
// initialize symbol table with all 1-character strings
for
(
i
=
0
;
i
<
R
;
i
++
)
st
[
i
]
=
""
+
(
char
)
i
;
st
[
i
++
]
=
""
;
// (unused) lookahead for EOF
int
codeword
=
BinaryStdIn
.
readInt
(
W
);
if
(
codeword
==
R
)
return
;
// expanded message is empty string
String
val
=
st
[
codeword
];
while
(
true
)
{
BinaryStdOut
.
write
(
val
);
codeword
=
BinaryStdIn
.
readInt
(
W
);
if
(
codeword
==
R
)
break
;
String
s
=
st
[
codeword
];
if
(
i
==
codeword
)
s
=
val
+
val
.
charAt
(
0
);
// special case hack
if
(
i
<
L
)
st
[
i
++
]
=
val
+
s
.
charAt
(
0
);
val
=
s
;
}
BinaryStdOut
.
close
();
}
/**
* Sample client that calls {
@code
compress()} if the command-line
* argument is "-" an {
@code
expand()} if it is "+".
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
if
(
args
[
0
].
equals
(
"-"
))
compress
();
else
if
(
args
[
0
].
equals
(
"+"
))
expand
();
else
throw
new
IllegalArgumentException
(
"Illegal command line argument"
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/MaxPQ.java
edu/princeton/cs/algs4/MaxPQ.java
/******************************************************************************
* Compilation: javac MaxPQ.java
* Execution: java MaxPQ < input.txt
* Dependencies: StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/24pq/tinyPQ.txt
*
* Generic max priority queue implementation with a binary heap.
* Can be used with a comparator instead of the natural order,
* but the generic Key type must still be Comparable.
*
* % java MaxPQ < tinyPQ.txt
* Q X P (6 left on pq)
*
* We use a one-based array to simplify parent and child calculations.
*
* Can be optimized by replacing full exchanges with half exchanges
* (ala insertion sort).
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Comparator
;
import
java
.
util
.
Iterator
;
import
java
.
util
.
NoSuchElementException
;
/**
* The {
@code
MaxPQ} class represents a priority queue of generic keys.
* It supports the usual insert and delete-the-maximum
* operations, along with methods for peeking at the maximum key,
* testing if the priority queue is empty, and iterating through
* the keys.
*
* This implementation uses a binary heap.
* The insert and delete-the-maximum operations take
* Θ(log n) amortized time, where n is the number
* of elements in the priority queue. This is an amortized bound
* (and not a worst-case bound) because of array resizing operations.
* The min, size, and is-empty operations take
* Θ(1) time in the worst case.
* Construction takes time proportional to the specified capacity or the
* number of items used to initialize the data structure.
*
* For additional documentation, see
* Section 2.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*
*
@param
*/
public
class
MaxPQ
<
Key
>
implements
Iterable
<
Key
>
{
private
Key
[]
pq
;
// store items at indices 1 to n
private
int
n
;
// number of items on priority queue
private
Comparator
<
Key
>
comparator
;
// optional comparator
/**
* Initializes an empty priority queue with the given initial capacity.
*
*
@param
initCapacity the initial capacity of this priority queue
*/
public
MaxPQ
(
int
initCapacity
)
{
pq
=
(
Key
[])
new
Object
[
initCapacity
+
1
];
n
=
0
;
}
/**
* Initializes an empty priority queue.
*/
public
MaxPQ
()
{
this
(
1
);
}
/**
* Initializes an empty priority queue with the given initial capacity,
* using the given comparator.
*
*
@param
initCapacity the initial capacity of this priority queue
*
@param
comparator the order in which to compare the keys
*/
public
MaxPQ
(
int
initCapacity
,
Comparator
<
Key
>
comparator
)
{
this
.
comparator
=
comparator
;
pq
=
(
Key
[])
new
Object
[
initCapacity
+
1
];
n
=
0
;
}
/**
* Initializes an empty priority queue using the given comparator.
*
*
@param
comparator the order in which to compare the keys
*/
public
MaxPQ
(
Comparator
<
Key
>
comparator
)
{
this
(
1
,
comparator
);
}
/**
* Initializes a priority queue from the array of keys.
* Takes time proportional to the number of keys, using sink-based heap construction.
*
*
@param
keys the array of keys
*/
public
MaxPQ
(
Key
[]
keys
)
{
n
=
keys
.
length
;
pq
=
(
Key
[])
new
Object
[
keys
.
length
+
1
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
pq
[
i
+
1
]
=
keys
[
i
];
for
(
int
k
=
n
/
2
;
k
>=
1
;
k
—
)
sink
(
k
);
assert
isMaxHeap
();
}
/**
* Returns true if this priority queue is empty.
*
*
@return
{
@code
true} if this priority queue is empty;
* {
@code
false} otherwise
*/
public
boolean
isEmpty
()
{
return
n
==
0
;
}
/**
* Returns the number of keys on this priority queue.
*
*
@return
the number of keys on this priority queue
*/
public
int
size
()
{
return
n
;
}
/**
* Returns a largest key on this priority queue.
*
*
@return
a largest key on this priority queue
*
@throws
NoSuchElementException if this priority queue is empty
*/
public
Key
max
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Priority queue underflow”
);
return
pq
[
1
];
}
// helper function to double the size of the heap array
private
void
resize
(
int
capacity
)
{
assert
capacity
>
n
;
Key
[]
temp
=
(
Key
[])
new
Object
[
capacity
];
for
(
int
i
=
1
;
i
<=
n
;
i
++
)
{
temp
[
i
]
=
pq
[
i
];
}
pq
=
temp
;
}
/**
* Adds a new key to this priority queue.
*
*
@param
x the new key to add to this priority queue
*/
public
void
insert
(
Key
x
)
{
// double size of array if necessary
if
(
n
==
pq
.
length
-
1
)
resize
(
2
*
pq
.
length
);
// add x, and percolate it up to maintain heap invariant
pq
[
++
n
]
=
x
;
swim
(
n
);
assert
isMaxHeap
();
}
/**
* Removes and returns a largest key on this priority queue.
*
*
@return
a largest key on this priority queue
*
@throws
NoSuchElementException if this priority queue is empty
*/
public
Key
delMax
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
"Priority queue underflow"
);
Key
max
=
pq
[
1
];
exch
(
1
,
n
--
);
sink
(
1
);
pq
[
n
+
1
]
=
null
;
// to avoid loitering and help with garbage collection
if
((
n
>
0
)
&&
(
n
==
(
pq
.
length
–
1
)
/
4
))
resize
(
pq
.
length
/
2
);
assert
isMaxHeap
();
return
max
;
}
/***************************************************************************
* Helper functions to restore the heap invariant.
***************************************************************************/
private
void
swim
(
int
k
)
{
while
(
k
>
1
&&
less
(
k
/
2
,
k
))
{
exch
(
k
,
k
/
2
);
k
=
k
/
2
;
}
}
private
void
sink
(
int
k
)
{
while
(
2
*
k
<=
n
)
{
int
j
=
2
*
k
;
if
(
j
<
n
&&
less
(
j
,
j
+
1
))
j
++
;
if
(
!
less
(
k
,
j
))
break
;
exch
(
k
,
j
);
k
=
j
;
}
}
/***************************************************************************
* Helper functions for compares and swaps.
***************************************************************************/
private
boolean
less
(
int
i
,
int
j
)
{
if
(
comparator
==
null
)
{
return
((
Comparable
<
Key
>
)
pq
[
i
]).
compareTo
(
pq
[
j
])
<
0
;
}
else
{
return
comparator
.
compare
(
pq
[
i
],
pq
[
j
])
<
0
;
}
}
private
void
exch
(
int
i
,
int
j
)
{
Key
swap
=
pq
[
i
];
pq
[
i
]
=
pq
[
j
];
pq
[
j
]
=
swap
;
}
// is pq[1..n] a max heap?
private
boolean
isMaxHeap
()
{
for
(
int
i
=
1
;
i
<=
n
;
i
++
)
{
if
(
pq
[
i
]
==
null
)
return
false
;
}
for
(
int
i
=
n
+
1
;
i
<
pq
.
length
;
i
++
)
{
if
(
pq
[
i
]
!=
null
)
return
false
;
}
if
(
pq
[
0
]
!=
null
)
return
false
;
return
isMaxHeapOrdered
(
1
);
}
// is subtree of pq[1..n] rooted at k a max heap?
private
boolean
isMaxHeapOrdered
(
int
k
)
{
if
(
k
>
n
)
return
true
;
int
left
=
2
*
k
;
int
right
=
2
*
k
+
1
;
if
(
left
<=
n
&&
less
(
k
,
left
))
return
false
;
if
(
right
<=
n
&&
less
(
k
,
right
))
return
false
;
return
isMaxHeapOrdered
(
left
)
&&
isMaxHeapOrdered
(
right
);
}
/***************************************************************************
* Iterator.
***************************************************************************/
/**
* Returns an iterator that iterates over the keys on this priority queue
* in descending order.
* The iterator doesn't implement {
@code
remove()} since it's optional.
*
*
@return
an iterator that iterates over the keys in descending order
*/
public
Iterator
<
Key
>
iterator
()
{
return
new
HeapIterator
();
}
private
class
HeapIterator
implements
Iterator
<
Key
>
{
// create a new pq
private
MaxPQ
<
Key
>
copy
;
// add all items to copy of heap
// takes linear time since already in heap order so no keys move
public
HeapIterator
()
{
if
(
comparator
==
null
)
copy
=
new
MaxPQ
<
Key
>
(
size
());
else
copy
=
new
MaxPQ
<
Key
>
(
size
(),
comparator
);
for
(
int
i
=
1
;
i
<=
n
;
i
++
)
copy
.
insert
(
pq
[
i
]);
}
public
boolean
hasNext
()
{
return
!
copy
.
isEmpty
();
}
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
public
Key
next
()
{
if
(
!
hasNext
())
throw
new
NoSuchElementException
();
return
copy
.
delMax
();
}
}
/**
* Unit tests the {
@code
MaxPQ} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
MaxPQ
<
String
>
pq
=
new
MaxPQ
<
String
>
();
while
(
!
StdIn
.
isEmpty
())
{
String
item
=
StdIn
.
readString
();
if
(
!
item
.
equals
(
“-”
))
pq
.
insert
(
item
);
else
if
(
!
pq
.
isEmpty
())
StdOut
.
print
(
pq
.
delMax
()
+
” ”
);
}
StdOut
.
println
(
“(”
+
pq
.
size
()
+
” left on pq)”
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/MergeBU.java
edu/princeton/cs/algs4/MergeBU.java
/******************************************************************************
* Compilation: javac MergeBU.java
* Execution: java MergeBU < input.txt * Dependencies: StdOut.java StdIn.java * Data files: https://algs4.cs.princeton.edu/22mergesort/tiny.txt * https://algs4.cs.princeton.edu/22mergesort/words3.txt * * Sorts a sequence of strings from standard input using * bottom-up mergesort. * * % more tiny.txt * S O R T E X A M P L E * * % java MergeBU < tiny.txt * A E E L M O P R S T X [ one string per line ] * * % more words3.txt * bed bug dad yes zoo ... all bad yet * * % java MergeBU < words3.txt * all bad bed bug dad ... yes yet zoo [ one string per line ] * ******************************************************************************/ package edu . princeton . cs . algs4 ; /** * The { @code MergeBU} class provides static methods for sorting an * array using bottom-up mergesort. It is non-recursive.
*
* This implementation takes Θ(n log n) time
* to sort any array of length n (assuming comparisons
* take constant time). It makes between
* ~ ½ n log2 n and
* ~ 1 n log2 n compares.
*
* This sorting algorithm is stable.
* It uses Θ(n) extra memory (not including the input array).
*
* For additional documentation, see
* Section 2.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
MergeBU
{
// This class should not be instantiated.
private
MergeBU
()
{
}
// stably merge a[lo..mid] with a[mid+1..hi] using aux[lo..hi]
private
static
void
merge
(
Comparable
[]
a
,
Comparable
[]
aux
,
int
lo
,
int
mid
,
int
hi
)
{
// copy to aux[]
for
(
int
k
=
lo
;
k
<=
hi
;
k
++
)
{
aux
[
k
]
=
a
[
k
];
}
// merge back to a[]
int
i
=
lo
,
j
=
mid
+
1
;
for
(
int
k
=
lo
;
k
<=
hi
;
k
++
)
{
if
(
i
>
mid
)
a
[
k
]
=
aux
[
j
++
];
// this copying is unneccessary
else
if
(
j
>
hi
)
a
[
k
]
=
aux
[
i
++
];
else
if
(
less
(
aux
[
j
],
aux
[
i
]))
a
[
k
]
=
aux
[
j
++
];
else
a
[
k
]
=
aux
[
i
++
];
}
}
/**
* Rearranges the array in ascending order, using the natural order.
*
@param
a the array to be sorted
*/
public
static
void
sort
(
Comparable
[]
a
)
{
int
n
=
a
.
length
;
Comparable
[]
aux
=
new
Comparable
[
n
];
for
(
int
len
=
1
;
len
<
n
;
len
*=
2
)
{
for
(
int
lo
=
0
;
lo
<
n
-
len
;
lo
+=
len
+
len
)
{
int
mid
=
lo
+
len
-
1
;
int
hi
=
Math
.
min
(
lo
+
len
+
len
-
1
,
n
-
1
);
merge
(
a
,
aux
,
lo
,
mid
,
hi
);
}
}
assert
isSorted
(
a
);
}
/***********************************************************************
* Helper sorting functions.
***************************************************************************/
// is v < w ?
private
static
boolean
less
(
Comparable
v
,
Comparable
w
)
{
return
v
.
compareTo
(
w
)
<
0
;
}
/***************************************************************************
* Check if array is sorted - useful for debugging.
***************************************************************************/
private
static
boolean
isSorted
(
Comparable
[]
a
)
{
for
(
int
i
=
1
;
i
<
a
.
length
;
i
++
)
if
(
less
(
a
[
i
],
a
[
i
-
1
]))
return
false
;
return
true
;
}
// print array to standard output
private
static
void
show
(
Comparable
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
StdOut
.
println
(
a
[
i
]);
}
}
/**
* Reads in a sequence of strings from standard input; bottom-up
* mergesorts them; and prints them to standard output in ascending order.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
[]
a
=
StdIn
.
readAllStrings
();
MergeBU
.
sort
(
a
);
show
(
a
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Merge.java
edu/princeton/cs/algs4/Merge.java
/******************************************************************************
* Compilation: javac Merge.java
* Execution: java Merge < input.txt
* Dependencies: StdOut.java StdIn.java
* Data files: https://algs4.cs.princeton.edu/22mergesort/tiny.txt
* https://algs4.cs.princeton.edu/22mergesort/words3.txt
*
* Sorts a sequence of strings from standard input using mergesort.
*
* % more tiny.txt
* S O R T E X A M P L E
*
* % java Merge < tiny.txt
* A E E L M O P R S T X [ one string per line ]
*
* % more words3.txt
* bed bug dad yes zoo ... all bad yet
*
* % java Merge < words3.txt
* all bad bed bug dad ... yes yet zoo [ one string per line ]
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Merge} class provides static methods for sorting an
* array using a top-down, recursive version of mergesort.
*
* This implementation takes Θ(n log n) time
* to sort any array of length n (assuming comparisons
* take constant time). It makes between
* ~ ½ n log2 n and
* ~ 1 n log2 n compares.
*
* This sorting algorithm is stable.
* It uses Θ(n) extra memory (not including the input array).
*
* For additional documentation, see
* Section 2.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
* For an optimized version, see {
@link
MergeX}.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Merge
{
// This class should not be instantiated.
private
Merge
()
{
}
// stably merge a[lo .. mid] with a[mid+1 ..hi] using aux[lo .. hi]
private
static
void
merge
(
Comparable
[]
a
,
Comparable
[]
aux
,
int
lo
,
int
mid
,
int
hi
)
{
// precondition: a[lo .. mid] and a[mid+1 .. hi] are sorted subarrays
assert
isSorted
(
a
,
lo
,
mid
);
assert
isSorted
(
a
,
mid
+
1
,
hi
);
// copy to aux[]
for
(
int
k
=
lo
;
k
<=
hi
;
k
++
)
{
aux
[
k
]
=
a
[
k
];
}
// merge back to a[]
int
i
=
lo
,
j
=
mid
+
1
;
for
(
int
k
=
lo
;
k
<=
hi
;
k
++
)
{
if
(
i
>
mid
)
a
[
k
]
=
aux
[
j
++
];
else
if
(
j
>
hi
)
a
[
k
]
=
aux
[
i
++
];
else
if
(
less
(
aux
[
j
],
aux
[
i
]))
a
[
k
]
=
aux
[
j
++
];
else
a
[
k
]
=
aux
[
i
++
];
}
// postcondition: a[lo .. hi] is sorted
assert
isSorted
(
a
,
lo
,
hi
);
}
// mergesort a[lo..hi] using auxiliary array aux[lo..hi]
private
static
void
sort
(
Comparable
[]
a
,
Comparable
[]
aux
,
int
lo
,
int
hi
)
{
if
(
hi
<=
lo
)
return
;
int
mid
=
lo
+
(
hi
-
lo
)
/
2
;
sort
(
a
,
aux
,
lo
,
mid
);
sort
(
a
,
aux
,
mid
+
1
,
hi
);
merge
(
a
,
aux
,
lo
,
mid
,
hi
);
}
/**
* Rearranges the array in ascending order, using the natural order.
*
@param
a the array to be sorted
*/
public
static
void
sort
(
Comparable
[]
a
)
{
Comparable
[]
aux
=
new
Comparable
[
a
.
length
];
sort
(
a
,
aux
,
0
,
a
.
length
-
1
);
assert
isSorted
(
a
);
}
/***************************************************************************
* Helper sorting function.
***************************************************************************/
// is v < w ?
private
static
boolean
less
(
Comparable
v
,
Comparable
w
)
{
return
v
.
compareTo
(
w
)
<
0
;
}
/***************************************************************************
* Check if array is sorted - useful for debugging.
***************************************************************************/
private
static
boolean
isSorted
(
Comparable
[]
a
)
{
return
isSorted
(
a
,
0
,
a
.
length
-
1
);
}
private
static
boolean
isSorted
(
Comparable
[]
a
,
int
lo
,
int
hi
)
{
for
(
int
i
=
lo
+
1
;
i
<=
hi
;
i
++
)
if
(
less
(
a
[
i
],
a
[
i
-
1
]))
return
false
;
return
true
;
}
/***************************************************************************
* Index mergesort.
***************************************************************************/
// stably merge a[lo .. mid] with a[mid+1 .. hi] using aux[lo .. hi]
private
static
void
merge
(
Comparable
[]
a
,
int
[]
index
,
int
[]
aux
,
int
lo
,
int
mid
,
int
hi
)
{
// copy to aux[]
for
(
int
k
=
lo
;
k
<=
hi
;
k
++
)
{
aux
[
k
]
=
index
[
k
];
}
// merge back to a[]
int
i
=
lo
,
j
=
mid
+
1
;
for
(
int
k
=
lo
;
k
<=
hi
;
k
++
)
{
if
(
i
>
mid
)
index
[
k
]
=
aux
[
j
++
];
else
if
(
j
>
hi
)
index
[
k
]
=
aux
[
i
++
];
else
if
(
less
(
a
[
aux
[
j
]],
a
[
aux
[
i
]]))
index
[
k
]
=
aux
[
j
++
];
else
index
[
k
]
=
aux
[
i
++
];
}
}
/**
* Returns a permutation that gives the elements in the array in ascending order.
*
@param
a the array
*
@return
a permutation {
@code
p[]} such that {
@code
a[p[0]]}, {
@code
a[p[1]]},
* …, {
@code
a[p[N-1]]} are in ascending order
*/
public
static
int
[]
indexSort
(
Comparable
[]
a
)
{
int
n
=
a
.
length
;
int
[]
index
=
new
int
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
index
[
i
]
=
i
;
int
[]
aux
=
new
int
[
n
];
sort
(
a
,
index
,
aux
,
0
,
n
-
1
);
return
index
;
}
// mergesort a[lo..hi] using auxiliary array aux[lo..hi]
private
static
void
sort
(
Comparable
[]
a
,
int
[]
index
,
int
[]
aux
,
int
lo
,
int
hi
)
{
if
(
hi
<=
lo
)
return
;
int
mid
=
lo
+
(
hi
-
lo
)
/
2
;
sort
(
a
,
index
,
aux
,
lo
,
mid
);
sort
(
a
,
index
,
aux
,
mid
+
1
,
hi
);
merge
(
a
,
index
,
aux
,
lo
,
mid
,
hi
);
}
// print array to standard output
private
static
void
show
(
Comparable
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
StdOut
.
println
(
a
[
i
]);
}
}
/**
* Reads in a sequence of strings from standard input; mergesorts them;
* and prints them to standard output in ascending order.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
[]
a
=
StdIn
.
readAllStrings
();
Merge
.
sort
(
a
);
show
(
a
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/MergeX.java
edu/princeton/cs/algs4/MergeX.java
/******************************************************************************
* Compilation: javac MergeX.java
* Execution: java MergeX < input.txt
* Dependencies: StdOut.java StdIn.java
* Data files: https://algs4.cs.princeton.edu/22mergesort/tiny.txt
* https://algs4.cs.princeton.edu/22mergesort/words3.txt
*
* Sorts a sequence of strings from standard input using an
* optimized version of mergesort.
*
* % more tiny.txt
* S O R T E X A M P L E
*
* % java MergeX < tiny.txt
* A E E L M O P R S T X [ one string per line ]
*
* % more words3.txt
* bed bug dad yes zoo ... all bad yet
*
* % java MergeX < words3.txt
* all bad bed bug dad ... yes yet zoo [ one string per line ]
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Comparator
;
/**
* The {
@code
MergeX} class provides static methods for sorting an
* array using an optimized version of mergesort.
*
* In the worst case, this implementation takes
* Θ(n log n) time to sort an array of
* length n (assuming comparisons take constant time).
*
* This sorting algorithm is stable.
* It uses Θ(n) extra memory (not including the input array).
*
* For additional documentation, see
* Section 2.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
MergeX
{
private
static
final
int
CUTOFF
=
7
;
// cutoff to insertion sort
// This class should not be instantiated.
private
MergeX
()
{
}
private
static
void
merge
(
Comparable
[]
src
,
Comparable
[]
dst
,
int
lo
,
int
mid
,
int
hi
)
{
// precondition: src[lo .. mid] and src[mid+1 .. hi] are sorted subarrays
assert
isSorted
(
src
,
lo
,
mid
);
assert
isSorted
(
src
,
mid
+
1
,
hi
);
int
i
=
lo
,
j
=
mid
+
1
;
for
(
int
k
=
lo
;
k
<=
hi
;
k
++
)
{
if
(
i
>
mid
)
dst
[
k
]
=
src
[
j
++
];
else
if
(
j
>
hi
)
dst
[
k
]
=
src
[
i
++
];
else
if
(
less
(
src
[
j
],
src
[
i
]))
dst
[
k
]
=
src
[
j
++
];
// to ensure stability
else
dst
[
k
]
=
src
[
i
++
];
}
// postcondition: dst[lo .. hi] is sorted subarray
assert
isSorted
(
dst
,
lo
,
hi
);
}
private
static
void
sort
(
Comparable
[]
src
,
Comparable
[]
dst
,
int
lo
,
int
hi
)
{
// if (hi <= lo) return;
if
(
hi
<=
lo
+
CUTOFF
)
{
insertionSort
(
dst
,
lo
,
hi
);
return
;
}
int
mid
=
lo
+
(
hi
-
lo
)
/
2
;
sort
(
dst
,
src
,
lo
,
mid
);
sort
(
dst
,
src
,
mid
+
1
,
hi
);
// if (!less(src[mid+1], src[mid])) {
// for (int i = lo; i <= hi; i++) dst[i] = src[i];
// return;
// }
// using System.arraycopy() is a bit faster than the above loop
if
(
!
less
(
src
[
mid
+
1
],
src
[
mid
]))
{
System
.
arraycopy
(
src
,
lo
,
dst
,
lo
,
hi
-
lo
+
1
);
return
;
}
merge
(
src
,
dst
,
lo
,
mid
,
hi
);
}
/**
* Rearranges the array in ascending order, using the natural order.
*
@param
a the array to be sorted
*/
public
static
void
sort
(
Comparable
[]
a
)
{
Comparable
[]
aux
=
a
.
clone
();
sort
(
aux
,
a
,
0
,
a
.
length
-
1
);
assert
isSorted
(
a
);
}
// sort from a[lo] to a[hi] using insertion sort
private
static
void
insertionSort
(
Comparable
[]
a
,
int
lo
,
int
hi
)
{
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
for
(
int
j
=
i
;
j
>
lo
&&
less
(
a
[
j
],
a
[
j
–
1
]);
j
—
)
exch
(
a
,
j
,
j
–
1
);
}
/*******************************************************************
* Utility methods.
*******************************************************************/
// exchange a[i] and a[j]
private
static
void
exch
(
Object
[]
a
,
int
i
,
int
j
)
{
Object
swap
=
a
[
i
];
a
[
i
]
=
a
[
j
];
a
[
j
]
=
swap
;
}
// is a[i] < a[j]?
private
static
boolean
less
(
Comparable
a
,
Comparable
b
)
{
return
a
.
compareTo
(
b
)
<
0
;
}
// is a[i] < a[j]?
private
static
boolean
less
(
Object
a
,
Object
b
,
Comparator
comparator
)
{
return
comparator
.
compare
(
a
,
b
)
<
0
;
}
/*******************************************************************
* Version that takes Comparator as argument.
*******************************************************************/
/**
* Rearranges the array in ascending order, using the provided order.
*
*
@param
a the array to be sorted
*
@param
comparator the comparator that defines the total order
*/
public
static
void
sort
(
Object
[]
a
,
Comparator
comparator
)
{
Object
[]
aux
=
a
.
clone
();
sort
(
aux
,
a
,
0
,
a
.
length
-
1
,
comparator
);
assert
isSorted
(
a
,
comparator
);
}
private
static
void
merge
(
Object
[]
src
,
Object
[]
dst
,
int
lo
,
int
mid
,
int
hi
,
Comparator
comparator
)
{
// precondition: src[lo .. mid] and src[mid+1 .. hi] are sorted subarrays
assert
isSorted
(
src
,
lo
,
mid
,
comparator
);
assert
isSorted
(
src
,
mid
+
1
,
hi
,
comparator
);
int
i
=
lo
,
j
=
mid
+
1
;
for
(
int
k
=
lo
;
k
<=
hi
;
k
++
)
{
if
(
i
>
mid
)
dst
[
k
]
=
src
[
j
++
];
else
if
(
j
>
hi
)
dst
[
k
]
=
src
[
i
++
];
else
if
(
less
(
src
[
j
],
src
[
i
],
comparator
))
dst
[
k
]
=
src
[
j
++
];
else
dst
[
k
]
=
src
[
i
++
];
}
// postcondition: dst[lo .. hi] is sorted subarray
assert
isSorted
(
dst
,
lo
,
hi
,
comparator
);
}
private
static
void
sort
(
Object
[]
src
,
Object
[]
dst
,
int
lo
,
int
hi
,
Comparator
comparator
)
{
// if (hi <= lo) return;
if
(
hi
<=
lo
+
CUTOFF
)
{
insertionSort
(
dst
,
lo
,
hi
,
comparator
);
return
;
}
int
mid
=
lo
+
(
hi
-
lo
)
/
2
;
sort
(
dst
,
src
,
lo
,
mid
,
comparator
);
sort
(
dst
,
src
,
mid
+
1
,
hi
,
comparator
);
// using System.arraycopy() is a bit faster than the above loop
if
(
!
less
(
src
[
mid
+
1
],
src
[
mid
],
comparator
))
{
System
.
arraycopy
(
src
,
lo
,
dst
,
lo
,
hi
-
lo
+
1
);
return
;
}
merge
(
src
,
dst
,
lo
,
mid
,
hi
,
comparator
);
}
// sort from a[lo] to a[hi] using insertion sort
private
static
void
insertionSort
(
Object
[]
a
,
int
lo
,
int
hi
,
Comparator
comparator
)
{
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
for
(
int
j
=
i
;
j
>
lo
&&
less
(
a
[
j
],
a
[
j
–
1
],
comparator
);
j
—
)
exch
(
a
,
j
,
j
–
1
);
}
/***************************************************************************
* Check if array is sorted – useful for debugging.
***************************************************************************/
private
static
boolean
isSorted
(
Comparable
[]
a
)
{
return
isSorted
(
a
,
0
,
a
.
length
–
1
);
}
private
static
boolean
isSorted
(
Comparable
[]
a
,
int
lo
,
int
hi
)
{
for
(
int
i
=
lo
+
1
;
i
<=
hi
;
i
++
)
if
(
less
(
a
[
i
],
a
[
i
-
1
]))
return
false
;
return
true
;
}
private
static
boolean
isSorted
(
Object
[]
a
,
Comparator
comparator
)
{
return
isSorted
(
a
,
0
,
a
.
length
-
1
,
comparator
);
}
private
static
boolean
isSorted
(
Object
[]
a
,
int
lo
,
int
hi
,
Comparator
comparator
)
{
for
(
int
i
=
lo
+
1
;
i
<=
hi
;
i
++
)
if
(
less
(
a
[
i
],
a
[
i
-
1
],
comparator
))
return
false
;
return
true
;
}
// print array to standard output
private
static
void
show
(
Object
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
StdOut
.
println
(
a
[
i
]);
}
}
/**
* Reads in a sequence of strings from standard input; mergesorts them
* (using an optimized version of mergesort);
* and prints them to standard output in ascending order.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
[]
a
=
StdIn
.
readAllStrings
();
MergeX
.
sort
(
a
);
show
(
a
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/MinPQ.java
edu/princeton/cs/algs4/MinPQ.java
/******************************************************************************
* Compilation: javac MinPQ.java
* Execution: java MinPQ < input.txt
* Dependencies: StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/24pq/tinyPQ.txt
*
* Generic min priority queue implementation with a binary heap.
* Can be used with a comparator instead of the natural order.
*
* % java MinPQ < tinyPQ.txt
* E A E (6 left on pq)
*
* We use a one-based array to simplify parent and child calculations.
*
* Can be optimized by replacing full exchanges with half exchanges
* (ala insertion sort).
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Comparator
;
import
java
.
util
.
Iterator
;
import
java
.
util
.
NoSuchElementException
;
/**
* The {
@code
MinPQ} class represents a priority queue of generic keys.
* It supports the usual insert and delete-the-minimum
* operations, along with methods for peeking at the minimum key,
* testing if the priority queue is empty, and iterating through
* the keys.
*
* This implementation uses a binary heap.
* The insert and delete-the-minimum operations take
* Θ(log n) amortized time, where n is the number
* of elements in the priority queue. This is an amortized bound
* (and not a worst-case bound) because of array resizing operations.
* The min, size, and is-empty operations take
* Θ(1) time in the worst case.
* Construction takes time proportional to the specified capacity or the
* number of items used to initialize the data structure.
*
* For additional documentation, see
* Section 2.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*
*
@param
*/
public
class
MinPQ
<
Key
>
implements
Iterable
<
Key
>
{
private
Key
[]
pq
;
// store items at indices 1 to n
private
int
n
;
// number of items on priority queue
private
Comparator
<
Key
>
comparator
;
// optional comparator
/**
* Initializes an empty priority queue with the given initial capacity.
*
*
@param
initCapacity the initial capacity of this priority queue
*/
public
MinPQ
(
int
initCapacity
)
{
pq
=
(
Key
[])
new
Object
[
initCapacity
+
1
];
n
=
0
;
}
/**
* Initializes an empty priority queue.
*/
public
MinPQ
()
{
this
(
1
);
}
/**
* Initializes an empty priority queue with the given initial capacity,
* using the given comparator.
*
*
@param
initCapacity the initial capacity of this priority queue
*
@param
comparator the order in which to compare the keys
*/
public
MinPQ
(
int
initCapacity
,
Comparator
<
Key
>
comparator
)
{
this
.
comparator
=
comparator
;
pq
=
(
Key
[])
new
Object
[
initCapacity
+
1
];
n
=
0
;
}
/**
* Initializes an empty priority queue using the given comparator.
*
*
@param
comparator the order in which to compare the keys
*/
public
MinPQ
(
Comparator
<
Key
>
comparator
)
{
this
(
1
,
comparator
);
}
/**
* Initializes a priority queue from the array of keys.
*
* Takes time proportional to the number of keys, using sink-based heap construction.
*
*
@param
keys the array of keys
*/
public
MinPQ
(
Key
[]
keys
)
{
n
=
keys
.
length
;
pq
=
(
Key
[])
new
Object
[
keys
.
length
+
1
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
pq
[
i
+
1
]
=
keys
[
i
];
for
(
int
k
=
n
/
2
;
k
>=
1
;
k
—
)
sink
(
k
);
assert
isMinHeap
();
}
/**
* Returns true if this priority queue is empty.
*
*
@return
{
@code
true} if this priority queue is empty;
* {
@code
false} otherwise
*/
public
boolean
isEmpty
()
{
return
n
==
0
;
}
/**
* Returns the number of keys on this priority queue.
*
*
@return
the number of keys on this priority queue
*/
public
int
size
()
{
return
n
;
}
/**
* Returns a smallest key on this priority queue.
*
*
@return
a smallest key on this priority queue
*
@throws
NoSuchElementException if this priority queue is empty
*/
public
Key
min
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Priority queue underflow”
);
return
pq
[
1
];
}
// helper function to double the size of the heap array
private
void
resize
(
int
capacity
)
{
assert
capacity
>
n
;
Key
[]
temp
=
(
Key
[])
new
Object
[
capacity
];
for
(
int
i
=
1
;
i
<=
n
;
i
++
)
{
temp
[
i
]
=
pq
[
i
];
}
pq
=
temp
;
}
/**
* Adds a new key to this priority queue.
*
*
@param
x the key to add to this priority queue
*/
public
void
insert
(
Key
x
)
{
// double size of array if necessary
if
(
n
==
pq
.
length
-
1
)
resize
(
2
*
pq
.
length
);
// add x, and percolate it up to maintain heap invariant
pq
[
++
n
]
=
x
;
swim
(
n
);
assert
isMinHeap
();
}
/**
* Removes and returns a smallest key on this priority queue.
*
*
@return
a smallest key on this priority queue
*
@throws
NoSuchElementException if this priority queue is empty
*/
public
Key
delMin
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
"Priority queue underflow"
);
Key
min
=
pq
[
1
];
exch
(
1
,
n
--
);
sink
(
1
);
pq
[
n
+
1
]
=
null
;
// to avoid loiterig and help with garbage collection
if
((
n
>
0
)
&&
(
n
==
(
pq
.
length
–
1
)
/
4
))
resize
(
pq
.
length
/
2
);
assert
isMinHeap
();
return
min
;
}
/***************************************************************************
* Helper functions to restore the heap invariant.
***************************************************************************/
private
void
swim
(
int
k
)
{
while
(
k
>
1
&&
greater
(
k
/
2
,
k
))
{
exch
(
k
,
k
/
2
);
k
=
k
/
2
;
}
}
private
void
sink
(
int
k
)
{
while
(
2
*
k
<=
n
)
{
int
j
=
2
*
k
;
if
(
j
<
n
&&
greater
(
j
,
j
+
1
))
j
++
;
if
(
!
greater
(
k
,
j
))
break
;
exch
(
k
,
j
);
k
=
j
;
}
}
/***************************************************************************
* Helper functions for compares and swaps.
***************************************************************************/
private
boolean
greater
(
int
i
,
int
j
)
{
if
(
comparator
==
null
)
{
return
((
Comparable
<
Key
>
)
pq
[
i
]).
compareTo
(
pq
[
j
])
>
0
;
}
else
{
return
comparator
.
compare
(
pq
[
i
],
pq
[
j
])
>
0
;
}
}
private
void
exch
(
int
i
,
int
j
)
{
Key
swap
=
pq
[
i
];
pq
[
i
]
=
pq
[
j
];
pq
[
j
]
=
swap
;
}
// is pq[1..n] a min heap?
private
boolean
isMinHeap
()
{
for
(
int
i
=
1
;
i
<=
n
;
i
++
)
{
if
(
pq
[
i
]
==
null
)
return
false
;
}
for
(
int
i
=
n
+
1
;
i
<
pq
.
length
;
i
++
)
{
if
(
pq
[
i
]
!=
null
)
return
false
;
}
if
(
pq
[
0
]
!=
null
)
return
false
;
return
isMinHeapOrdered
(
1
);
}
// is subtree of pq[1..n] rooted at k a min heap?
private
boolean
isMinHeapOrdered
(
int
k
)
{
if
(
k
>
n
)
return
true
;
int
left
=
2
*
k
;
int
right
=
2
*
k
+
1
;
if
(
left
<=
n
&&
greater
(
k
,
left
))
return
false
;
if
(
right
<=
n
&&
greater
(
k
,
right
))
return
false
;
return
isMinHeapOrdered
(
left
)
&&
isMinHeapOrdered
(
right
);
}
/**
* Returns an iterator that iterates over the keys on this priority queue
* in ascending order.
*
* The iterator doesn’t implement {
@code
remove()} since it’s optional.
*
*
@return
an iterator that iterates over the keys in ascending order
*/
public
Iterator
<
Key
>
iterator
()
{
return
new
HeapIterator
();
}
private
class
HeapIterator
implements
Iterator
<
Key
>
{
// create a new pq
private
MinPQ
<
Key
>
copy
;
// add all items to copy of heap
// takes linear time since already in heap order so no keys move
public
HeapIterator
()
{
if
(
comparator
==
null
)
copy
=
new
MinPQ
<
Key
>
(
size
());
else
copy
=
new
MinPQ
<
Key
>
(
size
(),
comparator
);
for
(
int
i
=
1
;
i
<=
n
;
i
++
)
copy
.
insert
(
pq
[
i
]);
}
public
boolean
hasNext
()
{
return
!
copy
.
isEmpty
();
}
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
public
Key
next
()
{
if
(
!
hasNext
())
throw
new
NoSuchElementException
();
return
copy
.
delMin
();
}
}
/**
* Unit tests the {
@code
MinPQ} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
MinPQ
<
String
>
pq
=
new
MinPQ
<
String
>
();
while
(
!
StdIn
.
isEmpty
())
{
String
item
=
StdIn
.
readString
();
if
(
!
item
.
equals
(
“-”
))
pq
.
insert
(
item
);
else
if
(
!
pq
.
isEmpty
())
StdOut
.
print
(
pq
.
delMin
()
+
” ”
);
}
StdOut
.
println
(
“(”
+
pq
.
size
()
+
” left on pq)”
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/MSD.java
edu/princeton/cs/algs4/MSD.java
/******************************************************************************
* Compilation: javac MSD.java
* Execution: java MSD < input.txt * Dependencies: StdIn.java StdOut.java * Data files: https://algs4.cs.princeton.edu/51radix/words3.txt * https://algs4.cs.princeton.edu/51radix/shells.txt * * Sort an array of strings or integers using MSD radix sort. * * % java MSD < shells.txt * are * by * sea * seashells * seashells * sells * sells * she * she * shells * shore * surely * the * the * ******************************************************************************/ package edu . princeton . cs . algs4 ; /** * The { @code MSD} class provides static methods for sorting an * array of extended ASCII strings or integers using MSD radix sort. *
* For additional documentation,
* see Section 5.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
MSD
{
private
static
final
int
BITS_PER_BYTE
=
8
;
private
static
final
int
BITS_PER_INT
=
32
;
// each Java int is 32 bits
private
static
final
int
R
=
256
;
// extended ASCII alphabet size
private
static
final
int
CUTOFF
=
15
;
// cutoff to insertion sort
// do not instantiate
private
MSD
()
{
}
/**
* Rearranges the array of extended ASCII strings in ascending order.
*
*
@param
a the array to be sorted
*/
public
static
void
sort
(
String
[]
a
)
{
int
n
=
a
.
length
;
String
[]
aux
=
new
String
[
n
];
sort
(
a
,
0
,
n
–
1
,
0
,
aux
);
}
// return dth character of s, -1 if d = length of string
private
static
int
charAt
(
String
s
,
int
d
)
{
assert
d
>=
0
&&
d
<=
s
.
length
();
if
(
d
==
s
.
length
())
return
-
1
;
return
s
.
charAt
(
d
);
}
// sort from a[lo] to a[hi], starting at the dth character
private
static
void
sort
(
String
[]
a
,
int
lo
,
int
hi
,
int
d
,
String
[]
aux
)
{
// cutoff to insertion sort for small subarrays
if
(
hi
<=
lo
+
CUTOFF
)
{
insertion
(
a
,
lo
,
hi
,
d
);
return
;
}
// compute frequency counts
int
[]
count
=
new
int
[
R
+
2
];
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
{
int
c
=
charAt
(
a
[
i
],
d
);
count
[
c
+
2
]
++
;
}
// transform counts to indicies
for
(
int
r
=
0
;
r
<
R
+
1
;
r
++
)
count
[
r
+
1
]
+=
count
[
r
];
// distribute
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
{
int
c
=
charAt
(
a
[
i
],
d
);
aux
[
count
[
c
+
1
]
++
]
=
a
[
i
];
}
// copy back
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
a
[
i
]
=
aux
[
i
-
lo
];
// recursively sort for each character (excludes sentinel -1)
for
(
int
r
=
0
;
r
<
R
;
r
++
)
sort
(
a
,
lo
+
count
[
r
],
lo
+
count
[
r
+
1
]
-
1
,
d
+
1
,
aux
);
}
// insertion sort a[lo..hi], starting at dth character
private
static
void
insertion
(
String
[]
a
,
int
lo
,
int
hi
,
int
d
)
{
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
for
(
int
j
=
i
;
j
>
lo
&&
less
(
a
[
j
],
a
[
j
–
1
],
d
);
j
—
)
exch
(
a
,
j
,
j
–
1
);
}
// exchange a[i] and a[j]
private
static
void
exch
(
String
[]
a
,
int
i
,
int
j
)
{
String
temp
=
a
[
i
];
a
[
i
]
=
a
[
j
];
a
[
j
]
=
temp
;
}
// is v less than w, starting at character d
private
static
boolean
less
(
String
v
,
String
w
,
int
d
)
{
// assert v.substring(0, d).equals(w.substring(0, d));
for
(
int
i
=
d
;
i
<
Math
.
min
(
v
.
length
(),
w
.
length
());
i
++
)
{
if
(
v
.
charAt
(
i
)
<
w
.
charAt
(
i
))
return
true
;
if
(
v
.
charAt
(
i
)
>
w
.
charAt
(
i
))
return
false
;
}
return
v
.
length
()
<
w
.
length
();
}
/**
* Rearranges the array of 32-bit integers in ascending order.
* Currently assumes that the integers are nonnegative.
*
*
@param
a the array to be sorted
*/
public
static
void
sort
(
int
[]
a
)
{
int
n
=
a
.
length
;
int
[]
aux
=
new
int
[
n
];
sort
(
a
,
0
,
n
-
1
,
0
,
aux
);
}
// MSD sort from a[lo] to a[hi], starting at the dth byte
private
static
void
sort
(
int
[]
a
,
int
lo
,
int
hi
,
int
d
,
int
[]
aux
)
{
// cutoff to insertion sort for small subarrays
if
(
hi
<=
lo
+
CUTOFF
)
{
insertion
(
a
,
lo
,
hi
,
d
);
return
;
}
// compute frequency counts (need R = 256)
int
[]
count
=
new
int
[
R
+
1
];
int
mask
=
R
-
1
;
// 0xFF;
int
shift
=
BITS_PER_INT
-
BITS_PER_BYTE
*
d
-
BITS_PER_BYTE
;
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
{
int
c
=
(
a
[
i
]
>>
shift
)
&
mask
;
count
[
c
+
1
]
++
;
}
// transform counts to indicies
for
(
int
r
=
0
;
r
<
R
;
r
++
)
count
[
r
+
1
]
+=
count
[
r
];
/************* BUGGGY CODE.
// for most significant byte, 0x80-0xFF comes before 0x00-0x7F
if (d == 0) {
int shift1 = count[R] - count[R/2];
int shift2 = count[R/2];
for (int r = 0; r < R/2; r++)
count[r] += shift1;
for (int r = R/2; r < R; r++)
count[r] -= shift2;
}
************************************/
// distribute
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
{
int
c
=
(
a
[
i
]
>>
shift
)
&
mask
;
aux
[
count
[
c
]
++
]
=
a
[
i
];
}
// copy back
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
a
[
i
]
=
aux
[
i
-
lo
];
// no more bits
if
(
d
==
4
)
return
;
// recursively sort for each character
if
(
count
[
0
]
>
0
)
sort
(
a
,
lo
,
lo
+
count
[
0
]
–
1
,
d
+
1
,
aux
);
for
(
int
r
=
0
;
r
<
R
;
r
++
)
if
(
count
[
r
+
1
]
>
count
[
r
])
sort
(
a
,
lo
+
count
[
r
],
lo
+
count
[
r
+
1
]
–
1
,
d
+
1
,
aux
);
}
// TODO: insertion sort a[lo..hi], starting at dth character
private
static
void
insertion
(
int
[]
a
,
int
lo
,
int
hi
,
int
d
)
{
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
for
(
int
j
=
i
;
j
>
lo
&&
a
[
j
]
<
a
[
j
-
1
];
j
--
)
exch
(
a
,
j
,
j
-
1
);
}
// exchange a[i] and a[j]
private
static
void
exch
(
int
[]
a
,
int
i
,
int
j
)
{
int
temp
=
a
[
i
];
a
[
i
]
=
a
[
j
];
a
[
j
]
=
temp
;
}
/**
* Reads in a sequence of extended ASCII strings from standard input;
* MSD radix sorts them;
* and prints them to standard output in ascending order.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
[]
a
=
StdIn
.
readAllStrings
();
int
n
=
a
.
length
;
sort
(
a
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
StdOut
.
println
(
a
[
i
]);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Multiway.java
edu/princeton/cs/algs4/Multiway.java
/******************************************************************************
* Compilation: javac Multiway.java
* Execution: java Multiway input1.txt input2.txt input3.txt ...
* Dependencies: IndexMinPQ.java In.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/24pq/m1.txt
* https://algs4.cs.princeton.edu/24pq/m2.txt
* https://algs4.cs.princeton.edu/24pq/m3.txt
*
* Merges together the sorted input stream given as command-line arguments
* into a single sorted output stream on standard output.
*
* % more m1.txt
* A B C F G I I Z
*
* % more m2.txt
* B D H P Q Q
*
* % more m3.txt
* A B E F J N
*
* % java Multiway m1.txt m2.txt m3.txt
* A A B B B C D E F F G H I I J N P Q Q Z
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Multiway} class provides a client for reading in several
* sorted text files and merging them together into a single sorted
* text stream.
* This implementation uses a {
@link
IndexMinPQ} to perform the multiway
* merge.
*
* For additional documentation, see Section 2.4
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Multiway
{
// This class should not be instantiated.
private
Multiway
()
{
}
// merge together the sorted input streams and write the sorted result to standard output
private
static
void
merge
(
In
[]
streams
)
{
int
n
=
streams
.
length
;
IndexMinPQ
<
String
>
pq
=
new
IndexMinPQ
<
String
>
(
n
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
if
(
!
streams
[
i
].
isEmpty
())
pq
.
insert
(
i
,
streams
[
i
].
readString
());
// Extract and print min and read next from its stream.
while
(
!
pq
.
isEmpty
())
{
StdOut
.
print
(
pq
.
minKey
()
+
" "
);
int
i
=
pq
.
delMin
();
if
(
!
streams
[
i
].
isEmpty
())
pq
.
insert
(
i
,
streams
[
i
].
readString
());
}
StdOut
.
println
();
}
/**
* Reads sorted text files specified as command-line arguments;
* merges them together into a sorted output; and writes
* the results to standard output.
* Note: this client does not check that the input files are sorted.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
n
=
args
.
length
;
In
[]
streams
=
new
In
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
streams
[
i
]
=
new
In
(
args
[
i
]);
merge
(
streams
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/MultiwayMinPQ.java
edu/princeton/cs/algs4/MultiwayMinPQ.java
/******************************************************************************
* Compilation: javac MultiwayMinPQ.java
* Execution:
*
* A multiway heap.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Iterator
;
import
java
.
util
.
Comparator
;
import
java
.
util
.
NoSuchElementException
;
/**
* The MultiwayMinPQ class represents a priority queue of generic keys.
* It supports the usual insert and delete-the-minimum operations.
* It also supports methods for peeking at the minimum key,
* testing if the priority queue is empty, and iterating through
* the keys.
* It is possible to build the priority queue using a Comparator.
* If not, the natural order relation between the keys will be used.
*
* This implementation uses a multiway heap.
* For simplified notations, logarithm in base d will be referred as log-d
* The delete-the-minimum operation takes time proportional to d*log-d(n)
* The insert takes time proportional to log-d(n)
* The is-empty, min-key and size operations take constant time.
* Constructor takes time proportional to the specified capacity.
*
*
@author
Tristan Claverie
*/
public
class
MultiwayMinPQ
<
Key
>
implements
Iterable
<
Key
>
{
private
final
int
d
;
//Dimension of the heap
private
int
n
;
//Number of keys currently in the heap
private
int
order
;
//Number of levels of the tree
private
Key
[]
keys
;
//Array of keys
private
final
Comparator
<
Key
>
comp
;
//Comparator over the keys
/**
* Initializes an empty priority queue
* Worst case is O(d)
*
*
@param
d dimension of the heap
*
@throws
java.lang.IllegalArgumentException if {
@code
d < 2}
*/
public
MultiwayMinPQ
(
int
d
)
{
if
(
d
<
2
)
throw
new
IllegalArgumentException
(
"Dimension should be 2 or over"
);
this
.
d
=
d
;
order
=
1
;
keys
=
(
Key
[])
new
Comparable
[
d
<<
1
];
comp
=
new
MyComparator
();
}
/**
* Initializes an empty priority queue
* Worst case is O(d)
*
*
@param
d dimension of the heap
*
@param
comparator a Comparator over the keys
*
@throws
java.lang.IllegalArgumentException if {
@code
d < 2}
*/
public
MultiwayMinPQ
(
Comparator
<
Key
>
comparator
,
int
d
)
{
if
(
d
<
2
)
throw
new
IllegalArgumentException
(
"Dimension should be 2 or over"
);
this
.
d
=
d
;
order
=
1
;
keys
=
(
Key
[])
new
Comparable
[
d
<<
1
];
comp
=
comparator
;
}
/**
* Initializes a priority queue with given indexes
* Worst case is O(n*log-d(n))
*
*
@param
d dimension of the heap
*
@param
a an array of keys
*
@throws
java.lang.IllegalArgumentException if {
@code
d < 2}
*/
public
MultiwayMinPQ
(
Key
[]
a
,
int
d
)
{
if
(
d
<
2
)
throw
new
IllegalArgumentException
(
"Dimension should be 2 or over"
);
this
.
d
=
d
;
order
=
1
;
keys
=
(
Key
[])
new
Comparable
[
d
<<
1
];
comp
=
new
MyComparator
();
for
(
Key
key
:
a
)
insert
(
key
);
}
/**
* Initializes a priority queue with given indexes
* Worst case is O(a*log-d(n))
*
*
@param
d dimension of the heap
*
@param
comparator a Comparator over the keys
*
@param
a an array of keys
*
@throws
java.lang.IllegalArgumentException if {
@code
d < 2}
*/
public
MultiwayMinPQ
(
Comparator
<
Key
>
comparator
,
Key
[]
a
,
int
d
)
{
if
(
d
<
2
)
throw
new
IllegalArgumentException
(
"Dimension should be 2 or over"
);
this
.
d
=
d
;
order
=
1
;
keys
=
(
Key
[])
new
Comparable
[
d
<<
1
];
comp
=
comparator
;
for
(
Key
key
:
a
)
insert
(
key
);
}
/**
* Whether the priority queue is empty
* Worst case is O(1)
*
@return
true if the priority queue is empty, false if not
*/
public
boolean
isEmpty
()
{
return
n
==
0
;
}
/**
* Number of elements currently on the priority queue
* Worst case is O(1)
*
@return
the number of elements on the priority queue
*/
public
int
size
()
{
return
n
;
}
/**
* Puts a Key on the priority queue
* Worst case is O(log-d(n))
*
@param
key a Key
*/
public
void
insert
(
Key
key
)
{
keys
[
n
+
d
]
=
key
;
swim
(
n
++
);
if
(
n
==
keys
.
length
-
d
)
{
resize
(
getN
(
order
+
1
)
+
d
);
order
++
;
}
}
/**
* Gets the minimum key currently in the queue
* Worst case is O(1)
*
@throws
java.util.NoSuchElementException if the priority queue is empty
*
@return
the minimum key currently in the priority queue
*/
public
Key
minKey
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
"Priority queue is empty"
);
return
keys
[
d
];
}
/**
* Deletes the minimum key
* Worst case is O(d*log-d(n))
*
@throws
java.util.NoSuchElementException if the priority queue is empty
*
@return
the minimum key
*/
public
Key
delMin
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
"Priority queue is empty"
);
exch
(
0
,
--
n
);
sink
(
0
);
Key
min
=
keys
[
n
+
d
];
keys
[
n
+
d
]
=
null
;
int
number
=
getN
(
order
-
2
);
if
(
order
>
1
&&
n
==
number
)
{
resize
(
number
+
(
int
)
Math
.
pow
(
d
,
order
–
1
)
+
d
);
order
—
;
}
return
min
;
}
/***************************
* General helper functions
**************************/
//Compares two keys
private
boolean
greater
(
int
x
,
int
y
)
{
int
i
=
x
+
d
,
j
=
y
+
d
;
if
(
keys
[
i
]
==
null
)
return
false
;
if
(
keys
[
j
]
==
null
)
return
true
;
return
comp
.
compare
(
keys
[
i
],
keys
[
j
])
>
0
;
}
//Exchanges the position of two keys
private
void
exch
(
int
x
,
int
y
)
{
int
i
=
x
+
d
,
j
=
y
+
d
;
Key
swap
=
keys
[
i
];
keys
[
i
]
=
keys
[
j
];
keys
[
j
]
=
swap
;
}
//Gets the maximum number of keys in the heap, given the number of levels of the tree
private
int
getN
(
int
order
)
{
return
(
1
–
((
int
)
Math
.
pow
(
d
,
order
+
1
)))
/
(
1
–
d
);
}
/***************************
* Functions for moving upward or downward
**************************/
//Moves upward
private
void
swim
(
int
i
)
{
if
(
i
>
0
&&
greater
((
i
–
1
)
/
d
,
i
))
{
exch
(
i
,
(
i
–
1
)
/
d
);
swim
((
i
–
1
)
/
d
);
}
}
//Moves downward
private
void
sink
(
int
i
)
{
int
child
=
d
*
i
+
1
;
if
(
child
>=
n
)
return
;
int
min
=
minChild
(
i
);
while
(
min
<
n
&&
greater
(
i
,
min
))
{
exch
(
i
,
min
);
i
=
min
;
min
=
minChild
(
i
);
}
}
/***************************
* Deletes the minimum child
**************************/
//Return the minimum child of i
private
int
minChild
(
int
i
)
{
int
loBound
=
d
*
i
+
1
,
hiBound
=
d
*
i
+
d
;
int
min
=
loBound
;
for
(
int
cur
=
loBound
;
cur
<=
hiBound
;
cur
++
)
{
if
(
cur
<
n
&&
greater
(
min
,
cur
))
min
=
cur
;
}
return
min
;
}
/***************************
* Resize the priority queue
**************************/
//Resizes the array containing the keys
//If the heap is full, it adds one floor
//If the heap has two floors empty, it removes one
private
void
resize
(
int
N
)
{
Key
[]
array
=
(
Key
[])
new
Comparable
[
N
];
for
(
int
i
=
0
;
i
<
Math
.
min
(
keys
.
length
,
array
.
length
);
i
++
)
{
array
[
i
]
=
keys
[
i
];
keys
[
i
]
=
null
;
}
keys
=
array
;
}
/***************************
* Iterator
**************************/
/**
* Gets an Iterator over the keys in the priority queue in ascending order
* The Iterator does not implement the remove() method
* iterator() : Worst case is O(n)
* next() : Worst case is O(d*log-d(n))
* hasNext() : Worst case is O(1)
*
@return
an Iterator over the keys in the priority queue in ascending order
*/
public
Iterator
<
Key
>
iterator
()
{
return
new
MyIterator
();
}
//Constructs an Iterator over the keys in linear time
private
class
MyIterator
implements
Iterator
<
Key
>
{
MultiwayMinPQ
<
Key
>
data
;
public
MyIterator
()
{
data
=
new
MultiwayMinPQ
<
Key
>
(
comp
,
d
);
data
.
keys
=
(
Key
[])
new
Comparable
[
keys
.
length
];
data
.
n
=
n
;
for
(
int
i
=
0
;
i
<
keys
.
length
;
i
++
)
{
data
.
keys
[
i
]
=
keys
[
i
];
}
}
public
boolean
hasNext
()
{
return
!
data
.
isEmpty
();
}
public
Key
next
()
{
if
(
!
hasNext
())
throw
new
NoSuchElementException
();
return
data
.
delMin
();
}
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
}
/***************************
* Comparator
**************************/
//default Comparator
private
class
MyComparator
implements
Comparator
<
Key
>
{
@
Override
public
int
compare
(
Key
key1
,
Key
key2
)
{
return
((
Comparable
<
Key
>
)
key1
).
compareTo
(
key2
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/NFA.java
edu/princeton/cs/algs4/NFA.java
/******************************************************************************
* Compilation: javac NFA.java
* Execution: java NFA regexp text
* Dependencies: Stack.java Bag.java Digraph.java DirectedDFS.java
*
* % java NFA “(A*B|AC)D” AAAABD
* true
*
* % java NFA “(A*B|AC)D” AAAAC
* false
*
* % java NFA “(a|(bc)*d)*” abcbcd
* true
*
* % java NFA “(a|(bc)*d)*” abcbcbcdaaaabcbcdaaaddd
* true
*
* Remarks
* ———–
* The following features are not supported:
* – The + operator
* – Multiway or
* – Metacharacters in the text
* – Character classes.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
NFA} class provides a data type for creating a
* nondeterministic finite state automaton (NFA) from a regular
* expression and testing whether a given string is matched by that regular
* expression.
* It supports the following operations: concatenation,
* closure, binary or, and parentheses.
* It does not support mutiway or, character classes,
* metacharacters (either in the text or pattern),
* capturing capabilities, greedy or relucantant
* modifiers, and other features in industrial-strength implementations
* such as {
@link
java.util.regex.Pattern} and {
@link
java.util.regex.Matcher}.
*
* This implementation builds the NFA using a digraph and a stack
* and simulates the NFA using digraph search (see the textbook for details).
* The constructor takes time proportional to m, where m
* is the number of characters in the regular expression.
* The recognizes method takes time proportional to m n,
* where n is the number of characters in the text.
*
* For additional documentation,
* see Section 5.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
NFA
{
private
Digraph
graph
;
// digraph of epsilon transitions
private
String
regexp
;
// regular expression
private
final
int
m
;
// number of characters in regular expression
/**
* Initializes the NFA from the specified regular expression.
*
*
@param
regexp the regular expression
*/
public
NFA
(
String
regexp
)
{
this
.
regexp
=
regexp
;
m
=
regexp
.
length
();
Stack
<
Integer
>
ops
=
new
Stack
<
Integer
>
();
graph
=
new
Digraph
(
m
+
1
);
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
int
lp
=
i
;
if
(
regexp
.
charAt
(
i
)
==
'('
||
regexp
.
charAt
(
i
)
==
'|'
)
ops
.
push
(
i
);
else
if
(
regexp
.
charAt
(
i
)
==
')'
)
{
int
or
=
ops
.
pop
();
// 2-way or operator
if
(
regexp
.
charAt
(
or
)
==
'|'
)
{
lp
=
ops
.
pop
();
graph
.
addEdge
(
lp
,
or
+
1
);
graph
.
addEdge
(
or
,
i
);
}
else
if
(
regexp
.
charAt
(
or
)
==
'('
)
lp
=
or
;
else
assert
false
;
}
// closure operator (uses 1-character lookahead)
if
(
i
<
m
-
1
&&
regexp
.
charAt
(
i
+
1
)
==
'*'
)
{
graph
.
addEdge
(
lp
,
i
+
1
);
graph
.
addEdge
(
i
+
1
,
lp
);
}
if
(
regexp
.
charAt
(
i
)
==
'('
||
regexp
.
charAt
(
i
)
==
'*'
||
regexp
.
charAt
(
i
)
==
')'
)
graph
.
addEdge
(
i
,
i
+
1
);
}
if
(
ops
.
size
()
!=
0
)
throw
new
IllegalArgumentException
(
"Invalid regular expression"
);
}
/**
* Returns true if the text is matched by the regular expression.
*
*
@param
txt the text
*
@return
{
@code
true} if the text is matched by the regular expression,
* {
@code
false} otherwise
*/
public
boolean
recognizes
(
String
txt
)
{
DirectedDFS
dfs
=
new
DirectedDFS
(
graph
,
0
);
Bag
<
Integer
>
pc
=
new
Bag
<
Integer
>
();
for
(
int
v
=
0
;
v
<
graph
.
V
();
v
++
)
if
(
dfs
.
marked
(
v
))
pc
.
add
(
v
);
// Compute possible NFA states for txt[i+1]
for
(
int
i
=
0
;
i
<
txt
.
length
();
i
++
)
{
if
(
txt
.
charAt
(
i
)
==
'*'
||
txt
.
charAt
(
i
)
==
'|'
||
txt
.
charAt
(
i
)
==
'('
||
txt
.
charAt
(
i
)
==
')'
)
throw
new
IllegalArgumentException
(
"text contains the metacharacter '"
+
txt
.
charAt
(
i
)
+
"'"
);
Bag
<
Integer
>
match
=
new
Bag
<
Integer
>
();
for
(
int
v
:
pc
)
{
if
(
v
==
m
)
continue
;
if
((
regexp
.
charAt
(
v
)
==
txt
.
charAt
(
i
))
||
regexp
.
charAt
(
v
)
==
‘.’
)
match
.
add
(
v
+
1
);
}
dfs
=
new
DirectedDFS
(
graph
,
match
);
pc
=
new
Bag
<
Integer
>
();
for
(
int
v
=
0
;
v
<
graph
.
V
();
v
++
)
if
(
dfs
.
marked
(
v
))
pc
.
add
(
v
);
// optimization if no states reachable
if
(
pc
.
size
()
==
0
)
return
false
;
}
// check for accept state
for
(
int
v
:
pc
)
if
(
v
==
m
)
return
true
;
return
false
;
}
/**
* Unit tests the {
@code
NFA} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
regexp
=
"("
+
args
[
0
]
+
")"
;
String
txt
=
args
[
1
];
NFA nfa
=
new
NFA
(
regexp
);
StdOut
.
println
(
nfa
.
recognizes
(
txt
));
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/NonrecursiveDFS.java
edu/princeton/cs/algs4/NonrecursiveDFS.java
/******************************************************************************
* Compilation: javac NonrecursiveDFS.java
* Execution: java NonrecursiveDFS graph.txt s
* Dependencies: Graph.java Queue.java Stack.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/41graph/tinyCG.txt
* https://algs4.cs.princeton.edu/41graph/tinyG.txt
* https://algs4.cs.princeton.edu/41graph/mediumG.txt
*
* Run nonrecurisve depth-first search on an undirected graph.
* Runs in O(E + V) time using O(V) extra space.
*
* Explores the vertices in exactly the same order as DepthFirstSearch.java.
*
* % java Graph tinyG.txt
* 13 vertices, 13 edges
* 0: 6 2 1 5
* 1: 0
* 2: 0
* 3: 5 4
* 4: 5 6 3
* 5: 3 4 0
* 6: 0 4
* 7: 8
* 8: 7
* 9: 11 10 12
* 10: 9
* 11: 9 12
* 12: 11 9
*
* % java NonrecursiveDFS tinyG.txt 0
* 0 1 2 3 4 5 6
*
* % java NonrecursiveDFS tinyG.txt 9
* 9 10 11 12
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Iterator
;
/**
* The {
@code
NonrecursiveDFS} class represents a data type for finding
* the vertices connected to a source vertex s in the undirected
* graph.
*
* This implementation uses a nonrecursive version of depth-first search
* with an explicit stack.
* See {
@link
DepthFirstSearch} for the classic recursive version.
* The constructor takes Θ(V + E) time in the worst
* case, where V is the number of vertices and E is the
* number of edges.
* The {
@link
#marked(int)} instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the graph).
*
* For additional documentation,
* see Section 4.1
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
NonrecursiveDFS
{
private
boolean
[]
marked
;
// marked[v] = is there an s-v path?
/**
* Computes the vertices connected to the source vertex {
@code
s} in the graph {
@code
G}.
*
@param
G the graph
*
@param
s the source vertex
*
@throws
IllegalArgumentException unless {
@code
0 <= s < V}
*/
public
NonrecursiveDFS
(
Graph
G
,
int
s
)
{
marked
=
new
boolean
[
G
.
V
()];
validateVertex
(
s
);
// to be able to iterate over each adjacency list, keeping track of which
// vertex in each adjacency list needs to be explored next
Iterator
<
Integer
>
[]
adj
=
(
Iterator
<
Integer
>
[])
new
Iterator
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
adj
[
v
]
=
G
.
adj
(
v
).
iterator
();
// depth-first search using an explicit stack
Stack
<
Integer
>
stack
=
new
Stack
<
Integer
>
();
marked
[
s
]
=
true
;
stack
.
push
(
s
);
while
(
!
stack
.
isEmpty
())
{
int
v
=
stack
.
peek
();
if
(
adj
[
v
].
hasNext
())
{
int
w
=
adj
[
v
].
next
();
// StdOut.printf(“check %d\n”, w);
if
(
!
marked
[
w
])
{
// discovered vertex w for the first time
marked
[
w
]
=
true
;
// edgeTo[w] = v;
stack
.
push
(
w
);
// StdOut.printf(“dfs(%d)\n”, w);
}
}
else
{
// StdOut.printf(“%d done\n”, v);
stack
.
pop
();
}
}
}
/**
* Is vertex {
@code
v} connected to the source vertex {
@code
s}?
*
@param
v the vertex
*
@return
{
@code
true} if vertex {
@code
v} is connected to the source vertex {
@code
s},
* and {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
boolean
marked
(
int
v
)
{
validateVertex
(
v
);
return
marked
[
v
];
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
marked
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
NonrecursiveDFS} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
Graph
G
=
new
Graph
(
in
);
int
s
=
Integer
.
parseInt
(
args
[
1
]);
NonrecursiveDFS
dfs
=
new
NonrecursiveDFS
(
G
,
s
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
dfs
.
marked
(
v
))
StdOut
.
print
(
v
+
" "
);
StdOut
.
println
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/NonrecursiveDirectedDFS.java
edu/princeton/cs/algs4/NonrecursiveDirectedDFS.java
/******************************************************************************
* Compilation: javac NonrecursiveDirectedDFS.java
* Execution: java NonrecursiveDirectedDFS digraph.txt s
* Dependencies: Digraph.java Queue.java Stack.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/42digraph/tinyDG.txt
* https://algs4.cs.princeton.edu/42digraph/mediumDG.txt
* https://algs4.cs.princeton.edu/42digraph/largeDG.txt
*
* Run nonrecurisve depth-first search on an directed graph.
* Runs in O(E + V) time.
*
* Explores the vertices in exactly the same order as DirectedDFS.java.
*
*
* % java NonrecursiveDirectedDFS tinyDG.txt 1
* 1
*
* % java NonrecursiveDirectedDFS tinyDG.txt 2
* 0 1 2 3 4 5
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Iterator
;
/**
* The {
@code
NonrecursiveDirectedDFS} class represents a data type for finding
* the vertices reachable from a source vertex s in the digraph.
*
* This implementation uses a nonrecursive version of depth-first search
* with an explicit stack.
* The constructor takes Θ(V + E) time in the
* worst case, where V is the number of vertices and E
* is the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the digraph).
*
* For additional documentation,
* see Section 4.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
NonrecursiveDirectedDFS
{
private
boolean
[]
marked
;
// marked[v] = is there an s->v path?
/**
* Computes the vertices reachable from the source vertex {
@code
s} in the digraph {
@code
G}.
*
@param
G the digraph
*
@param
s the source vertex
*
@throws
IllegalArgumentException unless {
@code
0 <= s < V}
*/
public
NonrecursiveDirectedDFS
(
Digraph
G
,
int
s
)
{
marked
=
new
boolean
[
G
.
V
()];
validateVertex
(
s
);
// to be able to iterate over each adjacency list, keeping track of which
// vertex in each adjacency list needs to be explored next
Iterator
<
Integer
>
[]
adj
=
(
Iterator
<
Integer
>
[])
new
Iterator
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
adj
[
v
]
=
G
.
adj
(
v
).
iterator
();
// depth-first search using an explicit stack
Stack
<
Integer
>
stack
=
new
Stack
<
Integer
>
();
marked
[
s
]
=
true
;
stack
.
push
(
s
);
while
(
!
stack
.
isEmpty
())
{
int
v
=
stack
.
peek
();
if
(
adj
[
v
].
hasNext
())
{
int
w
=
adj
[
v
].
next
();
// StdOut.printf(“check %d\n”, w);
if
(
!
marked
[
w
])
{
// discovered vertex w for the first time
marked
[
w
]
=
true
;
// edgeTo[w] = v;
stack
.
push
(
w
);
// StdOut.printf(“dfs(%d)\n”, w);
}
}
else
{
// StdOut.printf(“%d done\n”, v);
stack
.
pop
();
}
}
}
/**
* Is vertex {
@code
v} reachable from the source vertex {
@code
s}?
*
@param
v the vertex
*
@return
{
@code
true} if vertex {
@code
v} is reachable from the source vertex {
@code
s},
* and {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
boolean
marked
(
int
v
)
{
validateVertex
(
v
);
return
marked
[
v
];
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
marked
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
NonrecursiveDirectedDFS} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
Digraph
G
=
new
Digraph
(
in
);
int
s
=
Integer
.
parseInt
(
args
[
1
]);
NonrecursiveDirectedDFS
dfs
=
new
NonrecursiveDirectedDFS
(
G
,
s
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
dfs
.
marked
(
v
))
StdOut
.
print
(
v
+
" "
);
StdOut
.
println
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Out.java
edu/princeton/cs/algs4/Out.java
/******************************************************************************
* Compilation: javac Out.java
* Execution: java Out
* Dependencies: none
*
* Writes data of various types to: stdout, file, or socket.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
io
.
FileOutputStream
;
import
java
.
io
.
IOException
;
import
java
.
io
.
OutputStream
;
import
java
.
io
.
OutputStreamWriter
;
import
java
.
io
.
PrintWriter
;
import
java
.
net
.
Socket
;
import
java
.
util
.
Locale
;
/**
* This class provides methods for writing strings and numbers to
* various output streams, including standard output, file, and sockets.
*
* For additional documentation, see
* Section 3.1 of
* Computer Science: An Interdisciplinary Approach
* by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Out
{
// force Unicode UTF-8 encoding; otherwise it’s system dependent
private
static
final
String
CHARSET_NAME
=
“UTF-8”
;
// assume language = English, country = US for consistency with In
private
static
final
Locale
LOCALE
=
Locale
.
US
;
private
PrintWriter
out
;
/**
* Initializes an output stream from a {
@link
OutputStream}.
*
*
@param
os the {
@code
OutputStream}
*/
public
Out
(
OutputStream
os
)
{
try
{
OutputStreamWriter
osw
=
new
OutputStreamWriter
(
os
,
CHARSET_NAME
);
out
=
new
PrintWriter
(
osw
,
true
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
/**
* Initializes an output stream from standard output.
*/
public
Out
()
{
this
(
System
.
out
);
}
/**
* Initializes an output stream from a socket.
*
*
@param
socket the socket
*/
public
Out
(
Socket
socket
)
{
try
{
OutputStream
os
=
socket
.
getOutputStream
();
OutputStreamWriter
osw
=
new
OutputStreamWriter
(
os
,
CHARSET_NAME
);
out
=
new
PrintWriter
(
osw
,
true
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
/**
* Initializes an output stream from a file.
*
*
@param
filename the name of the file
*/
public
Out
(
String
filename
)
{
try
{
OutputStream
os
=
new
FileOutputStream
(
filename
);
OutputStreamWriter
osw
=
new
OutputStreamWriter
(
os
,
CHARSET_NAME
);
out
=
new
PrintWriter
(
osw
,
true
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
/**
* Closes the output stream.
*/
public
void
close
()
{
out
.
close
();
}
/**
* Terminates the current line by printing the line-separator string.
*/
public
void
println
()
{
out
.
println
();
}
/**
* Prints an object to this output stream and then terminates the line.
*
*
@param
x the object to print
*/
public
void
println
(
Object
x
)
{
out
.
println
(
x
);
}
/**
* Prints a boolean to this output stream and then terminates the line.
*
*
@param
x the boolean to print
*/
public
void
println
(
boolean
x
)
{
out
.
println
(
x
);
}
/**
* Prints a character to this output stream and then terminates the line.
*
*
@param
x the character to print
*/
public
void
println
(
char
x
)
{
out
.
println
(
x
);
}
/**
* Prints a double to this output stream and then terminates the line.
*
*
@param
x the double to print
*/
public
void
println
(
double
x
)
{
out
.
println
(
x
);
}
/**
* Prints a float to this output stream and then terminates the line.
*
*
@param
x the float to print
*/
public
void
println
(
float
x
)
{
out
.
println
(
x
);
}
/**
* Prints an integer to this output stream and then terminates the line.
*
*
@param
x the integer to print
*/
public
void
println
(
int
x
)
{
out
.
println
(
x
);
}
/**
* Prints a long to this output stream and then terminates the line.
*
*
@param
x the long to print
*/
public
void
println
(
long
x
)
{
out
.
println
(
x
);
}
/**
* Prints a byte to this output stream and then terminates the line.
*
* To write binary data, see {
@link
BinaryOut}.
*
*
@param
x the byte to print
*/
public
void
println
(
byte
x
)
{
out
.
println
(
x
);
}
/**
* Flushes this output stream.
*/
public
void
print
()
{
out
.
flush
();
}
/**
* Prints an object to this output stream and flushes this output stream.
*
*
@param
x the object to print
*/
public
void
print
(
Object
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a boolean to this output stream and flushes this output stream.
*
*
@param
x the boolean to print
*/
public
void
print
(
boolean
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a character to this output stream and flushes this output stream.
*
*
@param
x the character to print
*/
public
void
print
(
char
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a double to this output stream and flushes this output stream.
*
*
@param
x the double to print
*/
public
void
print
(
double
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a float to this output stream and flushes this output stream.
*
*
@param
x the float to print
*/
public
void
print
(
float
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints an integer to this output stream and flushes this output stream.
*
*
@param
x the integer to print
*/
public
void
print
(
int
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a long integer to this output stream and flushes this output stream.
*
*
@param
x the long integer to print
*/
public
void
print
(
long
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a byte to this output stream and flushes this output stream.
*
*
@param
x the byte to print
*/
public
void
print
(
byte
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a formatted string to this output stream, using the specified format
* string and arguments, and then flushes this output stream.
*
*
@param
format the format string
*
@param
args the arguments accompanying the format string
*/
public
void
printf
(
String
format
,
Object
…
args
)
{
out
.
printf
(
LOCALE
,
format
,
args
);
out
.
flush
();
}
/**
* Prints a formatted string to this output stream, using the specified
* locale, format string, and arguments, and then flushes this output stream.
*
*
@param
locale the locale
*
@param
format the format string
*
@param
args the arguments accompanying the format string
*/
public
void
printf
(
Locale
locale
,
String
format
,
Object
…
args
)
{
out
.
printf
(
locale
,
format
,
args
);
out
.
flush
();
}
/**
* A test client.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
Out
out
;
// write to stdout
out
=
new
Out
();
out
.
println
(
“Test 1”
);
out
.
close
();
// write to a file
out
=
new
Out
(
“test.txt”
);
out
.
println
(
“Test 2”
);
out
.
close
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Particle.java
edu/princeton/cs/algs4/Particle.java
/******************************************************************************
* Compilation: javac Particle.java
* Execution: none
* Dependencies: StdDraw.java
*
* A particle moving in the unit box with a given position, velocity,
* radius, and mass.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
awt
.
Color
;
/**
* The {
@code
Particle} class represents a particle moving in the unit box,
* with a given position, velocity, radius, and mass. Methods are provided
* for moving the particle and for predicting and resolvling elastic
* collisions with vertical walls, horizontal walls, and other particles.
* This data type is mutable because the position and velocity change.
*
* For additional documentation,
* see Section 6.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Particle
{
private
static
final
double
INFINITY
=
Double
.
POSITIVE_INFINITY
;
private
double
rx
,
ry
;
// position
private
double
vx
,
vy
;
// velocity
private
int
count
;
// number of collisions so far
private
final
double
radius
;
// radius
private
final
double
mass
;
// mass
private
final
Color
color
;
// color
/**
* Initializes a particle with the specified position, velocity, radius, mass, and color.
*
*
@param
rx x-coordinate of position
*
@param
ry y-coordinate of position
*
@param
vx x-coordinate of velocity
*
@param
vy y-coordinate of velocity
*
@param
radius the radius
*
@param
mass the mass
*
@param
color the color
*/
public
Particle
(
double
rx
,
double
ry
,
double
vx
,
double
vy
,
double
radius
,
double
mass
,
Color
color
)
{
this
.
vx
=
vx
;
this
.
vy
=
vy
;
this
.
rx
=
rx
;
this
.
ry
=
ry
;
this
.
radius
=
radius
;
this
.
mass
=
mass
;
this
.
color
=
color
;
}
/**
* Initializes a particle with a random position and velocity.
* The position is uniform in the unit box; the velocity in
* either direciton is chosen uniformly at random.
*/
public
Particle
()
{
rx
=
StdRandom
.
uniform
(
0.0
,
1.0
);
ry
=
StdRandom
.
uniform
(
0.0
,
1.0
);
vx
=
StdRandom
.
uniform
(
–
0.005
,
0.005
);
vy
=
StdRandom
.
uniform
(
–
0.005
,
0.005
);
radius
=
0.02
;
mass
=
0.5
;
color
=
Color
.
BLACK
;
}
/**
* Moves this particle in a straight line (based on its velocity)
* for the specified amount of time.
*
*
@param
dt the amount of time
*/
public
void
move
(
double
dt
)
{
rx
+=
vx
*
dt
;
ry
+=
vy
*
dt
;
}
/**
* Draws this particle to standard draw.
*/
public
void
draw
()
{
StdDraw
.
setPenColor
(
color
);
StdDraw
.
filledCircle
(
rx
,
ry
,
radius
);
}
/**
* Returns the number of collisions involving this particle with
* vertical walls, horizontal walls, or other particles.
* This is equal to the number of calls to {
@link
#bounceOff},
* {
@link
#bounceOffVerticalWall}, and
* {
@link
#bounceOffHorizontalWall}.
*
*
@return
the number of collisions involving this particle with
* vertical walls, horizontal walls, or other particles
*/
public
int
count
()
{
return
count
;
}
/**
* Returns the amount of time for this particle to collide with the specified
* particle, assuming no interening collisions.
*
*
@param
that the other particle
*
@return
the amount of time for this particle to collide with the specified
* particle, assuming no interening collisions;
* {
@code
Double.POSITIVE_INFINITY} if the particles will not collide
*/
public
double
timeToHit
(
Particle
that
)
{
if
(
this
==
that
)
return
INFINITY
;
double
dx
=
that
.
rx
–
this
.
rx
;
double
dy
=
that
.
ry
–
this
.
ry
;
double
dvx
=
that
.
vx
–
this
.
vx
;
double
dvy
=
that
.
vy
–
this
.
vy
;
double
dvdr
=
dx
*
dvx
+
dy
*
dvy
;
if
(
dvdr
>
0
)
return
INFINITY
;
double
dvdv
=
dvx
*
dvx
+
dvy
*
dvy
;
if
(
dvdv
==
0
)
return
INFINITY
;
double
drdr
=
dx
*
dx
+
dy
*
dy
;
double
sigma
=
this
.
radius
+
that
.
radius
;
double
d
=
(
dvdr
*
dvdr
)
–
dvdv
*
(
drdr
–
sigma
*
sigma
);
// if (drdr < sigma*sigma) StdOut.println("overlapping particles");
if
(
d
<
0
)
return
INFINITY
;
return
-
(
dvdr
+
Math
.
sqrt
(
d
))
/
dvdv
;
}
/**
* Returns the amount of time for this particle to collide with a vertical
* wall, assuming no interening collisions.
*
*
@return
the amount of time for this particle to collide with a vertical wall,
* assuming no interening collisions;
* {
@code
Double.POSITIVE_INFINITY} if the particle will not collide
* with a vertical wall
*/
public
double
timeToHitVerticalWall
()
{
if
(
vx
>
0
)
return
(
1.0
–
rx
–
radius
)
/
vx
;
else
if
(
vx
<
0
)
return
(
radius
-
rx
)
/
vx
;
else
return
INFINITY
;
}
/**
* Returns the amount of time for this particle to collide with a horizontal
* wall, assuming no interening collisions.
*
*
@return
the amount of time for this particle to collide with a horizontal wall,
* assuming no interening collisions;
* {
@code
Double.POSITIVE_INFINITY} if the particle will not collide
* with a horizontal wall
*/
public
double
timeToHitHorizontalWall
()
{
if
(
vy
>
0
)
return
(
1.0
–
ry
–
radius
)
/
vy
;
else
if
(
vy
<
0
)
return
(
radius
-
ry
)
/
vy
;
else
return
INFINITY
;
}
/**
* Updates the velocities of this particle and the specified particle according
* to the laws of elastic collision. Assumes that the particles are colliding
* at this instant.
*
*
@param
that the other particle
*/
public
void
bounceOff
(
Particle
that
)
{
double
dx
=
that
.
rx
-
this
.
rx
;
double
dy
=
that
.
ry
-
this
.
ry
;
double
dvx
=
that
.
vx
-
this
.
vx
;
double
dvy
=
that
.
vy
-
this
.
vy
;
double
dvdr
=
dx
*
dvx
+
dy
*
dvy
;
// dv dot dr
double
dist
=
this
.
radius
+
that
.
radius
;
// distance between particle centers at collison
// magnitude of normal force
double
magnitude
=
2
*
this
.
mass
*
that
.
mass
*
dvdr
/
((
this
.
mass
+
that
.
mass
)
*
dist
);
// normal force, and in x and y directions
double
fx
=
magnitude
*
dx
/
dist
;
double
fy
=
magnitude
*
dy
/
dist
;
// update velocities according to normal force
this
.
vx
+=
fx
/
this
.
mass
;
this
.
vy
+=
fy
/
this
.
mass
;
that
.
vx
-=
fx
/
that
.
mass
;
that
.
vy
-=
fy
/
that
.
mass
;
// update collision counts
this
.
count
++
;
that
.
count
++
;
}
/**
* Updates the velocity of this particle upon collision with a vertical
* wall (by reflecting the velocity in the x-direction).
* Assumes that the particle is colliding with a vertical wall at this instant.
*/
public
void
bounceOffVerticalWall
()
{
vx
=
–
vx
;
count
++
;
}
/**
* Updates the velocity of this particle upon collision with a horizontal
* wall (by reflecting the velocity in the y-direction).
* Assumes that the particle is colliding with a horizontal wall at this instant.
*/
public
void
bounceOffHorizontalWall
()
{
vy
=
–
vy
;
count
++
;
}
/**
* Returns the kinetic energy of this particle.
* The kinetic energy is given by the formula 1/2 m v2,
* where m is the mass of this particle and v is its velocity.
*
*
@return
the kinetic energy of this particle
*/
public
double
kineticEnergy
()
{
return
0.5
*
mass
*
(
vx
*
vx
+
vy
*
vy
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/PatriciaSET.java
edu/princeton/cs/algs4/PatriciaSET.java
/******************************************************************************
* Compilation: javac PatriciaSET.java
* Execution: java PatriciaSET
* Dependencies: StdOut.java StdRandom.java Queue.java
* Data files: n/a
*
* A set implementation based on PATRICIA.
*
* % java PatriciaSET 1000000 1
* Creating dataset (1000000 items)…
* Shuffling…
* Adding (1000000 items)…
* Iterating…
* 1000000 items iterated
* Shuffling…
* Deleting (500000 items)…
* Iterating…
* 500000 items iterated
* Checking…
* 500000 items found and 500000 (deleted) items missing
* Deleting the rest (500000 items)…
* PASS 1 TESTS SUCCEEDED
* %
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Iterator
;
/**
* The {
@code
PatriciaSET} class provides an implementation of an
* unordered set, with the restriction that the items (keys) are of class
* {
@link
java.lang.String}. It supports the usual add,
* contains, delete, size, and is-empty
* methods. It also provides an iterator method for iterating over all
* the elements in the set.
*
* This unordered set class implements PATRICIA (Practical Algorithm to
* Retrieve Information Coded In Alphanumeric). In spite of the acronym, string
* keys are not limited to alphanumeric content. A key may possess any string
* value, with one exception: a zero-length string is not permitted.
*
* Unlike other generic set implementations that can accept a parameterized key
* type, this set class can only accommodate keys of class
* {
@link
java.lang.String}. This unfortunate restriction stems from a
* limitation in Java. Although Java provides excellent support for generic
* programming, the current infrastructure somewhat limits generic collection
* implementations to those that employ comparison-based or hash-based methods.
* PATRICIA does not employ comparisons or hashing; instead, it relies on
* bit-test operations. Because Java does not furnish any generic abstractions
* (or implementations) for bit-testing the contents of an object, providing
* support for generic keys using PATRICIA does not seem practical.
*
* PATRICIA is a variation of a trie, and it is often classified as a
* space-optimized trie. In a classical trie, each level represents a
* subsequent digit in a key. In PATRICIA, nodes only exist to identify the
* digits (bits) that distinguish the individual keys within the trie. Because
* PATRICIA uses a radix of two, each node has only two children, like a binary
* tree. Also like a binary tree, the number of nodes, within the trie, equals
* the number of keys. Consequently, some classify PATRICIA as a tree.
*
* The analysis of PATRICIA is complicated. The theoretical wost-case
* performance for an add, contains, or delete
* operation is O(N), when N is less than
* W (where W is the length in bits of the
* longest key), and O(W), when N is greater
* than W. However, the worst case is unlikely to occur with
* typical use. The average (and usual) performance of PATRICIA is
* approximately ~lg N for each add,
* contains, or delete operation. Although this appears to
* put PATRICIA on the same footing as binary trees, this time complexity
* represents the number of single-bit test operations (under PATRICIA), and
* not full-key comparisons (as required by binary trees). After the single-bit
* tests conclude, PATRICIA requires just one full-key comparison to confirm
* the existence (or absence) of the key (per add, contains,
* or delete operation).
*
* In practice, decent implementations of PATRICIA can often outperform
* balanced binary trees, and even hash tables. Although this particular
* implementation performs well, the source code was written with an emphasis
* on clarity, and not performance. PATRICIA performs admirably when its
* bit-testing loops are well tuned. Consider using the source code as a guide,
* should you need to produce an optimized implementation, for anther key type,
* or in another programming language.
*
* Other resources for PATRICIA:
* Sedgewick, R. (1990) Algorithms in C, Addison-Wesley
* Knuth, D. (1973) The Art of Computer Programming, Addison-Wesley
*
*
@author
John Hentosh (based on an implementation by Robert Sedgewick)
*/
public
class
PatriciaSET
implements
Iterable
<
String
>
{
private
Node
head
;
private
int
count
;
/* An inner Node class specifies the objects that hold each key. The b
* value indicates the relevant bit position.
*/
private
class
Node
{
private
Node
left
,
right
;
private
String
key
;
private
int
b
;
public
Node
(
String
key
,
int
b
)
{
this
.
key
=
key
;
this
.
b
=
b
;
}
};
/**
* Initializes an empty PATRICIA-based set.
*/
/* The constructor creates a head (sentinel) node that contains a
* zero-length string.
*/
public
PatriciaSET
()
{
head
=
new
Node
(
“”
,
0
);
head
.
left
=
head
;
head
.
right
=
head
;
count
=
0
;
}
/**
* Adds the key to the set if it is not already present.
*
@param
key the key to add
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*
@throws
IllegalArgumentException if {
@code
key} is the empty string.
*/
public
void
add
(
String
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“called add(null)”
);
if
(
key
.
length
()
==
0
)
throw
new
IllegalArgumentException
(
“invalid key”
);
Node
p
;
Node
x
=
head
;
do
{
p
=
x
;
if
(
safeBitTest
(
key
,
x
.
b
))
x
=
x
.
right
;
else
x
=
x
.
left
;
}
while
(
p
.
b
<
x
.
b
);
if
(
!
x
.
key
.
equals
(
key
))
{
int
b
=
firstDifferingBit
(
x
.
key
,
key
);
x
=
head
;
do
{
p
=
x
;
if
(
safeBitTest
(
key
,
x
.
b
))
x
=
x
.
right
;
else
x
=
x
.
left
;
}
while
(
p
.
b
<
x
.
b
&&
x
.
b
<
b
);
Node
t
=
new
Node
(
key
,
b
);
if
(
safeBitTest
(
key
,
b
))
{
t
.
left
=
x
;
t
.
right
=
t
;
}
else
{
t
.
left
=
t
;
t
.
right
=
x
;
}
if
(
safeBitTest
(
key
,
p
.
b
))
p
.
right
=
t
;
else
p
.
left
=
t
;
count
++
;
}
}
/**
* Does the set contain the given key?
*
@param
key the key
*
@return
{
@code
true} if the set contains {
@code
key} and
* {
@code
false} otherwise
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*
@throws
IllegalArgumentException if {
@code
key} is the empty string.
*/
public
boolean
contains
(
String
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
"called contains(null)"
);
if
(
key
.
length
()
==
0
)
throw
new
IllegalArgumentException
(
"invalid key"
);
Node
p
;
Node
x
=
head
;
do
{
p
=
x
;
if
(
safeBitTest
(
key
,
x
.
b
))
x
=
x
.
right
;
else
x
=
x
.
left
;
}
while
(
p
.
b
<
x
.
b
);
return
x
.
key
.
equals
(
key
);
}
/**
* Removes the key from the set if the key is present.
*
@param
key the key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*
@throws
IllegalArgumentException if {
@code
key} is the empty string.
*/
public
void
delete
(
String
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
"called delete(null)"
);
if
(
key
.
length
()
==
0
)
throw
new
IllegalArgumentException
(
"invalid key"
);
Node
g
;
// previous previous (grandparent)
Node
p
=
head
;
// previous (parent)
Node
x
=
head
;
// node to delete
do
{
g
=
p
;
p
=
x
;
if
(
safeBitTest
(
key
,
x
.
b
))
x
=
x
.
right
;
else
x
=
x
.
left
;
}
while
(
p
.
b
<
x
.
b
);
if
(
x
.
key
.
equals
(
key
))
{
Node
z
;
Node
y
=
head
;
do
{
// find the true parent (z) of x
z
=
y
;
if
(
safeBitTest
(
key
,
y
.
b
))
y
=
y
.
right
;
else
y
=
y
.
left
;
}
while
(
y
!=
x
);
if
(
x
==
p
)
{
// case 1: remove (leaf node) x
Node
c
;
// child of x
if
(
safeBitTest
(
key
,
x
.
b
))
c
=
x
.
left
;
else
c
=
x
.
right
;
if
(
safeBitTest
(
key
,
z
.
b
))
z
.
right
=
c
;
else
z
.
left
=
c
;
}
else
{
// case 2: p replaces (internal node) x
Node
c
;
// child of p
if
(
safeBitTest
(
key
,
p
.
b
))
c
=
p
.
left
;
else
c
=
p
.
right
;
if
(
safeBitTest
(
key
,
g
.
b
))
g
.
right
=
c
;
else
g
.
left
=
c
;
if
(
safeBitTest
(
key
,
z
.
b
))
z
.
right
=
p
;
else
z
.
left
=
p
;
p
.
left
=
x
.
left
;
p
.
right
=
x
.
right
;
p
.
b
=
x
.
b
;
}
count
--
;
}
}
/**
* Is the set empty?
*
@return
{
@code
true} if the set is empty, and {
@code
false}
* otherwise
*/
boolean
isEmpty
()
{
return
count
==
0
;
}
/**
* Returns the number of keys in the set.
*
@return
the number of keys in the set
*/
int
size
()
{
return
count
;
}
/**
* Returns all of the keys in the set, as an iterator.
* To iterate over all of the keys in a set named {
@code
set}, use the
* foreach notation: {
@code
for (Key key : set)}.
*
@return
an iterator to all of the keys in the set
*/
public
Iterator
<
String
>
iterator
()
{
Queue
<
String
>
queue
=
new
Queue
<
String
>
();
if
(
head
.
left
!=
head
)
collect
(
head
.
left
,
0
,
queue
);
if
(
head
.
right
!=
head
)
collect
(
head
.
right
,
0
,
queue
);
return
queue
.
iterator
();
}
private
void
collect
(
Node
x
,
int
b
,
Queue
<
String
>
queue
)
{
if
(
x
.
b
>
b
)
{
collect
(
x
.
left
,
x
.
b
,
queue
);
queue
.
enqueue
(
x
.
key
);
collect
(
x
.
right
,
x
.
b
,
queue
);
}
}
/**
* Returns a string representation of this set.
*
@return
a string representation of this set, with the keys separated
* by single spaces
*/
public
String
toString
()
{
StringBuilder
s
=
new
StringBuilder
();
for
(
String
key
:
this
)
s
.
append
(
key
+
” ”
);
if
(
s
.
length
()
>
0
)
s
.
deleteCharAt
(
s
.
length
()
–
1
);
return
s
.
toString
();
}
/* The safeBitTest function logically appends a terminating sequence (when
* required) to extend (logically) the string beyond its length.
*
* The inner loops of the get and put methods flow much better when they
* are not concerned with the lengths of strings, so a trick is employed to
* allow the get and put methods to view every string as an “infinite”
* sequence of bits. Logically, every string gets a ‘\uffff’ character,
* followed by an “infinite” sequence of ‘\u0000’ characters, appended to
* the end.
*
* Note that the ‘\uffff’ character serves to mark the end of the string,
* and it is necessary. Simply padding with ‘\u0000’ is insufficient to
* make all unique Unicode strings “look” unique to the get and put methods
* (because these methods do not regard string lengths).
*/
private
static
boolean
safeBitTest
(
String
key
,
int
b
)
{
if
(
b
<
key
.
length
()
*
16
)
return
bitTest
(
key
,
b
)
!=
0
;
if
(
b
>
key
.
length
()
*
16
+
15
)
return
false
;
// padding
/* 16 bits of 0xffff */
return
true
;
// end marker
}
private
static
int
bitTest
(
String
key
,
int
b
)
{
return
(
key
.
charAt
(
b
>>>
4
)
>>>
(
b
&
0xf
))
&
1
;
}
/* Like the safeBitTest function, the safeCharAt function makes every
* string look like an “infinite” sequence of characters. Logically, every
* string gets a ‘\uffff’ character, followed by an “infinite” sequence of
* ‘\u0000’ characters, appended to the end.
*/
private
static
int
safeCharAt
(
String
key
,
int
i
)
{
if
(
i
<
key
.
length
())
return
key
.
charAt
(
i
);
if
(
i
>
key
.
length
())
return
0x0000
;
// padding
else
return
0xffff
;
// end marker
}
/* For efficiency’s sake, the firstDifferingBit function compares entire
* characters first, and then considers the individual bits (once it finds
* two characters that do not match). Also, the least significant bits of
* an individual character are examined first. There are many Unicode
* alphabets where most (if not all) of the “action” occurs in the least
* significant bits.
*
* Notice that the very first character comparison excludes the
* least-significant bit. The firstDifferingBit function must never return
* zero; otherwise, a node would become created as a child to the head
* (sentinel) node that matches the bit-index value (zero) stored in the
* head node. This would violate the invariant that bit-index values
* increase as you descend into the trie.
*/
private
static
int
firstDifferingBit
(
String
k1
,
String
k2
)
{
int
i
=
0
;
int
c1
=
safeCharAt
(
k1
,
0
)
&
~
1
;
int
c2
=
safeCharAt
(
k2
,
0
)
&
~
1
;
if
(
c1
==
c2
)
{
i
=
1
;
while
(
safeCharAt
(
k1
,
i
)
==
safeCharAt
(
k2
,
i
))
i
++
;
c1
=
safeCharAt
(
k1
,
i
);
c2
=
safeCharAt
(
k2
,
i
);
}
int
b
=
0
;
while
(((
c1
>>>
b
)
&
1
)
==
((
c2
>>>
b
)
&
1
))
b
++
;
return
i
*
16
+
b
;
}
/**
* Unit tests the {
@code
PatriciaSET} data type.
* This test fixture runs a series of tests on a randomly generated dataset.
* You may specify up to two integer parameters on the command line. The
* first parameter indicates the size of the dataset. The second parameter
* controls the number of passes (a new random dataset becomes generated at
* the start of each pass).
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
PatriciaSET
set
=
new
PatriciaSET
();
int
limitItem
=
1000000
;
int
limitPass
=
1
;
int
countPass
=
0
;
boolean
ok
=
true
;
if
(
args
.
length
>
0
)
limitItem
=
Integer
.
parseInt
(
args
[
0
]);
if
(
args
.
length
>
1
)
limitPass
=
Integer
.
parseInt
(
args
[
1
]);
do
{
String
[]
a
=
new
String
[
limitItem
];
StdOut
.
printf
(
“Creating dataset (%d items)…\n”
,
limitItem
);
for
(
int
i
=
0
;
i
<
limitItem
;
i
++
)
a
[
i
]
=
Integer
.
toString
(
i
,
16
);
StdOut
.
printf
(
"Shuffling...\n"
);
StdRandom
.
shuffle
(
a
);
StdOut
.
printf
(
"Adding (%d items)...\n"
,
limitItem
);
for
(
int
i
=
0
;
i
<
limitItem
;
i
++
)
set
.
add
(
a
[
i
]);
int
countItems
=
0
;
StdOut
.
printf
(
"Iterating...\n"
);
for
(
String
key
:
set
)
countItems
++
;
StdOut
.
printf
(
"%d items iterated\n"
,
countItems
);
if
(
countItems
!=
limitItem
)
ok
=
false
;
if
(
countItems
!=
set
.
size
())
ok
=
false
;
StdOut
.
printf
(
"Shuffling...\n"
);
StdRandom
.
shuffle
(
a
);
int
limitDelete
=
limitItem
/
2
;
StdOut
.
printf
(
"Deleting (%d items)...\n"
,
limitDelete
);
for
(
int
i
=
0
;
i
<
limitDelete
;
i
++
)
set
.
delete
(
a
[
i
]);
countItems
=
0
;
StdOut
.
printf
(
"Iterating...\n"
);
for
(
String
key
:
set
)
countItems
++
;
StdOut
.
printf
(
"%d items iterated\n"
,
countItems
);
if
(
countItems
!=
limitItem
-
limitDelete
)
ok
=
false
;
if
(
countItems
!=
set
.
size
())
ok
=
false
;
int
countDelete
=
0
;
int
countRemain
=
0
;
StdOut
.
printf
(
"Checking...\n"
);
for
(
int
i
=
0
;
i
<
limitItem
;
i
++
)
{
if
(
i
<
limitDelete
)
{
if
(
!
set
.
contains
(
a
[
i
]))
countDelete
++
;
}
else
{
if
(
set
.
contains
(
a
[
i
]))
countRemain
++
;
}
}
StdOut
.
printf
(
"%d items found and %d (deleted) items missing\n"
,
countRemain
,
countDelete
);
if
(
countRemain
+
countDelete
!=
limitItem
)
ok
=
false
;
if
(
countRemain
!=
set
.
size
())
ok
=
false
;
if
(
set
.
isEmpty
())
ok
=
false
;
StdOut
.
printf
(
"Deleting the rest (%d items)...\n"
,
limitItem
-
countDelete
);
for
(
int
i
=
countDelete
;
i
<
limitItem
;
i
++
)
set
.
delete
(
a
[
i
]);
if
(
!
set
.
isEmpty
())
ok
=
false
;
countPass
++
;
if
(
ok
)
StdOut
.
printf
(
"PASS %d TESTS SUCCEEDED\n"
,
countPass
);
else
StdOut
.
printf
(
"PASS %d TESTS FAILED\n"
,
countPass
);
}
while
(
ok
&&
countPass
<
limitPass
);
if
(
!
ok
)
throw
new
java
.
lang
.
RuntimeException
(
"TESTS FAILED"
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/PatriciaST.java
edu/princeton/cs/algs4/PatriciaST.java
/******************************************************************************
* Compilation: javac PatriciaST.java
* Execution: java PatriciaST
* Dependencies: StdOut.java StdRandom.java Queue.java
* Data files: n/a
*
* A symbol table implementation based on PATRICIA.
*
* % java PatriciaST 1000000 1
* Creating dataset (1000000 items)...
* Shuffling...
* Adding (1000000 items)...
* Iterating...
* 1000000 items iterated
* Shuffling...
* Deleting (500000 items)...
* Iterating...
* 500000 items iterated
* Checking...
* 500000 items found and 500000 (deleted) items missing
* Deleting the rest (500000 items)...
* PASS 1 TESTS SUCCEEDED
* %
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
PatriciaST} class provides an implementation of an unordered
* symbol table of key-value pairs, with the restriction that the key is of
* class {
@link
java.lang.String}. It supports the usual put,
* get, contains, delete, size, and
* is-empty methods. It also provides a keys method for
* iterating over all of the keys. A symbol table implements the
* associative array abstraction: when associating a value with a key
* that is already in the symbol table, the convention is to replace the old
* value with the new value. Unlike {
@link
java.util.Map}, this class uses the
* convention that values cannot be {
@code
null}—setting the value
* associated with a key to {
@code
null} is equivalent to deleting the key
* from the symbol table.
*
* This unordered symbol table class implements PATRICIA (Practical Algorithm
* to Retrieve Information Coded In Alphanumeric). In spite of the acronym,
* string keys are not limited to alphanumeric content. A key may possess any
* string value, except for the string of zero length (the empty string).
*
* Unlike other generic symbol table implementations that can accept a
* parameterized key type, this symbol table class can only accommodate keys
* of class {
@link
java.lang.String}. This unfortunate restriction stems from a
* limitation in Java. Although Java provides excellent support for generic
* programming, the current infrastructure somewhat limits generic collection
* implementations to those that employ comparison-based or hash-based methods.
* PATRICIA does not employ comparisons or hashing; instead, it relies on
* bit-test operations. Because Java does not furnish any generic abstractions
* (or implementations) for bit-testing the contents of an object, providing
* support for generic keys using PATRICIA does not seem practical.
*
* PATRICIA is a variation of a trie, and it is often classified as a
* space-optimized trie. In a classical trie, each level represents a
* subsequent digit in a key. In PATRICIA, nodes only exist to identify the
* digits (bits) that distinguish the individual keys within the trie. Because
* PATRICIA uses a radix of two, each node has only two children, like a binary
* tree. Also like a binary tree, the number of nodes, within the trie, equals
* the number of keys. Consequently, some classify PATRICIA as a tree.
*
* The analysis of PATRICIA is complicated. The theoretical wost-case
* performance for a get, put, or delete operation
* is O(N), when N is less than
* W (where W is the length in bits of the
* longest key), and O(W), when N is greater
* than W. However, the worst case is unlikely to occur with
* typical use. The average (and usual) performance of PATRICIA is
* approximately ~lg N for each get, put, or
* delete operation. Although this appears to put PATRICIA on the same
* footing as binary trees, this time complexity represents the number of
* single-bit test operations (under PATRICIA), and not full-key comparisons
* (as required by binary trees). After the single-bit tests conclude, PATRICIA
* requires just one full-key comparison to confirm the existence (or absence)
* of the key (per get, put, or delete operation).
*
* In practice, decent implementations of PATRICIA can often outperform
* balanced binary trees, and even hash tables. Although this particular
* implementation performs well, the source code was written with an emphasis
* on clarity, and not performance. PATRICIA performs admirably when its
* bit-testing loops are well tuned. Consider using the source code as a guide,
* should you need to produce an optimized implementation, for anther key type,
* or in another programming language.
*
* Other resources for PATRICIA:
* Sedgewick, R. (1990) Algorithms in C, Addison-Wesley
* Knuth, D. (1973) The Art of Computer Programming, Addison-Wesley
*
*
@author
John Hentosh (based on an implementation by Robert Sedgewick)
*/
public
class
PatriciaST
<
Value
>
{
private
Node
head
;
private
int
count
;
/* An inner Node class specifies the objects that hold each key-value pair.
* The b value indicates the relevant bit position.
*/
private
class
Node
{
private
Node
left
,
right
;
private
String
key
;
private
Value
val
;
private
int
b
;
public
Node
(
String
key
,
Value
val
,
int
b
)
{
this
.
key
=
key
;
this
.
val
=
val
;
this
.
b
=
b
;
}
};
/**
* Initializes an empty PATRICIA-based symbol table.
*/
/* The constructor creates a head (sentinel) node that contains a
* zero-length string.
*/
public
PatriciaST
()
{
head
=
new
Node
(
“”
,
null
,
0
);
head
.
left
=
head
;
head
.
right
=
head
;
count
=
0
;
}
/**
* Places a key-value pair into the symbol table. If the table already
* contains the specified key, then its associated value becomes updated.
* If the value provided is {
@code
null}, then the key becomes removed
* from the symbol table.
*
@param
key the key
*
@param
val the value
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*
@throws
IllegalArgumentException if {
@code
key} is the empty string.
*/
public
void
put
(
String
key
,
Value
val
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“called put(null)”
);
if
(
key
.
length
()
==
0
)
throw
new
IllegalArgumentException
(
“invalid key”
);
if
(
val
==
null
)
delete
(
key
);
Node
p
;
Node
x
=
head
;
do
{
p
=
x
;
if
(
safeBitTest
(
key
,
x
.
b
))
x
=
x
.
right
;
else
x
=
x
.
left
;
}
while
(
p
.
b
<
x
.
b
);
if
(
!
x
.
key
.
equals
(
key
))
{
int
b
=
firstDifferingBit
(
x
.
key
,
key
);
x
=
head
;
do
{
p
=
x
;
if
(
safeBitTest
(
key
,
x
.
b
))
x
=
x
.
right
;
else
x
=
x
.
left
;
}
while
(
p
.
b
<
x
.
b
&&
x
.
b
<
b
);
Node
t
=
new
Node
(
key
,
val
,
b
);
if
(
safeBitTest
(
key
,
b
))
{
t
.
left
=
x
;
t
.
right
=
t
;
}
else
{
t
.
left
=
t
;
t
.
right
=
x
;
}
if
(
safeBitTest
(
key
,
p
.
b
))
p
.
right
=
t
;
else
p
.
left
=
t
;
count
++
;
}
else
x
.
val
=
val
;
}
/**
* Retrieves the value associated with the given key.
*
@param
key the key
*
@return
the value associated with the given key if the key is in the
* symbol table and {
@code
null} if the key is not in the symbol table
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*
@throws
IllegalArgumentException if {
@code
key} is the empty string.
*/
public
Value
get
(
String
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
"called get(null)"
);
if
(
key
.
length
()
==
0
)
throw
new
IllegalArgumentException
(
"invalid key"
);
Node
p
;
Node
x
=
head
;
do
{
p
=
x
;
if
(
safeBitTest
(
key
,
x
.
b
))
x
=
x
.
right
;
else
x
=
x
.
left
;
}
while
(
p
.
b
<
x
.
b
);
if
(
x
.
key
.
equals
(
key
))
return
x
.
val
;
else
return
null
;
}
/**
* Removes a key and its associated value from the symbol table, if it
* exists.
*
@param
key the key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*
@throws
IllegalArgumentException if {
@code
key} is the empty string.
*/
public
void
delete
(
String
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
"called delete(null)"
);
if
(
key
.
length
()
==
0
)
throw
new
IllegalArgumentException
(
"invalid key"
);
Node
g
;
// previous previous (grandparent)
Node
p
=
head
;
// previous (parent)
Node
x
=
head
;
// node to delete
do
{
g
=
p
;
p
=
x
;
if
(
safeBitTest
(
key
,
x
.
b
))
x
=
x
.
right
;
else
x
=
x
.
left
;
}
while
(
p
.
b
<
x
.
b
);
if
(
x
.
key
.
equals
(
key
))
{
Node
z
;
Node
y
=
head
;
do
{
// find the true parent (z) of x
z
=
y
;
if
(
safeBitTest
(
key
,
y
.
b
))
y
=
y
.
right
;
else
y
=
y
.
left
;
}
while
(
y
!=
x
);
if
(
x
==
p
)
{
// case 1: remove (leaf node) x
Node
c
;
// child of x
if
(
safeBitTest
(
key
,
x
.
b
))
c
=
x
.
left
;
else
c
=
x
.
right
;
if
(
safeBitTest
(
key
,
z
.
b
))
z
.
right
=
c
;
else
z
.
left
=
c
;
}
else
{
// case 2: p replaces (internal node) x
Node
c
;
// child of p
if
(
safeBitTest
(
key
,
p
.
b
))
c
=
p
.
left
;
else
c
=
p
.
right
;
if
(
safeBitTest
(
key
,
g
.
b
))
g
.
right
=
c
;
else
g
.
left
=
c
;
if
(
safeBitTest
(
key
,
z
.
b
))
z
.
right
=
p
;
else
z
.
left
=
p
;
p
.
left
=
x
.
left
;
p
.
right
=
x
.
right
;
p
.
b
=
x
.
b
;
}
count
--
;
}
}
/**
* Returns {
@code
true} if the key-value pair, specified by the given
* key, exists within the symbol table.
*
@param
key the key
*
@return
{
@code
true} if this symbol table contains the given
* {
@code
key} and {
@code
false} otherwise
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*
@throws
IllegalArgumentException if {
@code
key} is the empty string.
*/
public
boolean
contains
(
String
key
)
{
return
get
(
key
)
!=
null
;
}
/**
* Returns {
@code
true} if the symbol table is empty.
*
@return
{
@code
true} if this symbol table is empty and
* {
@code
false} otherwise
*/
boolean
isEmpty
()
{
return
count
==
0
;
}
/**
* Returns the number of key-value pairs within the symbol table.
*
@return
the number of key-value pairs within this symbol table
*/
int
size
()
{
return
count
;
}
/**
* Returns all keys in the symbol table as an {
@code
Iterable}.
* To iterate over all of the keys in the symbol table named
* {
@code
st}, use the foreach notation:
* {
@code
for (Key key : st.keys())}.
*
@return
all keys in the symbol table as an {
@code
Iterable}
*/
public
Iterable
<
String
>
keys
()
{
Queue
<
String
>
queue
=
new
Queue
<
String
>
();
if
(
head
.
left
!=
head
)
keys
(
head
.
left
,
0
,
queue
);
if
(
head
.
right
!=
head
)
keys
(
head
.
right
,
0
,
queue
);
return
queue
;
}
private
void
keys
(
Node
x
,
int
b
,
Queue
<
String
>
queue
)
{
if
(
x
.
b
>
b
)
{
keys
(
x
.
left
,
x
.
b
,
queue
);
queue
.
enqueue
(
x
.
key
);
keys
(
x
.
right
,
x
.
b
,
queue
);
}
}
/* The safeBitTest function logically appends a terminating sequence (when
* required) to extend (logically) the string beyond its length.
*
* The inner loops of the get and put methods flow much better when they
* are not concerned with the lengths of strings, so a trick is employed to
* allow the get and put methods to view every string as an “infinite”
* sequence of bits. Logically, every string gets a ‘\uffff’ character,
* followed by an “infinite” sequence of ‘\u0000’ characters, appended to
* the end.
*
* Note that the ‘\uffff’ character serves to mark the end of the string,
* and it is necessary. Simply padding with ‘\u0000’ is insufficient to
* make all unique Unicode strings “look” unique to the get and put methods
* (because these methods do not regard string lengths).
*/
private
static
boolean
safeBitTest
(
String
key
,
int
b
)
{
if
(
b
<
key
.
length
()
*
16
)
return
bitTest
(
key
,
b
)
!=
0
;
if
(
b
>
key
.
length
()
*
16
+
15
)
return
false
;
// padding
/* 16 bits of 0xffff */
return
true
;
// end marker
}
private
static
int
bitTest
(
String
key
,
int
b
)
{
return
(
key
.
charAt
(
b
>>>
4
)
>>>
(
b
&
0xf
))
&
1
;
}
/* Like the safeBitTest function, the safeCharAt function makes every
* string look like an “infinite” sequence of characters. Logically, every
* string gets a ‘\uffff’ character, followed by an “infinite” sequence of
* ‘\u0000’ characters, appended to the end.
*/
private
static
int
safeCharAt
(
String
key
,
int
i
)
{
if
(
i
<
key
.
length
())
return
key
.
charAt
(
i
);
if
(
i
>
key
.
length
())
return
0x0000
;
// padding
else
return
0xffff
;
// end marker
}
/* For efficiency’s sake, the firstDifferingBit function compares entire
* characters first, and then considers the individual bits (once it finds
* two characters that do not match). Also, the least significant bits of
* an individual character are examined first. There are many Unicode
* alphabets where most (if not all) of the “action” occurs in the least
* significant bits.
*
* Notice that the very first character comparison excludes the
* least-significant bit. The firstDifferingBit function must never return
* zero; otherwise, a node would become created as a child to the head
* (sentinel) node that matches the bit-index value (zero) stored in the
* head node. This would violate the invariant that bit-index values
* increase as you descend into the trie.
*/
private
static
int
firstDifferingBit
(
String
k1
,
String
k2
)
{
int
i
=
0
;
int
c1
=
safeCharAt
(
k1
,
0
)
&
~
1
;
int
c2
=
safeCharAt
(
k2
,
0
)
&
~
1
;
if
(
c1
==
c2
)
{
i
=
1
;
while
(
safeCharAt
(
k1
,
i
)
==
safeCharAt
(
k2
,
i
))
i
++
;
c1
=
safeCharAt
(
k1
,
i
);
c2
=
safeCharAt
(
k2
,
i
);
}
int
b
=
0
;
while
(((
c1
>>>
b
)
&
1
)
==
((
c2
>>>
b
)
&
1
))
b
++
;
return
i
*
16
+
b
;
}
/**
* Unit tests the {
@code
PatriciaST} data type.
* This test fixture runs a series of tests on a randomly generated dataset.
* You may specify up to two integer parameters on the command line. The
* first parameter indicates the size of the dataset. The second parameter
* controls the number of passes (a new random dataset becomes generated at
* the start of each pass).
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
PatriciaST
<
Integer
>
st
=
new
PatriciaST
<
Integer
>
();
int
limitItem
=
1000000
;
int
limitPass
=
1
;
int
countPass
=
0
;
boolean
ok
=
true
;
if
(
args
.
length
>
0
)
limitItem
=
Integer
.
parseInt
(
args
[
0
]);
if
(
args
.
length
>
1
)
limitPass
=
Integer
.
parseInt
(
args
[
1
]);
do
{
String
[]
a
=
new
String
[
limitItem
];
int
[]
v
=
new
int
[
limitItem
];
StdOut
.
printf
(
“Creating dataset (%d items)…\n”
,
limitItem
);
for
(
int
i
=
0
;
i
<
limitItem
;
i
++
)
{
a
[
i
]
=
Integer
.
toString
(
i
,
16
);
v
[
i
]
=
i
;
}
StdOut
.
printf
(
"Shuffling...\n"
);
StdRandom
.
shuffle
(
v
);
StdOut
.
printf
(
"Adding (%d items)...\n"
,
limitItem
);
for
(
int
i
=
0
;
i
<
limitItem
;
i
++
)
st
.
put
(
a
[
v
[
i
]],
v
[
i
]);
int
countKeys
=
0
;
StdOut
.
printf
(
"Iterating...\n"
);
for
(
String
key
:
st
.
keys
())
countKeys
++
;
StdOut
.
printf
(
"%d items iterated\n"
,
countKeys
);
if
(
countKeys
!=
limitItem
)
ok
=
false
;
if
(
countKeys
!=
st
.
size
())
ok
=
false
;
StdOut
.
printf
(
"Shuffling...\n"
);
StdRandom
.
shuffle
(
v
);
int
limitDelete
=
limitItem
/
2
;
StdOut
.
printf
(
"Deleting (%d items)...\n"
,
limitDelete
);
for
(
int
i
=
0
;
i
<
limitDelete
;
i
++
)
st
.
delete
(
a
[
v
[
i
]]);
countKeys
=
0
;
StdOut
.
printf
(
"Iterating...\n"
);
for
(
String
key
:
st
.
keys
())
countKeys
++
;
StdOut
.
printf
(
"%d items iterated\n"
,
countKeys
);
if
(
countKeys
!=
limitItem
-
limitDelete
)
ok
=
false
;
if
(
countKeys
!=
st
.
size
())
ok
=
false
;
int
countDelete
=
0
;
int
countRemain
=
0
;
StdOut
.
printf
(
"Checking...\n"
);
for
(
int
i
=
0
;
i
<
limitItem
;
i
++
)
{
if
(
i
<
limitDelete
)
{
if
(
!
st
.
contains
(
a
[
v
[
i
]]))
countDelete
++
;
}
else
{
int
val
=
st
.
get
(
a
[
v
[
i
]]);
if
(
val
==
v
[
i
])
countRemain
++
;
}
}
StdOut
.
printf
(
"%d items found and %d (deleted) items missing\n"
,
countRemain
,
countDelete
);
if
(
countRemain
+
countDelete
!=
limitItem
)
ok
=
false
;
if
(
countRemain
!=
st
.
size
())
ok
=
false
;
if
(
st
.
isEmpty
())
ok
=
false
;
StdOut
.
printf
(
"Deleting the rest (%d items)...\n"
,
limitItem
-
countDelete
);
for
(
int
i
=
countDelete
;
i
<
limitItem
;
i
++
)
st
.
delete
(
a
[
v
[
i
]]);
if
(
!
st
.
isEmpty
())
ok
=
false
;
countPass
++
;
if
(
ok
)
StdOut
.
printf
(
"PASS %d TESTS SUCCEEDED\n"
,
countPass
);
else
StdOut
.
printf
(
"PASS %d TESTS FAILED\n"
,
countPass
);
}
while
(
ok
&&
countPass
<
limitPass
);
if
(
!
ok
)
throw
new
java
.
lang
.
RuntimeException
(
"TESTS FAILED"
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/PictureDump.java
edu/princeton/cs/algs4/PictureDump.java
/******************************************************************************
* Compilation: javac PictureDump.java
* Execution: java PictureDump width height < file
* Dependencies: BinaryStdIn.java Picture.java
* Data file: http://introcs.cs.princeton.edu/stdlib/abra.txt
*
* Reads in a binary file and writes out the bits as w-by-h picture,
* with the 1 bits in black and the 0 bits in white.
*
* % more abra.txt
* ABRACADABRA!
*
* % java PictureDump 16 6 < abra.txt
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
awt
.
Color
;
/**
* The {
@code
PictureDump} class provides a client for displaying the contents
* of a binary file as a black-and-white picture.
*
* For additional documentation,
* see Section 5.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
* See also {
@link
BinaryDump} and {
@link
HexDump}.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
PictureDump
{
// Do not instantiate.
private
PictureDump
()
{
}
/**
* Reads in a sequence of bytes from standard input and draws
* them to standard drawing output as a width-by-height picture,
* using black for 1 and white for 0 (and red for any leftover
* pixels).
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
width
=
Integer
.
parseInt
(
args
[
0
]);
int
height
=
Integer
.
parseInt
(
args
[
1
]);
Picture
picture
=
new
Picture
(
width
,
height
);
for
(
int
row
=
0
;
row
<
height
;
row
++
)
{
for
(
int
col
=
0
;
col
<
width
;
col
++
)
{
if
(
!
BinaryStdIn
.
isEmpty
())
{
boolean
bit
=
BinaryStdIn
.
readBoolean
();
if
(
bit
)
picture
.
set
(
col
,
row
,
Color
.
BLACK
);
else
picture
.
set
(
col
,
row
,
Color
.
WHITE
);
}
else
{
picture
.
set
(
col
,
row
,
Color
.
RED
);
}
}
}
picture
.
show
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Picture.java
edu/princeton/cs/algs4/Picture.java
/******************************************************************************
* Compilation: javac Picture.java
* Execution: java Picture imagename
* Dependencies: none
*
* Data type for manipulating individual pixels of an image. The original
* image can be read from a file in JPG, GIF, or PNG format, or the
* user can create a blank image of a given dimension. Includes methods for
* displaying the image in a window on the screen or saving to a file.
*
* % java Picture mandrill
*
* Remarks
* -------
* - pixel (x, y) is column x and row y, where (0, 0) is upper left
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
awt
.
Color
;
import
java
.
awt
.
FileDialog
;
import
java
.
awt
.
Toolkit
;
import
java
.
awt
.
event
.
ActionEvent
;
import
java
.
awt
.
event
.
ActionListener
;
import
java
.
awt
.
event
.
KeyEvent
;
import
java
.
awt
.
image
.
BufferedImage
;
import
java
.
io
.
File
;
import
java
.
io
.
IOException
;
import
java
.
net
.
URL
;
import
javax
.
imageio
.
ImageIO
;
import
javax
.
swing
.
ImageIcon
;
import
javax
.
swing
.
JFrame
;
import
javax
.
swing
.
JLabel
;
import
javax
.
swing
.
JMenu
;
import
javax
.
swing
.
JMenuBar
;
import
javax
.
swing
.
JMenuItem
;
import
javax
.
swing
.
JPanel
;
import
javax
.
swing
.
KeyStroke
;
/**
* This class provides methods for manipulating individual pixels of
* an image using the RGB color format. The alpha component (for transparency)
* is not currently supported.
* The original image can be read from a {
@code
PNG}, {
@code
GIF},
* or {
@code
JPEG} file or the user can create a blank image of a given dimension.
* This class includes methods for displaying the image in a window on
* the screen or saving it to a file.
*
* Pixel (col, row) is column col and row row.
* By default, the origin (0, 0) is the pixel in the top-left corner,
* which is a common convention in image processing.
* The method {
@link
#setOriginLowerLeft()} change the origin to the lower left.
*
* The {
@code
get()} and {
@code
set()} methods use {
@link
Color} objects to get
* or set the color of the specified pixel.
* The {
@code
getRGB()} and {
@code
setRGB()} methods use a 32-bit {
@code
int}
* to encode the color, thereby avoiding the need to create temporary
* {
@code
Color} objects. The red (R), green (G), and blue (B) components
* are encoded using the least significant 24 bits.
* Given a 32-bit {
@code
int} encoding the color, the following code extracts
* the RGB components:
*
* int r = (rgb >> 16) & 0xFF; * int g = (rgb >> 8) & 0xFF; * int b = (rgb >> 0) & 0xFF; *
* Given the RGB components (8-bits each) of a color,
* the following statement packs it into a 32-bit {
@code
int}:
*
* int rgb = (r << 16) + (g << 8) + (b << 0); *
*
* A W-by-H picture uses ~ 4 W H bytes of memory,
* since the color of each pixel is encoded as a 32-bit int
.
*
* For additional documentation, see
* Section 3.1 of
* Computer Science: An Interdisciplinary Approach
* by Robert Sedgewick and Kevin Wayne.
* See {
@link
GrayscalePicture} for a version that supports grayscale images.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
Picture
implements
ActionListener
{
private
BufferedImage
image
;
// the rasterized image
private
JFrame
frame
;
// on-screen view
private
String
filename
;
// name of file
private
boolean
isOriginUpperLeft
=
true
;
// location of origin
private
final
int
width
,
height
;
// width and height
/**
* Creates a {
@code
width}-by-{
@code
height} picture, with {
@code
width} columns
* and {
@code
height} rows, where each pixel is black.
*
*
@param
width the width of the picture
*
@param
height the height of the picture
*
@throws
IllegalArgumentException if {
@code
width} is negative or zero
*
@throws
IllegalArgumentException if {
@code
height} is negative or zero
*/
public
Picture
(
int
width
,
int
height
)
{
if
(
width
<=
0
)
throw
new
IllegalArgumentException
(
"width must be positive"
);
if
(
height
<=
0
)
throw
new
IllegalArgumentException
(
"height must be positive"
);
this
.
width
=
width
;
this
.
height
=
height
;
image
=
new
BufferedImage
(
width
,
height
,
BufferedImage
.
TYPE_INT_RGB
);
// set to TYPE_INT_ARGB here and in next constructor to support transparency
}
/**
* Creates a new picture that is a deep copy of the argument picture.
*
*
@param
picture the picture to copy
*
@throws
IllegalArgumentException if {
@code
picture} is {
@code
null}
*/
public
Picture
(
Picture
picture
)
{
if
(
picture
==
null
)
throw
new
IllegalArgumentException
(
"constructor argument is null"
);
width
=
picture
.
width
();
height
=
picture
.
height
();
image
=
new
BufferedImage
(
width
,
height
,
BufferedImage
.
TYPE_INT_RGB
);
filename
=
picture
.
filename
;
isOriginUpperLeft
=
picture
.
isOriginUpperLeft
;
for
(
int
col
=
0
;
col
<
width
();
col
++
)
for
(
int
row
=
0
;
row
<
height
();
row
++
)
image
.
setRGB
(
col
,
row
,
picture
.
image
.
getRGB
(
col
,
row
));
}
/**
* Creates a picture by reading an image from a file or URL.
*
*
@param
name the name of the file ( , .gif, or ) or URL.
*
@throws
IllegalArgumentException if cannot read image
*
@throws
IllegalArgumentException if {
@code
name} is {
@code
null}
*/
public
Picture
(
String
name
)
{
if
(
name
==
null
)
throw
new
IllegalArgumentException
(
"constructor argument is null"
);
this
.
filename
=
name
;
try
{
// try to read from file in working directory
File
file
=
new
File
(
name
);
if
(
file
.
isFile
())
{
image
=
ImageIO
.
read
(
file
);
}
else
{
// resource relative to .class file
URL url
=
getClass
().
getResource
(
filename
);
// resource relative to classloader root
if
(
url
==
null
)
{
url
=
getClass
().
getClassLoader
().
getResource
(
name
);
}
// or URL from web
if
(
url
==
null
)
{
url
=
new
URL
(
name
);
}
image
=
ImageIO
.
read
(
url
);
}
if
(
image
==
null
)
{
throw
new
IllegalArgumentException
(
"could not read image: "
+
name
);
}
width
=
image
.
getWidth
(
null
);
height
=
image
.
getHeight
(
null
);
}
catch
(
IOException
ioe
)
{
throw
new
IllegalArgumentException
(
"could not open image: "
+
name
,
ioe
);
}
}
/**
* Creates a picture by reading the image from a PNG, GIF, or JPEG file.
*
*
@param
file the file
*
@throws
IllegalArgumentException if cannot read image
*
@throws
IllegalArgumentException if {
@code
file} is {
@code
null}
*/
public
Picture
(
File
file
)
{
if
(
file
==
null
)
throw
new
IllegalArgumentException
(
"constructor argument is null"
);
try
{
image
=
ImageIO
.
read
(
file
);
}
catch
(
IOException
ioe
)
{
throw
new
IllegalArgumentException
(
"could not open file: "
+
file
,
ioe
);
}
if
(
image
==
null
)
{
throw
new
IllegalArgumentException
(
"could not read file: "
+
file
);
}
width
=
image
.
getWidth
(
null
);
height
=
image
.
getHeight
(
null
);
filename
=
file
.
getName
();
}
/**
* Returns a {
@link
JLabel} containing this picture, for embedding in a {
@link
JPanel},
* {
@link
JFrame} or other GUI widget.
*
*
@return
the {
@code
JLabel}
*/
public
JLabel
getJLabel
()
{
if
(
image
==
null
)
return
null
;
// no image available
ImageIcon
icon
=
new
ImageIcon
(
image
);
return
new
JLabel
(
icon
);
}
/**
* Sets the origin to be the upper left pixel. This is the default.
*/
public
void
setOriginUpperLeft
()
{
isOriginUpperLeft
=
true
;
}
/**
* Sets the origin to be the lower left pixel.
*/
public
void
setOriginLowerLeft
()
{
isOriginUpperLeft
=
false
;
}
/**
* Displays the picture in a window on the screen.
*/
public
void
show
()
{
// create the GUI for viewing the image if needed
if
(
frame
==
null
)
{
frame
=
new
JFrame
();
JMenuBar
menuBar
=
new
JMenuBar
();
JMenu
menu
=
new
JMenu
(
"File"
);
menuBar
.
add
(
menu
);
JMenuItem
menuItem1
=
new
JMenuItem
(
" Save... "
);
menuItem1
.
addActionListener
(
this
);
// use getMenuShortcutKeyMaskEx() in Java 10 (getMenuShortcutKeyMask() deprecated)
menuItem1
.
setAccelerator
(
KeyStroke
.
getKeyStroke
(
KeyEvent
.
VK_S
,
Toolkit
.
getDefaultToolkit
().
getMenuShortcutKeyMask
()));
menu
.
add
(
menuItem1
);
frame
.
setJMenuBar
(
menuBar
);
frame
.
setContentPane
(
getJLabel
());
// f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame
.
setDefaultCloseOperation
(
JFrame
.
DISPOSE_ON_CLOSE
);
if
(
filename
==
null
)
frame
.
setTitle
(
width
+
"-by-"
+
height
);
else
frame
.
setTitle
(
filename
);
frame
.
setResizable
(
false
);
frame
.
pack
();
frame
.
setVisible
(
true
);
}
// draw
frame
.
repaint
();
}
/**
* Returns the height of the picture.
*
*
@return
the height of the picture (in pixels)
*/
public
int
height
()
{
return
height
;
}
/**
* Returns the width of the picture.
*
*
@return
the width of the picture (in pixels)
*/
public
int
width
()
{
return
width
;
}
private
void
validateRowIndex
(
int
row
)
{
if
(
row
<
0
||
row
>=
height
())
throw
new
IllegalArgumentException
(
“row index must be between 0 and ”
+
(
height
()
–
1
)
+
“: ”
+
row
);
}
private
void
validateColumnIndex
(
int
col
)
{
if
(
col
<
0
||
col
>=
width
())
throw
new
IllegalArgumentException
(
“column index must be between 0 and ”
+
(
width
()
–
1
)
+
“: ”
+
col
);
}
/**
* Returns the color of pixel ({
@code
col}, {
@code
row}) as a {
@link
java.awt.Color}.
*
*
@param
col the column index
*
@param
row the row index
*
@return
the color of pixel ({
@code
col}, {
@code
row})
*
@throws
IllegalArgumentException unless both {
@code
0 <= col < width} and {
@code
0 <= row < height}
*/
public
Color
get
(
int
col
,
int
row
)
{
validateColumnIndex
(
col
);
validateRowIndex
(
row
);
int
rgb
=
getRGB
(
col
,
row
);
return
new
Color
(
rgb
);
}
/**
* Returns the color of pixel ({
@code
col}, {
@code
row}) as an {
@code
int}.
* Using this method can be more efficient than {
@link
#get(int, int)} because
* it does not create a {
@code
Color} object.
*
*
@param
col the column index
*
@param
row the row index
*
@return
the integer representation of the color of pixel ({
@code
col}, {
@code
row})
*
@throws
IllegalArgumentException unless both {
@code
0 <= col < width} and {
@code
0 <= row < height}
*/
public
int
getRGB
(
int
col
,
int
row
)
{
validateColumnIndex
(
col
);
validateRowIndex
(
row
);
if
(
isOriginUpperLeft
)
return
image
.
getRGB
(
col
,
row
);
else
return
image
.
getRGB
(
col
,
height
-
row
-
1
);
}
/**
* Sets the color of pixel ({
@code
col}, {
@code
row}) to given color.
*
*
@param
col the column index
*
@param
row the row index
*
@param
color the color
*
@throws
IllegalArgumentException unless both {
@code
0 <= col < width} and {
@code
0 <= row < height}
*
@throws
IllegalArgumentException if {
@code
color} is {
@code
null}
*/
public
void
set
(
int
col
,
int
row
,
Color
color
)
{
validateColumnIndex
(
col
);
validateRowIndex
(
row
);
if
(
color
==
null
)
throw
new
IllegalArgumentException
(
"color argument is null"
);
int
rgb
=
color
.
getRGB
();
setRGB
(
col
,
row
,
rgb
);
}
/**
* Sets the color of pixel ({
@code
col}, {
@code
row}) to given color.
*
*
@param
col the column index
*
@param
row the row index
*
@param
rgb the integer representation of the color
*
@throws
IllegalArgumentException unless both {
@code
0 <= col < width} and {
@code
0 <= row < height}
*/
public
void
setRGB
(
int
col
,
int
row
,
int
rgb
)
{
validateColumnIndex
(
col
);
validateRowIndex
(
row
);
if
(
isOriginUpperLeft
)
image
.
setRGB
(
col
,
row
,
rgb
);
else
image
.
setRGB
(
col
,
height
-
row
-
1
,
rgb
);
}
/**
* Returns true if this picture is equal to the argument picture.
*
*
@param
other the other picture
*
@return
{
@code
true} if this picture is the same dimension as {
@code
other}
* and if all pixels have the same color; {
@code
false} otherwise
*/
public
boolean
equals
(
Object
other
)
{
if
(
other
==
this
)
return
true
;
if
(
other
==
null
)
return
false
;
if
(
other
.
getClass
()
!=
this
.
getClass
())
return
false
;
Picture
that
=
(
Picture
)
other
;
if
(
this
.
width
()
!=
that
.
width
())
return
false
;
if
(
this
.
height
()
!=
that
.
height
())
return
false
;
for
(
int
col
=
0
;
col
<
width
();
col
++
)
for
(
int
row
=
0
;
row
<
height
();
row
++
)
if
(
this
.
getRGB
(
col
,
row
)
!=
that
.
getRGB
(
col
,
row
))
return
false
;
return
true
;
}
/**
* Returns a string representation of this picture.
* The result is a width
-by-height
matrix of pixels,
* where the color of a pixel is represented using 6 hex digits to encode
* the red, green, and blue components.
*
*
@return
a string representation of this picture
*/
public
String
toString
()
{
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
width
+
“-by-”
+
height
+
” picture (RGB values given in hex)\n”
);
for
(
int
row
=
0
;
row
<
height
;
row
++
)
{
for
(
int
col
=
0
;
col
<
width
;
col
++
)
{
int
rgb
=
0
;
if
(
isOriginUpperLeft
)
rgb
=
image
.
getRGB
(
col
,
row
);
else
rgb
=
image
.
getRGB
(
col
,
height
-
row
-
1
);
sb
.
append
(
String
.
format
(
"#%06X "
,
rgb
&
0xFFFFFF
));
}
sb
.
append
(
"\n"
);
}
return
sb
.
toString
().
trim
();
}
/**
* This operation is not supported because pictures are mutable.
*
*
@return
does not return a value
*
@throws
UnsupportedOperationException if called
*/
public
int
hashCode
()
{
throw
new
UnsupportedOperationException
(
"hashCode() is not supported because pictures are mutable"
);
}
/**
* Saves the picture to a file in either PNG or JPEG format.
* The filetype extension must be either or .
*
*
@param
name the name of the file
*
@throws
IllegalArgumentException if {
@code
name} is {
@code
null}
*/
public
void
save
(
String
name
)
{
if
(
name
==
null
)
throw
new
IllegalArgumentException
(
"argument to save() is null"
);
save
(
new
File
(
name
));
filename
=
name
;
}
/**
* Saves the picture to a file in a PNG or JPEG image format.
*
*
@param
file the file
*
@throws
IllegalArgumentException if {
@code
file} is {
@code
null}
*/
public
void
save
(
File
file
)
{
if
(
file
==
null
)
throw
new
IllegalArgumentException
(
"argument to save() is null"
);
filename
=
file
.
getName
();
if
(
frame
!=
null
)
frame
.
setTitle
(
filename
);
String
suffix
=
filename
.
substring
(
filename
.
lastIndexOf
(
'.'
)
+
1
);
if
(
"jpg"
.
equalsIgnoreCase
(
suffix
)
||
"png"
.
equalsIgnoreCase
(
suffix
))
{
try
{
ImageIO
.
write
(
image
,
suffix
,
file
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
else
{
System
.
out
.
println
(
"Error: filename must end in or "
);
}
}
/**
* Opens a save dialog box when the user selects "Save As" from the menu.
*/
@
Override
public
void
actionPerformed
(
ActionEvent
e
)
{
FileDialog
chooser
=
new
FileDialog
(
frame
,
"Use a or extension"
,
FileDialog
.
SAVE
);
chooser
.
setVisible
(
true
);
if
(
chooser
.
getFile
()
!=
null
)
{
save
(
chooser
.
getDirectory
()
+
File
.
separator
+
chooser
.
getFile
());
}
}
/**
* Unit tests this {
@code
Picture} data type.
* Reads a picture specified by the command-line argument,
* and shows it in a window on the screen.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
Picture
picture
=
new
Picture
(
args
[
0
]);
System
.
out
.
printf
(
"%d-by-%d\n"
,
picture
.
width
(),
picture
.
height
());
picture
.
show
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Point2D.java
edu/princeton/cs/algs4/Point2D.java
/******************************************************************************
* Compilation: javac Point2D.java
* Execution: java Point2D x0 y0 n
* Dependencies: StdDraw.java StdRandom.java
*
* Immutable point data type for points in the plane.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Arrays
;
import
java
.
util
.
Comparator
;
/**
* The {
@code
Point} class is an immutable data type to encapsulate a
* two-dimensional point with real-value coordinates.
*
* Note: in order to deal with the difference behavior of double and
* Double with respect to -0.0 and +0.0, the Point2D constructor converts
* any coordinates that are -0.0 to +0.0.
*
* For additional documentation,
* see Section 1.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
Point2D
implements
Comparable
<
Point2D
>
{
/**
* Compares two points by x-coordinate.
*/
public
static
final
Comparator
<
Point2D
>
X_ORDER
=
new
XOrder
();
/**
* Compares two points by y-coordinate.
*/
public
static
final
Comparator
<
Point2D
>
Y_ORDER
=
new
YOrder
();
/**
* Compares two points by polar radius.
*/
public
static
final
Comparator
<
Point2D
>
R_ORDER
=
new
ROrder
();
private
final
double
x
;
// x coordinate
private
final
double
y
;
// y coordinate
/**
* Initializes a new point (x, y).
*
@param
x the x-coordinate
*
@param
y the y-coordinate
*
@throws
IllegalArgumentException if either {
@code
x} or {
@code
y}
* is {
@code
Double.NaN}, {
@code
Double.POSITIVE_INFINITY} or
* {
@code
Double.NEGATIVE_INFINITY}
*/
public
Point2D
(
double
x
,
double
y
)
{
if
(
Double
.
isInfinite
(
x
)
||
Double
.
isInfinite
(
y
))
throw
new
IllegalArgumentException
(
“Coordinates must be finite”
);
if
(
Double
.
isNaN
(
x
)
||
Double
.
isNaN
(
y
))
throw
new
IllegalArgumentException
(
“Coordinates cannot be NaN”
);
if
(
x
==
0.0
)
this
.
x
=
0.0
;
// convert -0.0 to +0.0
else
this
.
x
=
x
;
if
(
y
==
0.0
)
this
.
y
=
0.0
;
// convert -0.0 to +0.0
else
this
.
y
=
y
;
}
/**
* Returns the x-coordinate.
*
@return
the x-coordinate
*/
public
double
x
()
{
return
x
;
}
/**
* Returns the y-coordinate.
*
@return
the y-coordinate
*/
public
double
y
()
{
return
y
;
}
/**
* Returns the polar radius of this point.
*
@return
the polar radius of this point in polar coordiantes: sqrt(x*x + y*y)
*/
public
double
r
()
{
return
Math
.
sqrt
(
x
*
x
+
y
*
y
);
}
/**
* Returns the angle of this point in polar coordinates.
*
@return
the angle (in radians) of this point in polar coordiantes (between –π and π)
*/
public
double
theta
()
{
return
Math
.
atan2
(
y
,
x
);
}
/**
* Returns the angle between this point and that point.
*
@return
the angle in radians (between –π and π) between this point and that point (0 if equal)
*/
private
double
angleTo
(
Point2D
that
)
{
double
dx
=
that
.
x
–
this
.
x
;
double
dy
=
that
.
y
–
this
.
y
;
return
Math
.
atan2
(
dy
,
dx
);
}
/**
* Returns true if a→b→c is a counterclockwise turn.
*
@param
a first point
*
@param
b second point
*
@param
c third point
*
@return
{ -1, 0, +1 } if a→b→c is a { clockwise, collinear; counterclocwise } turn.
*/
public
static
int
ccw
(
Point2D
a
,
Point2D
b
,
Point2D
c
)
{
double
area2
=
(
b
.
x
–
a
.
x
)
*
(
c
.
y
–
a
.
y
)
–
(
b
.
y
–
a
.
y
)
*
(
c
.
x
–
a
.
x
);
if
(
area2
<
0
)
return
-
1
;
else
if
(
area2
>
0
)
return
+
1
;
else
return
0
;
}
/**
* Returns twice the signed area of the triangle a-b-c.
*
@param
a first point
*
@param
b second point
*
@param
c third point
*
@return
twice the signed area of the triangle a-b-c
*/
public
static
double
area2
(
Point2D
a
,
Point2D
b
,
Point2D
c
)
{
return
(
b
.
x
–
a
.
x
)
*
(
c
.
y
–
a
.
y
)
–
(
b
.
y
–
a
.
y
)
*
(
c
.
x
–
a
.
x
);
}
/**
* Returns the Euclidean distance between this point and that point.
*
@param
that the other point
*
@return
the Euclidean distance between this point and that point
*/
public
double
distanceTo
(
Point2D
that
)
{
double
dx
=
this
.
x
–
that
.
x
;
double
dy
=
this
.
y
–
that
.
y
;
return
Math
.
sqrt
(
dx
*
dx
+
dy
*
dy
);
}
/**
* Returns the square of the Euclidean distance between this point and that point.
*
@param
that the other point
*
@return
the square of the Euclidean distance between this point and that point
*/
public
double
distanceSquaredTo
(
Point2D
that
)
{
double
dx
=
this
.
x
–
that
.
x
;
double
dy
=
this
.
y
–
that
.
y
;
return
dx
*
dx
+
dy
*
dy
;
}
/**
* Compares two points by y-coordinate, breaking ties by x-coordinate.
* Formally, the invoking point (x0, y0) is less than the argument point (x1, y1)
* if and only if either {
@code
y0 < y1} or if {
@code
y0 == y1} and {
@code
x0 < x1}.
*
*
@param
that the other point
*
@return
the value {
@code
0} if this string is equal to the argument
* string (precisely when {
@code
equals()} returns {
@code
true});
* a negative integer if this point is less than the argument
* point; and a positive integer if this point is greater than the
* argument point
*/
public
int
compareTo
(
Point2D
that
)
{
if
(
this
.
y
<
that
.
y
)
return
-
1
;
if
(
this
.
y
>
that
.
y
)
return
+
1
;
if
(
this
.
x
<
that
.
x
)
return
-
1
;
if
(
this
.
x
>
that
.
x
)
return
+
1
;
return
0
;
}
/**
* Compares two points by polar angle (between 0 and 2π) with respect to this point.
*
*
@return
the comparator
*/
public
Comparator
<
Point2D
>
polarOrder
()
{
return
new
PolarOrder
();
}
/**
* Compares two points by atan2() angle (between –π and π) with respect to this point.
*
*
@return
the comparator
*/
public
Comparator
<
Point2D
>
atan2Order
()
{
return
new
Atan2Order
();
}
/**
* Compares two points by distance to this point.
*
*
@return
the comparator
*/
public
Comparator
<
Point2D
>
distanceToOrder
()
{
return
new
DistanceToOrder
();
}
// compare points according to their x-coordinate
private
static
class
XOrder
implements
Comparator
<
Point2D
>
{
public
int
compare
(
Point2D
p
,
Point2D
q
)
{
if
(
p
.
x
<
q
.
x
)
return
-
1
;
if
(
p
.
x
>
q
.
x
)
return
+
1
;
return
0
;
}
}
// compare points according to their y-coordinate
private
static
class
YOrder
implements
Comparator
<
Point2D
>
{
public
int
compare
(
Point2D
p
,
Point2D
q
)
{
if
(
p
.
y
<
q
.
y
)
return
-
1
;
if
(
p
.
y
>
q
.
y
)
return
+
1
;
return
0
;
}
}
// compare points according to their polar radius
private
static
class
ROrder
implements
Comparator
<
Point2D
>
{
public
int
compare
(
Point2D
p
,
Point2D
q
)
{
double
delta
=
(
p
.
x
*
p
.
x
+
p
.
y
*
p
.
y
)
–
(
q
.
x
*
q
.
x
+
q
.
y
*
q
.
y
);
if
(
delta
<
0
)
return
-
1
;
if
(
delta
>
0
)
return
+
1
;
return
0
;
}
}
// compare other points relative to atan2 angle (bewteen -pi/2 and pi/2) they make with this Point
private
class
Atan2Order
implements
Comparator
<
Point2D
>
{
public
int
compare
(
Point2D
q1
,
Point2D
q2
)
{
double
angle1
=
angleTo
(
q1
);
double
angle2
=
angleTo
(
q2
);
if
(
angle1
<
angle2
)
return
-
1
;
else
if
(
angle1
>
angle2
)
return
+
1
;
else
return
0
;
}
}
// compare other points relative to polar angle (between 0 and 2pi) they make with this Point
private
class
PolarOrder
implements
Comparator
<
Point2D
>
{
public
int
compare
(
Point2D
q1
,
Point2D
q2
)
{
double
dx1
=
q1
.
x
–
x
;
double
dy1
=
q1
.
y
–
y
;
double
dx2
=
q2
.
x
–
x
;
double
dy2
=
q2
.
y
–
y
;
if
(
dy1
>=
0
&&
dy2
<
0
)
return
-
1
;
// q1 above; q2 below
else
if
(
dy2
>=
0
&&
dy1
<
0
)
return
+
1
;
// q1 below; q2 above
else
if
(
dy1
==
0
&&
dy2
==
0
)
{
// 3-collinear and horizontal
if
(
dx1
>=
0
&&
dx2
<
0
)
return
-
1
;
else
if
(
dx2
>=
0
&&
dx1
<
0
)
return
+
1
;
else
return
0
;
}
else
return
-
ccw
(
Point2D
.
this
,
q1
,
q2
);
// both above or below
// Note: ccw() recomputes dx1, dy1, dx2, and dy2
}
}
// compare points according to their distance to this point
private
class
DistanceToOrder
implements
Comparator
<
Point2D
>
{
public
int
compare
(
Point2D
p
,
Point2D
q
)
{
double
dist1
=
distanceSquaredTo
(
p
);
double
dist2
=
distanceSquaredTo
(
q
);
if
(
dist1
<
dist2
)
return
-
1
;
else
if
(
dist1
>
dist2
)
return
+
1
;
else
return
0
;
}
}
/**
* Compares this point to the specified point.
*
*
@param
other the other point
*
@return
{
@code
true} if this point equals {
@code
other};
* {
@code
false} otherwise
*/
@
Override
public
boolean
equals
(
Object
other
)
{
if
(
other
==
this
)
return
true
;
if
(
other
==
null
)
return
false
;
if
(
other
.
getClass
()
!=
this
.
getClass
())
return
false
;
Point2D
that
=
(
Point2D
)
other
;
return
this
.
x
==
that
.
x
&&
this
.
y
==
that
.
y
;
}
/**
* Return a string representation of this point.
*
@return
a string representation of this point in the format (x, y)
*/
@
Override
public
String
toString
()
{
return
“(”
+
x
+
“, ”
+
y
+
“)”
;
}
/**
* Returns an integer hash code for this point.
*
@return
an integer hash code for this point
*/
@
Override
public
int
hashCode
()
{
int
hashX
=
((
Double
)
x
).
hashCode
();
int
hashY
=
((
Double
)
y
).
hashCode
();
return
31
*
hashX
+
hashY
;
}
/**
* Plot this point using standard draw.
*/
public
void
draw
()
{
StdDraw
.
point
(
x
,
y
);
}
/**
* Plot a line from this point to that point using standard draw.
*
@param
that the other point
*/
public
void
drawTo
(
Point2D
that
)
{
StdDraw
.
line
(
this
.
x
,
this
.
y
,
that
.
x
,
that
.
y
);
}
/**
* Unit tests the point data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
x0
=
Integer
.
parseInt
(
args
[
0
]);
int
y0
=
Integer
.
parseInt
(
args
[
1
]);
int
n
=
Integer
.
parseInt
(
args
[
2
]);
StdDraw
.
setCanvasSize
(
800
,
800
);
StdDraw
.
setXscale
(
0
,
100
);
StdDraw
.
setYscale
(
0
,
100
);
StdDraw
.
setPenRadius
(
0.005
);
StdDraw
.
enableDoubleBuffering
();
Point2D
[]
points
=
new
Point2D
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
int
x
=
StdRandom
.
uniform
(
100
);
int
y
=
StdRandom
.
uniform
(
100
);
points
[
i
]
=
new
Point2D
(
x
,
y
);
points
[
i
].
draw
();
}
// draw p = (x0, x1) in red
Point2D
p
=
new
Point2D
(
x0
,
y0
);
StdDraw
.
setPenColor
(
StdDraw
.
RED
);
StdDraw
.
setPenRadius
(
0.02
);
p
.
draw
();
// draw line segments from p to each point, one at a time, in polar order
StdDraw
.
setPenRadius
();
StdDraw
.
setPenColor
(
StdDraw
.
BLUE
);
Arrays
.
sort
(
points
,
p
.
polarOrder
());
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
p
.
drawTo
(
points
[
i
]);
StdDraw
.
show
();
StdDraw
.
pause
(
100
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Polynomial.java
edu/princeton/cs/algs4/Polynomial.java
/******************************************************************************
* Compilation: javac Polynomial.java
* Execution: java Polynomial
*
* Polynomials with integer coefficients.
*
* % java Polynomial
* zero(x) = 0
* p(x) = 4x^3 + 3x^2 + 2x + 1
* q(x) = 3x^2 + 5
* p(x) + q(x) = 4x^3 + 6x^2 + 2x + 6
* p(x) * q(x) = 12x^5 + 9x^4 + 26x^3 + 18x^2 + 10x + 5
* p(q(x)) = 108x^6 + 567x^4 + 996x^2 + 586
* p(x) - p(x) = 0
* 0 - p(x) = -4x^3 - 3x^2 - 2x - 1
* p(3) = 142
* p'(x) = 12x^2 + 6x + 2
* p''(x) = 24x + 6
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Polynomial} class represents a polynomial with integer
* coefficients.
* Polynomials are immutable: their values cannot be changed after they
* are created.
* It includes methods for addition, subtraction, multiplication, composition,
* differentiation, and evaluation.
*
* For additional documentation,
* see Section 9.9 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Polynomial
{
private
int
[]
coef
;
// coefficients p(x) = sum { coef[i] * x^i }
private
int
degree
;
// degree of polynomial (-1 for the zero polynomial)
/**
* Initializes a new polynomial a x^b
*
@param
a the leading coefficient
*
@param
b the exponent
*
@throws
IllegalArgumentException if {
@code
b} is negative
*/
public
Polynomial
(
int
a
,
int
b
)
{
if
(
b
<
0
)
{
throw
new
IllegalArgumentException
(
"exponent cannot be negative: "
+
b
);
}
coef
=
new
int
[
b
+
1
];
coef
[
b
]
=
a
;
reduce
();
}
// pre-compute the degree of the polynomial, in case of leading zero coefficients
// (that is, the length of the array need not relate to the degree of the polynomial)
private
void
reduce
()
{
degree
=
-
1
;
for
(
int
i
=
coef
.
length
-
1
;
i
>=
0
;
i
—
)
{
if
(
coef
[
i
]
!=
0
)
{
degree
=
i
;
return
;
}
}
}
/**
* Returns the degree of this polynomial.
*
@return
the degree of this polynomial, -1 for the zero polynomial.
*/
public
int
degree
()
{
return
degree
;
}
/**
* Returns the sum of this polynomial and the specified polynomial.
*
*
@param
that the other polynomial
*
@return
the polynomial whose value is {
@code
(this(x) + that(x))}
*/
public
Polynomial
plus
(
Polynomial
that
)
{
Polynomial
poly
=
new
Polynomial
(
0
,
Math
.
max
(
this
.
degree
,
that
.
degree
));
for
(
int
i
=
0
;
i
<=
this
.
degree
;
i
++
)
poly
.
coef
[
i
]
+=
this
.
coef
[
i
];
for
(
int
i
=
0
;
i
<=
that
.
degree
;
i
++
)
poly
.
coef
[
i
]
+=
that
.
coef
[
i
];
poly
.
reduce
();
return
poly
;
}
/**
* Returns the result of subtracting the specified polynomial
* from this polynomial.
*
*
@param
that the other polynomial
*
@return
the polynomial whose value is {
@code
(this(x) - that(x))}
*/
public
Polynomial
minus
(
Polynomial
that
)
{
Polynomial
poly
=
new
Polynomial
(
0
,
Math
.
max
(
this
.
degree
,
that
.
degree
));
for
(
int
i
=
0
;
i
<=
this
.
degree
;
i
++
)
poly
.
coef
[
i
]
+=
this
.
coef
[
i
];
for
(
int
i
=
0
;
i
<=
that
.
degree
;
i
++
)
poly
.
coef
[
i
]
-=
that
.
coef
[
i
];
poly
.
reduce
();
return
poly
;
}
/**
* Returns the product of this polynomial and the specified polynomial.
* Takes time proportional to the product of the degrees.
* (Faster algorithms are known, e.g., via FFT.)
*
*
@param
that the other polynomial
*
@return
the polynomial whose value is {
@code
(this(x) * that(x))}
*/
public
Polynomial
times
(
Polynomial
that
)
{
Polynomial
poly
=
new
Polynomial
(
0
,
this
.
degree
+
that
.
degree
);
for
(
int
i
=
0
;
i
<=
this
.
degree
;
i
++
)
for
(
int
j
=
0
;
j
<=
that
.
degree
;
j
++
)
poly
.
coef
[
i
+
j
]
+=
(
this
.
coef
[
i
]
*
that
.
coef
[
j
]);
poly
.
reduce
();
return
poly
;
}
/**
* Returns the composition of this polynomial and the specified
* polynomial.
* Takes time proportional to the product of the degrees.
* (Faster algorithms are known, e.g., via FFT.)
*
*
@param
that the other polynomial
*
@return
the polynomial whose value is {
@code
(this(that(x)))}
*/
public
Polynomial
compose
(
Polynomial
that
)
{
Polynomial
poly
=
new
Polynomial
(
0
,
0
);
for
(
int
i
=
this
.
degree
;
i
>=
0
;
i
—
)
{
Polynomial
term
=
new
Polynomial
(
this
.
coef
[
i
],
0
);
poly
=
term
.
plus
(
that
.
times
(
poly
));
}
return
poly
;
}
/**
* Compares this polynomial to the specified polynomial.
*
*
@param
other the other polynoimal
*
@return
{
@code
true} if this polynomial equals {
@code
other};
* {
@code
false} otherwise
*/
@
Override
public
boolean
equals
(
Object
other
)
{
if
(
other
==
this
)
return
true
;
if
(
other
==
null
)
return
false
;
if
(
other
.
getClass
()
!=
this
.
getClass
())
return
false
;
Polynomial
that
=
(
Polynomial
)
other
;
if
(
this
.
degree
!=
that
.
degree
)
return
false
;
for
(
int
i
=
this
.
degree
;
i
>=
0
;
i
—
)
if
(
this
.
coef
[
i
]
!=
that
.
coef
[
i
])
return
false
;
return
true
;
}
/**
* Returns the result of differentiating this polynomial.
*
*
@return
the polynomial whose value is {
@code
this'(x)}
*/
public
Polynomial
differentiate
()
{
if
(
degree
==
0
)
return
new
Polynomial
(
0
,
0
);
Polynomial
poly
=
new
Polynomial
(
0
,
degree
–
1
);
poly
.
degree
=
degree
–
1
;
for
(
int
i
=
0
;
i
<
degree
;
i
++
)
poly
.
coef
[
i
]
=
(
i
+
1
)
*
coef
[
i
+
1
];
return
poly
;
}
/**
* Returns the result of evaluating this polynomial at the point x.
*
*
@param
x the point at which to evaluate the polynomial
*
@return
the integer whose value is {
@code
(this(x))}
*/
public
int
evaluate
(
int
x
)
{
int
p
=
0
;
for
(
int
i
=
degree
;
i
>=
0
;
i
—
)
p
=
coef
[
i
]
+
(
x
*
p
);
return
p
;
}
/**
* Compares two polynomials by degree, breaking ties by coefficient of leading term.
*
*
@param
that the other point
*
@return
the value {
@code
0} if this polynomial is equal to the argument
* polynomial (precisely when {
@code
equals()} returns {
@code
true});
* a negative integer if this polynomialt is less than the argument
* polynomial; and a positive integer if this polynomial is greater than the
* argument point
*/
public
int
compareTo
(
Polynomial
that
)
{
if
(
this
.
degree
<
that
.
degree
)
return
-
1
;
if
(
this
.
degree
>
that
.
degree
)
return
+
1
;
for
(
int
i
=
this
.
degree
;
i
>=
0
;
i
—
)
{
if
(
this
.
coef
[
i
]
<
that
.
coef
[
i
])
return
-
1
;
if
(
this
.
coef
[
i
]
>
that
.
coef
[
i
])
return
+
1
;
}
return
0
;
}
/**
* Return a string representation of this polynomial.
*
@return
a string representation of this polynomial in the format
* 4x^5 – 3x^2 + 11x + 5
*/
@
Override
public
String
toString
()
{
if
(
degree
==
–
1
)
return
“0”
;
else
if
(
degree
==
0
)
return
“”
+
coef
[
0
];
else
if
(
degree
==
1
)
return
coef
[
1
]
+
“x + ”
+
coef
[
0
];
String
s
=
coef
[
degree
]
+
“x^”
+
degree
;
for
(
int
i
=
degree
–
1
;
i
>=
0
;
i
—
)
{
if
(
coef
[
i
]
==
0
)
continue
;
else
if
(
coef
[
i
]
>
0
)
s
=
s
+
” + ”
+
(
coef
[
i
]);
else
if
(
coef
[
i
]
<
0
)
s
=
s
+
" - "
+
(
-
coef
[
i
]);
if
(
i
==
1
)
s
=
s
+
"x"
;
else
if
(
i
>
1
)
s
=
s
+
“x^”
+
i
;
}
return
s
;
}
/**
* Unit tests the polynomial data type.
*
*
@param
args the command-line arguments (none)
*/
public
static
void
main
(
String
[]
args
)
{
Polynomial
zero
=
new
Polynomial
(
0
,
0
);
Polynomial
p1
=
new
Polynomial
(
4
,
3
);
Polynomial
p2
=
new
Polynomial
(
3
,
2
);
Polynomial
p3
=
new
Polynomial
(
1
,
0
);
Polynomial
p4
=
new
Polynomial
(
2
,
1
);
Polynomial
p
=
p1
.
plus
(
p2
).
plus
(
p3
).
plus
(
p4
);
// 4x^3 + 3x^2 + 1
Polynomial
q1
=
new
Polynomial
(
3
,
2
);
Polynomial
q2
=
new
Polynomial
(
5
,
0
);
Polynomial
q
=
q1
.
plus
(
q2
);
// 3x^2 + 5
Polynomial
r
=
p
.
plus
(
q
);
Polynomial
s
=
p
.
times
(
q
);
Polynomial
t
=
p
.
compose
(
q
);
Polynomial
u
=
p
.
minus
(
p
);
StdOut
.
println
(
“zero(x) = ”
+
zero
);
StdOut
.
println
(
“p(x) = ”
+
p
);
StdOut
.
println
(
“q(x) = ”
+
q
);
StdOut
.
println
(
“p(x) + q(x) = ”
+
r
);
StdOut
.
println
(
“p(x) * q(x) = ”
+
s
);
StdOut
.
println
(
“p(q(x)) = ”
+
t
);
StdOut
.
println
(
“p(x) – p(x) = ”
+
u
);
StdOut
.
println
(
“0 – p(x) = ”
+
zero
.
minus
(
p
));
StdOut
.
println
(
“p(3) = ”
+
p
.
evaluate
(
3
));
StdOut
.
println
(
“p'(x) = ”
+
p
.
differentiate
());
StdOut
.
println
(
“p”(x) = ”
+
p
.
differentiate
().
differentiate
());
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/PrimMST.java
edu/princeton/cs/algs4/PrimMST.java
/******************************************************************************
* Compilation: javac PrimMST.java
* Execution: java PrimMST filename.txt
* Dependencies: EdgeWeightedGraph.java Edge.java Queue.java
* IndexMinPQ.java UF.java In.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/43mst/tinyEWG.txt
* https://algs4.cs.princeton.edu/43mst/mediumEWG.txt
* https://algs4.cs.princeton.edu/43mst/largeEWG.txt
*
* Compute a minimum spanning forest using Prim’s algorithm.
*
* % java PrimMST tinyEWG.txt
* 1-7 0.19000
* 0-2 0.26000
* 2-3 0.17000
* 4-5 0.35000
* 5-7 0.28000
* 6-2 0.40000
* 0-7 0.16000
* 1.81000
*
* % java PrimMST mediumEWG.txt
* 1-72 0.06506
* 2-86 0.05980
* 3-67 0.09725
* 4-55 0.06425
* 5-102 0.03834
* 6-129 0.05363
* 7-157 0.00516
* …
* 10.46351
*
* % java PrimMST largeEWG.txt
* …
* 647.66307
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
PrimMST} class represents a data type for computing a
* minimum spanning tree in an edge-weighted graph.
* The edge weights can be positive, zero, or negative and need not
* be distinct. If the graph is not connected, it computes a minimum
* spanning forest, which is the union of minimum spanning trees
* in each connected component. The {
@code
weight()} method returns the
* weight of a minimum spanning tree and the {
@code
edges()} method
* returns its edges.
*
* This implementation uses Prim’s algorithm with an indexed
* binary heap.
* The constructor takes Θ(E log V) time in
* the worst case, where V is the number of
* vertices and E is the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the
* edge-weighted graph).
*
* For additional documentation,
* see Section 4.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
* For alternate implementations, see {
@link
LazyPrimMST}, {
@link
KruskalMST},
* and {
@link
BoruvkaMST}.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
PrimMST
{
private
static
final
double
FLOATING_POINT_EPSILON
=
1E-12
;
private
Edge
[]
edgeTo
;
// edgeTo[v] = shortest edge from tree vertex to non-tree vertex
private
double
[]
distTo
;
// distTo[v] = weight of shortest such edge
private
boolean
[]
marked
;
// marked[v] = true if v on tree, false otherwise
private
IndexMinPQ
<
Double
>
pq
;
/**
* Compute a minimum spanning tree (or forest) of an edge-weighted graph.
*
@param
G the edge-weighted graph
*/
public
PrimMST
(
EdgeWeightedGraph
G
)
{
edgeTo
=
new
Edge
[
G
.
V
()];
distTo
=
new
double
[
G
.
V
()];
marked
=
new
boolean
[
G
.
V
()];
pq
=
new
IndexMinPQ
<
Double
>
(
G
.
V
());
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
distTo
[
v
]
=
Double
.
POSITIVE_INFINITY
;
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
// run from each vertex to find
if
(
!
marked
[
v
])
prim
(
G
,
v
);
// minimum spanning forest
// check optimality conditions
assert
check
(
G
);
}
// run Prim's algorithm in graph G, starting from vertex s
private
void
prim
(
EdgeWeightedGraph
G
,
int
s
)
{
distTo
[
s
]
=
0.0
;
pq
.
insert
(
s
,
distTo
[
s
]);
while
(
!
pq
.
isEmpty
())
{
int
v
=
pq
.
delMin
();
scan
(
G
,
v
);
}
}
// scan vertex v
private
void
scan
(
EdgeWeightedGraph
G
,
int
v
)
{
marked
[
v
]
=
true
;
for
(
Edge
e
:
G
.
adj
(
v
))
{
int
w
=
e
.
other
(
v
);
if
(
marked
[
w
])
continue
;
// v-w is obsolete edge
if
(
e
.
weight
()
<
distTo
[
w
])
{
distTo
[
w
]
=
e
.
weight
();
edgeTo
[
w
]
=
e
;
if
(
pq
.
contains
(
w
))
pq
.
decreaseKey
(
w
,
distTo
[
w
]);
else
pq
.
insert
(
w
,
distTo
[
w
]);
}
}
}
/**
* Returns the edges in a minimum spanning tree (or forest).
*
@return
the edges in a minimum spanning tree (or forest) as
* an iterable of edges
*/
public
Iterable
<
Edge
>
edges
()
{
Queue
<
Edge
>
mst
=
new
Queue
<
Edge
>
();
for
(
int
v
=
0
;
v
<
edgeTo
.
length
;
v
++
)
{
Edge
e
=
edgeTo
[
v
];
if
(
e
!=
null
)
{
mst
.
enqueue
(
e
);
}
}
return
mst
;
}
/**
* Returns the sum of the edge weights in a minimum spanning tree (or forest).
*
@return
the sum of the edge weights in a minimum spanning tree (or forest)
*/
public
double
weight
()
{
double
weight
=
0.0
;
for
(
Edge
e
:
edges
())
weight
+=
e
.
weight
();
return
weight
;
}
// check optimality conditions (takes time proportional to E V lg* V)
private
boolean
check
(
EdgeWeightedGraph
G
)
{
// check weight
double
totalWeight
=
0.0
;
for
(
Edge
e
:
edges
())
{
totalWeight
+=
e
.
weight
();
}
if
(
Math
.
abs
(
totalWeight
-
weight
())
>
FLOATING_POINT_EPSILON
)
{
System
.
err
.
printf
(
“Weight of edges does not equal weight(): %f vs. %f\n”
,
totalWeight
,
weight
());
return
false
;
}
// check that it is acyclic
UF uf
=
new
UF
(
G
.
V
());
for
(
Edge
e
:
edges
())
{
int
v
=
e
.
either
(),
w
=
e
.
other
(
v
);
if
(
uf
.
find
(
v
)
==
uf
.
find
(
w
))
{
System
.
err
.
println
(
“Not a forest”
);
return
false
;
}
uf
.
union
(
v
,
w
);
}
// check that it is a spanning forest
for
(
Edge
e
:
G
.
edges
())
{
int
v
=
e
.
either
(),
w
=
e
.
other
(
v
);
if
(
uf
.
find
(
v
)
!=
uf
.
find
(
w
))
{
System
.
err
.
println
(
“Not a spanning forest”
);
return
false
;
}
}
// check that it is a minimal spanning forest (cut optimality conditions)
for
(
Edge
e
:
edges
())
{
// all edges in MST except e
uf
=
new
UF
(
G
.
V
());
for
(
Edge
f
:
edges
())
{
int
x
=
f
.
either
(),
y
=
f
.
other
(
x
);
if
(
f
!=
e
)
uf
.
union
(
x
,
y
);
}
// check that e is min weight edge in crossing cut
for
(
Edge
f
:
G
.
edges
())
{
int
x
=
f
.
either
(),
y
=
f
.
other
(
x
);
if
(
uf
.
find
(
x
)
!=
uf
.
find
(
y
))
{
if
(
f
.
weight
()
<
e
.
weight
())
{
System
.
err
.
println
(
"Edge "
+
f
+
" violates cut optimality conditions"
);
return
false
;
}
}
}
}
return
true
;
}
/**
* Unit tests the {
@code
PrimMST} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
EdgeWeightedGraph
G
=
new
EdgeWeightedGraph
(
in
);
PrimMST
mst
=
new
PrimMST
(
G
);
for
(
Edge
e
:
mst
.
edges
())
{
StdOut
.
println
(
e
);
}
StdOut
.
printf
(
"%.5f\n"
,
mst
.
weight
());
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Queue.java
edu/princeton/cs/algs4/Queue.java
/******************************************************************************
* Compilation: javac Queue.java
* Execution: java Queue < input.txt
* Dependencies: StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/13stacks/tobe.txt
*
* A generic queue, implemented using a linked list.
*
* % java Queue < tobe.txt
* to be or not to be (2 left on queue)
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Iterator
;
import
java
.
util
.
NoSuchElementException
;
/**
* The {
@code
Queue} class represents a first-in-first-out (FIFO)
* queue of generic items.
* It supports the usual enqueue and dequeue
* operations, along with methods for peeking at the first item,
* testing if the queue is empty, and iterating through
* the items in FIFO order.
*
* This implementation uses a singly linked list with a static nested class for
* linked-list nodes. See {
@link
LinkedQueue} for the version from the
* textbook that uses a non-static nested class.
* See {
@link
ResizingArrayQueue} for a version that uses a resizing array.
* The enqueue, dequeue, peek, size, and is-empty
* operations all take constant time in the worst case.
*
* For additional documentation, see Section 1.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*
*
@param
*/
public
class
Queue
<
Item
>
implements
Iterable
<
Item
>
{
private
Node
<
Item
>
first
;
// beginning of queue
private
Node
<
Item
>
last
;
// end of queue
private
int
n
;
// number of elements on queue
// helper linked list class
private
static
class
Node
<
Item
>
{
private
Item
item
;
private
Node
<
Item
>
next
;
}
/**
* Initializes an empty queue.
*/
public
Queue
()
{
first
=
null
;
last
=
null
;
n
=
0
;
}
/**
* Returns true if this queue is empty.
*
*
@return
{
@code
true} if this queue is empty; {
@code
false} otherwise
*/
public
boolean
isEmpty
()
{
return
first
==
null
;
}
/**
* Returns the number of items in this queue.
*
*
@return
the number of items in this queue
*/
public
int
size
()
{
return
n
;
}
/**
* Returns the item least recently added to this queue.
*
*
@return
the item least recently added to this queue
*
@throws
NoSuchElementException if this queue is empty
*/
public
Item
peek
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Queue underflow”
);
return
first
.
item
;
}
/**
* Adds the item to this queue.
*
*
@param
item the item to add
*/
public
void
enqueue
(
Item
item
)
{
Node
<
Item
>
oldlast
=
last
;
last
=
new
Node
<
Item
>
();
last
.
item
=
item
;
last
.
next
=
null
;
if
(
isEmpty
())
first
=
last
;
else
oldlast
.
next
=
last
;
n
++
;
}
/**
* Removes and returns the item on this queue that was least recently added.
*
*
@return
the item on this queue that was least recently added
*
@throws
NoSuchElementException if this queue is empty
*/
public
Item
dequeue
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Queue underflow”
);
Item
item
=
first
.
item
;
first
=
first
.
next
;
n
—
;
if
(
isEmpty
())
last
=
null
;
// to avoid loitering
return
item
;
}
/**
* Returns a string representation of this queue.
*
*
@return
the sequence of items in FIFO order, separated by spaces
*/
public
String
toString
()
{
StringBuilder
s
=
new
StringBuilder
();
for
(
Item
item
:
this
)
{
s
.
append
(
item
);
s
.
append
(
‘ ‘
);
}
return
s
.
toString
();
}
/**
* Returns an iterator that iterates over the items in this queue in FIFO order.
*
*
@return
an iterator that iterates over the items in this queue in FIFO order
*/
public
Iterator
<
Item
>
iterator
()
{
return
new
ListIterator
(
first
);
}
// an iterator, doesn’t implement remove() since it’s optional
private
class
ListIterator
implements
Iterator
<
Item
>
{
private
Node
<
Item
>
current
;
public
ListIterator
(
Node
<
Item
>
first
)
{
current
=
first
;
}
public
boolean
hasNext
()
{
return
current
!=
null
;
}
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
public
Item
next
()
{
if
(
!
hasNext
())
throw
new
NoSuchElementException
();
Item
item
=
current
.
item
;
current
=
current
.
next
;
return
item
;
}
}
/**
* Unit tests the {
@code
Queue} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
Queue
<
String
>
queue
=
new
Queue
<
String
>
();
while
(
!
StdIn
.
isEmpty
())
{
String
item
=
StdIn
.
readString
();
if
(
!
item
.
equals
(
“-”
))
queue
.
enqueue
(
item
);
else
if
(
!
queue
.
isEmpty
())
StdOut
.
print
(
queue
.
dequeue
()
+
” ”
);
}
StdOut
.
println
(
“(”
+
queue
.
size
()
+
” left on queue)”
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Quick3string.java
edu/princeton/cs/algs4/Quick3string.java
/******************************************************************************
* Compilation: javac Quick3string.java
* Execution: java Quick3string < input.txt * Dependencies: StdIn.java StdOut.java * Data files: https://algs4.cs.princeton.edu/51radix/words3.txt * https://algs4.cs.princeton.edu/51radix/shells.txt * * Reads string from standard input and 3-way string quicksort them. * * % java Quick3string < shell.txt * are * by * sea * seashells * seashells * sells * sells * she * she * shells * shore * surely * the * the * * ******************************************************************************/ package edu . princeton . cs . algs4 ; /** * The { @code Quick3string} class provides static methods for sorting an * array of strings using 3-way radix quicksort. *
* For additional documentation,
* see Section 5.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Quick3string
{
private
static
final
int
CUTOFF
=
15
;
// cutoff to insertion sort
// do not instantiate
private
Quick3string
()
{
}
/**
* Rearranges the array of strings in ascending order.
*
*
@param
a the array to be sorted
*/
public
static
void
sort
(
String
[]
a
)
{
StdRandom
.
shuffle
(
a
);
sort
(
a
,
0
,
a
.
length
–
1
,
0
);
assert
isSorted
(
a
);
}
// return the dth character of s, -1 if d = length of s
private
static
int
charAt
(
String
s
,
int
d
)
{
assert
d
>=
0
&&
d
<=
s
.
length
();
if
(
d
==
s
.
length
())
return
-
1
;
return
s
.
charAt
(
d
);
}
// 3-way string quicksort a[lo..hi] starting at dth character
private
static
void
sort
(
String
[]
a
,
int
lo
,
int
hi
,
int
d
)
{
// cutoff to insertion sort for small subarrays
if
(
hi
<=
lo
+
CUTOFF
)
{
insertion
(
a
,
lo
,
hi
,
d
);
return
;
}
int
lt
=
lo
,
gt
=
hi
;
int
v
=
charAt
(
a
[
lo
],
d
);
int
i
=
lo
+
1
;
while
(
i
<=
gt
)
{
int
t
=
charAt
(
a
[
i
],
d
);
if
(
t
<
v
)
exch
(
a
,
lt
++
,
i
++
);
else
if
(
t
>
v
)
exch
(
a
,
i
,
gt
—
);
else
i
++
;
}
// a[lo..lt-1] < v = a[lt..gt] < a[gt+1..hi].
sort
(
a
,
lo
,
lt
-
1
,
d
);
if
(
v
>=
0
)
sort
(
a
,
lt
,
gt
,
d
+
1
);
sort
(
a
,
gt
+
1
,
hi
,
d
);
}
// sort from a[lo] to a[hi], starting at the dth character
private
static
void
insertion
(
String
[]
a
,
int
lo
,
int
hi
,
int
d
)
{
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
for
(
int
j
=
i
;
j
>
lo
&&
less
(
a
[
j
],
a
[
j
–
1
],
d
);
j
—
)
exch
(
a
,
j
,
j
–
1
);
}
// exchange a[i] and a[j]
private
static
void
exch
(
String
[]
a
,
int
i
,
int
j
)
{
String
temp
=
a
[
i
];
a
[
i
]
=
a
[
j
];
a
[
j
]
=
temp
;
}
// is v less than w, starting at character d
// DEPRECATED BECAUSE OF SLOW SUBSTRING EXTRACTION IN JAVA 7
// private static boolean less(String v, String w, int d) {
// assert v.substring(0, d).equals(w.substring(0, d));
// return v.substring(d).compareTo(w.substring(d)) < 0;
// }
// is v less than w, starting at character d
private
static
boolean
less
(
String
v
,
String
w
,
int
d
)
{
assert
v
.
substring
(
0
,
d
).
equals
(
w
.
substring
(
0
,
d
));
for
(
int
i
=
d
;
i
<
Math
.
min
(
v
.
length
(),
w
.
length
());
i
++
)
{
if
(
v
.
charAt
(
i
)
<
w
.
charAt
(
i
))
return
true
;
if
(
v
.
charAt
(
i
)
>
w
.
charAt
(
i
))
return
false
;
}
return
v
.
length
()
<
w
.
length
();
}
// is the array sorted
private
static
boolean
isSorted
(
String
[]
a
)
{
for
(
int
i
=
1
;
i
<
a
.
length
;
i
++
)
if
(
a
[
i
].
compareTo
(
a
[
i
-
1
])
<
0
)
return
false
;
return
true
;
}
/**
* Reads in a sequence of fixed-length strings from standard input;
* 3-way radix quicksorts them;
* and prints them to standard output in ascending order.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// read in the strings from standard input
String
[]
a
=
StdIn
.
readAllStrings
();
int
n
=
a
.
length
;
// sort the strings
sort
(
a
);
// print the results
for
(
int
i
=
0
;
i
<
n
;
i
++
)
StdOut
.
println
(
a
[
i
]);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Quick3way.java
edu/princeton/cs/algs4/Quick3way.java
/******************************************************************************
* Compilation: javac Quick3way.java
* Execution: java Quick3way < input.txt
* Dependencies: StdOut.java StdIn.java
* Data files: https://algs4.cs.princeton.edu/23quicksort/tiny.txt
* https://algs4.cs.princeton.edu/23quicksort/words3.txt
*
* Sorts a sequence of strings from standard input using 3-way quicksort.
*
* % more tiny.txt
* S O R T E X A M P L E
*
* % java Quick3way < tiny.txt
* A E E L M O P R S T X [ one string per line ]
*
* % more words3.txt
* bed bug dad yes zoo ... all bad yet
*
* % java Quick3way < words3.txt
* all bad bed bug dad ... yes yet zoo [ one string per line ]
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Quick3way} class provides static methods for sorting an
* array using quicksort with 3-way partitioning.
*
* For additional documentation,
* see Section 2.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Quick3way
{
// This class should not be instantiated.
private
Quick3way
()
{
}
/**
* Rearranges the array in ascending order, using the natural order.
*
@param
a the array to be sorted
*/
public
static
void
sort
(
Comparable
[]
a
)
{
StdRandom
.
shuffle
(
a
);
sort
(
a
,
0
,
a
.
length
–
1
);
assert
isSorted
(
a
);
}
// quicksort the subarray a[lo .. hi] using 3-way partitioning
private
static
void
sort
(
Comparable
[]
a
,
int
lo
,
int
hi
)
{
if
(
hi
<=
lo
)
return
;
int
lt
=
lo
,
gt
=
hi
;
Comparable
v
=
a
[
lo
];
int
i
=
lo
+
1
;
while
(
i
<=
gt
)
{
int
cmp
=
a
[
i
].
compareTo
(
v
);
if
(
cmp
<
0
)
exch
(
a
,
lt
++
,
i
++
);
else
if
(
cmp
>
0
)
exch
(
a
,
i
,
gt
—
);
else
i
++
;
}
// a[lo..lt-1] < v = a[lt..gt] < a[gt+1..hi].
sort
(
a
,
lo
,
lt
-
1
);
sort
(
a
,
gt
+
1
,
hi
);
assert
isSorted
(
a
,
lo
,
hi
);
}
/***************************************************************************
* Helper sorting functions.
***************************************************************************/
// is v < w ?
private
static
boolean
less
(
Comparable
v
,
Comparable
w
)
{
return
v
.
compareTo
(
w
)
<
0
;
}
// exchange a[i] and a[j]
private
static
void
exch
(
Object
[]
a
,
int
i
,
int
j
)
{
Object
swap
=
a
[
i
];
a
[
i
]
=
a
[
j
];
a
[
j
]
=
swap
;
}
/***************************************************************************
* Check if array is sorted - useful for debugging.
***************************************************************************/
private
static
boolean
isSorted
(
Comparable
[]
a
)
{
return
isSorted
(
a
,
0
,
a
.
length
-
1
);
}
private
static
boolean
isSorted
(
Comparable
[]
a
,
int
lo
,
int
hi
)
{
for
(
int
i
=
lo
+
1
;
i
<=
hi
;
i
++
)
if
(
less
(
a
[
i
],
a
[
i
-
1
]))
return
false
;
return
true
;
}
// print array to standard output
private
static
void
show
(
Comparable
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
StdOut
.
println
(
a
[
i
]);
}
}
/**
* Reads in a sequence of strings from standard input; 3-way
* quicksorts them; and prints them to standard output in ascending order.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
[]
a
=
StdIn
.
readAllStrings
();
Quick3way
.
sort
(
a
);
show
(
a
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/QuickBentleyMcIlroy.java
edu/princeton/cs/algs4/QuickBentleyMcIlroy.java
/******************************************************************************
* Compilation: javac QuickBentleyMcIlroy.java
* Execution: java QuickBentleyMcIlroy < input.txt
* Dependencies: StdOut.java StdIn.java
* Data files: https://algs4.cs.princeton.edu/23quicksort/tiny.txt
* https://algs4.cs.princeton.edu/23quicksort/words3.txt
*
* Uses the Bentley-McIlroy 3-way partitioning scheme,
* chooses the partitioning element using Tukey's ninther,
* and cuts off to insertion sort.
*
* Reference: Engineering a Sort Function by Jon L. Bentley
* and M. Douglas McIlroy. Softwae-Practice and Experience,
* Vol. 23 (11), 1249-1265 (November 1993).
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
QuickBentleyMcIlroy} class provides static methods for sorting
* an array using an optimized version of quicksort (using Bentley-McIlroy
* 3-way partitioning, Tukey's ninther, and cutoff to insertion sort).
*
* For additional documentation,
* see Section 2.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
QuickBentleyMcIlroy
{
// cutoff to insertion sort, must be >= 1
private
static
final
int
INSERTION_SORT_CUTOFF
=
8
;
// cutoff to median-of-3 partitioning
private
static
final
int
MEDIAN_OF_3_CUTOFF
=
40
;
// This class should not be instantiated.
private
QuickBentleyMcIlroy
()
{
}
/**
* Rearranges the array in ascending order, using the natural order.
*
@param
a the array to be sorted
*/
public
static
void
sort
(
Comparable
[]
a
)
{
sort
(
a
,
0
,
a
.
length
–
1
);
}
private
static
void
sort
(
Comparable
[]
a
,
int
lo
,
int
hi
)
{
int
n
=
hi
–
lo
+
1
;
// cutoff to insertion sort
if
(
n
<=
INSERTION_SORT_CUTOFF
)
{
insertionSort
(
a
,
lo
,
hi
);
return
;
}
// use median-of-3 as partitioning element
else
if
(
n
<=
MEDIAN_OF_3_CUTOFF
)
{
int
m
=
median3
(
a
,
lo
,
lo
+
n
/
2
,
hi
);
exch
(
a
,
m
,
lo
);
}
// use Tukey ninther as partitioning element
else
{
int
eps
=
n
/
8
;
int
mid
=
lo
+
n
/
2
;
int
m1
=
median3
(
a
,
lo
,
lo
+
eps
,
lo
+
eps
+
eps
);
int
m2
=
median3
(
a
,
mid
-
eps
,
mid
,
mid
+
eps
);
int
m3
=
median3
(
a
,
hi
-
eps
-
eps
,
hi
-
eps
,
hi
);
int
ninther
=
median3
(
a
,
m1
,
m2
,
m3
);
exch
(
a
,
ninther
,
lo
);
}
// Bentley-McIlroy 3-way partitioning
int
i
=
lo
,
j
=
hi
+
1
;
int
p
=
lo
,
q
=
hi
+
1
;
Comparable
v
=
a
[
lo
];
while
(
true
)
{
while
(
less
(
a
[
++
i
],
v
))
if
(
i
==
hi
)
break
;
while
(
less
(
v
,
a
[
--
j
]))
if
(
j
==
lo
)
break
;
// pointers cross
if
(
i
==
j
&&
eq
(
a
[
i
],
v
))
exch
(
a
,
++
p
,
i
);
if
(
i
>=
j
)
break
;
exch
(
a
,
i
,
j
);
if
(
eq
(
a
[
i
],
v
))
exch
(
a
,
++
p
,
i
);
if
(
eq
(
a
[
j
],
v
))
exch
(
a
,
—
q
,
j
);
}
i
=
j
+
1
;
for
(
int
k
=
lo
;
k
<=
p
;
k
++
)
exch
(
a
,
k
,
j
--
);
for
(
int
k
=
hi
;
k
>=
q
;
k
—
)
exch
(
a
,
k
,
i
++
);
sort
(
a
,
lo
,
j
);
sort
(
a
,
i
,
hi
);
}
// sort from a[lo] to a[hi] using insertion sort
private
static
void
insertionSort
(
Comparable
[]
a
,
int
lo
,
int
hi
)
{
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
for
(
int
j
=
i
;
j
>
lo
&&
less
(
a
[
j
],
a
[
j
–
1
]);
j
—
)
exch
(
a
,
j
,
j
–
1
);
}
// return the index of the median element among a[i], a[j], and a[k]
private
static
int
median3
(
Comparable
[]
a
,
int
i
,
int
j
,
int
k
)
{
return
(
less
(
a
[
i
],
a
[
j
])
?
(
less
(
a
[
j
],
a
[
k
])
?
j
:
less
(
a
[
i
],
a
[
k
])
?
k
:
i
)
:
(
less
(
a
[
k
],
a
[
j
])
?
j
:
less
(
a
[
k
],
a
[
i
])
?
k
:
i
));
}
/***************************************************************************
* Helper sorting functions.
***************************************************************************/
// is v < w ?
private
static
boolean
less
(
Comparable
v
,
Comparable
w
)
{
if
(
v
==
w
)
return
false
;
// optimization when reference equal
return
v
.
compareTo
(
w
)
<
0
;
}
// does v == w ?
private
static
boolean
eq
(
Comparable
v
,
Comparable
w
)
{
if
(
v
==
w
)
return
true
;
// optimization when reference equal
return
v
.
compareTo
(
w
)
==
0
;
}
// exchange a[i] and a[j]
private
static
void
exch
(
Object
[]
a
,
int
i
,
int
j
)
{
Object
swap
=
a
[
i
];
a
[
i
]
=
a
[
j
];
a
[
j
]
=
swap
;
}
/***************************************************************************
* Check if array is sorted - useful for debugging.
***************************************************************************/
private
static
boolean
isSorted
(
Comparable
[]
a
)
{
for
(
int
i
=
1
;
i
<
a
.
length
;
i
++
)
if
(
less
(
a
[
i
],
a
[
i
-
1
]))
return
false
;
return
true
;
}
// print array to standard output
private
static
void
show
(
Comparable
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
StdOut
.
println
(
a
[
i
]);
}
}
/**
* Reads in a sequence of strings from standard input; quicksorts them
* (using an optimized version of quicksort);
* and prints them to standard output in ascending order.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
[]
a
=
StdIn
.
readAllStrings
();
QuickBentleyMcIlroy
.
sort
(
a
);
assert
isSorted
(
a
);
show
(
a
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/QuickFindUF.java
edu/princeton/cs/algs4/QuickFindUF.java
/******************************************************************************
* Compilation: javac QuickFindUF.java
* Execution: java QuickFindUF < input.txt
* Dependencies: StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/15uf/tinyUF.txt
* https://algs4.cs.princeton.edu/15uf/mediumUF.txt
* https://algs4.cs.princeton.edu/15uf/largeUF.txt
*
* Quick-find algorithm.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
QuickFindUF} class represents a union–find data type
* (also known as the disjoint-sets data type).
* It supports the classic union and find operations,
* along with a count operation that returns the total number
* of sets.
*
* The union-find data type models a collection of sets containing
* n elements, with each element in exactly one set.
* The elements are named 0 through n–1.
* Initially, there are n sets, with each element in its
* own set. The cannonical elemement of a set
* (also known as the root, identifier,
* leader, or set representative)
* is one distinguished element in the set. Here is a summary of
* the operations:
*
*
* of the set containing p. The find operation
* returns the same value for two elements if and only if
* they are in the same set.
*
* containing element p with the set containing
* element q. That is, if p and q
* are in different sets, replace these two sets
* with a new set that is the union of the two.
*
*
*
* The canonical element of a set can change only when the set
* itself changes during a call to union—it cannot
* change during a call to either find or count.
*
* This implementation uses quick find.
* The constructor takes Θ(n) time, where n
* is the number of sites.
* The find, connected, and count
* operations take Θ(1) time; the union operation
* takes Θ(n) time.
*
* For alternative implementations of the same API, see
* {
@link
UF}, {
@link
QuickUnionUF}, and {
@link
WeightedQuickUnionUF}.
* For additional documentation, see
* Section 1.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
QuickFindUF
{
private
int
[]
id
;
// id[i] = component identifier of i
private
int
count
;
// number of components
/**
* Initializes an empty union-find data structure with
* {
@code
n} elements {
@code
0} through {
@code
n-1}.
* Initially, each elements is in its own set.
*
*
@param
n the number of elements
*
@throws
IllegalArgumentException if {
@code
n < 0}
*/
public
QuickFindUF
(
int
n
)
{
count
=
n
;
id
=
new
int
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
id
[
i
]
=
i
;
}
/**
* Returns the number of sets.
*
*
@return
the number of sets (between {
@code
1} and {
@code
n})
*/
public
int
count
()
{
return
count
;
}
/**
* Returns the canonical element of the set containing element {
@code
p}.
*
*
@param
p an element
*
@return
the canonical element of the set containing {
@code
p}
*
@throws
IllegalArgumentException unless {
@code
0 <= p < n}
*/
public
int
find
(
int
p
)
{
validate
(
p
);
return
id
[
p
];
}
// validate that p is a valid index
private
void
validate
(
int
p
)
{
int
n
=
id
.
length
;
if
(
p
<
0
||
p
>=
n
)
{
throw
new
IllegalArgumentException
(
“index ”
+
p
+
” is not between 0 and ”
+
(
n
–
1
));
}
}
/**
* Returns true if the two elements are in the same set.
*
*
@param
p one element
*
@param
q the other element
*
@return
{
@code
true} if {
@code
p} and {
@code
q} are in the same set;
* {
@code
false} otherwise
*
@throws
IllegalArgumentException unless
* both {
@code
0 <= p < n} and {
@code
0 <= q < n}
*
@deprecated
Replace with two calls to {
@link
#find(int)}.
*/
@
Deprecated
public
boolean
connected
(
int
p
,
int
q
)
{
validate
(
p
);
validate
(
q
);
return
id
[
p
]
==
id
[
q
];
}
/**
* Merges the set containing element {
@code
p} with the
* the set containing element {
@code
q}.
*
*
@param
p one element
*
@param
q the other element
*
@throws
IllegalArgumentException unless
* both {
@code
0 <= p < n} and {
@code
0 <= q < n}
*/
public
void
union
(
int
p
,
int
q
)
{
validate
(
p
);
validate
(
q
);
int
pID
=
id
[
p
];
// needed for correctness
int
qID
=
id
[
q
];
// to reduce the number of array accesses
// p and q are already in the same component
if
(
pID
==
qID
)
return
;
for
(
int
i
=
0
;
i
<
id
.
length
;
i
++
)
if
(
id
[
i
]
==
pID
)
id
[
i
]
=
qID
;
count
--
;
}
/**
* Reads in a an integer {
@code
n} and a sequence of pairs of integers
* (between {
@code
0} and {
@code
n-1}) from standard input, where each integer
* in the pair represents some element;
* if the elements are in different sets, merge the two sets
* and print the pair to standard output.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
n
=
StdIn
.
readInt
();
QuickFindUF
uf
=
new
QuickFindUF
(
n
);
while
(
!
StdIn
.
isEmpty
())
{
int
p
=
StdIn
.
readInt
();
int
q
=
StdIn
.
readInt
();
if
(
uf
.
find
(
p
)
==
uf
.
find
(
q
))
continue
;
uf
.
union
(
p
,
q
);
StdOut
.
println
(
p
+
" "
+
q
);
}
StdOut
.
println
(
uf
.
count
()
+
" components"
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Quick.java
edu/princeton/cs/algs4/Quick.java
/******************************************************************************
* Compilation: javac Quick.java
* Execution: java Quick < input.txt
* Dependencies: StdOut.java StdIn.java
* Data files: https://algs4.cs.princeton.edu/23quicksort/tiny.txt
* https://algs4.cs.princeton.edu/23quicksort/words3.txt
*
* Sorts a sequence of strings from standard input using quicksort.
*
* % more tiny.txt
* S O R T E X A M P L E
*
* % java Quick < tiny.txt
* A E E L M O P R S T X [ one string per line ]
*
* % more words3.txt
* bed bug dad yes zoo ... all bad yet
*
* % java Quick < words3.txt
* all bad bed bug dad ... yes yet zoo [ one string per line ]
*
*
* Remark: For a type-safe version that uses static generics, see
*
* https://algs4.cs.princeton.edu/23quicksort/QuickPedantic.java
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Quick} class provides static methods for sorting an
* array and selecting the ith smallest element in an array using quicksort.
*
* For additional documentation,
* see Section 2.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Quick
{
// This class should not be instantiated.
private
Quick
()
{
}
/**
* Rearranges the array in ascending order, using the natural order.
*
@param
a the array to be sorted
*/
public
static
void
sort
(
Comparable
[]
a
)
{
StdRandom
.
shuffle
(
a
);
sort
(
a
,
0
,
a
.
length
–
1
);
assert
isSorted
(
a
);
}
// quicksort the subarray from a[lo] to a[hi]
private
static
void
sort
(
Comparable
[]
a
,
int
lo
,
int
hi
)
{
if
(
hi
<=
lo
)
return
;
int
j
=
partition
(
a
,
lo
,
hi
);
sort
(
a
,
lo
,
j
-
1
);
sort
(
a
,
j
+
1
,
hi
);
assert
isSorted
(
a
,
lo
,
hi
);
}
// partition the subarray a[lo..hi] so that a[lo..j-1] <= a[j] <= a[j+1..hi]
// and return the index j.
private
static
int
partition
(
Comparable
[]
a
,
int
lo
,
int
hi
)
{
int
i
=
lo
;
int
j
=
hi
+
1
;
Comparable
v
=
a
[
lo
];
while
(
true
)
{
// find item on lo to swap
while
(
less
(
a
[
++
i
],
v
))
{
if
(
i
==
hi
)
break
;
}
// find item on hi to swap
while
(
less
(
v
,
a
[
--
j
]))
{
if
(
j
==
lo
)
break
;
// redundant since a[lo] acts as sentinel
}
// check if pointers cross
if
(
i
>=
j
)
break
;
exch
(
a
,
i
,
j
);
}
// put partitioning item v at a[j]
exch
(
a
,
lo
,
j
);
// now, a[lo .. j-1] <= a[j] <= a[j+1 .. hi]
return
j
;
}
/**
* Rearranges the array so that {
@code
a[k]} contains the kth smallest key;
* {
@code
a[0]} through {
@code
a[k-1]} are less than (or equal to) {
@code
a[k]}; and
* {
@code
a[k+1]} through {
@code
a[n-1]} are greater than (or equal to) {
@code
a[k]}.
*
*
@param
a the array
*
@param
k the rank of the key
*
@return
the key of rank {
@code
k}
*
@throws
IllegalArgumentException unless {
@code
0 <= k < a.length}
*/
public
static
Comparable
select
(
Comparable
[]
a
,
int
k
)
{
if
(
k
<
0
||
k
>=
a
.
length
)
{
throw
new
IllegalArgumentException
(
“index is not between 0 and ”
+
a
.
length
+
“: ”
+
k
);
}
StdRandom
.
shuffle
(
a
);
int
lo
=
0
,
hi
=
a
.
length
–
1
;
while
(
hi
>
lo
)
{
int
i
=
partition
(
a
,
lo
,
hi
);
if
(
i
>
k
)
hi
=
i
–
1
;
else
if
(
i
<
k
)
lo
=
i
+
1
;
else
return
a
[
i
];
}
return
a
[
lo
];
}
/***************************************************************************
* Helper sorting functions.
***************************************************************************/
// is v < w ?
private
static
boolean
less
(
Comparable
v
,
Comparable
w
)
{
if
(
v
==
w
)
return
false
;
// optimization when reference equals
return
v
.
compareTo
(
w
)
<
0
;
}
// exchange a[i] and a[j]
private
static
void
exch
(
Object
[]
a
,
int
i
,
int
j
)
{
Object
swap
=
a
[
i
];
a
[
i
]
=
a
[
j
];
a
[
j
]
=
swap
;
}
/***************************************************************************
* Check if array is sorted - useful for debugging.
***************************************************************************/
private
static
boolean
isSorted
(
Comparable
[]
a
)
{
return
isSorted
(
a
,
0
,
a
.
length
-
1
);
}
private
static
boolean
isSorted
(
Comparable
[]
a
,
int
lo
,
int
hi
)
{
for
(
int
i
=
lo
+
1
;
i
<=
hi
;
i
++
)
if
(
less
(
a
[
i
],
a
[
i
-
1
]))
return
false
;
return
true
;
}
// print array to standard output
private
static
void
show
(
Comparable
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
StdOut
.
println
(
a
[
i
]);
}
}
/**
* Reads in a sequence of strings from standard input; quicksorts them;
* and prints them to standard output in ascending order.
* Shuffles the array and then prints the strings again to
* standard output, but this time, using the select method.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
[]
a
=
StdIn
.
readAllStrings
();
Quick
.
sort
(
a
);
show
(
a
);
assert
isSorted
(
a
);
// shuffle
StdRandom
.
shuffle
(
a
);
// display results again using select
StdOut
.
println
();
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
String
ith
=
(
String
)
Quick
.
select
(
a
,
i
);
StdOut
.
println
(
ith
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/QuickUnionUF.java
edu/princeton/cs/algs4/QuickUnionUF.java
/******************************************************************************
* Compilation: javac QuickUnionUF.java
* Execution: java QuickUnionUF < input.txt
* Dependencies: StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/15uf/tinyUF.txt
* https://algs4.cs.princeton.edu/15uf/mediumUF.txt
* https://algs4.cs.princeton.edu/15uf/largeUF.txt
*
* Quick-union algorithm.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
QuickUnionUF} class represents a union–find data type
* (also known as the disjoint-sets data type).
* It supports the classic union and find operations,
* along with a count operation that returns the total number
* of sets.
*
* The union-find data type models a collection of sets containing
* n elements, with each element in exactly one set.
* The elements are named 0 through n–1.
* Initially, there are n sets, with each element in its
* own set. The cannonical elemement of a set
* (also known as the root, identifier,
* leader, or set representative)
* is one distinguished element in the set. Here is a summary of
* the operations:
*
*
* of the set containing p. The find operation
* returns the same value for two elements if and only if
* they are in the same set.
*
* containing element p with the set containing
* element q. That is, if p and q
* are in different sets, replace these two sets
* with a new set that is the union of the two.
*
*
*
* The canonical element of a set can change only when the set
* itself changes during a call to union—it cannot
* change during a call to either find or count.
*
* This implementation uses quick union.
* The constructor takes Θ(n) time, where
* n is the number of sites.
* The union and find operations take
* Θ(n) time in the worst case.
* The count operation takes Θ(1) time.
*
* For alternative implementations of the same API, see
* {
@link
UF}, {
@link
QuickFindUF}, and {
@link
WeightedQuickUnionUF}.
* For additional documentation,
* see Section 1.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
QuickUnionUF
{
private
int
[]
parent
;
// parent[i] = parent of i
private
int
count
;
// number of components
/**
* Initializes an empty union-find data structure with
* {
@code
n} elements {
@code
0} through {
@code
n-1}.
* Initially, each elements is in its own set.
*
*
@param
n the number of elements
*
@throws
IllegalArgumentException if {
@code
n < 0}
*/
public
QuickUnionUF
(
int
n
)
{
parent
=
new
int
[
n
];
count
=
n
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
parent
[
i
]
=
i
;
}
}
/**
* Returns the number of sets.
*
*
@return
the number of sets (between {
@code
1} and {
@code
n})
*/
public
int
count
()
{
return
count
;
}
/**
* Returns the canonical element of the set containing element {
@code
p}.
*
*
@param
p an element
*
@return
the canonical element of the set containing {
@code
p}
*
@throws
IllegalArgumentException unless {
@code
0 <= p < n}
*/
public
int
find
(
int
p
)
{
validate
(
p
);
while
(
p
!=
parent
[
p
])
p
=
parent
[
p
];
return
p
;
}
// validate that p is a valid index
private
void
validate
(
int
p
)
{
int
n
=
parent
.
length
;
if
(
p
<
0
||
p
>=
n
)
{
throw
new
IllegalArgumentException
(
“index ”
+
p
+
” is not between 0 and ”
+
(
n
–
1
));
}
}
/**
* Returns true if the two elements are in the same set.
*
*
@param
p one element
*
@param
q the other element
*
@return
{
@code
true} if {
@code
p} and {
@code
q} are in the same set;
* {
@code
false} otherwise
*
@throws
IllegalArgumentException unless
* both {
@code
0 <= p < n} and {
@code
0 <= q < n}
*
@deprecated
Replace with two calls to {
@link
#find(int)}.
*/
@
Deprecated
public
boolean
connected
(
int
p
,
int
q
)
{
return
find
(
p
)
==
find
(
q
);
}
/**
* Merges the set containing element {
@code
p} with the
* the set containing element {
@code
q}.
*
*
@param
p one element
*
@param
q the other element
*
@throws
IllegalArgumentException unless
* both {
@code
0 <= p < n} and {
@code
0 <= q < n}
*/
public
void
union
(
int
p
,
int
q
)
{
int
rootP
=
find
(
p
);
int
rootQ
=
find
(
q
);
if
(
rootP
==
rootQ
)
return
;
parent
[
rootP
]
=
rootQ
;
count
--
;
}
/**
* Reads in a an integer {
@code
n} and a sequence of pairs of integers
* (between {
@code
0} and {
@code
n-1}) from standard input, where each integer
* in the pair represents some element;
* if the elements are in different sets, merge the two sets
* and print the pair to standard output.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
n
=
StdIn
.
readInt
();
QuickUnionUF
uf
=
new
QuickUnionUF
(
n
);
while
(
!
StdIn
.
isEmpty
())
{
int
p
=
StdIn
.
readInt
();
int
q
=
StdIn
.
readInt
();
if
(
uf
.
find
(
p
)
==
uf
.
find
(
q
))
continue
;
uf
.
union
(
p
,
q
);
StdOut
.
println
(
p
+
" "
+
q
);
}
StdOut
.
println
(
uf
.
count
()
+
" components"
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/QuickX.java
edu/princeton/cs/algs4/QuickX.java
/******************************************************************************
* Compilation: javac QuickX.java
* Execution: java QuickX < input.txt
* Dependencies: StdOut.java StdIn.java
* Data files: https://algs4.cs.princeton.edu/23quicksort/tiny.txt
* https://algs4.cs.princeton.edu/23quicksort/words3.txt
*
* Uses the Hoare's 2-way partitioning scheme, chooses the partitioning
* element using median-of-3, and cuts off to insertion sort.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
QuickX} class provides static methods for sorting an array
* using an optimized version of quicksort (using Hoare's 2-way partitioning
* algorithm, median-of-3 to choose the partitioning element, and cutoff
* to insertion sort).
*
* For additional documentation,
* see Section 2.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
QuickX
{
// cutoff to insertion sort, must be >= 1
private
static
final
int
INSERTION_SORT_CUTOFF
=
8
;
// This class should not be instantiated.
private
QuickX
()
{
}
/**
* Rearranges the array in ascending order, using the natural order.
*
@param
a the array to be sorted
*/
public
static
void
sort
(
Comparable
[]
a
)
{
// StdRandom.shuffle(a);
sort
(
a
,
0
,
a
.
length
–
1
);
assert
isSorted
(
a
);
}
// quicksort the subarray from a[lo] to a[hi]
private
static
void
sort
(
Comparable
[]
a
,
int
lo
,
int
hi
)
{
if
(
hi
<=
lo
)
return
;
// cutoff to insertion sort (Insertion.sort() uses half-open intervals)
int
n
=
hi
-
lo
+
1
;
if
(
n
<=
INSERTION_SORT_CUTOFF
)
{
Insertion
.
sort
(
a
,
lo
,
hi
+
1
);
return
;
}
int
j
=
partition
(
a
,
lo
,
hi
);
sort
(
a
,
lo
,
j
-
1
);
sort
(
a
,
j
+
1
,
hi
);
}
// partition the subarray a[lo..hi] so that a[lo..j-1] <= a[j] <= a[j+1..hi]
// and return the index j.
private
static
int
partition
(
Comparable
[]
a
,
int
lo
,
int
hi
)
{
int
n
=
hi
-
lo
+
1
;
int
m
=
median3
(
a
,
lo
,
lo
+
n
/
2
,
hi
);
exch
(
a
,
m
,
lo
);
int
i
=
lo
;
int
j
=
hi
+
1
;
Comparable
v
=
a
[
lo
];
// a[lo] is unique largest element
while
(
less
(
a
[
++
i
],
v
))
{
if
(
i
==
hi
)
{
exch
(
a
,
lo
,
hi
);
return
hi
;
}
}
// a[lo] is unique smallest element
while
(
less
(
v
,
a
[
--
j
]))
{
if
(
j
==
lo
+
1
)
return
lo
;
}
// the main loop
while
(
i
<
j
)
{
exch
(
a
,
i
,
j
);
while
(
less
(
a
[
++
i
],
v
))
;
while
(
less
(
v
,
a
[
--
j
]))
;
}
// put partitioning item v at a[j]
exch
(
a
,
lo
,
j
);
// now, a[lo .. j-1] <= a[j] <= a[j+1 .. hi]
return
j
;
}
// return the index of the median element among a[i], a[j], and a[k]
private
static
int
median3
(
Comparable
[]
a
,
int
i
,
int
j
,
int
k
)
{
return
(
less
(
a
[
i
],
a
[
j
])
?
(
less
(
a
[
j
],
a
[
k
])
?
j
:
less
(
a
[
i
],
a
[
k
])
?
k
:
i
)
:
(
less
(
a
[
k
],
a
[
j
])
?
j
:
less
(
a
[
k
],
a
[
i
])
?
k
:
i
));
}
/***************************************************************************
* Helper sorting functions.
***************************************************************************/
// is v < w ?
private
static
boolean
less
(
Comparable
v
,
Comparable
w
)
{
return
v
.
compareTo
(
w
)
<
0
;
}
// exchange a[i] and a[j]
private
static
void
exch
(
Object
[]
a
,
int
i
,
int
j
)
{
Object
swap
=
a
[
i
];
a
[
i
]
=
a
[
j
];
a
[
j
]
=
swap
;
}
/***************************************************************************
* Check if array is sorted - useful for debugging.
***************************************************************************/
private
static
boolean
isSorted
(
Comparable
[]
a
)
{
for
(
int
i
=
1
;
i
<
a
.
length
;
i
++
)
if
(
less
(
a
[
i
],
a
[
i
-
1
]))
return
false
;
return
true
;
}
// print array to standard output
private
static
void
show
(
Comparable
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
StdOut
.
println
(
a
[
i
]);
}
}
/**
* Reads in a sequence of strings from standard input; quicksorts them
* (using an optimized version of 2-way quicksort);
* and prints them to standard output in ascending order.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
[]
a
=
StdIn
.
readAllStrings
();
QuickX
.
sort
(
a
);
assert
isSorted
(
a
);
show
(
a
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/RabinKarp.java
edu/princeton/cs/algs4/RabinKarp.java
/******************************************************************************
* Compilation: javac RabinKarp.java
* Execution: java RabinKarp pat txt
* Dependencies: StdOut.java
*
* Reads in two strings, the pattern and the input text, and
* searches for the pattern in the input text using the
* Las Vegas version of the Rabin-Karp algorithm.
*
* % java RabinKarp abracadabra abacadabrabracabracadabrabrabracad
* pattern: abracadabra
* text: abacadabrabracabracadabrabrabracad
* match: abracadabra
*
* % java RabinKarp rab abacadabrabracabracadabrabrabracad
* pattern: rab
* text: abacadabrabracabracadabrabrabracad
* match: rab
*
* % java RabinKarp bcara abacadabrabracabracadabrabrabracad
* pattern: bcara
* text: abacadabrabracabracadabrabrabracad
*
* % java RabinKarp rabrabracad abacadabrabracabracadabrabrabracad
* text: abacadabrabracabracadabrabrabracad
* pattern: rabrabracad
*
* % java RabinKarp abacad abacadabrabracabracadabrabrabracad
* text: abacadabrabracabracadabrabrabracad
* pattern: abacad
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
math
.
BigInteger
;
import
java
.
util
.
Random
;
/**
* The {
@code
RabinKarp} class finds the first occurrence of a pattern string
* in a text string.
*
* This implementation uses the Rabin-Karp algorithm.
*
* For additional documentation,
* see Section 5.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*/
public
class
RabinKarp
{
private
String
pat
;
// the pattern // needed only for Las Vegas
private
long
patHash
;
// pattern hash value
private
int
m
;
// pattern length
private
long
q
;
// a large prime, small enough to avoid long overflow
private
int
R
;
// radix
private
long
RM
;
// R^(M-1) % Q
/**
* Preprocesses the pattern string.
*
*
@param
pattern the pattern string
*
@param
R the alphabet size
*/
public
RabinKarp
(
char
[]
pattern
,
int
R
)
{
this
.
pat
=
String
.
valueOf
(
pattern
);
this
.
R
=
R
;
throw
new
UnsupportedOperationException
(
“Operation not supported yet”
);
}
/**
* Preprocesses the pattern string.
*
*
@param
pat the pattern string
*/
public
RabinKarp
(
String
pat
)
{
this
.
pat
=
pat
;
// save pattern (needed only for Las Vegas)
R
=
256
;
m
=
pat
.
length
();
q
=
longRandomPrime
();
// precompute R^(m-1) % q for use in removing leading digit
RM
=
1
;
for
(
int
i
=
1
;
i
<=
m
-
1
;
i
++
)
RM
=
(
R
*
RM
)
%
q
;
patHash
=
hash
(
pat
,
m
);
}
// Compute hash for key[0..m-1].
private
long
hash
(
String
key
,
int
m
)
{
long
h
=
0
;
for
(
int
j
=
0
;
j
<
m
;
j
++
)
h
=
(
R
*
h
+
key
.
charAt
(
j
))
%
q
;
return
h
;
}
// Las Vegas version: does pat[] match txt[i..i-m+1] ?
private
boolean
check
(
String
txt
,
int
i
)
{
for
(
int
j
=
0
;
j
<
m
;
j
++
)
if
(
pat
.
charAt
(
j
)
!=
txt
.
charAt
(
i
+
j
))
return
false
;
return
true
;
}
// Monte Carlo version: always return true
// private boolean check(int i) {
// return true;
//}
/**
* Returns the index of the first occurrrence of the pattern string
* in the text string.
*
*
@param
txt the text string
*
@return
the index of the first occurrence of the pattern string
* in the text string; n if no such match
*/
public
int
search
(
String
txt
)
{
int
n
=
txt
.
length
();
if
(
n
<
m
)
return
n
;
long
txtHash
=
hash
(
txt
,
m
);
// check for match at offset 0
if
((
patHash
==
txtHash
)
&&
check
(
txt
,
0
))
return
0
;
// check for hash match; if hash match, check for exact match
for
(
int
i
=
m
;
i
<
n
;
i
++
)
{
// Remove leading digit, add trailing digit, check for match.
txtHash
=
(
txtHash
+
q
-
RM
*
txt
.
charAt
(
i
-
m
)
%
q
)
%
q
;
txtHash
=
(
txtHash
*
R
+
txt
.
charAt
(
i
))
%
q
;
// match
int
offset
=
i
-
m
+
1
;
if
((
patHash
==
txtHash
)
&&
check
(
txt
,
offset
))
return
offset
;
}
// no match
return
n
;
}
// a random 31-bit prime
private
static
long
longRandomPrime
()
{
BigInteger
prime
=
BigInteger
.
probablePrime
(
31
,
new
Random
());
return
prime
.
longValue
();
}
/**
* Takes a pattern string and an input string as command-line arguments;
* searches for the pattern string in the text string; and prints
* the first occurrence of the pattern string in the text string.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
pat
=
args
[
0
];
String
txt
=
args
[
1
];
RabinKarp
searcher
=
new
RabinKarp
(
pat
);
int
offset
=
searcher
.
search
(
txt
);
// print results
StdOut
.
println
(
"text: "
+
txt
);
// from brute force search method 1
StdOut
.
print
(
"pattern: "
);
for
(
int
i
=
0
;
i
<
offset
;
i
++
)
StdOut
.
print
(
" "
);
StdOut
.
println
(
pat
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/RandomSeq.java
edu/princeton/cs/algs4/RandomSeq.java
/******************************************************************************
* Compilation: javac RandomSeq.java
* Execution: java RandomSeq n lo hi
* Dependencies: StdOut.java
*
* Prints N numbers between lo and hi.
*
* % java RandomSeq 5 100.0 200.0
* 123.43
* 153.13
* 144.38
* 155.18
* 104.02
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
RandomSeq} class is a client that prints out a pseudorandom
* sequence of real numbers in a given range.
*
* For additional documentation, see Section 1.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
RandomSeq
{
// this class should not be instantiated
private
RandomSeq
()
{
}
/**
* Reads in two command-line arguments lo and hi and prints n uniformly
* random real numbers in [lo, hi) to standard output.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// command-line arguments
int
n
=
Integer
.
parseInt
(
args
[
0
]);
// for backward compatibility with Intro to Programming in Java version of RandomSeq
if
(
args
.
length
==
1
)
{
// generate and print n numbers between 0.0 and 1.0
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
double
x
=
StdRandom
.
uniform
();
StdOut
.
println
(
x
);
}
}
else
if
(
args
.
length
==
3
)
{
double
lo
=
Double
.
parseDouble
(
args
[
1
]);
double
hi
=
Double
.
parseDouble
(
args
[
2
]);
// generate and print n numbers between lo and hi
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
double
x
=
StdRandom
.
uniform
(
lo
,
hi
);
StdOut
.
printf
(
"%.2f\n"
,
x
);
}
}
else
{
throw
new
IllegalArgumentException
(
"Invalid number of arguments"
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/RectHV.java
edu/princeton/cs/algs4/RectHV.java
/******************************************************************************
* Compilation: javac RectHV.java
* Execution: none
* Dependencies: Point2D.java
*
* Immutable data type for 2D axis-aligned rectangle.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
RectHV} class is an immutable data type to encapsulate a
* two-dimensional axis-aligned rectagle with real-value coordinates.
* The rectangle is closed—it includes the points on the boundary.
*
* For additional documentation,
* see Section 1.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
RectHV
{
private
final
double
xmin
,
ymin
;
// minimum x- and y-coordinates
private
final
double
xmax
,
ymax
;
// maximum x- and y-coordinates
/**
* Initializes a new rectangle [xmin, xmax]
* x [ymin, ymax].
*
*
@param
xmin the x-coordinate of the lower-left endpoint
*
@param
xmax the x-coordinate of the upper-right endpoint
*
@param
ymin the y-coordinate of the lower-left endpoint
*
@param
ymax the y-coordinate of the upper-right endpoint
*
@throws
IllegalArgumentException if any of {
@code
xmin},
* {
@code
xmax}, {
@code
ymin}, or {
@code
ymax}
* is {
@code
Double.NaN}.
*
@throws
IllegalArgumentException if {
@code
xmax < xmin} or {
@code
ymax < ymin}.
*/
public
RectHV
(
double
xmin
,
double
ymin
,
double
xmax
,
double
ymax
)
{
this
.
xmin
=
xmin
;
this
.
ymin
=
ymin
;
this
.
xmax
=
xmax
;
this
.
ymax
=
ymax
;
if
(
Double
.
isNaN
(
xmin
)
||
Double
.
isNaN
(
xmax
))
{
throw
new
IllegalArgumentException
(
"x-coordinate is NaN: "
+
toString
());
}
if
(
Double
.
isNaN
(
ymin
)
||
Double
.
isNaN
(
ymax
))
{
throw
new
IllegalArgumentException
(
"y-coordinate is NaN: "
+
toString
());
}
if
(
xmax
<
xmin
)
{
throw
new
IllegalArgumentException
(
"xmax < xmin: "
+
toString
());
}
if
(
ymax
<
ymin
)
{
throw
new
IllegalArgumentException
(
"ymax < ymin: "
+
toString
());
}
}
/**
* Returns the minimum x-coordinate of any point in this rectangle.
*
*
@return
the minimum x-coordinate of any point in this rectangle
*/
public
double
xmin
()
{
return
xmin
;
}
/**
* Returns the maximum x-coordinate of any point in this rectangle.
*
*
@return
the maximum x-coordinate of any point in this rectangle
*/
public
double
xmax
()
{
return
xmax
;
}
/**
* Returns the minimum y-coordinate of any point in this rectangle.
*
*
@return
the minimum y-coordinate of any point in this rectangle
*/
public
double
ymin
()
{
return
ymin
;
}
/**
* Returns the maximum y-coordinate of any point in this rectangle.
*
*
@return
the maximum y-coordinate of any point in this rectangle
*/
public
double
ymax
()
{
return
ymax
;
}
/**
* Returns the width of this rectangle.
*
*
@return
the width of this rectangle {
@code
xmax – xmin}
*/
public
double
width
()
{
return
xmax
–
xmin
;
}
/**
* Returns the height of this rectangle.
*
*
@return
the height of this rectangle {
@code
ymax – ymin}
*/
public
double
height
()
{
return
ymax
–
ymin
;
}
/**
* Returns true if the two rectangles intersect. This includes
* improper intersections (at points on the boundary
* of each rectangle) and nested intersctions
* (when one rectangle is contained inside the other)
*
*
@param
that the other rectangle
*
@return
{
@code
true} if this rectangle intersect the argument
rectangle at one or more points
*/
public
boolean
intersects
(
RectHV
that
)
{
return
this
.
xmax
>=
that
.
xmin
&&
this
.
ymax
>=
that
.
ymin
&&
that
.
xmax
>=
this
.
xmin
&&
that
.
ymax
>=
this
.
ymin
;
}
/**
* Returns true if this rectangle contain the point.
*
@param
p the point
*
@return
{
@code
true} if this rectangle contain the point {
@code
p},
possibly at the boundary; {
@code
false} otherwise
*/
public
boolean
contains
(
Point2D
p
)
{
return
(
p
.
x
()
>=
xmin
)
&&
(
p
.
x
()
<=
xmax
)
&&
(
p
.
y
()
>=
ymin
)
&&
(
p
.
y
()
<=
ymax
);
}
/**
* Returns the Euclidean distance between this rectangle and the point {
@code
p}.
*
*
@param
p the point
*
@return
the Euclidean distance between the point {
@code
p} and the closest point
on this rectangle; 0 if the point is contained in this rectangle
*/
public
double
distanceTo
(
Point2D
p
)
{
return
Math
.
sqrt
(
this
.
distanceSquaredTo
(
p
));
}
/**
* Returns the square of the Euclidean distance between this rectangle and the point {
@code
p}.
*
*
@param
p the point
*
@return
the square of the Euclidean distance between the point {
@code
p} and
* the closest point on this rectangle; 0 if the point is contained
* in this rectangle
*/
public
double
distanceSquaredTo
(
Point2D
p
)
{
double
dx
=
0.0
,
dy
=
0.0
;
if
(
p
.
x
()
<
xmin
)
dx
=
p
.
x
()
-
xmin
;
else
if
(
p
.
x
()
>
xmax
)
dx
=
p
.
x
()
–
xmax
;
if
(
p
.
y
()
<
ymin
)
dy
=
p
.
y
()
-
ymin
;
else
if
(
p
.
y
()
>
ymax
)
dy
=
p
.
y
()
–
ymax
;
return
dx
*
dx
+
dy
*
dy
;
}
/**
* Compares this rectangle to the specified rectangle.
*
*
@param
other the other rectangle
*
@return
{
@code
true} if this rectangle equals {
@code
other};
* {
@code
false} otherwise
*/
@
Override
public
boolean
equals
(
Object
other
)
{
if
(
other
==
this
)
return
true
;
if
(
other
==
null
)
return
false
;
if
(
other
.
getClass
()
!=
this
.
getClass
())
return
false
;
RectHV
that
=
(
RectHV
)
other
;
if
(
this
.
xmin
!=
that
.
xmin
)
return
false
;
if
(
this
.
ymin
!=
that
.
ymin
)
return
false
;
if
(
this
.
xmax
!=
that
.
xmax
)
return
false
;
if
(
this
.
ymax
!=
that
.
ymax
)
return
false
;
return
true
;
}
/**
* Returns an integer hash code for this rectangle.
*
@return
an integer hash code for this rectangle
*/
@
Override
public
int
hashCode
()
{
int
hash1
=
((
Double
)
xmin
).
hashCode
();
int
hash2
=
((
Double
)
ymin
).
hashCode
();
int
hash3
=
((
Double
)
xmax
).
hashCode
();
int
hash4
=
((
Double
)
ymax
).
hashCode
();
return
31
*
(
31
*
(
31
*
hash1
+
hash2
)
+
hash3
)
+
hash4
;
}
/**
* Returns a string representation of this rectangle.
*
*
@return
a string representation of this rectangle, using the format
* {
@code
[xmin, xmax] x [ymin, ymax]}
*/
@
Override
public
String
toString
()
{
return
“[”
+
xmin
+
“, ”
+
xmax
+
“] x [”
+
ymin
+
“, ”
+
ymax
+
“]”
;
}
/**
* Draws this rectangle to standard draw.
*/
public
void
draw
()
{
StdDraw
.
line
(
xmin
,
ymin
,
xmax
,
ymin
);
StdDraw
.
line
(
xmax
,
ymin
,
xmax
,
ymax
);
StdDraw
.
line
(
xmax
,
ymax
,
xmin
,
ymax
);
StdDraw
.
line
(
xmin
,
ymax
,
xmin
,
ymin
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/RedBlackBST.java
edu/princeton/cs/algs4/RedBlackBST.java
/******************************************************************************
* Compilation: javac RedBlackBST.java
* Execution: java RedBlackBST < input.txt * Dependencies: StdIn.java StdOut.java * Data files: https://algs4.cs.princeton.edu/33balanced/tinyST.txt * * A symbol table implemented using a left-leaning red-black BST. * This is the 2-3 version. * * Note: commented out assertions because DrJava now enables assertions * by default. * * % more tinyST.txt * S E A R C H E X A M P L E * * % java RedBlackBST < tinyST.txt * A 8 * C 4 * E 12 * H 5 * L 11 * M 9 * P 10 * R 3 * S 0 * X 7 * ******************************************************************************/ package edu . princeton . cs . algs4 ; import java . util . NoSuchElementException ; /** * The { @code BST} class represents an ordered symbol table of generic * key-value pairs. * It supports the usual put, get, contains,
* delete, size, and is-empty methods.
* It also provides ordered methods for finding the minimum,
* maximum, floor, and ceiling.
* It also provides a keys method for iterating over all of the keys.
* A symbol table implements the associative array abstraction:
* when associating a value with a key that is already in the symbol table,
* the convention is to replace the old value with the new value.
* Unlike {
@link
java.util.Map}, this class uses the convention that
* values cannot be {
@code
null}—setting the
* value associated with a key to {
@code
null} is equivalent to deleting the key
* from the symbol table.
*
* It requires that
* the key type implements the {
@code
Comparable} interface and calls the
* {
@code
compareTo()} and method to compare two keys. It does not call either
* {
@code
equals()} or {
@code
hashCode()}.
*
* This implementation uses a left-leaning red-black BST.
* The put, get, contains, remove,
* minimum, maximum, ceiling, floor,
* rank, and select operations each take
* Θ(log n) time in the worst case, where n is the
* number of key-value pairs in the symbol table.
* The size, and is-empty operations take Θ(1) time.
* The keys methods take
* O(log n + m) time, where m is
* the number of keys returned by the iterator.
* Construction takes Θ(1) time.
*
* For alternative implementations of the symbol table API, see {
@link
ST},
* {
@link
BinarySearchST}, {
@link
SequentialSearchST}, {
@link
BST},
* {
@link
SeparateChainingHashST}, {
@link
LinearProbingHashST}, and
* {
@link
AVLTreeST}.
* For additional documentation, see
* Section 3.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
RedBlackBST
<
Key
extends
Comparable
<
Key
>
,
Value
>
{
private
static
final
boolean
RED
=
true
;
private
static
final
boolean
BLACK
=
false
;
private
Node
root
;
// root of the BST
// BST helper node data type
private
class
Node
{
private
Key
key
;
// key
private
Value
val
;
// associated data
private
Node
left
,
right
;
// links to left and right subtrees
private
boolean
color
;
// color of parent link
private
int
size
;
// subtree count
public
Node
(
Key
key
,
Value
val
,
boolean
color
,
int
size
)
{
this
.
key
=
key
;
this
.
val
=
val
;
this
.
color
=
color
;
this
.
size
=
size
;
}
}
/**
* Initializes an empty symbol table.
*/
public
RedBlackBST
()
{
}
/***************************************************************************
* Node helper methods.
***************************************************************************/
// is node x red; false if x is null ?
private
boolean
isRed
(
Node
x
)
{
if
(
x
==
null
)
return
false
;
return
x
.
color
==
RED
;
}
// number of node in subtree rooted at x; 0 if x is null
private
int
size
(
Node
x
)
{
if
(
x
==
null
)
return
0
;
return
x
.
size
;
}
/**
* Returns the number of key-value pairs in this symbol table.
*
@return
the number of key-value pairs in this symbol table
*/
public
int
size
()
{
return
size
(
root
);
}
/**
* Is this symbol table empty?
*
@return
{
@code
true} if this symbol table is empty and {
@code
false} otherwise
*/
public
boolean
isEmpty
()
{
return
root
==
null
;
}
/***************************************************************************
* Standard BST search.
***************************************************************************/
/**
* Returns the value associated with the given key.
*
@param
key the key
*
@return
the value associated with the given key if the key is in the symbol table
* and {
@code
null} if the key is not in the symbol table
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
Value
get
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to get() is null”
);
return
get
(
root
,
key
);
}
// value associated with the given key in subtree rooted at x; null if no such key
private
Value
get
(
Node
x
,
Key
key
)
{
while
(
x
!=
null
)
{
int
cmp
=
key
.
compareTo
(
x
.
key
);
if
(
cmp
<
0
)
x
=
x
.
left
;
else
if
(
cmp
>
0
)
x
=
x
.
right
;
else
return
x
.
val
;
}
return
null
;
}
/**
* Does this symbol table contain the given key?
*
@param
key the key
*
@return
{
@code
true} if this symbol table contains {
@code
key} and
* {
@code
false} otherwise
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
boolean
contains
(
Key
key
)
{
return
get
(
key
)
!=
null
;
}
/***************************************************************************
* Red-black tree insertion.
***************************************************************************/
/**
* Inserts the specified key-value pair into the symbol table, overwriting the old
* value with the new value if the symbol table already contains the specified key.
* Deletes the specified key (and its associated value) from this symbol table
* if the specified value is {
@code
null}.
*
*
@param
key the key
*
@param
val the value
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
put
(
Key
key
,
Value
val
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“first argument to put() is null”
);
if
(
val
==
null
)
{
delete
(
key
);
return
;
}
root
=
put
(
root
,
key
,
val
);
root
.
color
=
BLACK
;
// assert check();
}
// insert the key-value pair in the subtree rooted at h
private
Node
put
(
Node
h
,
Key
key
,
Value
val
)
{
if
(
h
==
null
)
return
new
Node
(
key
,
val
,
RED
,
1
);
int
cmp
=
key
.
compareTo
(
h
.
key
);
if
(
cmp
<
0
)
h
.
left
=
put
(
h
.
left
,
key
,
val
);
else
if
(
cmp
>
0
)
h
.
right
=
put
(
h
.
right
,
key
,
val
);
else
h
.
val
=
val
;
// fix-up any right-leaning links
if
(
isRed
(
h
.
right
)
&&
!
isRed
(
h
.
left
))
h
=
rotateLeft
(
h
);
if
(
isRed
(
h
.
left
)
&&
isRed
(
h
.
left
.
left
))
h
=
rotateRight
(
h
);
if
(
isRed
(
h
.
left
)
&&
isRed
(
h
.
right
))
flipColors
(
h
);
h
.
size
=
size
(
h
.
left
)
+
size
(
h
.
right
)
+
1
;
return
h
;
}
/***************************************************************************
* Red-black tree deletion.
***************************************************************************/
/**
* Removes the smallest key and associated value from the symbol table.
*
@throws
NoSuchElementException if the symbol table is empty
*/
public
void
deleteMin
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“BST underflow”
);
// if both children of root are black, set root to red
if
(
!
isRed
(
root
.
left
)
&&
!
isRed
(
root
.
right
))
root
.
color
=
RED
;
root
=
deleteMin
(
root
);
if
(
!
isEmpty
())
root
.
color
=
BLACK
;
// assert check();
}
// delete the key-value pair with the minimum key rooted at h
private
Node
deleteMin
(
Node
h
)
{
if
(
h
.
left
==
null
)
return
null
;
if
(
!
isRed
(
h
.
left
)
&&
!
isRed
(
h
.
left
.
left
))
h
=
moveRedLeft
(
h
);
h
.
left
=
deleteMin
(
h
.
left
);
return
balance
(
h
);
}
/**
* Removes the largest key and associated value from the symbol table.
*
@throws
NoSuchElementException if the symbol table is empty
*/
public
void
deleteMax
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“BST underflow”
);
// if both children of root are black, set root to red
if
(
!
isRed
(
root
.
left
)
&&
!
isRed
(
root
.
right
))
root
.
color
=
RED
;
root
=
deleteMax
(
root
);
if
(
!
isEmpty
())
root
.
color
=
BLACK
;
// assert check();
}
// delete the key-value pair with the maximum key rooted at h
private
Node
deleteMax
(
Node
h
)
{
if
(
isRed
(
h
.
left
))
h
=
rotateRight
(
h
);
if
(
h
.
right
==
null
)
return
null
;
if
(
!
isRed
(
h
.
right
)
&&
!
isRed
(
h
.
right
.
left
))
h
=
moveRedRight
(
h
);
h
.
right
=
deleteMax
(
h
.
right
);
return
balance
(
h
);
}
/**
* Removes the specified key and its associated value from this symbol table
* (if the key is in this symbol table).
*
*
@param
key the key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
delete
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to delete() is null”
);
if
(
!
contains
(
key
))
return
;
// if both children of root are black, set root to red
if
(
!
isRed
(
root
.
left
)
&&
!
isRed
(
root
.
right
))
root
.
color
=
RED
;
root
=
delete
(
root
,
key
);
if
(
!
isEmpty
())
root
.
color
=
BLACK
;
// assert check();
}
// delete the key-value pair with the given key rooted at h
private
Node
delete
(
Node
h
,
Key
key
)
{
// assert get(h, key) != null;
if
(
key
.
compareTo
(
h
.
key
)
<
0
)
{
if
(
!
isRed
(
h
.
left
)
&&
!
isRed
(
h
.
left
.
left
))
h
=
moveRedLeft
(
h
);
h
.
left
=
delete
(
h
.
left
,
key
);
}
else
{
if
(
isRed
(
h
.
left
))
h
=
rotateRight
(
h
);
if
(
key
.
compareTo
(
h
.
key
)
==
0
&&
(
h
.
right
==
null
))
return
null
;
if
(
!
isRed
(
h
.
right
)
&&
!
isRed
(
h
.
right
.
left
))
h
=
moveRedRight
(
h
);
if
(
key
.
compareTo
(
h
.
key
)
==
0
)
{
Node
x
=
min
(
h
.
right
);
h
.
key
=
x
.
key
;
h
.
val
=
x
.
val
;
// h.val = get(h.right, min(h.right).key);
// h.key = min(h.right).key;
h
.
right
=
deleteMin
(
h
.
right
);
}
else
h
.
right
=
delete
(
h
.
right
,
key
);
}
return
balance
(
h
);
}
/***************************************************************************
* Red-black tree helper functions.
***************************************************************************/
// make a left-leaning link lean to the right
private
Node
rotateRight
(
Node
h
)
{
// assert (h != null) && isRed(h.left);
Node
x
=
h
.
left
;
h
.
left
=
x
.
right
;
x
.
right
=
h
;
x
.
color
=
x
.
right
.
color
;
x
.
right
.
color
=
RED
;
x
.
size
=
h
.
size
;
h
.
size
=
size
(
h
.
left
)
+
size
(
h
.
right
)
+
1
;
return
x
;
}
// make a right-leaning link lean to the left
private
Node
rotateLeft
(
Node
h
)
{
// assert (h != null) && isRed(h.right);
Node
x
=
h
.
right
;
h
.
right
=
x
.
left
;
x
.
left
=
h
;
x
.
color
=
x
.
left
.
color
;
x
.
left
.
color
=
RED
;
x
.
size
=
h
.
size
;
h
.
size
=
size
(
h
.
left
)
+
size
(
h
.
right
)
+
1
;
return
x
;
}
// flip the colors of a node and its two children
private
void
flipColors
(
Node
h
)
{
// h must have opposite color of its two children
// assert (h != null) && (h.left != null) && (h.right != null);
// assert (!isRed(h) && isRed(h.left) && isRed(h.right))
// || (isRed(h) && !isRed(h.left) && !isRed(h.right));
h
.
color
=
!
h
.
color
;
h
.
left
.
color
=
!
h
.
left
.
color
;
h
.
right
.
color
=
!
h
.
right
.
color
;
}
// Assuming that h is red and both h.left and h.left.left
// are black, make h.left or one of its children red.
private
Node
moveRedLeft
(
Node
h
)
{
// assert (h != null);
// assert isRed(h) && !isRed(h.left) && !isRed(h.left.left);
flipColors
(
h
);
if
(
isRed
(
h
.
right
.
left
))
{
h
.
right
=
rotateRight
(
h
.
right
);
h
=
rotateLeft
(
h
);
flipColors
(
h
);
}
return
h
;
}
// Assuming that h is red and both h.right and h.right.left
// are black, make h.right or one of its children red.
private
Node
moveRedRight
(
Node
h
)
{
// assert (h != null);
// assert isRed(h) && !isRed(h.right) && !isRed(h.right.left);
flipColors
(
h
);
if
(
isRed
(
h
.
left
.
left
))
{
h
=
rotateRight
(
h
);
flipColors
(
h
);
}
return
h
;
}
// restore red-black tree invariant
private
Node
balance
(
Node
h
)
{
// assert (h != null);
if
(
isRed
(
h
.
right
))
h
=
rotateLeft
(
h
);
if
(
isRed
(
h
.
left
)
&&
isRed
(
h
.
left
.
left
))
h
=
rotateRight
(
h
);
if
(
isRed
(
h
.
left
)
&&
isRed
(
h
.
right
))
flipColors
(
h
);
h
.
size
=
size
(
h
.
left
)
+
size
(
h
.
right
)
+
1
;
return
h
;
}
/***************************************************************************
* Utility functions.
***************************************************************************/
/**
* Returns the height of the BST (for debugging).
*
@return
the height of the BST (a 1-node tree has height 0)
*/
public
int
height
()
{
return
height
(
root
);
}
private
int
height
(
Node
x
)
{
if
(
x
==
null
)
return
-
1
;
return
1
+
Math
.
max
(
height
(
x
.
left
),
height
(
x
.
right
));
}
/***************************************************************************
* Ordered symbol table methods.
***************************************************************************/
/**
* Returns the smallest key in the symbol table.
*
@return
the smallest key in the symbol table
*
@throws
NoSuchElementException if the symbol table is empty
*/
public
Key
min
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
"calls min() with empty symbol table"
);
return
min
(
root
).
key
;
}
// the smallest key in subtree rooted at x; null if no such key
private
Node
min
(
Node
x
)
{
// assert x != null;
if
(
x
.
left
==
null
)
return
x
;
else
return
min
(
x
.
left
);
}
/**
* Returns the largest key in the symbol table.
*
@return
the largest key in the symbol table
*
@throws
NoSuchElementException if the symbol table is empty
*/
public
Key
max
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
"calls max() with empty symbol table"
);
return
max
(
root
).
key
;
}
// the largest key in the subtree rooted at x; null if no such key
private
Node
max
(
Node
x
)
{
// assert x != null;
if
(
x
.
right
==
null
)
return
x
;
else
return
max
(
x
.
right
);
}
/**
* Returns the largest key in the symbol table less than or equal to {
@code
key}.
*
@param
key the key
*
@return
the largest key in the symbol table less than or equal to {
@code
key}
*
@throws
NoSuchElementException if there is no such key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
Key
floor
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
"argument to floor() is null"
);
if
(
isEmpty
())
throw
new
NoSuchElementException
(
"calls floor() with empty symbol table"
);
Node
x
=
floor
(
root
,
key
);
if
(
x
==
null
)
throw
new
NoSuchElementException
(
"argument to floor() is too small"
);
else
return
x
.
key
;
}
// the largest key in the subtree rooted at x less than or equal to the given key
private
Node
floor
(
Node
x
,
Key
key
)
{
if
(
x
==
null
)
return
null
;
int
cmp
=
key
.
compareTo
(
x
.
key
);
if
(
cmp
==
0
)
return
x
;
if
(
cmp
<
0
)
return
floor
(
x
.
left
,
key
);
Node
t
=
floor
(
x
.
right
,
key
);
if
(
t
!=
null
)
return
t
;
else
return
x
;
}
/**
* Returns the smallest key in the symbol table greater than or equal to {
@code
key}.
*
@param
key the key
*
@return
the smallest key in the symbol table greater than or equal to {
@code
key}
*
@throws
NoSuchElementException if there is no such key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
Key
ceiling
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
"argument to ceiling() is null"
);
if
(
isEmpty
())
throw
new
NoSuchElementException
(
"calls ceiling() with empty symbol table"
);
Node
x
=
ceiling
(
root
,
key
);
if
(
x
==
null
)
throw
new
NoSuchElementException
(
"argument to ceiling() is too small"
);
else
return
x
.
key
;
}
// the smallest key in the subtree rooted at x greater than or equal to the given key
private
Node
ceiling
(
Node
x
,
Key
key
)
{
if
(
x
==
null
)
return
null
;
int
cmp
=
key
.
compareTo
(
x
.
key
);
if
(
cmp
==
0
)
return
x
;
if
(
cmp
>
0
)
return
ceiling
(
x
.
right
,
key
);
Node
t
=
ceiling
(
x
.
left
,
key
);
if
(
t
!=
null
)
return
t
;
else
return
x
;
}
/**
* Return the key in the symbol table whose rank is {
@code
k}.
* This is the (k+1)st smallest key in the symbol table.
*
*
@param
k the order statistic
*
@return
the key in the symbol table of rank {
@code
k}
*
@throws
IllegalArgumentException unless {
@code
k} is between 0 and
* n–1
*/
public
Key
select
(
int
k
)
{
if
(
k
<
0
||
k
>=
size
())
{
throw
new
IllegalArgumentException
(
“argument to select() is invalid: ”
+
k
);
}
Node
x
=
select
(
root
,
k
);
return
x
.
key
;
}
// the key of rank k in the subtree rooted at x
private
Node
select
(
Node
x
,
int
k
)
{
// assert x != null;
// assert k >= 0 && k < size(x);
int
t
=
size
(
x
.
left
);
if
(
t
>
k
)
return
select
(
x
.
left
,
k
);
else
if
(
t
<
k
)
return
select
(
x
.
right
,
k
-
t
-
1
);
else
return
x
;
}
/**
* Return the number of keys in the symbol table strictly less than {
@code
key}.
*
@param
key the key
*
@return
the number of keys in the symbol table strictly less than {
@code
key}
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
int
rank
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
"argument to rank() is null"
);
return
rank
(
key
,
root
);
}
// number of keys less than key in the subtree rooted at x
private
int
rank
(
Key
key
,
Node
x
)
{
if
(
x
==
null
)
return
0
;
int
cmp
=
key
.
compareTo
(
x
.
key
);
if
(
cmp
<
0
)
return
rank
(
key
,
x
.
left
);
else
if
(
cmp
>
0
)
return
1
+
size
(
x
.
left
)
+
rank
(
key
,
x
.
right
);
else
return
size
(
x
.
left
);
}
/***************************************************************************
* Range count and range search.
***************************************************************************/
/**
* Returns all keys in the symbol table as an {
@code
Iterable}.
* To iterate over all of the keys in the symbol table named {
@code
st},
* use the foreach notation: {
@code
for (Key key : st.keys())}.
*
@return
all keys in the symbol table as an {
@code
Iterable}
*/
public
Iterable
<
Key
>
keys
()
{
if
(
isEmpty
())
return
new
Queue
<
Key
>
();
return
keys
(
min
(),
max
());
}
/**
* Returns all keys in the symbol table in the given range,
* as an {
@code
Iterable}.
*
*
@param
lo minimum endpoint
*
@param
hi maximum endpoint
*
@return
all keys in the symbol table between {
@code
lo}
* (inclusive) and {
@code
hi} (inclusive) as an {
@code
Iterable}
*
@throws
IllegalArgumentException if either {
@code
lo} or {
@code
hi}
* is {
@code
null}
*/
public
Iterable
<
Key
>
keys
(
Key
lo
,
Key
hi
)
{
if
(
lo
==
null
)
throw
new
IllegalArgumentException
(
“first argument to keys() is null”
);
if
(
hi
==
null
)
throw
new
IllegalArgumentException
(
“second argument to keys() is null”
);
Queue
<
Key
>
queue
=
new
Queue
<
Key
>
();
// if (isEmpty() || lo.compareTo(hi) > 0) return queue;
keys
(
root
,
queue
,
lo
,
hi
);
return
queue
;
}
// add the keys between lo and hi in the subtree rooted at x
// to the queue
private
void
keys
(
Node
x
,
Queue
<
Key
>
queue
,
Key
lo
,
Key
hi
)
{
if
(
x
==
null
)
return
;
int
cmplo
=
lo
.
compareTo
(
x
.
key
);
int
cmphi
=
hi
.
compareTo
(
x
.
key
);
if
(
cmplo
<
0
)
keys
(
x
.
left
,
queue
,
lo
,
hi
);
if
(
cmplo
<=
0
&&
cmphi
>=
0
)
queue
.
enqueue
(
x
.
key
);
if
(
cmphi
>
0
)
keys
(
x
.
right
,
queue
,
lo
,
hi
);
}
/**
* Returns the number of keys in the symbol table in the given range.
*
*
@param
lo minimum endpoint
*
@param
hi maximum endpoint
*
@return
the number of keys in the symbol table between {
@code
lo}
* (inclusive) and {
@code
hi} (inclusive)
*
@throws
IllegalArgumentException if either {
@code
lo} or {
@code
hi}
* is {
@code
null}
*/
public
int
size
(
Key
lo
,
Key
hi
)
{
if
(
lo
==
null
)
throw
new
IllegalArgumentException
(
“first argument to size() is null”
);
if
(
hi
==
null
)
throw
new
IllegalArgumentException
(
“second argument to size() is null”
);
if
(
lo
.
compareTo
(
hi
)
>
0
)
return
0
;
if
(
contains
(
hi
))
return
rank
(
hi
)
–
rank
(
lo
)
+
1
;
else
return
rank
(
hi
)
–
rank
(
lo
);
}
/*************************************************************************** * Check integrity of red-black tree data structure. ***************************************************************************/
private boolean check() {
if (!isBST()) StdOut.println(“Not in symmetric order”);
if (!isSizeConsistent()) StdOut.println(“Subtree counts not consistent”);
if (!isRankConsistent()) StdOut.println(“Ranks not consistent”);
if (!is23()) StdOut.println(“Not a 2-3 tree”);
if (!isBalanced()) StdOut.println(“Not balanced”);
return isBST() && isSizeConsistent() && isRankConsistent() && is23() && isBalanced();
}
// does this binary tree satisfy symmetric order? // Note: this test also ensures that data structure is a binary tree since order is strict private boolean isBST() {
return isBST(root, null, null);
}
// is the tree rooted at x a BST with all keys strictly between min and max // (if min or max is null, treat as empty constraint) // Credit: Bob Dondero’s elegant solution private boolean isBST(Node x, Key min, Key max) {
if (x == null) return true;
if (min != null && x.key.compareTo(min) <= 0) return false; if (max != null && x.key.compareTo(max) >= 0) return false;
return isBST(x.left, min, x.key) && isBST(x.right, x.key, max);
}
// are the size fields correct? private boolean isSizeConsistent() { return isSizeConsistent(root); }
private boolean isSizeConsistent(Node x) {
if (x == null) return true;
if (x.size != size(x.left) + size(x.right) + 1) return false;
return isSizeConsistent(x.left) && isSizeConsistent(x.right);
}
// check that ranks are consistent private boolean isRankConsistent() {
for (int i = 0; i < size(); i++)
if (i != rank(select(i))) return false;
for (Key key : keys())
if (key.compareTo(select(rank(key))) != 0) return false;
return true;
}
// Does the tree have no red right links, and at most one (left) // red links in a row on any path? private boolean is23() { return is23(root); }
private boolean is23(Node x) {
if (x == null) return true;
if (isRed(x.right)) return false;
if (x != root && isRed(x) && isRed(x.left))
return false;
return is23(x.left) && is23(x.right);
}
// do all paths from root to leaf have same number of black edges? private boolean isBalanced() { int black = 0; // number of black links on path from root to min Node x = root;
while (x != null) {
if (!isRed(x)) black++;
x = x.left;
}
return isBalanced(root, black);
}
// does every path from the root to a leaf have the given number of black links? private boolean isBalanced(Node x, int black) {
if (x == null) return black == 0;
if (!isRed(x)) black--;
return isBalanced(x.left, black) && isBalanced(x.right, black);
}
/** * Unit tests the {@code RedBlackBST} data type. * * @param args the command-line arguments */
public static void main(String[] args) { RedBlackBST
for (int i = 0; !StdIn.isEmpty(); i++) {
String key = StdIn.readString();
st.put(key, i);
}
StdOut.println();
for (String s : st.keys())
StdOut.println(s + ” ” + st.get(s));
StdOut.println();
}
}
/****************************************************************************** * Copyright 2002-2020, Robert Sedgewick and Kevin Wayne. * * This file is part of algs4.jar, which accompanies the textbook * * Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne, * Addison-Wesley Professional, 2011, ISBN 0-321-57351-X. * http://algs4.cs.princeton.edu * * * algs4.jar is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * algs4.jar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with algs4.jar. If not, see http://www.gnu.org/licenses. ******************************************************************************/
edu/princeton/cs/algs4/ResizingArrayBag.java
edu/princeton/cs/algs4/ResizingArrayBag.java
/******************************************************************************
* Compilation: javac ResizingArrayBag.java
* Execution: java ResizingArrayBag
* Dependencies: StdIn.java StdOut.java
*
* Bag implementation with a resizing array.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Iterator
;
import
java
.
util
.
NoSuchElementException
;
/**
* The {
@code
ResizingArrayBag} class represents a bag (or multiset) of
* generic items. It supports insertion and iterating over the
* items in arbitrary order.
*
* This implementation uses a resizing array.
* See {
@link
LinkedBag} for a version that uses a singly linked list.
* The add operation takes constant amortized time; the
* isEmpty, and size operations
* take constant time. Iteration takes time proportional to the number of items.
*
* For additional documentation, see Section 1.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
ResizingArrayBag
<
Item
>
implements
Iterable
<
Item
>
{
private
Item
[]
a
;
// array of items
private
int
n
;
// number of elements on bag
/**
* Initializes an empty bag.
*/
public
ResizingArrayBag
()
{
a
=
(
Item
[])
new
Object
[
2
];
n
=
0
;
}
/**
* Is this bag empty?
*
@return
true if this bag is empty; false otherwise
*/
public
boolean
isEmpty
()
{
return
n
==
0
;
}
/**
* Returns the number of items in this bag.
*
@return
the number of items in this bag
*/
public
int
size
()
{
return
n
;
}
// resize the underlying array holding the elements
private
void
resize
(
int
capacity
)
{
assert
capacity
>=
n
;
Item
[]
temp
=
(
Item
[])
new
Object
[
capacity
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
temp
[
i
]
=
a
[
i
];
a
=
temp
;
}
/**
* Adds the item to this bag.
*
@param
item the item to add to this bag
*/
public
void
add
(
Item
item
)
{
if
(
n
==
a
.
length
)
resize
(
2
*
a
.
length
);
// double size of array if necessary
a
[
n
++
]
=
item
;
// add item
}
/**
* Returns an iterator that iterates over the items in the bag in arbitrary order.
*
@return
an iterator that iterates over the items in the bag in arbitrary order
*/
public
Iterator
<
Item
>
iterator
()
{
return
new
ArrayIterator
();
}
// an iterator, doesn’t implement remove() since it’s optional
private
class
ArrayIterator
implements
Iterator
<
Item
>
{
private
int
i
=
0
;
public
boolean
hasNext
()
{
return
i
<
n
;
}
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
public
Item
next
()
{
if
(
!
hasNext
())
throw
new
NoSuchElementException
();
return
a
[
i
++
];
}
}
/**
* Unit tests the {
@code
ResizingArrayBag} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
ResizingArrayBag
<
String
>
bag
=
new
ResizingArrayBag
<
String
>
();
bag
.
add
(
“Hello”
);
bag
.
add
(
“World”
);
bag
.
add
(
“how”
);
bag
.
add
(
“are”
);
bag
.
add
(
“you”
);
for
(
String
s
:
bag
)
StdOut
.
println
(
s
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/ResizingArrayQueue.java
edu/princeton/cs/algs4/ResizingArrayQueue.java
/******************************************************************************
* Compilation: javac ResizingArrayQueue.java
* Execution: java ResizingArrayQueue < input.txt * Dependencies: StdIn.java StdOut.java * Data files: https://algs4.cs.princeton.edu/13stacks/tobe.txt * * Queue implementation with a resizing array. * * % java ResizingArrayQueue < tobe.txt * to be or not to be (2 left on queue) * ******************************************************************************/ package edu . princeton . cs . algs4 ; import java . util . Iterator ; import java . util . NoSuchElementException ; /** * The { @code ResizingArrayQueue} class represents a first-in-first-out (FIFO) * queue of generic items. * It supports the usual enqueue and dequeue
* operations, along with methods for peeking at the first item,
* testing if the queue is empty, and iterating through
* the items in FIFO order.
*
* This implementation uses a resizing array, which double the underlying array
* when it is full and halves the underlying array when it is one-quarter full.
* The enqueue and dequeue operations take constant amortized time.
* The size, peek, and is-empty operations takes
* constant time in the worst case.
*
* For additional documentation, see Section 1.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
ResizingArrayQueue
<
Item
>
implements
Iterable
<
Item
>
{
private
Item
[]
q
;
// queue elements
private
int
n
;
// number of elements on queue
private
int
first
;
// index of first element of queue
private
int
last
;
// index of next available slot
/**
* Initializes an empty queue.
*/
public
ResizingArrayQueue
()
{
q
=
(
Item
[])
new
Object
[
2
];
n
=
0
;
first
=
0
;
last
=
0
;
}
/**
* Is this queue empty?
*
@return
true if this queue is empty; false otherwise
*/
public
boolean
isEmpty
()
{
return
n
==
0
;
}
/**
* Returns the number of items in this queue.
*
@return
the number of items in this queue
*/
public
int
size
()
{
return
n
;
}
// resize the underlying array
private
void
resize
(
int
capacity
)
{
assert
capacity
>=
n
;
Item
[]
temp
=
(
Item
[])
new
Object
[
capacity
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
temp
[
i
]
=
q
[(
first
+
i
)
%
q
.
length
];
}
q
=
temp
;
first
=
0
;
last
=
n
;
}
/**
* Adds the item to this queue.
*
@param
item the item to add
*/
public
void
enqueue
(
Item
item
)
{
// double size of array if necessary and recopy to front of array
if
(
n
==
q
.
length
)
resize
(
2
*
q
.
length
);
// double size of array if necessary
q
[
last
++
]
=
item
;
// add item
if
(
last
==
q
.
length
)
last
=
0
;
// wrap-around
n
++
;
}
/**
* Removes and returns the item on this queue that was least recently added.
*
@return
the item on this queue that was least recently added
*
@throws
java.util.NoSuchElementException if this queue is empty
*/
public
Item
dequeue
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
"Queue underflow"
);
Item
item
=
q
[
first
];
q
[
first
]
=
null
;
// to avoid loitering
n
--
;
first
++
;
if
(
first
==
q
.
length
)
first
=
0
;
// wrap-around
// shrink size of array if necessary
if
(
n
>
0
&&
n
==
q
.
length
/
4
)
resize
(
q
.
length
/
2
);
return
item
;
}
/**
* Returns the item least recently added to this queue.
*
@return
the item least recently added to this queue
*
@throws
java.util.NoSuchElementException if this queue is empty
*/
public
Item
peek
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Queue underflow”
);
return
q
[
first
];
}
/**
* Returns an iterator that iterates over the items in this queue in FIFO order.
*
@return
an iterator that iterates over the items in this queue in FIFO order
*/
public
Iterator
<
Item
>
iterator
()
{
return
new
ArrayIterator
();
}
// an iterator, doesn’t implement remove() since it’s optional
private
class
ArrayIterator
implements
Iterator
<
Item
>
{
private
int
i
=
0
;
public
boolean
hasNext
()
{
return
i
<
n
;
}
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
public
Item
next
()
{
if
(
!
hasNext
())
throw
new
NoSuchElementException
();
Item
item
=
q
[(
i
+
first
)
%
q
.
length
];
i
++
;
return
item
;
}
}
/**
* Unit tests the {
@code
ResizingArrayQueue} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
ResizingArrayQueue
<
String
>
queue
=
new
ResizingArrayQueue
<
String
>
();
while
(
!
StdIn
.
isEmpty
())
{
String
item
=
StdIn
.
readString
();
if
(
!
item
.
equals
(
“-”
))
queue
.
enqueue
(
item
);
else
if
(
!
queue
.
isEmpty
())
StdOut
.
print
(
queue
.
dequeue
()
+
” ”
);
}
StdOut
.
println
(
“(”
+
queue
.
size
()
+
” left on queue)”
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/ResizingArrayStack.java
edu/princeton/cs/algs4/ResizingArrayStack.java
/******************************************************************************
* Compilation: javac ResizingArrayStack.java
* Execution: java ResizingArrayStack < input.txt * Dependencies: StdIn.java StdOut.java * Data files: https://algs4.cs.princeton.edu/13stacks/tobe.txt * * Stack implementation with a resizing array. * * % more tobe.txt * to be or not to - be - - that - - - is * * % java ResizingArrayStack < tobe.txt * to be not that or be (2 left on stack) * ******************************************************************************/ package edu . princeton . cs . algs4 ; import java . util . Iterator ; import java . util . NoSuchElementException ; /** * The { @code ResizingArrayStack} class represents a last-in-first-out (LIFO) stack * of generic items. * It supports the usual push and pop operations, along with methods
* for peeking at the top item, testing if the stack is empty, and iterating through
* the items in LIFO order.
*
* This implementation uses a resizing array, which double the underlying array
* when it is full and halves the underlying array when it is one-quarter full.
* The push and pop operations take constant amortized time.
* The size, peek, and is-empty operations takes
* constant time in the worst case.
*
* For additional documentation,
* see Section 1.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
ResizingArrayStack
<
Item
>
implements
Iterable
<
Item
>
{
private
Item
[]
a
;
// array of items
private
int
n
;
// number of elements on stack
/**
* Initializes an empty stack.
*/
public
ResizingArrayStack
()
{
a
=
(
Item
[])
new
Object
[
2
];
n
=
0
;
}
/**
* Is this stack empty?
*
@return
true if this stack is empty; false otherwise
*/
public
boolean
isEmpty
()
{
return
n
==
0
;
}
/**
* Returns the number of items in the stack.
*
@return
the number of items in the stack
*/
public
int
size
()
{
return
n
;
}
// resize the underlying array holding the elements
private
void
resize
(
int
capacity
)
{
assert
capacity
>=
n
;
// textbook implementation
Item
[]
temp
=
(
Item
[])
new
Object
[
capacity
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
temp
[
i
]
=
a
[
i
];
}
a
=
temp
;
// alternative implementation
// a = java.util.Arrays.copyOf(a, capacity);
}
/**
* Adds the item to this stack.
*
@param
item the item to add
*/
public
void
push
(
Item
item
)
{
if
(
n
==
a
.
length
)
resize
(
2
*
a
.
length
);
// double size of array if necessary
a
[
n
++
]
=
item
;
// add item
}
/**
* Removes and returns the item most recently added to this stack.
*
@return
the item most recently added
*
@throws
java.util.NoSuchElementException if this stack is empty
*/
public
Item
pop
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
"Stack underflow"
);
Item
item
=
a
[
n
-
1
];
a
[
n
-
1
]
=
null
;
// to avoid loitering
n
--
;
// shrink size of array if necessary
if
(
n
>
0
&&
n
==
a
.
length
/
4
)
resize
(
a
.
length
/
2
);
return
item
;
}
/**
* Returns (but does not remove) the item most recently added to this stack.
*
@return
the item most recently added to this stack
*
@throws
java.util.NoSuchElementException if this stack is empty
*/
public
Item
peek
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Stack underflow”
);
return
a
[
n
–
1
];
}
/**
* Returns an iterator to this stack that iterates through the items in LIFO order.
*
@return
an iterator to this stack that iterates through the items in LIFO order.
*/
public
Iterator
<
Item
>
iterator
()
{
return
new
ReverseArrayIterator
();
}
// an iterator, doesn’t implement remove() since it’s optional
private
class
ReverseArrayIterator
implements
Iterator
<
Item
>
{
private
int
i
;
public
ReverseArrayIterator
()
{
i
=
n
–
1
;
}
public
boolean
hasNext
()
{
return
i
>=
0
;
}
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
public
Item
next
()
{
if
(
!
hasNext
())
throw
new
NoSuchElementException
();
return
a
[
i
—
];
}
}
/**
* Unit tests the {
@code
Stack} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
ResizingArrayStack
<
String
>
stack
=
new
ResizingArrayStack
<
String
>
();
while
(
!
StdIn
.
isEmpty
())
{
String
item
=
StdIn
.
readString
();
if
(
!
item
.
equals
(
“-”
))
stack
.
push
(
item
);
else
if
(
!
stack
.
isEmpty
())
StdOut
.
print
(
stack
.
pop
()
+
” ”
);
}
StdOut
.
println
(
“(”
+
stack
.
size
()
+
” left on stack)”
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/RunLength.java
edu/princeton/cs/algs4/RunLength.java
/******************************************************************************
* Compilation: javac RunLength.java
* Execution: java RunLength – < input.txt (compress) * Execution: java RunLength + < input.txt (expand) * Dependencies: BinaryIn.java BinaryOut.java * Data files: https://algs4.cs.princeton.edu/55compression/4runs.bin * https://algs4.cs.princeton.edu/55compression/q32x48.bin * https://algs4.cs.princeton.edu/55compression/q64x96.bin * * Compress or expand binary input from standard input using * run-length encoding. * * % java BinaryDump 40 < 4runs.bin * 0000000000000001111111000000011111111111 * 40 bits * * This has runs of 15 0s, 7 1s, 7 0s, and 11 1s. * * % java RunLength - < 4runs.bin | java HexDump * 0f 07 07 0b * 4 bytes * ******************************************************************************/ package edu . princeton . cs . algs4 ; /** * The { @code RunLength} class provides static methods for compressing * and expanding a binary input using run-length coding with 8-bit * run lengths. *
* For additional documentation,
* see Section 5.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
RunLength
{
private
static
final
int
R
=
256
;
private
static
final
int
LG_R
=
8
;
// Do not instantiate.
private
RunLength
()
{
}
/**
* Reads a sequence of bits from standard input (that are encoded
* using run-length encoding with 8-bit run lengths); decodes them;
* and writes the results to standard output.
*/
public
static
void
expand
()
{
boolean
b
=
false
;
while
(
!
BinaryStdIn
.
isEmpty
())
{
int
run
=
BinaryStdIn
.
readInt
(
LG_R
);
for
(
int
i
=
0
;
i
<
run
;
i
++
)
BinaryStdOut
.
write
(
b
);
b
=
!
b
;
}
BinaryStdOut
.
close
();
}
/**
* Reads a sequence of bits from standard input; compresses
* them using run-length coding with 8-bit run lengths; and writes the
* results to standard output.
*/
public
static
void
compress
()
{
char
run
=
0
;
boolean
old
=
false
;
while
(
!
BinaryStdIn
.
isEmpty
())
{
boolean
b
=
BinaryStdIn
.
readBoolean
();
if
(
b
!=
old
)
{
BinaryStdOut
.
write
(
run
,
LG_R
);
run
=
1
;
old
=
!
old
;
}
else
{
if
(
run
==
R
-
1
)
{
BinaryStdOut
.
write
(
run
,
LG_R
);
run
=
0
;
BinaryStdOut
.
write
(
run
,
LG_R
);
}
run
++
;
}
}
BinaryStdOut
.
write
(
run
,
LG_R
);
BinaryStdOut
.
close
();
}
/**
* Sample client that calls {
@code
compress()} if the command-line
* argument is "-" an {
@code
expand()} if it is "+".
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
if
(
args
[
0
].
equals
(
"-"
))
compress
();
else
if
(
args
[
0
].
equals
(
"+"
))
expand
();
else
throw
new
IllegalArgumentException
(
"Illegal command line argument"
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/SegmentTree.java
edu/princeton/cs/algs4/SegmentTree.java
/******************************************************************************
* Compilation: javac SegmentTree.java
* Execution: java SegmentTree
*
* A segment tree data structure.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Arrays
;
/**
* The {
@code
SegmentTree} class is an structure for efficient search of cummulative data.
* It performs Range Minimum Query and Range Sum Query in O(log(n)) time.
* It can be easily customizable to support Range Max Query, Range Multiplication Query etc.
*
* Also it has been develop with {
@code
LazyPropagation} for range updates, which means
* when you perform update operations over a range, the update process affects the least nodes as possible
* so that the bigger the range you want to update the less time it consumes to update it. Eventually those changes will be propagated
* to the children and the whole array will be up to date.
*
* Example:
*
* SegmentTreeHeap st = new SegmentTreeHeap(new Integer[]{1,3,4,2,1, -2, 4});
* st.update(0,3, 1)
* In the above case only the node that represents the range [0,3] will be updated (and not their children) so in this case
* the update task will be less than n*log(n)
*
* Memory usage: O(n)
*
*
@author
Ricardo Pacheco
*/
public
class
SegmentTree
{
private
Node
[]
heap
;
private
int
[]
array
;
private
int
size
;
/**
* Time-Complexity: O(n*log(n))
*
*
@param
array the Initialization array
*/
public
SegmentTree
(
int
[]
array
)
{
this
.
array
=
Arrays
.
copyOf
(
array
,
array
.
length
);
//The max size of this array is about 2 * 2 ^ log2(n) + 1
size
=
(
int
)
(
2
*
Math
.
pow
(
2.0
,
Math
.
floor
((
Math
.
log
((
double
)
array
.
length
)
/
Math
.
log
(
2.0
))
+
1
)));
heap
=
new
Node
[
size
];
build
(
1
,
0
,
array
.
length
);
}
public
int
size
()
{
return
array
.
length
;
}
//Initialize the Nodes of the Segment tree
private
void
build
(
int
v
,
int
from
,
int
size
)
{
heap
[
v
]
=
new
Node
();
heap
[
v
].
from
=
from
;
heap
[
v
].
to
=
from
+
size
–
1
;
if
(
size
==
1
)
{
heap
[
v
].
sum
=
array
[
from
];
heap
[
v
].
min
=
array
[
from
];
}
else
{
//Build childs
build
(
2
*
v
,
from
,
size
/
2
);
build
(
2
*
v
+
1
,
from
+
size
/
2
,
size
–
size
/
2
);
heap
[
v
].
sum
=
heap
[
2
*
v
].
sum
+
heap
[
2
*
v
+
1
].
sum
;
//min = min of the children
heap
[
v
].
min
=
Math
.
min
(
heap
[
2
*
v
].
min
,
heap
[
2
*
v
+
1
].
min
);
}
}
/**
* Range Sum Query
*
* Time-Complexity: O(log(n))
*
*
@param
from from index
*
@param
to to index
*
@return
sum
*/
public
int
rsq
(
int
from
,
int
to
)
{
return
rsq
(
1
,
from
,
to
);
}
private
int
rsq
(
int
v
,
int
from
,
int
to
)
{
Node
n
=
heap
[
v
];
//If you did a range update that contained this node, you can infer the Sum without going down the tree
if
(
n
.
pendingVal
!=
null
&&
contains
(
n
.
from
,
n
.
to
,
from
,
to
))
{
return
(
to
–
from
+
1
)
*
n
.
pendingVal
;
}
if
(
contains
(
from
,
to
,
n
.
from
,
n
.
to
))
{
return
heap
[
v
].
sum
;
}
if
(
intersects
(
from
,
to
,
n
.
from
,
n
.
to
))
{
propagate
(
v
);
int
leftSum
=
rsq
(
2
*
v
,
from
,
to
);
int
rightSum
=
rsq
(
2
*
v
+
1
,
from
,
to
);
return
leftSum
+
rightSum
;
}
return
0
;
}
/**
* Range Min Query
*
* Time-Complexity: O(log(n))
*
*
@param
from from index
*
@param
to to index
*
@return
min
*/
public
int
rMinQ
(
int
from
,
int
to
)
{
return
rMinQ
(
1
,
from
,
to
);
}
private
int
rMinQ
(
int
v
,
int
from
,
int
to
)
{
Node
n
=
heap
[
v
];
//If you did a range update that contained this node, you can infer the Min value without going down the tree
if
(
n
.
pendingVal
!=
null
&&
contains
(
n
.
from
,
n
.
to
,
from
,
to
))
{
return
n
.
pendingVal
;
}
if
(
contains
(
from
,
to
,
n
.
from
,
n
.
to
))
{
return
heap
[
v
].
min
;
}
if
(
intersects
(
from
,
to
,
n
.
from
,
n
.
to
))
{
propagate
(
v
);
int
leftMin
=
rMinQ
(
2
*
v
,
from
,
to
);
int
rightMin
=
rMinQ
(
2
*
v
+
1
,
from
,
to
);
return
Math
.
min
(
leftMin
,
rightMin
);
}
return
Integer
.
MAX_VALUE
;
}
/**
* Range Update Operation.
* With this operation you can update either one position or a range of positions with a given number.
* The update operations will update the less it can to update the whole range (Lazy Propagation).
* The values will be propagated lazily from top to bottom of the segment tree.
* This behavior is really useful for updates on portions of the array
*
* Time-Complexity: O(log(n))
*
*
@param
from from index
*
@param
to to index
*
@param
value value
*/
public
void
update
(
int
from
,
int
to
,
int
value
)
{
update
(
1
,
from
,
to
,
value
);
}
private
void
update
(
int
v
,
int
from
,
int
to
,
int
value
)
{
//The Node of the heap tree represents a range of the array with bounds: [n.from, n.to]
Node
n
=
heap
[
v
];
/**
* If the updating-range contains the portion of the current Node We lazily update it.
* This means We do NOT update each position of the vector, but update only some temporal
* values into the Node; such values into the Node will be propagated down to its children only when they need to.
*/
if
(
contains
(
from
,
to
,
n
.
from
,
n
.
to
))
{
change
(
n
,
value
);
}
if
(
n
.
size
()
==
1
)
return
;
if
(
intersects
(
from
,
to
,
n
.
from
,
n
.
to
))
{
/**
* Before keeping going down to the tree We need to propagate the
* the values that have been temporally/lazily saved into this Node to its children
* So that when We visit them the values are properly updated
*/
propagate
(
v
);
update
(
2
*
v
,
from
,
to
,
value
);
update
(
2
*
v
+
1
,
from
,
to
,
value
);
n
.
sum
=
heap
[
2
*
v
].
sum
+
heap
[
2
*
v
+
1
].
sum
;
n
.
min
=
Math
.
min
(
heap
[
2
*
v
].
min
,
heap
[
2
*
v
+
1
].
min
);
}
}
//Propagate temporal values to children
private
void
propagate
(
int
v
)
{
Node
n
=
heap
[
v
];
if
(
n
.
pendingVal
!=
null
)
{
change
(
heap
[
2
*
v
],
n
.
pendingVal
);
change
(
heap
[
2
*
v
+
1
],
n
.
pendingVal
);
n
.
pendingVal
=
null
;
//unset the pending propagation value
}
}
//Save the temporal values that will be propagated lazily
private
void
change
(
Node
n
,
int
value
)
{
n
.
pendingVal
=
value
;
n
.
sum
=
n
.
size
()
*
value
;
n
.
min
=
value
;
array
[
n
.
from
]
=
value
;
}
//Test if the range1 contains range2
private
boolean
contains
(
int
from1
,
int
to1
,
int
from2
,
int
to2
)
{
return
from2
>=
from1
&&
to2
<=
to1
;
}
//check inclusive intersection, test if range1[from1, to1] intersects range2[from2, to2]
private
boolean
intersects
(
int
from1
,
int
to1
,
int
from2
,
int
to2
)
{
return
from1
<=
from2
&&
to1
>=
from2
// (.[..)..] or (.[…]..)
||
from1
>=
from2
&&
from1
<=
to2
;
// [.(..]..) or [..(..)..
}
//The Node class represents a partition range of the array.
static
class
Node
{
int
sum
;
int
min
;
//Here We store the value that will be propagated lazily
Integer
pendingVal
=
null
;
int
from
;
int
to
;
int
size
()
{
return
to
-
from
+
1
;
}
}
/**
* Read the following commands:
* init n v Initializes the array of size n with all v's
* set a b c... Initializes the array with [a, b, c ...]
* rsq a b Range Sum Query for the range [a, b]
* rmq a b Range Min Query for the range [a, b]
* up a b v Update the [a,b] portion of the array with value v.
* exit
*
* Example:
* init
* set 1 2 3 4 5 6
* rsq 1 3
* Sum from 1 to 3 = 6
* rmq 1 3
* Min from 1 to 3 = 1
* input up 1 3
* [3,2,3,4,5,6]
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
SegmentTree
st
=
null
;
String
cmd
=
“cmp”
;
while
(
true
)
{
String
[]
line
=
StdIn
.
readLine
().
split
(
” ”
);
if
(
line
[
0
].
equals
(
“exit”
))
break
;
int
arg1
=
0
,
arg2
=
0
,
arg3
=
0
;
if
(
line
.
length
>
1
)
{
arg1
=
Integer
.
parseInt
(
line
[
1
]);
}
if
(
line
.
length
>
2
)
{
arg2
=
Integer
.
parseInt
(
line
[
2
]);
}
if
(
line
.
length
>
3
)
{
arg3
=
Integer
.
parseInt
(
line
[
3
]);
}
if
((
!
line
[
0
].
equals
(
“set”
)
&&
!
line
[
0
].
equals
(
“init”
))
&&
st
==
null
)
{
StdOut
.
println
(
“Segment Tree not initialized”
);
continue
;
}
int
array
[];
if
(
line
[
0
].
equals
(
“set”
))
{
array
=
new
int
[
line
.
length
–
1
];
for
(
int
i
=
0
;
i
<
line
.
length
-
1
;
i
++
)
{
array
[
i
]
=
Integer
.
parseInt
(
line
[
i
+
1
]);
}
st
=
new
SegmentTree
(
array
);
}
else
if
(
line
[
0
].
equals
(
"init"
))
{
array
=
new
int
[
arg1
];
Arrays
.
fill
(
array
,
arg2
);
st
=
new
SegmentTree
(
array
);
for
(
int
i
=
0
;
i
<
st
.
size
();
i
++
)
{
StdOut
.
print
(
st
.
rsq
(
i
,
i
)
+
" "
);
}
StdOut
.
println
();
}
else
if
(
line
[
0
].
equals
(
"up"
))
{
st
.
update
(
arg1
,
arg2
,
arg3
);
for
(
int
i
=
0
;
i
<
st
.
size
();
i
++
)
{
StdOut
.
print
(
st
.
rsq
(
i
,
i
)
+
" "
);
}
StdOut
.
println
();
}
else
if
(
line
[
0
].
equals
(
"rsq"
))
{
StdOut
.
printf
(
"Sum from %d to %d = %d%n"
,
arg1
,
arg2
,
st
.
rsq
(
arg1
,
arg2
));
}
else
if
(
line
[
0
].
equals
(
"rmq"
))
{
StdOut
.
printf
(
"Min from %d to %d = %d%n"
,
arg1
,
arg2
,
st
.
rMinQ
(
arg1
,
arg2
));
}
else
{
StdOut
.
println
(
"Invalid command"
);
}
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Selection.java
edu/princeton/cs/algs4/Selection.java
/******************************************************************************
* Compilation: javac Selection.java
* Execution: java Selection < input.txt
* Dependencies: StdOut.java StdIn.java
* Data files: https://algs4.cs.princeton.edu/21elementary/tiny.txt
* https://algs4.cs.princeton.edu/21elementary/words3.txt
*
* Sorts a sequence of strings from standard input using selection sort.
*
* % more tiny.txt
* S O R T E X A M P L E
*
* % java Selection < tiny.txt
* A E E L M O P R S T X [ one string per line ]
*
* % more words3.txt
* bed bug dad yes zoo ... all bad yet
*
* % java Selection < words3.txt
* all bad bed bug dad ... yes yet zoo [ one string per line ]
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Comparator
;
/**
* The {
@code
Selection} class provides static methods for sorting an
* array using selection sort.
* This implementation makes ~ ½ n2 compares to sort
* any array of length n, so it is not suitable for sorting large arrays.
* It performs exactly n exchanges.
*
* This sorting algorithm is not stable. It uses Θ(1) extra memory
* (not including the input array).
*
* For additional documentation, see
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Selection
{
// This class should not be instantiated.
private
Selection
()
{
}
/**
* Rearranges the array in ascending order, using the natural order.
*
@param
a the array to be sorted
*/
public
static
void
sort
(
Comparable
[]
a
)
{
int
n
=
a
.
length
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
int
min
=
i
;
for
(
int
j
=
i
+
1
;
j
<
n
;
j
++
)
{
if
(
less
(
a
[
j
],
a
[
min
]))
min
=
j
;
}
exch
(
a
,
i
,
min
);
assert
isSorted
(
a
,
0
,
i
);
}
assert
isSorted
(
a
);
}
/**
* Rearranges the array in ascending order, using a comparator.
*
@param
a the array
*
@param
comparator the comparator specifying the order
*/
public
static
void
sort
(
Object
[]
a
,
Comparator
comparator
)
{
int
n
=
a
.
length
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
int
min
=
i
;
for
(
int
j
=
i
+
1
;
j
<
n
;
j
++
)
{
if
(
less
(
comparator
,
a
[
j
],
a
[
min
]))
min
=
j
;
}
exch
(
a
,
i
,
min
);
assert
isSorted
(
a
,
comparator
,
0
,
i
);
}
assert
isSorted
(
a
,
comparator
);
}
/***************************************************************************
* Helper sorting functions.
***************************************************************************/
// is v < w ?
private
static
boolean
less
(
Comparable
v
,
Comparable
w
)
{
return
v
.
compareTo
(
w
)
<
0
;
}
// is v < w ?
private
static
boolean
less
(
Comparator
comparator
,
Object
v
,
Object
w
)
{
return
comparator
.
compare
(
v
,
w
)
<
0
;
}
// exchange a[i] and a[j]
private
static
void
exch
(
Object
[]
a
,
int
i
,
int
j
)
{
Object
swap
=
a
[
i
];
a
[
i
]
=
a
[
j
];
a
[
j
]
=
swap
;
}
/***************************************************************************
* Check if array is sorted - useful for debugging.
***************************************************************************/
// is the array a[] sorted?
private
static
boolean
isSorted
(
Comparable
[]
a
)
{
return
isSorted
(
a
,
0
,
a
.
length
-
1
);
}
// is the array sorted from a[lo] to a[hi]
private
static
boolean
isSorted
(
Comparable
[]
a
,
int
lo
,
int
hi
)
{
for
(
int
i
=
lo
+
1
;
i
<=
hi
;
i
++
)
if
(
less
(
a
[
i
],
a
[
i
-
1
]))
return
false
;
return
true
;
}
// is the array a[] sorted?
private
static
boolean
isSorted
(
Object
[]
a
,
Comparator
comparator
)
{
return
isSorted
(
a
,
comparator
,
0
,
a
.
length
-
1
);
}
// is the array sorted from a[lo] to a[hi]
private
static
boolean
isSorted
(
Object
[]
a
,
Comparator
comparator
,
int
lo
,
int
hi
)
{
for
(
int
i
=
lo
+
1
;
i
<=
hi
;
i
++
)
if
(
less
(
comparator
,
a
[
i
],
a
[
i
-
1
]))
return
false
;
return
true
;
}
// print array to standard output
private
static
void
show
(
Comparable
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
StdOut
.
println
(
a
[
i
]);
}
}
/**
* Reads in a sequence of strings from standard input; selection sorts them;
* and prints them to standard output in ascending order.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
[]
a
=
StdIn
.
readAllStrings
();
Selection
.
sort
(
a
);
show
(
a
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/SeparateChainingHashST.java
edu/princeton/cs/algs4/SeparateChainingHashST.java
/******************************************************************************
* Compilation: javac SeparateChainingHashST.java
* Execution: java SeparateChainingHashST < input.txt
* Dependencies: StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/34hash/tinyST.txt
*
* A symbol table implemented with a separate-chaining hash table.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
SeparateChainingHashST} class represents a symbol table of generic
* key-value pairs.
* It supports the usual put, get, contains,
* delete, size, and is-empty methods.
* It also provides a keys method for iterating over all of the keys.
* A symbol table implements the associative array abstraction:
* when associating a value with a key that is already in the symbol table,
* the convention is to replace the old value with the new value.
* Unlike {
@link
java.util.Map}, this class uses the convention that
* values cannot be {
@code
null}—setting the
* value associated with a key to {
@code
null} is equivalent to deleting the key
* from the symbol table.
*
* This implementation uses a separate chaining hash table. It requires that
* the key type overrides the {
@code
equals()} and {
@code
hashCode()} methods.
* The expected time per put, contains, or remove
* operation is constant, subject to the uniform hashing assumption.
* The size, and is-empty operations take constant time.
* Construction takes constant time.
*
* For additional documentation, see Section 3.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
* For other implementations, see {
@link
ST}, {
@link
BinarySearchST},
* {
@link
SequentialSearchST}, {
@link
BST}, {
@link
RedBlackBST}, and
* {
@link
LinearProbingHashST},
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
SeparateChainingHashST
<
Key
,
Value
>
{
private
static
final
int
INIT_CAPACITY
=
4
;
private
int
n
;
// number of key-value pairs
private
int
m
;
// hash table size
private
SequentialSearchST
<
Key
,
Value
>
[]
st
;
// array of linked-list symbol tables
/**
* Initializes an empty symbol table.
*/
public
SeparateChainingHashST
()
{
this
(
INIT_CAPACITY
);
}
/**
* Initializes an empty symbol table with {
@code
m} chains.
*
@param
m the initial number of chains
*/
public
SeparateChainingHashST
(
int
m
)
{
this
.
m
=
m
;
st
=
(
SequentialSearchST
<
Key
,
Value
>
[])
new
SequentialSearchST
[
m
];
for
(
int
i
=
0
;
i
<
m
;
i
++
)
st
[
i
]
=
new
SequentialSearchST
<
Key
,
Value
>
();
}
// resize the hash table to have the given number of chains,
// rehashing all of the keys
private
void
resize
(
int
chains
)
{
SeparateChainingHashST
<
Key
,
Value
>
temp
=
new
SeparateChainingHashST
<
Key
,
Value
>
(
chains
);
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
for
(
Key
key
:
st
[
i
].
keys
())
{
temp
.
put
(
key
,
st
[
i
].
get
(
key
));
}
}
this
.
m
=
temp
.
m
;
this
.
n
=
temp
.
n
;
this
.
st
=
temp
.
st
;
}
// hash value between 0 and m-1
private
int
hash
(
Key
key
)
{
return
(
key
.
hashCode
()
&
0x7fffffff
)
%
m
;
}
/**
* Returns the number of key-value pairs in this symbol table.
*
*
@return
the number of key-value pairs in this symbol table
*/
public
int
size
()
{
return
n
;
}
/**
* Returns true if this symbol table is empty.
*
*
@return
{
@code
true} if this symbol table is empty;
* {
@code
false} otherwise
*/
public
boolean
isEmpty
()
{
return
size
()
==
0
;
}
/**
* Returns true if this symbol table contains the specified key.
*
*
@param
key the key
*
@return
{
@code
true} if this symbol table contains {
@code
key};
* {
@code
false} otherwise
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
boolean
contains
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
"argument to contains() is null"
);
return
get
(
key
)
!=
null
;
}
/**
* Returns the value associated with the specified key in this symbol table.
*
*
@param
key the key
*
@return
the value associated with {
@code
key} in the symbol table;
* {
@code
null} if no such value
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
Value
get
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
"argument to get() is null"
);
int
i
=
hash
(
key
);
return
st
[
i
].
get
(
key
);
}
/**
* Inserts the specified key-value pair into the symbol table, overwriting the old
* value with the new value if the symbol table already contains the specified key.
* Deletes the specified key (and its associated value) from this symbol table
* if the specified value is {
@code
null}.
*
*
@param
key the key
*
@param
val the value
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
put
(
Key
key
,
Value
val
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
"first argument to put() is null"
);
if
(
val
==
null
)
{
delete
(
key
);
return
;
}
// double table size if average length of list >= 10
if
(
n
>=
10
*
m
)
resize
(
2
*
m
);
int
i
=
hash
(
key
);
if
(
!
st
[
i
].
contains
(
key
))
n
++
;
st
[
i
].
put
(
key
,
val
);
}
/**
* Removes the specified key and its associated value from this symbol table
* (if the key is in this symbol table).
*
*
@param
key the key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
delete
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to delete() is null”
);
int
i
=
hash
(
key
);
if
(
st
[
i
].
contains
(
key
))
n
—
;
st
[
i
].
delete
(
key
);
// halve table size if average length of list <= 2
if
(
m
>
INIT_CAPACITY
&&
n
<=
2
*
m
)
resize
(
m
/
2
);
}
// return keys in symbol table as an Iterable
public
Iterable
<
Key
>
keys
()
{
Queue
<
Key
>
queue
=
new
Queue
<
Key
>
();
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
for
(
Key
key
:
st
[
i
].
keys
())
queue
.
enqueue
(
key
);
}
return
queue
;
}
/**
* Unit tests the {
@code
SeparateChainingHashST} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
SeparateChainingHashST
<
String
,
Integer
>
st
=
new
SeparateChainingHashST
<
String
,
Integer
>
();
for
(
int
i
=
0
;
!
StdIn
.
isEmpty
();
i
++
)
{
String
key
=
StdIn
.
readString
();
st
.
put
(
key
,
i
);
}
// print keys
for
(
String
s
:
st
.
keys
())
StdOut
.
println
(
s
+
” ”
+
st
.
get
(
s
));
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/SequentialSearchST.java
edu/princeton/cs/algs4/SequentialSearchST.java
/******************************************************************************
* Compilation: javac SequentialSearchST.java
* Execution: java SequentialSearchST
* Dependencies: StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/31elementary/tinyST.txt
*
* Symbol table implementation with sequential search in an
* unordered linked list of key-value pairs.
*
* % more tinyST.txt
* S E A R C H E X A M P L E
*
* % java SequentialSearchST < tinyST.txt * L 11 * P 10 * M 9 * X 7 * H 5 * C 4 * R 3 * A 8 * E 12 * S 0 * ******************************************************************************/ package edu . princeton . cs . algs4 ; /** * The { @code SequentialSearchST} class represents an (unordered) * symbol table of generic key-value pairs. * It supports the usual put, get, contains,
* delete, size, and is-empty methods.
* It also provides a keys method for iterating over all of the keys.
* A symbol table implements the associative array abstraction:
* when associating a value with a key that is already in the symbol table,
* the convention is to replace the old value with the new value.
* The class also uses the convention that values cannot be {
@code
null}. Setting the
* value associated with a key to {
@code
null} is equivalent to deleting the key
* from the symbol table.
*
* It relies on the {
@code
equals()} method to test whether two keys
* are equal. It does not call either the {
@code
compareTo()} or
* {
@code
hashCode()} method.
*
* This implementation uses a singly linked list and
* sequential search.
* The put and delete operations take Θ(n).
* The get and contains operations takes Θ(n)
* time in the worst case.
* The size, and is-empty operations take Θ(1) time.
* Construction takes Θ(1) time.
*
* For additional documentation, see
* Section 3.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
SequentialSearchST
<
Key
,
Value
>
{
private
int
n
;
// number of key-value pairs
private
Node
first
;
// the linked list of key-value pairs
// a helper linked list data type
private
class
Node
{
private
Key
key
;
private
Value
val
;
private
Node
next
;
public
Node
(
Key
key
,
Value
val
,
Node
next
)
{
this
.
key
=
key
;
this
.
val
=
val
;
this
.
next
=
next
;
}
}
/**
* Initializes an empty symbol table.
*/
public
SequentialSearchST
()
{
}
/**
* Returns the number of key-value pairs in this symbol table.
*
*
@return
the number of key-value pairs in this symbol table
*/
public
int
size
()
{
return
n
;
}
/**
* Returns true if this symbol table is empty.
*
*
@return
{
@code
true} if this symbol table is empty;
* {
@code
false} otherwise
*/
public
boolean
isEmpty
()
{
return
size
()
==
0
;
}
/**
* Returns true if this symbol table contains the specified key.
*
*
@param
key the key
*
@return
{
@code
true} if this symbol table contains {
@code
key};
* {
@code
false} otherwise
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
boolean
contains
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to contains() is null”
);
return
get
(
key
)
!=
null
;
}
/**
* Returns the value associated with the given key in this symbol table.
*
*
@param
key the key
*
@return
the value associated with the given key if the key is in the symbol table
* and {
@code
null} if the key is not in the symbol table
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
Value
get
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to get() is null”
);
for
(
Node
x
=
first
;
x
!=
null
;
x
=
x
.
next
)
{
if
(
key
.
equals
(
x
.
key
))
return
x
.
val
;
}
return
null
;
}
/**
* Inserts the specified key-value pair into the symbol table, overwriting the old
* value with the new value if the symbol table already contains the specified key.
* Deletes the specified key (and its associated value) from this symbol table
* if the specified value is {
@code
null}.
*
*
@param
key the key
*
@param
val the value
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
put
(
Key
key
,
Value
val
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“first argument to put() is null”
);
if
(
val
==
null
)
{
delete
(
key
);
return
;
}
for
(
Node
x
=
first
;
x
!=
null
;
x
=
x
.
next
)
{
if
(
key
.
equals
(
x
.
key
))
{
x
.
val
=
val
;
return
;
}
}
first
=
new
Node
(
key
,
val
,
first
);
n
++
;
}
/**
* Removes the specified key and its associated value from this symbol table
* (if the key is in this symbol table).
*
*
@param
key the key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
delete
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to delete() is null”
);
first
=
delete
(
first
,
key
);
}
// delete key in linked list beginning at Node x
// warning: function call stack too large if table is large
private
Node
delete
(
Node
x
,
Key
key
)
{
if
(
x
==
null
)
return
null
;
if
(
key
.
equals
(
x
.
key
))
{
n
—
;
return
x
.
next
;
}
x
.
next
=
delete
(
x
.
next
,
key
);
return
x
;
}
/**
* Returns all keys in the symbol table as an {
@code
Iterable}.
* To iterate over all of the keys in the symbol table named {
@code
st},
* use the foreach notation: {
@code
for (Key key : st.keys())}.
*
*
@return
all keys in the symbol table
*/
public
Iterable
<
Key
>
keys
()
{
Queue
<
Key
>
queue
=
new
Queue
<
Key
>
();
for
(
Node
x
=
first
;
x
!=
null
;
x
=
x
.
next
)
queue
.
enqueue
(
x
.
key
);
return
queue
;
}
/**
* Unit tests the {
@code
SequentialSearchST} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
SequentialSearchST
<
String
,
Integer
>
st
=
new
SequentialSearchST
<
String
,
Integer
>
();
for
(
int
i
=
0
;
!
StdIn
.
isEmpty
();
i
++
)
{
String
key
=
StdIn
.
readString
();
st
.
put
(
key
,
i
);
}
for
(
String
s
:
st
.
keys
())
StdOut
.
println
(
s
+
” ”
+
st
.
get
(
s
));
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/SET.java
edu/princeton/cs/algs4/SET.java
/******************************************************************************
* Compilation: javac SET.java
* Execution: java SET
* Dependencies: StdOut.java
*
* Set implementation using Java’s TreeSet library.
* Does not allow duplicates.
*
* % java SET
* 128.112.136.11
* 208.216.181.15
* null
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Iterator
;
import
java
.
util
.
NoSuchElementException
;
import
java
.
util
.
TreeSet
;
/**
* The {
@code
SET} class represents an ordered set of comparable keys.
* It supports the usual add, contains, and delete
* methods. It also provides ordered methods for finding the minimum,
* maximum, floor, and ceiling and set methods
* for union, intersection, and equality.
*
* Even though this implementation include the method {
@code
equals()}, it
* does not support the method {
@code
hashCode()} because sets are mutable.
*
* This implementation uses a balanced binary search tree. It requires that
* the key type implements the {
@code
Comparable} interface and calls the
* {
@code
compareTo()} and method to compare two keys. It does not call either
* {
@code
equals()} or {
@code
hashCode()}.
* The add, contains, delete, minimum,
* maximum, ceiling, and floor methods take
* logarithmic time in the worst case.
* The size, and is-empty operations take constant time.
* Construction takes constant time.
*
* For additional documentation, see
* Section 3.5 of
* Algorithms in Java, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*
*
@param
*/
public
class
SET
<
Key
extends
Comparable
<
Key
>>
implements
Iterable
<
Key
>
{
private
TreeSet
<
Key
>
set
;
/**
* Initializes an empty set.
*/
public
SET
()
{
set
=
new
TreeSet
<
Key
>
();
}
/**
* Initializes a new set that is an independent copy of the specified set.
*
*
@param
x the set to copy
*/
public
SET
(
SET
<
Key
>
x
)
{
set
=
new
TreeSet
<
Key
>
(
x
.
set
);
}
/**
* Adds the key to this set (if it is not already present).
*
*
@param
key the key to add
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
add
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“called add() with a null key”
);
set
.
add
(
key
);
}
/**
* Returns true if this set contains the given key.
*
*
@param
key the key
*
@return
{
@code
true} if this set contains {
@code
key};
* {
@code
false} otherwise
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
boolean
contains
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“called contains() with a null key”
);
return
set
.
contains
(
key
);
}
/**
* Removes the specified key from this set (if the set contains the specified key).
* This is equivalent to {
@code
remove()}, but we plan to deprecate {
@code
delete()}.
*
*
@param
key the key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
delete
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“called delete() with a null key”
);
set
.
remove
(
key
);
}
/**
* Removes the specified key from this set (if the set contains the specified key).
* This is equivalent to {
@code
delete()}, but we plan to deprecate {
@code
delete()}.
*
*
@param
key the key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
remove
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“called remove() with a null key”
);
set
.
remove
(
key
);
}
/**
* Returns the number of keys in this set.
*
*
@return
the number of keys in this set
*/
public
int
size
()
{
return
set
.
size
();
}
/**
* Returns true if this set is empty.
*
*
@return
{
@code
true} if this set is empty;
* {
@code
false} otherwise
*/
public
boolean
isEmpty
()
{
return
size
()
==
0
;
}
/**
* Returns all of the keys in this set, as an iterator.
* To iterate over all of the keys in a set named {
@code
set}, use the
* foreach notation: {
@code
for (Key key : set)}.
*
*
@return
an iterator to all of the keys in this set
*/
public
Iterator
<
Key
>
iterator
()
{
return
set
.
iterator
();
}
/**
* Returns the largest key in this set.
*
*
@return
the largest key in this set
*
@throws
NoSuchElementException if this set is empty
*/
public
Key
max
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“called max() with empty set”
);
return
set
.
last
();
}
/**
* Returns the smallest key in this set.
*
*
@return
the smallest key in this set
*
@throws
NoSuchElementException if this set is empty
*/
public
Key
min
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“called min() with empty set”
);
return
set
.
first
();
}
/**
* Returns the smallest key in this set greater than or equal to {
@code
key}.
*
*
@param
key the key
*
@return
the smallest key in this set greater than or equal to {
@code
key}
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*
@throws
NoSuchElementException if there is no such key
*/
public
Key
ceiling
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“called ceiling() with a null key”
);
Key
k
=
set
.
ceiling
(
key
);
if
(
k
==
null
)
throw
new
NoSuchElementException
(
“all keys are less than ”
+
key
);
return
k
;
}
/**
* Returns the largest key in this set less than or equal to {
@code
key}.
*
*
@param
key the key
*
@return
the largest key in this set table less than or equal to {
@code
key}
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*
@throws
NoSuchElementException if there is no such key
*/
public
Key
floor
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“called floor() with a null key”
);
Key
k
=
set
.
floor
(
key
);
if
(
k
==
null
)
throw
new
NoSuchElementException
(
“all keys are greater than ”
+
key
);
return
k
;
}
/**
* Returns the union of this set and that set.
*
*
@param
that the other set
*
@return
the union of this set and that set
*
@throws
IllegalArgumentException if {
@code
that} is {
@code
null}
*/
public
SET
<
Key
>
union
(
SET
<
Key
>
that
)
{
if
(
that
==
null
)
throw
new
IllegalArgumentException
(
“called union() with a null argument”
);
SET
<
Key
>
c
=
new
SET
<
Key
>
();
for
(
Key
x
:
this
)
{
c
.
add
(
x
);
}
for
(
Key
x
:
that
)
{
c
.
add
(
x
);
}
return
c
;
}
/**
* Returns the intersection of this set and that set.
*
*
@param
that the other set
*
@return
the intersection of this set and that set
*
@throws
IllegalArgumentException if {
@code
that} is {
@code
null}
*/
public
SET
<
Key
>
intersects
(
SET
<
Key
>
that
)
{
if
(
that
==
null
)
throw
new
IllegalArgumentException
(
“called intersects() with a null argument”
);
SET
<
Key
>
c
=
new
SET
<
Key
>
();
if
(
this
.
size
()
<
that
.
size
())
{
for
(
Key
x
:
this
)
{
if
(
that
.
contains
(
x
))
c
.
add
(
x
);
}
}
else
{
for
(
Key
x
:
that
)
{
if
(
this
.
contains
(
x
))
c
.
add
(
x
);
}
}
return
c
;
}
/**
* Compares this set to the specified set.
*
* Note that this method declares two empty sets to be equal
* even if they are parameterized by different generic types.
* This is consistent with the behavior of {
@code
equals()}
* within Java’s Collections framework.
*
*
@param
other the other set
*
@return
{
@code
true} if this set equals {
@code
other};
* {
@code
false} otherwise
*/
@
Override
public
boolean
equals
(
Object
other
)
{
if
(
other
==
this
)
return
true
;
if
(
other
==
null
)
return
false
;
if
(
other
.
getClass
()
!=
this
.
getClass
())
return
false
;
SET that
=
(
SET
)
other
;
return
this
.
set
.
equals
(
that
.
set
);
}
/**
* This operation is not supported because sets are mutable.
*
*
@return
does not return a value
*
@throws
UnsupportedOperationException if called
*/
@
Override
public
int
hashCode
()
{
throw
new
UnsupportedOperationException
(
“hashCode() is not supported because sets are mutable”
);
}
/**
* Returns a string representation of this set.
*
*
@return
a string representation of this set, enclosed in curly braces,
* with adjacent keys separated by a comma and a space
*/
@
Override
public
String
toString
()
{
String
s
=
set
.
toString
();
return
“{ ”
+
s
.
substring
(
1
,
s
.
length
()
–
1
)
+
” }”
;
}
/**
* Unit tests the {
@code
SET} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
SET
<
String
>
set
=
new
SET
<
String
>
();
StdOut
.
println
(
“set = ”
+
set
);
// insert some keys
set
.
add
(
“www.cs.princeton.edu”
);
set
.
add
(
“www.cs.princeton.edu”
);
// overwrite old value
set
.
add
(
“www.princeton.edu”
);
set
.
add
(
“www.math.princeton.edu”
);
set
.
add
(
“www.yale.edu”
);
set
.
add
(
“www.amazon.com”
);
set
.
add
(
“www.simpsons.com”
);
set
.
add
(
“www.stanford.edu”
);
set
.
add
(
“www.google.com”
);
set
.
add
(
“www.ibm.com”
);
set
.
add
(
“www.apple.com”
);
set
.
add
(
“www.slashdot.com”
);
set
.
add
(
“www.whitehouse.gov”
);
set
.
add
(
“www.espn.com”
);
set
.
add
(
“www.snopes.com”
);
set
.
add
(
“www.movies.com”
);
set
.
add
(
“www.cnn.com”
);
set
.
add
(
“www.iitb.ac.in”
);
StdOut
.
println
(
set
.
contains
(
“www.cs.princeton.edu”
));
StdOut
.
println
(
!
set
.
contains
(
“www.harvardsucks.com”
));
StdOut
.
println
(
set
.
contains
(
“www.simpsons.com”
));
StdOut
.
println
();
StdOut
.
println
(
“ceiling(www.simpsonr.com) = ”
+
set
.
ceiling
(
“www.simpsonr.com”
));
StdOut
.
println
(
“ceiling(www.simpsons.com) = ”
+
set
.
ceiling
(
“www.simpsons.com”
));
StdOut
.
println
(
“ceiling(www.simpsont.com) = ”
+
set
.
ceiling
(
“www.simpsont.com”
));
StdOut
.
println
(
“floor(www.simpsonr.com) = ”
+
set
.
floor
(
“www.simpsonr.com”
));
StdOut
.
println
(
“floor(www.simpsons.com) = ”
+
set
.
floor
(
“www.simpsons.com”
));
StdOut
.
println
(
“floor(www.simpsont.com) = ”
+
set
.
floor
(
“www.simpsont.com”
));
StdOut
.
println
();
StdOut
.
println
(
“set = ”
+
set
);
StdOut
.
println
();
// print out all keys in this set in lexicographic order
for
(
String
s
:
set
)
{
StdOut
.
println
(
s
);
}
StdOut
.
println
();
SET
<
String
>
set2
=
new
SET
<
String
>
(
set
);
StdOut
.
println
(
set
.
equals
(
set2
));
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Shell.java
edu/princeton/cs/algs4/Shell.java
/******************************************************************************
* Compilation: javac Shell.java
* Execution: java Shell < input.txt * Dependencies: StdOut.java StdIn.java * Data files: https://algs4.cs.princeton.edu/21elementary/tiny.txt * https://algs4.cs.princeton.edu/21elementary/words3.txt * * Sorts a sequence of strings from standard input using shellsort. * * % more tiny.txt * S O R T E X A M P L E * * % java Shell < tiny.txt * A E E L M O P R S T X [ one string per line ] * * % more words3.txt * bed bug dad yes zoo ... all bad yet * * % java Shell < words3.txt * all bad bed bug dad ... yes yet zoo [ one string per line ] * * ******************************************************************************/ package edu . princeton . cs . algs4 ; /** * The { @code Shell} class provides static methods for sorting an * array using Shellsort with
* (1, 4, 13, 40, …). In the worst case, this implementation makes
* Θ(n3/2) compares and exchanges to sort
* an array of length n.
*
* This sorting algorithm is not stable.
* It uses Θ(1) extra memory (not including the input array).
*
* For additional documentation, see
* Section 2.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Shell
{
// This class should not be instantiated.
private
Shell
()
{
}
/**
* Rearranges the array in ascending order, using the natural order.
*
@param
a the array to be sorted
*/
public
static
void
sort
(
Comparable
[]
a
)
{
int
n
=
a
.
length
;
// 3x+1 increment sequence: 1, 4, 13, 40, 121, 364, 1093, …
int
h
=
1
;
while
(
h
<
n
/
3
)
h
=
3
*
h
+
1
;
while
(
h
>=
1
)
{
// h-sort the array
for
(
int
i
=
h
;
i
<
n
;
i
++
)
{
for
(
int
j
=
i
;
j
>=
h
&&
less
(
a
[
j
],
a
[
j
–
h
]);
j
-=
h
)
{
exch
(
a
,
j
,
j
–
h
);
}
}
assert
isHsorted
(
a
,
h
);
h
/=
3
;
}
assert
isSorted
(
a
);
}
/***************************************************************************
* Helper sorting functions.
***************************************************************************/
// is v < w ?
private
static
boolean
less
(
Comparable
v
,
Comparable
w
)
{
return
v
.
compareTo
(
w
)
<
0
;
}
// exchange a[i] and a[j]
private
static
void
exch
(
Object
[]
a
,
int
i
,
int
j
)
{
Object
swap
=
a
[
i
];
a
[
i
]
=
a
[
j
];
a
[
j
]
=
swap
;
}
/***************************************************************************
* Check if array is sorted - useful for debugging.
***************************************************************************/
private
static
boolean
isSorted
(
Comparable
[]
a
)
{
for
(
int
i
=
1
;
i
<
a
.
length
;
i
++
)
if
(
less
(
a
[
i
],
a
[
i
-
1
]))
return
false
;
return
true
;
}
// is the array h-sorted?
private
static
boolean
isHsorted
(
Comparable
[]
a
,
int
h
)
{
for
(
int
i
=
h
;
i
<
a
.
length
;
i
++
)
if
(
less
(
a
[
i
],
a
[
i
-
h
]))
return
false
;
return
true
;
}
// print array to standard output
private
static
void
show
(
Comparable
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
StdOut
.
println
(
a
[
i
]);
}
}
/**
* Reads in a sequence of strings from standard input; Shellsorts them;
* and prints them to standard output in ascending order.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
[]
a
=
StdIn
.
readAllStrings
();
Shell
.
sort
(
a
);
show
(
a
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/SparseVector.java
edu/princeton/cs/algs4/SparseVector.java
/******************************************************************************
* Compilation: javac SparseVector.java
* Execution: java SparseVector
* Dependencies: StdOut.java
*
* A sparse vector, implementing using a symbol table.
*
* [Not clear we need the instance variable N except for error checking.]
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
SparseVector} class represents a d-dimensional mathematical vector.
* Vectors are mutable: their values can be changed after they are created.
* It includes methods for addition, subtraction,
* dot product, scalar product, unit vector, and Euclidean norm.
*
* The implementation is a symbol table of indices and values for which the vector
* coordinates are nonzero. This makes it efficient when most of the vector coordindates
* are zero.
*
* For additional documentation,
* see Section 3.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
* See also {
@link
Vector} for an immutable (dense) vector data type.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
SparseVector
{
private
int
d
;
// dimension
private
ST
<
Integer
,
Double
>
st
;
// the vector, represented by index-value pairs
/**
* Initializes a d-dimensional zero vector.
*
@param
d the dimension of the vector
*/
public
SparseVector
(
int
d
)
{
this
.
d
=
d
;
this
.
st
=
new
ST
<
Integer
,
Double
>
();
}
/**
* Sets the ith coordinate of this vector to the specified value.
*
*
@param
i the index
*
@param
value the new value
*
@throws
IllegalArgumentException unless i is between 0 and d-1
*/
public
void
put
(
int
i
,
double
value
)
{
if
(
i
<
0
||
i
>=
d
)
throw
new
IllegalArgumentException
(
“Illegal index”
);
if
(
value
==
0.0
)
st
.
delete
(
i
);
else
st
.
put
(
i
,
value
);
}
/**
* Returns the ith coordinate of this vector.
*
*
@param
i the index
*
@return
the value of the ith coordinate of this vector
*
@throws
IllegalArgumentException unless i is between 0 and d-1
*/
public
double
get
(
int
i
)
{
if
(
i
<
0
||
i
>=
d
)
throw
new
IllegalArgumentException
(
“Illegal index”
);
if
(
st
.
contains
(
i
))
return
st
.
get
(
i
);
else
return
0.0
;
}
/**
* Returns the number of nonzero entries in this vector.
*
*
@return
the number of nonzero entries in this vector
*/
public
int
nnz
()
{
return
st
.
size
();
}
/**
* Returns the dimension of this vector.
*
*
@return
the dimension of this vector
*
@deprecated
Replaced by {
@link
#dimension()}.
*/
@
Deprecated
public
int
size
()
{
return
d
;
}
/**
* Returns the dimension of this vector.
*
*
@return
the dimension of this vector
*/
public
int
dimension
()
{
return
d
;
}
/**
* Returns the inner product of this vector with the specified vector.
*
*
@param
that the other vector
*
@return
the dot product between this vector and that vector
*
@throws
IllegalArgumentException if the lengths of the two vectors are not equal
*/
public
double
dot
(
SparseVector
that
)
{
if
(
this
.
d
!=
that
.
d
)
throw
new
IllegalArgumentException
(
“Vector lengths disagree”
);
double
sum
=
0.0
;
// iterate over the vector with the fewest nonzeros
if
(
this
.
st
.
size
()
<=
that
.
st
.
size
())
{
for
(
int
i
:
this
.
st
.
keys
())
if
(
that
.
st
.
contains
(
i
))
sum
+=
this
.
get
(
i
)
*
that
.
get
(
i
);
}
else
{
for
(
int
i
:
that
.
st
.
keys
())
if
(
this
.
st
.
contains
(
i
))
sum
+=
this
.
get
(
i
)
*
that
.
get
(
i
);
}
return
sum
;
}
/**
* Returns the inner product of this vector with the specified array.
*
*
@param
that the array
*
@return
the dot product between this vector and that array
*
@throws
IllegalArgumentException if the dimensions of the vector and the array are not equal
*/
public
double
dot
(
double
[]
that
)
{
double
sum
=
0.0
;
for
(
int
i
:
st
.
keys
())
sum
+=
that
[
i
]
*
this
.
get
(
i
);
return
sum
;
}
/**
* Returns the magnitude of this vector.
* This is also known as the L2 norm or the Euclidean norm.
*
*
@return
the magnitude of this vector
*/
public
double
magnitude
()
{
return
Math
.
sqrt
(
this
.
dot
(
this
));
}
/**
* Returns the Euclidean norm of this vector.
*
*
@return
the Euclidean norm of this vector
*
@deprecated
Replaced by {
@link
#magnitude()}.
*/
@
Deprecated
public
double
norm
()
{
return
Math
.
sqrt
(
this
.
dot
(
this
));
}
/**
* Returns the scalar-vector product of this vector with the specified scalar.
*
*
@param
alpha the scalar
*
@return
the scalar-vector product of this vector with the specified scalar
*/
public
SparseVector
scale
(
double
alpha
)
{
SparseVector
c
=
new
SparseVector
(
d
);
for
(
int
i
:
this
.
st
.
keys
())
c
.
put
(
i
,
alpha
*
this
.
get
(
i
));
return
c
;
}
/**
* Returns the sum of this vector and the specified vector.
*
*
@param
that the vector to add to this vector
*
@return
the sum of this vector and that vector
*
@throws
IllegalArgumentException if the dimensions of the two vectors are not equal
*/
public
SparseVector
plus
(
SparseVector
that
)
{
if
(
this
.
d
!=
that
.
d
)
throw
new
IllegalArgumentException
(
"Vector lengths disagree"
);
SparseVector
c
=
new
SparseVector
(
d
);
for
(
int
i
:
this
.
st
.
keys
())
c
.
put
(
i
,
this
.
get
(
i
));
// c = this
for
(
int
i
:
that
.
st
.
keys
())
c
.
put
(
i
,
that
.
get
(
i
)
+
c
.
get
(
i
));
// c = c + that
return
c
;
}
/**
* Returns a string representation of this vector.
*
@return
a string representation of this vector, which consists of the
* the vector entries, separates by commas, enclosed in parentheses
*/
public
String
toString
()
{
StringBuilder
s
=
new
StringBuilder
();
for
(
int
i
:
st
.
keys
())
{
s
.
append
(
"("
+
i
+
", "
+
st
.
get
(
i
)
+
") "
);
}
return
s
.
toString
();
}
/**
* Unit tests the {
@code
SparseVector} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
SparseVector
a
=
new
SparseVector
(
10
);
SparseVector
b
=
new
SparseVector
(
10
);
a
.
put
(
3
,
0.50
);
a
.
put
(
9
,
0.75
);
a
.
put
(
6
,
0.11
);
a
.
put
(
6
,
0.00
);
b
.
put
(
3
,
0.60
);
b
.
put
(
4
,
0.90
);
StdOut
.
println
(
"a = "
+
a
);
StdOut
.
println
(
"b = "
+
b
);
StdOut
.
println
(
"a dot b = "
+
a
.
dot
(
b
));
StdOut
.
println
(
"a + b = "
+
a
.
plus
(
b
));
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Stack.java
edu/princeton/cs/algs4/Stack.java
/******************************************************************************
* Compilation: javac Stack.java
* Execution: java Stack < input.txt
* Dependencies: StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/13stacks/tobe.txt
*
* A generic stack, implemented using a singly linked list.
* Each stack element is of type Item.
*
* This version uses a static nested class Node (to save 8 bytes per
* Node), whereas the version in the textbook uses a non-static nested
* class (for simplicity).
*
* % more tobe.txt
* to be or not to - be - - that - - - is
*
* % java Stack < tobe.txt
* to be not that or be (2 left on stack)
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Iterator
;
import
java
.
util
.
NoSuchElementException
;
/**
* The {
@code
Stack} class represents a last-in-first-out (LIFO) stack of generic items.
* It supports the usual push and pop operations, along with methods
* for peeking at the top item, testing if the stack is empty, and iterating through
* the items in LIFO order.
*
* This implementation uses a singly linked list with a static nested class for
* linked-list nodes. See {
@link
LinkedStack} for the version from the
* textbook that uses a non-static nested class.
* See {
@link
ResizingArrayStack} for a version that uses a resizing array.
* The push, pop, peek, size, and is-empty
* operations all take constant time in the worst case.
*
* For additional documentation,
* see Section 1.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*
*
@param
*/
public
class
Stack
<
Item
>
implements
Iterable
<
Item
>
{
private
Node
<
Item
>
first
;
// top of stack
private
int
n
;
// size of the stack
// helper linked list class
private
static
class
Node
<
Item
>
{
private
Item
item
;
private
Node
<
Item
>
next
;
}
/**
* Initializes an empty stack.
*/
public
Stack
()
{
first
=
null
;
n
=
0
;
}
/**
* Returns true if this stack is empty.
*
*
@return
true if this stack is empty; false otherwise
*/
public
boolean
isEmpty
()
{
return
first
==
null
;
}
/**
* Returns the number of items in this stack.
*
*
@return
the number of items in this stack
*/
public
int
size
()
{
return
n
;
}
/**
* Adds the item to this stack.
*
*
@param
item the item to add
*/
public
void
push
(
Item
item
)
{
Node
<
Item
>
oldfirst
=
first
;
first
=
new
Node
<
Item
>
();
first
.
item
=
item
;
first
.
next
=
oldfirst
;
n
++
;
}
/**
* Removes and returns the item most recently added to this stack.
*
*
@return
the item most recently added
*
@throws
NoSuchElementException if this stack is empty
*/
public
Item
pop
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Stack underflow”
);
Item
item
=
first
.
item
;
// save item to return
first
=
first
.
next
;
// delete first node
n
—
;
return
item
;
// return the saved item
}
/**
* Returns (but does not remove) the item most recently added to this stack.
*
*
@return
the item most recently added to this stack
*
@throws
NoSuchElementException if this stack is empty
*/
public
Item
peek
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Stack underflow”
);
return
first
.
item
;
}
/**
* Returns a string representation of this stack.
*
*
@return
the sequence of items in this stack in LIFO order, separated by spaces
*/
public
String
toString
()
{
StringBuilder
s
=
new
StringBuilder
();
for
(
Item
item
:
this
)
{
s
.
append
(
item
);
s
.
append
(
‘ ‘
);
}
return
s
.
toString
();
}
/**
* Returns an iterator to this stack that iterates through the items in LIFO order.
*
*
@return
an iterator to this stack that iterates through the items in LIFO order
*/
public
Iterator
<
Item
>
iterator
()
{
return
new
ListIterator
(
first
);
}
// an iterator, doesn’t implement remove() since it’s optional
private
class
ListIterator
implements
Iterator
<
Item
>
{
private
Node
<
Item
>
current
;
public
ListIterator
(
Node
<
Item
>
first
)
{
current
=
first
;
}
public
boolean
hasNext
()
{
return
current
!=
null
;
}
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
public
Item
next
()
{
if
(
!
hasNext
())
throw
new
NoSuchElementException
();
Item
item
=
current
.
item
;
current
=
current
.
next
;
return
item
;
}
}
/**
* Unit tests the {
@code
Stack} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
Stack
<
String
>
stack
=
new
Stack
<
String
>
();
while
(
!
StdIn
.
isEmpty
())
{
String
item
=
StdIn
.
readString
();
if
(
!
item
.
equals
(
“-”
))
stack
.
push
(
item
);
else
if
(
!
stack
.
isEmpty
())
StdOut
.
print
(
stack
.
pop
()
+
” ”
);
}
StdOut
.
println
(
“(”
+
stack
.
size
()
+
” left on stack)”
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/StaticSETofInts.java
edu/princeton/cs/algs4/StaticSETofInts.java
/******************************************************************************
* Compilation: javac StaticSetOfInts.java
* Execution: none
* Dependencies: StdOut.java
*
* Data type to store a set of integers.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Arrays
;
/**
* The {
@code
StaticSETofInts} class represents a set of integers.
* It supports searching for a given integer is in the set. It accomplishes
* this by keeping the set of integers in a sorted array and using
* binary search to find the given integer.
*
* The rank and contains operations take
* logarithmic time in the worst case.
*
* For additional documentation, see Section 1.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
StaticSETofInts
{
private
int
[]
a
;
/**
* Initializes a set of integers specified by the integer array.
*
@param
keys the array of integers
*
@throws
IllegalArgumentException if the array contains duplicate integers
*/
public
StaticSETofInts
(
int
[]
keys
)
{
// defensive copy
a
=
new
int
[
keys
.
length
];
for
(
int
i
=
0
;
i
<
keys
.
length
;
i
++
)
a
[
i
]
=
keys
[
i
];
// sort the integers
Arrays
.
sort
(
a
);
// check for duplicates
for
(
int
i
=
1
;
i
<
a
.
length
;
i
++
)
if
(
a
[
i
]
==
a
[
i
-
1
])
throw
new
IllegalArgumentException
(
"Argument arrays contains duplicate keys."
);
}
/**
* Is the key in this set of integers?
*
@param
key the search key
*
@return
true if the set of integers contains the key; false otherwise
*/
public
boolean
contains
(
int
key
)
{
return
rank
(
key
)
!=
-
1
;
}
/**
* Returns either the index of the search key in the sorted array
* (if the key is in the set) or -1 (if the key is not in the set).
*
@param
key the search key
*
@return
the number of keys in this set less than the key (if the key is in the set)
* or -1 (if the key is not in the set).
*/
public
int
rank
(
int
key
)
{
int
lo
=
0
;
int
hi
=
a
.
length
-
1
;
while
(
lo
<=
hi
)
{
// Key is in a[lo..hi] or not present.
int
mid
=
lo
+
(
hi
-
lo
)
/
2
;
if
(
key
<
a
[
mid
])
hi
=
mid
-
1
;
else
if
(
key
>
a
[
mid
])
lo
=
mid
+
1
;
else
return
mid
;
}
return
–
1
;
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/StdArrayIO.java
edu/princeton/cs/algs4/StdArrayIO.java
/******************************************************************************
* Compilation: javac StdArrayIO.java
* Execution: java StdArrayIO < input.txt * Dependencies: StdOut.java * Data files: https://introcs.cs.princeton.edu/java/22library/tinyDouble1D.txt * https://introcs.cs.princeton.edu/java/22library/tinyDouble2D.txt * https://introcs.cs.princeton.edu/java/22library/tinyBoolean2D.txt * * A library for reading in 1D and 2D arrays of integers, doubles, * and booleans from standard input and printing them out to * standard output. * * % more tinyDouble1D.txt * 4 * .000 .246 .222 -.032 * * % more tinyDouble2D.txt * 4 3 * .000 .270 .000 * .246 .224 -.036 * .222 .176 .0893 * -.032 .739 .270 * * % more tinyBoolean2D.txt * 4 3 * 1 1 0 * 0 0 0 * 0 1 1 * 1 1 1 * * % cat tinyDouble1D.txt tinyDouble2D.txt tinyBoolean2D.txt | java StdArrayIO * 4 * 0.00000 0.24600 0.22200 -0.03200 * * 4 3 * 0.00000 0.27000 0.00000 * 0.24600 0.22400 -0.03600 * 0.22200 0.17600 0.08930 * 0.03200 0.73900 0.27000 * * 4 3 * 1 1 0 * 0 0 0 * 0 1 1 * 1 1 1 * ******************************************************************************/ package edu . princeton . cs . algs4 ; /** * Standard array IO. This class provides methods for reading
* in 1D and 2D arrays from standard input and printing out to
* standard output.
*
* For additional documentation, see
* Section 2.2 of
* Computer Science: An Interdisciplinary Approach
* by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
StdArrayIO
{
// it doesn’t make sense to instantiate this class
private
StdArrayIO
()
{
}
/**
* Reads a 1D array of doubles from standard input and returns it.
*
*
@return
the 1D array of doubles
*/
public
static
double
[]
readDouble1D
()
{
int
n
=
StdIn
.
readInt
();
double
[]
a
=
new
double
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
a
[
i
]
=
StdIn
.
readDouble
();
}
return
a
;
}
/**
* Prints an array of doubles to standard output.
*
*
@param
a the 1D array of doubles
*/
public
static
void
print
(
double
[]
a
)
{
int
n
=
a
.
length
;
StdOut
.
println
(
n
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
StdOut
.
printf
(
"%9.5f "
,
a
[
i
]);
}
StdOut
.
println
();
}
/**
* Reads a 2D array of doubles from standard input and returns it.
*
*
@return
the 2D array of doubles
*/
public
static
double
[][]
readDouble2D
()
{
int
m
=
StdIn
.
readInt
();
int
n
=
StdIn
.
readInt
();
double
[][]
a
=
new
double
[
m
][
n
];
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
a
[
i
][
j
]
=
StdIn
.
readDouble
();
}
}
return
a
;
}
/**
* Prints the 2D array of doubles to standard output.
*
*
@param
a the 2D array of doubles
*/
public
static
void
print
(
double
[][]
a
)
{
int
m
=
a
.
length
;
int
n
=
a
[
0
].
length
;
StdOut
.
println
(
m
+
" "
+
n
);
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
StdOut
.
printf
(
"%9.5f "
,
a
[
i
][
j
]);
}
StdOut
.
println
();
}
}
/**
* Reads a 1D array of integers from standard input and returns it.
*
*
@return
the 1D array of integers
*/
public
static
int
[]
readInt1D
()
{
int
n
=
StdIn
.
readInt
();
int
[]
a
=
new
int
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
a
[
i
]
=
StdIn
.
readInt
();
}
return
a
;
}
/**
* Prints an array of integers to standard output.
*
*
@param
a the 1D array of integers
*/
public
static
void
print
(
int
[]
a
)
{
int
n
=
a
.
length
;
StdOut
.
println
(
n
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
StdOut
.
printf
(
"%9d "
,
a
[
i
]);
}
StdOut
.
println
();
}
/**
* Reads a 2D array of integers from standard input and returns it.
*
*
@return
the 2D array of integers
*/
public
static
int
[][]
readInt2D
()
{
int
m
=
StdIn
.
readInt
();
int
n
=
StdIn
.
readInt
();
int
[][]
a
=
new
int
[
m
][
n
];
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
a
[
i
][
j
]
=
StdIn
.
readInt
();
}
}
return
a
;
}
/**
* Print a 2D array of integers to standard output.
*
*
@param
a the 2D array of integers
*/
public
static
void
print
(
int
[][]
a
)
{
int
m
=
a
.
length
;
int
n
=
a
[
0
].
length
;
StdOut
.
println
(
m
+
" "
+
n
);
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
StdOut
.
printf
(
"%9d "
,
a
[
i
][
j
]);
}
StdOut
.
println
();
}
}
/**
* Reads a 1D array of booleans from standard input and returns it.
*
*
@return
the 1D array of booleans
*/
public
static
boolean
[]
readBoolean1D
()
{
int
n
=
StdIn
.
readInt
();
boolean
[]
a
=
new
boolean
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
a
[
i
]
=
StdIn
.
readBoolean
();
}
return
a
;
}
/**
* Prints a 1D array of booleans to standard output.
*
*
@param
a the 1D array of booleans
*/
public
static
void
print
(
boolean
[]
a
)
{
int
n
=
a
.
length
;
StdOut
.
println
(
n
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
if
(
a
[
i
])
StdOut
.
print
(
"1 "
);
else
StdOut
.
print
(
"0 "
);
}
StdOut
.
println
();
}
/**
* Reads a 2D array of booleans from standard input and returns it.
*
*
@return
the 2D array of booleans
*/
public
static
boolean
[][]
readBoolean2D
()
{
int
m
=
StdIn
.
readInt
();
int
n
=
StdIn
.
readInt
();
boolean
[][]
a
=
new
boolean
[
m
][
n
];
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
a
[
i
][
j
]
=
StdIn
.
readBoolean
();
}
}
return
a
;
}
/**
* Prints a 2D array of booleans to standard output.
*
*
@param
a the 2D array of booleans
*/
public
static
void
print
(
boolean
[][]
a
)
{
int
m
=
a
.
length
;
int
n
=
a
[
0
].
length
;
StdOut
.
println
(
m
+
" "
+
n
);
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
if
(
a
[
i
][
j
])
StdOut
.
print
(
"1 "
);
else
StdOut
.
print
(
"0 "
);
}
StdOut
.
println
();
}
}
/**
* Unit tests {
@code
StdArrayIO}.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// read and print an array of doubles
double
[]
a
=
StdArrayIO
.
readDouble1D
();
StdArrayIO
.
print
(
a
);
StdOut
.
println
();
// read and print a matrix of doubles
double
[][]
b
=
StdArrayIO
.
readDouble2D
();
StdArrayIO
.
print
(
b
);
StdOut
.
println
();
// read and print a matrix of doubles
boolean
[][]
d
=
StdArrayIO
.
readBoolean2D
();
StdArrayIO
.
print
(
d
);
StdOut
.
println
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/StdAudio.java
edu/princeton/cs/algs4/StdAudio.java
/******************************************************************************
* Compilation: javac StdAudio.java
* Execution: java StdAudio
* Dependencies: none
*
* Simple library for reading, writing, and manipulating .wav files.
*
*
* Limitations
* -----------
* - Assumes the audio is monaural, little endian, with sampling rate
* of 44,100
* - check when reading .wav files from a .jar file ?
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
javax
.
sound
.
sampled
.
Clip
;
import
java
.
io
.
File
;
import
java
.
io
.
ByteArrayInputStream
;
import
java
.
io
.
InputStream
;
import
java
.
io
.
IOException
;
import
java
.
net
.
URL
;
import
javax
.
sound
.
sampled
.
AudioFileFormat
;
import
javax
.
sound
.
sampled
.
AudioFormat
;
import
javax
.
sound
.
sampled
.
AudioInputStream
;
import
javax
.
sound
.
sampled
.
AudioSystem
;
import
javax
.
sound
.
sampled
.
DataLine
;
import
javax
.
sound
.
sampled
.
LineUnavailableException
;
import
javax
.
sound
.
sampled
.
SourceDataLine
;
import
javax
.
sound
.
sampled
.
UnsupportedAudioFileException
;
import
javax
.
sound
.
sampled
.
LineListener
;
import
javax
.
sound
.
sampled
.
LineEvent
;
/**
* Standard audio. This class provides a basic capability for
* creating, reading, and saving audio.
*
* The audio format uses a sampling rate of 44,100 Hz, 16-bit, monaural.
*
*
* For additional documentation, see Section 1.5 of
* Computer Science: An Interdisciplinary Approach by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
StdAudio
{
/**
* The sample rate: 44,100 Hz for CD quality audio.
*/
public
static
final
int
SAMPLE_RATE
=
44100
;
private
static
final
int
BYTES_PER_SAMPLE
=
2
;
// 16-bit audio
private
static
final
int
BITS_PER_SAMPLE
=
16
;
// 16-bit audio
private
static
final
double
MAX_16_BIT
=
32768
;
private
static
final
int
SAMPLE_BUFFER_SIZE
=
4096
;
private
static
final
int
MONO
=
1
;
private
static
final
int
STEREO
=
2
;
private
static
final
boolean
LITTLE_ENDIAN
=
false
;
private
static
final
boolean
BIG_ENDIAN
=
true
;
private
static
final
boolean
SIGNED
=
true
;
private
static
final
boolean
UNSIGNED
=
false
;
private
static
SourceDataLine
line
;
// to play the sound
private
static
byte
[]
buffer
;
// our internal buffer
private
static
int
bufferSize
=
0
;
// number of samples currently in internal buffer
private
StdAudio
()
{
// can not instantiate
}
// static initializer
static
{
init
();
}
// open up an audio stream
private
static
void
init
()
{
try
{
// 44,100 Hz, 16-bit audio, mono, signed PCM, little endian
AudioFormat
format
=
new
AudioFormat
((
float
)
SAMPLE_RATE
,
BITS_PER_SAMPLE
,
MONO
,
SIGNED
,
LITTLE_ENDIAN
);
DataLine
.
Info
info
=
new
DataLine
.
Info
(
SourceDataLine
.
class
,
format
);
line
=
(
SourceDataLine
)
AudioSystem
.
getLine
(
info
);
line
.
open
(
format
,
SAMPLE_BUFFER_SIZE
*
BYTES_PER_SAMPLE
);
// the internal buffer is a fraction of the actual buffer size, this choice is arbitrary
// it gets divided because we can’t expect the buffered data to line up exactly with when
// the sound card decides to push out its samples.
buffer
=
new
byte
[
SAMPLE_BUFFER_SIZE
*
BYTES_PER_SAMPLE
/
3
];
}
catch
(
LineUnavailableException
e
)
{
System
.
out
.
println
(
e
.
getMessage
());
}
// no sound gets made before this call
line
.
start
();
}
// get an AudioInputStream object from a file
private
static
AudioInputStream
getAudioInputStreamFromFile
(
String
filename
)
{
if
(
filename
==
null
)
{
throw
new
IllegalArgumentException
(
“filename is null”
);
}
try
{
// first try to read file from local file system
File
file
=
new
File
(
filename
);
if
(
file
.
exists
())
{
return
AudioSystem
.
getAudioInputStream
(
file
);
}
// resource relative to .class file
InputStream
is1
=
StdAudio
.
class
.
getResourceAsStream
(
filename
);
if
(
is1
!=
null
)
{
return
AudioSystem
.
getAudioInputStream
(
is1
);
}
// resource relative to classloader root
InputStream
is2
=
StdAudio
.
class
.
getClassLoader
().
getResourceAsStream
(
filename
);
if
(
is2
!=
null
)
{
return
AudioSystem
.
getAudioInputStream
(
is2
);
}
// give up
else
{
throw
new
IllegalArgumentException
(
“could not read ‘”
+
filename
+
“‘”
);
}
}
catch
(
IOException
e
)
{
throw
new
IllegalArgumentException
(
“could not read ‘”
+
filename
+
“‘”
,
e
);
}
catch
(
UnsupportedAudioFileException
e
)
{
throw
new
IllegalArgumentException
(
“file of unsupported audio format: ‘”
+
filename
+
“‘”
,
e
);
}
}
/**
* Closes standard audio.
*/
public
static
void
close
()
{
line
.
drain
();
line
.
stop
();
}
/**
* Writes one sample (between -1.0 and +1.0) to standard audio.
* If the sample is outside the range, it will be clipped.
*
*
@param
sample the sample to play
*
@throws
IllegalArgumentException if the sample is {
@code
Double.NaN}
*/
public
static
void
play
(
double
sample
)
{
if
(
Double
.
isNaN
(
sample
))
throw
new
IllegalArgumentException
(
“sample is NaN”
);
// clip if outside [-1, +1]
if
(
sample
<
-
1.0
)
sample
=
-
1.0
;
if
(
sample
>
+
1.0
)
sample
=
+
1.0
;
// convert to bytes
short
s
=
(
short
)
(
MAX_16_BIT
*
sample
);
if
(
sample
==
1.0
)
s
=
Short
.
MAX_VALUE
;
// special case since 32768 not a short
buffer
[
bufferSize
++
]
=
(
byte
)
s
;
buffer
[
bufferSize
++
]
=
(
byte
)
(
s
>>
8
);
// little endian
// send to sound card if buffer is full
if
(
bufferSize
>=
buffer
.
length
)
{
line
.
write
(
buffer
,
0
,
buffer
.
length
);
bufferSize
=
0
;
}
}
/**
* Writes the array of samples (between -1.0 and +1.0) to standard audio.
* If a sample is outside the range, it will be clipped.
*
*
@param
samples the array of samples to play
*
@throws
IllegalArgumentException if any sample is {
@code
Double.NaN}
*
@throws
IllegalArgumentException if {
@code
samples} is {
@code
null}
*/
public
static
void
play
(
double
[]
samples
)
{
if
(
samples
==
null
)
throw
new
IllegalArgumentException
(
“argument to play() is null”
);
for
(
int
i
=
0
;
i
<
samples
.
length
;
i
++
)
{
play
(
samples
[
i
]);
}
}
/**
* Reads audio samples from a file (in .wav or .au format) and returns
* them as a double array with values between -1.0 and +1.0.
* The audio file must be 16-bit with a sampling rate of 44,100.
* It can be mono or stereo.
*
*
@param
filename the name of the audio file
*
@return
the array of samples
*/
public
static
double
[]
read
(
String
filename
)
{
// make sure that AudioFormat is 16-bit, 44,100 Hz, little endian
final
AudioInputStream
ais
=
getAudioInputStreamFromFile
(
filename
);
AudioFormat
audioFormat
=
ais
.
getFormat
();
// require sampling rate = 44,100 Hz
if
(
audioFormat
.
getSampleRate
()
!=
SAMPLE_RATE
)
{
throw
new
IllegalArgumentException
(
"StdAudio.read() currently supports only a sample rate of "
+
SAMPLE_RATE
+
" Hz\n"
+
"audio format: "
+
audioFormat
);
}
// require 16-bit audio
if
(
audioFormat
.
getSampleSizeInBits
()
!=
BITS_PER_SAMPLE
)
{
throw
new
IllegalArgumentException
(
"StdAudio.read() currently supports only "
+
BITS_PER_SAMPLE
+
"-bit audio\n"
+
"audio format: "
+
audioFormat
);
}
// require little endian
if
(
audioFormat
.
isBigEndian
())
{
throw
new
IllegalArgumentException
(
"StdAudio.read() currently supports only audio stored using little endian\n"
+
"audio format: "
+
audioFormat
);
}
byte
[]
bytes
=
null
;
try
{
int
bytesToRead
=
ais
.
available
();
bytes
=
new
byte
[
bytesToRead
];
int
bytesRead
=
ais
.
read
(
bytes
);
if
(
bytesToRead
!=
bytesRead
)
{
throw
new
IllegalStateException
(
"read only "
+
bytesRead
+
" of "
+
bytesToRead
+
" bytes"
);
}
}
catch
(
IOException
ioe
)
{
throw
new
IllegalArgumentException
(
"could not read '"
+
filename
+
"'"
,
ioe
);
}
int
n
=
bytes
.
length
;
// little endian, mono
if
(
audioFormat
.
getChannels
()
==
MONO
)
{
double
[]
data
=
new
double
[
n
/
2
];
for
(
int
i
=
0
;
i
<
n
/
2
;
i
++
)
{
// little endian, mono
data
[
i
]
=
((
short
)
(((
bytes
[
2
*
i
+
1
]
&
0xFF
)
<<
8
)
|
(
bytes
[
2
*
i
]
&
0xFF
)))
/
((
double
)
MAX_16_BIT
);
}
return
data
;
}
// little endian, stereo
else
if
(
audioFormat
.
getChannels
()
==
STEREO
)
{
double
[]
data
=
new
double
[
n
/
4
];
for
(
int
i
=
0
;
i
<
n
/
4
;
i
++
)
{
double
left
=
((
short
)
(((
bytes
[
4
*
i
+
1
]
&
0xFF
)
<<
8
)
|
(
bytes
[
4
*
i
+
0
]
&
0xFF
)))
/
((
double
)
MAX_16_BIT
);
double
right
=
((
short
)
(((
bytes
[
4
*
i
+
3
]
&
0xFF
)
<<
8
)
|
(
bytes
[
4
*
i
+
2
]
&
0xFF
)))
/
((
double
)
MAX_16_BIT
);
data
[
i
]
=
(
left
+
right
)
/
2.0
;
}
return
data
;
}
// TODO: handle big endian (or other formats)
else
throw
new
IllegalStateException
(
"audio format is neither mono or stereo"
);
}
/**
* Saves the double array as an audio file (using .wav or .au format).
*
*
@param
filename the name of the audio file
*
@param
samples the array of samples
*
@throws
IllegalArgumentException if unable to save {
@code
filename}
*
@throws
IllegalArgumentException if {
@code
samples} is {
@code
null}
*
@throws
IllegalArgumentException if {
@code
filename} is {
@code
null}
*
@throws
IllegalArgumentException if {
@code
filename} extension is not {
@code
.wav}
* or {
@code
.au}
*/
public
static
void
save
(
String
filename
,
double
[]
samples
)
{
if
(
filename
==
null
)
{
throw
new
IllegalArgumentException
(
"filenameis null"
);
}
if
(
samples
==
null
)
{
throw
new
IllegalArgumentException
(
"samples[] is null"
);
}
// assumes 16-bit samples with sample rate = 44,100 Hz
// use 16-bit audio, mono, signed PCM, little Endian
AudioFormat
format
=
new
AudioFormat
(
SAMPLE_RATE
,
16
,
MONO
,
SIGNED
,
LITTLE_ENDIAN
);
byte
[]
data
=
new
byte
[
2
*
samples
.
length
];
for
(
int
i
=
0
;
i
<
samples
.
length
;
i
++
)
{
int
temp
=
(
short
)
(
samples
[
i
]
*
MAX_16_BIT
);
if
(
samples
[
i
]
==
1.0
)
temp
=
Short
.
MAX_VALUE
;
// special case since 32768 not a short
data
[
2
*
i
+
0
]
=
(
byte
)
temp
;
data
[
2
*
i
+
1
]
=
(
byte
)
(
temp
>>
8
);
// little endian
}
// now save the file
try
{
ByteArrayInputStream
bais
=
new
ByteArrayInputStream
(
data
);
AudioInputStream
ais
=
new
AudioInputStream
(
bais
,
format
,
samples
.
length
);
if
(
filename
.
endsWith
(
“.wav”
)
||
filename
.
endsWith
(
“.WAV”
))
{
AudioSystem
.
write
(
ais
,
AudioFileFormat
.
Type
.
WAVE
,
new
File
(
filename
));
}
else
if
(
filename
.
endsWith
(
“.au”
)
||
filename
.
endsWith
(
“.AU”
))
{
AudioSystem
.
write
(
ais
,
AudioFileFormat
.
Type
.
AU
,
new
File
(
filename
));
}
else
{
throw
new
IllegalArgumentException
(
“file type for saving must be .wav or .au”
);
}
}
catch
(
IOException
ioe
)
{
throw
new
IllegalArgumentException
(
“unable to save file ‘”
+
filename
+
“‘”
,
ioe
);
}
}
/**
* Plays an audio file (in .wav, .mid, or .au format) in a background thread.
*
*
@param
filename the name of the audio file
*
@throws
IllegalArgumentException if unable to play {
@code
filename}
*
@throws
IllegalArgumentException if {
@code
filename} is {
@code
null}
*/
public
static
synchronized
void
play
(
final
String
filename
)
{
new
Thread
(
new
Runnable
()
{
public
void
run
()
{
AudioInputStream
ais
=
getAudioInputStreamFromFile
(
filename
);
stream
(
ais
);
}
}).
start
();
}
// https://www3.ntu.edu.sg/home/ehchua/programming/java/J8c_PlayingSound.html
// play a wav or aif file
// javax.sound.sampled.Clip fails for long clips (on some systems), perhaps because
// JVM closes (see remedy in loop)
private
static
void
stream
(
AudioInputStream
ais
)
{
SourceDataLine
line
=
null
;
int
BUFFER_SIZE
=
4096
;
// 4K buffer
try
{
AudioFormat
audioFormat
=
ais
.
getFormat
();
DataLine
.
Info
info
=
new
DataLine
.
Info
(
SourceDataLine
.
class
,
audioFormat
);
line
=
(
SourceDataLine
)
AudioSystem
.
getLine
(
info
);
line
.
open
(
audioFormat
);
line
.
start
();
byte
[]
samples
=
new
byte
[
BUFFER_SIZE
];
int
count
=
0
;
while
((
count
=
ais
.
read
(
samples
,
0
,
BUFFER_SIZE
))
!=
–
1
)
{
line
.
write
(
samples
,
0
,
count
);
}
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
catch
(
LineUnavailableException
e
)
{
e
.
printStackTrace
();
}
finally
{
if
(
line
!=
null
)
{
line
.
drain
();
line
.
close
();
}
}
}
/**
* Loops an audio file (in .wav, .mid, or .au format) in a background thread.
*
*
@param
filename the name of the audio file
*
@throws
IllegalArgumentException if {
@code
filename} is {
@code
null}
*/
public
static
synchronized
void
loop
(
String
filename
)
{
if
(
filename
==
null
)
throw
new
IllegalArgumentException
();
final
AudioInputStream
ais
=
getAudioInputStreamFromFile
(
filename
);
try
{
Clip
clip
=
AudioSystem
.
getClip
();
// Clip clip = (Clip) AudioSystem.getLine(new Line.Info(Clip.class));
clip
.
open
(
ais
);
clip
.
loop
(
Clip
.
LOOP_CONTINUOUSLY
);
}
catch
(
LineUnavailableException
e
)
{
e
.
printStackTrace
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
// keep JVM open
new
Thread
(
new
Runnable
()
{
public
void
run
()
{
while
(
true
)
{
try
{
Thread
.
sleep
(
1000
);
}
catch
(
InterruptedException
e
)
{
e
.
printStackTrace
();
}
}
}
}).
start
();
}
/***************************************************************************
* Unit tests {
@code
StdAudio}.
***************************************************************************/
// create a note (sine wave) of the given frequency (Hz), for the given
// duration (seconds) scaled to the given volume (amplitude)
private
static
double
[]
note
(
double
hz
,
double
duration
,
double
amplitude
)
{
int
n
=
(
int
)
(
StdAudio
.
SAMPLE_RATE
*
duration
);
double
[]
a
=
new
double
[
n
+
1
];
for
(
int
i
=
0
;
i
<=
n
;
i
++
)
a
[
i
]
=
amplitude
*
Math
.
sin
(
2
*
Math
.
PI
*
i
*
hz
/
StdAudio
.
SAMPLE_RATE
);
return
a
;
}
/**
* Test client - play an A major scale to standard audio.
*
*
@param
args the command-line arguments
*/
/**
* Test client - play an A major scale to standard audio.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// 440 Hz for 1 sec
double
freq
=
440.0
;
for
(
int
i
=
0
;
i
<=
StdAudio
.
SAMPLE_RATE
;
i
++
)
{
StdAudio
.
play
(
0.5
*
Math
.
sin
(
2
*
Math
.
PI
*
freq
*
i
/
StdAudio
.
SAMPLE_RATE
));
}
// scale increments
int
[]
steps
=
{
0
,
2
,
4
,
5
,
7
,
9
,
11
,
12
};
for
(
int
i
=
0
;
i
<
steps
.
length
;
i
++
)
{
double
hz
=
440.0
*
Math
.
pow
(
2
,
steps
[
i
]
/
12.0
);
StdAudio
.
play
(
note
(
hz
,
1.0
,
0.5
));
}
// need to call this in non-interactive stuff so the program doesn't terminate
// until all the sound leaves the speaker.
StdAudio
.
close
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/StdDraw.java
edu/princeton/cs/algs4/StdDraw.java
/******************************************************************************
* Compilation: javac StdDraw.java
* Execution: java StdDraw
* Dependencies: none
*
* Standard drawing library. This class provides a basic capability for
* creating drawings with your programs. It uses a simple graphics model that
* allows you to create drawings consisting of geometric shapes (e.g.,
* points, lines, circles, rectangles) in a window on your computer
* and to save the drawings to a file.
*
* Todo
* ----
* - Add support for gradient fill, etc.
* - Fix setCanvasSize() so that it can be called only once.
* - Should setCanvasSize() reset xScale(), yScale(), penRadius(),
* penColor(), and font()
* - On some systems, drawing a line (or other shape) that extends way
* beyond canvas (e.g., to infinity) dimensions does not get drawn.
*
* Remarks
* -------
* - don't use AffineTransform for rescaling since it inverts
* images and strings
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
awt
.
BasicStroke
;
import
java
.
awt
.
Color
;
import
java
.
awt
.
Component
;
import
java
.
awt
.
FileDialog
;
import
java
.
awt
.
Font
;
import
java
.
awt
.
FontMetrics
;
import
java
.
awt
.
Graphics
;
import
java
.
awt
.
Graphics2D
;
import
java
.
awt
.
Image
;
import
java
.
awt
.
MediaTracker
;
import
java
.
awt
.
RenderingHints
;
import
java
.
awt
.
Toolkit
;
import
java
.
awt
.
event
.
ActionEvent
;
import
java
.
awt
.
event
.
ActionListener
;
import
java
.
awt
.
event
.
MouseEvent
;
import
java
.
awt
.
event
.
MouseListener
;
import
java
.
awt
.
event
.
MouseMotionListener
;
import
java
.
awt
.
event
.
KeyEvent
;
import
java
.
awt
.
event
.
KeyListener
;
import
java
.
awt
.
geom
.
Arc2D
;
import
java
.
awt
.
geom
.
Ellipse2D
;
import
java
.
awt
.
geom
.
GeneralPath
;
import
java
.
awt
.
geom
.
Line2D
;
import
java
.
awt
.
geom
.
Rectangle2D
;
import
java
.
awt
.
image
.
BufferedImage
;
import
java
.
awt
.
image
.
DirectColorModel
;
import
java
.
awt
.
image
.
WritableRaster
;
import
java
.
io
.
File
;
import
java
.
io
.
IOException
;
import
java
.
net
.
MalformedURLException
;
import
java
.
net
.
URL
;
import
java
.
util
.
LinkedList
;
import
java
.
util
.
TreeSet
;
import
java
.
util
.
NoSuchElementException
;
import
javax
.
imageio
.
ImageIO
;
import
javax
.
swing
.
ImageIcon
;
import
javax
.
swing
.
JFrame
;
import
javax
.
swing
.
JLabel
;
import
javax
.
swing
.
JMenu
;
import
javax
.
swing
.
JMenuBar
;
import
javax
.
swing
.
JMenuItem
;
import
javax
.
swing
.
KeyStroke
;
/**
* The {
@code
StdDraw} class provides a basic capability for
* creating drawings with your programs. It uses a simple graphics model that
* allows you to create drawings consisting of points, lines, squares,
* circles, and other geometric shapes in a window on your computer and
* to save the drawings to a file. Standard drawing also includes
* facilities for text, color, pictures, and animation, along with
* user interaction via the keyboard and mouse.
*
* Getting started.
* To use this class, you must have {
@code
StdDraw.class} in your
* Java classpath. If you used our autoinstaller, you should be all set.
* Otherwise, either download
* and add to your Java classpath or download
* and put a copy in your working directory.
*
* Now, type the following short program into your editor:
*
* public class TestStdDraw { * public static void main(String[] args) { * StdDraw.setPenRadius(0.05); * StdDraw.setPenColor(StdDraw.BLUE); * StdDraw.point(0.5, 0.5); * StdDraw.setPenColor(StdDraw.MAGENTA); * StdDraw.line(0.2, 0.2, 0.8, 0.2); * } * } *
* If you compile and execute the program, you should see a window
* appear with a thick magenta line and a blue point.
* This program illustrates the two main types of methods in standard
* drawing—methods that draw geometric shapes and methods that
* control drawing parameters.
* The methods {
@code
StdDraw.line()} and {
@code
StdDraw.point()}
* draw lines and points; the methods {
@code
StdDraw.setPenRadius()}
* and {
@code
StdDraw.setPenColor()} control the line thickness and color.
*
* Points and lines.
* You can draw points and line segments with the following methods:
*
*
*
*
*
* The x– and y-coordinates must be in the drawing area
* (between 0 and 1 and by default) or the points and lines will not be visible.
*
* Squares, circles, rectangles, and ellipses.
* You can draw squares, circles, rectangles, and ellipses using
* the following methods:
*
*
*
*
*
*
*
* All of these methods take as arguments the location and size of the shape.
* The location is always specified by the x– and y-coordinates
* of its center.
* The size of a circle is specified by its radius and the size of an ellipse is
* specified by the lengths of its semi-major and semi-minor axes.
* The size of a square or rectangle is specified by its half-width or half-height.
* The convention for drawing squares and rectangles is parallel to those for
* drawing circles and ellipses, but may be unexpected to the uninitiated.
*
* The methods above trace outlines of the given shapes. The following methods
* draw filled versions:
*
*
*
*
*
*
*
* Circular arcs.
* You can draw circular arcs with the following method:
*
*
*
*
* The arc is from the circle centered at (x, y) of the specified radius.
* The arc extends from angle1 to angle2. By convention, the angles are
* polar (counterclockwise angle from the x-axis)
* and represented in degrees. For example, {
@code
StdDraw.arc(0.0, 0.0, 1.0, 0, 90)}
* draws the arc of the unit circle from 3 o’clock (0 degrees) to 12 o’clock (90 degrees).
*
* Polygons.
* You can draw polygons with the following methods:
*
*
*
*
*
* The points in the polygon are ({
@code
x[i]}, {
@code
y[i]}).
* For example, the following code fragment draws a filled diamond
* with vertices (0.1, 0.2), (0.2, 0.3), (0.3, 0.2), and (0.2, 0.1):
*
* double[] x = { 0.1, 0.2, 0.3, 0.2 }; * double[] y = { 0.2, 0.3, 0.2, 0.1 }; * StdDraw.filledPolygon(x, y); *
*
* Pen size.
* The pen is circular, so that when you set the pen radius to r
* and draw a point, you get a circle of radius r. Also, lines are
* of thickness 2r and have rounded ends. The default pen radius
* is 0.005 and is not affected by coordinate scaling. This default pen
* radius is about 1/200 the width of the default canvas, so that if
* you draw 100 points equally spaced along a horizontal or vertical line,
* you will be able to see individual circles, but if you draw 200 such
* points, the result will look like a line.
*
*
*
*
* For example, {
@code
StdDraw.setPenRadius(0.025)} makes
* the thickness of the lines and the size of the points to be five times
* the 0.005 default.
* To draw points with the minimum possible radius (one pixel on typical
* displays), set the pen radius to 0.0.
*
* Pen color.
* All geometric shapes (such as points, lines, and circles) are drawn using
* the current pen color. By default, it is black.
* You can change the pen color with the following methods:
*
*
*
*
*
* The first method allows you to specify colors using the RGB color system.
* This color picker
* is a convenient way to find a desired color.
* The second method allows you to specify colors using the
* {
@link
Color} data type that is discussed in Chapter 3. Until then,
* you can use this method with one of these predefined colors in standard drawing:
* {
@link
#BLACK}, {
@link
#BLUE}, {
@link
#CYAN}, {
@link
#DARK_GRAY}, {
@link
#GRAY},
* {
@link
#GREEN}, {
@link
#LIGHT_GRAY}, {
@link
#MAGENTA}, {
@link
#ORANGE},
* {
@link
#PINK}, {
@link
#RED}, {
@link
#WHITE}, {
@link
#YELLOW},
* {
@link
#BOOK_BLUE}, {
@link
#BOOK_LIGHT_BLUE}, {
@link
#BOOK_RED}, and
* {
@link
#PRINCETON_ORANGE}.
* For example, {
@code
StdDraw.setPenColor(StdDraw.MAGENTA)} sets the
* pen color to magenta.
*
* Canvas size.
* By default, all drawing takes places in a 512-by-512 canvas.
* The canvas does not include the window title or window border.
* You can change the size of the canvas with the following method:
*
*
*
*
* This sets the canvas size to be width-by-height pixels.
* It also erases the current drawing and resets the coordinate system,
* pen radius, pen color, and font back to their default values.
* Ordinarly, this method is called once, at the very beginning of a program.
* For example, {
@code
StdDraw.setCanvasSize(800, 800)}
* sets the canvas size to be 800-by-800 pixels.
*
* Canvas scale and coordinate system.
* By default, all drawing takes places in the unit square, with (0, 0) at
* lower left and (1, 1) at upper right. You can change the default
* coordinate system with the following methods:
*
*
*
*
*
*
* The arguments are the coordinates of the minimum and maximum
* x– or y-coordinates that will appear in the canvas.
* For example, if you wish to use the default coordinate system but
* leave a small margin, you can call {
@code
StdDraw.setScale(-.05, 1.05)}.
*
* These methods change the coordinate system for subsequent drawing
* commands; they do not affect previous drawings.
* These methods do not change the canvas size; so, if the x–
* and y-scales are different, squares will become rectangles
* and circles will become ellipses.
*
* Text.
* You can use the following methods to annotate your drawings with text:
*
*
*
*
*
*
*
* The first two methods write the specified text in the current font,
* centered at (x, y).
* The second method allows you to rotate the text.
* The last two methods either left- or right-align the text at (x, y).
*
* The default font is a Sans Serif font with point size 16.
* You can use the following method to change the font:
*
*
*
*
* You use the {
@link
Font} data type to specify the font. This allows you to
* choose the face, size, and style of the font. For example, the following
* code fragment sets the font to Arial Bold, 60 point.
*
* Font font = new Font("Arial", Font.BOLD, 60); * StdDraw.setFont(font); * StdDraw.text(0.5, 0.5, "Hello, World"); *
*
* Images.
* You can use the following methods to add images to your drawings:
*
*
*
*
*
*
*
* These methods draw the specified image, centered at (x, y).
* The supported image formats are JPEG, PNG, and GIF.
* The image will display at its native size, independent of the coordinate system.
* Optionally, you can rotate the image a specified number of degrees counterclockwise
* or rescale it to fit snugly inside a width-by-height bounding box.
*
* Saving to a file.
* You save your image to a file using the File → Save menu option.
* You can also save a file programatically using the following method:
*
*
*
*
* The supported image formats are JPEG and PNG. The filename must have either the
* extension or .
* We recommend using PNG for drawing that consist solely of geometric shapes and JPEG
* for drawings that contains pictures.
*
* Clearing the canvas.
* To clear the entire drawing canvas, you can use the following methods:
*
*
*
*
*
* The first method clears the canvas to white; the second method
* allows you to specify a color of your choice. For example,
* {
@code
StdDraw.clear(StdDraw.LIGHT_GRAY)} clears the canvas to a shade
* of gray.
*
* Computer animations and double buffering.
* Double buffering is one of the most powerful features of standard drawing,
* enabling computer animations.
* The following methods control the way in which objects are drawn:
*
*
*
*
*
*
*
* By default, double buffering is disabled, which means that as soon as you
* call a drawing
* method—such as {
@code
point()} or {
@code
line()}—the
* results appear on the screen.
*
* When double buffering is enabled by calling {
@link
#enableDoubleBuffering()},
* all drawing takes place on the offscreen canvas. The offscreen canvas
* is not displayed. Only when you call
* {
@link
#show()} does your drawing get copied from the offscreen canvas to
* the onscreen canvas, where it is displayed in the standard drawing window. You
* can think of double buffering as collecting all of the lines, points, shapes,
* and text that you tell it to draw, and then drawing them all
* simultaneously, upon request.
*
* The most important use of double buffering is to produce computer
* animations, creating the illusion of motion by rapidly
* displaying static drawings. To produce an animation, repeat
* the following four steps:
*
*
*
*
*
*
*
* The {
@link
#clear()}, {
@link
#show()}, and {
@link
#pause(int t)} methods
* support the first, third, and fourth of these steps, respectively.
*
* For example, this code fragment animates two balls moving in a circle.
*
* StdDraw.setScale(-2, +2); * StdDraw.enableDoubleBuffering(); * * for (double t = 0.0; true; t += 0.02) { * double x = Math.sin(t); * double y = Math.cos(t); * StdDraw.clear(); * StdDraw.filledCircle(x, y, 0.05); * StdDraw.filledCircle(-x, -y, 0.05); * StdDraw.show(); * StdDraw.pause(20); * } *
*
* Keyboard and mouse inputs.
* Standard drawing has very basic support for keyboard and mouse input.
* It is much less powerful than most user interface libraries provide, but also much simpler.
* You can use the following methods to intercept mouse events:
*
*
*
*
*
*
* The first method tells you whether a mouse button is currently being pressed.
* The last two methods tells you the x– and y-coordinates of the mouse’s
* current position, using the same coordinate system as the canvas (the unit square, by default).
* You should use these methods in an animation loop that waits a short while before trying
* to poll the mouse for its current state.
* You can use the following methods to intercept keyboard events:
*
*
*
*
*
*
* If the user types lots of keys, they will be saved in a list until you process them.
* The first method tells you whether the user has typed a key (that your program has
* not yet processed).
* The second method returns the next key that the user typed (that your program has
* not yet processed) and removes it from the list of saved keystrokes.
* The third method tells you whether a key is currently being pressed.
*
* Accessing control parameters.
* You can use the following methods to access the current pen color, pen radius,
* and font:
*
*
*
*
*
*
* These methods are useful when you want to temporarily change a
* control parameter and reset it back to its original value.
*
* Corner cases.
* Here are some corner cases.
*
*
* However, only the part of the object that appears inside the canvas
* will be visible.
*
* {
@link
IllegalArgumentException}.
*
* {
@link
Double#POSITIVE_INFINITY}, or {
@link
Double#NEGATIVE_INFINITY}
* argument will throw an {
@link
IllegalArgumentException}.
*
* y-coordinate that is way outside the canvas (such as the line segment
* from (0.5, –10^308) to (0.5, 10^308) may not be visible even in the
* part of the canvas where it should be.
*
*
* Performance tricks.
* Standard drawing is capable of drawing large amounts of data.
* Here are a few tricks and tips:
*
*
* number of objects.
* That is, call {
@link
#enableDoubleBuffering()} before
* the sequence of drawing commands and call {
@link
#show()} afterwards.
* Incrementally displaying a complex drawing while it is being
* created can be intolerably inefficient on many computer systems.
*
* only once per frame, not after drawing each individual object.
*
* Java will cache the image, so you do not incur the cost of reading
* from a file each time.
*
*
* Known bugs and issues.
*
*
* inside the canvas if the center point (x, y) is outside the
* canvas.
* This bug appears only on some systems.
*
*
* Reference.
* For additional documentation,
* see Section 1.5 of
* Computer Science: An Interdisciplinary Approach
* by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
StdDraw
implements
ActionListener
,
MouseListener
,
MouseMotionListener
,
KeyListener
{
/**
* The color black.
*/
public
static
final
Color
BLACK
=
Color
.
BLACK
;
/**
* The color blue.
*/
public
static
final
Color
BLUE
=
Color
.
BLUE
;
/**
* The color cyan.
*/
public
static
final
Color
CYAN
=
Color
.
CYAN
;
/**
* The color dark gray.
*/
public
static
final
Color
DARK_GRAY
=
Color
.
DARK_GRAY
;
/**
* The color gray.
*/
public
static
final
Color
GRAY
=
Color
.
GRAY
;
/**
* The color green.
*/
public
static
final
Color
GREEN
=
Color
.
GREEN
;
/**
* The color light gray.
*/
public
static
final
Color
LIGHT_GRAY
=
Color
.
LIGHT_GRAY
;
/**
* The color magenta.
*/
public
static
final
Color
MAGENTA
=
Color
.
MAGENTA
;
/**
* The color orange.
*/
public
static
final
Color
ORANGE
=
Color
.
ORANGE
;
/**
* The color pink.
*/
public
static
final
Color
PINK
=
Color
.
PINK
;
/**
* The color red.
*/
public
static
final
Color
RED
=
Color
.
RED
;
/**
* The color white.
*/
public
static
final
Color
WHITE
=
Color
.
WHITE
;
/**
* The color yellow.
*/
public
static
final
Color
YELLOW
=
Color
.
YELLOW
;
/**
* Shade of blue used in Introduction to Programming in Java.
* It is Pantone 300U. The RGB values are approximately (9, 90, 166).
*/
public
static
final
Color
BOOK_BLUE
=
new
Color
(
9
,
90
,
166
);
/**
* Shade of light blue used in Introduction to Programming in Java.
* The RGB values are approximately (103, 198, 243).
*/
public
static
final
Color
BOOK_LIGHT_BLUE
=
new
Color
(
103
,
198
,
243
);
/**
* Shade of red used in Algorithms, 4th edition.
* It is Pantone 1805U. The RGB values are approximately (150, 35, 31).
*/
public
static
final
Color
BOOK_RED
=
new
Color
(
150
,
35
,
31
);
/**
* Shade of orange used in Princeton University’s identity.
* It is PMS 158. The RGB values are approximately (245, 128, 37).
*/
public
static
final
Color
PRINCETON_ORANGE
=
new
Color
(
245
,
128
,
37
);
// default colors
private
static
final
Color
DEFAULT_PEN_COLOR
=
BLACK
;
private
static
final
Color
DEFAULT_CLEAR_COLOR
=
WHITE
;
// current pen color
private
static
Color
penColor
;
// default canvas size is DEFAULT_SIZE-by-DEFAULT_SIZE
private
static
final
int
DEFAULT_SIZE
=
512
;
private
static
int
width
=
DEFAULT_SIZE
;
private
static
int
height
=
DEFAULT_SIZE
;
// default pen radius
private
static
final
double
DEFAULT_PEN_RADIUS
=
0.002
;
// current pen radius
private
static
double
penRadius
;
// show we draw immediately or wait until next show?
private
static
boolean
defer
=
false
;
// boundary of drawing canvas, 0% border
// private static final double BORDER = 0.05;
private
static
final
double
BORDER
=
0.00
;
private
static
final
double
DEFAULT_XMIN
=
0.0
;
private
static
final
double
DEFAULT_XMAX
=
1.0
;
private
static
final
double
DEFAULT_YMIN
=
0.0
;
private
static
final
double
DEFAULT_YMAX
=
1.0
;
private
static
double
xmin
,
ymin
,
xmax
,
ymax
;
// for synchronization
private
static
Object
mouseLock
=
new
Object
();
private
static
Object
keyLock
=
new
Object
();
// default font
private
static
final
Font
DEFAULT_FONT
=
new
Font
(
“SansSerif”
,
Font
.
PLAIN
,
16
);
// current font
private
static
Font
font
;
// double buffered graphics
private
static
BufferedImage
offscreenImage
,
onscreenImage
;
private
static
Graphics2D
offscreen
,
onscreen
;
// singleton for callbacks: avoids generation of extra .class files
private
static
StdDraw
std
=
new
StdDraw
();
// the frame for drawing to the screen
private
static
JFrame
frame
;
// mouse state
private
static
boolean
isMousePressed
=
false
;
private
static
double
mouseX
=
0
;
private
static
double
mouseY
=
0
;
// queue of typed key characters
private
static
LinkedList
<
Character
>
keysTyped
=
new
LinkedList
<
Character
>
();
// set of key codes currently pressed down
private
static
TreeSet
<
Integer
>
keysDown
=
new
TreeSet
<
Integer
>
();
// singleton pattern: client can’t instantiate
private
StdDraw
()
{
}
// static initializer
static
{
init
();
}
/**
* Sets the canvas (drawing area) to be 512-by-512 pixels.
* This also erases the current drawing and resets the coordinate system,
* pen radius, pen color, and font back to their default values.
* Ordinarly, this method is called once, at the very beginning
* of a program.
*/
public
static
void
setCanvasSize
()
{
setCanvasSize
(
DEFAULT_SIZE
,
DEFAULT_SIZE
);
}
/**
* Sets the canvas (drawing area) to be width-by-height pixels.
* This also erases the current drawing and resets the coordinate system,
* pen radius, pen color, and font back to their default values.
* Ordinarly, this method is called once, at the very beginning
* of a program.
*
*
@param
canvasWidth the width as a number of pixels
*
@param
canvasHeight the height as a number of pixels
*
@throws
IllegalArgumentException unless both {
@code
canvasWidth} and
* {
@code
canvasHeight} are positive
*/
public
static
void
setCanvasSize
(
int
canvasWidth
,
int
canvasHeight
)
{
if
(
canvasWidth
<=
0
)
throw
new
IllegalArgumentException
(
"width must be positive"
);
if
(
canvasHeight
<=
0
)
throw
new
IllegalArgumentException
(
"height must be positive"
);
width
=
canvasWidth
;
height
=
canvasHeight
;
init
();
}
// init
private
static
void
init
()
{
if
(
frame
!=
null
)
frame
.
setVisible
(
false
);
frame
=
new
JFrame
();
offscreenImage
=
new
BufferedImage
(
2
*
width
,
2
*
height
,
BufferedImage
.
TYPE_INT_ARGB
);
onscreenImage
=
new
BufferedImage
(
2
*
width
,
2
*
height
,
BufferedImage
.
TYPE_INT_ARGB
);
offscreen
=
offscreenImage
.
createGraphics
();
onscreen
=
onscreenImage
.
createGraphics
();
offscreen
.
scale
(
2.0
,
2.0
);
// since we made it 2x as big
setXscale
();
setYscale
();
offscreen
.
setColor
(
DEFAULT_CLEAR_COLOR
);
offscreen
.
fillRect
(
0
,
0
,
width
,
height
);
setPenColor
();
setPenRadius
();
setFont
();
clear
();
// add antialiasing
RenderingHints
hints
=
new
RenderingHints
(
RenderingHints
.
KEY_ANTIALIASING
,
RenderingHints
.
VALUE_ANTIALIAS_ON
);
hints
.
put
(
RenderingHints
.
KEY_RENDERING
,
RenderingHints
.
VALUE_RENDER_QUALITY
);
offscreen
.
addRenderingHints
(
hints
);
// frame stuff
RetinaImageIcon
icon
=
new
RetinaImageIcon
(
onscreenImage
);
JLabel
draw
=
new
JLabel
(
icon
);
draw
.
addMouseListener
(
std
);
draw
.
addMouseMotionListener
(
std
);
frame
.
setContentPane
(
draw
);
frame
.
addKeyListener
(
std
);
// JLabel cannot get keyboard focus
frame
.
setFocusTraversalKeysEnabled
(
false
);
// allow VK_TAB with isKeyPressed()
frame
.
setResizable
(
false
);
frame
.
setDefaultCloseOperation
(
JFrame
.
EXIT_ON_CLOSE
);
// closes all windows
// frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // closes only current window
frame
.
setTitle
(
"Standard Draw"
);
frame
.
setJMenuBar
(
createMenuBar
());
frame
.
pack
();
frame
.
requestFocusInWindow
();
frame
.
setVisible
(
true
);
}
// create the menu bar (changed to private)
private
static
JMenuBar
createMenuBar
()
{
JMenuBar
menuBar
=
new
JMenuBar
();
JMenu
menu
=
new
JMenu
(
"File"
);
menuBar
.
add
(
menu
);
JMenuItem
menuItem1
=
new
JMenuItem
(
" Save... "
);
menuItem1
.
addActionListener
(
std
);
// Java 10+: replace getMenuShortcutKeyMask() with getMenuShortcutKeyMaskEx()
menuItem1
.
setAccelerator
(
KeyStroke
.
getKeyStroke
(
KeyEvent
.
VK_S
,
Toolkit
.
getDefaultToolkit
().
getMenuShortcutKeyMask
()));
menu
.
add
(
menuItem1
);
return
menuBar
;
}
/***************************************************************************
* User and screen coordinate systems.
***************************************************************************/
// throw an IllegalArgumentException if x is NaN or infinite
private
static
void
validate
(
double
x
,
String
name
)
{
if
(
Double
.
isNaN
(
x
))
throw
new
IllegalArgumentException
(
name
+
" is NaN"
);
if
(
Double
.
isInfinite
(
x
))
throw
new
IllegalArgumentException
(
name
+
" is infinite"
);
}
// throw an IllegalArgumentException if s is null
private
static
void
validateNonnegative
(
double
x
,
String
name
)
{
if
(
x
<
0
)
throw
new
IllegalArgumentException
(
name
+
" negative"
);
}
// throw an IllegalArgumentException if s is null
private
static
void
validateNotNull
(
Object
x
,
String
name
)
{
if
(
x
==
null
)
throw
new
IllegalArgumentException
(
name
+
" is null"
);
}
/**
* Sets the x-scale to be the default (between 0.0 and 1.0).
*/
public
static
void
setXscale
()
{
setXscale
(
DEFAULT_XMIN
,
DEFAULT_XMAX
);
}
/**
* Sets the y-scale to be the default (between 0.0 and 1.0).
*/
public
static
void
setYscale
()
{
setYscale
(
DEFAULT_YMIN
,
DEFAULT_YMAX
);
}
/**
* Sets the x-scale and y-scale to be the default
* (between 0.0 and 1.0).
*/
public
static
void
setScale
()
{
setXscale
();
setYscale
();
}
/**
* Sets the x-scale to the specified range.
*
*
@param
min the minimum value of the x-scale
*
@param
max the maximum value of the x-scale
*
@throws
IllegalArgumentException if {
@code
(max == min)}
*
@throws
IllegalArgumentException if either {
@code
min} or {
@code
max} is either NaN or infinite
*/
public
static
void
setXscale
(
double
min
,
double
max
)
{
validate
(
min
,
“min”
);
validate
(
max
,
“max”
);
double
size
=
max
–
min
;
if
(
size
==
0.0
)
throw
new
IllegalArgumentException
(
“the min and max are the same”
);
synchronized
(
mouseLock
)
{
xmin
=
min
–
BORDER
*
size
;
xmax
=
max
+
BORDER
*
size
;
}
}
/**
* Sets the y-scale to the specified range.
*
*
@param
min the minimum value of the y-scale
*
@param
max the maximum value of the y-scale
*
@throws
IllegalArgumentException if {
@code
(max == min)}
*
@throws
IllegalArgumentException if either {
@code
min} or {
@code
max} is either NaN or infinite
*/
public
static
void
setYscale
(
double
min
,
double
max
)
{
validate
(
min
,
“min”
);
validate
(
max
,
“max”
);
double
size
=
max
–
min
;
if
(
size
==
0.0
)
throw
new
IllegalArgumentException
(
“the min and max are the same”
);
synchronized
(
mouseLock
)
{
ymin
=
min
–
BORDER
*
size
;
ymax
=
max
+
BORDER
*
size
;
}
}
/**
* Sets both the x-scale and y-scale to the (same) specified range.
*
*
@param
min the minimum value of the x– and y-scales
*
@param
max the maximum value of the x– and y-scales
*
@throws
IllegalArgumentException if {
@code
(max == min)}
*
@throws
IllegalArgumentException if either {
@code
min} or {
@code
max} is either NaN or infinite
*/
public
static
void
setScale
(
double
min
,
double
max
)
{
validate
(
min
,
“min”
);
validate
(
max
,
“max”
);
double
size
=
max
–
min
;
if
(
size
==
0.0
)
throw
new
IllegalArgumentException
(
“the min and max are the same”
);
synchronized
(
mouseLock
)
{
xmin
=
min
–
BORDER
*
size
;
xmax
=
max
+
BORDER
*
size
;
ymin
=
min
–
BORDER
*
size
;
ymax
=
max
+
BORDER
*
size
;
}
}
// helper functions that scale from user coordinates to screen coordinates and back
private
static
double
scaleX
(
double
x
)
{
return
width
*
(
x
–
xmin
)
/
(
xmax
–
xmin
);
}
private
static
double
scaleY
(
double
y
)
{
return
height
*
(
ymax
–
y
)
/
(
ymax
–
ymin
);
}
private
static
double
factorX
(
double
w
)
{
return
w
*
width
/
Math
.
abs
(
xmax
–
xmin
);
}
private
static
double
factorY
(
double
h
)
{
return
h
*
height
/
Math
.
abs
(
ymax
–
ymin
);
}
private
static
double
userX
(
double
x
)
{
return
xmin
+
x
*
(
xmax
–
xmin
)
/
width
;
}
private
static
double
userY
(
double
y
)
{
return
ymax
–
y
*
(
ymax
–
ymin
)
/
height
;
}
/**
* Clears the screen to the default color (white).
*/
public
static
void
clear
()
{
clear
(
DEFAULT_CLEAR_COLOR
);
}
/**
* Clears the screen to the specified color.
*
*
@param
color the color to make the background
*
@throws
IllegalArgumentException if {
@code
color} is {
@code
null}
*/
public
static
void
clear
(
Color
color
)
{
validateNotNull
(
color
,
“color”
);
offscreen
.
setColor
(
color
);
offscreen
.
fillRect
(
0
,
0
,
width
,
height
);
offscreen
.
setColor
(
penColor
);
draw
();
}
/**
* Returns the current pen radius.
*
*
@return
the current value of the pen radius
*/
public
static
double
getPenRadius
()
{
return
penRadius
;
}
/**
* Sets the pen size to the default size (0.002).
* The pen is circular, so that lines have rounded ends, and when you set the
* pen radius and draw a point, you get a circle of the specified radius.
* The pen radius is not affected by coordinate scaling.
*/
public
static
void
setPenRadius
()
{
setPenRadius
(
DEFAULT_PEN_RADIUS
);
}
/**
* Sets the radius of the pen to the specified size.
* The pen is circular, so that lines have rounded ends, and when you set the
* pen radius and draw a point, you get a circle of the specified radius.
* The pen radius is not affected by coordinate scaling.
*
*
@param
radius the radius of the pen
*
@throws
IllegalArgumentException if {
@code
radius} is negative, NaN, or infinite
*/
public
static
void
setPenRadius
(
double
radius
)
{
validate
(
radius
,
“pen radius”
);
validateNonnegative
(
radius
,
“pen radius”
);
penRadius
=
radius
;
float scaledPenRadius = (float) (radius * DEFAULT_SIZE);
BasicStroke stroke = new BasicStroke(scaledPenRadius, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
// BasicStroke stroke = new BasicStroke(scaledPenRadius); offscreen.setStroke(stroke);
}
/** * Returns the current pen color. * * @return the current pen color */
public static Color getPenColor() {
return penColor;
}
/** * Sets the pen color to the default color (black). */
public static void setPenColor() {
setPenColor(DEFAULT_PEN_COLOR);
}
/** * Sets the pen color to the specified color. *
* The predefined pen colors are * {@code StdDraw.BLACK}, {@code StdDraw.BLUE}, {@code StdDraw.CYAN}, * {@code StdDraw.DARK_GRAY}, {@code StdDraw.GRAY}, {@code StdDraw.GREEN}, * {@code StdDraw.LIGHT_GRAY}, {@code StdDraw.MAGENTA}, {@code StdDraw.ORANGE}, * {@code StdDraw.PINK}, {@code StdDraw.RED}, {@code StdDraw.WHITE}, and * {@code StdDraw.YELLOW}. * * @param color the color to make the pen * @throws IllegalArgumentException if {@code color} is {@code null} */
public static void setPenColor(Color color) {
validateNotNull(color, “color”);
penColor = color;
offscreen.setColor(penColor);
}
/** * Sets the pen color to the specified RGB color. * * @param red the amount of red (between 0 and 255) * @param green the amount of green (between 0 and 255) * @param blue the amount of blue (between 0 and 255) * @throws IllegalArgumentException if {@code red}, {@code green}, * or {@code blue} is outside its prescribed range */
public static void setPenColor(int red, int green, int blue) {
if (red < 0 || red >= 256) throw new IllegalArgumentException(“red must be between 0 and 255”);
if (green < 0 || green >= 256) throw new IllegalArgumentException(“green must be between 0 and 255”);
if (blue < 0 || blue >= 256) throw new IllegalArgumentException(“blue must be between 0 and 255”);
setPenColor(new Color(red, green, blue));
}
/** * Returns the current font. * * @return the current font */
public static Font getFont() {
return font;
}
/** * Sets the font to the default font (sans serif, 16 point). */
public static void setFont() {
setFont(DEFAULT_FONT);
}
/** * Sets the font to the specified value. * * @param font the font * @throws IllegalArgumentException if {@code font} is {@code null} */
public static void setFont(Font font) {
validateNotNull(font, “font”);
StdDraw.font = font;
}
/*************************************************************************** * Drawing geometric shapes. ***************************************************************************/
/** * Draws a line segment between (x0, y0) and * (x1, y1). * * @param x0 the x-coordinate of one endpoint * @param y0 the y-coordinate of one endpoint * @param x1 the x-coordinate of the other endpoint * @param y1 the y-coordinate of the other endpoint * @throws IllegalArgumentException if any coordinate is either NaN or infinite */
public static void line(double x0, double y0, double x1, double y1) {
validate(x0, “x0”);
validate(y0, “y0”);
validate(x1, “x1”);
validate(y1, “y1”);
offscreen.draw(new Line2D.Double(scaleX(x0), scaleY(y0), scaleX(x1), scaleY(y1)));
draw();
}
/** * Draws one pixel at (x, y). * This method is private because pixels depend on the display. * To achieve the same effect, set the pen radius to 0 and call {@code point()}. * * @param x the x-coordinate of the pixel * @param y the y-coordinate of the pixel * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite */
private static void pixel(double x, double y) {
validate(x, “x”);
validate(y, “y”);
offscreen.fillRect((int) Math.round(scaleX(x)), (int) Math.round(scaleY(y)), 1, 1);
}
/** * Draws a point centered at (x, y). * The point is a filled circle whose radius is equal to the pen radius. * To draw a single-pixel point, first set the pen radius to 0. * * @param x the x-coordinate of the point * @param y the y-coordinate of the point * @throws IllegalArgumentException if either {@code x} or {@code y} is either NaN or infinite */
public static void point(double x, double y) {
validate(x, “x”);
validate(y, “y”);
double xs = scaleX(x);
double ys = scaleY(y);
double r = penRadius;
float scaledPenRadius = (float) (r * DEFAULT_SIZE);
// double ws = factorX(2*r); // double hs = factorY(2*r); // if (ws <= 1 && hs <= 1) pixel(x, y); if (scaledPenRadius <= 1) pixel(x, y); else offscreen.fill(new Ellipse2D.Double(xs - scaledPenRadius/2, ys - scaledPenRadius/2, scaledPenRadius, scaledPenRadius)); draw(); } /** * Draws a circle of the specified radius, centered at (x, y). * * @param x the x-coordinate of the center of the circle * @param y the y-coordinate of the center of the circle * @param radius the radius of the circle * @throws IllegalArgumentException if {@code radius} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public static void circle(double x, double y, double radius) {
validate(x, “x”);
validate(y, “y”);
validate(radius, “radius”);
validateNonnegative(radius, “radius”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*radius);
double hs = factorY(2*radius);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.draw(new Ellipse2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws a filled circle of the specified radius, centered at (x, y). * * @param x the x-coordinate of the center of the circle * @param y the y-coordinate of the center of the circle * @param radius the radius of the circle * @throws IllegalArgumentException if {@code radius} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public static void filledCircle(double x, double y, double radius) {
validate(x, “x”);
validate(y, “y”);
validate(radius, “radius”);
validateNonnegative(radius, “radius”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*radius);
double hs = factorY(2*radius);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.fill(new Ellipse2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws an ellipse with the specified semimajor and semiminor axes, * centered at (x, y). * * @param x the x-coordinate of the center of the ellipse * @param y the y-coordinate of the center of the ellipse * @param semiMajorAxis is the semimajor axis of the ellipse * @param semiMinorAxis is the semiminor axis of the ellipse * @throws IllegalArgumentException if either {@code semiMajorAxis} * or {@code semiMinorAxis} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public static void ellipse(double x, double y, double semiMajorAxis, double semiMinorAxis) {
validate(x, “x”);
validate(y, “y”);
validate(semiMajorAxis, “semimajor axis”);
validate(semiMinorAxis, “semiminor axis”);
validateNonnegative(semiMajorAxis, “semimajor axis”);
validateNonnegative(semiMinorAxis, “semiminor axis”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*semiMajorAxis);
double hs = factorY(2*semiMinorAxis);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.draw(new Ellipse2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws a filled ellipse with the specified semimajor and semiminor axes, * centered at (x, y). * * @param x the x-coordinate of the center of the ellipse * @param y the y-coordinate of the center of the ellipse * @param semiMajorAxis is the semimajor axis of the ellipse * @param semiMinorAxis is the semiminor axis of the ellipse * @throws IllegalArgumentException if either {@code semiMajorAxis} * or {@code semiMinorAxis} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public static void filledEllipse(double x, double y, double semiMajorAxis, double semiMinorAxis) {
validate(x, “x”);
validate(y, “y”);
validate(semiMajorAxis, “semimajor axis”);
validate(semiMinorAxis, “semiminor axis”);
validateNonnegative(semiMajorAxis, “semimajor axis”);
validateNonnegative(semiMinorAxis, “semiminor axis”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*semiMajorAxis);
double hs = factorY(2*semiMinorAxis);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.fill(new Ellipse2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws a circular arc of the specified radius, * centered at (x, y), from angle1 to angle2 (in degrees). * * @param x the x-coordinate of the center of the circle * @param y the y-coordinate of the center of the circle * @param radius the radius of the circle * @param angle1 the starting angle. 0 would mean an arc beginning at 3 o’clock. * @param angle2 the angle at the end of the arc. For example, if * you want a 90 degree arc, then angle2 should be angle1 + 90. * @throws IllegalArgumentException if {@code radius} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public static void arc(double x, double y, double radius, double angle1, double angle2) {
validate(x, “x”);
validate(y, “y”);
validate(radius, “arc radius”);
validate(angle1, “angle1”);
validate(angle2, “angle2”);
validateNonnegative(radius, “arc radius”);
while (angle2 < angle1) angle2 += 360; double xs = scaleX(x); double ys = scaleY(y); double ws = factorX(2*radius); double hs = factorY(2*radius); if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.draw(new Arc2D.Double(xs - ws/2, ys - hs/2, ws, hs, angle1, angle2 - angle1, Arc2D.OPEN)); draw(); } /** * Draws a square of the specified size, centered at (x, y). * * @param x the x-coordinate of the center of the square * @param y the y-coordinate of the center of the square * @param halfLength one half the length of any side of the square * @throws IllegalArgumentException if {@code halfLength} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public static void square(double x, double y, double halfLength) {
validate(x, “x”);
validate(y, “y”);
validate(halfLength, “halfLength”);
validateNonnegative(halfLength, “half length”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*halfLength);
double hs = factorY(2*halfLength);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.draw(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws a filled square of the specified size, centered at (x, y). * * @param x the x-coordinate of the center of the square * @param y the y-coordinate of the center of the square * @param halfLength one half the length of any side of the square * @throws IllegalArgumentException if {@code halfLength} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public static void filledSquare(double x, double y, double halfLength) {
validate(x, “x”);
validate(y, “y”);
validate(halfLength, “halfLength”);
validateNonnegative(halfLength, “half length”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*halfLength);
double hs = factorY(2*halfLength);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.fill(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws a rectangle of the specified size, centered at (x, y). * * @param x the x-coordinate of the center of the rectangle * @param y the y-coordinate of the center of the rectangle * @param halfWidth one half the width of the rectangle * @param halfHeight one half the height of the rectangle * @throws IllegalArgumentException if either {@code halfWidth} or {@code halfHeight} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public static void rectangle(double x, double y, double halfWidth, double halfHeight) {
validate(x, “x”);
validate(y, “y”);
validate(halfWidth, “halfWidth”);
validate(halfHeight, “halfHeight”);
validateNonnegative(halfWidth, “half width”);
validateNonnegative(halfHeight, “half height”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*halfWidth);
double hs = factorY(2*halfHeight);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.draw(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws a filled rectangle of the specified size, centered at (x, y). * * @param x the x-coordinate of the center of the rectangle * @param y the y-coordinate of the center of the rectangle * @param halfWidth one half the width of the rectangle * @param halfHeight one half the height of the rectangle * @throws IllegalArgumentException if either {@code halfWidth} or {@code halfHeight} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public static void filledRectangle(double x, double y, double halfWidth, double halfHeight) {
validate(x, “x”);
validate(y, “y”);
validate(halfWidth, “halfWidth”);
validate(halfHeight, “halfHeight”);
validateNonnegative(halfWidth, “half width”);
validateNonnegative(halfHeight, “half height”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*halfWidth);
double hs = factorY(2*halfHeight);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.fill(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws a polygon with the vertices * (x0, y0), * (x1, y1), …, * (xn–1, yn–1). * * @param x an array of all the x-coordinates of the polygon * @param y an array of all the y-coordinates of the polygon * @throws IllegalArgumentException unless {@code x[]} and {@code y[]} * are of the same length * @throws IllegalArgumentException if any coordinate is either NaN or infinite * @throws IllegalArgumentException if either {@code x[]} or {@code y[]} is {@code null} */
public static void polygon(double[] x, double[] y) {
validateNotNull(x, “x-coordinate array”);
validateNotNull(y, “y-coordinate array”);
for (int i = 0; i < x.length; i++) validate(x[i], "x[" + i + "]"); for (int i = 0; i < y.length; i++) validate(y[i], "y[" + i + "]"); int n1 = x.length; int n2 = y.length; if (n1 != n2) throw new IllegalArgumentException("arrays must be of the same length"); int n = n1; if (n == 0) return; GeneralPath path = new GeneralPath(); path.moveTo((float) scaleX(x[0]), (float) scaleY(y[0])); for (int i = 0; i < n; i++) path.lineTo((float) scaleX(x[i]), (float) scaleY(y[i])); path.closePath(); offscreen.draw(path); draw(); } /** * Draws a filled polygon with the vertices * (x0, y0), * (x1, y1), …, * (xn–1, yn–1). * * @param x an array of all the x-coordinates of the polygon * @param y an array of all the y-coordinates of the polygon * @throws IllegalArgumentException unless {@code x[]} and {@code y[]} * are of the same length * @throws IllegalArgumentException if any coordinate is either NaN or infinite * @throws IllegalArgumentException if either {@code x[]} or {@code y[]} is {@code null} */
public static void filledPolygon(double[] x, double[] y) {
validateNotNull(x, “x-coordinate array”);
validateNotNull(y, “y-coordinate array”);
for (int i = 0; i < x.length; i++) validate(x[i], "x[" + i + "]"); for (int i = 0; i < y.length; i++) validate(y[i], "y[" + i + "]"); int n1 = x.length; int n2 = y.length; if (n1 != n2) throw new IllegalArgumentException("arrays must be of the same length"); int n = n1; if (n == 0) return; GeneralPath path = new GeneralPath(); path.moveTo((float) scaleX(x[0]), (float) scaleY(y[0])); for (int i = 0; i < n; i++) path.lineTo((float) scaleX(x[i]), (float) scaleY(y[i])); path.closePath(); offscreen.fill(path); draw(); } /*************************************************************************** * Drawing images. ***************************************************************************/ // get an image from the given filename private static Image getImage(String filename) { if (filename == null) throw new IllegalArgumentException(); // to read from file ImageIcon icon = new ImageIcon(filename); // try to read from URL if ((icon == null) || (icon.getImageLoadStatus() != MediaTracker.COMPLETE)) { try { URL url = new URL(filename); icon = new ImageIcon(url); } catch (MalformedURLException e) { /* not a url */ } } // in case file is inside a .jar (classpath relative to StdDraw) if ((icon == null) || (icon.getImageLoadStatus() != MediaTracker.COMPLETE)) { URL url = StdDraw.class.getResource(filename); if (url != null) icon = new ImageIcon(url); } // in case file is inside a .jar (classpath relative to root of jar) if ((icon == null) || (icon.getImageLoadStatus() != MediaTracker.COMPLETE)) { URL url = StdDraw.class.getResource("/" + filename); if (url == null) throw new IllegalArgumentException("image " + filename + " not found"); icon = new ImageIcon(url); } return icon.getImage(); } /*************************************************************************** * [Summer 2016] Should we update to use ImageIO instead of ImageIcon()? * Seems to have some issues loading images on some systems * and slows things down on other systems. * especially if you don't call ImageIO.setUseCache(false) * One advantage is that it returns a BufferedImage. ***************************************************************************/ /* private static BufferedImage getImage(String filename) { if (filename == null) throw new IllegalArgumentException(); // from a file or URL try { URL url = new URL(filename); BufferedImage image = ImageIO.read(url); return image; } catch (IOException e) { // ignore } // in case file is inside a .jar (classpath relative to StdDraw) try { URL url = StdDraw.class.getResource(filename); BufferedImage image = ImageIO.read(url); return image; } catch (IOException e) { // ignore } // in case file is inside a .jar (classpath relative to root of jar) try { URL url = StdDraw.class.getResource("/" + filename); BufferedImage image = ImageIO.read(url); return image; } catch (IOException e) { // ignore } throw new IllegalArgumentException("image " + filename + " not found"); }*/ /** * Draws the specified image centered at (x, y). * The supported image formats are JPEG, PNG, and GIF. * As an optimization, the picture is cached, so there is no performance * penalty for redrawing the same image multiple times (e.g., in an animation). * However, if you change the picture file after drawing it, subsequent * calls will draw the original picture. * * @param x the center x-coordinate of the image * @param y the center y-coordinate of the image * @param filename the name of the image/picture, e.g., “ball.gif” * @throws IllegalArgumentException if the image filename is invalid * @throws IllegalArgumentException if either {@code x} or {@code y} is either NaN or infinite */
public static void picture(double x, double y, String filename) {
validate(x, “x”);
validate(y, “y”);
validateNotNull(filename, “filename”);
// BufferedImage image = getImage(filename); Image image = getImage(filename);
double xs = scaleX(x);
double ys = scaleY(y);
// int ws = image.getWidth(); // can call only if image is a BufferedImage // int hs = image.getHeight(); int ws = image.getWidth(null);
int hs = image.getHeight(null);
if (ws < 0 || hs < 0) throw new IllegalArgumentException("image " + filename + " is corrupt"); offscreen.drawImage(image, (int) Math.round(xs - ws/2.0), (int) Math.round(ys - hs/2.0), null); draw(); } /** * Draws the specified image centered at (x, y), * rotated given number of degrees. * The supported image formats are JPEG, PNG, and GIF. * * @param x the center x-coordinate of the image * @param y the center y-coordinate of the image * @param filename the name of the image/picture, e.g., “ball.gif” * @param degrees is the number of degrees to rotate counterclockwise * @throws IllegalArgumentException if the image filename is invalid * @throws IllegalArgumentException if {@code x}, {@code y}, {@code degrees} is NaN or infinite * @throws IllegalArgumentException if {@code filename} is {@code null} */
public static void picture(double x, double y, String filename, double degrees) {
validate(x, “x”);
validate(y, “y”);
validate(degrees, “degrees”);
validateNotNull(filename, “filename”);
// BufferedImage image = getImage(filename); Image image = getImage(filename);
double xs = scaleX(x);
double ys = scaleY(y);
// int ws = image.getWidth(); // can call only if image is a BufferedImage // int hs = image.getHeight(); int ws = image.getWidth(null);
int hs = image.getHeight(null);
if (ws < 0 || hs < 0) throw new IllegalArgumentException("image " + filename + " is corrupt"); offscreen.rotate(Math.toRadians(-degrees), xs, ys); offscreen.drawImage(image, (int) Math.round(xs - ws/2.0), (int) Math.round(ys - hs/2.0), null); offscreen.rotate(Math.toRadians(+degrees), xs, ys); draw(); } /** * Draws the specified image centered at (x, y), * rescaled to the specified bounding box. * The supported image formats are JPEG, PNG, and GIF. * * @param x the center x-coordinate of the image * @param y the center y-coordinate of the image * @param filename the name of the image/picture, e.g., “ball.gif” * @param scaledWidth the width of the scaled image (in screen coordinates) * @param scaledHeight the height of the scaled image (in screen coordinates) * @throws IllegalArgumentException if either {@code scaledWidth} * or {@code scaledHeight} is negative * @throws IllegalArgumentException if the image filename is invalid * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite * @throws IllegalArgumentException if {@code filename} is {@code null} */
public static void picture(double x, double y, String filename, double scaledWidth, double scaledHeight) {
validate(x, “x”);
validate(y, “y”);
validate(scaledWidth, “scaled width”);
validate(scaledHeight, “scaled height”);
validateNotNull(filename, “filename”);
validateNonnegative(scaledWidth, “scaled width”);
validateNonnegative(scaledHeight, “scaled height”);
Image image = getImage(filename);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(scaledWidth);
double hs = factorY(scaledHeight);
if (ws < 0 || hs < 0) throw new IllegalArgumentException("image " + filename + " is corrupt"); if (ws <= 1 && hs <= 1) pixel(x, y); else { offscreen.drawImage(image, (int) Math.round(xs - ws/2.0), (int) Math.round(ys - hs/2.0), (int) Math.round(ws), (int) Math.round(hs), null); } draw(); } /** * Draws the specified image centered at (x, y), rotated * given number of degrees, and rescaled to the specified bounding box. * The supported image formats are JPEG, PNG, and GIF. * * @param x the center x-coordinate of the image * @param y the center y-coordinate of the image * @param filename the name of the image/picture, e.g., “ball.gif” * @param scaledWidth the width of the scaled image (in screen coordinates) * @param scaledHeight the height of the scaled image (in screen coordinates) * @param degrees is the number of degrees to rotate counterclockwise * @throws IllegalArgumentException if either {@code scaledWidth} * or {@code scaledHeight} is negative * @throws IllegalArgumentException if the image filename is invalid */
public static void picture(double x, double y, String filename, double scaledWidth, double scaledHeight, double degrees) {
validate(x, “x”);
validate(y, “y”);
validate(scaledWidth, “scaled width”);
validate(scaledHeight, “scaled height”);
validate(degrees, “degrees”);
validateNotNull(filename, “filename”);
validateNonnegative(scaledWidth, “scaled width”);
validateNonnegative(scaledHeight, “scaled height”);
Image image = getImage(filename);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(scaledWidth);
double hs = factorY(scaledHeight);
if (ws < 0 || hs < 0) throw new IllegalArgumentException("image " + filename + " is corrupt"); if (ws <= 1 && hs <= 1) pixel(x, y); offscreen.rotate(Math.toRadians(-degrees), xs, ys); offscreen.drawImage(image, (int) Math.round(xs - ws/2.0), (int) Math.round(ys - hs/2.0), (int) Math.round(ws), (int) Math.round(hs), null); offscreen.rotate(Math.toRadians(+degrees), xs, ys); draw(); } /*************************************************************************** * Drawing text. ***************************************************************************/ /** * Writes the given text string in the current font, centered at (x, y). * * @param x the center x-coordinate of the text * @param y the center y-coordinate of the text * @param text the text to write * @throws IllegalArgumentException if {@code text} is {@code null} * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite */
public static void text(double x, double y, String text) {
validate(x, “x”);
validate(y, “y”);
validateNotNull(text, “text”);
offscreen.setFont(font);
FontMetrics metrics = offscreen.getFontMetrics();
double xs = scaleX(x);
double ys = scaleY(y);
int ws = metrics.stringWidth(text);
int hs = metrics.getDescent();
offscreen.drawString(text, (float) (xs – ws/2.0), (float) (ys + hs));
draw();
}
/** * Writes the given text string in the current font, centered at (x, y) and * rotated by the specified number of degrees. * @param x the center x-coordinate of the text * @param y the center y-coordinate of the text * @param text the text to write * @param degrees is the number of degrees to rotate counterclockwise * @throws IllegalArgumentException if {@code text} is {@code null} * @throws IllegalArgumentException if {@code x}, {@code y}, or {@code degrees} is either NaN or infinite */
public static void text(double x, double y, String text, double degrees) {
validate(x, “x”);
validate(y, “y”);
validate(degrees, “degrees”);
validateNotNull(text, “text”);
double xs = scaleX(x);
double ys = scaleY(y);
offscreen.rotate(Math.toRadians(-degrees), xs, ys);
text(x, y, text);
offscreen.rotate(Math.toRadians(+degrees), xs, ys);
}
/** * Writes the given text string in the current font, left-aligned at (x, y). * @param x the x-coordinate of the text * @param y the y-coordinate of the text * @param text the text * @throws IllegalArgumentException if {@code text} is {@code null} * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite */
public static void textLeft(double x, double y, String text) {
validate(x, “x”);
validate(y, “y”);
validateNotNull(text, “text”);
offscreen.setFont(font);
FontMetrics metrics = offscreen.getFontMetrics();
double xs = scaleX(x);
double ys = scaleY(y);
int hs = metrics.getDescent();
offscreen.drawString(text, (float) xs, (float) (ys + hs));
draw();
}
/** * Writes the given text string in the current font, right-aligned at (x, y). * * @param x the x-coordinate of the text * @param y the y-coordinate of the text * @param text the text to write * @throws IllegalArgumentException if {@code text} is {@code null} * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite */
public static void textRight(double x, double y, String text) {
validate(x, “x”);
validate(y, “y”);
validateNotNull(text, “text”);
offscreen.setFont(font);
FontMetrics metrics = offscreen.getFontMetrics();
double xs = scaleX(x);
double ys = scaleY(y);
int ws = metrics.stringWidth(text);
int hs = metrics.getDescent();
offscreen.drawString(text, (float) (xs – ws), (float) (ys + hs));
draw();
}
/** * Copies the offscreen buffer to the onscreen buffer, pauses for t milliseconds * and enables double buffering. * @param t number of milliseconds * @deprecated replaced by {@link #enableDoubleBuffering()}, {@link #show()}, and {@link #pause(int t)} */
@Deprecated
public static void show(int t) {
validateNonnegative(t, “t”);
show();
pause(t);
enableDoubleBuffering();
}
/** * Pauses for t milliseconds. This method is intended to support computer animations. * @param t number of milliseconds */
public static void pause(int t) {
validateNonnegative(t, “t”);
try {
Thread.sleep(t);
}
catch (InterruptedException e) {
System.out.println(“Error sleeping”);
}
}
/** * Copies offscreen buffer to onscreen buffer. There is no reason to call * this method unless double buffering is enabled. */
public static void show() {
onscreen.drawImage(offscreenImage, 0, 0, null);
frame.repaint();
}
// draw onscreen if defer is false private static void draw() {
if (!defer) show();
}
/** * Enables double buffering. All subsequent calls to * drawing methods such as {@code line()}, {@code circle()}, * and {@code square()} will be deferred until the next call * to show(). Useful for animations. */
public static void enableDoubleBuffering() {
defer = true;
}
/** * Disables double buffering. All subsequent calls to * drawing methods such as {@code line()}, {@code circle()}, * and {@code square()} will be displayed on screen when called. * This is the default. */
public static void disableDoubleBuffering() {
defer = false;
}
/*************************************************************************** * Save drawing to a file. ***************************************************************************/
/** * Saves the drawing to using the specified filename. * The supported image formats are JPEG and PNG; * the filename suffix must be {@code } or {@code }. * * @param filename the name of the file with one of the required suffixes * @throws IllegalArgumentException if {@code filename} is {@code null} */
public static void save(String filename) {
validateNotNull(filename, “filename”);
File file = new File(filename);
String suffix = filename.substring(filename.lastIndexOf(‘.’) + 1);
// png files if (“png”.equalsIgnoreCase(suffix)) {
try {
ImageIO.write(onscreenImage, suffix, file);
}
catch (IOException e) {
e.printStackTrace();
}
}
// need to change from ARGB to RGB for JPEG // reference: http://archives.java.sun.com/cgi-bin/wa?A2=ind0404&L=java2d-interest&D=0&P=2727 else if (“jpg”.equalsIgnoreCase(suffix)) {
WritableRaster raster = onscreenImage.getRaster();
WritableRaster newRaster;
newRaster = raster.createWritableChild(0, 0, width, height, 0, 0, new int[] {0, 1, 2});
DirectColorModel cm = (DirectColorModel) onscreenImage.getColorModel();
DirectColorModel newCM = new DirectColorModel(cm.getPixelSize(),
cm.getRedMask(),
cm.getGreenMask(),
cm.getBlueMask());
BufferedImage rgbBuffer = new BufferedImage(newCM, newRaster, false, null);
try {
ImageIO.write(rgbBuffer, suffix, file);
}
catch (IOException e) {
e.printStackTrace();
}
}
else {
System.out.println(“Invalid image file type: ” + suffix);
}
}
/** * This method cannot be called directly. */
@Override
public void actionPerformed(ActionEvent e) {
FileDialog chooser = new FileDialog(StdDraw.frame, “Use a or extension”, FileDialog.SAVE);
chooser.setVisible(true);
String filename = chooser.getFile();
if (filename != null) {
StdDraw.save(chooser.getDirectory() + File.separator + chooser.getFile());
}
}
/*************************************************************************** * Mouse interactions. ***************************************************************************/
/** * Returns true if the mouse is being pressed. * * @return {@code true} if the mouse is being pressed; {@code false} otherwise */
public static boolean isMousePressed() {
synchronized (mouseLock) {
return isMousePressed;
}
}
/** * Returns true if the mouse is being pressed. * * @return {@code true} if the mouse is being pressed; {@code false} otherwise * @deprecated replaced by {@link #isMousePressed()} */
@Deprecated
public static boolean mousePressed() {
synchronized (mouseLock) {
return isMousePressed;
}
}
/** * Returns the x-coordinate of the mouse. * * @return the x-coordinate of the mouse */
public static double mouseX() {
synchronized (mouseLock) {
return mouseX;
}
}
/** * Returns the y-coordinate of the mouse. * * @return y-coordinate of the mouse */
public static double mouseY() {
synchronized (mouseLock) {
return mouseY;
}
}
/** * This method cannot be called directly. */
@Override
public void mouseClicked(MouseEvent e) {
// this body is intentionally left empty }
/** * This method cannot be called directly. */
@Override
public void mouseEntered(MouseEvent e) {
// this body is intentionally left empty }
/** * This method cannot be called directly. */
@Override
public void mouseExited(MouseEvent e) {
// this body is intentionally left empty }
/** * This method cannot be called directly. */
@Override
public void mousePressed(MouseEvent e) {
synchronized (mouseLock) {
mouseX = StdDraw.userX(e.getX());
mouseY = StdDraw.userY(e.getY());
isMousePressed = true;
}
}
/** * This method cannot be called directly. */
@Override
public void mouseReleased(MouseEvent e) {
synchronized (mouseLock) {
isMousePressed = false;
}
}
/** * This method cannot be called directly. */
@Override
public void mouseDragged(MouseEvent e) {
synchronized (mouseLock) {
mouseX = StdDraw.userX(e.getX());
mouseY = StdDraw.userY(e.getY());
}
}
/** * This method cannot be called directly. */
@Override
public void mouseMoved(MouseEvent e) {
synchronized (mouseLock) {
mouseX = StdDraw.userX(e.getX());
mouseY = StdDraw.userY(e.getY());
}
}
/*************************************************************************** * Keyboard interactions. ***************************************************************************/
/** * Returns true if the user has typed a key (that has not yet been processed). * * @return {@code true} if the user has typed a key (that has not yet been processed * by {@link #nextKeyTyped()}; {@code false} otherwise */
public static boolean hasNextKeyTyped() {
synchronized (keyLock) {
return !keysTyped.isEmpty();
}
}
/** * Returns the next key that was typed by the user (that your program has not already processed). * This method should be preceded by a call to {@link #hasNextKeyTyped()} to ensure * that there is a next key to process. * This method returns a Unicode character corresponding to the key * typed (such as {@code ‘a’} or {@code ‘A’}). * It cannot identify action keys (such as F1 and arrow keys) * or modifier keys (such as control). * * @return the next key typed by the user (that your program has not already processed). * @throws NoSuchElementException if there is no remaining key */
public static char nextKeyTyped() {
synchronized (keyLock) {
if (keysTyped.isEmpty()) {
throw new NoSuchElementException(“your program has already processed all keystrokes”);
}
return keysTyped.remove(keysTyped.size() – 1);
// return keysTyped.removeLast(); }
}
/** * Returns true if the given key is being pressed. *
* This method takes the keycode (corresponding to a physical key) * as an argument. It can handle action keys * (such as F1 and arrow keys) and modifier keys (such as shift and control). * See {@link KeyEvent} for a description of key codes. * * @param keycode the key to check if it is being pressed * @return {@code true} if {@code keycode} is currently being pressed; * {@code false} otherwise */
public static boolean isKeyPressed(int keycode) {
synchronized (keyLock) {
return keysDown.contains(keycode);
}
}
/** * This method cannot be called directly. */
@Override
public void keyTyped(KeyEvent e) {
synchronized (keyLock) {
keysTyped.addFirst(e.getKeyChar());
}
}
/** * This method cannot be called directly. */
@Override
public void keyPressed(KeyEvent e) {
synchronized (keyLock) {
keysDown.add(e.getKeyCode());
}
}
/** * This method cannot be called directly. */
@Override
public void keyReleased(KeyEvent e) {
synchronized (keyLock) {
keysDown.remove(e.getKeyCode());
}
}
/*************************************************************************** * For improved resolution on Mac Retina displays. ***************************************************************************/
private static class RetinaImageIcon extends ImageIcon {
public RetinaImageIcon(Image image) {
super(image);
}
public int getIconWidth() {
return super.getIconWidth() / 2;
}
/** * Gets the height of the icon. * * @return the height in pixels of this icon */
public int getIconHeight() {
return super.getIconHeight() / 2;
}
public synchronized void paintIcon(Component c, Graphics g, int x, int y) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2.scale(0.5, 0.5);
super.paintIcon(c, g2, x * 2, y * 2);
g2.dispose();
}
}
/** * Test client. * * @param args the command-line arguments */
public static void main(String[] args) {
StdDraw.square(0.2, 0.8, 0.1);
StdDraw.filledSquare(0.8, 0.8, 0.2);
StdDraw.circle(0.8, 0.2, 0.2);
StdDraw.setPenColor(StdDraw.BOOK_RED);
StdDraw.setPenRadius(0.02);
StdDraw.arc(0.8, 0.2, 0.1, 200, 45);
// draw a blue diamond StdDraw.setPenRadius();
StdDraw.setPenColor(StdDraw.BOOK_BLUE);
double[] x = { 0.1, 0.2, 0.3, 0.2 };
double[] y = { 0.2, 0.3, 0.2, 0.1 };
StdDraw.filledPolygon(x, y);
// text StdDraw.setPenColor(StdDraw.BLACK);
StdDraw.text(0.2, 0.5, “black text”);
StdDraw.setPenColor(StdDraw.WHITE);
StdDraw.text(0.8, 0.8, “white text”);
}
}
/****************************************************************************** * Copyright 2002-2020, Robert Sedgewick and Kevin Wayne. * * This file is part of algs4.jar, which accompanies the textbook * * Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne, * Addison-Wesley Professional, 2011, ISBN 0-321-57351-X. * http://algs4.cs.princeton.edu * * * algs4.jar is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * algs4.jar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with algs4.jar. If not, see http://www.gnu.org/licenses. ******************************************************************************/
edu/princeton/cs/algs4/StdIn.java
edu/princeton/cs/algs4/StdIn.java
/******************************************************************************
* Compilation: javac StdIn.java
* Execution: java StdIn (interactive test of basic functionality)
* Dependencies: none
*
* Reads in data of various types from standard input.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
ArrayList
;
import
java
.
util
.
InputMismatchException
;
import
java
.
util
.
Locale
;
import
java
.
util
.
NoSuchElementException
;
import
java
.
util
.
Scanner
;
import
java
.
util
.
regex
.
Pattern
;
/**
* The {
@code
StdIn} class provides static methods for reading strings
* and numbers from standard input.
* These functions fall into one of four categories:
*
*
* and converting each to a number, string, or boolean
*
*
*
* and returning the values in an array
*
*
* Generally, it is best not to mix functions from the different
* categories in the same program.
*
* Getting started.
* To use this class, you must have {
@code
StdIn.class} in your
* Java classpath. If you used our autoinstaller, you should be all set.
* Otherwise, either download
* and add to your Java classpath or download
* and put a copy in your working directory.
*
* Reading tokens from standard input and converting to numbers and strings.
* You can use the following methods to read numbers, strings, and booleans
* from standard input one at a time:
*
*
*
*
*
*
*
*
*
*
*
*
* The first method returns true if standard input has no more tokens.
* Each other method skips over any input that is whitespace. Then, it reads
* the next token and attempts to convert it into a value of the specified
* type. If it succeeds, it returns that value; otherwise, it
* throws an {
@link
InputMismatchException}.
*
* Whitespace includes spaces, tabs, and newlines; the full definition
* is inherited from {
@link
Character#isWhitespace(char)}.
* A token is a maximal sequence of non-whitespace characters.
* The precise rules for describing which tokens can be converted to
* integers and floating-point numbers are inherited from
* Scanner,
* using the locale {
@link
Locale#US}; the rules
* for floating-point numbers are slightly different
* from those in {
@link
Double#valueOf(String)},
* but unlikely to be of concern to most programmers.
*
* As an example, the following code fragment reads integers from standard input,
* one at a time, and prints them one per line.
*
* while (!StdIn.isEmpty()) { * double value = StdIn.readDouble(); * StdOut.println(value); * } *
*
* Reading characters from standard input.
* You can use the following two methods to read characters from standard input one at a time:
*
*
*
*
*
* The first method returns true if standard input has more input (including whitespace).
* The second method reads and returns the next character of input on standard
* input (possibly a whitespace character).
*
* As an example, the following code fragment reads characters from standard input,
* one character at a time, and prints it to standard output.
*
* while (StdIn.hasNextChar()) { * char c = StdIn.readChar(); * StdOut.print(c); * } *
*
* Reading lines from standard input.
* You can use the following two methods to read lines from standard input:
*
*
*
*
*
* The first method returns true if standard input has more input (including whitespace).
* The second method reads and returns the remaining portion of
* the next line of input on standard input (possibly whitespace),
* discarding the trailing line separator.
*
* A line separator is defined to be one of the following strings:
* {
@code
\n} (Linux), {
@code
\r} (old Macintosh),
* {
@code
\r\n} (Windows),
* {
@code
\}{
@code
u2028}, {
@code
\}{
@code
u2029}, or {
@code
\}{
@code
u0085}.
*
* As an example, the following code fragment reads text from standard input,
* one line at a time, and prints it to standard output.
*
* while (StdIn.hasNextLine()) { * String line = StdIn.readLine(); * StdOut.println(line); * } *
*
* Reading a sequence of values of the same type from standard input.
* You can use the following methods to read a sequence numbers, strings,
* or booleans (all of the same type) from standard input:
*
*
*
*
*
*
*
*
*
* The first three methods read of all of remaining token on standard input
* and converts the tokens to values of
* the specified type, as in the corresponding
* {
@code
readDouble}, {
@code
readInt}, and {
@code
readString()} methods.
* The {
@code
readAllLines()} method reads all remaining lines on standard
* input and returns them as an array of strings.
* The {
@code
readAll()} method reads all remaining input on standard
* input and returns it as a string.
*
* As an example, the following code fragment reads all of the remaining
* tokens from standard input and returns them as an array of strings.
*
* String[] words = StdIn.readAllStrings(); *
*
* Differences with Scanner.
* {
@code
StdIn} and {
@link
Scanner} are both designed to parse
* tokens and convert them to primitive types and strings.
* The main differences are summarized below:
*
*
* reads input from only standard input. It is suitable for use before
* a programmer knows about objects.
* See {
@link
In} for an object-oriented version that handles
* input from files, URLs,
* and sockets.
*
* that separates tokens.
* {
@link
Scanner} supports arbitrary delimiter patterns.
*
* which is the most widely used character encoding for Unicode.
*
* for consistency with {
@link
StdOut}, {
@link
Double#parseDouble(String)},
* and floating-point literals.
*
* character; reading in sequences of integers, doubles, or strings;
* and reading in all of the remaining input.
*
*
* Historical note: {
@code
StdIn} preceded {
@code
Scanner}; when
* {
@code
Scanner} was introduced, this class was re-implemented to use {
@code
Scanner}.
*
* Using standard input.
* Standard input is a fundamental operating system abstraction on Mac OS X,
* Windows, and Linux.
* The methods in {
@code
StdIn} are blocking, which means that they
* will wait until you enter input on standard input.
* If your program has a loop that repeats until standard input is empty,
* you must signal that the input is finished.
* To do so, depending on your operating system and IDE,
* use either {
@code
@code
* If you are redirecting standard input from a file, you will not need
* to do anything to signal that the input is finished.
*
* Known bugs.
* Java’s UTF-8 encoding does not recognize the optional
* If the input begins with the optional byte-order mask, {
@code
StdIn}
* will have an extra character {
@code
\}{
@code
uFEFF} at the beginning.
*
* Reference.
* For additional documentation,
* see Section 1.5 of
* Computer Science: An Interdisciplinary Approach
* by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*
@author
David Pritchard
*/
public
final
class
StdIn
{
/*** begin: section (1 of 2) of code duplicated from In to StdIn. */
// assume Unicode UTF-8 encoding
private
static
final
String
CHARSET_NAME
=
“UTF-8”
;
// assume language = English, country = US for consistency with System.out.
private
static
final
Locale
LOCALE
=
Locale
.
US
;
// the default token separator; we maintain the invariant that this value
// is held by the scanner’s delimiter between calls
private
static
final
Pattern
WHITESPACE_PATTERN
=
Pattern
.
compile
(
“\\p{javaWhitespace}+”
);
// makes whitespace significant
private
static
final
Pattern
EMPTY_PATTERN
=
Pattern
.
compile
(
“”
);
// used to read the entire input
private
static
final
Pattern
EVERYTHING_PATTERN
=
Pattern
.
compile
(
“\\A”
);
/*** end: section (1 of 2) of code duplicated from In to StdIn. */
private
static
Scanner
scanner
;
// it doesn’t make sense to instantiate this class
private
StdIn
()
{
}
//// begin: section (2 of 2) of code duplicated from In to StdIn,
//// with all methods changed from “public” to “public static”
/**
* Returns true if standard input is empty (except possibly for whitespace).
* Use this method to know whether the next call to {
@link
#readString()},
* {
@link
#readDouble()}, etc will succeed.
*
*
@return
{
@code
true} if standard input is empty (except possibly
* for whitespace); {
@code
false} otherwise
*/
public
static
boolean
isEmpty
()
{
return
!
scanner
.
hasNext
();
}
/**
* Returns true if standard input has a next line.
* Use this method to know whether the
* next call to {
@link
#readLine()} will succeed.
* This method is functionally equivalent to {
@link
#hasNextChar()}.
*
*
@return
{
@code
true} if standard input has more input (including whitespace);
* {
@code
false} otherwise
*/
public
static
boolean
hasNextLine
()
{
return
scanner
.
hasNextLine
();
}
/**
* Returns true if standard input has more input (including whitespace).
* Use this method to know whether the next call to {
@link
#readChar()} will succeed.
* This method is functionally equivalent to {
@link
#hasNextLine()}.
*
*
@return
{
@code
true} if standard input has more input (including whitespace);
* {
@code
false} otherwise
*/
public
static
boolean
hasNextChar
()
{
scanner
.
useDelimiter
(
EMPTY_PATTERN
);
boolean
result
=
scanner
.
hasNext
();
scanner
.
useDelimiter
(
WHITESPACE_PATTERN
);
return
result
;
}
/**
* Reads and returns the next line, excluding the line separator if present.
*
*
@return
the next line, excluding the line separator if present;
* {
@code
null} if no such line
*/
public
static
String
readLine
()
{
String
line
;
try
{
line
=
scanner
.
nextLine
();
}
catch
(
NoSuchElementException
e
)
{
line
=
null
;
}
return
line
;
}
/**
* Reads and returns the next character.
*
*
@return
the next {
@code
char}
*
@throws
NoSuchElementException if standard input is empty
*/
public
static
char
readChar
()
{
try
{
scanner
.
useDelimiter
(
EMPTY_PATTERN
);
String
ch
=
scanner
.
next
();
assert
ch
.
length
()
==
1
:
“Internal (Std)In.readChar() error!”
+
” Please contact the authors.”
;
scanner
.
useDelimiter
(
WHITESPACE_PATTERN
);
return
ch
.
charAt
(
0
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attempts to read a ‘char’ value from standard input, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads and returns the remainder of the input, as a string.
*
*
@return
the remainder of the input, as a string
*
@throws
NoSuchElementException if standard input is empty
*/
public
static
String
readAll
()
{
if
(
!
scanner
.
hasNextLine
())
return
“”
;
String
result
=
scanner
.
useDelimiter
(
EVERYTHING_PATTERN
).
next
();
// not that important to reset delimeter, since now scanner is empty
scanner
.
useDelimiter
(
WHITESPACE_PATTERN
);
// but let’s do it anyway
return
result
;
}
/**
* Reads the next token and returns the {
@code
String}.
*
*
@return
the next {
@code
String}
*
@throws
NoSuchElementException if standard input is empty
*/
public
static
String
readString
()
{
try
{
return
scanner
.
next
();
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attempts to read a ‘String’ value from standard input, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from standard input, parses it as an integer, and returns the integer.
*
*
@return
the next integer on standard input
*
@throws
NoSuchElementException if standard input is empty
*
@throws
InputMismatchException if the next token cannot be parsed as an {
@code
int}
*/
public
static
int
readInt
()
{
try
{
return
scanner
.
nextInt
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read an ‘int’ value from standard input, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attemps to read an ‘int’ value from standard input, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from standard input, parses it as a double, and returns the double.
*
*
@return
the next double on standard input
*
@throws
NoSuchElementException if standard input is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
double}
*/
public
static
double
readDouble
()
{
try
{
return
scanner
.
nextDouble
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read a ‘double’ value from standard input, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attempts to read a ‘double’ value from standard input, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from standard input, parses it as a float, and returns the float.
*
*
@return
the next float on standard input
*
@throws
NoSuchElementException if standard input is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
float}
*/
public
static
float
readFloat
()
{
try
{
return
scanner
.
nextFloat
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read a ‘float’ value from standard input, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attempts to read a ‘float’ value from standard input, ”
+
“but there no more tokens are available”
);
}
}
/**
* Reads the next token from standard input, parses it as a long integer, and returns the long integer.
*
*
@return
the next long integer on standard input
*
@throws
NoSuchElementException if standard input is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
long}
*/
public
static
long
readLong
()
{
try
{
return
scanner
.
nextLong
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read a ‘long’ value from standard input, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attempts to read a ‘long’ value from standard input, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from standard input, parses it as a short integer, and returns the short integer.
*
*
@return
the next short integer on standard input
*
@throws
NoSuchElementException if standard input is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
short}
*/
public
static
short
readShort
()
{
try
{
return
scanner
.
nextShort
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read a ‘short’ value from standard input, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attempts to read a ‘short’ value from standard input, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from standard input, parses it as a byte, and returns the byte.
*
*
@return
the next byte on standard input
*
@throws
NoSuchElementException if standard input is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
byte}
*/
public
static
byte
readByte
()
{
try
{
return
scanner
.
nextByte
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read a ‘byte’ value from standard input, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attempts to read a ‘byte’ value from standard input, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from standard input, parses it as a boolean,
* and returns the boolean.
*
*
@return
the next boolean on standard input
*
@throws
NoSuchElementException if standard input is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
boolean}:
* {
@code
true} or {
@code
1} for true, and {
@code
false} or {
@code
0} for false,
* ignoring case
*/
public
static
boolean
readBoolean
()
{
try
{
String
token
=
readString
();
if
(
“true”
.
equalsIgnoreCase
(
token
))
return
true
;
if
(
“false”
.
equalsIgnoreCase
(
token
))
return
false
;
if
(
“1”
.
equals
(
token
))
return
true
;
if
(
“0”
.
equals
(
token
))
return
false
;
throw
new
InputMismatchException
(
“attempts to read a ‘boolean’ value from standard input, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attempts to read a ‘boolean’ value from standard input, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads all remaining tokens from standard input and returns them as an array of strings.
*
*
@return
all remaining tokens on standard input, as an array of strings
*/
public
static
String
[]
readAllStrings
()
{
// we could use readAll.trim().split(), but that’s not consistent
// because trim() uses characters 0x00..0x20 as whitespace
String
[]
tokens
=
WHITESPACE_PATTERN
.
split
(
readAll
());
if
(
tokens
.
length
==
0
||
tokens
[
0
].
length
()
>
0
)
return
tokens
;
// don’t include first token if it is leading whitespace
String
[]
decapitokens
=
new
String
[
tokens
.
length
–
1
];
for
(
int
i
=
0
;
i
<
tokens
.
length
-
1
;
i
++
)
decapitokens
[
i
]
=
tokens
[
i
+
1
];
return
decapitokens
;
}
/**
* Reads all remaining lines from standard input and returns them as an array of strings.
*
@return
all remaining lines on standard input, as an array of strings
*/
public
static
String
[]
readAllLines
()
{
ArrayList
<
String
>
lines
=
new
ArrayList
<
String
>
();
while
(
hasNextLine
())
{
lines
.
add
(
readLine
());
}
return
lines
.
toArray
(
new
String
[
lines
.
size
()]);
}
/**
* Reads all remaining tokens from standard input, parses them as integers, and returns
* them as an array of integers.
*
@return
all remaining integers on standard input, as an array
*
@throws
InputMismatchException if any token cannot be parsed as an {
@code
int}
*/
public
static
int
[]
readAllInts
()
{
String
[]
fields
=
readAllStrings
();
int
[]
vals
=
new
int
[
fields
.
length
];
for
(
int
i
=
0
;
i
<
fields
.
length
;
i
++
)
vals
[
i
]
=
Integer
.
parseInt
(
fields
[
i
]);
return
vals
;
}
/**
* Reads all remaining tokens from standard input, parses them as longs, and returns
* them as an array of longs.
*
@return
all remaining longs on standard input, as an array
*
@throws
InputMismatchException if any token cannot be parsed as a {
@code
long}
*/
public
static
long
[]
readAllLongs
()
{
String
[]
fields
=
readAllStrings
();
long
[]
vals
=
new
long
[
fields
.
length
];
for
(
int
i
=
0
;
i
<
fields
.
length
;
i
++
)
vals
[
i
]
=
Long
.
parseLong
(
fields
[
i
]);
return
vals
;
}
/**
* Reads all remaining tokens from standard input, parses them as doubles, and returns
* them as an array of doubles.
*
@return
all remaining doubles on standard input, as an array
*
@throws
InputMismatchException if any token cannot be parsed as a {
@code
double}
*/
public
static
double
[]
readAllDoubles
()
{
String
[]
fields
=
readAllStrings
();
double
[]
vals
=
new
double
[
fields
.
length
];
for
(
int
i
=
0
;
i
<
fields
.
length
;
i
++
)
vals
[
i
]
=
Double
.
parseDouble
(
fields
[
i
]);
return
vals
;
}
//// end: section (2 of 2) of code duplicated from In to StdIn
// do this once when StdIn is initialized
static
{
resync
();
}
/**
* If StdIn changes, use this to reinitialize the scanner.
*/
private
static
void
resync
()
{
setScanner
(
new
Scanner
(
new
java
.
io
.
BufferedInputStream
(
System
.
in
),
CHARSET_NAME
));
}
private
static
void
setScanner
(
Scanner
scanner
)
{
StdIn
.
scanner
=
scanner
;
StdIn
.
scanner
.
useLocale
(
LOCALE
);
}
/**
* Reads all remaining tokens, parses them as integers, and returns
* them as an array of integers.
*
@return
all remaining integers, as an array
*
@throws
InputMismatchException if any token cannot be parsed as an {
@code
int}
*
@deprecated
Replaced by {
@link
#readAllInts()}.
*/
@
Deprecated
public
static
int
[]
readInts
()
{
return
readAllInts
();
}
/**
* Reads all remaining tokens, parses them as doubles, and returns
* them as an array of doubles.
*
@return
all remaining doubles, as an array
*
@throws
InputMismatchException if any token cannot be parsed as a {
@code
double}
*
@deprecated
Replaced by {
@link
#readAllDoubles()}.
*/
@
Deprecated
public
static
double
[]
readDoubles
()
{
return
readAllDoubles
();
}
/**
* Reads all remaining tokens and returns them as an array of strings.
*
@return
all remaining tokens, as an array of strings
*
@deprecated
Replaced by {
@link
#readAllStrings()}.
*/
@
Deprecated
public
static
String
[]
readStrings
()
{
return
readAllStrings
();
}
/**
* Interactive test of basic functionality.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
StdOut
.
print
(
"Type a string: "
);
String
s
=
StdIn
.
readString
();
StdOut
.
println
(
"Your string was: "
+
s
);
StdOut
.
println
();
StdOut
.
print
(
"Type an int: "
);
int
a
=
StdIn
.
readInt
();
StdOut
.
println
(
"Your int was: "
+
a
);
StdOut
.
println
();
StdOut
.
print
(
"Type a boolean: "
);
boolean
b
=
StdIn
.
readBoolean
();
StdOut
.
println
(
"Your boolean was: "
+
b
);
StdOut
.
println
();
StdOut
.
print
(
"Type a double: "
);
double
c
=
StdIn
.
readDouble
();
StdOut
.
println
(
"Your double was: "
+
c
);
StdOut
.
println
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/StdOut.java
edu/princeton/cs/algs4/StdOut.java
/******************************************************************************
* Compilation: javac StdOut.java
* Execution: java StdOut
* Dependencies: none
*
* Writes data of various types to standard output.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
io
.
OutputStreamWriter
;
import
java
.
io
.
PrintWriter
;
import
java
.
io
.
UnsupportedEncodingException
;
import
java
.
util
.
Locale
;
/**
* This class provides methods for printing strings and numbers to standard output.
*
* Getting started.
* To use this class, you must have {
@code
StdOut.class} in your
* Java classpath. If you used our autoinstaller, you should be all set.
* Otherwise, either download
* and add to your Java classpath or download
* and put a copy in your working directory.
*
* Here is an example program that uses {
@code
StdOut}:
*
* public class TestStdOut { * public static void main(String[] args) { * int a = 17; * int b = 23; * int sum = a + b; * StdOut.println("Hello, World"); * StdOut.printf("%d + %d = %d\n", a, b, sum); * } * } *
*
* Differences with System.out.
* The behavior of {
@code
StdOut} is similar to that of {
@link
System#out},
* but there are a few technical differences:
*
*
* which is a standard character encoding for Unicode.
*
* for consistency with {
@link
StdIn}, {
@link
Double#parseDouble(String)},
* and floating-point literals.
*
* {
@code
print()} so that text will appear immediately in the terminal.
*
*
* Reference.
* For additional documentation,
* see Section 1.5 of
* Computer Science: An Interdisciplinary Approach
* by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
StdOut
{
// force Unicode UTF-8 encoding; otherwise it’s system dependent
private
static
final
String
CHARSET_NAME
=
“UTF-8”
;
// assume language = English, country = US for consistency with StdIn
private
static
final
Locale
LOCALE
=
Locale
.
US
;
// send output here
private
static
PrintWriter
out
;
// this is called before invoking any methods
static
{
try
{
out
=
new
PrintWriter
(
new
OutputStreamWriter
(
System
.
out
,
CHARSET_NAME
),
true
);
}
catch
(
UnsupportedEncodingException
e
)
{
System
.
out
.
println
(
e
);
}
}
// don’t instantiate
private
StdOut
()
{
}
/**
* Terminates the current line by printing the line-separator string.
*/
public
static
void
println
()
{
out
.
println
();
}
/**
* Prints an object to this output stream and then terminates the line.
*
*
@param
x the object to print
*/
public
static
void
println
(
Object
x
)
{
out
.
println
(
x
);
}
/**
* Prints a boolean to standard output and then terminates the line.
*
*
@param
x the boolean to print
*/
public
static
void
println
(
boolean
x
)
{
out
.
println
(
x
);
}
/**
* Prints a character to standard output and then terminates the line.
*
*
@param
x the character to print
*/
public
static
void
println
(
char
x
)
{
out
.
println
(
x
);
}
/**
* Prints a double to standard output and then terminates the line.
*
*
@param
x the double to print
*/
public
static
void
println
(
double
x
)
{
out
.
println
(
x
);
}
/**
* Prints an integer to standard output and then terminates the line.
*
*
@param
x the integer to print
*/
public
static
void
println
(
float
x
)
{
out
.
println
(
x
);
}
/**
* Prints an integer to standard output and then terminates the line.
*
*
@param
x the integer to print
*/
public
static
void
println
(
int
x
)
{
out
.
println
(
x
);
}
/**
* Prints a long to standard output and then terminates the line.
*
*
@param
x the long to print
*/
public
static
void
println
(
long
x
)
{
out
.
println
(
x
);
}
/**
* Prints a short integer to standard output and then terminates the line.
*
*
@param
x the short to print
*/
public
static
void
println
(
short
x
)
{
out
.
println
(
x
);
}
/**
* Prints a byte to standard output and then terminates the line.
*
* To write binary data, see {
@link
BinaryStdOut}.
*
*
@param
x the byte to print
*/
public
static
void
println
(
byte
x
)
{
out
.
println
(
x
);
}
/**
* Flushes standard output.
*/
public
static
void
print
()
{
out
.
flush
();
}
/**
* Prints an object to standard output and flushes standard output.
*
*
@param
x the object to print
*/
public
static
void
print
(
Object
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a boolean to standard output and flushes standard output.
*
*
@param
x the boolean to print
*/
public
static
void
print
(
boolean
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a character to standard output and flushes standard output.
*
*
@param
x the character to print
*/
public
static
void
print
(
char
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a double to standard output and flushes standard output.
*
*
@param
x the double to print
*/
public
static
void
print
(
double
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a float to standard output and flushes standard output.
*
*
@param
x the float to print
*/
public
static
void
print
(
float
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints an integer to standard output and flushes standard output.
*
*
@param
x the integer to print
*/
public
static
void
print
(
int
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a long integer to standard output and flushes standard output.
*
*
@param
x the long integer to print
*/
public
static
void
print
(
long
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a short integer to standard output and flushes standard output.
*
*
@param
x the short integer to print
*/
public
static
void
print
(
short
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a byte to standard output and flushes standard output.
*
*
@param
x the byte to print
*/
public
static
void
print
(
byte
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a formatted string to standard output, using the specified format
* string and arguments, and then flushes standard output.
*
*
*
@param
format the format string
*
@param
args the arguments accompanying the format string
*/
public
static
void
printf
(
String
format
,
Object
…
args
)
{
out
.
printf
(
LOCALE
,
format
,
args
);
out
.
flush
();
}
/**
* Prints a formatted string to standard output, using the locale and
* the specified format string and arguments; then flushes standard output.
*
*
@param
locale the locale
*
@param
format the format string
*
@param
args the arguments accompanying the format string
*/
public
static
void
printf
(
Locale
locale
,
String
format
,
Object
…
args
)
{
out
.
printf
(
locale
,
format
,
args
);
out
.
flush
();
}
/**
* Unit tests some of the methods in {
@code
StdOut}.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// write to stdout
StdOut
.
println
(
“Test”
);
StdOut
.
println
(
17
);
StdOut
.
println
(
true
);
StdOut
.
printf
(
“%.6f\n”
,
1.0
/
7.0
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/StdRandom.java
edu/princeton/cs/algs4/StdRandom.java
/******************************************************************************
* Compilation: javac StdRandom.java
* Execution: java StdRandom
* Dependencies: StdOut.java
*
* A library of static methods to generate pseudo-random numbers from
* different distributions (bernoulli, uniform, gaussian, discrete,
* and exponential). Also includes a method for shuffling an array.
*
*
* % java StdRandom 5
* seed = 1316600602069
* 59 16.81826 true 8.83954 0
* 32 91.32098 true 9.11026 0
* 35 10.11874 true 8.95396 3
* 92 32.88401 true 8.87089 0
* 72 92.55791 true 9.46241 0
*
* % java StdRandom 5
* seed = 1316600616575
* 96 60.17070 true 8.72821 0
* 79 32.01607 true 8.58159 0
* 81 59.49065 true 9.10423 1
* 96 51.65818 true 9.02102 0
* 99 17.55771 true 8.99762 0
*
* % java StdRandom 5 1316600616575
* seed = 1316600616575
* 96 60.17070 true 8.72821 0
* 79 32.01607 true 8.58159 0
* 81 59.49065 true 9.10423 1
* 96 51.65818 true 9.02102 0
* 99 17.55771 true 8.99762 0
*
*
* Remark
* ——
* – Relies on randomness of nextDouble() method in java.util.Random
* to generate pseudo-random numbers in [0, 1).
*
* – This library allows you to set and get the pseudo-random number seed.
*
* – See http://www.honeylocust.com/RngPack/ for an industrial
* strength random number generator in Java.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Random
;
/**
* The {
@code
StdRandom} class provides static methods for generating
* random number from various discrete and continuous distributions,
* including uniform, Bernoulli, geometric, Gaussian, exponential, Pareto,
* Poisson, and Cauchy. It also provides method for shuffling an
* array or subarray and generating random permutations.
*
* By convention, all intervals are half open. For example,
* uniform(-1.0, 1.0)
returns a random number between
* -1.0
(inclusive) and 1.0
(exclusive).
* Similarly, shuffle(a, lo, hi)
shuffles the hi - lo
* elements in the array a[]
, starting at index lo
* (inclusive) and ending at index hi
(exclusive).
*
* For additional documentation,
* see Section 2.2 of
* Computer Science: An Interdisciplinary Approach
* by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
StdRandom
{
private
static
Random
random
;
// pseudo-random number generator
private
static
long
seed
;
// pseudo-random number generator seed
// static initializer
static
{
// this is how the seed was set in Java 1.4
seed
=
System
.
currentTimeMillis
();
random
=
new
Random
(
seed
);
}
// don’t instantiate
private
StdRandom
()
{
}
/**
* Sets the seed of the pseudo-random number generator.
* This method enables you to produce the same sequence of “random”
* number for each execution of the program.
* Ordinarily, you should call this method at most once per program.
*
*
@param
s the seed
*/
public
static
void
setSeed
(
long
s
)
{
seed
=
s
;
random
=
new
Random
(
seed
);
}
/**
* Returns the seed of the pseudo-random number generator.
*
*
@return
the seed
*/
public
static
long
getSeed
()
{
return
seed
;
}
/**
* Returns a random real number uniformly in [0, 1).
*
*
@return
a random real number uniformly in [0, 1)
*/
public
static
double
uniform
()
{
return
random
.
nextDouble
();
}
/**
* Returns a random integer uniformly in [0, n).
*
*
@param
n number of possible integers
*
@return
a random integer uniformly between 0 (inclusive) and {
@code
n} (exclusive)
*
@throws
IllegalArgumentException if {
@code
n <= 0}
*/
public
static
int
uniform
(
int
n
)
{
if
(
n
<=
0
)
throw
new
IllegalArgumentException
(
"argument must be positive: "
+
n
);
return
random
.
nextInt
(
n
);
}
/**
* Returns a random long integer uniformly in [0, n).
*
*
@param
n number of possible {
@code
long} integers
*
@return
a random long integer uniformly between 0 (inclusive) and {
@code
n} (exclusive)
*
@throws
IllegalArgumentException if {
@code
n <= 0}
*/
public
static
long
uniform
(
long
n
)
{
if
(
n
<=
0L
)
throw
new
IllegalArgumentException
(
"argument must be positive: "
+
n
);
// https://docs.oracle.com/javase/8/docs/api/java/util/Random.html#longs-long-long-long-
long
r
=
random
.
nextLong
();
long
m
=
n
-
1
;
// power of two
if
((
n
&
m
)
==
0L
)
{
return
r
&
m
;
}
// reject over-represented candidates
long
u
=
r
>>>
1
;
while
(
u
+
m
–
(
r
=
u
%
n
)
<
0L
)
{
u
=
random
.
nextLong
()
>>>
1
;
}
return
r
;
}
///////////////////////////////////////////////////////////////////////////
// STATIC METHODS BELOW RELY ON JAVA.UTIL.RANDOM ONLY INDIRECTLY VIA
// THE STATIC METHODS ABOVE.
///////////////////////////////////////////////////////////////////////////
/**
* Returns a random real number uniformly in [0, 1).
*
*
@return
a random real number uniformly in [0, 1)
*
@deprecated
Replaced by {
@link
#uniform()}.
*/
@
Deprecated
public
static
double
random
()
{
return
uniform
();
}
/**
* Returns a random integer uniformly in [a, b).
*
*
@param
a the left endpoint
*
@param
b the right endpoint
*
@return
a random integer uniformly in [a, b)
*
@throws
IllegalArgumentException if {
@code
b <= a}
*
@throws
IllegalArgumentException if {
@code
b - a >= Integer.MAX_VALUE}
*/
public
static
int
uniform
(
int
a
,
int
b
)
{
if
((
b
<=
a
)
||
((
long
)
b
-
a
>=
Integer
.
MAX_VALUE
))
{
throw
new
IllegalArgumentException
(
“invalid range: [”
+
a
+
“, ”
+
b
+
“)”
);
}
return
a
+
uniform
(
b
–
a
);
}
/**
* Returns a random real number uniformly in [a, b).
*
*
@param
a the left endpoint
*
@param
b the right endpoint
*
@return
a random real number uniformly in [a, b)
*
@throws
IllegalArgumentException unless {
@code
a < b}
*/
public
static
double
uniform
(
double
a
,
double
b
)
{
if
(
!
(
a
<
b
))
{
throw
new
IllegalArgumentException
(
"invalid range: ["
+
a
+
", "
+
b
+
")"
);
}
return
a
+
uniform
()
*
(
b
-
a
);
}
/**
* Returns a random boolean from a Bernoulli distribution with success
* probability p.
*
*
@param
p the probability of returning {
@code
true}
*
@return
{
@code
true} with probability {
@code
p} and
* {
@code
false} with probability {
@code
1 – p}
*
@throws
IllegalArgumentException unless {
@code
0} ≤ {
@code
p} ≤ {
@code
1.0}
*/
public
static
boolean
bernoulli
(
double
p
)
{
if
(
!
(
p
>=
0.0
&&
p
<=
1.0
))
throw
new
IllegalArgumentException
(
"probability p must be between 0.0 and 1.0: "
+
p
);
return
uniform
()
<
p
;
}
/**
* Returns a random boolean from a Bernoulli distribution with success
* probability 1/2.
*
*
@return
{
@code
true} with probability 1/2 and
* {
@code
false} with probability 1/2
*/
public
static
boolean
bernoulli
()
{
return
bernoulli
(
0.5
);
}
/**
* Returns a random real number from a standard Gaussian distribution.
*
*
@return
a random real number from a standard Gaussian distribution
* (mean 0 and standard deviation 1).
*/
public
static
double
gaussian
()
{
// use the polar form of the Box-Muller transform
double
r
,
x
,
y
;
do
{
x
=
uniform
(
-
1.0
,
1.0
);
y
=
uniform
(
-
1.0
,
1.0
);
r
=
x
*
x
+
y
*
y
;
}
while
(
r
>=
1
||
r
==
0
);
return
x
*
Math
.
sqrt
(
–
2
*
Math
.
log
(
r
)
/
r
);
// Remark: y * Math.sqrt(-2 * Math.log(r) / r)
// is an independent random gaussian
}
/**
* Returns a random real number from a Gaussian distribution with mean μ
* and standard deviation σ.
*
*
@param
mu the mean
*
@param
sigma the standard deviation
*
@return
a real number distributed according to the Gaussian distribution
* with mean {
@code
mu} and standard deviation {
@code
sigma}
*/
public
static
double
gaussian
(
double
mu
,
double
sigma
)
{
return
mu
+
sigma
*
gaussian
();
}
/**
* Returns a random integer from a geometric distribution with success
* probability p.
* The integer represents the number of independent trials
* before the first success.
*
*
@param
p the parameter of the geometric distribution
*
@return
a random integer from a geometric distribution with success
* probability {
@code
p}; or {
@code
Integer.MAX_VALUE} if
* {
@code
p} is (nearly) equal to {
@code
1.0}.
*
@throws
IllegalArgumentException unless {
@code
p >= 0.0} and {
@code
p <= 1.0}
*/
public
static
int
geometric
(
double
p
)
{
if
(
!
(
p
>=
0
))
{
throw
new
IllegalArgumentException
(
“probability p must be greater than 0: ”
+
p
);
}
if
(
!
(
p
<=
1.0
))
{
throw
new
IllegalArgumentException
(
"probability p must not be larger than 1: "
+
p
);
}
// using algorithm given by Knuth
return
(
int
)
Math
.
ceil
(
Math
.
log
(
uniform
())
/
Math
.
log
(
1.0
-
p
));
}
/**
* Returns a random integer from a Poisson distribution with mean λ.
*
*
@param
lambda the mean of the Poisson distribution
*
@return
a random integer from a Poisson distribution with mean {
@code
lambda}
*
@throws
IllegalArgumentException unless {
@code
lambda > 0.0} and not infinite
*/
public
static
int
poisson
(
double
lambda
)
{
if
(
!
(
lambda
>
0.0
))
throw
new
IllegalArgumentException
(
“lambda must be positive: ”
+
lambda
);
if
(
Double
.
isInfinite
(
lambda
))
throw
new
IllegalArgumentException
(
“lambda must not be infinite: ”
+
lambda
);
// using algorithm given by Knuth
// see http://en.wikipedia.org/wiki/Poisson_distribution
int
k
=
0
;
double
p
=
1.0
;
double
expLambda
=
Math
.
exp
(
–
lambda
);
do
{
k
++
;
p
*=
uniform
();
}
while
(
p
>=
expLambda
);
return
k
–
1
;
}
/**
* Returns a random real number from the standard Pareto distribution.
*
*
@return
a random real number from the standard Pareto distribution
*/
public
static
double
pareto
()
{
return
pareto
(
1.0
);
}
/**
* Returns a random real number from a Pareto distribution with
* shape parameter α.
*
*
@param
alpha shape parameter
*
@return
a random real number from a Pareto distribution with shape
* parameter {
@code
alpha}
*
@throws
IllegalArgumentException unless {
@code
alpha > 0.0}
*/
public
static
double
pareto
(
double
alpha
)
{
if
(
!
(
alpha
>
0.0
))
throw
new
IllegalArgumentException
(
“alpha must be positive: ”
+
alpha
);
return
Math
.
pow
(
1
–
uniform
(),
–
1.0
/
alpha
)
–
1.0
;
}
/**
* Returns a random real number from the Cauchy distribution.
*
*
@return
a random real number from the Cauchy distribution.
*/
public
static
double
cauchy
()
{
return
Math
.
tan
(
Math
.
PI
*
(
uniform
()
–
0.5
));
}
/**
* Returns a random integer from the specified discrete distribution.
*
*
@param
probabilities the probability of occurrence of each integer
*
@return
a random integer from a discrete distribution:
* {
@code
i} with probability {
@code
probabilities[i]}
*
@throws
IllegalArgumentException if {
@code
probabilities} is {
@code
null}
*
@throws
IllegalArgumentException if sum of array entries is not (very nearly) equal to {
@code
1.0}
*
@throws
IllegalArgumentException unless {
@code
probabilities[i] >= 0.0} for each index {
@code
i}
*/
public
static
int
discrete
(
double
[]
probabilities
)
{
if
(
probabilities
==
null
)
throw
new
IllegalArgumentException
(
“argument array is null”
);
double
EPSILON
=
1.0E-14
;
double
sum
=
0.0
;
for
(
int
i
=
0
;
i
<
probabilities
.
length
;
i
++
)
{
if
(
!
(
probabilities
[
i
]
>=
0.0
))
throw
new
IllegalArgumentException
(
“array entry ”
+
i
+
” must be nonnegative: ”
+
probabilities
[
i
]);
sum
+=
probabilities
[
i
];
}
if
(
sum
>
1.0
+
EPSILON
||
sum
<
1.0
-
EPSILON
)
throw
new
IllegalArgumentException
(
"sum of array entries does not approximately equal 1.0: "
+
sum
);
// the for loop may not return a value when both r is (nearly) 1.0 and when the
// cumulative sum is less than 1.0 (as a result of floating-point roundoff error)
while
(
true
)
{
double
r
=
uniform
();
sum
=
0.0
;
for
(
int
i
=
0
;
i
<
probabilities
.
length
;
i
++
)
{
sum
=
sum
+
probabilities
[
i
];
if
(
sum
>
r
)
return
i
;
}
}
}
/**
* Returns a random integer from the specified discrete distribution.
*
*
@param
frequencies the frequency of occurrence of each integer
*
@return
a random integer from a discrete distribution:
* {
@code
i} with probability proportional to {
@code
frequencies[i]}
*
@throws
IllegalArgumentException if {
@code
frequencies} is {
@code
null}
*
@throws
IllegalArgumentException if all array entries are {
@code
0}
*
@throws
IllegalArgumentException if {
@code
frequencies[i]} is negative for any index {
@code
i}
*
@throws
IllegalArgumentException if sum of frequencies exceeds {
@code
Integer.MAX_VALUE} (231 – 1)
*/
public
static
int
discrete
(
int
[]
frequencies
)
{
if
(
frequencies
==
null
)
throw
new
IllegalArgumentException
(
“argument array is null”
);
long
sum
=
0
;
for
(
int
i
=
0
;
i
<
frequencies
.
length
;
i
++
)
{
if
(
frequencies
[
i
]
<
0
)
throw
new
IllegalArgumentException
(
"array entry "
+
i
+
" must be nonnegative: "
+
frequencies
[
i
]);
sum
+=
frequencies
[
i
];
}
if
(
sum
==
0
)
throw
new
IllegalArgumentException
(
"at least one array entry must be positive"
);
if
(
sum
>=
Integer
.
MAX_VALUE
)
throw
new
IllegalArgumentException
(
“sum of frequencies overflows an int”
);
// pick index i with probabilitity proportional to frequency
double
r
=
uniform
((
int
)
sum
);
sum
=
0
;
for
(
int
i
=
0
;
i
<
frequencies
.
length
;
i
++
)
{
sum
+=
frequencies
[
i
];
if
(
sum
>
r
)
return
i
;
}
// can’t reach here
assert
false
;
return
–
1
;
}
/**
* Returns a random real number from an exponential distribution
* with rate λ.
*
*
@param
lambda the rate of the exponential distribution
*
@return
a random real number from an exponential distribution with
* rate {
@code
lambda}
*
@throws
IllegalArgumentException unless {
@code
lambda > 0.0}
*/
public
static
double
exp
(
double
lambda
)
{
if
(
!
(
lambda
>
0.0
))
throw
new
IllegalArgumentException
(
“lambda must be positive: ”
+
lambda
);
return
–
Math
.
log
(
1
–
uniform
())
/
lambda
;
}
/**
* Rearranges the elements of the specified array in uniformly random order.
*
*
@param
a the array to shuffle
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*/
public
static
void
shuffle
(
Object
[]
a
)
{
validateNotNull
(
a
);
int
n
=
a
.
length
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
int
r
=
i
+
uniform
(
n
-
i
);
// between i and n-1
Object
temp
=
a
[
i
];
a
[
i
]
=
a
[
r
];
a
[
r
]
=
temp
;
}
}
/**
* Rearranges the elements of the specified array in uniformly random order.
*
*
@param
a the array to shuffle
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*/
public
static
void
shuffle
(
double
[]
a
)
{
validateNotNull
(
a
);
int
n
=
a
.
length
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
int
r
=
i
+
uniform
(
n
-
i
);
// between i and n-1
double
temp
=
a
[
i
];
a
[
i
]
=
a
[
r
];
a
[
r
]
=
temp
;
}
}
/**
* Rearranges the elements of the specified array in uniformly random order.
*
*
@param
a the array to shuffle
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*/
public
static
void
shuffle
(
int
[]
a
)
{
validateNotNull
(
a
);
int
n
=
a
.
length
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
int
r
=
i
+
uniform
(
n
-
i
);
// between i and n-1
int
temp
=
a
[
i
];
a
[
i
]
=
a
[
r
];
a
[
r
]
=
temp
;
}
}
/**
* Rearranges the elements of the specified array in uniformly random order.
*
*
@param
a the array to shuffle
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*/
public
static
void
shuffle
(
char
[]
a
)
{
validateNotNull
(
a
);
int
n
=
a
.
length
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
int
r
=
i
+
uniform
(
n
-
i
);
// between i and n-1
char
temp
=
a
[
i
];
a
[
i
]
=
a
[
r
];
a
[
r
]
=
temp
;
}
}
/**
* Rearranges the elements of the specified subarray in uniformly random order.
*
*
@param
a the array to shuffle
*
@param
lo the left endpoint (inclusive)
*
@param
hi the right endpoint (exclusive)
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*
@throws
IllegalArgumentException unless {
@code
(0 <= lo) && (lo < hi) && (hi <= a.length)}
*
*/
public
static
void
shuffle
(
Object
[]
a
,
int
lo
,
int
hi
)
{
validateNotNull
(
a
);
validateSubarrayIndices
(
lo
,
hi
,
a
.
length
);
for
(
int
i
=
lo
;
i
<
hi
;
i
++
)
{
int
r
=
i
+
uniform
(
hi
-
i
);
// between i and hi-1
Object
temp
=
a
[
i
];
a
[
i
]
=
a
[
r
];
a
[
r
]
=
temp
;
}
}
/**
* Rearranges the elements of the specified subarray in uniformly random order.
*
*
@param
a the array to shuffle
*
@param
lo the left endpoint (inclusive)
*
@param
hi the right endpoint (exclusive)
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*
@throws
IllegalArgumentException unless {
@code
(0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
public
static
void
shuffle
(
double
[]
a
,
int
lo
,
int
hi
)
{
validateNotNull
(
a
);
validateSubarrayIndices
(
lo
,
hi
,
a
.
length
);
for
(
int
i
=
lo
;
i
<
hi
;
i
++
)
{
int
r
=
i
+
uniform
(
hi
-
i
);
// between i and hi-1
double
temp
=
a
[
i
];
a
[
i
]
=
a
[
r
];
a
[
r
]
=
temp
;
}
}
/**
* Rearranges the elements of the specified subarray in uniformly random order.
*
*
@param
a the array to shuffle
*
@param
lo the left endpoint (inclusive)
*
@param
hi the right endpoint (exclusive)
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*
@throws
IllegalArgumentException unless {
@code
(0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
public
static
void
shuffle
(
int
[]
a
,
int
lo
,
int
hi
)
{
validateNotNull
(
a
);
validateSubarrayIndices
(
lo
,
hi
,
a
.
length
);
for
(
int
i
=
lo
;
i
<
hi
;
i
++
)
{
int
r
=
i
+
uniform
(
hi
-
i
);
// between i and hi-1
int
temp
=
a
[
i
];
a
[
i
]
=
a
[
r
];
a
[
r
]
=
temp
;
}
}
/**
* Returns a uniformly random permutation of n elements.
*
*
@param
n number of elements
*
@throws
IllegalArgumentException if {
@code
n} is negative
*
@return
an array of length {
@code
n} that is a uniformly random permutation
* of {
@code
0}, {
@code
1}, …, {
@code
n-1}
*/
public
static
int
[]
permutation
(
int
n
)
{
if
(
n
<
0
)
throw
new
IllegalArgumentException
(
"argument is negative"
);
int
[]
perm
=
new
int
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
perm
[
i
]
=
i
;
shuffle
(
perm
);
return
perm
;
}
/**
* Returns a uniformly random permutation of k of n elements.
*
*
@param
n number of elements
*
@param
k number of elements to select
*
@throws
IllegalArgumentException if {
@code
n} is negative
*
@throws
IllegalArgumentException unless {
@code
0 <= k <= n}
*
@return
an array of length {
@code
k} that is a uniformly random permutation
* of {
@code
k} of the elements from {
@code
0}, {
@code
1}, ..., {
@code
n-1}
*/
public
static
int
[]
permutation
(
int
n
,
int
k
)
{
if
(
n
<
0
)
throw
new
IllegalArgumentException
(
"argument is negative"
);
if
(
k
<
0
||
k
>
n
)
throw
new
IllegalArgumentException
(
“k must be between 0 and n”
);
int
[]
perm
=
new
int
[
k
];
for
(
int
i
=
0
;
i
<
k
;
i
++
)
{
int
r
=
uniform
(
i
+
1
);
// between 0 and i
perm
[
i
]
=
perm
[
r
];
perm
[
r
]
=
i
;
}
for
(
int
i
=
k
;
i
<
n
;
i
++
)
{
int
r
=
uniform
(
i
+
1
);
// between 0 and i
if
(
r
<
k
)
perm
[
r
]
=
i
;
}
return
perm
;
}
// throw an IllegalArgumentException if x is null
// (x can be of type Object[], double[], int[], ...)
private
static
void
validateNotNull
(
Object
x
)
{
if
(
x
==
null
)
{
throw
new
IllegalArgumentException
(
"argument is null"
);
}
}
// throw an exception unless 0 <= lo <= hi <= length
private
static
void
validateSubarrayIndices
(
int
lo
,
int
hi
,
int
length
)
{
if
(
lo
<
0
||
hi
>
length
||
lo
>
hi
)
{
throw
new
IllegalArgumentException
(
“subarray indices out of bounds: [”
+
lo
+
“, ”
+
hi
+
“)”
);
}
}
/**
* Unit tests the methods in this class.
*
*
@param
args the command-line arguments
*/
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
if (args.length == 2) StdRandom.setSeed(Long.parseLong(args[1]));
double[] probabilities = { 0.5, 0.3, 0.1, 0.1 };
int[] frequencies = { 5, 3, 1, 1 };
String[] a = “A B C D E F G”.split(” “);
StdOut.println(“seed = ” + StdRandom.getSeed());
for (int i = 0; i < n; i++) { StdOut.printf("%2d ", uniform(100)); StdOut.printf("%8.5f ", uniform(10.0, 99.0)); StdOut.printf("%5b ", bernoulli(0.5)); StdOut.printf("%7.5f ", gaussian(9.0, 0.2)); StdOut.printf("%1d ", discrete(probabilities)); StdOut.printf("%1d ", discrete(frequencies)); StdOut.printf("%11d ", uniform(100000000000L)); StdRandom.shuffle(a); for (String s : a) StdOut.print(s); StdOut.println(); } } } /****************************************************************************** * Copyright 2002-2020, Robert Sedgewick and Kevin Wayne. * * This file is part of algs4.jar, which accompanies the textbook * * Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne, * Addison-Wesley Professional, 2011, ISBN 0-321-57351-X. * http://algs4.cs.princeton.edu * * * algs4.jar is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * algs4.jar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with algs4.jar. If not, see http://www.gnu.org/licenses. ******************************************************************************/ edu/princeton/cs/algs4/StdStats.java edu/princeton/cs/algs4/StdStats.java /****************************************************************************** * Compilation: javac StdStats.java * Execution: java StdStats < input.txt * Dependencies: StdOut.java * * Library of statistical functions. * * The test client reads an array of real numbers from standard * input, and computes the minimum, mean, maximum, and * standard deviation. * * The functions all throw a java.lang.IllegalArgumentException * if the array passed in as an argument is null. * * The floating-point functions all return NaN if any input is NaN. * * Unlike Math.min() and Math.max(), the min() and max() functions * do not differentiate between -0.0 and 0.0. * * % more tiny.txt * 5 * 3.0 1.0 2.0 5.0 4.0 * * % java StdStats < tiny.txt * min 1.000 * mean 3.000 * max 5.000 * std dev 1.581 * * Should these funtions use varargs instead of array arguments? * ******************************************************************************/ package edu . princeton . cs . algs4 ; /** * The { @code StdStats} class provides static methods for computing * statistics such as min, max, mean, sample standard deviation, and * sample variance. *
* For additional documentation, see
* Section 2.2 of
* Computer Science: An Interdisciplinary Approach
* by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
StdStats
{
private
StdStats
()
{
}
/**
* Returns the maximum value in the specified array.
*
*
@param
a the array
*
@return
the maximum value in the array {
@code
a[]};
* {
@code
Double.NEGATIVE_INFINITY} if no such value
*/
public
static
double
max
(
double
[]
a
)
{
validateNotNull
(
a
);
double
max
=
Double
.
NEGATIVE_INFINITY
;
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
if
(
Double
.
isNaN
(
a
[
i
]))
return
Double
.
NaN
;
if
(
a
[
i
]
>
max
)
max
=
a
[
i
];
}
return
max
;
}
/**
* Returns the maximum value in the specified subarray.
*
*
@param
a the array
*
@param
lo the left endpoint of the subarray (inclusive)
*
@param
hi the right endpoint of the subarray (exclusive)
*
@return
the maximum value in the subarray {
@code
a[lo..hi)};
* {
@code
Double.NEGATIVE_INFINITY} if no such value
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*
@throws
IllegalArgumentException unless {
@code
(0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
public
static
double
max
(
double
[]
a
,
int
lo
,
int
hi
)
{
validateNotNull
(
a
);
validateSubarrayIndices
(
lo
,
hi
,
a
.
length
);
double
max
=
Double
.
NEGATIVE_INFINITY
;
for
(
int
i
=
lo
;
i
<
hi
;
i
++
)
{
if
(
Double
.
isNaN
(
a
[
i
]))
return
Double
.
NaN
;
if
(
a
[
i
]
>
max
)
max
=
a
[
i
];
}
return
max
;
}
/**
* Returns the maximum value in the specified array.
*
*
@param
a the array
*
@return
the maximum value in the array {
@code
a[]};
* {
@code
Integer.MIN_VALUE} if no such value
*/
public
static
int
max
(
int
[]
a
)
{
validateNotNull
(
a
);
int
max
=
Integer
.
MIN_VALUE
;
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
if
(
a
[
i
]
>
max
)
max
=
a
[
i
];
}
return
max
;
}
/**
* Returns the minimum value in the specified array.
*
*
@param
a the array
*
@return
the minimum value in the array {
@code
a[]};
* {
@code
Double.POSITIVE_INFINITY} if no such value
*/
public
static
double
min
(
double
[]
a
)
{
validateNotNull
(
a
);
double
min
=
Double
.
POSITIVE_INFINITY
;
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
if
(
Double
.
isNaN
(
a
[
i
]))
return
Double
.
NaN
;
if
(
a
[
i
]
<
min
)
min
=
a
[
i
];
}
return
min
;
}
/**
* Returns the minimum value in the specified subarray.
*
*
@param
a the array
*
@param
lo the left endpoint of the subarray (inclusive)
*
@param
hi the right endpoint of the subarray (exclusive)
*
@return
the maximum value in the subarray {
@code
a[lo..hi)};
* {
@code
Double.POSITIVE_INFINITY} if no such value
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*
@throws
IllegalArgumentException unless {
@code
(0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
public
static
double
min
(
double
[]
a
,
int
lo
,
int
hi
)
{
validateNotNull
(
a
);
validateSubarrayIndices
(
lo
,
hi
,
a
.
length
);
double
min
=
Double
.
POSITIVE_INFINITY
;
for
(
int
i
=
lo
;
i
<
hi
;
i
++
)
{
if
(
Double
.
isNaN
(
a
[
i
]))
return
Double
.
NaN
;
if
(
a
[
i
]
<
min
)
min
=
a
[
i
];
}
return
min
;
}
/**
* Returns the minimum value in the specified array.
*
*
@param
a the array
*
@return
the minimum value in the array {
@code
a[]};
* {
@code
Integer.MAX_VALUE} if no such value
*/
public
static
int
min
(
int
[]
a
)
{
validateNotNull
(
a
);
int
min
=
Integer
.
MAX_VALUE
;
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
if
(
a
[
i
]
<
min
)
min
=
a
[
i
];
}
return
min
;
}
/**
* Returns the average value in the specified array.
*
*
@param
a the array
*
@return
the average value in the array {
@code
a[]};
* {
@code
Double.NaN} if no such value
*/
public
static
double
mean
(
double
[]
a
)
{
validateNotNull
(
a
);
if
(
a
.
length
==
0
)
return
Double
.
NaN
;
double
sum
=
sum
(
a
);
return
sum
/
a
.
length
;
}
/**
* Returns the average value in the specified subarray.
*
*
@param
a the array
*
@param
lo the left endpoint of the subarray (inclusive)
*
@param
hi the right endpoint of the subarray (exclusive)
*
@return
the average value in the subarray {
@code
a[lo..hi)};
* {
@code
Double.NaN} if no such value
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*
@throws
IllegalArgumentException unless {
@code
(0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
public
static
double
mean
(
double
[]
a
,
int
lo
,
int
hi
)
{
validateNotNull
(
a
);
validateSubarrayIndices
(
lo
,
hi
,
a
.
length
);
int
length
=
hi
-
lo
;
if
(
length
==
0
)
return
Double
.
NaN
;
double
sum
=
sum
(
a
,
lo
,
hi
);
return
sum
/
length
;
}
/**
* Returns the average value in the specified array.
*
*
@param
a the array
*
@return
the average value in the array {
@code
a[]};
* {
@code
Double.NaN} if no such value
*/
public
static
double
mean
(
int
[]
a
)
{
validateNotNull
(
a
);
if
(
a
.
length
==
0
)
return
Double
.
NaN
;
int
sum
=
sum
(
a
);
return
1.0
*
sum
/
a
.
length
;
}
/**
* Returns the sample variance in the specified array.
*
*
@param
a the array
*
@return
the sample variance in the array {
@code
a[]};
* {
@code
Double.NaN} if no such value
*/
public
static
double
var
(
double
[]
a
)
{
validateNotNull
(
a
);
if
(
a
.
length
==
0
)
return
Double
.
NaN
;
double
avg
=
mean
(
a
);
double
sum
=
0.0
;
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
sum
+=
(
a
[
i
]
-
avg
)
*
(
a
[
i
]
-
avg
);
}
return
sum
/
(
a
.
length
-
1
);
}
/**
* Returns the sample variance in the specified subarray.
*
*
@param
a the array
*
@param
lo the left endpoint of the subarray (inclusive)
*
@param
hi the right endpoint of the subarray (exclusive)
*
@return
the sample variance in the subarray {
@code
a[lo..hi)};
* {
@code
Double.NaN} if no such value
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*
@throws
IllegalArgumentException unless {
@code
(0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
public
static
double
var
(
double
[]
a
,
int
lo
,
int
hi
)
{
validateNotNull
(
a
);
validateSubarrayIndices
(
lo
,
hi
,
a
.
length
);
int
length
=
hi
-
lo
;
if
(
length
==
0
)
return
Double
.
NaN
;
double
avg
=
mean
(
a
,
lo
,
hi
);
double
sum
=
0.0
;
for
(
int
i
=
lo
;
i
<
hi
;
i
++
)
{
sum
+=
(
a
[
i
]
-
avg
)
*
(
a
[
i
]
-
avg
);
}
return
sum
/
(
length
-
1
);
}
/**
* Returns the sample variance in the specified array.
*
*
@param
a the array
*
@return
the sample variance in the array {
@code
a[]};
* {
@code
Double.NaN} if no such value
*/
public
static
double
var
(
int
[]
a
)
{
validateNotNull
(
a
);
if
(
a
.
length
==
0
)
return
Double
.
NaN
;
double
avg
=
mean
(
a
);
double
sum
=
0.0
;
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
sum
+=
(
a
[
i
]
-
avg
)
*
(
a
[
i
]
-
avg
);
}
return
sum
/
(
a
.
length
-
1
);
}
/**
* Returns the population variance in the specified array.
*
*
@param
a the array
*
@return
the population variance in the array {
@code
a[]};
* {
@code
Double.NaN} if no such value
*/
public
static
double
varp
(
double
[]
a
)
{
validateNotNull
(
a
);
if
(
a
.
length
==
0
)
return
Double
.
NaN
;
double
avg
=
mean
(
a
);
double
sum
=
0.0
;
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
sum
+=
(
a
[
i
]
-
avg
)
*
(
a
[
i
]
-
avg
);
}
return
sum
/
a
.
length
;
}
/**
* Returns the population variance in the specified subarray.
*
*
@param
a the array
*
@param
lo the left endpoint of the subarray (inclusive)
*
@param
hi the right endpoint of the subarray (exclusive)
*
@return
the population variance in the subarray {
@code
a[lo..hi)};
* {
@code
Double.NaN} if no such value
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*
@throws
IllegalArgumentException unless {
@code
(0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
public
static
double
varp
(
double
[]
a
,
int
lo
,
int
hi
)
{
validateNotNull
(
a
);
validateSubarrayIndices
(
lo
,
hi
,
a
.
length
);
int
length
=
hi
-
lo
;
if
(
length
==
0
)
return
Double
.
NaN
;
double
avg
=
mean
(
a
,
lo
,
hi
);
double
sum
=
0.0
;
for
(
int
i
=
lo
;
i
<
hi
;
i
++
)
{
sum
+=
(
a
[
i
]
-
avg
)
*
(
a
[
i
]
-
avg
);
}
return
sum
/
length
;
}
/**
* Returns the sample standard deviation in the specified array.
*
*
@param
a the array
*
@return
the sample standard deviation in the array {
@code
a[]};
* {
@code
Double.NaN} if no such value
*/
public
static
double
stddev
(
double
[]
a
)
{
validateNotNull
(
a
);
return
Math
.
sqrt
(
var
(
a
));
}
/**
* Returns the sample standard deviation in the specified array.
*
*
@param
a the array
*
@return
the sample standard deviation in the array {
@code
a[]};
* {
@code
Double.NaN} if no such value
*/
public
static
double
stddev
(
int
[]
a
)
{
validateNotNull
(
a
);
return
Math
.
sqrt
(
var
(
a
));
}
/**
* Returns the sample standard deviation in the specified subarray.
*
*
@param
a the array
*
@param
lo the left endpoint of the subarray (inclusive)
*
@param
hi the right endpoint of the subarray (exclusive)
*
@return
the sample standard deviation in the subarray {
@code
a[lo..hi)};
* {
@code
Double.NaN} if no such value
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*
@throws
IllegalArgumentException unless {
@code
(0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
public
static
double
stddev
(
double
[]
a
,
int
lo
,
int
hi
)
{
validateNotNull
(
a
);
validateSubarrayIndices
(
lo
,
hi
,
a
.
length
);
return
Math
.
sqrt
(
var
(
a
,
lo
,
hi
));
}
/**
* Returns the population standard deviation in the specified array.
*
*
@param
a the array
*
@return
the population standard deviation in the array;
* {
@code
Double.NaN} if no such value
*/
public
static
double
stddevp
(
double
[]
a
)
{
validateNotNull
(
a
);
return
Math
.
sqrt
(
varp
(
a
));
}
/**
* Returns the population standard deviation in the specified subarray.
*
*
@param
a the array
*
@param
lo the left endpoint of the subarray (inclusive)
*
@param
hi the right endpoint of the subarray (exclusive)
*
@return
the population standard deviation in the subarray {
@code
a[lo..hi)};
* {
@code
Double.NaN} if no such value
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*
@throws
IllegalArgumentException unless {
@code
(0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
public
static
double
stddevp
(
double
[]
a
,
int
lo
,
int
hi
)
{
validateNotNull
(
a
);
validateSubarrayIndices
(
lo
,
hi
,
a
.
length
);
return
Math
.
sqrt
(
varp
(
a
,
lo
,
hi
));
}
/**
* Returns the sum of all values in the specified array.
*
*
@param
a the array
*
@return
the sum of all values in the array {
@code
a[]};
* {
@code
0.0} if no such value
*/
private
static
double
sum
(
double
[]
a
)
{
validateNotNull
(
a
);
double
sum
=
0.0
;
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
sum
+=
a
[
i
];
}
return
sum
;
}
/**
* Returns the sum of all values in the specified subarray.
*
*
@param
a the array
*
@param
lo the left endpoint of the subarray (inclusive)
*
@param
hi the right endpoint of the subarray (exclusive)
*
@return
the sum of all values in the subarray {
@code
a[lo..hi)};
* {
@code
0.0} if no such value
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*
@throws
IllegalArgumentException unless {
@code
(0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
private
static
double
sum
(
double
[]
a
,
int
lo
,
int
hi
)
{
validateNotNull
(
a
);
validateSubarrayIndices
(
lo
,
hi
,
a
.
length
);
double
sum
=
0.0
;
for
(
int
i
=
lo
;
i
<
hi
;
i
++
)
{
sum
+=
a
[
i
];
}
return
sum
;
}
/**
* Returns the sum of all values in the specified array.
*
*
@param
a the array
*
@return
the sum of all values in the array {
@code
a[]};
* {
@code
0.0} if no such value
*/
private
static
int
sum
(
int
[]
a
)
{
validateNotNull
(
a
);
int
sum
=
0
;
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
sum
+=
a
[
i
];
}
return
sum
;
}
/**
* Plots the points (0, a0), (1, a1), …,
* (n-1, an-1) to standard draw.
*
*
@param
a the array of values
*/
public
static
void
plotPoints
(
double
[]
a
)
{
validateNotNull
(
a
);
int
n
=
a
.
length
;
StdDraw
.
setXscale
(
–
1
,
n
);
StdDraw
.
setPenRadius
(
1.0
/
(
3.0
*
n
));
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
StdDraw
.
point
(
i
,
a
[
i
]);
}
}
/**
* Plots the line segments connecting
* (i, ai) to
* (i+1, ai+1) for
* each i to standard draw.
*
*
@param
a the array of values
*/
public
static
void
plotLines
(
double
[]
a
)
{
validateNotNull
(
a
);
int
n
=
a
.
length
;
StdDraw
.
setXscale
(
–
1
,
n
);
StdDraw
.
setPenRadius
();
for
(
int
i
=
1
;
i
<
n
;
i
++
)
{
StdDraw
.
line
(
i
-
1
,
a
[
i
-
1
],
i
,
a
[
i
]);
}
}
/**
* Plots bars from (0, ai) to
* (ai) for each i
* to standard draw.
*
*
@param
a the array of values
*/
public
static
void
plotBars
(
double
[]
a
)
{
validateNotNull
(
a
);
int
n
=
a
.
length
;
StdDraw
.
setXscale
(
–
1
,
n
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
StdDraw
.
filledRectangle
(
i
,
a
[
i
]
/
2
,
0.25
,
a
[
i
]
/
2
);
}
}
// throw an IllegalArgumentException if x is null
// (x is either of type double[] or int[])
private
static
void
validateNotNull
(
Object
x
)
{
if
(
x
==
null
)
throw
new
IllegalArgumentException
(
"argument is null"
);
}
// throw an exception unless 0 <= lo <= hi <= length
private
static
void
validateSubarrayIndices
(
int
lo
,
int
hi
,
int
length
)
{
if
(
lo
<
0
||
hi
>
length
||
lo
>
hi
)
throw
new
IllegalArgumentException
(
“subarray indices out of bounds: [”
+
lo
+
“, ”
+
hi
+
“)”
);
}
/**
* Unit tests {
@code
StdStats}.
* Convert command-line arguments to array of doubles and call various methods.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
double
[]
a
=
StdArrayIO
.
readDouble1D
();
StdOut
.
printf
(
” min %10.3f\n”
,
min
(
a
));
StdOut
.
printf
(
” mean %10.3f\n”
,
mean
(
a
));
StdOut
.
printf
(
” max %10.3f\n”
,
max
(
a
));
StdOut
.
printf
(
” stddev %10.3f\n”
,
stddev
(
a
));
StdOut
.
printf
(
” var %10.3f\n”
,
var
(
a
));
StdOut
.
printf
(
” stddevp %10.3f\n”
,
stddevp
(
a
));
StdOut
.
printf
(
” varp %10.3f\n”
,
varp
(
a
));
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/ST.java
edu/princeton/cs/algs4/ST.java
/******************************************************************************
* Compilation: javac ST.java
* Execution: java ST < input.txt * Dependencies: StdIn.java StdOut.java * Data files: https://algs4.cs.princeton.edu/35applications/tinyST.txt * * Sorted symbol table implementation using a java.util.TreeMap. * Does not allow duplicates. * ******************************************************************************/ package edu . princeton . cs . algs4 ; import java . util . Iterator ; import java . util . NoSuchElementException ; import java . util . TreeMap ; /** * The { @code ST} class represents an ordered symbol table of generic * key-value pairs. * It supports the usual put, get, contains,
* delete, size, and is-empty methods.
* It also provides ordered methods for finding the minimum,
* maximum, floor, and ceiling.
* It also provides a keys method for iterating over all of the keys.
* A symbol table implements the associative array abstraction:
* when associating a value with a key that is already in the symbol table,
* the convention is to replace the old value with the new value.
* Unlike {
@link
java.util.Map}, this class uses the convention that
* values cannot be {
@code
null}—setting the
* value associated with a key to {
@code
null} is equivalent to deleting the key
* from the symbol table.
*
* It requires that
* the key type implements the {
@code
Comparable} interface and calls the
* {
@code
compareTo()} and method to compare two keys. It does not call either
* {
@code
equals()} or {
@code
hashCode()}.
*
* This implementation uses a red-black BST.
* The put, get, contains, remove,
* minimum, maximum, ceiling, and floor
* operations each take Θ(log n) time in the worst case,
* where n is the number of key-value pairs in the symbol table.
* The size and is-empty operations take Θ(1) time.
* Construction takes Θ(1) time.
*
* For additional documentation, see
* Section 3.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*
*
@param
*
@param
*/
public
class
ST
<
Key
extends
Comparable
<
Key
>
,
Value
>
implements
Iterable
<
Key
>
{
private
TreeMap
<
Key
,
Value
>
st
;
/**
* Initializes an empty symbol table.
*/
public
ST
()
{
st
=
new
TreeMap
<
Key
,
Value
>
();
}
/**
* Returns the value associated with the given key in this symbol table.
*
*
@param
key the key
*
@return
the value associated with the given key if the key is in this symbol table;
* {
@code
null} if the key is not in this symbol table
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
Value
get
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“calls get() with null key”
);
return
st
.
get
(
key
);
}
/**
* Inserts the specified key-value pair into the symbol table, overwriting the old
* value with the new value if the symbol table already contains the specified key.
* Deletes the specified key (and its associated value) from this symbol table
* if the specified value is {
@code
null}.
*
*
@param
key the key
*
@param
val the value
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
put
(
Key
key
,
Value
val
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“calls put() with null key”
);
if
(
val
==
null
)
st
.
remove
(
key
);
else
st
.
put
(
key
,
val
);
}
/**
* Removes the specified key and its associated value from this symbol table
* (if the key is in this symbol table).
* This is equivalent to {
@code
remove()}, but we plan to deprecate {
@code
delete()}.
*
*
@param
key the key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
delete
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“calls delete() with null key”
);
st
.
remove
(
key
);
}
/**
* Removes the specified key and its associated value from this symbol table
* (if the key is in this symbol table).
* This is equivalent to {
@code
delete()}, but we plan to deprecate {
@code
delete()}.
*
*
@param
key the key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
remove
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“calls remove() with null key”
);
st
.
remove
(
key
);
}
/**
* Returns true if this symbol table contain the given key.
*
*
@param
key the key
*
@return
{
@code
true} if this symbol table contains {
@code
key} and
* {
@code
false} otherwise
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
boolean
contains
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“calls contains() with null key”
);
return
st
.
containsKey
(
key
);
}
/**
* Returns the number of key-value pairs in this symbol table.
*
*
@return
the number of key-value pairs in this symbol table
*/
public
int
size
()
{
return
st
.
size
();
}
/**
* Returns true if this symbol table is empty.
*
*
@return
{
@code
true} if this symbol table is empty and {
@code
false} otherwise
*/
public
boolean
isEmpty
()
{
return
size
()
==
0
;
}
/**
* Returns all keys in this symbol table.
*
* To iterate over all of the keys in the symbol table named {
@code
st},
* use the foreach notation: {
@code
for (Key key : st.keys())}.
*
*
@return
all keys in this symbol table
*/
public
Iterable
<
Key
>
keys
()
{
return
st
.
keySet
();
}
/**
* Returns all of the keys in this symbol table.
* To iterate over all of the keys in a symbol table named {
@code
st}, use the
* foreach notation: {
@code
for (Key key : st)}.
*
* This method is provided for backward compatibility with the version from
* Introduction to Programming in Java: An Interdisciplinary Approach.
*
*
@return
an iterator to all of the keys in this symbol table
*
@deprecated
Replaced by {
@link
#keys()}.
*/
@
Deprecated
public
Iterator
<
Key
>
iterator
()
{
return
st
.
keySet
().
iterator
();
}
/**
* Returns the smallest key in this symbol table.
*
*
@return
the smallest key in this symbol table
*
@throws
NoSuchElementException if this symbol table is empty
*/
public
Key
min
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“calls min() with empty symbol table”
);
return
st
.
firstKey
();
}
/**
* Returns the largest key in this symbol table.
*
*
@return
the largest key in this symbol table
*
@throws
NoSuchElementException if this symbol table is empty
*/
public
Key
max
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“calls max() with empty symbol table”
);
return
st
.
lastKey
();
}
/**
* Returns the smallest key in this symbol table greater than or equal to {
@code
key}.
*
*
@param
key the key
*
@return
the smallest key in this symbol table greater than or equal to {
@code
key}
*
@throws
NoSuchElementException if there is no such key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
Key
ceiling
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to ceiling() is null”
);
Key
k
=
st
.
ceilingKey
(
key
);
if
(
k
==
null
)
throw
new
NoSuchElementException
(
“argument to ceiling() is too large”
);
return
k
;
}
/**
* Returns the largest key in this symbol table less than or equal to {
@code
key}.
*
*
@param
key the key
*
@return
the largest key in this symbol table less than or equal to {
@code
key}
*
@throws
NoSuchElementException if there is no such key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
Key
floor
(
Key
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to floor() is null”
);
Key
k
=
st
.
floorKey
(
key
);
if
(
k
==
null
)
throw
new
NoSuchElementException
(
“argument to floor() is too small”
);
return
k
;
}
/**
* Unit tests the {
@code
ST} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
ST
<
String
,
Integer
>
st
=
new
ST
<
String
,
Integer
>
();
for
(
int
i
=
0
;
!
StdIn
.
isEmpty
();
i
++
)
{
String
key
=
StdIn
.
readString
();
st
.
put
(
key
,
i
);
}
for
(
String
s
:
st
.
keys
())
StdOut
.
println
(
s
+
” ”
+
st
.
get
(
s
));
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/StopwatchCPU.java
edu/princeton/cs/algs4/StopwatchCPU.java
/******************************************************************************
* Compilation: javac StopwatchCPU.java
* Execution: java StopwtachCPU n
* Dependencies: none
*
* A version of Stopwatch.java that measures CPU time on a single
* core or processor (instead of wall clock time).
*
* % java8 StopwatchCPU 100000000
* 6.666667e+11 (1.05 seconds)
* 6.666667e+11 (7.50 seconds)
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
lang
.
management
.
ThreadMXBean
;
import
java
.
lang
.
management
.
ManagementFactory
;
/**
* The {
@code
StopwatchCPU} data type is for measuring
* the CPU time used during a programming task.
*
* See {
@link
Stopwatch} for a version that measures wall-clock time
* (the real time that elapses).
*
*
@author
Josh Hug
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
StopwatchCPU
{
private
static
final
double
NANOSECONDS_PER_SECOND
=
1000000000
;
private
final
ThreadMXBean
threadTimer
;
private
final
long
start
;
/**
* Initializes a new stopwatch.
*/
public
StopwatchCPU
()
{
threadTimer
=
ManagementFactory
.
getThreadMXBean
();
start
=
threadTimer
.
getCurrentThreadCpuTime
();
}
/**
* Returns the elapsed CPU time (in seconds) since the stopwatch was created.
*
*
@return
elapsed CPU time (in seconds) since the stopwatch was created
*/
public
double
elapsedTime
()
{
long
now
=
threadTimer
.
getCurrentThreadCpuTime
();
return
(
now
–
start
)
/
NANOSECONDS_PER_SECOND
;
}
/**
* Unit tests the {
@code
StopwatchCPU} data type.
* Takes a command-line argument {
@code
n} and computes the
* sum of the square roots of the first {
@code
n} positive integers,
* first using {
@code
Math.sqrt()}, then using {
@code
Math.pow()}.
* It prints to standard output the sum and the amount of time to
* compute the sum. Note that the discrete sum can be approximated by
* an integral – the sum should be approximately 2/3 * (n^(3/2) – 1).
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
n
=
Integer
.
parseInt
(
args
[
0
]);
// sum of square roots of integers from 1 to n using Math.sqrt(x).
StopwatchCPU
timer1
=
new
StopwatchCPU
();
double
sum1
=
0.0
;
for
(
int
i
=
1
;
i
<=
n
;
i
++
)
{
sum1
+=
Math
.
sqrt
(
i
);
}
double
time1
=
timer1
.
elapsedTime
();
StdOut
.
printf
(
"%e (%.2f seconds)\n"
,
sum1
,
time1
);
// sum of square roots of integers from 1 to n using Math.pow(x, 0.5).
StopwatchCPU
timer2
=
new
StopwatchCPU
();
double
sum2
=
0.0
;
for
(
int
i
=
1
;
i
<=
n
;
i
++
)
{
sum2
+=
Math
.
pow
(
i
,
0.5
);
}
double
time2
=
timer2
.
elapsedTime
();
StdOut
.
printf
(
"%e (%.2f seconds)\n"
,
sum2
,
time2
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Stopwatch.java
edu/princeton/cs/algs4/Stopwatch.java
/******************************************************************************
* Compilation: javac Stopwatch.java
* Execution: java Stopwatch n
* Dependencies: none
*
* A utility class to measure the running time (wall clock) of a program.
*
* % java8 Stopwatch 100000000
* 6.666667e+11 0.5820 seconds
* 6.666667e+11 8.4530 seconds
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Stopwatch} data type is for measuring
* the time that elapses between the start and end of a
* programming task (wall-clock time).
*
* See {
@link
StopwatchCPU} for a version that measures CPU time.
* For additional documentation,
* see Section 1.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Stopwatch
{
private
final
long
start
;
/**
* Initializes a new stopwatch.
*/
public
Stopwatch
()
{
start
=
System
.
currentTimeMillis
();
}
/**
* Returns the elapsed CPU time (in seconds) since the stopwatch was created.
*
*
@return
elapsed CPU time (in seconds) since the stopwatch was created
*/
public
double
elapsedTime
()
{
long
now
=
System
.
currentTimeMillis
();
return
(
now
–
start
)
/
1000.0
;
}
/**
* Unit tests the {
@code
Stopwatch} data type.
* Takes a command-line argument {
@code
n} and computes the
* sum of the square roots of the first {
@code
n} positive integers,
* first using {
@code
Math.sqrt()}, then using {
@code
Math.pow()}.
* It prints to standard output the sum and the amount of time to
* compute the sum. Note that the discrete sum can be approximated by
* an integral – the sum should be approximately 2/3 * (n^(3/2) – 1).
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
n
=
Integer
.
parseInt
(
args
[
0
]);
// sum of square roots of integers from 1 to n using Math.sqrt(x).
Stopwatch
timer1
=
new
Stopwatch
();
double
sum1
=
0.0
;
for
(
int
i
=
1
;
i
<=
n
;
i
++
)
{
sum1
+=
Math
.
sqrt
(
i
);
}
double
time1
=
timer1
.
elapsedTime
();
StdOut
.
printf
(
"%e (%.2f seconds)\n"
,
sum1
,
time1
);
// sum of square roots of integers from 1 to n using Math.pow(x, 0.5).
Stopwatch
timer2
=
new
Stopwatch
();
double
sum2
=
0.0
;
for
(
int
i
=
1
;
i
<=
n
;
i
++
)
{
sum2
+=
Math
.
pow
(
i
,
0.5
);
}
double
time2
=
timer2
.
elapsedTime
();
StdOut
.
printf
(
"%e (%.2f seconds)\n"
,
sum2
,
time2
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/SuffixArray.java
edu/princeton/cs/algs4/SuffixArray.java
/******************************************************************************
* Compilation: javac SuffixArray.java
* Execution: java SuffixArray < input.txt
* Dependencies: StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/63suffix/abra.txt
*
* A data type that computes the suffix array of a string.
*
* % java SuffixArray < abra.txt
* i ind lcp rnk select
* ---------------------------
* 0 11 - 0 "!"
* 1 10 0 1 "A!"
* 2 7 1 2 "ABRA!"
* 3 0 4 3 "ABRACADABRA!"
* 4 3 1 4 "ACADABRA!"
* 5 5 1 5 "ADABRA!"
* 6 8 0 6 "BRA!"
* 7 1 3 7 "BRACADABRA!"
* 8 4 0 8 "CADABRA!"
* 9 6 0 9 "DABRA!"
* 10 9 0 10 "RA!"
* 11 2 2 11 "RACADABRA!"
*
* See SuffixArrayX.java for an optimized version that uses 3-way
* radix quicksort and does not use the nested class Suffix.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Arrays
;
/**
* The {
@code
SuffixArray} class represents a suffix array of a string of
* length n.
* It supports the selecting the ith smallest suffix,
* getting the index of the ith smallest suffix,
* computing the length of the longest common prefix between the
* ith smallest suffix and the i-1st smallest suffix,
* and determining the rank of a query string (which is the number
* of suffixes strictly less than the query string).
*
* This implementation uses a nested class {
@code
Suffix} to represent
* a suffix of a string (using constant time and space) and
* {
@code
Arrays.sort()} to sort the array of suffixes.
* The index and length operations takes constant time
* in the worst case. The lcp operation takes time proportional to the
* length of the longest common prefix.
* The select operation takes time proportional
* to the length of the suffix and should be used primarily for debugging.
*
* For alternate implementations of the same API, see
* {
@link
SuffixArrayX}, which is faster in practice (uses 3-way radix quicksort)
* and uses less memory (does not create {
@code
Suffix} objects)
* and SuffixArrayJava6.java,
* which relies on the constant-time substring extraction method that existed
* in Java 6.
*
* For additional documentation, see Section 6.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*/
public
class
SuffixArray
{
private
Suffix
[]
suffixes
;
/**
* Initializes a suffix array for the given {
@code
text} string.
*
@param
text the input string
*/
public
SuffixArray
(
String
text
)
{
int
n
=
text
.
length
();
this
.
suffixes
=
new
Suffix
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
suffixes
[
i
]
=
new
Suffix
(
text
,
i
);
Arrays
.
sort
(
suffixes
);
}
private
static
class
Suffix
implements
Comparable
<
Suffix
>
{
private
final
String
text
;
private
final
int
index
;
private
Suffix
(
String
text
,
int
index
)
{
this
.
text
=
text
;
this
.
index
=
index
;
}
private
int
length
()
{
return
text
.
length
()
–
index
;
}
private
char
charAt
(
int
i
)
{
return
text
.
charAt
(
index
+
i
);
}
public
int
compareTo
(
Suffix
that
)
{
if
(
this
==
that
)
return
0
;
// optimization
int
n
=
Math
.
min
(
this
.
length
(),
that
.
length
());
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
if
(
this
.
charAt
(
i
)
<
that
.
charAt
(
i
))
return
-
1
;
if
(
this
.
charAt
(
i
)
>
that
.
charAt
(
i
))
return
+
1
;
}
return
this
.
length
()
–
that
.
length
();
}
public
String
toString
()
{
return
text
.
substring
(
index
);
}
}
/**
* Returns the length of the input string.
*
@return
the length of the input string
*/
public
int
length
()
{
return
suffixes
.
length
;
}
/**
* Returns the index into the original string of the ith smallest suffix.
* That is, {
@code
text.substring(sa.index(i))} is the ith smallest suffix.
*
@param
i an integer between 0 and n-1
*
@return
the index into the original string of the ith smallest suffix
*
@throws
java.lang.IllegalArgumentException unless {
@code
0 <= i < n}
*/
public
int
index
(
int
i
)
{
if
(
i
<
0
||
i
>=
suffixes
.
length
)
throw
new
IllegalArgumentException
();
return
suffixes
[
i
].
index
;
}
/**
* Returns the length of the longest common prefix of the ith
* smallest suffix and the i-1st smallest suffix.
*
@param
i an integer between 1 and n-1
*
@return
the length of the longest common prefix of the ith
* smallest suffix and the i-1st smallest suffix.
*
@throws
java.lang.IllegalArgumentException unless {
@code
1 <= i < n}
*/
public
int
lcp
(
int
i
)
{
if
(
i
<
1
||
i
>=
suffixes
.
length
)
throw
new
IllegalArgumentException
();
return
lcpSuffix
(
suffixes
[
i
],
suffixes
[
i
–
1
]);
}
// longest common prefix of s and t
private
static
int
lcpSuffix
(
Suffix
s
,
Suffix
t
)
{
int
n
=
Math
.
min
(
s
.
length
(),
t
.
length
());
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
if
(
s
.
charAt
(
i
)
!=
t
.
charAt
(
i
))
return
i
;
}
return
n
;
}
/**
* Returns the ith smallest suffix as a string.
*
@param
i the index
*
@return
the i smallest suffix as a string
*
@throws
java.lang.IllegalArgumentException unless {
@code
0 <= i < n}
*/
public
String
select
(
int
i
)
{
if
(
i
<
0
||
i
>=
suffixes
.
length
)
throw
new
IllegalArgumentException
();
return
suffixes
[
i
].
toString
();
}
/**
* Returns the number of suffixes strictly less than the {
@code
query} string.
* We note that {
@code
rank(select(i))} equals {
@code
i} for each {
@code
i}
* between 0 and n-1.
*
@param
query the query string
*
@return
the number of suffixes strictly less than {
@code
query}
*/
public
int
rank
(
String
query
)
{
int
lo
=
0
,
hi
=
suffixes
.
length
–
1
;
while
(
lo
<=
hi
)
{
int
mid
=
lo
+
(
hi
-
lo
)
/
2
;
int
cmp
=
compare
(
query
,
suffixes
[
mid
]);
if
(
cmp
<
0
)
hi
=
mid
-
1
;
else
if
(
cmp
>
0
)
lo
=
mid
+
1
;
else
return
mid
;
}
return
lo
;
}
// compare query string to suffix
private
static
int
compare
(
String
query
,
Suffix
suffix
)
{
int
n
=
Math
.
min
(
query
.
length
(),
suffix
.
length
());
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
if
(
query
.
charAt
(
i
)
<
suffix
.
charAt
(
i
))
return
-
1
;
if
(
query
.
charAt
(
i
)
>
suffix
.
charAt
(
i
))
return
+
1
;
}
return
query
.
length
()
–
suffix
.
length
();
}
/**
* Unit tests the {
@code
SuffixArray} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
s
=
StdIn
.
readAll
().
replaceAll
(
“\\s+”
,
” ”
).
trim
();
SuffixArray
suffix
=
new
SuffixArray
(
s
);
// StdOut.println(“rank(” + args[0] + “) = ” + suffix.rank(args[0]));
StdOut
.
println
(
” i ind lcp rnk select”
);
StdOut
.
println
(
“—————————”
);
for
(
int
i
=
0
;
i
<
s
.
length
();
i
++
)
{
int
index
=
suffix
.
index
(
i
);
String
ith
=
"\""
+
s
.
substring
(
index
,
Math
.
min
(
index
+
50
,
s
.
length
()))
+
"\""
;
assert
s
.
substring
(
index
).
equals
(
suffix
.
select
(
i
));
int
rank
=
suffix
.
rank
(
s
.
substring
(
index
));
if
(
i
==
0
)
{
StdOut
.
printf
(
"%3d %3d %3s %3d %s\n"
,
i
,
index
,
"-"
,
rank
,
ith
);
}
else
{
int
lcp
=
suffix
.
lcp
(
i
);
StdOut
.
printf
(
"%3d %3d %3d %3d %s\n"
,
i
,
index
,
lcp
,
rank
,
ith
);
}
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/SuffixArrayX.java
edu/princeton/cs/algs4/SuffixArrayX.java
/******************************************************************************
* Compilation: javac SuffixArrayX.java
* Execution: java SuffixArrayX < input.txt
* Dependencies: StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/63suffix/abra.txt
*
* A data type that computes the suffix array of a string using 3-way
* radix quicksort.
*
* % java SuffixArrayX < abra.txt
* i ind lcp rnk select
* ---------------------------
* 0 11 - 0 !
* 1 10 0 1 A!
* 2 7 1 2 ABRA!
* 3 0 4 3 ABRACADABRA!
* 4 3 1 4 ACADABRA!
* 5 5 1 5 ADABRA!
* 6 8 0 6 BRA!
* 7 1 3 7 BRACADABRA!
* 8 4 0 8 CADABRA!
* 9 6 0 9 DABRA!
* 10 9 0 10 RA!
* 11 2 2 11 RACADABRA!
*
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
SuffixArrayX} class represents a suffix array of a string of
* length n.
* It supports the selecting the ith smallest suffix,
* getting the index of the ith smallest suffix,
* computing the length of the longest common prefix between the
* ith smallest suffix and the i-1st smallest suffix,
* and determining the rank of a query string (which is the number
* of suffixes strictly less than the query string).
*
* This implementation uses 3-way radix quicksort to sort the array of suffixes.
* For a simpler (but less efficient) implementations of the same API, see
* {
@link
SuffixArray}.
* The index and length operations takes constant time
* in the worst case. The lcp operation takes time proportional to the
* length of the longest common prefix.
* The select operation takes time proportional
* to the length of the suffix and should be used primarily for debugging.
*
* This implementation uses ‘\0’ as a sentinel and assumes that the charater
* ‘\0’ does not appear in the text.
*
* In practice, this algorithm runs very fast. However, in the worst-case
* it can be very poor (e.g., a string consisting of N copies of the same
* character. We do not shuffle the array of suffixes before sorting because
* shuffling is relatively expensive and a pathologial input for which
* the suffixes start out in a bad order (e.g., sorted) is likely to be
* a bad input for this algorithm with or without the shuffle.
*
* For additional documentation, see Section 6.3 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*/
public
class
SuffixArrayX
{
private
static
final
int
CUTOFF
=
5
;
// cutoff to insertion sort (any value between 0 and 12)
private
final
char
[]
text
;
private
final
int
[]
index
;
// index[i] = j means text.substring(j) is ith largest suffix
private
final
int
n
;
// number of characters in text
/**
* Initializes a suffix array for the given {
@code
text} string.
*
@param
text the input string
*/
public
SuffixArrayX
(
String
text
)
{
n
=
text
.
length
();
text
=
text
+
‘\0’
;
this
.
text
=
text
.
toCharArray
();
this
.
index
=
new
int
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
index
[
i
]
=
i
;
sort
(
0
,
n
-
1
,
0
);
}
// 3-way string quicksort lo..hi starting at dth character
private
void
sort
(
int
lo
,
int
hi
,
int
d
)
{
// cutoff to insertion sort for small subarrays
if
(
hi
<=
lo
+
CUTOFF
)
{
insertion
(
lo
,
hi
,
d
);
return
;
}
int
lt
=
lo
,
gt
=
hi
;
char
v
=
text
[
index
[
lo
]
+
d
];
int
i
=
lo
+
1
;
while
(
i
<=
gt
)
{
char
t
=
text
[
index
[
i
]
+
d
];
if
(
t
<
v
)
exch
(
lt
++
,
i
++
);
else
if
(
t
>
v
)
exch
(
i
,
gt
—
);
else
i
++
;
}
// a[lo..lt-1] < v = a[lt..gt] < a[gt+1..hi].
sort
(
lo
,
lt
-
1
,
d
);
if
(
v
>
0
)
sort
(
lt
,
gt
,
d
+
1
);
sort
(
gt
+
1
,
hi
,
d
);
}
// sort from a[lo] to a[hi], starting at the dth character
private
void
insertion
(
int
lo
,
int
hi
,
int
d
)
{
for
(
int
i
=
lo
;
i
<=
hi
;
i
++
)
for
(
int
j
=
i
;
j
>
lo
&&
less
(
index
[
j
],
index
[
j
–
1
],
d
);
j
—
)
exch
(
j
,
j
–
1
);
}
// is text[i+d..n) < text[j+d..n) ?
private
boolean
less
(
int
i
,
int
j
,
int
d
)
{
if
(
i
==
j
)
return
false
;
i
=
i
+
d
;
j
=
j
+
d
;
while
(
i
<
n
&&
j
<
n
)
{
if
(
text
[
i
]
<
text
[
j
])
return
true
;
if
(
text
[
i
]
>
text
[
j
])
return
false
;
i
++
;
j
++
;
}
return
i
>
j
;
}
// exchange index[i] and index[j]
private
void
exch
(
int
i
,
int
j
)
{
int
swap
=
index
[
i
];
index
[
i
]
=
index
[
j
];
index
[
j
]
=
swap
;
}
/**
* Returns the length of the input string.
*
@return
the length of the input string
*/
public
int
length
()
{
return
n
;
}
/**
* Returns the index into the original string of the ith smallest suffix.
* That is, {
@code
text.substring(sa.index(i))} is the i smallest suffix.
*
@param
i an integer between 0 and n-1
*
@return
the index into the original string of the ith smallest suffix
*
@throws
java.lang.IllegalArgumentException unless {
@code
0 <=i < n}
*/
public
int
index
(
int
i
)
{
if
(
i
<
0
||
i
>=
n
)
throw
new
IllegalArgumentException
();
return
index
[
i
];
}
/**
* Returns the length of the longest common prefix of the ith
* smallest suffix and the i-1st smallest suffix.
*
@param
i an integer between 1 and n-1
*
@return
the length of the longest common prefix of the ith
* smallest suffix and the i-1st smallest suffix.
*
@throws
java.lang.IllegalArgumentException unless {
@code
1 <= i < n}
*/
public
int
lcp
(
int
i
)
{
if
(
i
<
1
||
i
>=
n
)
throw
new
IllegalArgumentException
();
return
lcp
(
index
[
i
],
index
[
i
–
1
]);
}
// longest common prefix of text[i..n) and text[j..n)
private
int
lcp
(
int
i
,
int
j
)
{
int
length
=
0
;
while
(
i
<
n
&&
j
<
n
)
{
if
(
text
[
i
]
!=
text
[
j
])
return
length
;
i
++
;
j
++
;
length
++
;
}
return
length
;
}
/**
* Returns the ith smallest suffix as a string.
*
@param
i the index
*
@return
the i smallest suffix as a string
*
@throws
java.lang.IllegalArgumentException unless {
@code
0 <= i < n}
*/
public
String
select
(
int
i
)
{
if
(
i
<
0
||
i
>=
n
)
throw
new
IllegalArgumentException
();
return
new
String
(
text
,
index
[
i
],
n
–
index
[
i
]);
}
/**
* Returns the number of suffixes strictly less than the {
@code
query} string.
* We note that {
@code
rank(select(i))} equals {
@code
i} for each {
@code
i}
* between 0 and n-1.
*
@param
query the query string
*
@return
the number of suffixes strictly less than {
@code
query}
*/
public
int
rank
(
String
query
)
{
int
lo
=
0
,
hi
=
n
–
1
;
while
(
lo
<=
hi
)
{
int
mid
=
lo
+
(
hi
-
lo
)
/
2
;
int
cmp
=
compare
(
query
,
index
[
mid
]);
if
(
cmp
<
0
)
hi
=
mid
-
1
;
else
if
(
cmp
>
0
)
lo
=
mid
+
1
;
else
return
mid
;
}
return
lo
;
}
// is query < text[i..n) ?
private
int
compare
(
String
query
,
int
i
)
{
int
m
=
query
.
length
();
int
j
=
0
;
while
(
i
<
n
&&
j
<
m
)
{
if
(
query
.
charAt
(
j
)
!=
text
[
i
])
return
query
.
charAt
(
j
)
-
text
[
i
];
i
++
;
j
++
;
}
if
(
i
<
n
)
return
-
1
;
if
(
j
<
m
)
return
+
1
;
return
0
;
}
/**
* Unit tests the {
@code
SuffixArrayx} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
s
=
StdIn
.
readAll
().
replaceAll
(
"\n"
,
" "
).
trim
();
SuffixArrayX
suffix1
=
new
SuffixArrayX
(
s
);
SuffixArray
suffix2
=
new
SuffixArray
(
s
);
boolean
check
=
true
;
for
(
int
i
=
0
;
check
&&
i
<
s
.
length
();
i
++
)
{
if
(
suffix1
.
index
(
i
)
!=
suffix2
.
index
(
i
))
{
StdOut
.
println
(
"suffix1("
+
i
+
") = "
+
suffix1
.
index
(
i
));
StdOut
.
println
(
"suffix2("
+
i
+
") = "
+
suffix2
.
index
(
i
));
String
ith
=
"\""
+
s
.
substring
(
suffix1
.
index
(
i
),
Math
.
min
(
suffix1
.
index
(
i
)
+
50
,
s
.
length
()))
+
"\""
;
String
jth
=
"\""
+
s
.
substring
(
suffix2
.
index
(
i
),
Math
.
min
(
suffix2
.
index
(
i
)
+
50
,
s
.
length
()))
+
"\""
;
StdOut
.
println
(
ith
);
StdOut
.
println
(
jth
);
check
=
false
;
}
}
StdOut
.
println
(
" i ind lcp rnk select"
);
StdOut
.
println
(
"---------------------------"
);
for
(
int
i
=
0
;
i
<
s
.
length
();
i
++
)
{
int
index
=
suffix2
.
index
(
i
);
String
ith
=
"\""
+
s
.
substring
(
index
,
Math
.
min
(
index
+
50
,
s
.
length
()))
+
"\""
;
int
rank
=
suffix2
.
rank
(
s
.
substring
(
index
));
assert
s
.
substring
(
index
).
equals
(
suffix2
.
select
(
i
));
if
(
i
==
0
)
{
StdOut
.
printf
(
"%3d %3d %3s %3d %s\n"
,
i
,
index
,
"-"
,
rank
,
ith
);
}
else
{
// int lcp = suffix.lcp(suffix2.index(i), suffix2.index(i-1));
int
lcp
=
suffix2
.
lcp
(
i
);
StdOut
.
printf
(
"%3d %3d %3d %3d %s\n"
,
i
,
index
,
lcp
,
rank
,
ith
);
}
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/SymbolDigraph.java
edu/princeton/cs/algs4/SymbolDigraph.java
/******************************************************************************
* Compilation: javac SymbolDigraph.java
* Execution: java SymbolDigraph
* Dependencies: ST.java Digraph.java In.java
* Data files: https://algs4.cs.princeton.edu/42digraph/routes.txt
*
* % java SymbolDigraph routes.txt " "
* JFK
* MCO
* ATL
* ORD
* ATL
* HOU
* MCO
* LAX
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
SymbolDigraph} class represents a digraph, where the
* vertex names are arbitrary strings.
* By providing mappings between string vertex names and integers,
* it serves as a wrapper around the
* {
@link
Digraph} data type, which assumes the vertex names are integers
* between 0 and V – 1.
* It also supports initializing a symbol digraph from a file.
*
* This implementation uses an {
@link
ST} to map from strings to integers,
* an array to map from integers to strings, and a {
@link
Digraph} to store
* the underlying graph.
* The indexOf and contains operations take time
* proportional to log V, where V is the number of vertices.
* The nameOf operation takes constant time.
*
* For additional documentation, see Section 4.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
SymbolDigraph
{
private
ST
<
String
,
Integer
>
st
;
// string -> index
private
String
[]
keys
;
// index -> string
private
Digraph
graph
;
// the underlying digraph
/**
* Initializes a digraph from a file using the specified delimiter.
* Each line in the file contains
* the name of a vertex, followed by a list of the names
* of the vertices adjacent to that vertex, separated by the delimiter.
*
@param
filename the name of the file
*
@param
delimiter the delimiter between fields
*/
public
SymbolDigraph
(
String
filename
,
String
delimiter
)
{
st
=
new
ST
<
String
,
Integer
>
();
// First pass builds the index by reading strings to associate
// distinct strings with an index
In
in
=
new
In
(
filename
);
while
(
in
.
hasNextLine
())
{
String
[]
a
=
in
.
readLine
().
split
(
delimiter
);
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
if
(
!
st
.
contains
(
a
[
i
]))
st
.
put
(
a
[
i
],
st
.
size
());
}
}
// inverted index to get string keys in an array
keys
=
new
String
[
st
.
size
()];
for
(
String
name
:
st
.
keys
())
{
keys
[
st
.
get
(
name
)]
=
name
;
}
// second pass builds the digraph by connecting first vertex on each
// line to all others
graph
=
new
Digraph
(
st
.
size
());
in
=
new
In
(
filename
);
while
(
in
.
hasNextLine
())
{
String
[]
a
=
in
.
readLine
().
split
(
delimiter
);
int
v
=
st
.
get
(
a
[
0
]);
for
(
int
i
=
1
;
i
<
a
.
length
;
i
++
)
{
int
w
=
st
.
get
(
a
[
i
]);
graph
.
addEdge
(
v
,
w
);
}
}
}
/**
* Does the digraph contain the vertex named {
@code
s}?
*
@param
s the name of a vertex
*
@return
{
@code
true} if {
@code
s} is the name of a vertex, and {
@code
false} otherwise
*/
public
boolean
contains
(
String
s
)
{
return
st
.
contains
(
s
);
}
/**
* Returns the integer associated with the vertex named {
@code
s}.
*
@param
s the name of a vertex
*
@return
the integer (between 0 and V – 1) associated with the vertex named {
@code
s}
*
@deprecated
Replaced by {
@link
#indexOf(String)}.
*/
@
Deprecated
public
int
index
(
String
s
)
{
return
st
.
get
(
s
);
}
/**
* Returns the integer associated with the vertex named {
@code
s}.
*
@param
s the name of a vertex
*
@return
the integer (between 0 and V – 1) associated with the vertex named {
@code
s}
*/
public
int
indexOf
(
String
s
)
{
return
st
.
get
(
s
);
}
/**
* Returns the name of the vertex associated with the integer {
@code
v}.
*
@param
v the integer corresponding to a vertex (between 0 and V – 1)
*
@return
the name of the vertex associated with the integer {
@code
v}
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*
@deprecated
Replaced by {
@link
#nameOf(int)}.
*/
@
Deprecated
public
String
name
(
int
v
)
{
validateVertex
(
v
);
return
keys
[
v
];
}
/**
* Returns the name of the vertex associated with the integer {
@code
v}.
*
@param
v the integer corresponding to a vertex (between 0 and V – 1)
*
@return
the name of the vertex associated with the integer {
@code
v}
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
String
nameOf
(
int
v
)
{
validateVertex
(
v
);
return
keys
[
v
];
}
/**
* Returns the digraph assoicated with the symbol graph. It is the client's responsibility
* not to mutate the digraph.
*
*
@return
the digraph associated with the symbol digraph
*
@deprecated
Replaced by {
@link
#digraph()}.
*/
@
Deprecated
public
Digraph
G
()
{
return
graph
;
}
/**
* Returns the digraph assoicated with the symbol graph. It is the client's responsibility
* not to mutate the digraph.
*
*
@return
the digraph associated with the symbol digraph
*/
public
Digraph
digraph
()
{
return
graph
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
graph
.
V
();
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
SymbolDigraph} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
filename
=
args
[
0
];
String
delimiter
=
args
[
1
];
SymbolDigraph
sg
=
new
SymbolDigraph
(
filename
,
delimiter
);
Digraph
graph
=
sg
.
digraph
();
while
(
!
StdIn
.
isEmpty
())
{
String
t
=
StdIn
.
readLine
();
for
(
int
v
:
graph
.
adj
(
sg
.
index
(
t
)))
{
StdOut
.
println
(
” ”
+
sg
.
name
(
v
));
}
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/SymbolGraph.java
edu/princeton/cs/algs4/SymbolGraph.java
/******************************************************************************
* Compilation: javac SymbolGraph.java
* Execution: java SymbolGraph filename.txt delimiter
* Dependencies: ST.java Graph.java In.java StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/41graph/routes.txt
* https://algs4.cs.princeton.edu/41graph/movies.txt
* https://algs4.cs.princeton.edu/41graph/moviestiny.txt
* https://algs4.cs.princeton.edu/41graph/moviesG.txt
* https://algs4.cs.princeton.edu/41graph/moviestopGrossing.txt
*
* % java SymbolGraph routes.txt ” ”
* JFK
* MCO
* ATL
* ORD
* LAX
* PHX
* LAS
*
* % java SymbolGraph movies.txt “/”
* Tin Men (1987)
* Hershey, Barbara
* Geppi, Cindy
* Jones, Kathy (II)
* Herr, Marcia
* …
* Blumenfeld, Alan
* DeBoy, David
* Bacon, Kevin
* Woodsman, The (2004)
* Wild Things (1998)
* Where the Truth Lies (2005)
* Tremors (1990)
* …
* Apollo 13 (1995)
* Animal House (1978)
*
*
* Assumes that input file is encoded using UTF-8.
* % iconv -f ISO-8859-1 -t UTF-8 movies-iso8859.txt > movies.txt
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
SymbolGraph} class represents an undirected graph, where the
* vertex names are arbitrary strings.
* By providing mappings between string vertex names and integers,
* it serves as a wrapper around the
* {
@link
Graph} data type, which assumes the vertex names are integers
* between 0 and V – 1.
* It also supports initializing a symbol graph from a file.
*
* This implementation uses an {
@link
ST} to map from strings to integers,
* an array to map from integers to strings, and a {
@link
Graph} to store
* the underlying graph.
* The indexOf and contains operations take time
* proportional to log V, where V is the number of vertices.
* The nameOf operation takes constant time.
*
* For additional documentation, see Section 4.1 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
SymbolGraph
{
private
ST
<
String
,
Integer
>
st
;
// string -> index
private
String
[]
keys
;
// index -> string
private
Graph
graph
;
// the underlying graph
/**
* Initializes a graph from a file using the specified delimiter.
* Each line in the file contains
* the name of a vertex, followed by a list of the names
* of the vertices adjacent to that vertex, separated by the delimiter.
*
@param
filename the name of the file
*
@param
delimiter the delimiter between fields
*/
public
SymbolGraph
(
String
filename
,
String
delimiter
)
{
st
=
new
ST
<
String
,
Integer
>
();
// First pass builds the index by reading strings to associate
// distinct strings with an index
In
in
=
new
In
(
filename
);
// while (in.hasNextLine()) {
while
(
!
in
.
isEmpty
())
{
String
[]
a
=
in
.
readLine
().
split
(
delimiter
);
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
if
(
!
st
.
contains
(
a
[
i
]))
st
.
put
(
a
[
i
],
st
.
size
());
}
}
// inverted index to get string keys in an array
keys
=
new
String
[
st
.
size
()];
for
(
String
name
:
st
.
keys
())
{
keys
[
st
.
get
(
name
)]
=
name
;
}
// second pass builds the graph by connecting first vertex on each
// line to all others
graph
=
new
Graph
(
st
.
size
());
in
=
new
In
(
filename
);
while
(
in
.
hasNextLine
())
{
String
[]
a
=
in
.
readLine
().
split
(
delimiter
);
int
v
=
st
.
get
(
a
[
0
]);
for
(
int
i
=
1
;
i
<
a
.
length
;
i
++
)
{
int
w
=
st
.
get
(
a
[
i
]);
graph
.
addEdge
(
v
,
w
);
}
}
}
/**
* Does the graph contain the vertex named {
@code
s}?
*
@param
s the name of a vertex
*
@return
{
@code
true} if {
@code
s} is the name of a vertex, and {
@code
false} otherwise
*/
public
boolean
contains
(
String
s
)
{
return
st
.
contains
(
s
);
}
/**
* Returns the integer associated with the vertex named {
@code
s}.
*
@param
s the name of a vertex
*
@return
the integer (between 0 and V – 1) associated with the vertex named {
@code
s}
*
@deprecated
Replaced by {
@link
#indexOf(String)}.
*/
@
Deprecated
public
int
index
(
String
s
)
{
return
st
.
get
(
s
);
}
/**
* Returns the integer associated with the vertex named {
@code
s}.
*
@param
s the name of a vertex
*
@return
the integer (between 0 and V – 1) associated with the vertex named {
@code
s}
*/
public
int
indexOf
(
String
s
)
{
return
st
.
get
(
s
);
}
/**
* Returns the name of the vertex associated with the integer {
@code
v}.
*
@param
v the integer corresponding to a vertex (between 0 and V – 1)
*
@return
the name of the vertex associated with the integer {
@code
v}
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*
@deprecated
Replaced by {
@link
#nameOf(int)}.
*/
@
Deprecated
public
String
name
(
int
v
)
{
validateVertex
(
v
);
return
keys
[
v
];
}
/**
* Returns the name of the vertex associated with the integer {
@code
v}.
*
@param
v the integer corresponding to a vertex (between 0 and V – 1)
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*
@return
the name of the vertex associated with the integer {
@code
v}
*/
public
String
nameOf
(
int
v
)
{
validateVertex
(
v
);
return
keys
[
v
];
}
/**
* Returns the graph assoicated with the symbol graph. It is the client's responsibility
* not to mutate the graph.
*
@return
the graph associated with the symbol graph
*
@deprecated
Replaced by {
@link
#graph()}.
*/
@
Deprecated
public
Graph
G
()
{
return
graph
;
}
/**
* Returns the graph assoicated with the symbol graph. It is the client's responsibility
* not to mutate the graph.
*
@return
the graph associated with the symbol graph
*/
public
Graph
graph
()
{
return
graph
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
graph
.
V
();
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
SymbolGraph} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
filename
=
args
[
0
];
String
delimiter
=
args
[
1
];
SymbolGraph
sg
=
new
SymbolGraph
(
filename
,
delimiter
);
Graph
graph
=
sg
.
graph
();
while
(
StdIn
.
hasNextLine
())
{
String
source
=
StdIn
.
readLine
();
if
(
sg
.
contains
(
source
))
{
int
s
=
sg
.
index
(
source
);
for
(
int
v
:
graph
.
adj
(
s
))
{
StdOut
.
println
(
” ”
+
sg
.
name
(
v
));
}
}
else
{
StdOut
.
println
(
“input not contain ‘”
+
source
+
“‘”
);
}
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/TarjanSCC.java
edu/princeton/cs/algs4/TarjanSCC.java
/******************************************************************************
* Compilation: javac TarjanSCC.java
* Execution: Java TarjanSCC V E
* Dependencies: Digraph.java Stack.java TransitiveClosure.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/42digraph/tinyDG.txt
* https://algs4.cs.princeton.edu/42digraph/mediumDG.txt
* https://algs4.cs.princeton.edu/42digraph/largeDG.txt
*
* Compute the strongly-connected components of a digraph using
* Tarjan’s algorithm.
*
* Runs in O(E + V) time.
*
* % java TarjanSCC tinyDG.txt
* 5 components
* 1
* 0 2 3 4 5
* 9 10 11 12
* 6 8
* 7
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
TarjanSCC} class represents a data type for
* determining the strong components in a digraph.
* The id operation determines in which strong component
* a given vertex lies; the areStronglyConnected operation
* determines whether two vertices are in the same strong component;
* and the count operation determines the number of strong
* components.
*
* The component identifier of a component is one of the
* vertices in the strong component: two vertices have the same component
* identifier if and only if they are in the same strong component.
*
* This implementation uses Tarjan’s algorithm.
* The constructor takes Θ(V + E) time,
* where V is the number of vertices and E is the
* number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the digraph).
* For alternative implementations of the same API, see
* {
@link
KosarajuSharirSCC} and {
@link
GabowSCC}.
*
* For additional documentation,
* see Section 4.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
TarjanSCC
{
private
boolean
[]
marked
;
// marked[v] = has v been visited?
private
int
[]
id
;
// id[v] = id of strong component containing v
private
int
[]
low
;
// low[v] = low number of v
private
int
pre
;
// preorder number counter
private
int
count
;
// number of strongly-connected components
private
Stack
<
Integer
>
stack
;
/**
* Computes the strong components of the digraph {
@code
G}.
*
@param
G the digraph
*/
public
TarjanSCC
(
Digraph
G
)
{
marked
=
new
boolean
[
G
.
V
()];
stack
=
new
Stack
<
Integer
>
();
id
=
new
int
[
G
.
V
()];
low
=
new
int
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
if
(
!
marked
[
v
])
dfs
(
G
,
v
);
}
// check that id[] gives strong components
assert
check
(
G
);
}
private
void
dfs
(
Digraph
G
,
int
v
)
{
marked
[
v
]
=
true
;
low
[
v
]
=
pre
++
;
int
min
=
low
[
v
];
stack
.
push
(
v
);
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
!
marked
[
w
])
dfs
(
G
,
w
);
if
(
low
[
w
]
<
min
)
min
=
low
[
w
];
}
if
(
min
<
low
[
v
])
{
low
[
v
]
=
min
;
return
;
}
int
w
;
do
{
w
=
stack
.
pop
();
id
[
w
]
=
count
;
low
[
w
]
=
G
.
V
();
}
while
(
w
!=
v
);
count
++
;
}
/**
* Returns the number of strong components.
*
@return
the number of strong components
*/
public
int
count
()
{
return
count
;
}
/**
* Are vertices {
@code
v} and {
@code
w} in the same strong component?
*
@param
v one vertex
*
@param
w the other vertex
*
@return
{
@code
true} if vertices {
@code
v} and {
@code
w} are in the same
* strong component, and {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*
@throws
IllegalArgumentException unless {
@code
0 <= w < V}
*/
public
boolean
stronglyConnected
(
int
v
,
int
w
)
{
validateVertex
(
v
);
validateVertex
(
w
);
return
id
[
v
]
==
id
[
w
];
}
/**
* Returns the component id of the strong component containing vertex {
@code
v}.
*
@param
v the vertex
*
@return
the component id of the strong component containing vertex {
@code
v}
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
int
id
(
int
v
)
{
validateVertex
(
v
);
return
id
[
v
];
}
// does the id[] array contain the strongly connected components?
private
boolean
check
(
Digraph
G
)
{
TransitiveClosure
tc
=
new
TransitiveClosure
(
G
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
for
(
int
w
=
0
;
w
<
G
.
V
();
w
++
)
{
if
(
stronglyConnected
(
v
,
w
)
!=
(
tc
.
reachable
(
v
,
w
)
&&
tc
.
reachable
(
w
,
v
)))
return
false
;
}
}
return
true
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
marked
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
TarjanSCC} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
Digraph
G
=
new
Digraph
(
in
);
TarjanSCC
scc
=
new
TarjanSCC
(
G
);
// number of connected components
int
m
=
scc
.
count
();
StdOut
.
println
(
m
+
” components”
);
// compute list of vertices in each strong component
Queue
<
Integer
>
[]
components
=
(
Queue
<
Integer
>
[])
new
Queue
[
m
];
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
components
[
i
]
=
new
Queue
<
Integer
>
();
}
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
components
[
scc
.
id
(
v
)].
enqueue
(
v
);
}
// print results
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
for
(
int
v
:
components
[
i
])
{
StdOut
.
print
(
v
+
" "
);
}
StdOut
.
println
();
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/ThreeSumFast.java
edu/princeton/cs/algs4/ThreeSumFast.java
/******************************************************************************
* Compilation: javac ThreeSumFast.java
* Execution: java ThreeSumFast input.txt
* Dependencies: StdOut.java In.java Stopwatch.java
* Data files: https://algs4.cs.princeton.edu/14analysis/1Kints.txt
* https://algs4.cs.princeton.edu/14analysis/2Kints.txt
* https://algs4.cs.princeton.edu/14analysis/4Kints.txt
* https://algs4.cs.princeton.edu/14analysis/8Kints.txt
* https://algs4.cs.princeton.edu/14analysis/16Kints.txt
* https://algs4.cs.princeton.edu/14analysis/32Kints.txt
* https://algs4.cs.princeton.edu/14analysis/1Mints.txt
*
* A program with n^2 log n running time. Reads n integers
* and counts the number of triples that sum to exactly 0.
*
* Limitations
* -----------
* - we ignore integer overflow
* - doesn't handle case when input has duplicates
*
*
* % java ThreeSumFast 1Kints.txt
* 70
*
* % java ThreeSumFast 2Kints.txt
* 528
*
* % java ThreeSumFast 4Kints.txt
* 4039
*
* % java ThreeSumFast 8Kints.txt
* 32074
*
* % java ThreeSumFast 16Kints.txt
* 255181
*
* % java ThreeSumFast 32Kints.txt
* 2052358
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Arrays
;
/**
* The {
@code
ThreeSumFast} class provides static methods for counting
* and printing the number of triples in an array of distinct integers that
* sum to 0 (ignoring integer overflow).
*
* This implementation uses sorting and binary search and takes time
* proportional to n^2 log n, where n is the number of integers.
*
* For additional documentation, see Section 1.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
ThreeSumFast
{
// Do not instantiate.
private
ThreeSumFast
()
{
}
// returns true if the sorted array a[] contains any duplicated integers
private
static
boolean
containsDuplicates
(
int
[]
a
)
{
for
(
int
i
=
1
;
i
<
a
.
length
;
i
++
)
if
(
a
[
i
]
==
a
[
i
-
1
])
return
true
;
return
false
;
}
/**
* Prints to standard output the (i, j, k) with {
@code
i < j < k}
* such that {
@code
a[i] + a[j] + a[k] == 0}.
*
*
@param
a the array of integers
*
@throws
IllegalArgumentException if the array contains duplicate integers
*/
public
static
void
printAll
(
int
[]
a
)
{
int
n
=
a
.
length
;
Arrays
.
sort
(
a
);
if
(
containsDuplicates
(
a
))
throw
new
IllegalArgumentException
(
"array contains duplicate integers"
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
for
(
int
j
=
i
+
1
;
j
<
n
;
j
++
)
{
int
k
=
Arrays
.
binarySearch
(
a
,
-
(
a
[
i
]
+
a
[
j
]));
if
(
k
>
j
)
StdOut
.
println
(
a
[
i
]
+
” ”
+
a
[
j
]
+
” ”
+
a
[
k
]);
}
}
}
/**
* Returns the number of triples (i, j, k) with {
@code
i < j < k}
* such that {
@code
a[i] + a[j] + a[k] == 0}.
*
*
@param
a the array of integers
*
@return
the number of triples (i, j, k) with {
@code
i < j < k}
* such that {
@code
a[i] + a[j] + a[k] == 0}
*/
public
static
int
count
(
int
[]
a
)
{
int
n
=
a
.
length
;
Arrays
.
sort
(
a
);
if
(
containsDuplicates
(
a
))
throw
new
IllegalArgumentException
(
"array contains duplicate integers"
);
int
count
=
0
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
for
(
int
j
=
i
+
1
;
j
<
n
;
j
++
)
{
int
k
=
Arrays
.
binarySearch
(
a
,
-
(
a
[
i
]
+
a
[
j
]));
if
(
k
>
j
)
count
++
;
}
}
return
count
;
}
/**
* Reads in a sequence of distinct integers from a file, specified as a command-line argument;
* counts the number of triples sum to exactly zero; prints out the time to perform
* the computation.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
int
[]
a
=
in
.
readAllInts
();
int
count
=
count
(
a
);
StdOut
.
println
(
count
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/ThreeSum.java
edu/princeton/cs/algs4/ThreeSum.java
/******************************************************************************
* Compilation: javac ThreeSum.java
* Execution: java ThreeSum input.txt
* Dependencies: In.java StdOut.java Stopwatch.java
* Data files: https://algs4.cs.princeton.edu/14analysis/1Kints.txt
* https://algs4.cs.princeton.edu/14analysis/2Kints.txt
* https://algs4.cs.princeton.edu/14analysis/4Kints.txt
* https://algs4.cs.princeton.edu/14analysis/8Kints.txt
* https://algs4.cs.princeton.edu/14analysis/16Kints.txt
* https://algs4.cs.princeton.edu/14analysis/32Kints.txt
* https://algs4.cs.princeton.edu/14analysis/1Mints.txt
*
* A program with cubic running time. Reads n integers
* and counts the number of triples that sum to exactly 0
* (ignoring integer overflow).
*
* % java ThreeSum 1Kints.txt
* 70
*
* % java ThreeSum 2Kints.txt
* 528
*
* % java ThreeSum 4Kints.txt
* 4039
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
ThreeSum} class provides static methods for counting
* and printing the number of triples in an array of integers that sum to 0
* (ignoring integer overflow).
*
* This implementation uses a triply nested loop and takes proportional to n^3,
* where n is the number of integers.
*
* For additional documentation, see Section 1.4 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
ThreeSum
{
// Do not instantiate.
private
ThreeSum
()
{
}
/**
* Prints to standard output the (i, j, k) with {
@code
i < j < k}
* such that {
@code
a[i] + a[j] + a[k] == 0}.
*
*
@param
a the array of integers
*/
public
static
void
printAll
(
int
[]
a
)
{
int
n
=
a
.
length
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
for
(
int
j
=
i
+
1
;
j
<
n
;
j
++
)
{
for
(
int
k
=
j
+
1
;
k
<
n
;
k
++
)
{
if
(
a
[
i
]
+
a
[
j
]
+
a
[
k
]
==
0
)
{
StdOut
.
println
(
a
[
i
]
+
" "
+
a
[
j
]
+
" "
+
a
[
k
]);
}
}
}
}
}
/**
* Returns the number of triples (i, j, k) with {
@code
i < j < k}
* such that {
@code
a[i] + a[j] + a[k] == 0}.
*
*
@param
a the array of integers
*
@return
the number of triples (i, j, k) with {
@code
i < j < k}
* such that {
@code
a[i] + a[j] + a[k] == 0}
*/
public
static
int
count
(
int
[]
a
)
{
int
n
=
a
.
length
;
int
count
=
0
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
for
(
int
j
=
i
+
1
;
j
<
n
;
j
++
)
{
for
(
int
k
=
j
+
1
;
k
<
n
;
k
++
)
{
if
(
a
[
i
]
+
a
[
j
]
+
a
[
k
]
==
0
)
{
count
++
;
}
}
}
}
return
count
;
}
/**
* Reads in a sequence of integers from a file, specified as a command-line argument;
* counts the number of triples sum to exactly zero; prints out the time to perform
* the computation.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
int
[]
a
=
in
.
readAllInts
();
Stopwatch
timer
=
new
Stopwatch
();
int
count
=
count
(
a
);
StdOut
.
println
(
"elapsed time = "
+
timer
.
elapsedTime
());
StdOut
.
println
(
count
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/TopM.java
edu/princeton/cs/algs4/TopM.java
/******************************************************************************
* Compilation: javac TopM.java
* Execution: java TopM m < input.txt
* Dependencies: MinPQ.java Transaction.java StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/24pq/tinyBatch.txt
*
* Given an integer m from the command line and an input stream where
* each line contains a String and a long value, this MinPQ client
* prints the m lines whose numbers are the highest.
*
* % java TopM 5 < tinyBatch.txt
* Thompson 2/27/2000 4747.08
* vonNeumann 2/12/1994 4732.35
* vonNeumann 1/11/1999 4409.74
* Hoare 8/18/1992 4381.21
* vonNeumann 3/26/2002 4121.85
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
TopM} class provides a client that reads a sequence of
* transactions from standard input and prints the m largest ones
* to standard output. This implementation uses a {
@link
MinPQ} of size
* at most m + 1 to identify the M largest transactions
* and a {
@link
Stack} to output them in the proper order.
*
* For additional documentation, see Section 2.4
* of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
TopM
{
// This class should not be instantiated.
private
TopM
()
{
}
/**
* Reads a sequence of transactions from standard input; takes a
* command-line integer m; prints to standard output the m largest
* transactions in descending order.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
m
=
Integer
.
parseInt
(
args
[
0
]);
MinPQ
<
Transaction
>
pq
=
new
MinPQ
<
Transaction
>
(
m
+
1
);
while
(
StdIn
.
hasNextLine
())
{
// Create an entry from the next line and put on the PQ.
String
line
=
StdIn
.
readLine
();
Transaction
transaction
=
new
Transaction
(
line
);
pq
.
insert
(
transaction
);
// remove minimum if m+1 entries on the PQ
if
(
pq
.
size
()
>
m
)
pq
.
delMin
();
}
// top m entries are on the PQ
// print entries on PQ in reverse order
Stack
<
Transaction
>
stack
=
new
Stack
<
Transaction
>
();
for
(
Transaction
transaction
:
pq
)
stack
.
push
(
transaction
);
for
(
Transaction
transaction
:
stack
)
StdOut
.
println
(
transaction
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Topological.java
edu/princeton/cs/algs4/Topological.java
/******************************************************************************
* Compilation: javac Topological.java
* Execution: java Topological filename.txt delimiter
* Dependencies: Digraph.java DepthFirstOrder.java DirectedCycle.java
* EdgeWeightedDigraph.java EdgeWeightedDirectedCycle.java
* SymbolDigraph.java
* Data files: https://algs4.cs.princeton.edu/42digraph/jobs.txt
*
* Compute topological ordering of a DAG or edge-weighted DAG.
* Runs in O(E + V) time.
*
* % java Topological jobs.txt “/”
* Calculus
* Linear Algebra
* Introduction to CS
* Advanced Programming
* Algorithms
* Theoretical CS
* Artificial Intelligence
* Robotics
* Machine Learning
* Neural Networks
* Databases
* Scientific Computing
* Computational Biology
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Topological} class represents a data type for
* determining a topological order of a directed acyclic graph (DAG).
* A digraph has a topological order if and only if it is a DAG.
* The hasOrder operation determines whether the digraph has
* a topological order, and if so, the order operation
* returns one.
*
* This implementation uses depth-first search.
* The constructor takes Θ(V + E) time in the
* worst case, where V is the number of vertices and E
* is the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the digraph).
*
* See {
@link
DirectedCycle}, {
@link
DirectedCycleX}, and
* {
@link
EdgeWeightedDirectedCycle} for computing a directed cycle
* if the digraph is not a DAG.
* See {
@link
TopologicalX} for a nonrecursive queue-based algorithm
* for computing a topological order of a DAG.
*
* For additional documentation,
* see Section 4.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Topological
{
private
Iterable
<
Integer
>
order
;
// topological order
private
int
[]
rank
;
// rank[v] = rank of vertex v in order
/**
* Determines whether the digraph {
@code
G} has a topological order and, if so,
* finds such a topological order.
*
@param
G the digraph
*/
public
Topological
(
Digraph
G
)
{
DirectedCycle
finder
=
new
DirectedCycle
(
G
);
if
(
!
finder
.
hasCycle
())
{
DepthFirstOrder
dfs
=
new
DepthFirstOrder
(
G
);
order
=
dfs
.
reversePost
();
rank
=
new
int
[
G
.
V
()];
int
i
=
0
;
for
(
int
v
:
order
)
rank
[
v
]
=
i
++
;
}
}
/**
* Determines whether the edge-weighted digraph {
@code
G} has a topological
* order and, if so, finds such an order.
*
@param
G the edge-weighted digraph
*/
public
Topological
(
EdgeWeightedDigraph
G
)
{
EdgeWeightedDirectedCycle
finder
=
new
EdgeWeightedDirectedCycle
(
G
);
if
(
!
finder
.
hasCycle
())
{
DepthFirstOrder
dfs
=
new
DepthFirstOrder
(
G
);
order
=
dfs
.
reversePost
();
}
}
/**
* Returns a topological order if the digraph has a topologial order,
* and {
@code
null} otherwise.
*
@return
a topological order of the vertices (as an interable) if the
* digraph has a topological order (or equivalently, if the digraph is a DAG),
* and {
@code
null} otherwise
*/
public
Iterable
<
Integer
>
order
()
{
return
order
;
}
/**
* Does the digraph have a topological order?
*
@return
{
@code
true} if the digraph has a topological order (or equivalently,
* if the digraph is a DAG), and {
@code
false} otherwise
*/
public
boolean
hasOrder
()
{
return
order
!=
null
;
}
/**
* Does the digraph have a topological order?
*
@return
{
@code
true} if the digraph has a topological order (or equivalently,
* if the digraph is a DAG), and {
@code
false} otherwise
*
@deprecated
Replaced by {
@link
#hasOrder()}.
*/
@
Deprecated
public
boolean
isDAG
()
{
return
hasOrder
();
}
/**
* The the rank of vertex {
@code
v} in the topological order;
* -1 if the digraph is not a DAG
*
*
@param
v the vertex
*
@return
the position of vertex {
@code
v} in a topological order
* of the digraph; -1 if the digraph is not a DAG
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
int
rank
(
int
v
)
{
validateVertex
(
v
);
if
(
hasOrder
())
return
rank
[
v
];
else
return
-
1
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
rank
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
Topological} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
String
filename
=
args
[
0
];
String
delimiter
=
args
[
1
];
SymbolDigraph
sg
=
new
SymbolDigraph
(
filename
,
delimiter
);
Topological
topological
=
new
Topological
(
sg
.
digraph
());
for
(
int
v
:
topological
.
order
())
{
StdOut
.
println
(
sg
.
nameOf
(
v
));
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/TopologicalX.java
edu/princeton/cs/algs4/TopologicalX.java
/******************************************************************************
* Compilation: javac TopologicalX.java
* Execution: java TopologicalX V E F
* Dependencies: Queue.java Digraph.java
*
* Compute topological ordering of a DAG using queue-based algorithm.
* Runs in O(E + V) time.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
TopologicalX} class represents a data type for
* determining a topological order of a directed acyclic graph (DAG).
* A digraph has a topological order if and only if it is a DAG.
* The hasOrder operation determines whether the digraph has
* a topological order, and if so, the order operation
* returns one.
*
* This implementation uses a nonrecursive, queue-based algorithm.
* The constructor takes Θ(V + E) time in the worst
* case, where V is the number of vertices and E
* is the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V) extra space (not including the digraph).
*
* See {
@link
DirectedCycle}, {
@link
DirectedCycleX}, and
* {
@link
EdgeWeightedDirectedCycle} to compute a
* directed cycle if the digraph is not a DAG.
* See {
@link
Topological} for a recursive version that uses depth-first search.
*
* For additional documentation,
* see Section 4.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
TopologicalX
{
private
Queue
<
Integer
>
order
;
// vertices in topological order
private
int
[]
ranks
;
// ranks[v] = order where vertex v appers in order
/**
* Determines whether the digraph {
@code
G} has a topological order and, if so,
* finds such a topological order.
*
@param
G the digraph
*/
public
TopologicalX
(
Digraph
G
)
{
// indegrees of remaining vertices
int
[]
indegree
=
new
int
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
indegree
[
v
]
=
G
.
indegree
(
v
);
}
// initialize
ranks
=
new
int
[
G
.
V
()];
order
=
new
Queue
<
Integer
>
();
int
count
=
0
;
// initialize queue to contain all vertices with indegree = 0
Queue
<
Integer
>
queue
=
new
Queue
<
Integer
>
();
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
indegree
[
v
]
==
0
)
queue
.
enqueue
(
v
);
while
(
!
queue
.
isEmpty
())
{
int
v
=
queue
.
dequeue
();
order
.
enqueue
(
v
);
ranks
[
v
]
=
count
++
;
for
(
int
w
:
G
.
adj
(
v
))
{
indegree
[
w
]
--
;
if
(
indegree
[
w
]
==
0
)
queue
.
enqueue
(
w
);
}
}
// there is a directed cycle in subgraph of vertices with indegree >= 1.
if
(
count
!=
G
.
V
())
{
order
=
null
;
}
assert
check
(
G
);
}
/**
* Determines whether the edge-weighted digraph {
@code
G} has a
* topological order and, if so, finds such a topological order.
*
@param
G the digraph
*/
public
TopologicalX
(
EdgeWeightedDigraph
G
)
{
// indegrees of remaining vertices
int
[]
indegree
=
new
int
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
indegree
[
v
]
=
G
.
indegree
(
v
);
}
// initialize
ranks
=
new
int
[
G
.
V
()];
order
=
new
Queue
<
Integer
>
();
int
count
=
0
;
// initialize queue to contain all vertices with indegree = 0
Queue
<
Integer
>
queue
=
new
Queue
<
Integer
>
();
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
if
(
indegree
[
v
]
==
0
)
queue
.
enqueue
(
v
);
while
(
!
queue
.
isEmpty
())
{
int
v
=
queue
.
dequeue
();
order
.
enqueue
(
v
);
ranks
[
v
]
=
count
++
;
for
(
DirectedEdge
e
:
G
.
adj
(
v
))
{
int
w
=
e
.
to
();
indegree
[
w
]
--
;
if
(
indegree
[
w
]
==
0
)
queue
.
enqueue
(
w
);
}
}
// there is a directed cycle in subgraph of vertices with indegree >= 1.
if
(
count
!=
G
.
V
())
{
order
=
null
;
}
assert
check
(
G
);
}
/**
* Returns a topological order if the digraph has a topologial order,
* and {
@code
null} otherwise.
*
@return
a topological order of the vertices (as an interable) if the
* digraph has a topological order (or equivalently, if the digraph is a DAG),
* and {
@code
null} otherwise
*/
public
Iterable
<
Integer
>
order
()
{
return
order
;
}
/**
* Does the digraph have a topological order?
*
@return
{
@code
true} if the digraph has a topological order (or equivalently,
* if the digraph is a DAG), and {
@code
false} otherwise
*/
public
boolean
hasOrder
()
{
return
order
!=
null
;
}
/**
* The the rank of vertex {
@code
v} in the topological order;
* -1 if the digraph is not a DAG
*
*
@param
v vertex
*
@return
the position of vertex {
@code
v} in a topological order
* of the digraph; -1 if the digraph is not a DAG
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*/
public
int
rank
(
int
v
)
{
validateVertex
(
v
);
if
(
hasOrder
())
return
ranks
[
v
];
else
return
-
1
;
}
// certify that digraph is acyclic
private
boolean
check
(
Digraph
G
)
{
// digraph is acyclic
if
(
hasOrder
())
{
// check that ranks are a permutation of 0 to V-1
boolean
[]
found
=
new
boolean
[
G
.
V
()];
for
(
int
i
=
0
;
i
<
G
.
V
();
i
++
)
{
found
[
rank
(
i
)]
=
true
;
}
for
(
int
i
=
0
;
i
<
G
.
V
();
i
++
)
{
if
(
!
found
[
i
])
{
System
.
err
.
println
(
"No vertex with rank "
+
i
);
return
false
;
}
}
// check that ranks provide a valid topological order
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
for
(
int
w
:
G
.
adj
(
v
))
{
if
(
rank
(
v
)
>
rank
(
w
))
{
System
.
err
.
printf
(
“%d-%d: rank(%d) = %d, rank(%d) = %d\n”
,
v
,
w
,
v
,
rank
(
v
),
w
,
rank
(
w
));
return
false
;
}
}
}
// check that order() is consistent with rank()
int
r
=
0
;
for
(
int
v
:
order
())
{
if
(
rank
(
v
)
!=
r
)
{
System
.
err
.
println
(
“order() and rank() inconsistent”
);
return
false
;
}
r
++
;
}
}
return
true
;
}
// certify that digraph is acyclic
private
boolean
check
(
EdgeWeightedDigraph
G
)
{
// digraph is acyclic
if
(
hasOrder
())
{
// check that ranks are a permutation of 0 to V-1
boolean
[]
found
=
new
boolean
[
G
.
V
()];
for
(
int
i
=
0
;
i
<
G
.
V
();
i
++
)
{
found
[
rank
(
i
)]
=
true
;
}
for
(
int
i
=
0
;
i
<
G
.
V
();
i
++
)
{
if
(
!
found
[
i
])
{
System
.
err
.
println
(
"No vertex with rank "
+
i
);
return
false
;
}
}
// check that ranks provide a valid topological order
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
for
(
DirectedEdge
e
:
G
.
adj
(
v
))
{
int
w
=
e
.
to
();
if
(
rank
(
v
)
>
rank
(
w
))
{
System
.
err
.
printf
(
“%d-%d: rank(%d) = %d, rank(%d) = %d\n”
,
v
,
w
,
v
,
rank
(
v
),
w
,
rank
(
w
));
return
false
;
}
}
}
// check that order() is consistent with rank()
int
r
=
0
;
for
(
int
v
:
order
())
{
if
(
rank
(
v
)
!=
r
)
{
System
.
err
.
println
(
“order() and rank() inconsistent”
);
return
false
;
}
r
++
;
}
}
return
true
;
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
ranks
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
TopologicalX} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// create random DAG with V vertices and E edges; then add F random edges
int
V
=
Integer
.
parseInt
(
args
[
0
]);
int
E
=
Integer
.
parseInt
(
args
[
1
]);
int
F
=
Integer
.
parseInt
(
args
[
2
]);
Digraph
G1
=
DigraphGenerator
.
dag
(
V
,
E
);
// corresponding edge-weighted digraph
EdgeWeightedDigraph
G2
=
new
EdgeWeightedDigraph
(
V
);
for
(
int
v
=
0
;
v
<
G1
.
V
();
v
++
)
for
(
int
w
:
G1
.
adj
(
v
))
G2
.
addEdge
(
new
DirectedEdge
(
v
,
w
,
0.0
));
// add F extra edges
for
(
int
i
=
0
;
i
<
F
;
i
++
)
{
int
v
=
StdRandom
.
uniform
(
V
);
int
w
=
StdRandom
.
uniform
(
V
);
G1
.
addEdge
(
v
,
w
);
G2
.
addEdge
(
new
DirectedEdge
(
v
,
w
,
0.0
));
}
StdOut
.
println
(
G1
);
StdOut
.
println
();
StdOut
.
println
(
G2
);
// find a directed cycle
TopologicalX
topological1
=
new
TopologicalX
(
G1
);
if
(
!
topological1
.
hasOrder
())
{
StdOut
.
println
(
"Not a DAG"
);
}
// or give topologial sort
else
{
StdOut
.
print
(
"Topological order: "
);
for
(
int
v
:
topological1
.
order
())
{
StdOut
.
print
(
v
+
" "
);
}
StdOut
.
println
();
}
// find a directed cycle
TopologicalX
topological2
=
new
TopologicalX
(
G2
);
if
(
!
topological2
.
hasOrder
())
{
StdOut
.
println
(
"Not a DAG"
);
}
// or give topologial sort
else
{
StdOut
.
print
(
"Topological order: "
);
for
(
int
v
:
topological2
.
order
())
{
StdOut
.
print
(
v
+
" "
);
}
StdOut
.
println
();
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Transaction.java
edu/princeton/cs/algs4/Transaction.java
/******************************************************************************
* Compilation: javac Transaction.java
* Execution: java Transaction
* Dependencies: StdOut.java
*
* Data type for commercial transactions.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Arrays
;
import
java
.
util
.
Comparator
;
/**
* The {
@code
Transaction} class is an immutable data type to encapsulate a
* commercial transaction with a customer name, date, and amount.
*
* For additional documentation,
* see Section 1.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Transaction
implements
Comparable
<
Transaction
>
{
private
final
String
who
;
// customer
private
final
Date
when
;
// date
private
final
double
amount
;
// amount
/**
* Initializes a new transaction from the given arguments.
*
*
@param
who the person involved in this transaction
*
@param
when the date of this transaction
*
@param
amount the amount of this transaction
*
@throws
IllegalArgumentException if {
@code
amount}
* is {
@code
Double.NaN}, {
@code
Double.POSITIVE_INFINITY},
* or {
@code
Double.NEGATIVE_INFINITY}
*/
public
Transaction
(
String
who
,
Date
when
,
double
amount
)
{
if
(
Double
.
isNaN
(
amount
)
||
Double
.
isInfinite
(
amount
))
throw
new
IllegalArgumentException
(
“Amount cannot be NaN or infinite”
);
this
.
who
=
who
;
this
.
when
=
when
;
this
.
amount
=
amount
;
}
/**
* Initializes a new transaction by parsing a string of the form NAME DATE AMOUNT.
*
*
@param
transaction the string to parse
*
@throws
IllegalArgumentException if {
@code
amount}
* is {
@code
Double.NaN}, {
@code
Double.POSITIVE_INFINITY},
* or {
@code
Double.NEGATIVE_INFINITY}
*/
public
Transaction
(
String
transaction
)
{
String
[]
a
=
transaction
.
split
(
“\\s+”
);
who
=
a
[
0
];
when
=
new
Date
(
a
[
1
]);
amount
=
Double
.
parseDouble
(
a
[
2
]);
if
(
Double
.
isNaN
(
amount
)
||
Double
.
isInfinite
(
amount
))
throw
new
IllegalArgumentException
(
“Amount cannot be NaN or infinite”
);
}
/**
* Returns the name of the customer involved in this transaction.
*
*
@return
the name of the customer involved in this transaction
*/
public
String
who
()
{
return
who
;
}
/**
* Returns the date of this transaction.
*
*
@return
the date of this transaction
*/
public
Date
when
()
{
return
when
;
}
/**
* Returns the amount of this transaction.
*
*
@return
the amount of this transaction
*/
public
double
amount
()
{
return
amount
;
}
/**
* Returns a string representation of this transaction.
*
*
@return
a string representation of this transaction
*/
@
Override
public
String
toString
()
{
return
String
.
format
(
“%-10s %10s %8.2f”
,
who
,
when
,
amount
);
}
/**
* Compares two transactions by amount.
*
*
@param
that the other transaction
*
@return
{ a negative integer, zero, a positive integer}, depending
* on whether the amount of this transaction is { less than,
* equal to, or greater than } the amount of that transaction
*/
public
int
compareTo
(
Transaction
that
)
{
return
Double
.
compare
(
this
.
amount
,
that
.
amount
);
}
/**
* Compares this transaction to the specified object.
*
*
@param
other the other transaction
*
@return
true if this transaction is equal to {
@code
other}; false otherwise
*/
@
Override
public
boolean
equals
(
Object
other
)
{
if
(
other
==
this
)
return
true
;
if
(
other
==
null
)
return
false
;
if
(
other
.
getClass
()
!=
this
.
getClass
())
return
false
;
Transaction
that
=
(
Transaction
)
other
;
return
(
this
.
amount
==
that
.
amount
)
&&
(
this
.
who
.
equals
(
that
.
who
))
&&
(
this
.
when
.
equals
(
that
.
when
));
}
/**
* Returns a hash code for this transaction.
*
*
@return
a hash code for this transaction
*/
public
int
hashCode
()
{
int
hash
=
1
;
hash
=
31
*
hash
+
who
.
hashCode
();
hash
=
31
*
hash
+
when
.
hashCode
();
hash
=
31
*
hash
+
((
Double
)
amount
).
hashCode
();
return
hash
;
// return Objects.hash(who, when, amount);
}
/**
* Compares two transactions by customer name.
*/
public
static
class
WhoOrder
implements
Comparator
<
Transaction
>
{
@
Override
public
int
compare
(
Transaction
v
,
Transaction
w
)
{
return
v
.
who
.
compareTo
(
w
.
who
);
}
}
/**
* Compares two transactions by date.
*/
public
static
class
WhenOrder
implements
Comparator
<
Transaction
>
{
@
Override
public
int
compare
(
Transaction
v
,
Transaction
w
)
{
return
v
.
when
.
compareTo
(
w
.
when
);
}
}
/**
* Compares two transactions by amount.
*/
public
static
class
HowMuchOrder
implements
Comparator
<
Transaction
>
{
@
Override
public
int
compare
(
Transaction
v
,
Transaction
w
)
{
return
Double
.
compare
(
v
.
amount
,
w
.
amount
);
}
}
/**
* Unit tests the {
@code
Transaction} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
Transaction
[]
a
=
new
Transaction
[
4
];
a
[
0
]
=
new
Transaction
(
“Turing 6/17/1990 644.08”
);
a
[
1
]
=
new
Transaction
(
“Tarjan 3/26/2002 4121.85”
);
a
[
2
]
=
new
Transaction
(
“Knuth 6/14/1999 288.34”
);
a
[
3
]
=
new
Transaction
(
“Dijkstra 8/22/2007 2678.40”
);
StdOut
.
println
(
“Unsorted”
);
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
StdOut
.
println
(
a
[
i
]);
StdOut
.
println
();
StdOut
.
println
(
"Sort by date"
);
Arrays
.
sort
(
a
,
new
Transaction
.
WhenOrder
());
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
StdOut
.
println
(
a
[
i
]);
StdOut
.
println
();
StdOut
.
println
(
"Sort by customer"
);
Arrays
.
sort
(
a
,
new
Transaction
.
WhoOrder
());
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
StdOut
.
println
(
a
[
i
]);
StdOut
.
println
();
StdOut
.
println
(
"Sort by amount"
);
Arrays
.
sort
(
a
,
new
Transaction
.
HowMuchOrder
());
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
StdOut
.
println
(
a
[
i
]);
StdOut
.
println
();
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/TransitiveClosure.java
edu/princeton/cs/algs4/TransitiveClosure.java
/******************************************************************************
* Compilation: javac TransitiveClosure.java
* Execution: java TransitiveClosure filename.txt
* Dependencies: Digraph.java DepthFirstDirectedPaths.java In.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/42digraph/tinyDG.txt
*
* Compute transitive closure of a digraph and support
* reachability queries.
*
* Preprocessing time: O(V(E + V)) time.
* Query time: O(1).
* Space: O(V^2).
*
* % java TransitiveClosure tinyDG.txt
* 0 1 2 3 4 5 6 7 8 9 10 11 12
* --------------------------------------------
* 0: T T T T T T
* 1: T
* 2: T T T T T T
* 3: T T T T T T
* 4: T T T T T T
* 5: T T T T T T
* 6: T T T T T T T T T T T
* 7: T T T T T T T T T T T T T
* 8: T T T T T T T T T T T T T
* 9: T T T T T T T T T T
* 10: T T T T T T T T T T
* 11: T T T T T T T T T T
* 12: T T T T T T T T T T
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
TransitiveClosure} class represents a data type for
* computing the transitive closure of a digraph.
*
* This implementation runs depth-first search from each vertex.
* The constructor takes Θ(V(V + E))
* in the worst case, where V is the number of vertices and
* E is the number of edges.
* Each instance method takes Θ(1) time.
* It uses Θ(V2) extra space (not including the digraph).
*
* For large digraphs, you may want to consider a more sophisticated algorithm.
* Nuutila proposes two
* algorithm for the problem (based on strong components and an interval representation)
* that runs in Θ(E + V) time on typical digraphs.
*
* For additional documentation,
* see Section 4.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
TransitiveClosure
{
private
DirectedDFS
[]
tc
;
// tc[v] = reachable from v
/**
* Computes the transitive closure of the digraph {
@code
G}.
*
@param
G the digraph
*/
public
TransitiveClosure
(
Digraph
G
)
{
tc
=
new
DirectedDFS
[
G
.
V
()];
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
tc
[
v
]
=
new
DirectedDFS
(
G
,
v
);
}
/**
* Is there a directed path from vertex {
@code
v} to vertex {
@code
w} in the digraph?
*
@param
v the source vertex
*
@param
w the target vertex
*
@return
{
@code
true} if there is a directed path from {
@code
v} to {
@code
w},
* {
@code
false} otherwise
*
@throws
IllegalArgumentException unless {
@code
0 <= v < V}
*
@throws
IllegalArgumentException unless {
@code
0 <= w < V}
*/
public
boolean
reachable
(
int
v
,
int
w
)
{
validateVertex
(
v
);
validateVertex
(
w
);
return
tc
[
v
].
marked
(
w
);
}
// throw an IllegalArgumentException unless {@code 0 <= v < V}
private
void
validateVertex
(
int
v
)
{
int
V
=
tc
.
length
;
if
(
v
<
0
||
v
>=
V
)
throw
new
IllegalArgumentException
(
“vertex ”
+
v
+
” is not between 0 and ”
+
(
V
–
1
));
}
/**
* Unit tests the {
@code
TransitiveClosure} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
Digraph
G
=
new
Digraph
(
in
);
TransitiveClosure
tc
=
new
TransitiveClosure
(
G
);
// print header
StdOut
.
print
(
” ”
);
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
StdOut
.
printf
(
"%3d"
,
v
);
StdOut
.
println
();
StdOut
.
println
(
"--------------------------------------------"
);
// print transitive closure
for
(
int
v
=
0
;
v
<
G
.
V
();
v
++
)
{
StdOut
.
printf
(
"%3d: "
,
v
);
for
(
int
w
=
0
;
w
<
G
.
V
();
w
++
)
{
if
(
tc
.
reachable
(
v
,
w
))
StdOut
.
printf
(
" T"
);
else
StdOut
.
printf
(
" "
);
}
StdOut
.
println
();
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/TrieSET.java
edu/princeton/cs/algs4/TrieSET.java
/******************************************************************************
* Compilation: javac TrieSET.java
* Execution: java TrieSET < words.txt
* Dependencies: StdIn.java
* Data files: https://algs4.cs.princeton.edu/52trie/shellsST.txt
*
* An set for extended ASCII strings, implemented using a 256-way trie.
*
* Sample client reads in a list of words from standard input and
* prints out each word, removing any duplicates.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
import
java
.
util
.
Iterator
;
/**
* The {
@code
TrieSET} class represents an ordered set of strings over
* the extended ASCII alphabet.
* It supports the usual add, contains, and delete
* methods. It also provides character-based methods for finding the string
* in the set that is the longest prefix of a given prefix,
* finding all strings in the set that start with a given prefix,
* and finding all strings in the set that match a given pattern.
*
* This implementation uses a 256-way trie.
* The add, contains, delete, and
* longest prefix methods take time proportional to the length
* of the key (in the worst case). Construction takes constant time.
*
* For additional documentation, see
* Section 5.2 of
* Algorithms in Java, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
TrieSET
implements
Iterable
<
String
>
{
private
static
final
int
R
=
256
;
// extended ASCII
private
Node
root
;
// root of trie
private
int
n
;
// number of keys in trie
// R-way trie node
private
static
class
Node
{
private
Node
[]
next
=
new
Node
[
R
];
private
boolean
isString
;
}
/**
* Initializes an empty set of strings.
*/
public
TrieSET
()
{
}
/**
* Does the set contain the given key?
*
@param
key the key
*
@return
{
@code
true} if the set contains {
@code
key} and
* {
@code
false} otherwise
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
boolean
contains
(
String
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to contains() is null”
);
Node
x
=
get
(
root
,
key
,
0
);
if
(
x
==
null
)
return
false
;
return
x
.
isString
;
}
private
Node
get
(
Node
x
,
String
key
,
int
d
)
{
if
(
x
==
null
)
return
null
;
if
(
d
==
key
.
length
())
return
x
;
char
c
=
key
.
charAt
(
d
);
return
get
(
x
.
next
[
c
],
key
,
d
+
1
);
}
/**
* Adds the key to the set if it is not already present.
*
@param
key the key to add
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
add
(
String
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to add() is null”
);
root
=
add
(
root
,
key
,
0
);
}
private
Node
add
(
Node
x
,
String
key
,
int
d
)
{
if
(
x
==
null
)
x
=
new
Node
();
if
(
d
==
key
.
length
())
{
if
(
!
x
.
isString
)
n
++
;
x
.
isString
=
true
;
}
else
{
char
c
=
key
.
charAt
(
d
);
x
.
next
[
c
]
=
add
(
x
.
next
[
c
],
key
,
d
+
1
);
}
return
x
;
}
/**
* Returns the number of strings in the set.
*
@return
the number of strings in the set
*/
public
int
size
()
{
return
n
;
}
/**
* Is the set empty?
*
@return
{
@code
true} if the set is empty, and {
@code
false} otherwise
*/
public
boolean
isEmpty
()
{
return
size
()
==
0
;
}
/**
* Returns all of the keys in the set, as an iterator.
* To iterate over all of the keys in a set named {
@code
set}, use the
* foreach notation: {
@code
for (Key key : set)}.
*
@return
an iterator to all of the keys in the set
*/
public
Iterator
<
String
>
iterator
()
{
return
keysWithPrefix
(
“”
).
iterator
();
}
/**
* Returns all of the keys in the set that start with {
@code
prefix}.
*
@param
prefix the prefix
*
@return
all of the keys in the set that start with {
@code
prefix},
* as an iterable
*/
public
Iterable
<
String
>
keysWithPrefix
(
String
prefix
)
{
Queue
<
String
>
results
=
new
Queue
<
String
>
();
Node
x
=
get
(
root
,
prefix
,
0
);
collect
(
x
,
new
StringBuilder
(
prefix
),
results
);
return
results
;
}
private
void
collect
(
Node
x
,
StringBuilder
prefix
,
Queue
<
String
>
results
)
{
if
(
x
==
null
)
return
;
if
(
x
.
isString
)
results
.
enqueue
(
prefix
.
toString
());
for
(
char
c
=
0
;
c
<
R
;
c
++
)
{
prefix
.
append
(
c
);
collect
(
x
.
next
[
c
],
prefix
,
results
);
prefix
.
deleteCharAt
(
prefix
.
length
()
-
1
);
}
}
/**
* Returns all of the keys in the set that match {
@code
pattern},
* where . symbol is treated as a wildcard character.
*
@param
pattern the pattern
*
@return
all of the keys in the set that match {
@code
pattern},
* as an iterable, where . is treated as a wildcard character.
*/
public
Iterable
<
String
>
keysThatMatch
(
String
pattern
)
{
Queue
<
String
>
results
=
new
Queue
<
String
>
();
StringBuilder
prefix
=
new
StringBuilder
();
collect
(
root
,
prefix
,
pattern
,
results
);
return
results
;
}
private
void
collect
(
Node
x
,
StringBuilder
prefix
,
String
pattern
,
Queue
<
String
>
results
)
{
if
(
x
==
null
)
return
;
int
d
=
prefix
.
length
();
if
(
d
==
pattern
.
length
()
&&
x
.
isString
)
results
.
enqueue
(
prefix
.
toString
());
if
(
d
==
pattern
.
length
())
return
;
char
c
=
pattern
.
charAt
(
d
);
if
(
c
==
‘.’
)
{
for
(
char
ch
=
0
;
ch
<
R
;
ch
++
)
{
prefix
.
append
(
ch
);
collect
(
x
.
next
[
ch
],
prefix
,
pattern
,
results
);
prefix
.
deleteCharAt
(
prefix
.
length
()
-
1
);
}
}
else
{
prefix
.
append
(
c
);
collect
(
x
.
next
[
c
],
prefix
,
pattern
,
results
);
prefix
.
deleteCharAt
(
prefix
.
length
()
-
1
);
}
}
/**
* Returns the string in the set that is the longest prefix of {
@code
query},
* or {
@code
null}, if no such string.
*
@param
query the query string
*
@return
the string in the set that is the longest prefix of {
@code
query},
* or {
@code
null} if no such string
*
@throws
IllegalArgumentException if {
@code
query} is {
@code
null}
*/
public
String
longestPrefixOf
(
String
query
)
{
if
(
query
==
null
)
throw
new
IllegalArgumentException
(
"argument to longestPrefixOf() is null"
);
int
length
=
longestPrefixOf
(
root
,
query
,
0
,
-
1
);
if
(
length
==
-
1
)
return
null
;
return
query
.
substring
(
0
,
length
);
}
// returns the length of the longest string key in the subtrie
// rooted at x that is a prefix of the query string,
// assuming the first d character match and we have already
// found a prefix match of length length
private
int
longestPrefixOf
(
Node
x
,
String
query
,
int
d
,
int
length
)
{
if
(
x
==
null
)
return
length
;
if
(
x
.
isString
)
length
=
d
;
if
(
d
==
query
.
length
())
return
length
;
char
c
=
query
.
charAt
(
d
);
return
longestPrefixOf
(
x
.
next
[
c
],
query
,
d
+
1
,
length
);
}
/**
* Removes the key from the set if the key is present.
*
@param
key the key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
delete
(
String
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
"argument to delete() is null"
);
root
=
delete
(
root
,
key
,
0
);
}
private
Node
delete
(
Node
x
,
String
key
,
int
d
)
{
if
(
x
==
null
)
return
null
;
if
(
d
==
key
.
length
())
{
if
(
x
.
isString
)
n
--
;
x
.
isString
=
false
;
}
else
{
char
c
=
key
.
charAt
(
d
);
x
.
next
[
c
]
=
delete
(
x
.
next
[
c
],
key
,
d
+
1
);
}
// remove subtrie rooted at x if it is completely empty
if
(
x
.
isString
)
return
x
;
for
(
int
c
=
0
;
c
<
R
;
c
++
)
if
(
x
.
next
[
c
]
!=
null
)
return
x
;
return
null
;
}
/**
* Unit tests the {
@code
TrieSET} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
TrieSET
set
=
new
TrieSET
();
while
(
!
StdIn
.
isEmpty
())
{
String
key
=
StdIn
.
readString
();
set
.
add
(
key
);
}
// print results
if
(
set
.
size
()
<
100
)
{
StdOut
.
println
(
"keys(\"\"):"
);
for
(
String
key
:
set
)
{
StdOut
.
println
(
key
);
}
StdOut
.
println
();
}
StdOut
.
println
(
"longestPrefixOf(\"shellsort\"):"
);
StdOut
.
println
(
set
.
longestPrefixOf
(
"shellsort"
));
StdOut
.
println
();
StdOut
.
println
(
"longestPrefixOf(\"xshellsort\"):"
);
StdOut
.
println
(
set
.
longestPrefixOf
(
"xshellsort"
));
StdOut
.
println
();
StdOut
.
println
(
"keysWithPrefix(\"shor\"):"
);
for
(
String
s
:
set
.
keysWithPrefix
(
"shor"
))
StdOut
.
println
(
s
);
StdOut
.
println
();
StdOut
.
println
(
"keysWithPrefix(\"shortening\"):"
);
for
(
String
s
:
set
.
keysWithPrefix
(
"shortening"
))
StdOut
.
println
(
s
);
StdOut
.
println
();
StdOut
.
println
(
"keysThatMatch(\".he.l.\"):"
);
for
(
String
s
:
set
.
keysThatMatch
(
".he.l."
))
StdOut
.
println
(
s
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/TrieST.java
edu/princeton/cs/algs4/TrieST.java
/******************************************************************************
* Compilation: javac TrieST.java
* Execution: java TrieST < words.txt
* Dependencies: StdIn.java
* Data files: https://algs4.cs.princeton.edu/52trie/shellsST.txt
*
* A string symbol table for extended ASCII strings, implemented
* using a 256-way trie.
*
* % java TrieST < shellsST.txt
* by 4
* sea 6
* sells 1
* she 0
* shells 3
* shore 7
* the 5
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
TrieST} class represents an symbol table of key-value
* pairs, with string keys and generic values.
* It supports the usual put, get, contains,
* delete, size, and is-empty methods.
* It also provides character-based methods for finding the string
* in the symbol table that is the longest prefix of a given prefix,
* finding all strings in the symbol table that start with a given prefix,
* and finding all strings in the symbol table that match a given pattern.
* A symbol table implements the associative array abstraction:
* when associating a value with a key that is already in the symbol table,
* the convention is to replace the old value with the new value.
* Unlike {
@link
java.util.Map}, this class uses the convention that
* values cannot be {
@code
null}—setting the
* value associated with a key to {
@code
null} is equivalent to deleting the key
* from the symbol table.
*
* This implementation uses a 256-way trie.
* The put, contains, delete, and
* longest prefix operations take time proportional to the length
* of the key (in the worst case). Construction takes constant time.
* The size, and is-empty operations take constant time.
* Construction takes constant time.
*
* For additional documentation, see Section 5.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*/
public
class
TrieST
<
Value
>
{
private
static
final
int
R
=
256
;
// extended ASCII
private
Node
root
;
// root of trie
private
int
n
;
// number of keys in trie
// R-way trie node
private
static
class
Node
{
private
Object
val
;
private
Node
[]
next
=
new
Node
[
R
];
}
/**
* Initializes an empty string symbol table.
*/
public
TrieST
()
{
}
/**
* Returns the value associated with the given key.
*
@param
key the key
*
@return
the value associated with the given key if the key is in the symbol table
* and {
@code
null} if the key is not in the symbol table
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
Value
get
(
String
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to get() is null”
);
Node
x
=
get
(
root
,
key
,
0
);
if
(
x
==
null
)
return
null
;
return
(
Value
)
x
.
val
;
}
/**
* Does this symbol table contain the given key?
*
@param
key the key
*
@return
{
@code
true} if this symbol table contains {
@code
key} and
* {
@code
false} otherwise
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
boolean
contains
(
String
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“argument to contains() is null”
);
return
get
(
key
)
!=
null
;
}
private
Node
get
(
Node
x
,
String
key
,
int
d
)
{
if
(
x
==
null
)
return
null
;
if
(
d
==
key
.
length
())
return
x
;
char
c
=
key
.
charAt
(
d
);
return
get
(
x
.
next
[
c
],
key
,
d
+
1
);
}
/**
* Inserts the key-value pair into the symbol table, overwriting the old value
* with the new value if the key is already in the symbol table.
* If the value is {
@code
null}, this effectively deletes the key from the symbol table.
*
@param
key the key
*
@param
val the value
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
put
(
String
key
,
Value
val
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
“first argument to put() is null”
);
if
(
val
==
null
)
delete
(
key
);
else
root
=
put
(
root
,
key
,
val
,
0
);
}
private
Node
put
(
Node
x
,
String
key
,
Value
val
,
int
d
)
{
if
(
x
==
null
)
x
=
new
Node
();
if
(
d
==
key
.
length
())
{
if
(
x
.
val
==
null
)
n
++
;
x
.
val
=
val
;
return
x
;
}
char
c
=
key
.
charAt
(
d
);
x
.
next
[
c
]
=
put
(
x
.
next
[
c
],
key
,
val
,
d
+
1
);
return
x
;
}
/**
* Returns the number of key-value pairs in this symbol table.
*
@return
the number of key-value pairs in this symbol table
*/
public
int
size
()
{
return
n
;
}
/**
* Is this symbol table empty?
*
@return
{
@code
true} if this symbol table is empty and {
@code
false} otherwise
*/
public
boolean
isEmpty
()
{
return
size
()
==
0
;
}
/**
* Returns all keys in the symbol table as an {
@code
Iterable}.
* To iterate over all of the keys in the symbol table named {
@code
st},
* use the foreach notation: {
@code
for (Key key : st.keys())}.
*
@return
all keys in the symbol table as an {
@code
Iterable}
*/
public
Iterable
<
String
>
keys
()
{
return
keysWithPrefix
(
“”
);
}
/**
* Returns all of the keys in the set that start with {
@code
prefix}.
*
@param
prefix the prefix
*
@return
all of the keys in the set that start with {
@code
prefix},
* as an iterable
*/
public
Iterable
<
String
>
keysWithPrefix
(
String
prefix
)
{
Queue
<
String
>
results
=
new
Queue
<
String
>
();
Node
x
=
get
(
root
,
prefix
,
0
);
collect
(
x
,
new
StringBuilder
(
prefix
),
results
);
return
results
;
}
private
void
collect
(
Node
x
,
StringBuilder
prefix
,
Queue
<
String
>
results
)
{
if
(
x
==
null
)
return
;
if
(
x
.
val
!=
null
)
results
.
enqueue
(
prefix
.
toString
());
for
(
char
c
=
0
;
c
<
R
;
c
++
)
{
prefix
.
append
(
c
);
collect
(
x
.
next
[
c
],
prefix
,
results
);
prefix
.
deleteCharAt
(
prefix
.
length
()
-
1
);
}
}
/**
* Returns all of the keys in the symbol table that match {
@code
pattern},
* where . symbol is treated as a wildcard character.
*
@param
pattern the pattern
*
@return
all of the keys in the symbol table that match {
@code
pattern},
* as an iterable, where . is treated as a wildcard character.
*/
public
Iterable
<
String
>
keysThatMatch
(
String
pattern
)
{
Queue
<
String
>
results
=
new
Queue
<
String
>
();
collect
(
root
,
new
StringBuilder
(),
pattern
,
results
);
return
results
;
}
private
void
collect
(
Node
x
,
StringBuilder
prefix
,
String
pattern
,
Queue
<
String
>
results
)
{
if
(
x
==
null
)
return
;
int
d
=
prefix
.
length
();
if
(
d
==
pattern
.
length
()
&&
x
.
val
!=
null
)
results
.
enqueue
(
prefix
.
toString
());
if
(
d
==
pattern
.
length
())
return
;
char
c
=
pattern
.
charAt
(
d
);
if
(
c
==
‘.’
)
{
for
(
char
ch
=
0
;
ch
<
R
;
ch
++
)
{
prefix
.
append
(
ch
);
collect
(
x
.
next
[
ch
],
prefix
,
pattern
,
results
);
prefix
.
deleteCharAt
(
prefix
.
length
()
-
1
);
}
}
else
{
prefix
.
append
(
c
);
collect
(
x
.
next
[
c
],
prefix
,
pattern
,
results
);
prefix
.
deleteCharAt
(
prefix
.
length
()
-
1
);
}
}
/**
* Returns the string in the symbol table that is the longest prefix of {
@code
query},
* or {
@code
null}, if no such string.
*
@param
query the query string
*
@return
the string in the symbol table that is the longest prefix of {
@code
query},
* or {
@code
null} if no such string
*
@throws
IllegalArgumentException if {
@code
query} is {
@code
null}
*/
public
String
longestPrefixOf
(
String
query
)
{
if
(
query
==
null
)
throw
new
IllegalArgumentException
(
"argument to longestPrefixOf() is null"
);
int
length
=
longestPrefixOf
(
root
,
query
,
0
,
-
1
);
if
(
length
==
-
1
)
return
null
;
else
return
query
.
substring
(
0
,
length
);
}
// returns the length of the longest string key in the subtrie
// rooted at x that is a prefix of the query string,
// assuming the first d character match and we have already
// found a prefix match of given length (-1 if no such match)
private
int
longestPrefixOf
(
Node
x
,
String
query
,
int
d
,
int
length
)
{
if
(
x
==
null
)
return
length
;
if
(
x
.
val
!=
null
)
length
=
d
;
if
(
d
==
query
.
length
())
return
length
;
char
c
=
query
.
charAt
(
d
);
return
longestPrefixOf
(
x
.
next
[
c
],
query
,
d
+
1
,
length
);
}
/**
* Removes the key from the set if the key is present.
*
@param
key the key
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
delete
(
String
key
)
{
if
(
key
==
null
)
throw
new
IllegalArgumentException
(
"argument to delete() is null"
);
root
=
delete
(
root
,
key
,
0
);
}
private
Node
delete
(
Node
x
,
String
key
,
int
d
)
{
if
(
x
==
null
)
return
null
;
if
(
d
==
key
.
length
())
{
if
(
x
.
val
!=
null
)
n
--
;
x
.
val
=
null
;
}
else
{
char
c
=
key
.
charAt
(
d
);
x
.
next
[
c
]
=
delete
(
x
.
next
[
c
],
key
,
d
+
1
);
}
// remove subtrie rooted at x if it is completely empty
if
(
x
.
val
!=
null
)
return
x
;
for
(
int
c
=
0
;
c
<
R
;
c
++
)
if
(
x
.
next
[
c
]
!=
null
)
return
x
;
return
null
;
}
/**
* Unit tests the {
@code
TrieST} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// build symbol table from standard input
TrieST
<
Integer
>
st
=
new
TrieST
<
Integer
>
();
for
(
int
i
=
0
;
!
StdIn
.
isEmpty
();
i
++
)
{
String
key
=
StdIn
.
readString
();
st
.
put
(
key
,
i
);
}
// print results
if
(
st
.
size
()
<
100
)
{
StdOut
.
println
(
"keys(\"\"):"
);
for
(
String
key
:
st
.
keys
())
{
StdOut
.
println
(
key
+
" "
+
st
.
get
(
key
));
}
StdOut
.
println
();
}
StdOut
.
println
(
"longestPrefixOf(\"shellsort\"):"
);
StdOut
.
println
(
st
.
longestPrefixOf
(
"shellsort"
));
StdOut
.
println
();
StdOut
.
println
(
"longestPrefixOf(\"quicksort\"):"
);
StdOut
.
println
(
st
.
longestPrefixOf
(
"quicksort"
));
StdOut
.
println
();
StdOut
.
println
(
"keysWithPrefix(\"shor\"):"
);
for
(
String
s
:
st
.
keysWithPrefix
(
"shor"
))
StdOut
.
println
(
s
);
StdOut
.
println
();
StdOut
.
println
(
"keysThatMatch(\".he.l.\"):"
);
for
(
String
s
:
st
.
keysThatMatch
(
".he.l."
))
StdOut
.
println
(
s
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/TST.java
edu/princeton/cs/algs4/TST.java
/******************************************************************************
* Compilation: javac TST.java
* Execution: java TST < words.txt
* Dependencies: StdIn.java
* Data files: https://algs4.cs.princeton.edu/52trie/shellsST.txt
*
* Symbol table with string keys, implemented using a ternary search
* trie (TST).
*
*
* % java TST < shellsST.txt
* keys(""):
* by 4
* sea 6
* sells 1
* she 0
* shells 3
* shore 7
* the 5
*
* longestPrefixOf("shellsort"):
* shells
*
* keysWithPrefix("shor"):
* shore
*
* keysThatMatch(".he.l."):
* shells
*
* % java TST
* theory the now is the time for all good men
*
* Remarks
* --------
* - can't use a key that is the empty string ""
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
TST} class represents an symbol table of key-value
* pairs, with string keys and generic values.
* It supports the usual put, get, contains,
* delete, size, and is-empty methods.
* It also provides character-based methods for finding the string
* in the symbol table that is the longest prefix of a given prefix,
* finding all strings in the symbol table that start with a given prefix,
* and finding all strings in the symbol table that match a given pattern.
* A symbol table implements the associative array abstraction:
* when associating a value with a key that is already in the symbol table,
* the convention is to replace the old value with the new value.
* Unlike {
@link
java.util.Map}, this class uses the convention that
* values cannot be {
@code
null}—setting the
* value associated with a key to {
@code
null} is equivalent to deleting the key
* from the symbol table.
*
* This implementation uses a ternary search trie.
*
* For additional documentation, see Section 5.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*/
public
class
TST
<
Value
>
{
private
int
n
;
// size
private
Node
<
Value
>
root
;
// root of TST
private
static
class
Node
<
Value
>
{
private
char
c
;
// character
private
Node
<
Value
>
left
,
mid
,
right
;
// left, middle, and right subtries
private
Value
val
;
// value associated with string
}
/**
* Initializes an empty string symbol table.
*/
public
TST
()
{
}
/**
* Returns the number of key-value pairs in this symbol table.
*
@return
the number of key-value pairs in this symbol table
*/
public
int
size
()
{
return
n
;
}
/**
* Does this symbol table contain the given key?
*
@param
key the key
*
@return
{
@code
true} if this symbol table contains {
@code
key} and
* {
@code
false} otherwise
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
boolean
contains
(
String
key
)
{
if
(
key
==
null
)
{
throw
new
IllegalArgumentException
(
“argument to contains() is null”
);
}
return
get
(
key
)
!=
null
;
}
/**
* Returns the value associated with the given key.
*
@param
key the key
*
@return
the value associated with the given key if the key is in the symbol table
* and {
@code
null} if the key is not in the symbol table
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
Value
get
(
String
key
)
{
if
(
key
==
null
)
{
throw
new
IllegalArgumentException
(
“calls get() with null argument”
);
}
if
(
key
.
length
()
==
0
)
throw
new
IllegalArgumentException
(
“key must have length >= 1”
);
Node
<
Value
>
x
=
get
(
root
,
key
,
0
);
if
(
x
==
null
)
return
null
;
return
x
.
val
;
}
// return subtrie corresponding to given key
private
Node
<
Value
>
get
(
Node
<
Value
>
x
,
String
key
,
int
d
)
{
if
(
x
==
null
)
return
null
;
if
(
key
.
length
()
==
0
)
throw
new
IllegalArgumentException
(
“key must have length >= 1”
);
char
c
=
key
.
charAt
(
d
);
if
(
c
<
x
.
c
)
return
get
(
x
.
left
,
key
,
d
);
else
if
(
c
>
x
.
c
)
return
get
(
x
.
right
,
key
,
d
);
else
if
(
d
<
key
.
length
()
-
1
)
return
get
(
x
.
mid
,
key
,
d
+
1
);
else
return
x
;
}
/**
* Inserts the key-value pair into the symbol table, overwriting the old value
* with the new value if the key is already in the symbol table.
* If the value is {
@code
null}, this effectively deletes the key from the symbol table.
*
@param
key the key
*
@param
val the value
*
@throws
IllegalArgumentException if {
@code
key} is {
@code
null}
*/
public
void
put
(
String
key
,
Value
val
)
{
if
(
key
==
null
)
{
throw
new
IllegalArgumentException
(
"calls put() with null key"
);
}
if
(
!
contains
(
key
))
n
++
;
else
if
(
val
==
null
)
n
--
;
// delete existing key
root
=
put
(
root
,
key
,
val
,
0
);
}
private
Node
<
Value
>
put
(
Node
<
Value
>
x
,
String
key
,
Value
val
,
int
d
)
{
char
c
=
key
.
charAt
(
d
);
if
(
x
==
null
)
{
x
=
new
Node
<
Value
>
();
x
.
c
=
c
;
}
if
(
c
<
x
.
c
)
x
.
left
=
put
(
x
.
left
,
key
,
val
,
d
);
else
if
(
c
>
x
.
c
)
x
.
right
=
put
(
x
.
right
,
key
,
val
,
d
);
else
if
(
d
<
key
.
length
()
-
1
)
x
.
mid
=
put
(
x
.
mid
,
key
,
val
,
d
+
1
);
else
x
.
val
=
val
;
return
x
;
}
/**
* Returns the string in the symbol table that is the longest prefix of {
@code
query},
* or {
@code
null}, if no such string.
*
@param
query the query string
*
@return
the string in the symbol table that is the longest prefix of {
@code
query},
* or {
@code
null} if no such string
*
@throws
IllegalArgumentException if {
@code
query} is {
@code
null}
*/
public
String
longestPrefixOf
(
String
query
)
{
if
(
query
==
null
)
{
throw
new
IllegalArgumentException
(
"calls longestPrefixOf() with null argument"
);
}
if
(
query
.
length
()
==
0
)
return
null
;
int
length
=
0
;
Node
<
Value
>
x
=
root
;
int
i
=
0
;
while
(
x
!=
null
&&
i
<
query
.
length
())
{
char
c
=
query
.
charAt
(
i
);
if
(
c
<
x
.
c
)
x
=
x
.
left
;
else
if
(
c
>
x
.
c
)
x
=
x
.
right
;
else
{
i
++
;
if
(
x
.
val
!=
null
)
length
=
i
;
x
=
x
.
mid
;
}
}
return
query
.
substring
(
0
,
length
);
}
/**
* Returns all keys in the symbol table as an {
@code
Iterable}.
* To iterate over all of the keys in the symbol table named {
@code
st},
* use the foreach notation: {
@code
for (Key key : st.keys())}.
*
@return
all keys in the symbol table as an {
@code
Iterable}
*/
public
Iterable
<
String
>
keys
()
{
Queue
<
String
>
queue
=
new
Queue
<
String
>
();
collect
(
root
,
new
StringBuilder
(),
queue
);
return
queue
;
}
/**
* Returns all of the keys in the set that start with {
@code
prefix}.
*
@param
prefix the prefix
*
@return
all of the keys in the set that start with {
@code
prefix},
* as an iterable
*
@throws
IllegalArgumentException if {
@code
prefix} is {
@code
null}
*/
public
Iterable
<
String
>
keysWithPrefix
(
String
prefix
)
{
if
(
prefix
==
null
)
{
throw
new
IllegalArgumentException
(
“calls keysWithPrefix() with null argument”
);
}
Queue
<
String
>
queue
=
new
Queue
<
String
>
();
Node
<
Value
>
x
=
get
(
root
,
prefix
,
0
);
if
(
x
==
null
)
return
queue
;
if
(
x
.
val
!=
null
)
queue
.
enqueue
(
prefix
);
collect
(
x
.
mid
,
new
StringBuilder
(
prefix
),
queue
);
return
queue
;
}
// all keys in subtrie rooted at x with given prefix
private
void
collect
(
Node
<
Value
>
x
,
StringBuilder
prefix
,
Queue
<
String
>
queue
)
{
if
(
x
==
null
)
return
;
collect
(
x
.
left
,
prefix
,
queue
);
if
(
x
.
val
!=
null
)
queue
.
enqueue
(
prefix
.
toString
()
+
x
.
c
);
collect
(
x
.
mid
,
prefix
.
append
(
x
.
c
),
queue
);
prefix
.
deleteCharAt
(
prefix
.
length
()
–
1
);
collect
(
x
.
right
,
prefix
,
queue
);
}
/**
* Returns all of the keys in the symbol table that match {
@code
pattern},
* where . symbol is treated as a wildcard character.
*
@param
pattern the pattern
*
@return
all of the keys in the symbol table that match {
@code
pattern},
* as an iterable, where . is treated as a wildcard character.
*/
public
Iterable
<
String
>
keysThatMatch
(
String
pattern
)
{
Queue
<
String
>
queue
=
new
Queue
<
String
>
();
collect
(
root
,
new
StringBuilder
(),
0
,
pattern
,
queue
);
return
queue
;
}
private
void
collect
(
Node
<
Value
>
x
,
StringBuilder
prefix
,
int
i
,
String
pattern
,
Queue
<
String
>
queue
)
{
if
(
x
==
null
)
return
;
char
c
=
pattern
.
charAt
(
i
);
if
(
c
==
‘.’
||
c
<
x
.
c
)
collect
(
x
.
left
,
prefix
,
i
,
pattern
,
queue
);
if
(
c
==
'.'
||
c
==
x
.
c
)
{
if
(
i
==
pattern
.
length
()
-
1
&&
x
.
val
!=
null
)
queue
.
enqueue
(
prefix
.
toString
()
+
x
.
c
);
if
(
i
<
pattern
.
length
()
-
1
)
{
collect
(
x
.
mid
,
prefix
.
append
(
x
.
c
),
i
+
1
,
pattern
,
queue
);
prefix
.
deleteCharAt
(
prefix
.
length
()
-
1
);
}
}
if
(
c
==
'.'
||
c
>
x
.
c
)
collect
(
x
.
right
,
prefix
,
i
,
pattern
,
queue
);
}
/**
* Unit tests the {
@code
TST} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// build symbol table from standard input
TST
<
Integer
>
st
=
new
TST
<
Integer
>
();
for
(
int
i
=
0
;
!
StdIn
.
isEmpty
();
i
++
)
{
String
key
=
StdIn
.
readString
();
st
.
put
(
key
,
i
);
}
// print results
if
(
st
.
size
()
<
100
)
{
StdOut
.
println
(
"keys(\"\"):"
);
for
(
String
key
:
st
.
keys
())
{
StdOut
.
println
(
key
+
" "
+
st
.
get
(
key
));
}
StdOut
.
println
();
}
StdOut
.
println
(
"longestPrefixOf(\"shellsort\"):"
);
StdOut
.
println
(
st
.
longestPrefixOf
(
"shellsort"
));
StdOut
.
println
();
StdOut
.
println
(
"longestPrefixOf(\"shell\"):"
);
StdOut
.
println
(
st
.
longestPrefixOf
(
"shell"
));
StdOut
.
println
();
StdOut
.
println
(
"keysWithPrefix(\"shor\"):"
);
for
(
String
s
:
st
.
keysWithPrefix
(
"shor"
))
StdOut
.
println
(
s
);
StdOut
.
println
();
StdOut
.
println
(
"keysThatMatch(\".he.l.\"):"
);
for
(
String
s
:
st
.
keysThatMatch
(
".he.l."
))
StdOut
.
println
(
s
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/TwoPersonZeroSumGame.java
edu/princeton/cs/algs4/TwoPersonZeroSumGame.java
/******************************************************************************
* Compilation: javac TwoPersonZeroSumGame.java
* Execution: java TwoPersonZeroSumGame m n
* Dependencies: LinearProgramming.java StdOut.java
*
* Solve an m-by-n two-person zero-sum game by reducing it to
* linear programming. Assuming A is a strictly positive payoff
* matrix, the optimal row and column player strategies are x* an y*,
* scaled to be probability distributions.
*
* (P) max y^T 1 (D) min 1^T x
* s.t A^T y <= 1 s.t A x >= 1
* y >= 0 x >= 0
*
* Row player is x, column player is y.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
TwoPersonZeroSumGame} class represents a data type for
* computing optimal row and column strategies to two-person zero-sum games.
*
* This implementation solves an m-by-n two-person
* zero-sum game by reducing it to a linear programming problem.
* Assuming the payoff matrix A is strictly positive, the
* optimal row and column player strategies x* and y* are obtained
* by solving the following primal and dual pair of linear programs,
* scaling the results to be probability distributions.
*
* (P) max y^T 1 (D) min 1^T x * s.t A^T y ≤ 1 s.t A x ≥ 1 * y ≤ 0 x ≥ 0 *
*
* If the payoff matrix A has any negative entries, we add
* the same constant to every entry so that every entry is positive.
* This increases the value of the game by that constant, but does not
* change solutions to the two-person zero-sum game.
*
* This implementation is not suitable for large inputs, as it calls
* a bare-bones linear programming solver that is neither fast nor
* robust with respect to floating-point roundoff error.
*
* For additional documentation, see
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
TwoPersonZeroSumGame
{
private
static
final
double
EPSILON
=
1E-8
;
private
final
int
m
;
// number of rows
private
final
int
n
;
// number of columns
private
LinearProgramming
lp
;
// linear program solver
private
double
constant
;
// constant added to each entry in payoff matrix
// (0 if all entries are strictly positive)
/**
* Determines an optimal solution to the two-sum zero-sum game
* with the specified payoff matrix.
*
*
@param
payoff the m-by-n payoff matrix
*/
public
TwoPersonZeroSumGame
(
double
[][]
payoff
)
{
m
=
payoff
.
length
;
n
=
payoff
[
0
].
length
;
double
[]
c
=
new
double
[
n
];
double
[]
b
=
new
double
[
m
];
double
[][]
A
=
new
double
[
m
][
n
];
for
(
int
i
=
0
;
i
<
m
;
i
++
)
b
[
i
]
=
1.0
;
for
(
int
j
=
0
;
j
<
n
;
j
++
)
c
[
j
]
=
1.0
;
// find smallest entry
constant
=
Double
.
POSITIVE_INFINITY
;
for
(
int
i
=
0
;
i
<
m
;
i
++
)
for
(
int
j
=
0
;
j
<
n
;
j
++
)
if
(
payoff
[
i
][
j
]
<
constant
)
constant
=
payoff
[
i
][
j
];
// add constant to every entry to make strictly positive
if
(
constant
<=
0
)
constant
=
-
constant
+
1
;
else
constant
=
0
;
for
(
int
i
=
0
;
i
<
m
;
i
++
)
for
(
int
j
=
0
;
j
<
n
;
j
++
)
A
[
i
][
j
]
=
payoff
[
i
][
j
]
+
constant
;
lp
=
new
LinearProgramming
(
A
,
b
,
c
);
assert
certifySolution
(
payoff
);
}
/**
* Returns the optimal value of this two-person zero-sum game.
*
*
@return
the optimal value of this two-person zero-sum game
*
*/
public
double
value
()
{
return
1.0
/
scale
()
-
constant
;
}
// sum of x[j]
private
double
scale
()
{
double
[]
x
=
lp
.
primal
();
double
sum
=
0.0
;
for
(
int
j
=
0
;
j
<
n
;
j
++
)
sum
+=
x
[
j
];
return
sum
;
}
/**
* Returns the optimal row strategy of this two-person zero-sum game.
*
*
@return
the optimal row strategy x of this two-person zero-sum game
*/
public
double
[]
row
()
{
double
scale
=
scale
();
double
[]
x
=
lp
.
primal
();
for
(
int
j
=
0
;
j
<
n
;
j
++
)
x
[
j
]
/=
scale
;
return
x
;
}
/**
* Returns the optimal column strategy of this two-person zero-sum game.
*
*
@return
the optimal column strategy y of this two-person zero-sum game
*/
public
double
[]
column
()
{
double
scale
=
scale
();
double
[]
y
=
lp
.
dual
();
for
(
int
i
=
0
;
i
<
m
;
i
++
)
y
[
i
]
/=
scale
;
return
y
;
}
/**************************************************************************
*
* The code below is solely for testing correctness of the data type.
*
**************************************************************************/
// is the row vector x primal feasible?
private
boolean
isPrimalFeasible
()
{
double
[]
x
=
row
();
double
sum
=
0.0
;
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
if
(
x
[
j
]
<
0
)
{
StdOut
.
println
(
"row vector not a probability distribution"
);
StdOut
.
printf
(
" x[%d] = %f\n"
,
j
,
x
[
j
]);
return
false
;
}
sum
+=
x
[
j
];
}
if
(
Math
.
abs
(
sum
-
1.0
)
>
EPSILON
)
{
StdOut
.
println
(
“row vector x[] is not a probability distribution”
);
StdOut
.
println
(
” sum = ”
+
sum
);
return
false
;
}
return
true
;
}
// is the column vector y dual feasible?
private
boolean
isDualFeasible
()
{
double
[]
y
=
column
();
double
sum
=
0.0
;
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
if
(
y
[
i
]
<
0
)
{
StdOut
.
println
(
"column vector y[] is not a probability distribution"
);
StdOut
.
printf
(
" y[%d] = %f\n"
,
i
,
y
[
i
]);
return
false
;
}
sum
+=
y
[
i
];
}
if
(
Math
.
abs
(
sum
-
1.0
)
>
EPSILON
)
{
StdOut
.
println
(
“column vector not a probability distribution”
);
StdOut
.
println
(
” sum = ”
+
sum
);
return
false
;
}
return
true
;
}
// is the solution a Nash equilibrium?
private
boolean
isNashEquilibrium
(
double
[][]
payoff
)
{
double
[]
x
=
row
();
double
[]
y
=
column
();
double
value
=
value
();
// given row player’s mixed strategy, find column player’s best pure strategy
double
opt1
=
Double
.
NEGATIVE_INFINITY
;
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
double
sum
=
0.0
;
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
sum
+=
payoff
[
i
][
j
]
*
x
[
j
];
}
if
(
sum
>
opt1
)
opt1
=
sum
;
}
if
(
Math
.
abs
(
opt1
–
value
)
>
EPSILON
)
{
StdOut
.
println
(
“Optimal value = ”
+
value
);
StdOut
.
println
(
“Optimal best response for column player = ”
+
opt1
);
return
false
;
}
// given column player’s mixed strategy, find row player’s best pure strategy
double
opt2
=
Double
.
POSITIVE_INFINITY
;
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
double
sum
=
0.0
;
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
sum
+=
payoff
[
i
][
j
]
*
y
[
i
];
}
if
(
sum
<
opt2
)
opt2
=
sum
;
}
if
(
Math
.
abs
(
opt2
-
value
)
>
EPSILON
)
{
StdOut
.
println
(
“Optimal value = ”
+
value
);
StdOut
.
println
(
“Optimal best response for row player = ”
+
opt2
);
return
false
;
}
return
true
;
}
private
boolean
certifySolution
(
double
[][]
payoff
)
{
return
isPrimalFeasible
()
&&
isDualFeasible
()
&&
isNashEquilibrium
(
payoff
);
}
private
static
void
test
(
String
description
,
double
[][]
payoff
)
{
StdOut
.
println
();
StdOut
.
println
(
description
);
StdOut
.
println
(
“————————————”
);
int
m
=
payoff
.
length
;
int
n
=
payoff
[
0
].
length
;
TwoPersonZeroSumGame
zerosum
=
new
TwoPersonZeroSumGame
(
payoff
);
double
[]
x
=
zerosum
.
row
();
double
[]
y
=
zerosum
.
column
();
StdOut
.
print
(
“x[] = [”
);
for
(
int
j
=
0
;
j
<
n
-
1
;
j
++
)
StdOut
.
printf
(
"%8.4f, "
,
x
[
j
]);
StdOut
.
printf
(
"%8.4f]\n"
,
x
[
n
-
1
]);
StdOut
.
print
(
"y[] = ["
);
for
(
int
i
=
0
;
i
<
m
-
1
;
i
++
)
StdOut
.
printf
(
"%8.4f, "
,
y
[
i
]);
StdOut
.
printf
(
"%8.4f]\n"
,
y
[
m
-
1
]);
StdOut
.
println
(
"value = "
+
zerosum
.
value
());
}
// row = { 4/7, 3/7 }, column = { 0, 4/7, 3/7 }, value = 20/7
// http://en.wikipedia.org/wiki/Zero-sum
private
static
void
test1
()
{
double
[][]
payoff
=
{
{
30
,
-
10
,
20
},
{
10
,
20
,
-
20
}
};
test
(
"wikipedia"
,
payoff
);
}
// skew-symmetric => value = 0
// Linear Programming by Chvatal, p. 230
private
static
void
test2
()
{
double
[][]
payoff
=
{
{
0
,
2
,
–
3
,
0
},
{
–
2
,
0
,
0
,
3
},
{
3
,
0
,
0
,
–
4
},
{
0
,
–
3
,
4
,
0
}
};
test
(
“Chvatal, p. 230”
,
payoff
);
}
// Linear Programming by Chvatal, p. 234
// row = { 0, 56/99, 40/99, 0, 0, 2/99, 0, 1/99 }
// column = { 28/99, 30/99, 21/99, 20/99 }
// value = 4/99
private
static
void
test3
()
{
double
[][]
payoff
=
{
{
0
,
2
,
–
3
,
0
},
{
–
2
,
0
,
0
,
3
},
{
3
,
0
,
0
,
–
4
},
{
0
,
–
3
,
4
,
0
},
{
0
,
0
,
–
3
,
3
},
{
–
2
,
2
,
0
,
0
},
{
3
,
–
3
,
0
,
0
},
{
0
,
0
,
4
,
–
4
}
};
test
(
“Chvatal, p. 234”
,
payoff
);
}
// Linear Programming by Chvatal, p. 236
// row = { 0, 2/5, 7/15, 0, 2/15, 0, 0, 0 }
// column = { 2/3, 0, 0, 1/3 }
// value = -1/3
private
static
void
test4
()
{
double
[][]
payoff
=
{
{
0
,
2
,
–
1
,
–
1
},
{
0
,
1
,
–
2
,
–
1
},
{
–
1
,
–
1
,
1
,
1
},
{
–
1
,
0
,
0
,
1
},
{
1
,
–
2
,
0
,
–
3
},
{
1
,
–
1
,
–
1
,
–
3
},
{
0
,
–
3
,
2
,
–
1
},
{
0
,
–
2
,
1
,
–
1
},
};
test
(
“Chvatal p. 236”
,
payoff
);
}
// rock, paper, scissors
// row = { 1/3, 1/3, 1/3 }
// column = { 1/3, 1/3, 1/3 }
private
static
void
test5
()
{
double
[][]
payoff
=
{
{
0
,
–
1
,
1
},
{
1
,
0
,
–
1
},
{
–
1
,
1
,
0
}
};
test
(
“rock, paper, scisssors”
,
payoff
);
}
/**
* Unit tests the {
@code
ZeroSumGameToLP} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
test1
();
test2
();
test3
();
test4
();
test5
();
int
m
=
Integer
.
parseInt
(
args
[
0
]);
int
n
=
Integer
.
parseInt
(
args
[
1
]);
double
[][]
payoff
=
new
double
[
m
][
n
];
for
(
int
i
=
0
;
i
<
m
;
i
++
)
for
(
int
j
=
0
;
j
<
n
;
j
++
)
payoff
[
i
][
j
]
=
StdRandom
.
uniform
(
-
0.5
,
0.5
);
test
(
"random "
+
m
+
"-by-"
+
n
,
payoff
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/UF.java
edu/princeton/cs/algs4/UF.java
/******************************************************************************
* Compilation: javac UF.java
* Execution: java UF < input.txt
* Dependencies: StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/15uf/tinyUF.txt
* https://algs4.cs.princeton.edu/15uf/mediumUF.txt
* https://algs4.cs.princeton.edu/15uf/largeUF.txt
*
* Weighted quick-union by rank with path compression by halving.
*
* % java UF < tinyUF.txt
* 4 3
* 3 8
* 6 5
* 9 4
* 2 1
* 5 0
* 7 2
* 6 1
* 2 components
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
UF} class represents a union–find data type
* (also known as the disjoint-sets data type).
* It supports the classic union and find operations,
* along with a count operation that returns the total number
* of sets.
*
* The union-find data type models a collection of sets containing
* n elements, with each element in exactly one set.
* The elements are named 0 through n–1.
* Initially, there are n sets, with each element in its
* own set. The cannonical elemement of a set
* (also known as the root, identifier,
* leader, or set representative)
* is one distinguished element in the set. Here is a summary of
* the operations:
*
*
* of the set containing p. The find operation
* returns the same value for two elements if and only if
* they are in the same set.
*
* containing element p with the set containing
* element q. That is, if p and q
* are in different sets, replace these two sets
* with a new set that is the union of the two.
*
*
*
* The canonical element of a set can change only when the set
* itself changes during a call to union—it cannot
* change during a call to either find or count.
*
* This implementation uses weighted quick union by rank
* with path compression by halving.
* The constructor takes Θ(n) time, where
* n is the number of elements.
* The union and find operations take
* Θ(log n) time in the worst case.
* The count operation takes Θ(1) time.
* Moreover, starting from an empty data structure with n sites,
* any intermixed sequence of m union and find
* operations takes O(m α(n)) time,
* where α(n) is the inverse of
*
* For alternative implementations of the same API, see
* {
@link
QuickUnionUF}, {
@link
QuickFindUF}, and {
@link
WeightedQuickUnionUF}.
* For additional documentation, see
* Section 1.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
UF
{
private
int
[]
parent
;
// parent[i] = parent of i
private
byte
[]
rank
;
// rank[i] = rank of subtree rooted at i (never more than 31)
private
int
count
;
// number of components
/**
* Initializes an empty union-find data structure with
* {
@code
n} elements {
@code
0} through {
@code
n-1}.
* Initially, each elements is in its own set.
*
*
@param
n the number of elements
*
@throws
IllegalArgumentException if {
@code
n < 0}
*/
public
UF
(
int
n
)
{
if
(
n
<
0
)
throw
new
IllegalArgumentException
();
count
=
n
;
parent
=
new
int
[
n
];
rank
=
new
byte
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
parent
[
i
]
=
i
;
rank
[
i
]
=
0
;
}
}
/**
* Returns the canonical element of the set containing element {
@code
p}.
*
*
@param
p an element
*
@return
the canonical element of the set containing {
@code
p}
*
@throws
IllegalArgumentException unless {
@code
0 <= p < n}
*/
public
int
find
(
int
p
)
{
validate
(
p
);
while
(
p
!=
parent
[
p
])
{
parent
[
p
]
=
parent
[
parent
[
p
]];
// path compression by halving
p
=
parent
[
p
];
}
return
p
;
}
/**
* Returns the number of sets.
*
*
@return
the number of sets (between {
@code
1} and {
@code
n})
*/
public
int
count
()
{
return
count
;
}
/**
* Returns true if the two elements are in the same set.
*
*
@param
p one element
*
@param
q the other element
*
@return
{
@code
true} if {
@code
p} and {
@code
q} are in the same set;
* {
@code
false} otherwise
*
@throws
IllegalArgumentException unless
* both {
@code
0 <= p < n} and {
@code
0 <= q < n}
*
@deprecated
Replace with two calls to {
@link
#find(int)}.
*/
@
Deprecated
public
boolean
connected
(
int
p
,
int
q
)
{
return
find
(
p
)
==
find
(
q
);
}
/**
* Merges the set containing element {
@code
p} with the
* the set containing element {
@code
q}.
*
*
@param
p one element
*
@param
q the other element
*
@throws
IllegalArgumentException unless
* both {
@code
0 <= p < n} and {
@code
0 <= q < n}
*/
public
void
union
(
int
p
,
int
q
)
{
int
rootP
=
find
(
p
);
int
rootQ
=
find
(
q
);
if
(
rootP
==
rootQ
)
return
;
// make root of smaller rank point to root of larger rank
if
(
rank
[
rootP
]
<
rank
[
rootQ
])
parent
[
rootP
]
=
rootQ
;
else
if
(
rank
[
rootP
]
>
rank
[
rootQ
])
parent
[
rootQ
]
=
rootP
;
else
{
parent
[
rootQ
]
=
rootP
;
rank
[
rootP
]
++
;
}
count
—
;
}
// validate that p is a valid index
private
void
validate
(
int
p
)
{
int
n
=
parent
.
length
;
if
(
p
<
0
||
p
>=
n
)
{
throw
new
IllegalArgumentException
(
“index ”
+
p
+
” is not between 0 and ”
+
(
n
–
1
));
}
}
/**
* Reads in a an integer {
@code
n} and a sequence of pairs of integers
* (between {
@code
0} and {
@code
n-1}) from standard input, where each integer
* in the pair represents some element;
* if the elements are in different sets, merge the two sets
* and print the pair to standard output.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
n
=
StdIn
.
readInt
();
UF uf
=
new
UF
(
n
);
while
(
!
StdIn
.
isEmpty
())
{
int
p
=
StdIn
.
readInt
();
int
q
=
StdIn
.
readInt
();
if
(
uf
.
find
(
p
)
==
uf
.
find
(
q
))
continue
;
uf
.
union
(
p
,
q
);
StdOut
.
println
(
p
+
” ”
+
q
);
}
StdOut
.
println
(
uf
.
count
()
+
” components”
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Vector.java
edu/princeton/cs/algs4/Vector.java
/******************************************************************************
* Compilation: javac Vector.java
* Execution: java Vector
* Dependencies: StdOut.java
*
* Implementation of a vector of real numbers.
*
* This class is implemented to be immutable: once the client program
* initialize a Vector, it cannot change any of its fields
* (d or data[i]) either directly or indirectly. Immutability is a
* very desirable feature of a data type.
*
* % java Vector
* x = [ 1.0 2.0 3.0 4.0 ]
* y = [ 5.0 2.0 4.0 1.0 ]
* z = [ 6.0 4.0 7.0 5.0 ]
* 10z = [ 60.0 40.0 70.0 50.0 ]
* |x| = 5.477225575051661
*
*
*
* Note that Vector is also the name of an unrelated Java library class
* in the package java.util.
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
Vector} class represents a d-dimensional Euclidean vector.
* Vectors are immutable: their values cannot be changed after they are created.
* It includes methods for addition, subtraction,
* dot product, scalar product, unit vector, Euclidean norm, and the Euclidean
* distance between two vectors.
*
* For additional documentation,
* see Section 1.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Vector
{
private
int
d
;
// dimension of the vector
private
double
[]
data
;
// array of vector’s components
/**
* Initializes a d-dimensional zero vector.
*
*
@param
d the dimension of the vector
*/
public
Vector
(
int
d
)
{
this
.
d
=
d
;
data
=
new
double
[
d
];
}
/**
* Initializes a vector from either an array or a vararg list.
* The vararg syntax supports a constructor that takes a variable number of
* arugments such as Vector x = new Vector(1.0, 2.0, 3.0, 4.0).
*
*
@param
a the array or vararg list
*/
public
Vector
(
double
…
a
)
{
d
=
a
.
length
;
// defensive copy so that client can’t alter our copy of data[]
data
=
new
double
[
d
];
for
(
int
i
=
0
;
i
<
d
;
i
++
)
data
[
i
]
=
a
[
i
];
}
/**
* Returns the length of this vector.
*
*
@return
the dimension of this vector
*
@deprecated
Replaced by {
@link
#dimension()}.
*/
@
Deprecated
public
int
length
()
{
return
d
;
}
/**
* Returns the dimension of this vector.
*
*
@return
the dimension of this vector
*/
public
int
dimension
()
{
return
d
;
}
/**
* Returns the dot product of this vector with the specified vector.
*
*
@param
that the other vector
*
@return
the dot product of this vector and that vector
*
@throws
IllegalArgumentException if the dimensions of the two vectors are not equal
*/
public
double
dot
(
Vector
that
)
{
if
(
this
.
d
!=
that
.
d
)
throw
new
IllegalArgumentException
(
"Dimensions don't agree"
);
double
sum
=
0.0
;
for
(
int
i
=
0
;
i
<
d
;
i
++
)
sum
=
sum
+
(
this
.
data
[
i
]
*
that
.
data
[
i
]);
return
sum
;
}
/**
* Returns the magnitude of this vector.
* This is also known as the L2 norm or the Euclidean norm.
*
*
@return
the magnitude of this vector
*/
public
double
magnitude
()
{
return
Math
.
sqrt
(
this
.
dot
(
this
));
}
/**
* Returns the Euclidean distance between this vector and the specified vector.
*
*
@param
that the other vector
*
@return
the Euclidean distance between this vector and that vector
*
@throws
IllegalArgumentException if the dimensions of the two vectors are not equal
*/
public
double
distanceTo
(
Vector
that
)
{
if
(
this
.
d
!=
that
.
d
)
throw
new
IllegalArgumentException
(
"Dimensions don't agree"
);
return
this
.
minus
(
that
).
magnitude
();
}
/**
* Returns the sum of this vector and the specified vector.
*
*
@param
that the vector to add to this vector
*
@return
the vector whose value is {
@code
(this + that)}
*
@throws
IllegalArgumentException if the dimensions of the two vectors are not equal
*/
public
Vector
plus
(
Vector
that
)
{
if
(
this
.
d
!=
that
.
d
)
throw
new
IllegalArgumentException
(
"Dimensions don't agree"
);
Vector
c
=
new
Vector
(
d
);
for
(
int
i
=
0
;
i
<
d
;
i
++
)
c
.
data
[
i
]
=
this
.
data
[
i
]
+
that
.
data
[
i
];
return
c
;
}
/**
* Returns the difference between this vector and the specified vector.
*
*
@param
that the vector to subtract from this vector
*
@return
the vector whose value is {
@code
(this - that)}
*
@throws
IllegalArgumentException if the dimensions of the two vectors are not equal
*/
public
Vector
minus
(
Vector
that
)
{
if
(
this
.
d
!=
that
.
d
)
throw
new
IllegalArgumentException
(
"Dimensions don't agree"
);
Vector
c
=
new
Vector
(
d
);
for
(
int
i
=
0
;
i
<
d
;
i
++
)
c
.
data
[
i
]
=
this
.
data
[
i
]
-
that
.
data
[
i
];
return
c
;
}
/**
* Returns the ith cartesian coordinate.
*
*
@param
i the coordinate index
*
@return
the ith cartesian coordinate
*/
public
double
cartesian
(
int
i
)
{
return
data
[
i
];
}
/**
* Returns the scalar-vector product of this vector and the specified scalar
*
*
@param
alpha the scalar
*
@return
the vector whose value is {
@code
(alpha * this)}
*
@deprecated
Replaced by {
@link
#scale(double)}.
*/
@
Deprecated
public
Vector
times
(
double
alpha
)
{
Vector
c
=
new
Vector
(
d
);
for
(
int
i
=
0
;
i
<
d
;
i
++
)
c
.
data
[
i
]
=
alpha
*
data
[
i
];
return
c
;
}
/**
* Returns the scalar-vector product of this vector and the specified scalar
*
*
@param
alpha the scalar
*
@return
the vector whose value is {
@code
(alpha * this)}
*/
public
Vector
scale
(
double
alpha
)
{
Vector
c
=
new
Vector
(
d
);
for
(
int
i
=
0
;
i
<
d
;
i
++
)
c
.
data
[
i
]
=
alpha
*
data
[
i
];
return
c
;
}
/**
* Returns a unit vector in the direction of this vector.
*
*
@return
a unit vector in the direction of this vector
*
@throws
ArithmeticException if this vector is the zero vector
*/
public
Vector
direction
()
{
if
(
this
.
magnitude
()
==
0.0
)
throw
new
ArithmeticException
(
"Zero-vector has no direction"
);
return
this
.
times
(
1.0
/
this
.
magnitude
());
}
/**
* Returns a string representation of this vector.
*
*
@return
a string representation of this vector, which consists of the
* the vector entries, separates by single spaces
*/
public
String
toString
()
{
StringBuilder
s
=
new
StringBuilder
();
for
(
int
i
=
0
;
i
<
d
;
i
++
)
s
.
append
(
data
[
i
]
+
" "
);
return
s
.
toString
();
}
/**
* Unit tests the {
@code
Vector} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
double
[]
xdata
=
{
1.0
,
2.0
,
3.0
,
4.0
};
double
[]
ydata
=
{
5.0
,
2.0
,
4.0
,
1.0
};
Vector
x
=
new
Vector
(
xdata
);
Vector
y
=
new
Vector
(
ydata
);
StdOut
.
println
(
" x = "
+
x
);
StdOut
.
println
(
" y = "
+
y
);
Vector
z
=
x
.
plus
(
y
);
StdOut
.
println
(
" z = "
+
z
);
z
=
z
.
times
(
10.0
);
StdOut
.
println
(
" 10z = "
+
z
);
StdOut
.
println
(
" |x| = "
+
x
.
magnitude
());
StdOut
.
println
(
"
+
x
.
dot
(
y
));
StdOut
.
println
(
“dist(x, y) = ”
+
x
.
distanceTo
(
y
));
StdOut
.
println
(
“dir(x) = ”
+
x
.
direction
());
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/WeightedQuickUnionUF.java
edu/princeton/cs/algs4/WeightedQuickUnionUF.java
/******************************************************************************
* Compilation: javac WeightedQuickUnionUF.java
* Execution: java WeightedQuickUnionUF < input.txt * Dependencies: StdIn.java StdOut.java * Data files: https://algs4.cs.princeton.edu/15uf/tinyUF.txt * https://algs4.cs.princeton.edu/15uf/mediumUF.txt * https://algs4.cs.princeton.edu/15uf/largeUF.txt * * Weighted quick-union (without path compression). * ******************************************************************************/ package edu . princeton . cs . algs4 ; /** * The { @code WeightedQuickUnionUF} class represents a union–find data type
* (also known as the disjoint-sets data type).
* It supports the classic union and find operations,
* along with a count operation that returns the total number
* of sets.
*
* The union-find data type models a collection of sets containing
* n elements, with each element in exactly one set.
* The elements are named 0 through n–1.
* Initially, there are n sets, with each element in its
* own set. The cannonical elemement of a set
* (also known as the root, identifier,
* leader, or set representative)
* is one distinguished element in the set. Here is a summary of
* the operations:
*
*
* of the set containing p. The find operation
* returns the same value for two elements if and only if
* they are in the same set.
*
* containing element p with the set containing
* element q. That is, if p and q
* are in different sets, replace these two sets
* with a new set that is the union of the two.
*
*
*
* The canonical element of a set can change only when the set
* itself changes during a call to union—it cannot
* change during a call to either find or count.
*
* This implementation uses weighted quick union by size
* (without path compression).
* The constructor takes Θ(n), where n
* is the number of elements.
* The union and find
* operations take Θ(log n) time in the worst
* case. The count operation takes Θ(1) time.
*
* For alternative implementations of the same API, see
* {
@link
UF}, {
@link
QuickFindUF}, and {
@link
QuickUnionUF}.
* For additional documentation, see
* Section 1.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
WeightedQuickUnionUF
{
private
int
[]
parent
;
// parent[i] = parent of i
private
int
[]
size
;
// size[i] = number of elements in subtree rooted at i
private
int
count
;
// number of components
/**
* Initializes an empty union-find data structure with
* {
@code
n} elements {
@code
0} through {
@code
n-1}.
* Initially, each elements is in its own set.
*
*
@param
n the number of elements
*
@throws
IllegalArgumentException if {
@code
n < 0}
*/
public
WeightedQuickUnionUF
(
int
n
)
{
count
=
n
;
parent
=
new
int
[
n
];
size
=
new
int
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
parent
[
i
]
=
i
;
size
[
i
]
=
1
;
}
}
/**
* Returns the number of sets.
*
*
@return
the number of sets (between {
@code
1} and {
@code
n})
*/
public
int
count
()
{
return
count
;
}
/**
* Returns the canonical element of the set containing element {
@code
p}.
*
*
@param
p an element
*
@return
the canonical element of the set containing {
@code
p}
*
@throws
IllegalArgumentException unless {
@code
0 <= p < n}
*/
public
int
find
(
int
p
)
{
validate
(
p
);
while
(
p
!=
parent
[
p
])
p
=
parent
[
p
];
return
p
;
}
/**
* Returns true if the two elements are in the same set.
*
*
@param
p one element
*
@param
q the other element
*
@return
{
@code
true} if {
@code
p} and {
@code
q} are in the same set;
* {
@code
false} otherwise
*
@throws
IllegalArgumentException unless
* both {
@code
0 <= p < n} and {
@code
0 <= q < n}
*
@deprecated
Replace with two calls to {
@link
#find(int)}.
*/
@
Deprecated
public
boolean
connected
(
int
p
,
int
q
)
{
return
find
(
p
)
==
find
(
q
);
}
// validate that p is a valid index
private
void
validate
(
int
p
)
{
int
n
=
parent
.
length
;
if
(
p
<
0
||
p
>=
n
)
{
throw
new
IllegalArgumentException
(
“index ”
+
p
+
” is not between 0 and ”
+
(
n
–
1
));
}
}
/**
* Merges the set containing element {
@code
p} with the
* the set containing element {
@code
q}.
*
*
@param
p one element
*
@param
q the other element
*
@throws
IllegalArgumentException unless
* both {
@code
0 <= p < n} and {
@code
0 <= q < n}
*/
public
void
union
(
int
p
,
int
q
)
{
int
rootP
=
find
(
p
);
int
rootQ
=
find
(
q
);
if
(
rootP
==
rootQ
)
return
;
// make smaller root point to larger one
if
(
size
[
rootP
]
<
size
[
rootQ
])
{
parent
[
rootP
]
=
rootQ
;
size
[
rootQ
]
+=
size
[
rootP
];
}
else
{
parent
[
rootQ
]
=
rootP
;
size
[
rootP
]
+=
size
[
rootQ
];
}
count
--
;
}
/**
* Reads in a an integer {
@code
n} and a sequence of pairs of integers
* (between {
@code
0} and {
@code
n-1}) from standard input, where each integer
* in the pair represents some element;
* if the elements are in different sets, merge the two sets
* and print the pair to standard output.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
n
=
StdIn
.
readInt
();
WeightedQuickUnionUF
uf
=
new
WeightedQuickUnionUF
(
n
);
while
(
!
StdIn
.
isEmpty
())
{
int
p
=
StdIn
.
readInt
();
int
q
=
StdIn
.
readInt
();
if
(
uf
.
find
(
p
)
==
uf
.
find
(
q
))
continue
;
uf
.
union
(
p
,
q
);
StdOut
.
println
(
p
+
" "
+
q
);
}
StdOut
.
println
(
uf
.
count
()
+
" components"
);
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/WhiteFilter.java
edu/princeton/cs/algs4/WhiteFilter.java
/******************************************************************************
* Compilation: javac WhiteFilter.java
* Execution: java WhiteFilter whitelist.txt < input.txt
* Dependencies: SET In.java StdIn.java StdOut.java
* Data files: https://algs4.cs.princeton.edu/35applications/tinyTale.txt
* https://algs4.cs.princeton.edu/35applications/list.txt
*
* Read in a whitelist of words from a file. Then read in a list of
* words from standard input and print out all those words that
* are in the first file.
*
* % more tinyTale.txt
* it was the best of times it was the worst of times
* it was the age of wisdom it was the age of foolishness
* it was the epoch of belief it was the epoch of incredulity
* it was the season of light it was the season of darkness
* it was the spring of hope it was the winter of despair
*
* % more list.txt
* was it the of
*
* % java WhiteFilter list.txt < tinyTale.txt
* it was the of it was the of
* it was the of it was the of
* it was the of it was the of
* it was the of it was the of
* it was the of it was the of
*
******************************************************************************/
package
edu
.
princeton
.
cs
.
algs4
;
/**
* The {
@code
WhiteFilter} class provides a client for reading in a whitelist
* of words from a file; then, reading in a sequence of words from standard input,
* printing out each word that appears in the file.
* It is useful as a test client for various symbol table implementations.
*
* For additional documentation, see Section 3.5 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
WhiteFilter
{
// Do not instantiate.
private
WhiteFilter
()
{
}
public
static
void
main
(
String
[]
args
)
{
SET
<
String
>
set
=
new
SET
<
String
>
();
// read in strings and add to set
In
in
=
new
In
(
args
[
0
]);
while
(
!
in
.
isEmpty
())
{
String
word
=
in
.
readString
();
set
.
add
(
word
);
}
// read in string from standard input, printing out all exceptions
while
(
!
StdIn
.
isEmpty
())
{
String
word
=
StdIn
.
readString
();
if
(
set
.
contains
(
word
))
StdOut
.
println
(
word
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Whitelist.java
edu/princeton/cs/algs4/Whitelist.java
/******************************************************************************
* Compilation: javac Whitelist.java
* Execution: java Whitelist whitelist.txt < data.txt * Dependencies: StaticSetOfInts.java In.java StdOut.java * * Data files: https://algs4.cs.princeton.edu/11model/tinyW.txt * https://algs4.cs.princeton.edu/11model/tinyT.txt * https://algs4.cs.princeton.edu/11model/largeW.txt * https://algs4.cs.princeton.edu/11model/largeT.txt * * Whitelist filter. * * * % java Whitelist tinyW.txt < tinyT.txt * 50 * 99 * 13 * * % java Whitelist largeW.txt < largeT.txt | more * 499569 * 984875 * 295754 * 207807 * 140925 * 161828 * [367,966 total values] * ******************************************************************************/ package edu . princeton . cs . algs4 ; /** * The { @code Whitelist} class provides a client for reading in * a set of integers from a file; reading in a sequence of integers * from standard input; and printing to standard output those * integers not in the whitelist. *
* For additional documentation, see Section 1.2 of
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Whitelist
{
// Do not instantiate.
private
Whitelist
()
{
}
/**
* Reads in a sequence of integers from the whitelist file, specified as
* a command-line argument. Reads in integers from standard input and
* prints to standard output those integers that are not in the file.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
=
new
In
(
args
[
0
]);
int
[]
white
=
in
.
readAllInts
();
StaticSETofInts
set
=
new
StaticSETofInts
(
white
);
// Read key, print if not in whitelist.
while
(
!
StdIn
.
isEmpty
())
{
int
key
=
StdIn
.
readInt
();
if
(
!
set
.
contains
(
key
))
StdOut
.
println
(
key
);
}
}
}
/******************************************************************************
* Copyright 2002-2020, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
edu/princeton/cs/algs4/Accumulator.class
package edu.princeton.cs.algs4;
public synchronized class Accumulator {
private int n;
private double sum;
private double mu;
public void Accumulator();
public void addDataValue(double);
public double mean();
public double var();
public double stddev();
public int count();
public String toString();
public static void main(String[]);
}
edu/princeton/cs/algs4/AcyclicLP.class
package edu.princeton.cs.algs4;
public synchronized class AcyclicLP {
private double[] distTo;
private DirectedEdge[] edgeTo;
public void AcyclicLP(EdgeWeightedDigraph, int);
private void relax(DirectedEdge);
public double distTo(int);
public boolean hasPathTo(int);
public Iterable pathTo(int);
private void validateVertex(int);
public static void main(String[]);
}
edu/princeton/cs/algs4/AcyclicSP.class
package edu.princeton.cs.algs4;
public synchronized class AcyclicSP {
private double[] distTo;
private DirectedEdge[] edgeTo;
public void AcyclicSP(EdgeWeightedDigraph, int);
private void relax(DirectedEdge);
public double distTo(int);
public boolean hasPathTo(int);
public Iterable pathTo(int);
private void validateVertex(int);
public static void main(String[]);
}
edu/princeton/cs/algs4/AdjMatrixEdgeWeightedDigraph$AdjIterator.class
package edu.princeton.cs.algs4;
synchronized class AdjMatrixEdgeWeightedDigraph$AdjIterator implements java.util.Iterator, Iterable {
private int v;
private int w;
public void AdjMatrixEdgeWeightedDigraph$AdjIterator(AdjMatrixEdgeWeightedDigraph, int);
public java.util.Iterator iterator();
public boolean hasNext();
public DirectedEdge next();
public void remove();
}
edu/princeton/cs/algs4/AdjMatrixEdgeWeightedDigraph.class
package edu.princeton.cs.algs4;
public synchronized class AdjMatrixEdgeWeightedDigraph {
private static final String NEWLINE;
private final int V;
private int E;
private DirectedEdge[][] adj;
public void AdjMatrixEdgeWeightedDigraph(int);
public void AdjMatrixEdgeWeightedDigraph(int, int);
public int V();
public int E();
public void addEdge(DirectedEdge);
public Iterable adj(int);
public String toString();
private void validateVertex(int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/Alphabet.class
package edu.princeton.cs.algs4;
public synchronized class Alphabet {
public static final Alphabet BINARY;
public static final Alphabet OCTAL;
public static final Alphabet DECIMAL;
public static final Alphabet HEXADECIMAL;
public static final Alphabet DNA;
public static final Alphabet LOWERCASE;
public static final Alphabet UPPERCASE;
public static final Alphabet PROTEIN;
public static final Alphabet BASE64;
public static final Alphabet ASCII;
public static final Alphabet EXTENDED_ASCII;
public static final Alphabet UNICODE16;
private char[] alphabet;
private int[] inverse;
private final int R;
public void Alphabet(String);
private void Alphabet(int);
public void Alphabet();
public boolean contains(char);
public int R();
public int radix();
public int lgR();
public int toIndex(char);
public int[] toIndices(String);
public char toChar(int);
public String toChars(int[]);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/AmericanFlag.class
package edu.princeton.cs.algs4;
public synchronized class AmericanFlag {
private static final int BITS_PER_BYTE = 8;
private static final int BITS_PER_INT = 32;
private static final int R = 256;
private static final int CUTOFF = 15;
private void AmericanFlag();
private static int charAt(String, int);
public static void sort(String[]);
public static void sort(String[], int, int);
private static void insertion(String[], int, int, int);
private static void exch(String[], int, int);
private static boolean less(String, String, int);
public static void sort(int[]);
private static void sort(int[], int, int);
private static void insertion(int[], int, int, int);
private static void exch(int[], int, int);
private static boolean less(int, int, int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/AmericanFlagX.class
package edu.princeton.cs.algs4;
public synchronized class AmericanFlagX {
private static final int R = 256;
private static final int CUTOFF = 15;
private void AmericanFlagX();
private static int charAt(String, int);
public static void sort(String[]);
public static void sort(String[], int, int);
private static void insertion(String[], int, int, int);
private static void exch(String[], int, int);
private static boolean less(String, String, int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/Arbitrage.class
package edu.princeton.cs.algs4;
public synchronized class Arbitrage {
private void Arbitrage();
public static void main(String[]);
}
edu/princeton/cs/algs4/AssignmentProblem.class
package edu.princeton.cs.algs4;
public synchronized class AssignmentProblem {
private static final double FLOATING_POINT_EPSILON = 1.0E-14;
private static final int UNMATCHED = -1;
private int n;
private double[][] weight;
private double minWeight;
private double[] px;
private double[] py;
private int[] xy;
private int[] yx;
public void AssignmentProblem(double[][]);
private void augment();
private double reducedCost(int, int);
public double dualRow(int);
public double dualCol(int);
public int sol(int);
public double weight();
private void validate(int);
private boolean isDualFeasible();
private boolean isComplementarySlack();
private boolean isPerfectMatching();
private boolean certifySolution();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/Average.class
package edu.princeton.cs.algs4;
public synchronized class Average {
private void Average();
public static void main(String[]);
}
edu/princeton/cs/algs4/AVLTreeST.class
package edu.princeton.cs.algs4;
public synchronized class AVLTreeST {
private AVLTreeST$Node root;
public void AVLTreeST();
public boolean isEmpty();
public int size();
private int size(AVLTreeST$Node);
public int height();
private int height(AVLTreeST$Node);
public Object get(Comparable);
private AVLTreeST$Node get(AVLTreeST$Node, Comparable);
public boolean contains(Comparable);
public void put(Comparable, Object);
private AVLTreeST$Node put(AVLTreeST$Node, Comparable, Object);
private AVLTreeST$Node balance(AVLTreeST$Node);
private int balanceFactor(AVLTreeST$Node);
private AVLTreeST$Node rotateRight(AVLTreeST$Node);
private AVLTreeST$Node rotateLeft(AVLTreeST$Node);
public void delete(Comparable);
private AVLTreeST$Node delete(AVLTreeST$Node, Comparable);
public void deleteMin();
private AVLTreeST$Node deleteMin(AVLTreeST$Node);
public void deleteMax();
private AVLTreeST$Node deleteMax(AVLTreeST$Node);
public Comparable min();
private AVLTreeST$Node min(AVLTreeST$Node);
public Comparable max();
private AVLTreeST$Node max(AVLTreeST$Node);
public Comparable floor(Comparable);
private AVLTreeST$Node floor(AVLTreeST$Node, Comparable);
public Comparable ceiling(Comparable);
private AVLTreeST$Node ceiling(AVLTreeST$Node, Comparable);
public Comparable select(int);
private AVLTreeST$Node select(AVLTreeST$Node, int);
public int rank(Comparable);
private int rank(Comparable, AVLTreeST$Node);
public Iterable keys();
public Iterable keysInOrder();
private void keysInOrder(AVLTreeST$Node, Queue);
public Iterable keysLevelOrder();
public Iterable keys(Comparable, Comparable);
private void keys(AVLTreeST$Node, Queue, Comparable, Comparable);
public int size(Comparable, Comparable);
private boolean check();
private boolean isAVL();
private boolean isAVL(AVLTreeST$Node);
private boolean isBST();
private boolean isBST(AVLTreeST$Node, Comparable, Comparable);
private boolean isSizeConsistent();
private boolean isSizeConsistent(AVLTreeST$Node);
private boolean isRankConsistent();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/AVLTreeST$Node.class
package edu.princeton.cs.algs4;
synchronized class AVLTreeST$Node {
private final Comparable key;
private Object val;
private int height;
private int size;
private AVLTreeST$Node left;
private AVLTreeST$Node right;
public void AVLTreeST$Node(AVLTreeST, Comparable, Object, int, int);
}
edu/princeton/cs/algs4/Bag$1.class
package edu.princeton.cs.algs4;
synchronized class Bag$1 {
}
edu/princeton/cs/algs4/Bag.class
package edu.princeton.cs.algs4;
public synchronized class Bag implements Iterable {
private Bag$Node first;
private int n;
public void Bag();
public boolean isEmpty();
public int size();
public void add(Object);
public java.util.Iterator iterator();
public static void main(String[]);
}
edu/princeton/cs/algs4/Bag$ListIterator.class
package edu.princeton.cs.algs4;
synchronized class Bag$ListIterator implements java.util.Iterator {
private Bag$Node current;
public void Bag$ListIterator(Bag, Bag$Node);
public boolean hasNext();
public void remove();
public Object next();
}
edu/princeton/cs/algs4/Bag$Node.class
package edu.princeton.cs.algs4;
synchronized class Bag$Node {
private Object item;
private Bag$Node next;
private void Bag$Node();
}
edu/princeton/cs/algs4/BellmanFordSP.class
package edu.princeton.cs.algs4;
public synchronized class BellmanFordSP {
private double[] distTo;
private DirectedEdge[] edgeTo;
private boolean[] onQueue;
private Queue queue;
private int cost;
private Iterable cycle;
public void BellmanFordSP(EdgeWeightedDigraph, int);
private void relax(EdgeWeightedDigraph, int);
public boolean hasNegativeCycle();
public Iterable negativeCycle();
private void findNegativeCycle();
public double distTo(int);
public boolean hasPathTo(int);
public Iterable pathTo(int);
private boolean check(EdgeWeightedDigraph, int);
private void validateVertex(int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/BinaryDump.class
package edu.princeton.cs.algs4;
public synchronized class BinaryDump {
private void BinaryDump();
public static void main(String[]);
}
edu/princeton/cs/algs4/BinaryIn.class
package edu.princeton.cs.algs4;
public final synchronized class BinaryIn {
private static final int EOF = -1;
private java.io.BufferedInputStream in;
private int buffer;
private int n;
public void BinaryIn();
public void BinaryIn(java.io.InputStream);
public void BinaryIn(java.net.Socket);
public void BinaryIn(java.net.URL);
public void BinaryIn(String);
private void fillBuffer();
public boolean exists();
public boolean isEmpty();
public boolean readBoolean();
public char readChar();
public char readChar(int);
public String readString();
public short readShort();
public int readInt();
public int readInt(int);
public long readLong();
public double readDouble();
public float readFloat();
public byte readByte();
public static void main(String[]);
}
edu/princeton/cs/algs4/BinaryInsertion.class
package edu.princeton.cs.algs4;
public synchronized class BinaryInsertion {
private void BinaryInsertion();
public static void sort(Comparable[]);
private static boolean less(Comparable, Comparable);
private static boolean isSorted(Comparable[]);
private static boolean isSorted(Comparable[], int, int);
private static void show(Comparable[]);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/BinaryOut.class
package edu.princeton.cs.algs4;
public final synchronized class BinaryOut {
private java.io.BufferedOutputStream out;
private int buffer;
private int n;
public void BinaryOut();
public void BinaryOut(java.io.OutputStream);
public void BinaryOut(String);
public void BinaryOut(java.net.Socket);
private void writeBit(boolean);
private void writeByte(int);
private void clearBuffer();
public void flush();
public void close();
public void write(boolean);
public void write(byte);
public void write(int);
public void write(int, int);
public void write(double);
public void write(long);
public void write(float);
public void write(short);
public void write(char);
public void write(char, int);
public void write(String);
public void write(String, int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/BinarySearch.class
package edu.princeton.cs.algs4;
public synchronized class BinarySearch {
private void BinarySearch();
public static int indexOf(int[], int);
public static int rank(int, int[]);
public static void main(String[]);
}
edu/princeton/cs/algs4/BinarySearchST.class
package edu.princeton.cs.algs4;
public synchronized class BinarySearchST {
private static final int INIT_CAPACITY = 2;
private Comparable[] keys;
private Object[] vals;
private int n;
public void BinarySearchST();
public void BinarySearchST(int);
private void resize(int);
public int size();
public boolean isEmpty();
public boolean contains(Comparable);
public Object get(Comparable);
public int rank(Comparable);
public void put(Comparable, Object);
public void delete(Comparable);
public void deleteMin();
public void deleteMax();
public Comparable min();
public Comparable max();
public Comparable select(int);
public Comparable floor(Comparable);
public Comparable ceiling(Comparable);
public int size(Comparable, Comparable);
public Iterable keys();
public Iterable keys(Comparable, Comparable);
private boolean check();
private boolean isSorted();
private boolean rankCheck();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/BinaryStdIn.class
package edu.princeton.cs.algs4;
public final synchronized class BinaryStdIn {
private static final int EOF = -1;
private static java.io.BufferedInputStream in;
private static int buffer;
private static int n;
private static boolean isInitialized;
private void BinaryStdIn();
private static void initialize();
private static void fillBuffer();
public static void close();
public static boolean isEmpty();
public static boolean readBoolean();
public static char readChar();
public static char readChar(int);
public static String readString();
public static short readShort();
public static int readInt();
public static int readInt(int);
public static long readLong();
public static double readDouble();
public static float readFloat();
public static byte readByte();
public static void main(String[]);
}
edu/princeton/cs/algs4/BinaryStdOut.class
package edu.princeton.cs.algs4;
public final synchronized class BinaryStdOut {
private static java.io.BufferedOutputStream out;
private static int buffer;
private static int n;
private static boolean isInitialized;
private void BinaryStdOut();
private static void initialize();
private static void writeBit(boolean);
private static void writeByte(int);
private static void clearBuffer();
public static void flush();
public static void close();
public static void write(boolean);
public static void write(byte);
public static void write(int);
public static void write(int, int);
public static void write(double);
public static void write(long);
public static void write(float);
public static void write(short);
public static void write(char);
public static void write(char, int);
public static void write(String);
public static void write(String, int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/BinomialMinPQ$1.class
package edu.princeton.cs.algs4;
synchronized class BinomialMinPQ$1 {
}
edu/princeton/cs/algs4/BinomialMinPQ.class
package edu.princeton.cs.algs4;
public synchronized class BinomialMinPQ implements Iterable {
private BinomialMinPQ$Node head;
private final java.util.Comparator comp;
public void BinomialMinPQ();
public void BinomialMinPQ(java.util.Comparator);
public void BinomialMinPQ(Object[]);
public void BinomialMinPQ(java.util.Comparator, Object[]);
public boolean isEmpty();
public int size();
public void insert(Object);
public Object minKey();
public Object delMin();
public BinomialMinPQ union(BinomialMinPQ);
private boolean greater(Object, Object);
private void link(BinomialMinPQ$Node, BinomialMinPQ$Node);
private BinomialMinPQ$Node eraseMin();
private BinomialMinPQ$Node merge(BinomialMinPQ$Node, BinomialMinPQ$Node, BinomialMinPQ$Node);
public java.util.Iterator iterator();
}
edu/princeton/cs/algs4/BinomialMinPQ$MyComparator.class
package edu.princeton.cs.algs4;
synchronized class BinomialMinPQ$MyComparator implements java.util.Comparator {
private void BinomialMinPQ$MyComparator(BinomialMinPQ);
public int compare(Object, Object);
}
edu/princeton/cs/algs4/BinomialMinPQ$MyIterator.class
package edu.princeton.cs.algs4;
synchronized class BinomialMinPQ$MyIterator implements java.util.Iterator {
BinomialMinPQ data;
public void BinomialMinPQ$MyIterator(BinomialMinPQ);
private BinomialMinPQ$Node clone(BinomialMinPQ$Node, BinomialMinPQ$Node);
public boolean hasNext();
public Object next();
public void remove();
}
edu/princeton/cs/algs4/BinomialMinPQ$Node.class
package edu.princeton.cs.algs4;
synchronized class BinomialMinPQ$Node {
Object key;
int order;
BinomialMinPQ$Node child;
BinomialMinPQ$Node sibling;
private void BinomialMinPQ$Node(BinomialMinPQ);
}
edu/princeton/cs/algs4/Bipartite.class
package edu.princeton.cs.algs4;
public synchronized class Bipartite {
private boolean isBipartite;
private boolean[] color;
private boolean[] marked;
private int[] edgeTo;
private Stack cycle;
public void Bipartite(Graph);
private void dfs(Graph, int);
public boolean isBipartite();
public boolean color(int);
public Iterable oddCycle();
private boolean check(Graph);
private void validateVertex(int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/BipartiteMatching.class
package edu.princeton.cs.algs4;
public synchronized class BipartiteMatching {
private static final int UNMATCHED = -1;
private final int V;
private BipartiteX bipartition;
private int cardinality;
private int[] mate;
private boolean[] inMinVertexCover;
private boolean[] marked;
private int[] edgeTo;
public void BipartiteMatching(Graph);
private boolean hasAugmentingPath(Graph);
private boolean isResidualGraphEdge(int, int);
public int mate(int);
public boolean isMatched(int);
public int size();
public boolean isPerfect();
public boolean inMinVertexCover(int);
private void validate(int);
private boolean certifySolution(Graph);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/BipartiteX.class
package edu.princeton.cs.algs4;
public synchronized class BipartiteX {
private static final boolean WHITE = 0;
private static final boolean BLACK = 1;
private boolean isBipartite;
private boolean[] color;
private boolean[] marked;
private int[] edgeTo;
private Queue cycle;
public void BipartiteX(Graph);
private void bfs(Graph, int);
public boolean isBipartite();
public boolean color(int);
public Iterable oddCycle();
private boolean check(Graph);
private void validateVertex(int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/BlackFilter.class
package edu.princeton.cs.algs4;
public synchronized class BlackFilter {
private void BlackFilter();
public static void main(String[]);
}
edu/princeton/cs/algs4/BoruvkaMST.class
package edu.princeton.cs.algs4;
public synchronized class BoruvkaMST {
private static final double FLOATING_POINT_EPSILON = 1.0E-12;
private Bag mst;
private double weight;
public void BoruvkaMST(EdgeWeightedGraph);
public Iterable edges();
public double weight();
private static boolean less(Edge, Edge);
private boolean check(EdgeWeightedGraph);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/BoyerMoore.class
package edu.princeton.cs.algs4;
public synchronized class BoyerMoore {
private final int R;
private int[] right;
private char[] pattern;
private String pat;
public void BoyerMoore(String);
public void BoyerMoore(char[], int);
public int search(String);
public int search(char[]);
public static void main(String[]);
}
edu/princeton/cs/algs4/BreadthFirstDirectedPaths.class
package edu.princeton.cs.algs4;
public synchronized class BreadthFirstDirectedPaths {
private static final int INFINITY = 2147483647;
private boolean[] marked;
private int[] edgeTo;
private int[] distTo;
public void BreadthFirstDirectedPaths(Digraph, int);
public void BreadthFirstDirectedPaths(Digraph, Iterable);
private void bfs(Digraph, int);
private void bfs(Digraph, Iterable);
public boolean hasPathTo(int);
public int distTo(int);
public Iterable pathTo(int);
private void validateVertex(int);
private void validateVertices(Iterable);
public static void main(String[]);
}
edu/princeton/cs/algs4/BreadthFirstPaths.class
package edu.princeton.cs.algs4;
public synchronized class BreadthFirstPaths {
private static final int INFINITY = 2147483647;
private boolean[] marked;
private int[] edgeTo;
private int[] distTo;
public void BreadthFirstPaths(Graph, int);
public void BreadthFirstPaths(Graph, Iterable);
private void bfs(Graph, int);
private void bfs(Graph, Iterable);
public boolean hasPathTo(int);
public int distTo(int);
public Iterable pathTo(int);
private boolean check(Graph, int);
private void validateVertex(int);
private void validateVertices(Iterable);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/BST.class
package edu.princeton.cs.algs4;
public synchronized class BST {
private BST$Node root;
public void BST();
public boolean isEmpty();
public int size();
private int size(BST$Node);
public boolean contains(Comparable);
public Object get(Comparable);
private Object get(BST$Node, Comparable);
public void put(Comparable, Object);
private BST$Node put(BST$Node, Comparable, Object);
public void deleteMin();
private BST$Node deleteMin(BST$Node);
public void deleteMax();
private BST$Node deleteMax(BST$Node);
public void delete(Comparable);
private BST$Node delete(BST$Node, Comparable);
public Comparable min();
private BST$Node min(BST$Node);
public Comparable max();
private BST$Node max(BST$Node);
public Comparable floor(Comparable);
private BST$Node floor(BST$Node, Comparable);
public Comparable floor2(Comparable);
private Comparable floor2(BST$Node, Comparable, Comparable);
public Comparable ceiling(Comparable);
private BST$Node ceiling(BST$Node, Comparable);
public Comparable select(int);
private BST$Node select(BST$Node, int);
public int rank(Comparable);
private int rank(Comparable, BST$Node);
public Iterable keys();
public Iterable keys(Comparable, Comparable);
private void keys(BST$Node, Queue, Comparable, Comparable);
public int size(Comparable, Comparable);
public int height();
private int height(BST$Node);
public Iterable levelOrder();
private boolean check();
private boolean isBST();
private boolean isBST(BST$Node, Comparable, Comparable);
private boolean isSizeConsistent();
private boolean isSizeConsistent(BST$Node);
private boolean isRankConsistent();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/BST$Node.class
package edu.princeton.cs.algs4;
synchronized class BST$Node {
private Comparable key;
private Object val;
private BST$Node left;
private BST$Node right;
private int size;
public void BST$Node(BST, Comparable, Object, int);
}
edu/princeton/cs/algs4/BTree$1.class
package edu.princeton.cs.algs4;
synchronized class BTree$1 {
}
edu/princeton/cs/algs4/BTree.class
package edu.princeton.cs.algs4;
public synchronized class BTree {
private static final int M = 4;
private BTree$Node root;
private int height;
private int n;
public void BTree();
public boolean isEmpty();
public int size();
public int height();
public Object get(Comparable);
private Object search(BTree$Node, Comparable, int);
public void put(Comparable, Object);
private BTree$Node insert(BTree$Node, Comparable, Object, int);
private BTree$Node split(BTree$Node);
public String toString();
private String toString(BTree$Node, int, String);
private boolean less(Comparable, Comparable);
private boolean eq(Comparable, Comparable);
public static void main(String[]);
}
edu/princeton/cs/algs4/BTree$Entry.class
package edu.princeton.cs.algs4;
synchronized class BTree$Entry {
private Comparable key;
private final Object val;
private BTree$Node next;
public void BTree$Entry(Comparable, Object, BTree$Node);
}
edu/princeton/cs/algs4/BTree$Node.class
package edu.princeton.cs.algs4;
final synchronized class BTree$Node {
private int m;
private BTree$Entry[] children;
private void BTree$Node(int);
}
edu/princeton/cs/algs4/Cat.class
package edu.princeton.cs.algs4;
public synchronized class Cat {
private void Cat();
public static void main(String[]);
}
edu/princeton/cs/algs4/CC.class
package edu.princeton.cs.algs4;
public synchronized class CC {
private boolean[] marked;
private int[] id;
private int[] size;
private int count;
public void CC(Graph);
public void CC(EdgeWeightedGraph);
private void dfs(Graph, int);
private void dfs(EdgeWeightedGraph, int);
public int id(int);
public int size(int);
public int count();
public boolean connected(int, int);
public boolean areConnected(int, int);
private void validateVertex(int);
public static void main(String[]);
}
edu/princeton/cs/algs4/ClosestPair.class
package edu.princeton.cs.algs4;
public synchronized class ClosestPair {
private Point2D best1;
private Point2D best2;
private double bestDistance;
public void ClosestPair(Point2D[]);
private double closest(Point2D[], Point2D[], Point2D[], int, int);
public Point2D either();
public Point2D other();
public double distance();
private static boolean less(Comparable, Comparable);
private static void merge(Comparable[], Comparable[], int, int, int);
public static void main(String[]);
}
edu/princeton/cs/algs4/CollisionSystem.class
package edu.princeton.cs.algs4;
public synchronized class CollisionSystem {
private static final double HZ = 0.5;
private MinPQ pq;
private double t;
private Particle[] particles;
public void CollisionSystem(Particle[]);
private void predict(Particle, double);
private void redraw(double);
public void simulate(double);
public static void main(String[]);
}
edu/princeton/cs/algs4/CollisionSystem$Event.class
package edu.princeton.cs.algs4;
synchronized class CollisionSystem$Event implements Comparable {
private final double time;
private final Particle a;
private final Particle b;
private final int countA;
private final int countB;
public void CollisionSystem$Event(double, Particle, Particle);
public int compareTo(CollisionSystem$Event);
public boolean isValid();
}
edu/princeton/cs/algs4/Complex.class
package edu.princeton.cs.algs4;
public synchronized class Complex {
private final double re;
private final double im;
public void Complex(double, double);
public String toString();
public double abs();
public double phase();
public Complex plus(Complex);
public Complex minus(Complex);
public Complex times(Complex);
public Complex scale(double);
public Complex times(double);
public Complex conjugate();
public Complex reciprocal();
public double re();
public double im();
public Complex divides(Complex);
public Complex exp();
public Complex sin();
public Complex cos();
public Complex tan();
public static void main(String[]);
}
edu/princeton/cs/algs4/Count.class
package edu.princeton.cs.algs4;
public synchronized class Count {
private void Count();
public static void main(String[]);
}
edu/princeton/cs/algs4/Counter.class
package edu.princeton.cs.algs4;
public synchronized class Counter implements Comparable {
private final String name;
private int count;
public void Counter(String);
public void increment();
public int tally();
public String toString();
public int compareTo(Counter);
public static void main(String[]);
}
edu/princeton/cs/algs4/CPM.class
package edu.princeton.cs.algs4;
public synchronized class CPM {
private void CPM();
public static void main(String[]);
}
edu/princeton/cs/algs4/Cycle.class
package edu.princeton.cs.algs4;
public synchronized class Cycle {
private boolean[] marked;
private int[] edgeTo;
private Stack cycle;
public void Cycle(Graph);
private boolean hasSelfLoop(Graph);
private boolean hasParallelEdges(Graph);
public boolean hasCycle();
public Iterable cycle();
private void dfs(Graph, int, int);
public static void main(String[]);
}
edu/princeton/cs/algs4/Date.class
package edu.princeton.cs.algs4;
public synchronized class Date implements Comparable {
private static final int[] DAYS;
private final int month;
private final int day;
private final int year;
public void Date(int, int, int);
public void Date(String);
public int month();
public int day();
public int year();
private static boolean isValid(int, int, int);
private static boolean isLeapYear(int);
public Date next();
public boolean isAfter(Date);
public boolean isBefore(Date);
public int compareTo(Date);
public String toString();
public boolean equals(Object);
public int hashCode();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/DeDup.class
package edu.princeton.cs.algs4;
public synchronized class DeDup {
private void DeDup();
public static void main(String[]);
}
edu/princeton/cs/algs4/DegreesOfSeparation.class
package edu.princeton.cs.algs4;
public synchronized class DegreesOfSeparation {
private void DegreesOfSeparation();
public static void main(String[]);
}
edu/princeton/cs/algs4/DepthFirstDirectedPaths.class
package edu.princeton.cs.algs4;
public synchronized class DepthFirstDirectedPaths {
private boolean[] marked;
private int[] edgeTo;
private final int s;
public void DepthFirstDirectedPaths(Digraph, int);
private void dfs(Digraph, int);
public boolean hasPathTo(int);
public Iterable pathTo(int);
private void validateVertex(int);
public static void main(String[]);
}
edu/princeton/cs/algs4/DepthFirstOrder.class
package edu.princeton.cs.algs4;
public synchronized class DepthFirstOrder {
private boolean[] marked;
private int[] pre;
private int[] post;
private Queue preorder;
private Queue postorder;
private int preCounter;
private int postCounter;
public void DepthFirstOrder(Digraph);
public void DepthFirstOrder(EdgeWeightedDigraph);
private void dfs(Digraph, int);
private void dfs(EdgeWeightedDigraph, int);
public int pre(int);
public int post(int);
public Iterable post();
public Iterable pre();
public Iterable reversePost();
private boolean check();
private void validateVertex(int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/DepthFirstPaths.class
package edu.princeton.cs.algs4;
public synchronized class DepthFirstPaths {
private boolean[] marked;
private int[] edgeTo;
private final int s;
public void DepthFirstPaths(Graph, int);
private void dfs(Graph, int);
public boolean hasPathTo(int);
public Iterable pathTo(int);
private void validateVertex(int);
public static void main(String[]);
}
edu/princeton/cs/algs4/DepthFirstSearch.class
package edu.princeton.cs.algs4;
public synchronized class DepthFirstSearch {
private boolean[] marked;
private int count;
public void DepthFirstSearch(Graph, int);
private void dfs(Graph, int);
public boolean marked(int);
public int count();
private void validateVertex(int);
public static void main(String[]);
}
edu/princeton/cs/algs4/Digraph.class
package edu.princeton.cs.algs4;
public synchronized class Digraph {
private static final String NEWLINE;
private final int V;
private int E;
private Bag[] adj;
private int[] indegree;
public void Digraph(int);
public void Digraph(In);
public void Digraph(Digraph);
public int V();
public int E();
private void validateVertex(int);
public void addEdge(int, int);
public Iterable adj(int);
public int outdegree(int);
public int indegree(int);
public Digraph reverse();
public String toString();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/DigraphGenerator$1.class
package edu.princeton.cs.algs4;
synchronized class DigraphGenerator$1 {
}
edu/princeton/cs/algs4/DigraphGenerator.class
package edu.princeton.cs.algs4;
public synchronized class DigraphGenerator {
private void DigraphGenerator();
public static Digraph simple(int, int);
public static Digraph simple(int, double);
public static Digraph complete(int);
public static Digraph dag(int, int);
public static Digraph tournament(int);
public static Digraph completeRootedInDAG(int);
public static Digraph rootedInDAG(int, int);
public static Digraph completeRootedOutDAG(int);
public static Digraph rootedOutDAG(int, int);
public static Digraph rootedInTree(int);
public static Digraph rootedOutTree(int);
public static Digraph path(int);
public static Digraph binaryTree(int);
public static Digraph cycle(int);
public static Digraph eulerianCycle(int, int);
public static Digraph eulerianPath(int, int);
public static Digraph strong(int, int, int);
public static void main(String[]);
}
edu/princeton/cs/algs4/DigraphGenerator$Edge.class
package edu.princeton.cs.algs4;
final synchronized class DigraphGenerator$Edge implements Comparable {
private final int v;
private final int w;
private void DigraphGenerator$Edge(int, int);
public int compareTo(DigraphGenerator$Edge);
}
edu/princeton/cs/algs4/DijkstraAllPairsSP.class
package edu.princeton.cs.algs4;
public synchronized class DijkstraAllPairsSP {
private DijkstraSP[] all;
public void DijkstraAllPairsSP(EdgeWeightedDigraph);
public Iterable path(int, int);
public boolean hasPath(int, int);
public double dist(int, int);
private void validateVertex(int);
public static void main(String[]);
}
edu/princeton/cs/algs4/DijkstraSP.class
package edu.princeton.cs.algs4;
public synchronized class DijkstraSP {
private double[] distTo;
private DirectedEdge[] edgeTo;
private IndexMinPQ pq;
public void DijkstraSP(EdgeWeightedDigraph, int);
private void relax(DirectedEdge);
public double distTo(int);
public boolean hasPathTo(int);
public Iterable pathTo(int);
private boolean check(EdgeWeightedDigraph, int);
private void validateVertex(int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/DijkstraUndirectedSP.class
package edu.princeton.cs.algs4;
public synchronized class DijkstraUndirectedSP {
private double[] distTo;
private Edge[] edgeTo;
private IndexMinPQ pq;
public void DijkstraUndirectedSP(EdgeWeightedGraph, int);
private void relax(Edge, int);
public double distTo(int);
public boolean hasPathTo(int);
public Iterable pathTo(int);
private boolean check(EdgeWeightedGraph, int);
private void validateVertex(int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/DirectedCycle.class
package edu.princeton.cs.algs4;
public synchronized class DirectedCycle {
private boolean[] marked;
private int[] edgeTo;
private boolean[] onStack;
private Stack cycle;
public void DirectedCycle(Digraph);
private void dfs(Digraph, int);
public boolean hasCycle();
public Iterable cycle();
private boolean check();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/DirectedCycleX.class
package edu.princeton.cs.algs4;
public synchronized class DirectedCycleX {
private Stack cycle;
public void DirectedCycleX(Digraph);
public Iterable cycle();
public boolean hasCycle();
private boolean check();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/DirectedDFS.class
package edu.princeton.cs.algs4;
public synchronized class DirectedDFS {
private boolean[] marked;
private int count;
public void DirectedDFS(Digraph, int);
public void DirectedDFS(Digraph, Iterable);
private void dfs(Digraph, int);
public boolean marked(int);
public int count();
private void validateVertex(int);
private void validateVertices(Iterable);
public static void main(String[]);
}
edu/princeton/cs/algs4/DirectedEdge.class
package edu.princeton.cs.algs4;
public synchronized class DirectedEdge {
private final int v;
private final int w;
private final double weight;
public void DirectedEdge(int, int, double);
public int from();
public int to();
public double weight();
public String toString();
public static void main(String[]);
}
edu/princeton/cs/algs4/DirectedEulerianCycle.class
package edu.princeton.cs.algs4;
public synchronized class DirectedEulerianCycle {
private Stack cycle;
public void DirectedEulerianCycle(Digraph);
public Iterable cycle();
public boolean hasEulerianCycle();
private static int nonIsolatedVertex(Digraph);
private static boolean satisfiesNecessaryAndSufficientConditions(Digraph);
private boolean certifySolution(Digraph);
private static void unitTest(Digraph, String);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/DirectedEulerianPath.class
package edu.princeton.cs.algs4;
public synchronized class DirectedEulerianPath {
private Stack path;
public void DirectedEulerianPath(Digraph);
public Iterable path();
public boolean hasEulerianPath();
private static int nonIsolatedVertex(Digraph);
private static boolean satisfiesNecessaryAndSufficientConditions(Digraph);
private boolean check(Digraph);
private static void unitTest(Digraph, String);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/DoublingRatio.class
package edu.princeton.cs.algs4;
public synchronized class DoublingRatio {
private static final int MAXIMUM_INTEGER = 1000000;
private void DoublingRatio();
public static double timeTrial(int);
public static void main(String[]);
}
edu/princeton/cs/algs4/DoublingTest.class
package edu.princeton.cs.algs4;
public synchronized class DoublingTest {
private static final int MAXIMUM_INTEGER = 1000000;
private void DoublingTest();
public static double timeTrial(int);
public static void main(String[]);
}
edu/princeton/cs/algs4/Draw.class
package edu.princeton.cs.algs4;
public final synchronized class Draw implements java.awt.event.ActionListener, java.awt.event.MouseListener, java.awt.event.MouseMotionListener, java.awt.event.KeyListener {
public static final java.awt.Color BLACK;
public static final java.awt.Color BLUE;
public static final java.awt.Color CYAN;
public static final java.awt.Color DARK_GRAY;
public static final java.awt.Color GRAY;
public static final java.awt.Color GREEN;
public static final java.awt.Color LIGHT_GRAY;
public static final java.awt.Color MAGENTA;
public static final java.awt.Color ORANGE;
public static final java.awt.Color PINK;
public static final java.awt.Color RED;
public static final java.awt.Color WHITE;
public static final java.awt.Color YELLOW;
public static final java.awt.Color BOOK_BLUE;
public static final java.awt.Color BOOK_LIGHT_BLUE;
public static final java.awt.Color BOOK_RED;
public static final java.awt.Color PRINCETON_ORANGE;
private static final java.awt.Color DEFAULT_PEN_COLOR;
private static final java.awt.Color DEFAULT_CLEAR_COLOR;
private static final double BORDER = 0.0;
private static final double DEFAULT_XMIN = 0.0;
private static final double DEFAULT_XMAX = 1.0;
private static final double DEFAULT_YMIN = 0.0;
private static final double DEFAULT_YMAX = 1.0;
private static final int DEFAULT_SIZE = 512;
private static final double DEFAULT_PEN_RADIUS = 0.002;
private static final java.awt.Font DEFAULT_FONT;
private java.awt.Color penColor;
private int width;
private int height;
private double penRadius;
private boolean defer;
private double xmin;
private double ymin;
private double xmax;
private double ymax;
private String name;
private final Object mouseLock;
private final Object keyLock;
private java.awt.Font font;
private javax.swing.JLabel draw;
private java.awt.image.BufferedImage offscreenImage;
private java.awt.image.BufferedImage onscreenImage;
private java.awt.Graphics2D offscreen;
private java.awt.Graphics2D onscreen;
private javax.swing.JFrame frame;
private boolean isMousePressed;
private double mouseX;
private double mouseY;
private final java.util.LinkedList keysTyped;
private final java.util.TreeSet keysDown;
private final java.util.ArrayList listeners;
public void Draw(String);
public void Draw();
private void init();
public void setLocationOnScreen(int, int);
public void setDefaultCloseOperation(int);
public void setCanvasSize(int, int);
private javax.swing.JMenuBar createMenuBar();
private static void validate(double, String);
private static void validateNonnegative(double, String);
private static void validateNotNull(Object, String);
public void setXscale();
public void setYscale();
public void setXscale(double, double);
public void setYscale(double, double);
private double scaleX(double);
private double scaleY(double);
private double factorX(double);
private double factorY(double);
private double userX(double);
private double userY(double);
public void clear();
public void clear(java.awt.Color);
public double getPenRadius();
public void setPenRadius();
public void setPenRadius(double);
public java.awt.Color getPenColor();
public void setPenColor();
public void setPenColor(java.awt.Color);
public void setPenColor(int, int, int);
public void xorOn();
public void xorOff();
public javax.swing.JLabel getJLabel();
public java.awt.Font getFont();
public void setFont();
public void setFont(java.awt.Font);
public void line(double, double, double, double);
private void pixel(double, double);
public void point(double, double);
public void circle(double, double, double);
public void filledCircle(double, double, double);
public void ellipse(double, double, double, double);
public void filledEllipse(double, double, double, double);
public void arc(double, double, double, double, double);
public void square(double, double, double);
public void filledSquare(double, double, double);
public void rectangle(double, double, double, double);
public void filledRectangle(double, double, double, double);
public void polygon(double[], double[]);
public void filledPolygon(double[], double[]);
private static java.awt.Image getImage(String);
public void picture(double, double, String);
public void picture(double, double, String, double);
public void picture(double, double, String, double, double);
public void picture(double, double, String, double, double, double);
public void text(double, double, String);
public void text(double, double, String, double);
public void textLeft(double, double, String);
public void textRight(double, double, String);
public void show(int);
public void pause(int);
public void show();
private void draw();
public void enableDoubleBuffering();
public void disableDoubleBuffering();
public void save(String);
public void actionPerformed(java.awt.event.ActionEvent);
public void addListener(DrawListener);
public boolean isMousePressed();
public boolean mousePressed();
public double mouseX();
public double mouseY();
public void mouseEntered(java.awt.event.MouseEvent);
public void mouseExited(java.awt.event.MouseEvent);
public void mousePressed(java.awt.event.MouseEvent);
public void mouseReleased(java.awt.event.MouseEvent);
public void mouseClicked(java.awt.event.MouseEvent);
public void mouseDragged(java.awt.event.MouseEvent);
public void mouseMoved(java.awt.event.MouseEvent);
public boolean hasNextKeyTyped();
public char nextKeyTyped();
public boolean isKeyPressed(int);
public void keyTyped(java.awt.event.KeyEvent);
public void keyPressed(java.awt.event.KeyEvent);
public void keyReleased(java.awt.event.KeyEvent);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/DrawListener.class
package edu.princeton.cs.algs4;
public abstract interface DrawListener {
public abstract void mousePressed(double, double);
public abstract void mouseDragged(double, double);
public abstract void mouseReleased(double, double);
public abstract void mouseClicked(double, double);
public abstract void keyTyped(char);
public abstract void keyPressed(int);
public abstract void keyReleased(int);
}
edu/princeton/cs/algs4/Draw$RetinaImageIcon.class
package edu.princeton.cs.algs4;
synchronized class Draw$RetinaImageIcon extends javax.swing.ImageIcon {
public void Draw$RetinaImageIcon(java.awt.Image);
public int getIconWidth();
public int getIconHeight();
public synchronized void paintIcon(java.awt.Component, java.awt.Graphics, int, int);
}
edu/princeton/cs/algs4/Edge.class
package edu.princeton.cs.algs4;
public synchronized class Edge implements Comparable {
private final int v;
private final int w;
private final double weight;
public void Edge(int, int, double);
public double weight();
public int either();
public int other(int);
public int compareTo(Edge);
public String toString();
public static void main(String[]);
}
edu/princeton/cs/algs4/EdgeWeightedDigraph.class
package edu.princeton.cs.algs4;
public synchronized class EdgeWeightedDigraph {
private static final String NEWLINE;
private final int V;
private int E;
private Bag[] adj;
private int[] indegree;
public void EdgeWeightedDigraph(int);
public void EdgeWeightedDigraph(int, int);
public void EdgeWeightedDigraph(In);
public void EdgeWeightedDigraph(EdgeWeightedDigraph);
public int V();
public int E();
private void validateVertex(int);
public void addEdge(DirectedEdge);
public Iterable adj(int);
public int outdegree(int);
public int indegree(int);
public Iterable edges();
public String toString();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/EdgeWeightedDirectedCycle.class
package edu.princeton.cs.algs4;
public synchronized class EdgeWeightedDirectedCycle {
private boolean[] marked;
private DirectedEdge[] edgeTo;
private boolean[] onStack;
private Stack cycle;
public void EdgeWeightedDirectedCycle(EdgeWeightedDigraph);
private void dfs(EdgeWeightedDigraph, int);
public boolean hasCycle();
public Iterable cycle();
private boolean check();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/EdgeWeightedGraph.class
package edu.princeton.cs.algs4;
public synchronized class EdgeWeightedGraph {
private static final String NEWLINE;
private final int V;
private int E;
private Bag[] adj;
public void EdgeWeightedGraph(int);
public void EdgeWeightedGraph(int, int);
public void EdgeWeightedGraph(In);
public void EdgeWeightedGraph(EdgeWeightedGraph);
public int V();
public int E();
private void validateVertex(int);
public void addEdge(Edge);
public Iterable adj(int);
public int degree(int);
public Iterable edges();
public String toString();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/EulerianCycle.class
package edu.princeton.cs.algs4;
public synchronized class EulerianCycle {
private Stack cycle;
public void EulerianCycle(Graph);
public Iterable cycle();
public boolean hasEulerianCycle();
private static int nonIsolatedVertex(Graph);
private static boolean satisfiesNecessaryAndSufficientConditions(Graph);
private boolean certifySolution(Graph);
private static void unitTest(Graph, String);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/EulerianCycle$Edge.class
package edu.princeton.cs.algs4;
synchronized class EulerianCycle$Edge {
private final int v;
private final int w;
private boolean isUsed;
public void EulerianCycle$Edge(int, int);
public int other(int);
}
edu/princeton/cs/algs4/EulerianPath.class
package edu.princeton.cs.algs4;
public synchronized class EulerianPath {
private Stack path;
public void EulerianPath(Graph);
public Iterable path();
public boolean hasEulerianPath();
private static int nonIsolatedVertex(Graph);
private static boolean satisfiesNecessaryAndSufficientConditions(Graph);
private boolean certifySolution(Graph);
private static void unitTest(Graph, String);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/EulerianPath$Edge.class
package edu.princeton.cs.algs4;
synchronized class EulerianPath$Edge {
private final int v;
private final int w;
private boolean isUsed;
public void EulerianPath$Edge(int, int);
public int other(int);
}
edu/princeton/cs/algs4/FarthestPair.class
package edu.princeton.cs.algs4;
public synchronized class FarthestPair {
private Point2D best1;
private Point2D best2;
private double bestDistanceSquared;
public void FarthestPair(Point2D[]);
public Point2D either();
public Point2D other();
public double distance();
public static void main(String[]);
}
edu/princeton/cs/algs4/FenwickTree.class
package edu.princeton.cs.algs4;
public synchronized class FenwickTree {
int[] array;
public void FenwickTree(int);
public int rsq(int);
public int rsq(int, int);
public void update(int, int);
public int size();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/FFT.class
package edu.princeton.cs.algs4;
public synchronized class FFT {
private static final Complex ZERO;
private void FFT();
public static Complex[] fft(Complex[]);
public static Complex[] ifft(Complex[]);
public static Complex[] cconvolve(Complex[], Complex[]);
public static Complex[] convolve(Complex[], Complex[]);
private static void show(Complex[], String);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/FibonacciMinPQ$1.class
package edu.princeton.cs.algs4;
synchronized class FibonacciMinPQ$1 {
}
edu/princeton/cs/algs4/FibonacciMinPQ.class
package edu.princeton.cs.algs4;
public synchronized class FibonacciMinPQ implements Iterable {
private FibonacciMinPQ$Node head;
private FibonacciMinPQ$Node min;
private int size;
private final java.util.Comparator comp;
private java.util.HashMap table;
public void FibonacciMinPQ(java.util.Comparator);
public void FibonacciMinPQ();
public void FibonacciMinPQ(Object[]);
public void FibonacciMinPQ(java.util.Comparator, Object[]);
public boolean isEmpty();
public int size();
public void insert(Object);
public Object minKey();
public Object delMin();
public FibonacciMinPQ union(FibonacciMinPQ);
private boolean greater(Object, Object);
private void link(FibonacciMinPQ$Node, FibonacciMinPQ$Node);
private void consolidate();
private FibonacciMinPQ$Node insert(FibonacciMinPQ$Node, FibonacciMinPQ$Node);
private FibonacciMinPQ$Node cut(FibonacciMinPQ$Node, FibonacciMinPQ$Node);
private FibonacciMinPQ$Node meld(FibonacciMinPQ$Node, FibonacciMinPQ$Node);
public java.util.Iterator iterator();
}
edu/princeton/cs/algs4/FibonacciMinPQ$MyComparator.class
package edu.princeton.cs.algs4;
synchronized class FibonacciMinPQ$MyComparator implements java.util.Comparator {
private void FibonacciMinPQ$MyComparator(FibonacciMinPQ);
public int compare(Object, Object);
}
edu/princeton/cs/algs4/FibonacciMinPQ$MyIterator.class
package edu.princeton.cs.algs4;
synchronized class FibonacciMinPQ$MyIterator implements java.util.Iterator {
private FibonacciMinPQ copy;
public void FibonacciMinPQ$MyIterator(FibonacciMinPQ);
private void insertAll(FibonacciMinPQ$Node);
public void remove();
public boolean hasNext();
public Object next();
}
edu/princeton/cs/algs4/FibonacciMinPQ$Node.class
package edu.princeton.cs.algs4;
synchronized class FibonacciMinPQ$Node {
Object key;
int order;
FibonacciMinPQ$Node prev;
FibonacciMinPQ$Node next;
FibonacciMinPQ$Node child;
private void FibonacciMinPQ$Node(FibonacciMinPQ);
}
edu/princeton/cs/algs4/FileIndex.class
package edu.princeton.cs.algs4;
public synchronized class FileIndex {
private void FileIndex();
public static void main(String[]);
}
edu/princeton/cs/algs4/FlowEdge.class
package edu.princeton.cs.algs4;
public synchronized class FlowEdge {
private static final double FLOATING_POINT_EPSILON = 1.0E-10;
private final int v;
private final int w;
private final double capacity;
private double flow;
public void FlowEdge(int, int, double);
public void FlowEdge(int, int, double, double);
public void FlowEdge(FlowEdge);
public int from();
public int to();
public double capacity();
public double flow();
public int other(int);
public double residualCapacityTo(int);
public void addResidualFlowTo(int, double);
public String toString();
public static void main(String[]);
}
edu/princeton/cs/algs4/FlowNetwork.class
package edu.princeton.cs.algs4;
public synchronized class FlowNetwork {
private static final String NEWLINE;
private final int V;
private int E;
private Bag[] adj;
public void FlowNetwork(int);
public void FlowNetwork(int, int);
public void FlowNetwork(In);
public int V();
public int E();
private void validateVertex(int);
public void addEdge(FlowEdge);
public Iterable adj(int);
public Iterable edges();
public String toString();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/FloydWarshall.class
package edu.princeton.cs.algs4;
public synchronized class FloydWarshall {
private boolean hasNegativeCycle;
private double[][] distTo;
private DirectedEdge[][] edgeTo;
public void FloydWarshall(AdjMatrixEdgeWeightedDigraph);
public boolean hasNegativeCycle();
public Iterable negativeCycle();
public boolean hasPath(int, int);
public double dist(int, int);
public Iterable path(int, int);
private boolean check(AdjMatrixEdgeWeightedDigraph);
private void validateVertex(int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/FordFulkerson.class
package edu.princeton.cs.algs4;
public synchronized class FordFulkerson {
private static final double FLOATING_POINT_EPSILON = 1.0E-11;
private final int V;
private boolean[] marked;
private FlowEdge[] edgeTo;
private double value;
public void FordFulkerson(FlowNetwork, int, int);
public double value();
public boolean inCut(int);
private void validate(int);
private boolean hasAugmentingPath(FlowNetwork, int, int);
private double excess(FlowNetwork, int);
private boolean isFeasible(FlowNetwork, int, int);
private boolean check(FlowNetwork, int, int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/FrequencyCounter.class
package edu.princeton.cs.algs4;
public synchronized class FrequencyCounter {
private void FrequencyCounter();
public static void main(String[]);
}
edu/princeton/cs/algs4/GabowSCC.class
package edu.princeton.cs.algs4;
public synchronized class GabowSCC {
private boolean[] marked;
private int[] id;
private int[] preorder;
private int pre;
private int count;
private Stack stack1;
private Stack stack2;
public void GabowSCC(Digraph);
private void dfs(Digraph, int);
public int count();
public boolean stronglyConnected(int, int);
public int id(int);
private boolean check(Digraph);
private void validateVertex(int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/GaussianElimination.class
package edu.princeton.cs.algs4;
public synchronized class GaussianElimination {
private static final double EPSILON = 1.0E-8;
private final int m;
private final int n;
private double[][] a;
public void GaussianElimination(double[][], double[]);
private void forwardElimination();
private void swap(int, int);
private void pivot(int);
public double[] primal();
public boolean isFeasible();
private boolean certifySolution(double[][], double[]);
private static void test(String, double[][], double[]);
private static void test1();
private static void test2();
private static void test3();
private static void test4();
private static void test5();
private static void test6();
private static void test7();
private static void test8();
private static void test9();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/GaussJordanElimination.class
package edu.princeton.cs.algs4;
public synchronized class GaussJordanElimination {
private static final double EPSILON = 1.0E-8;
private final int n;
private double[][] a;
public void GaussJordanElimination(double[][], double[]);
private void solve();
private void swap(int, int);
private void pivot(int, int);
public double[] primal();
public double[] dual();
public boolean isFeasible();
private void show();
private boolean certifySolution(double[][], double[]);
private static void test(String, double[][], double[]);
private static void test1();
private static void test2();
private static void test3();
private static void test4();
private static void test5();
private static void test6();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/Genome.class
package edu.princeton.cs.algs4;
public synchronized class Genome {
private void Genome();
public static void compress();
public static void expand();
public static void main(String[]);
}
edu/princeton/cs/algs4/GlobalMincut.class
package edu.princeton.cs.algs4;
public synchronized class GlobalMincut {
private static final double FLOATING_POINT_EPSILON = 1.0E-11;
private double weight;
private boolean[] cut;
private int V;
public void GlobalMincut(EdgeWeightedGraph);
private void validate(EdgeWeightedGraph);
public double weight();
public boolean cut(int);
private void makeCut(int, UF);
private void minCut(EdgeWeightedGraph, int);
private GlobalMincut$CutPhase minCutPhase(EdgeWeightedGraph, boolean[], GlobalMincut$CutPhase);
private EdgeWeightedGraph contractEdge(EdgeWeightedGraph, int, int);
private boolean check(EdgeWeightedGraph);
private void validateVertex(int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/GlobalMincut$CutPhase.class
package edu.princeton.cs.algs4;
synchronized class GlobalMincut$CutPhase {
private double weight;
private int s;
private int t;
public void GlobalMincut$CutPhase(GlobalMincut, double, int, int);
}
edu/princeton/cs/algs4/GrahamScan.class
package edu.princeton.cs.algs4;
public synchronized class GrahamScan {
private Stack hull;
public void GrahamScan(Point2D[]);
public Iterable hull();
private boolean isConvex();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/Graph.class
package edu.princeton.cs.algs4;
public synchronized class Graph {
private static final String NEWLINE;
private final int V;
private int E;
private Bag[] adj;
public void Graph(int);
public void Graph(In);
public void Graph(Graph);
public int V();
public int E();
private void validateVertex(int);
public void addEdge(int, int);
public Iterable adj(int);
public int degree(int);
public String toString();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/GraphGenerator$1.class
package edu.princeton.cs.algs4;
synchronized class GraphGenerator$1 {
}
edu/princeton/cs/algs4/GraphGenerator.class
package edu.princeton.cs.algs4;
public synchronized class GraphGenerator {
private void GraphGenerator();
public static Graph simple(int, int);
public static Graph simple(int, double);
public static Graph complete(int);
public static Graph completeBipartite(int, int);
public static Graph bipartite(int, int, int);
public static Graph bipartite(int, int, double);
public static Graph path(int);
public static Graph binaryTree(int);
public static Graph cycle(int);
public static Graph eulerianCycle(int, int);
public static Graph eulerianPath(int, int);
public static Graph wheel(int);
public static Graph star(int);
public static Graph regular(int, int);
public static Graph tree(int);
public static void main(String[]);
}
edu/princeton/cs/algs4/GraphGenerator$Edge.class
package edu.princeton.cs.algs4;
final synchronized class GraphGenerator$Edge implements Comparable {
private int v;
private int w;
private void GraphGenerator$Edge(int, int);
public int compareTo(GraphGenerator$Edge);
}
edu/princeton/cs/algs4/GrayscalePicture.class
package edu.princeton.cs.algs4;
public final synchronized class GrayscalePicture implements java.awt.event.ActionListener {
private java.awt.image.BufferedImage image;
private javax.swing.JFrame frame;
private String filename;
private boolean isOriginUpperLeft;
private final int width;
private final int height;
public void GrayscalePicture(int, int);
public void GrayscalePicture(GrayscalePicture);
public void GrayscalePicture(String);
private static java.awt.Color toGray(java.awt.Color);
public javax.swing.JLabel getJLabel();
public void setOriginUpperLeft();
public void setOriginLowerLeft();
public void show();
public int height();
public int width();
private void validateRowIndex(int);
private void validateColumnIndex(int);
private void validateGrayscaleValue(int);
public java.awt.Color get(int, int);
public int getGrayscale(int, int);
public void set(int, int, java.awt.Color);
public void setGrayscale(int, int, int);
public boolean equals(Object);
public String toString();
public int hashCode();
public void save(String);
public void save(java.io.File);
public void actionPerformed(java.awt.event.ActionEvent);
public static void main(String[]);
}
edu/princeton/cs/algs4/GREP.class
package edu.princeton.cs.algs4;
public synchronized class GREP {
private void GREP();
public static void main(String[]);
}
edu/princeton/cs/algs4/Heap.class
package edu.princeton.cs.algs4;
public synchronized class Heap {
private void Heap();
public static void sort(Comparable[]);
private static void sink(Comparable[], int, int);
private static boolean less(Comparable[], int, int);
private static void exch(Object[], int, int);
private static void show(Comparable[]);
public static void main(String[]);
}
edu/princeton/cs/algs4/HexDump.class
package edu.princeton.cs.algs4;
public synchronized class HexDump {
private void HexDump();
public static void main(String[]);
}
edu/princeton/cs/algs4/HopcroftKarp.class
package edu.princeton.cs.algs4;
public synchronized class HopcroftKarp {
private static final int UNMATCHED = -1;
private final int V;
private BipartiteX bipartition;
private int cardinality;
private int[] mate;
private boolean[] inMinVertexCover;
private boolean[] marked;
private int[] distTo;
public void HopcroftKarp(Graph);
private static String toString(Iterable);
private boolean isLevelGraphEdge(int, int);
private boolean isResidualGraphEdge(int, int);
private boolean hasAugmentingPath(Graph);
public int mate(int);
public boolean isMatched(int);
public int size();
public boolean isPerfect();
public boolean inMinVertexCover(int);
private void validate(int);
private boolean certifySolution(Graph);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/Huffman.class
package edu.princeton.cs.algs4;
public synchronized class Huffman {
private static final int R = 256;
private void Huffman();
public static void compress();
private static Huffman$Node buildTrie(int[]);
private static void writeTrie(Huffman$Node);
private static void buildCode(String[], Huffman$Node, String);
public static void expand();
private static Huffman$Node readTrie();
public static void main(String[]);
}
edu/princeton/cs/algs4/Huffman$Node.class
package edu.princeton.cs.algs4;
synchronized class Huffman$Node implements Comparable {
private final char ch;
private final int freq;
private final Huffman$Node left;
private final Huffman$Node right;
void Huffman$Node(char, int, Huffman$Node, Huffman$Node);
private boolean isLeaf();
public int compareTo(Huffman$Node);
static void
}
edu/princeton/cs/algs4/In.class
package edu.princeton.cs.algs4;
public final synchronized class In {
private static final String CHARSET_NAME = UTF-8;
private static final java.util.Locale LOCALE;
private static final java.util.regex.Pattern WHITESPACE_PATTERN;
private static final java.util.regex.Pattern EMPTY_PATTERN;
private static final java.util.regex.Pattern EVERYTHING_PATTERN;
private java.util.Scanner scanner;
public void In();
public void In(java.net.Socket);
public void In(java.net.URL);
public void In(java.io.File);
public void In(String);
public void In(java.util.Scanner);
public boolean exists();
public boolean isEmpty();
public boolean hasNextLine();
public boolean hasNextChar();
public String readLine();
public char readChar();
public String readAll();
public String readString();
public int readInt();
public double readDouble();
public float readFloat();
public long readLong();
public short readShort();
public byte readByte();
public boolean readBoolean();
public String[] readAllStrings();
public String[] readAllLines();
public int[] readAllInts();
public long[] readAllLongs();
public double[] readAllDoubles();
public void close();
public static int[] readInts(String);
public static double[] readDoubles(String);
public static String[] readStrings(String);
public static int[] readInts();
public static double[] readDoubles();
public static String[] readStrings();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/IndexBinomialMinPQ$1.class
package edu.princeton.cs.algs4;
synchronized class IndexBinomialMinPQ$1 {
}
edu/princeton/cs/algs4/IndexBinomialMinPQ.class
package edu.princeton.cs.algs4;
public synchronized class IndexBinomialMinPQ implements Iterable {
private IndexBinomialMinPQ$Node head;
private IndexBinomialMinPQ$Node[] nodes;
private int n;
private final java.util.Comparator comparator;
public void IndexBinomialMinPQ(int);
public void IndexBinomialMinPQ(int, java.util.Comparator);
public boolean isEmpty();
public boolean contains(int);
public int size();
public void insert(int, Object);
public int minIndex();
public Object minKey();
public int delMin();
public Object keyOf(int);
public void changeKey(int, Object);
public void decreaseKey(int, Object);
public void increaseKey(int, Object);
public void delete(int);
private boolean greater(Object, Object);
private void exchange(IndexBinomialMinPQ$Node, IndexBinomialMinPQ$Node);
private void link(IndexBinomialMinPQ$Node, IndexBinomialMinPQ$Node);
private void swim(int);
private void toTheRoot(int);
private IndexBinomialMinPQ$Node erase(int);
private IndexBinomialMinPQ$Node eraseMin();
private IndexBinomialMinPQ$Node merge(IndexBinomialMinPQ$Node, IndexBinomialMinPQ$Node, IndexBinomialMinPQ$Node);
private IndexBinomialMinPQ union(IndexBinomialMinPQ);
private void IndexBinomialMinPQ();
public java.util.Iterator iterator();
}
edu/princeton/cs/algs4/IndexBinomialMinPQ$MyComparator.class
package edu.princeton.cs.algs4;
synchronized class IndexBinomialMinPQ$MyComparator implements java.util.Comparator {
private void IndexBinomialMinPQ$MyComparator(IndexBinomialMinPQ);
public int compare(Object, Object);
}
edu/princeton/cs/algs4/IndexBinomialMinPQ$MyIterator.class
package edu.princeton.cs.algs4;
synchronized class IndexBinomialMinPQ$MyIterator implements java.util.Iterator {
IndexBinomialMinPQ data;
public void IndexBinomialMinPQ$MyIterator(IndexBinomialMinPQ);
private IndexBinomialMinPQ$Node clone(IndexBinomialMinPQ$Node, IndexBinomialMinPQ$Node);
public boolean hasNext();
public Integer next();
public void remove();
}
edu/princeton/cs/algs4/IndexBinomialMinPQ$Node.class
package edu.princeton.cs.algs4;
synchronized class IndexBinomialMinPQ$Node {
Object key;
int order;
int index;
IndexBinomialMinPQ$Node parent;
IndexBinomialMinPQ$Node child;
IndexBinomialMinPQ$Node sibling;
private void IndexBinomialMinPQ$Node(IndexBinomialMinPQ);
}
edu/princeton/cs/algs4/IndexFibonacciMinPQ$1.class
package edu.princeton.cs.algs4;
synchronized class IndexFibonacciMinPQ$1 {
}
edu/princeton/cs/algs4/IndexFibonacciMinPQ.class
package edu.princeton.cs.algs4;
public synchronized class IndexFibonacciMinPQ implements Iterable {
private IndexFibonacciMinPQ$Node[] nodes;
private IndexFibonacciMinPQ$Node head;
private IndexFibonacciMinPQ$Node min;
private int size;
private int n;
private final java.util.Comparator comp;
private java.util.HashMap table;
public void IndexFibonacciMinPQ(int);
public void IndexFibonacciMinPQ(java.util.Comparator, int);
public boolean isEmpty();
public boolean contains(int);
public int size();
public void insert(int, Object);
public int minIndex();
public Object minKey();
public int delMin();
public Object keyOf(int);
public void changeKey(int, Object);
public void decreaseKey(int, Object);
public void increaseKey(int, Object);
public void delete(int);
private boolean greater(Object, Object);
private void link(IndexFibonacciMinPQ$Node, IndexFibonacciMinPQ$Node);
private void cut(int);
private void consolidate();
private IndexFibonacciMinPQ$Node insert(IndexFibonacciMinPQ$Node, IndexFibonacciMinPQ$Node);
private IndexFibonacciMinPQ$Node cut(IndexFibonacciMinPQ$Node, IndexFibonacciMinPQ$Node);
private IndexFibonacciMinPQ$Node meld(IndexFibonacciMinPQ$Node, IndexFibonacciMinPQ$Node);
public java.util.Iterator iterator();
}
edu/princeton/cs/algs4/IndexFibonacciMinPQ$MyComparator.class
package edu.princeton.cs.algs4;
synchronized class IndexFibonacciMinPQ$MyComparator implements java.util.Comparator {
private void IndexFibonacciMinPQ$MyComparator(IndexFibonacciMinPQ);
public int compare(Object, Object);
}
edu/princeton/cs/algs4/IndexFibonacciMinPQ$MyIterator.class
package edu.princeton.cs.algs4;
synchronized class IndexFibonacciMinPQ$MyIterator implements java.util.Iterator {
private IndexFibonacciMinPQ copy;
public void IndexFibonacciMinPQ$MyIterator(IndexFibonacciMinPQ);
public void remove();
public boolean hasNext();
public Integer next();
}
edu/princeton/cs/algs4/IndexFibonacciMinPQ$Node.class
package edu.princeton.cs.algs4;
synchronized class IndexFibonacciMinPQ$Node {
Object key;
int order;
int index;
IndexFibonacciMinPQ$Node prev;
IndexFibonacciMinPQ$Node next;
IndexFibonacciMinPQ$Node parent;
IndexFibonacciMinPQ$Node child;
boolean mark;
private void IndexFibonacciMinPQ$Node(IndexFibonacciMinPQ);
}
edu/princeton/cs/algs4/IndexMaxPQ.class
package edu.princeton.cs.algs4;
public synchronized class IndexMaxPQ implements Iterable {
private int maxN;
private int n;
private int[] pq;
private int[] qp;
private Comparable[] keys;
public void IndexMaxPQ(int);
public boolean isEmpty();
public boolean contains(int);
public int size();
public void insert(int, Comparable);
public int maxIndex();
public Comparable maxKey();
public int delMax();
public Comparable keyOf(int);
public void changeKey(int, Comparable);
public void change(int, Comparable);
public void increaseKey(int, Comparable);
public void decreaseKey(int, Comparable);
public void delete(int);
private void validateIndex(int);
private boolean less(int, int);
private void exch(int, int);
private void swim(int);
private void sink(int);
public java.util.Iterator iterator();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/IndexMaxPQ$HeapIterator.class
package edu.princeton.cs.algs4;
synchronized class IndexMaxPQ$HeapIterator implements java.util.Iterator {
private IndexMaxPQ copy;
public void IndexMaxPQ$HeapIterator(IndexMaxPQ);
public boolean hasNext();
public void remove();
public Integer next();
}
edu/princeton/cs/algs4/IndexMinPQ.class
package edu.princeton.cs.algs4;
public synchronized class IndexMinPQ implements Iterable {
private int maxN;
private int n;
private int[] pq;
private int[] qp;
private Comparable[] keys;
public void IndexMinPQ(int);
public boolean isEmpty();
public boolean contains(int);
public int size();
public void insert(int, Comparable);
public int minIndex();
public Comparable minKey();
public int delMin();
public Comparable keyOf(int);
public void changeKey(int, Comparable);
public void change(int, Comparable);
public void decreaseKey(int, Comparable);
public void increaseKey(int, Comparable);
public void delete(int);
private void validateIndex(int);
private boolean greater(int, int);
private void exch(int, int);
private void swim(int);
private void sink(int);
public java.util.Iterator iterator();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/IndexMinPQ$HeapIterator.class
package edu.princeton.cs.algs4;
synchronized class IndexMinPQ$HeapIterator implements java.util.Iterator {
private IndexMinPQ copy;
public void IndexMinPQ$HeapIterator(IndexMinPQ);
public boolean hasNext();
public void remove();
public Integer next();
}
edu/princeton/cs/algs4/IndexMultiwayMinPQ$1.class
package edu.princeton.cs.algs4;
synchronized class IndexMultiwayMinPQ$1 {
}
edu/princeton/cs/algs4/IndexMultiwayMinPQ.class
package edu.princeton.cs.algs4;
public synchronized class IndexMultiwayMinPQ implements Iterable {
private final int d;
private int n;
private int nmax;
private int[] pq;
private int[] qp;
private Object[] keys;
private final java.util.Comparator comp;
public void IndexMultiwayMinPQ(int, int);
public void IndexMultiwayMinPQ(int, java.util.Comparator, int);
public boolean isEmpty();
public boolean contains(int);
public int size();
public void insert(int, Object);
public int minIndex();
public Object minKey();
public int delMin();
public Object keyOf(int);
public void changeKey(int, Object);
public void decreaseKey(int, Object);
public void increaseKey(int, Object);
public void delete(int);
private boolean greater(int, int);
private void exch(int, int);
private void swim(int);
private void sink(int);
private int minChild(int);
public java.util.Iterator iterator();
}
edu/princeton/cs/algs4/IndexMultiwayMinPQ$MyComparator.class
package edu.princeton.cs.algs4;
synchronized class IndexMultiwayMinPQ$MyComparator implements java.util.Comparator {
private void IndexMultiwayMinPQ$MyComparator(IndexMultiwayMinPQ);
public int compare(Object, Object);
}
edu/princeton/cs/algs4/IndexMultiwayMinPQ$MyIterator.class
package edu.princeton.cs.algs4;
synchronized class IndexMultiwayMinPQ$MyIterator implements java.util.Iterator {
IndexMultiwayMinPQ clone;
public void IndexMultiwayMinPQ$MyIterator(IndexMultiwayMinPQ);
public boolean hasNext();
public Integer next();
public void remove();
}
edu/princeton/cs/algs4/InplaceMSD.class
package edu.princeton.cs.algs4;
public synchronized class InplaceMSD {
private static final int R = 256;
private static final int CUTOFF = 15;
private void InplaceMSD();
public static void sort(String[]);
private static int charAt(String, int);
private static void sort(String[], int, int, int);
private static void insertion(String[], int, int, int);
private static void exch(String[], int, int);
private static boolean less(String, String, int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/Insertion.class
package edu.princeton.cs.algs4;
public synchronized class Insertion {
private void Insertion();
public static void sort(Comparable[]);
public static void sort(Comparable[], int, int);
public static void sort(Object[], java.util.Comparator);
public static void sort(Object[], int, int, java.util.Comparator);
public static int[] indexSort(Comparable[]);
private static boolean less(Comparable, Comparable);
private static boolean less(Object, Object, java.util.Comparator);
private static void exch(Object[], int, int);
private static void exch(int[], int, int);
private static boolean isSorted(Comparable[]);
private static boolean isSorted(Comparable[], int, int);
private static boolean isSorted(Object[], java.util.Comparator);
private static boolean isSorted(Object[], int, int, java.util.Comparator);
private static void show(Comparable[]);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/InsertionX.class
package edu.princeton.cs.algs4;
public synchronized class InsertionX {
private void InsertionX();
public static void sort(Comparable[]);
private static boolean less(Comparable, Comparable);
private static void exch(Object[], int, int);
private static boolean isSorted(Comparable[]);
private static void show(Comparable[]);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/Interval1D$1.class
package edu.princeton.cs.algs4;
synchronized class Interval1D$1 {
}
edu/princeton/cs/algs4/Interval1D.class
package edu.princeton.cs.algs4;
public synchronized class Interval1D {
public static final java.util.Comparator MIN_ENDPOINT_ORDER;
public static final java.util.Comparator MAX_ENDPOINT_ORDER;
public static final java.util.Comparator LENGTH_ORDER;
private final double min;
private final double max;
public void Interval1D(double, double);
public double left();
public double right();
public double min();
public double max();
public boolean intersects(Interval1D);
public boolean contains(double);
public double length();
public String toString();
public boolean equals(Object);
public int hashCode();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/Interval1D$LengthComparator.class
package edu.princeton.cs.algs4;
synchronized class Interval1D$LengthComparator implements java.util.Comparator {
private void Interval1D$LengthComparator();
public int compare(Interval1D, Interval1D);
}
edu/princeton/cs/algs4/Interval1D$MaxEndpointComparator.class
package edu.princeton.cs.algs4;
synchronized class Interval1D$MaxEndpointComparator implements java.util.Comparator {
private void Interval1D$MaxEndpointComparator();
public int compare(Interval1D, Interval1D);
}
edu/princeton/cs/algs4/Interval1D$MinEndpointComparator.class
package edu.princeton.cs.algs4;
synchronized class Interval1D$MinEndpointComparator implements java.util.Comparator {
private void Interval1D$MinEndpointComparator();
public int compare(Interval1D, Interval1D);
}
edu/princeton/cs/algs4/Interval2D.class
package edu.princeton.cs.algs4;
public synchronized class Interval2D {
private final Interval1D x;
private final Interval1D y;
public void Interval2D(Interval1D, Interval1D);
public boolean intersects(Interval2D);
public boolean contains(Point2D);
public double area();
public String toString();
public boolean equals(Object);
public int hashCode();
public void draw();
public static void main(String[]);
}
edu/princeton/cs/algs4/Inversions.class
package edu.princeton.cs.algs4;
public synchronized class Inversions {
private void Inversions();
private static long merge(int[], int[], int, int, int);
private static long count(int[], int[], int[], int, int);
public static long count(int[]);
private static long merge(Comparable[], Comparable[], int, int, int);
private static long count(Comparable[], Comparable[], Comparable[], int, int);
public static long count(Comparable[]);
private static boolean less(Comparable, Comparable);
private static long brute(Comparable[], int, int);
private static long brute(int[], int, int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/KMP.class
package edu.princeton.cs.algs4;
public synchronized class KMP {
private final int R;
private int[][] dfa;
private char[] pattern;
private String pat;
public void KMP(String);
public void KMP(char[], int);
public int search(String);
public int search(char[]);
public static void main(String[]);
}
edu/princeton/cs/algs4/Knuth.class
package edu.princeton.cs.algs4;
public synchronized class Knuth {
private void Knuth();
public static void shuffle(Object[]);
public static void shuffleAlternate(Object[]);
public static void main(String[]);
}
edu/princeton/cs/algs4/KosarajuSharirSCC.class
package edu.princeton.cs.algs4;
public synchronized class KosarajuSharirSCC {
private boolean[] marked;
private int[] id;
private int count;
public void KosarajuSharirSCC(Digraph);
private void dfs(Digraph, int);
public int count();
public boolean stronglyConnected(int, int);
public int id(int);
private boolean check(Digraph);
private void validateVertex(int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/KruskalMST.class
package edu.princeton.cs.algs4;
public synchronized class KruskalMST {
private static final double FLOATING_POINT_EPSILON = 1.0E-12;
private double weight;
private Queue mst;
public void KruskalMST(EdgeWeightedGraph);
public Iterable edges();
public double weight();
private boolean check(EdgeWeightedGraph);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/KWIK.class
package edu.princeton.cs.algs4;
public synchronized class KWIK {
private void KWIK();
public static void main(String[]);
}
edu/princeton/cs/algs4/LazyPrimMST.class
package edu.princeton.cs.algs4;
public synchronized class LazyPrimMST {
private static final double FLOATING_POINT_EPSILON = 1.0E-12;
private double weight;
private Queue mst;
private boolean[] marked;
private MinPQ pq;
public void LazyPrimMST(EdgeWeightedGraph);
private void prim(EdgeWeightedGraph, int);
private void scan(EdgeWeightedGraph, int);
public Iterable edges();
public double weight();
private boolean check(EdgeWeightedGraph);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/LinearProbingHashST.class
package edu.princeton.cs.algs4;
public synchronized class LinearProbingHashST {
private static final int INIT_CAPACITY = 4;
private int n;
private int m;
private Object[] keys;
private Object[] vals;
public void LinearProbingHashST();
public void LinearProbingHashST(int);
public int size();
public boolean isEmpty();
public boolean contains(Object);
private int hash(Object);
private void resize(int);
public void put(Object, Object);
public Object get(Object);
public void delete(Object);
public Iterable keys();
private boolean check();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/LinearProgramming.class
package edu.princeton.cs.algs4;
public synchronized class LinearProgramming {
private static final double EPSILON = 1.0E-10;
private double[][] a;
private int m;
private int n;
private int[] basis;
public void LinearProgramming(double[][], double[], double[]);
private void solve();
private int bland();
private int dantzig();
private int minRatioRule(int);
private void pivot(int, int);
public double value();
public double[] primal();
public double[] dual();
private boolean isPrimalFeasible(double[][], double[]);
private boolean isDualFeasible(double[][], double[]);
private boolean isOptimal(double[], double[]);
private boolean check(double[][], double[], double[]);
private void show();
private static void test(double[][], double[], double[]);
private static void test1();
private static void test2();
private static void test3();
private static void test4();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/LinearRegression.class
package edu.princeton.cs.algs4;
public synchronized class LinearRegression {
private final double intercept;
private final double slope;
private final double r2;
private final double svar0;
private final double svar1;
public void LinearRegression(double[], double[]);
public double intercept();
public double slope();
public double R2();
public double interceptStdErr();
public double slopeStdErr();
public double predict(double);
public String toString();
}
edu/princeton/cs/algs4/LinkedBag$1.class
package edu.princeton.cs.algs4;
synchronized class LinkedBag$1 {
}
edu/princeton/cs/algs4/LinkedBag.class
package edu.princeton.cs.algs4;
public synchronized class LinkedBag implements Iterable {
private LinkedBag$Node first;
private int n;
public void LinkedBag();
public boolean isEmpty();
public int size();
public void add(Object);
public java.util.Iterator iterator();
public static void main(String[]);
}
edu/princeton/cs/algs4/LinkedBag$ListIterator.class
package edu.princeton.cs.algs4;
synchronized class LinkedBag$ListIterator implements java.util.Iterator {
private LinkedBag$Node current;
public void LinkedBag$ListIterator(LinkedBag);
public boolean hasNext();
public void remove();
public Object next();
}
edu/princeton/cs/algs4/LinkedBag$Node.class
package edu.princeton.cs.algs4;
synchronized class LinkedBag$Node {
private Object item;
private LinkedBag$Node next;
private void LinkedBag$Node(LinkedBag);
}
edu/princeton/cs/algs4/LinkedQueue$1.class
package edu.princeton.cs.algs4;
synchronized class LinkedQueue$1 {
}
edu/princeton/cs/algs4/LinkedQueue.class
package edu.princeton.cs.algs4;
public synchronized class LinkedQueue implements Iterable {
private int n;
private LinkedQueue$Node first;
private LinkedQueue$Node last;
public void LinkedQueue();
public boolean isEmpty();
public int size();
public Object peek();
public void enqueue(Object);
public Object dequeue();
public String toString();
private boolean check();
public java.util.Iterator iterator();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/LinkedQueue$ListIterator.class
package edu.princeton.cs.algs4;
synchronized class LinkedQueue$ListIterator implements java.util.Iterator {
private LinkedQueue$Node current;
private void LinkedQueue$ListIterator(LinkedQueue);
public boolean hasNext();
public void remove();
public Object next();
}
edu/princeton/cs/algs4/LinkedQueue$Node.class
package edu.princeton.cs.algs4;
synchronized class LinkedQueue$Node {
private Object item;
private LinkedQueue$Node next;
private void LinkedQueue$Node(LinkedQueue);
}
edu/princeton/cs/algs4/LinkedStack$1.class
package edu.princeton.cs.algs4;
synchronized class LinkedStack$1 {
}
edu/princeton/cs/algs4/LinkedStack.class
package edu.princeton.cs.algs4;
public synchronized class LinkedStack implements Iterable {
private int n;
private LinkedStack$Node first;
public void LinkedStack();
public boolean isEmpty();
public int size();
public void push(Object);
public Object pop();
public Object peek();
public String toString();
public java.util.Iterator iterator();
private boolean check();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/LinkedStack$ListIterator.class
package edu.princeton.cs.algs4;
synchronized class LinkedStack$ListIterator implements java.util.Iterator {
private LinkedStack$Node current;
private void LinkedStack$ListIterator(LinkedStack);
public boolean hasNext();
public void remove();
public Object next();
}
edu/princeton/cs/algs4/LinkedStack$Node.class
package edu.princeton.cs.algs4;
synchronized class LinkedStack$Node {
private Object item;
private LinkedStack$Node next;
private void LinkedStack$Node(LinkedStack);
}
edu/princeton/cs/algs4/LongestCommonSubstring.class
package edu.princeton.cs.algs4;
public synchronized class LongestCommonSubstring {
private void LongestCommonSubstring();
private static String lcp(String, int, String, int);
private static int compare(String, int, String, int);
public static String lcs(String, String);
public static void main(String[]);
}
edu/princeton/cs/algs4/LongestRepeatedSubstring.class
package edu.princeton.cs.algs4;
public synchronized class LongestRepeatedSubstring {
private void LongestRepeatedSubstring();
public static String lrs(String);
public static void main(String[]);
}
edu/princeton/cs/algs4/LookupCSV.class
package edu.princeton.cs.algs4;
public synchronized class LookupCSV {
private void LookupCSV();
public static void main(String[]);
}
edu/princeton/cs/algs4/LookupIndex.class
package edu.princeton.cs.algs4;
public synchronized class LookupIndex {
private void LookupIndex();
public static void main(String[]);
}
edu/princeton/cs/algs4/LSD.class
package edu.princeton.cs.algs4;
public synchronized class LSD {
private static final int BITS_PER_BYTE = 8;
private void LSD();
public static void sort(String[], int);
public static void sort(int[]);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/LZW.class
package edu.princeton.cs.algs4;
public synchronized class LZW {
private static final int R = 256;
private static final int L = 4096;
private static final int W = 12;
private void LZW();
public static void compress();
public static void expand();
public static void main(String[]);
}
edu/princeton/cs/algs4/MaxPQ.class
package edu.princeton.cs.algs4;
public synchronized class MaxPQ implements Iterable {
private Object[] pq;
private int n;
private java.util.Comparator comparator;
public void MaxPQ(int);
public void MaxPQ();
public void MaxPQ(int, java.util.Comparator);
public void MaxPQ(java.util.Comparator);
public void MaxPQ(Object[]);
public boolean isEmpty();
public int size();
public Object max();
private void resize(int);
public void insert(Object);
public Object delMax();
private void swim(int);
private void sink(int);
private boolean less(int, int);
private void exch(int, int);
private boolean isMaxHeap();
private boolean isMaxHeapOrdered(int);
public java.util.Iterator iterator();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/MaxPQ$HeapIterator.class
package edu.princeton.cs.algs4;
synchronized class MaxPQ$HeapIterator implements java.util.Iterator {
private MaxPQ copy;
public void MaxPQ$HeapIterator(MaxPQ);
public boolean hasNext();
public void remove();
public Object next();
}
edu/princeton/cs/algs4/MergeBU.class
package edu.princeton.cs.algs4;
public synchronized class MergeBU {
private void MergeBU();
private static void merge(Comparable[], Comparable[], int, int, int);
public static void sort(Comparable[]);
private static boolean less(Comparable, Comparable);
private static boolean isSorted(Comparable[]);
private static void show(Comparable[]);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/Merge.class
package edu.princeton.cs.algs4;
public synchronized class Merge {
private void Merge();
private static void merge(Comparable[], Comparable[], int, int, int);
private static void sort(Comparable[], Comparable[], int, int);
public static void sort(Comparable[]);
private static boolean less(Comparable, Comparable);
private static boolean isSorted(Comparable[]);
private static boolean isSorted(Comparable[], int, int);
private static void merge(Comparable[], int[], int[], int, int, int);
public static int[] indexSort(Comparable[]);
private static void sort(Comparable[], int[], int[], int, int);
private static void show(Comparable[]);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/MergeX.class
package edu.princeton.cs.algs4;
public synchronized class MergeX {
private static final int CUTOFF = 7;
private void MergeX();
private static void merge(Comparable[], Comparable[], int, int, int);
private static void sort(Comparable[], Comparable[], int, int);
public static void sort(Comparable[]);
private static void insertionSort(Comparable[], int, int);
private static void exch(Object[], int, int);
private static boolean less(Comparable, Comparable);
private static boolean less(Object, Object, java.util.Comparator);
public static void sort(Object[], java.util.Comparator);
private static void merge(Object[], Object[], int, int, int, java.util.Comparator);
private static void sort(Object[], Object[], int, int, java.util.Comparator);
private static void insertionSort(Object[], int, int, java.util.Comparator);
private static boolean isSorted(Comparable[]);
private static boolean isSorted(Comparable[], int, int);
private static boolean isSorted(Object[], java.util.Comparator);
private static boolean isSorted(Object[], int, int, java.util.Comparator);
private static void show(Object[]);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/MinPQ.class
package edu.princeton.cs.algs4;
public synchronized class MinPQ implements Iterable {
private Object[] pq;
private int n;
private java.util.Comparator comparator;
public void MinPQ(int);
public void MinPQ();
public void MinPQ(int, java.util.Comparator);
public void MinPQ(java.util.Comparator);
public void MinPQ(Object[]);
public boolean isEmpty();
public int size();
public Object min();
private void resize(int);
public void insert(Object);
public Object delMin();
private void swim(int);
private void sink(int);
private boolean greater(int, int);
private void exch(int, int);
private boolean isMinHeap();
private boolean isMinHeapOrdered(int);
public java.util.Iterator iterator();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/MinPQ$HeapIterator.class
package edu.princeton.cs.algs4;
synchronized class MinPQ$HeapIterator implements java.util.Iterator {
private MinPQ copy;
public void MinPQ$HeapIterator(MinPQ);
public boolean hasNext();
public void remove();
public Object next();
}
edu/princeton/cs/algs4/MSD.class
package edu.princeton.cs.algs4;
public synchronized class MSD {
private static final int BITS_PER_BYTE = 8;
private static final int BITS_PER_INT = 32;
private static final int R = 256;
private static final int CUTOFF = 15;
private void MSD();
public static void sort(String[]);
private static int charAt(String, int);
private static void sort(String[], int, int, int, String[]);
private static void insertion(String[], int, int, int);
private static void exch(String[], int, int);
private static boolean less(String, String, int);
public static void sort(int[]);
private static void sort(int[], int, int, int, int[]);
private static void insertion(int[], int, int, int);
private static void exch(int[], int, int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/Multiway.class
package edu.princeton.cs.algs4;
public synchronized class Multiway {
private void Multiway();
private static void merge(In[]);
public static void main(String[]);
}
edu/princeton/cs/algs4/MultiwayMinPQ$1.class
package edu.princeton.cs.algs4;
synchronized class MultiwayMinPQ$1 {
}
edu/princeton/cs/algs4/MultiwayMinPQ.class
package edu.princeton.cs.algs4;
public synchronized class MultiwayMinPQ implements Iterable {
private final int d;
private int n;
private int order;
private Object[] keys;
private final java.util.Comparator comp;
public void MultiwayMinPQ(int);
public void MultiwayMinPQ(java.util.Comparator, int);
public void MultiwayMinPQ(Object[], int);
public void MultiwayMinPQ(java.util.Comparator, Object[], int);
public boolean isEmpty();
public int size();
public void insert(Object);
public Object minKey();
public Object delMin();
private boolean greater(int, int);
private void exch(int, int);
private int getN(int);
private void swim(int);
private void sink(int);
private int minChild(int);
private void resize(int);
public java.util.Iterator iterator();
}
edu/princeton/cs/algs4/MultiwayMinPQ$MyComparator.class
package edu.princeton.cs.algs4;
synchronized class MultiwayMinPQ$MyComparator implements java.util.Comparator {
private void MultiwayMinPQ$MyComparator(MultiwayMinPQ);
public int compare(Object, Object);
}
edu/princeton/cs/algs4/MultiwayMinPQ$MyIterator.class
package edu.princeton.cs.algs4;
synchronized class MultiwayMinPQ$MyIterator implements java.util.Iterator {
MultiwayMinPQ data;
public void MultiwayMinPQ$MyIterator(MultiwayMinPQ);
public boolean hasNext();
public Object next();
public void remove();
}
edu/princeton/cs/algs4/NFA.class
package edu.princeton.cs.algs4;
public synchronized class NFA {
private Digraph graph;
private String regexp;
private final int m;
public void NFA(String);
public boolean recognizes(String);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/NonrecursiveDFS.class
package edu.princeton.cs.algs4;
public synchronized class NonrecursiveDFS {
private boolean[] marked;
public void NonrecursiveDFS(Graph, int);
public boolean marked(int);
private void validateVertex(int);
public static void main(String[]);
}
edu/princeton/cs/algs4/NonrecursiveDirectedDFS.class
package edu.princeton.cs.algs4;
public synchronized class NonrecursiveDirectedDFS {
private boolean[] marked;
public void NonrecursiveDirectedDFS(Digraph, int);
public boolean marked(int);
private void validateVertex(int);
public static void main(String[]);
}
edu/princeton/cs/algs4/Out.class
package edu.princeton.cs.algs4;
public synchronized class Out {
private static final String CHARSET_NAME = UTF-8;
private static final java.util.Locale LOCALE;
private java.io.PrintWriter out;
public void Out(java.io.OutputStream);
public void Out();
public void Out(java.net.Socket);
public void Out(String);
public void close();
public void println();
public void println(Object);
public void println(boolean);
public void println(char);
public void println(double);
public void println(float);
public void println(int);
public void println(long);
public void println(byte);
public void print();
public void print(Object);
public void print(boolean);
public void print(char);
public void print(double);
public void print(float);
public void print(int);
public void print(long);
public void print(byte);
public transient void printf(String, Object[]);
public transient void printf(java.util.Locale, String, Object[]);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/Particle.class
package edu.princeton.cs.algs4;
public synchronized class Particle {
private static final double INFINITY = Infinity;
private double rx;
private double ry;
private double vx;
private double vy;
private int count;
private final double radius;
private final double mass;
private final java.awt.Color color;
public void Particle(double, double, double, double, double, double, java.awt.Color);
public void Particle();
public void move(double);
public void draw();
public int count();
public double timeToHit(Particle);
public double timeToHitVerticalWall();
public double timeToHitHorizontalWall();
public void bounceOff(Particle);
public void bounceOffVerticalWall();
public void bounceOffHorizontalWall();
public double kineticEnergy();
}
edu/princeton/cs/algs4/PatriciaSET.class
package edu.princeton.cs.algs4;
public synchronized class PatriciaSET implements Iterable {
private PatriciaSET$Node head;
private int count;
public void PatriciaSET();
public void add(String);
public boolean contains(String);
public void delete(String);
boolean isEmpty();
int size();
public java.util.Iterator iterator();
private void collect(PatriciaSET$Node, int, Queue);
public String toString();
private static boolean safeBitTest(String, int);
private static int bitTest(String, int);
private static int safeCharAt(String, int);
private static int firstDifferingBit(String, String);
public static void main(String[]);
}
edu/princeton/cs/algs4/PatriciaSET$Node.class
package edu.princeton.cs.algs4;
synchronized class PatriciaSET$Node {
private PatriciaSET$Node left;
private PatriciaSET$Node right;
private String key;
private int b;
public void PatriciaSET$Node(PatriciaSET, String, int);
}
edu/princeton/cs/algs4/PatriciaST.class
package edu.princeton.cs.algs4;
public synchronized class PatriciaST {
private PatriciaST$Node head;
private int count;
public void PatriciaST();
public void put(String, Object);
public Object get(String);
public void delete(String);
public boolean contains(String);
boolean isEmpty();
int size();
public Iterable keys();
private void keys(PatriciaST$Node, int, Queue);
private static boolean safeBitTest(String, int);
private static int bitTest(String, int);
private static int safeCharAt(String, int);
private static int firstDifferingBit(String, String);
public static void main(String[]);
}
edu/princeton/cs/algs4/PatriciaST$Node.class
package edu.princeton.cs.algs4;
synchronized class PatriciaST$Node {
private PatriciaST$Node left;
private PatriciaST$Node right;
private String key;
private Object val;
private int b;
public void PatriciaST$Node(PatriciaST, String, Object, int);
}
edu/princeton/cs/algs4/Picture.class
package edu.princeton.cs.algs4;
public final synchronized class Picture implements java.awt.event.ActionListener {
private java.awt.image.BufferedImage image;
private javax.swing.JFrame frame;
private String filename;
private boolean isOriginUpperLeft;
private final int width;
private final int height;
public void Picture(int, int);
public void Picture(Picture);
public void Picture(String);
public void Picture(java.io.File);
public javax.swing.JLabel getJLabel();
public void setOriginUpperLeft();
public void setOriginLowerLeft();
public void show();
public int height();
public int width();
private void validateRowIndex(int);
private void validateColumnIndex(int);
public java.awt.Color get(int, int);
public int getRGB(int, int);
public void set(int, int, java.awt.Color);
public void setRGB(int, int, int);
public boolean equals(Object);
public String toString();
public int hashCode();
public void save(String);
public void save(java.io.File);
public void actionPerformed(java.awt.event.ActionEvent);
public static void main(String[]);
}
edu/princeton/cs/algs4/PictureDump.class
package edu.princeton.cs.algs4;
public synchronized class PictureDump {
private void PictureDump();
public static void main(String[]);
}
edu/princeton/cs/algs4/Point2D$1.class
package edu.princeton.cs.algs4;
synchronized class Point2D$1 {
}
edu/princeton/cs/algs4/Point2D$Atan2Order.class
package edu.princeton.cs.algs4;
synchronized class Point2D$Atan2Order implements java.util.Comparator {
private void Point2D$Atan2Order(Point2D);
public int compare(Point2D, Point2D);
}
edu/princeton/cs/algs4/Point2D.class
package edu.princeton.cs.algs4;
public final synchronized class Point2D implements Comparable {
public static final java.util.Comparator X_ORDER;
public static final java.util.Comparator Y_ORDER;
public static final java.util.Comparator R_ORDER;
private final double x;
private final double y;
public void Point2D(double, double);
public double x();
public double y();
public double r();
public double theta();
private double angleTo(Point2D);
public static int ccw(Point2D, Point2D, Point2D);
public static double area2(Point2D, Point2D, Point2D);
public double distanceTo(Point2D);
public double distanceSquaredTo(Point2D);
public int compareTo(Point2D);
public java.util.Comparator polarOrder();
public java.util.Comparator atan2Order();
public java.util.Comparator distanceToOrder();
public boolean equals(Object);
public String toString();
public int hashCode();
public void draw();
public void drawTo(Point2D);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/Point2D$DistanceToOrder.class
package edu.princeton.cs.algs4;
synchronized class Point2D$DistanceToOrder implements java.util.Comparator {
private void Point2D$DistanceToOrder(Point2D);
public int compare(Point2D, Point2D);
}
edu/princeton/cs/algs4/Point2D$PolarOrder.class
package edu.princeton.cs.algs4;
synchronized class Point2D$PolarOrder implements java.util.Comparator {
private void Point2D$PolarOrder(Point2D);
public int compare(Point2D, Point2D);
}
edu/princeton/cs/algs4/Point2D$ROrder.class
package edu.princeton.cs.algs4;
synchronized class Point2D$ROrder implements java.util.Comparator {
private void Point2D$ROrder();
public int compare(Point2D, Point2D);
}
edu/princeton/cs/algs4/Point2D$XOrder.class
package edu.princeton.cs.algs4;
synchronized class Point2D$XOrder implements java.util.Comparator {
private void Point2D$XOrder();
public int compare(Point2D, Point2D);
}
edu/princeton/cs/algs4/Point2D$YOrder.class
package edu.princeton.cs.algs4;
synchronized class Point2D$YOrder implements java.util.Comparator {
private void Point2D$YOrder();
public int compare(Point2D, Point2D);
}
edu/princeton/cs/algs4/Polynomial.class
package edu.princeton.cs.algs4;
public synchronized class Polynomial {
private int[] coef;
private int degree;
public void Polynomial(int, int);
private void reduce();
public int degree();
public Polynomial plus(Polynomial);
public Polynomial minus(Polynomial);
public Polynomial times(Polynomial);
public Polynomial compose(Polynomial);
public boolean equals(Object);
public Polynomial differentiate();
public int evaluate(int);
public int compareTo(Polynomial);
public String toString();
public static void main(String[]);
}
edu/princeton/cs/algs4/PrimMST.class
package edu.princeton.cs.algs4;
public synchronized class PrimMST {
private static final double FLOATING_POINT_EPSILON = 1.0E-12;
private Edge[] edgeTo;
private double[] distTo;
private boolean[] marked;
private IndexMinPQ pq;
public void PrimMST(EdgeWeightedGraph);
private void prim(EdgeWeightedGraph, int);
private void scan(EdgeWeightedGraph, int);
public Iterable edges();
public double weight();
private boolean check(EdgeWeightedGraph);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/Queue$1.class
package edu.princeton.cs.algs4;
synchronized class Queue$1 {
}
edu/princeton/cs/algs4/Queue.class
package edu.princeton.cs.algs4;
public synchronized class Queue implements Iterable {
private Queue$Node first;
private Queue$Node last;
private int n;
public void Queue();
public boolean isEmpty();
public int size();
public Object peek();
public void enqueue(Object);
public Object dequeue();
public String toString();
public java.util.Iterator iterator();
public static void main(String[]);
}
edu/princeton/cs/algs4/Queue$ListIterator.class
package edu.princeton.cs.algs4;
synchronized class Queue$ListIterator implements java.util.Iterator {
private Queue$Node current;
public void Queue$ListIterator(Queue, Queue$Node);
public boolean hasNext();
public void remove();
public Object next();
}
edu/princeton/cs/algs4/Queue$Node.class
package edu.princeton.cs.algs4;
synchronized class Queue$Node {
private Object item;
private Queue$Node next;
private void Queue$Node();
}
edu/princeton/cs/algs4/Quick3string.class
package edu.princeton.cs.algs4;
public synchronized class Quick3string {
private static final int CUTOFF = 15;
private void Quick3string();
public static void sort(String[]);
private static int charAt(String, int);
private static void sort(String[], int, int, int);
private static void insertion(String[], int, int, int);
private static void exch(String[], int, int);
private static boolean less(String, String, int);
private static boolean isSorted(String[]);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/Quick3way.class
package edu.princeton.cs.algs4;
public synchronized class Quick3way {
private void Quick3way();
public static void sort(Comparable[]);
private static void sort(Comparable[], int, int);
private static boolean less(Comparable, Comparable);
private static void exch(Object[], int, int);
private static boolean isSorted(Comparable[]);
private static boolean isSorted(Comparable[], int, int);
private static void show(Comparable[]);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/QuickBentleyMcIlroy.class
package edu.princeton.cs.algs4;
public synchronized class QuickBentleyMcIlroy {
private static final int INSERTION_SORT_CUTOFF = 8;
private static final int MEDIAN_OF_3_CUTOFF = 40;
private void QuickBentleyMcIlroy();
public static void sort(Comparable[]);
private static void sort(Comparable[], int, int);
private static void insertionSort(Comparable[], int, int);
private static int median3(Comparable[], int, int, int);
private static boolean less(Comparable, Comparable);
private static boolean eq(Comparable, Comparable);
private static void exch(Object[], int, int);
private static boolean isSorted(Comparable[]);
private static void show(Comparable[]);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/Quick.class
package edu.princeton.cs.algs4;
public synchronized class Quick {
private void Quick();
public static void sort(Comparable[]);
private static void sort(Comparable[], int, int);
private static int partition(Comparable[], int, int);
public static Comparable select(Comparable[], int);
private static boolean less(Comparable, Comparable);
private static void exch(Object[], int, int);
private static boolean isSorted(Comparable[]);
private static boolean isSorted(Comparable[], int, int);
private static void show(Comparable[]);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/QuickFindUF.class
package edu.princeton.cs.algs4;
public synchronized class QuickFindUF {
private int[] id;
private int count;
public void QuickFindUF(int);
public int count();
public int find(int);
private void validate(int);
public boolean connected(int, int);
public void union(int, int);
public static void main(String[]);
}
edu/princeton/cs/algs4/QuickUnionUF.class
package edu.princeton.cs.algs4;
public synchronized class QuickUnionUF {
private int[] parent;
private int count;
public void QuickUnionUF(int);
public int count();
public int find(int);
private void validate(int);
public boolean connected(int, int);
public void union(int, int);
public static void main(String[]);
}
edu/princeton/cs/algs4/QuickX.class
package edu.princeton.cs.algs4;
public synchronized class QuickX {
private static final int INSERTION_SORT_CUTOFF = 8;
private void QuickX();
public static void sort(Comparable[]);
private static void sort(Comparable[], int, int);
private static int partition(Comparable[], int, int);
private static int median3(Comparable[], int, int, int);
private static boolean less(Comparable, Comparable);
private static void exch(Object[], int, int);
private static boolean isSorted(Comparable[]);
private static void show(Comparable[]);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/RabinKarp.class
package edu.princeton.cs.algs4;
public synchronized class RabinKarp {
private String pat;
private long patHash;
private int m;
private long q;
private int R;
private long RM;
public void RabinKarp(char[], int);
public void RabinKarp(String);
private long hash(String, int);
private boolean check(String, int);
public int search(String);
private static long longRandomPrime();
public static void main(String[]);
}
edu/princeton/cs/algs4/RandomSeq.class
package edu.princeton.cs.algs4;
public synchronized class RandomSeq {
private void RandomSeq();
public static void main(String[]);
}
edu/princeton/cs/algs4/RectHV.class
package edu.princeton.cs.algs4;
public final synchronized class RectHV {
private final double xmin;
private final double ymin;
private final double xmax;
private final double ymax;
public void RectHV(double, double, double, double);
public double xmin();
public double xmax();
public double ymin();
public double ymax();
public double width();
public double height();
public boolean intersects(RectHV);
public boolean contains(Point2D);
public double distanceTo(Point2D);
public double distanceSquaredTo(Point2D);
public boolean equals(Object);
public int hashCode();
public String toString();
public void draw();
}
edu/princeton/cs/algs4/RedBlackBST.class
package edu.princeton.cs.algs4;
public synchronized class RedBlackBST {
private static final boolean RED = 1;
private static final boolean BLACK = 0;
private RedBlackBST$Node root;
public void RedBlackBST();
private boolean isRed(RedBlackBST$Node);
private int size(RedBlackBST$Node);
public int size();
public boolean isEmpty();
public Object get(Comparable);
private Object get(RedBlackBST$Node, Comparable);
public boolean contains(Comparable);
public void put(Comparable, Object);
private RedBlackBST$Node put(RedBlackBST$Node, Comparable, Object);
public void deleteMin();
private RedBlackBST$Node deleteMin(RedBlackBST$Node);
public void deleteMax();
private RedBlackBST$Node deleteMax(RedBlackBST$Node);
public void delete(Comparable);
private RedBlackBST$Node delete(RedBlackBST$Node, Comparable);
private RedBlackBST$Node rotateRight(RedBlackBST$Node);
private RedBlackBST$Node rotateLeft(RedBlackBST$Node);
private void flipColors(RedBlackBST$Node);
private RedBlackBST$Node moveRedLeft(RedBlackBST$Node);
private RedBlackBST$Node moveRedRight(RedBlackBST$Node);
private RedBlackBST$Node balance(RedBlackBST$Node);
public int height();
private int height(RedBlackBST$Node);
public Comparable min();
private RedBlackBST$Node min(RedBlackBST$Node);
public Comparable max();
private RedBlackBST$Node max(RedBlackBST$Node);
public Comparable floor(Comparable);
private RedBlackBST$Node floor(RedBlackBST$Node, Comparable);
public Comparable ceiling(Comparable);
private RedBlackBST$Node ceiling(RedBlackBST$Node, Comparable);
public Comparable select(int);
private RedBlackBST$Node select(RedBlackBST$Node, int);
public int rank(Comparable);
private int rank(Comparable, RedBlackBST$Node);
public Iterable keys();
public Iterable keys(Comparable, Comparable);
private void keys(RedBlackBST$Node, Queue, Comparable, Comparable);
public int size(Comparable, Comparable);
private boolean check();
private boolean isBST();
private boolean isBST(RedBlackBST$Node, Comparable, Comparable);
private boolean isSizeConsistent();
private boolean isSizeConsistent(RedBlackBST$Node);
private boolean isRankConsistent();
private boolean is23();
private boolean is23(RedBlackBST$Node);
private boolean isBalanced();
private boolean isBalanced(RedBlackBST$Node, int);
public static void main(String[]);
}
edu/princeton/cs/algs4/RedBlackBST$Node.class
package edu.princeton.cs.algs4;
synchronized class RedBlackBST$Node {
private Comparable key;
private Object val;
private RedBlackBST$Node left;
private RedBlackBST$Node right;
private boolean color;
private int size;
public void RedBlackBST$Node(RedBlackBST, Comparable, Object, boolean, int);
}
edu/princeton/cs/algs4/ResizingArrayBag$1.class
package edu.princeton.cs.algs4;
synchronized class ResizingArrayBag$1 {
}
edu/princeton/cs/algs4/ResizingArrayBag$ArrayIterator.class
package edu.princeton.cs.algs4;
synchronized class ResizingArrayBag$ArrayIterator implements java.util.Iterator {
private int i;
private void ResizingArrayBag$ArrayIterator(ResizingArrayBag);
public boolean hasNext();
public void remove();
public Object next();
}
edu/princeton/cs/algs4/ResizingArrayBag.class
package edu.princeton.cs.algs4;
public synchronized class ResizingArrayBag implements Iterable {
private Object[] a;
private int n;
public void ResizingArrayBag();
public boolean isEmpty();
public int size();
private void resize(int);
public void add(Object);
public java.util.Iterator iterator();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/ResizingArrayQueue$1.class
package edu.princeton.cs.algs4;
synchronized class ResizingArrayQueue$1 {
}
edu/princeton/cs/algs4/ResizingArrayQueue$ArrayIterator.class
package edu.princeton.cs.algs4;
synchronized class ResizingArrayQueue$ArrayIterator implements java.util.Iterator {
private int i;
private void ResizingArrayQueue$ArrayIterator(ResizingArrayQueue);
public boolean hasNext();
public void remove();
public Object next();
}
edu/princeton/cs/algs4/ResizingArrayQueue.class
package edu.princeton.cs.algs4;
public synchronized class ResizingArrayQueue implements Iterable {
private Object[] q;
private int n;
private int first;
private int last;
public void ResizingArrayQueue();
public boolean isEmpty();
public int size();
private void resize(int);
public void enqueue(Object);
public Object dequeue();
public Object peek();
public java.util.Iterator iterator();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/ResizingArrayStack.class
package edu.princeton.cs.algs4;
public synchronized class ResizingArrayStack implements Iterable {
private Object[] a;
private int n;
public void ResizingArrayStack();
public boolean isEmpty();
public int size();
private void resize(int);
public void push(Object);
public Object pop();
public Object peek();
public java.util.Iterator iterator();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/ResizingArrayStack$ReverseArrayIterator.class
package edu.princeton.cs.algs4;
synchronized class ResizingArrayStack$ReverseArrayIterator implements java.util.Iterator {
private int i;
public void ResizingArrayStack$ReverseArrayIterator(ResizingArrayStack);
public boolean hasNext();
public void remove();
public Object next();
}
edu/princeton/cs/algs4/RunLength.class
package edu.princeton.cs.algs4;
public synchronized class RunLength {
private static final int R = 256;
private static final int LG_R = 8;
private void RunLength();
public static void expand();
public static void compress();
public static void main(String[]);
}
edu/princeton/cs/algs4/SegmentTree.class
package edu.princeton.cs.algs4;
public synchronized class SegmentTree {
private SegmentTree$Node[] heap;
private int[] array;
private int size;
public void SegmentTree(int[]);
public int size();
private void build(int, int, int);
public int rsq(int, int);
private int rsq(int, int, int);
public int rMinQ(int, int);
private int rMinQ(int, int, int);
public void update(int, int, int);
private void update(int, int, int, int);
private void propagate(int);
private void change(SegmentTree$Node, int);
private boolean contains(int, int, int, int);
private boolean intersects(int, int, int, int);
public static void main(String[]);
}
edu/princeton/cs/algs4/SegmentTree$Node.class
package edu.princeton.cs.algs4;
synchronized class SegmentTree$Node {
int sum;
int min;
Integer pendingVal;
int from;
int to;
void SegmentTree$Node();
int size();
}
edu/princeton/cs/algs4/Selection.class
package edu.princeton.cs.algs4;
public synchronized class Selection {
private void Selection();
public static void sort(Comparable[]);
public static void sort(Object[], java.util.Comparator);
private static boolean less(Comparable, Comparable);
private static boolean less(java.util.Comparator, Object, Object);
private static void exch(Object[], int, int);
private static boolean isSorted(Comparable[]);
private static boolean isSorted(Comparable[], int, int);
private static boolean isSorted(Object[], java.util.Comparator);
private static boolean isSorted(Object[], java.util.Comparator, int, int);
private static void show(Comparable[]);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/SeparateChainingHashST.class
package edu.princeton.cs.algs4;
public synchronized class SeparateChainingHashST {
private static final int INIT_CAPACITY = 4;
private int n;
private int m;
private SequentialSearchST[] st;
public void SeparateChainingHashST();
public void SeparateChainingHashST(int);
private void resize(int);
private int hash(Object);
public int size();
public boolean isEmpty();
public boolean contains(Object);
public Object get(Object);
public void put(Object, Object);
public void delete(Object);
public Iterable keys();
public static void main(String[]);
}
edu/princeton/cs/algs4/SequentialSearchST.class
package edu.princeton.cs.algs4;
public synchronized class SequentialSearchST {
private int n;
private SequentialSearchST$Node first;
public void SequentialSearchST();
public int size();
public boolean isEmpty();
public boolean contains(Object);
public Object get(Object);
public void put(Object, Object);
public void delete(Object);
private SequentialSearchST$Node delete(SequentialSearchST$Node, Object);
public Iterable keys();
public static void main(String[]);
}
edu/princeton/cs/algs4/SequentialSearchST$Node.class
package edu.princeton.cs.algs4;
synchronized class SequentialSearchST$Node {
private Object key;
private Object val;
private SequentialSearchST$Node next;
public void SequentialSearchST$Node(SequentialSearchST, Object, Object, SequentialSearchST$Node);
}
edu/princeton/cs/algs4/SET.class
package edu.princeton.cs.algs4;
public synchronized class SET implements Iterable {
private java.util.TreeSet set;
public void SET();
public void SET(SET);
public void add(Comparable);
public boolean contains(Comparable);
public void delete(Comparable);
public void remove(Comparable);
public int size();
public boolean isEmpty();
public java.util.Iterator iterator();
public Comparable max();
public Comparable min();
public Comparable ceiling(Comparable);
public Comparable floor(Comparable);
public SET union(SET);
public SET intersects(SET);
public boolean equals(Object);
public int hashCode();
public String toString();
public static void main(String[]);
}
edu/princeton/cs/algs4/Shell.class
package edu.princeton.cs.algs4;
public synchronized class Shell {
private void Shell();
public static void sort(Comparable[]);
private static boolean less(Comparable, Comparable);
private static void exch(Object[], int, int);
private static boolean isSorted(Comparable[]);
private static boolean isHsorted(Comparable[], int);
private static void show(Comparable[]);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/SparseVector.class
package edu.princeton.cs.algs4;
public synchronized class SparseVector {
private int d;
private ST st;
public void SparseVector(int);
public void put(int, double);
public double get(int);
public int nnz();
public int size();
public int dimension();
public double dot(SparseVector);
public double dot(double[]);
public double magnitude();
public double norm();
public SparseVector scale(double);
public SparseVector plus(SparseVector);
public String toString();
public static void main(String[]);
}
edu/princeton/cs/algs4/Stack$1.class
package edu.princeton.cs.algs4;
synchronized class Stack$1 {
}
edu/princeton/cs/algs4/Stack.class
package edu.princeton.cs.algs4;
public synchronized class Stack implements Iterable {
private Stack$Node first;
private int n;
public void Stack();
public boolean isEmpty();
public int size();
public void push(Object);
public Object pop();
public Object peek();
public String toString();
public java.util.Iterator iterator();
public static void main(String[]);
}
edu/princeton/cs/algs4/Stack$ListIterator.class
package edu.princeton.cs.algs4;
synchronized class Stack$ListIterator implements java.util.Iterator {
private Stack$Node current;
public void Stack$ListIterator(Stack, Stack$Node);
public boolean hasNext();
public void remove();
public Object next();
}
edu/princeton/cs/algs4/Stack$Node.class
package edu.princeton.cs.algs4;
synchronized class Stack$Node {
private Object item;
private Stack$Node next;
private void Stack$Node();
}
edu/princeton/cs/algs4/StaticSETofInts.class
package edu.princeton.cs.algs4;
public synchronized class StaticSETofInts {
private int[] a;
public void StaticSETofInts(int[]);
public boolean contains(int);
public int rank(int);
}
edu/princeton/cs/algs4/ST.class
package edu.princeton.cs.algs4;
public synchronized class ST implements Iterable {
private java.util.TreeMap st;
public void ST();
public Object get(Comparable);
public void put(Comparable, Object);
public void delete(Comparable);
public void remove(Comparable);
public boolean contains(Comparable);
public int size();
public boolean isEmpty();
public Iterable keys();
public java.util.Iterator iterator();
public Comparable min();
public Comparable max();
public Comparable ceiling(Comparable);
public Comparable floor(Comparable);
public static void main(String[]);
}
edu/princeton/cs/algs4/StdArrayIO.class
package edu.princeton.cs.algs4;
public synchronized class StdArrayIO {
private void StdArrayIO();
public static double[] readDouble1D();
public static void print(double[]);
public static double[][] readDouble2D();
public static void print(double[][]);
public static int[] readInt1D();
public static void print(int[]);
public static int[][] readInt2D();
public static void print(int[][]);
public static boolean[] readBoolean1D();
public static void print(boolean[]);
public static boolean[][] readBoolean2D();
public static void print(boolean[][]);
public static void main(String[]);
}
edu/princeton/cs/algs4/StdAudio$1.class
package edu.princeton.cs.algs4;
final synchronized class StdAudio$1 implements Runnable {
void StdAudio$1(String);
public void run();
}
edu/princeton/cs/algs4/StdAudio$2.class
package edu.princeton.cs.algs4;
final synchronized class StdAudio$2 implements Runnable {
void StdAudio$2();
public void run();
}
edu/princeton/cs/algs4/StdAudio.class
package edu.princeton.cs.algs4;
public final synchronized class StdAudio {
public static final int SAMPLE_RATE = 44100;
private static final int BYTES_PER_SAMPLE = 2;
private static final int BITS_PER_SAMPLE = 16;
private static final double MAX_16_BIT = 32768.0;
private static final int SAMPLE_BUFFER_SIZE = 4096;
private static final int MONO = 1;
private static final int STEREO = 2;
private static final boolean LITTLE_ENDIAN = 0;
private static final boolean BIG_ENDIAN = 1;
private static final boolean SIGNED = 1;
private static final boolean UNSIGNED = 0;
private static javax.sound.sampled.SourceDataLine line;
private static byte[] buffer;
private static int bufferSize;
private void StdAudio();
private static void init();
private static javax.sound.sampled.AudioInputStream getAudioInputStreamFromFile(String);
public static void close();
public static void play(double);
public static void play(double[]);
public static double[] read(String);
public static void save(String, double[]);
public static synchronized void play(String);
private static void stream(javax.sound.sampled.AudioInputStream);
public static synchronized void loop(String);
private static double[] note(double, double, double);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/StdDraw.class
package edu.princeton.cs.algs4;
public final synchronized class StdDraw implements java.awt.event.ActionListener, java.awt.event.MouseListener, java.awt.event.MouseMotionListener, java.awt.event.KeyListener {
public static final java.awt.Color BLACK;
public static final java.awt.Color BLUE;
public static final java.awt.Color CYAN;
public static final java.awt.Color DARK_GRAY;
public static final java.awt.Color GRAY;
public static final java.awt.Color GREEN;
public static final java.awt.Color LIGHT_GRAY;
public static final java.awt.Color MAGENTA;
public static final java.awt.Color ORANGE;
public static final java.awt.Color PINK;
public static final java.awt.Color RED;
public static final java.awt.Color WHITE;
public static final java.awt.Color YELLOW;
public static final java.awt.Color BOOK_BLUE;
public static final java.awt.Color BOOK_LIGHT_BLUE;
public static final java.awt.Color BOOK_RED;
public static final java.awt.Color PRINCETON_ORANGE;
private static final java.awt.Color DEFAULT_PEN_COLOR;
private static final java.awt.Color DEFAULT_CLEAR_COLOR;
private static java.awt.Color penColor;
private static final int DEFAULT_SIZE = 512;
private static int width;
private static int height;
private static final double DEFAULT_PEN_RADIUS = 0.002;
private static double penRadius;
private static boolean defer;
private static final double BORDER = 0.0;
private static final double DEFAULT_XMIN = 0.0;
private static final double DEFAULT_XMAX = 1.0;
private static final double DEFAULT_YMIN = 0.0;
private static final double DEFAULT_YMAX = 1.0;
private static double xmin;
private static double ymin;
private static double xmax;
private static double ymax;
private static Object mouseLock;
private static Object keyLock;
private static final java.awt.Font DEFAULT_FONT;
private static java.awt.Font font;
private static java.awt.image.BufferedImage offscreenImage;
private static java.awt.image.BufferedImage onscreenImage;
private static java.awt.Graphics2D offscreen;
private static java.awt.Graphics2D onscreen;
private static StdDraw std;
private static javax.swing.JFrame frame;
private static boolean isMousePressed;
private static double mouseX;
private static double mouseY;
private static java.util.LinkedList keysTyped;
private static java.util.TreeSet keysDown;
private void StdDraw();
public static void setCanvasSize();
public static void setCanvasSize(int, int);
private static void init();
private static javax.swing.JMenuBar createMenuBar();
private static void validate(double, String);
private static void validateNonnegative(double, String);
private static void validateNotNull(Object, String);
public static void setXscale();
public static void setYscale();
public static void setScale();
public static void setXscale(double, double);
public static void setYscale(double, double);
public static void setScale(double, double);
private static double scaleX(double);
private static double scaleY(double);
private static double factorX(double);
private static double factorY(double);
private static double userX(double);
private static double userY(double);
public static void clear();
public static void clear(java.awt.Color);
public static double getPenRadius();
public static void setPenRadius();
public static void setPenRadius(double);
public static java.awt.Color getPenColor();
public static void setPenColor();
public static void setPenColor(java.awt.Color);
public static void setPenColor(int, int, int);
public static java.awt.Font getFont();
public static void setFont();
public static void setFont(java.awt.Font);
public static void line(double, double, double, double);
private static void pixel(double, double);
public static void point(double, double);
public static void circle(double, double, double);
public static void filledCircle(double, double, double);
public static void ellipse(double, double, double, double);
public static void filledEllipse(double, double, double, double);
public static void arc(double, double, double, double, double);
public static void square(double, double, double);
public static void filledSquare(double, double, double);
public static void rectangle(double, double, double, double);
public static void filledRectangle(double, double, double, double);
public static void polygon(double[], double[]);
public static void filledPolygon(double[], double[]);
private static java.awt.Image getImage(String);
public static void picture(double, double, String);
public static void picture(double, double, String, double);
public static void picture(double, double, String, double, double);
public static void picture(double, double, String, double, double, double);
public static void text(double, double, String);
public static void text(double, double, String, double);
public static void textLeft(double, double, String);
public static void textRight(double, double, String);
public static void show(int);
public static void pause(int);
public static void show();
private static void draw();
public static void enableDoubleBuffering();
public static void disableDoubleBuffering();
public static void save(String);
public void actionPerformed(java.awt.event.ActionEvent);
public static boolean isMousePressed();
public static boolean mousePressed();
public static double mouseX();
public static double mouseY();
public void mouseClicked(java.awt.event.MouseEvent);
public void mouseEntered(java.awt.event.MouseEvent);
public void mouseExited(java.awt.event.MouseEvent);
public void mousePressed(java.awt.event.MouseEvent);
public void mouseReleased(java.awt.event.MouseEvent);
public void mouseDragged(java.awt.event.MouseEvent);
public void mouseMoved(java.awt.event.MouseEvent);
public static boolean hasNextKeyTyped();
public static char nextKeyTyped();
public static boolean isKeyPressed(int);
public void keyTyped(java.awt.event.KeyEvent);
public void keyPressed(java.awt.event.KeyEvent);
public void keyReleased(java.awt.event.KeyEvent);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/StdDraw$RetinaImageIcon.class
package edu.princeton.cs.algs4;
synchronized class StdDraw$RetinaImageIcon extends javax.swing.ImageIcon {
public void StdDraw$RetinaImageIcon(java.awt.Image);
public int getIconWidth();
public int getIconHeight();
public synchronized void paintIcon(java.awt.Component, java.awt.Graphics, int, int);
}
edu/princeton/cs/algs4/StdIn.class
package edu.princeton.cs.algs4;
public final synchronized class StdIn {
private static final String CHARSET_NAME = UTF-8;
private static final java.util.Locale LOCALE;
private static final java.util.regex.Pattern WHITESPACE_PATTERN;
private static final java.util.regex.Pattern EMPTY_PATTERN;
private static final java.util.regex.Pattern EVERYTHING_PATTERN;
private static java.util.Scanner scanner;
private void StdIn();
public static boolean isEmpty();
public static boolean hasNextLine();
public static boolean hasNextChar();
public static String readLine();
public static char readChar();
public static String readAll();
public static String readString();
public static int readInt();
public static double readDouble();
public static float readFloat();
public static long readLong();
public static short readShort();
public static byte readByte();
public static boolean readBoolean();
public static String[] readAllStrings();
public static String[] readAllLines();
public static int[] readAllInts();
public static long[] readAllLongs();
public static double[] readAllDoubles();
private static void resync();
private static void setScanner(java.util.Scanner);
public static int[] readInts();
public static double[] readDoubles();
public static String[] readStrings();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/StdOut.class
package edu.princeton.cs.algs4;
public final synchronized class StdOut {
private static final String CHARSET_NAME = UTF-8;
private static final java.util.Locale LOCALE;
private static java.io.PrintWriter out;
private void StdOut();
public static void println();
public static void println(Object);
public static void println(boolean);
public static void println(char);
public static void println(double);
public static void println(float);
public static void println(int);
public static void println(long);
public static void println(short);
public static void println(byte);
public static void print();
public static void print(Object);
public static void print(boolean);
public static void print(char);
public static void print(double);
public static void print(float);
public static void print(int);
public static void print(long);
public static void print(short);
public static void print(byte);
public static transient void printf(String, Object[]);
public static transient void printf(java.util.Locale, String, Object[]);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/StdRandom.class
package edu.princeton.cs.algs4;
public final synchronized class StdRandom {
private static java.util.Random random;
private static long seed;
private void StdRandom();
public static void setSeed(long);
public static long getSeed();
public static double uniform();
public static int uniform(int);
public static long uniform(long);
public static double random();
public static int uniform(int, int);
public static double uniform(double, double);
public static boolean bernoulli(double);
public static boolean bernoulli();
public static double gaussian();
public static double gaussian(double, double);
public static int geometric(double);
public static int poisson(double);
public static double pareto();
public static double pareto(double);
public static double cauchy();
public static int discrete(double[]);
public static int discrete(int[]);
public static double exp(double);
public static void shuffle(Object[]);
public static void shuffle(double[]);
public static void shuffle(int[]);
public static void shuffle(char[]);
public static void shuffle(Object[], int, int);
public static void shuffle(double[], int, int);
public static void shuffle(int[], int, int);
public static int[] permutation(int);
public static int[] permutation(int, int);
private static void validateNotNull(Object);
private static void validateSubarrayIndices(int, int, int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/StdStats.class
package edu.princeton.cs.algs4;
public final synchronized class StdStats {
private void StdStats();
public static double max(double[]);
public static double max(double[], int, int);
public static int max(int[]);
public static double min(double[]);
public static double min(double[], int, int);
public static int min(int[]);
public static double mean(double[]);
public static double mean(double[], int, int);
public static double mean(int[]);
public static double var(double[]);
public static double var(double[], int, int);
public static double var(int[]);
public static double varp(double[]);
public static double varp(double[], int, int);
public static double stddev(double[]);
public static double stddev(int[]);
public static double stddev(double[], int, int);
public static double stddevp(double[]);
public static double stddevp(double[], int, int);
private static double sum(double[]);
private static double sum(double[], int, int);
private static int sum(int[]);
public static void plotPoints(double[]);
public static void plotLines(double[]);
public static void plotBars(double[]);
private static void validateNotNull(Object);
private static void validateSubarrayIndices(int, int, int);
public static void main(String[]);
}
edu/princeton/cs/algs4/Stopwatch.class
package edu.princeton.cs.algs4;
public synchronized class Stopwatch {
private final long start;
public void Stopwatch();
public double elapsedTime();
public static void main(String[]);
}
edu/princeton/cs/algs4/StopwatchCPU.class
package edu.princeton.cs.algs4;
public synchronized class StopwatchCPU {
private static final double NANOSECONDS_PER_SECOND = 1.0E9;
private final management.ThreadMXBean threadTimer;
private final long start;
public void StopwatchCPU();
public double elapsedTime();
public static void main(String[]);
}
edu/princeton/cs/algs4/SuffixArray$1.class
package edu.princeton.cs.algs4;
synchronized class SuffixArray$1 {
}
edu/princeton/cs/algs4/SuffixArray.class
package edu.princeton.cs.algs4;
public synchronized class SuffixArray {
private SuffixArray$Suffix[] suffixes;
public void SuffixArray(String);
public int length();
public int index(int);
public int lcp(int);
private static int lcpSuffix(SuffixArray$Suffix, SuffixArray$Suffix);
public String select(int);
public int rank(String);
private static int compare(String, SuffixArray$Suffix);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/SuffixArray$Suffix.class
package edu.princeton.cs.algs4;
synchronized class SuffixArray$Suffix implements Comparable {
private final String text;
private final int index;
private void SuffixArray$Suffix(String, int);
private int length();
private char charAt(int);
public int compareTo(SuffixArray$Suffix);
public String toString();
}
edu/princeton/cs/algs4/SuffixArrayX.class
package edu.princeton.cs.algs4;
public synchronized class SuffixArrayX {
private static final int CUTOFF = 5;
private final char[] text;
private final int[] index;
private final int n;
public void SuffixArrayX(String);
private void sort(int, int, int);
private void insertion(int, int, int);
private boolean less(int, int, int);
private void exch(int, int);
public int length();
public int index(int);
public int lcp(int);
private int lcp(int, int);
public String select(int);
public int rank(String);
private int compare(String, int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/SymbolDigraph.class
package edu.princeton.cs.algs4;
public synchronized class SymbolDigraph {
private ST st;
private String[] keys;
private Digraph graph;
public void SymbolDigraph(String, String);
public boolean contains(String);
public int index(String);
public int indexOf(String);
public String name(int);
public String nameOf(int);
public Digraph G();
public Digraph digraph();
private void validateVertex(int);
public static void main(String[]);
}
edu/princeton/cs/algs4/SymbolGraph.class
package edu.princeton.cs.algs4;
public synchronized class SymbolGraph {
private ST st;
private String[] keys;
private Graph graph;
public void SymbolGraph(String, String);
public boolean contains(String);
public int index(String);
public int indexOf(String);
public String name(int);
public String nameOf(int);
public Graph G();
public Graph graph();
private void validateVertex(int);
public static void main(String[]);
}
edu/princeton/cs/algs4/TarjanSCC.class
package edu.princeton.cs.algs4;
public synchronized class TarjanSCC {
private boolean[] marked;
private int[] id;
private int[] low;
private int pre;
private int count;
private Stack stack;
public void TarjanSCC(Digraph);
private void dfs(Digraph, int);
public int count();
public boolean stronglyConnected(int, int);
public int id(int);
private boolean check(Digraph);
private void validateVertex(int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/ThreeSum.class
package edu.princeton.cs.algs4;
public synchronized class ThreeSum {
private void ThreeSum();
public static void printAll(int[]);
public static int count(int[]);
public static void main(String[]);
}
edu/princeton/cs/algs4/ThreeSumFast.class
package edu.princeton.cs.algs4;
public synchronized class ThreeSumFast {
private void ThreeSumFast();
private static boolean containsDuplicates(int[]);
public static void printAll(int[]);
public static int count(int[]);
public static void main(String[]);
}
edu/princeton/cs/algs4/TopM.class
package edu.princeton.cs.algs4;
public synchronized class TopM {
private void TopM();
public static void main(String[]);
}
edu/princeton/cs/algs4/Topological.class
package edu.princeton.cs.algs4;
public synchronized class Topological {
private Iterable order;
private int[] rank;
public void Topological(Digraph);
public void Topological(EdgeWeightedDigraph);
public Iterable order();
public boolean hasOrder();
public boolean isDAG();
public int rank(int);
private void validateVertex(int);
public static void main(String[]);
}
edu/princeton/cs/algs4/TopologicalX.class
package edu.princeton.cs.algs4;
public synchronized class TopologicalX {
private Queue order;
private int[] ranks;
public void TopologicalX(Digraph);
public void TopologicalX(EdgeWeightedDigraph);
public Iterable order();
public boolean hasOrder();
public int rank(int);
private boolean check(Digraph);
private boolean check(EdgeWeightedDigraph);
private void validateVertex(int);
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/Transaction.class
package edu.princeton.cs.algs4;
public synchronized class Transaction implements Comparable {
private final String who;
private final Date when;
private final double amount;
public void Transaction(String, Date, double);
public void Transaction(String);
public String who();
public Date when();
public double amount();
public String toString();
public int compareTo(Transaction);
public boolean equals(Object);
public int hashCode();
public static void main(String[]);
}
edu/princeton/cs/algs4/Transaction$HowMuchOrder.class
package edu.princeton.cs.algs4;
public synchronized class Transaction$HowMuchOrder implements java.util.Comparator {
public void Transaction$HowMuchOrder();
public int compare(Transaction, Transaction);
}
edu/princeton/cs/algs4/Transaction$WhenOrder.class
package edu.princeton.cs.algs4;
public synchronized class Transaction$WhenOrder implements java.util.Comparator {
public void Transaction$WhenOrder();
public int compare(Transaction, Transaction);
}
edu/princeton/cs/algs4/Transaction$WhoOrder.class
package edu.princeton.cs.algs4;
public synchronized class Transaction$WhoOrder implements java.util.Comparator {
public void Transaction$WhoOrder();
public int compare(Transaction, Transaction);
}
edu/princeton/cs/algs4/TransitiveClosure.class
package edu.princeton.cs.algs4;
public synchronized class TransitiveClosure {
private DirectedDFS[] tc;
public void TransitiveClosure(Digraph);
public boolean reachable(int, int);
private void validateVertex(int);
public static void main(String[]);
}
edu/princeton/cs/algs4/TrieSET$1.class
package edu.princeton.cs.algs4;
synchronized class TrieSET$1 {
}
edu/princeton/cs/algs4/TrieSET.class
package edu.princeton.cs.algs4;
public synchronized class TrieSET implements Iterable {
private static final int R = 256;
private TrieSET$Node root;
private int n;
public void TrieSET();
public boolean contains(String);
private TrieSET$Node get(TrieSET$Node, String, int);
public void add(String);
private TrieSET$Node add(TrieSET$Node, String, int);
public int size();
public boolean isEmpty();
public java.util.Iterator iterator();
public Iterable keysWithPrefix(String);
private void collect(TrieSET$Node, StringBuilder, Queue);
public Iterable keysThatMatch(String);
private void collect(TrieSET$Node, StringBuilder, String, Queue);
public String longestPrefixOf(String);
private int longestPrefixOf(TrieSET$Node, String, int, int);
public void delete(String);
private TrieSET$Node delete(TrieSET$Node, String, int);
public static void main(String[]);
}
edu/princeton/cs/algs4/TrieSET$Node.class
package edu.princeton.cs.algs4;
synchronized class TrieSET$Node {
private TrieSET$Node[] next;
private boolean isString;
private void TrieSET$Node();
}
edu/princeton/cs/algs4/TrieST$1.class
package edu.princeton.cs.algs4;
synchronized class TrieST$1 {
}
edu/princeton/cs/algs4/TrieST.class
package edu.princeton.cs.algs4;
public synchronized class TrieST {
private static final int R = 256;
private TrieST$Node root;
private int n;
public void TrieST();
public Object get(String);
public boolean contains(String);
private TrieST$Node get(TrieST$Node, String, int);
public void put(String, Object);
private TrieST$Node put(TrieST$Node, String, Object, int);
public int size();
public boolean isEmpty();
public Iterable keys();
public Iterable keysWithPrefix(String);
private void collect(TrieST$Node, StringBuilder, Queue);
public Iterable keysThatMatch(String);
private void collect(TrieST$Node, StringBuilder, String, Queue);
public String longestPrefixOf(String);
private int longestPrefixOf(TrieST$Node, String, int, int);
public void delete(String);
private TrieST$Node delete(TrieST$Node, String, int);
public static void main(String[]);
}
edu/princeton/cs/algs4/TrieST$Node.class
package edu.princeton.cs.algs4;
synchronized class TrieST$Node {
private Object val;
private TrieST$Node[] next;
private void TrieST$Node();
}
edu/princeton/cs/algs4/TST$1.class
package edu.princeton.cs.algs4;
synchronized class TST$1 {
}
edu/princeton/cs/algs4/TST.class
package edu.princeton.cs.algs4;
public synchronized class TST {
private int n;
private TST$Node root;
public void TST();
public int size();
public boolean contains(String);
public Object get(String);
private TST$Node get(TST$Node, String, int);
public void put(String, Object);
private TST$Node put(TST$Node, String, Object, int);
public String longestPrefixOf(String);
public Iterable keys();
public Iterable keysWithPrefix(String);
private void collect(TST$Node, StringBuilder, Queue);
public Iterable keysThatMatch(String);
private void collect(TST$Node, StringBuilder, int, String, Queue);
public static void main(String[]);
}
edu/princeton/cs/algs4/TST$Node.class
package edu.princeton.cs.algs4;
synchronized class TST$Node {
private char c;
private TST$Node left;
private TST$Node mid;
private TST$Node right;
private Object val;
private void TST$Node();
}
edu/princeton/cs/algs4/TwoPersonZeroSumGame.class
package edu.princeton.cs.algs4;
public synchronized class TwoPersonZeroSumGame {
private static final double EPSILON = 1.0E-8;
private final int m;
private final int n;
private LinearProgramming lp;
private double constant;
public void TwoPersonZeroSumGame(double[][]);
public double value();
private double scale();
public double[] row();
public double[] column();
private boolean isPrimalFeasible();
private boolean isDualFeasible();
private boolean isNashEquilibrium(double[][]);
private boolean certifySolution(double[][]);
private static void test(String, double[][]);
private static void test1();
private static void test2();
private static void test3();
private static void test4();
private static void test5();
public static void main(String[]);
static void
}
edu/princeton/cs/algs4/UF.class
package edu.princeton.cs.algs4;
public synchronized class UF {
private int[] parent;
private byte[] rank;
private int count;
public void UF(int);
public int find(int);
public int count();
public boolean connected(int, int);
public void union(int, int);
private void validate(int);
public static void main(String[]);
}
edu/princeton/cs/algs4/Vector.class
package edu.princeton.cs.algs4;
public synchronized class Vector {
private int d;
private double[] data;
public void Vector(int);
public transient void Vector(double[]);
public int length();
public int dimension();
public double dot(Vector);
public double magnitude();
public double distanceTo(Vector);
public Vector plus(Vector);
public Vector minus(Vector);
public double cartesian(int);
public Vector times(double);
public Vector scale(double);
public Vector direction();
public String toString();
public static void main(String[]);
}
edu/princeton/cs/algs4/WeightedQuickUnionUF.class
package edu.princeton.cs.algs4;
public synchronized class WeightedQuickUnionUF {
private int[] parent;
private int[] size;
private int count;
public void WeightedQuickUnionUF(int);
public int count();
public int find(int);
public boolean connected(int, int);
private void validate(int);
public void union(int, int);
public static void main(String[]);
}
edu/princeton/cs/algs4/WhiteFilter.class
package edu.princeton.cs.algs4;
public synchronized class WhiteFilter {
private void WhiteFilter();
public static void main(String[]);
}
edu/princeton/cs/algs4/Whitelist.class
package edu.princeton.cs.algs4;
public synchronized class Whitelist {
private void Whitelist();
public static void main(String[]);
}
TestAlgs4.java
TestAlgs4.java
/******************************************************************************
* Compilation: javac-algs4 TestAlgs4.java
* Execution: java-algs4 TestAlgs4 n
*
* Simulates the motion of n hard disks, subject to the laws of elastic
* collisions. This program is intended to test that algs4.jar is properly
* installed.
*
******************************************************************************/
import
edu
.
princeton
.
cs
.
algs4
.
CollisionSystem
;
import
edu
.
princeton
.
cs
.
algs4
.
Particle
;
import
edu
.
princeton
.
cs
.
algs4
.
StdDraw
;
public
class
TestAlgs4
{
public static void main(String[] args) {
int n = 20; // number of particles (default 20) if (args.length == 1) {
n = Integer.parseInt(args[0]);
}
// enable double buffering to support animations StdDraw.enableDoubleBuffering();
// create the n particles Particle[] particles = new Particle[n];
for (int i = 0; i < n; i++) { particles[i] = new Particle(); } // simulate the system CollisionSystem system = new CollisionSystem(particles); system.simulate(Double.POSITIVE_INFINITY); } } TestAlgs4.class public synchronized class TestAlgs4 { public void TestAlgs4(); public static void main(String[]); } META-INF/MANIFEST.MF Manifest-Version: 1.0 Created-By: 1.8.0_191 (Oracle Corporation) BinaryIn.java BinaryIn.java /****************************************************************************** * Compilation: javac BinaryIn.java * Execution: java BinaryIn input output * Dependencies: none * * This library is for reading binary data from an input stream. * * % java BinaryIn https://introcs.cs.princeton.edu/java/cover output * ******************************************************************************/ import java . io . BufferedInputStream ; import java . io . File ; import java . io . FileInputStream ; import java . io . IOException ; import java . io . InputStream ; import java . net . Socket ; import java . net . URL ; import java . net . URLConnection ; import java . util . NoSuchElementException ; /** * Binary input. This class provides methods for reading
* in bits from a binary input stream, either
* one bit at a time (as a {
@code
boolean}),
* 8 bits at a time (as a {
@code
byte} or {
@code
char}),
* 16 bits at a time (as a {
@code
short}),
* 32 bits at a time (as an {
@code
int} or {
@code
float}), or
* 64 bits at a time (as a {
@code
double} or {
@code
long}).
*
* The binary input stream can be from standard input, a filename,
* a URL name, a Socket, or an InputStream.
*
* All primitive types are assumed to be represented using their
* standard Java representations, in big-endian (most significant
* byte first) order.
*
* The client should not intermix calls to {
@code
BinaryIn} with calls
* to {
@code
In}; otherwise unexpected behavior will result.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
BinaryIn
{
private
static
final
int
EOF
=
–
1
;
// end of file
private
BufferedInputStream
in
;
// the input stream
private
int
buffer
;
// one character buffer
private
int
n
;
// number of bits left in buffer
/**
* Initializes a binary input stream from standard input.
*/
public
BinaryIn
()
{
in
=
new
BufferedInputStream
(
System
.
in
);
fillBuffer
();
}
/**
* Initializes a binary input stream from an {
@code
InputStream}.
*
*
@param
is the {
@code
InputStream} object
*/
public
BinaryIn
(
InputStream
is
)
{
in
=
new
BufferedInputStream
(
is
);
fillBuffer
();
}
/**
* Initializes a binary input stream from a socket.
*
*
@param
socket the socket
*/
public
BinaryIn
(
Socket
socket
)
{
try
{
InputStream
is
=
socket
.
getInputStream
();
in
=
new
BufferedInputStream
(
is
);
fillBuffer
();
}
catch
(
IOException
ioe
)
{
System
.
err
.
println
(
“Could not open ”
+
socket
);
}
}
/**
* Initializes a binary input stream from a URL.
*
*
@param
url the URL
*/
public
BinaryIn
(
URL url
)
{
try
{
URLConnection
site
=
url
.
openConnection
();
InputStream
is
=
site
.
getInputStream
();
in
=
new
BufferedInputStream
(
is
);
fillBuffer
();
}
catch
(
IOException
ioe
)
{
System
.
err
.
println
(
“Could not open ”
+
url
);
}
}
/**
* Initializes a binary input stream from a filename or URL name.
*
*
@param
name the name of the file or URL
*/
public
BinaryIn
(
String
name
)
{
try
{
// first try to read file from local file system
File
file
=
new
File
(
name
);
if
(
file
.
exists
())
{
FileInputStream
fis
=
new
FileInputStream
(
file
);
in
=
new
BufferedInputStream
(
fis
);
fillBuffer
();
return
;
}
// next try for files included in jar
URL url
=
getClass
().
getResource
(
name
);
// or URL from web
if
(
url
==
null
)
{
url
=
new
URL
(
name
);
}
URLConnection
site
=
url
.
openConnection
();
InputStream
is
=
site
.
getInputStream
();
in
=
new
BufferedInputStream
(
is
);
fillBuffer
();
}
catch
(
IOException
ioe
)
{
System
.
err
.
println
(
“Could not open ”
+
name
);
}
}
private
void
fillBuffer
()
{
try
{
buffer
=
in
.
read
();
n
=
8
;
}
catch
(
IOException
e
)
{
System
.
err
.
println
(
“EOF”
);
buffer
=
EOF
;
n
=
–
1
;
}
}
/**
* Returns true if this binary input stream exists.
*
*
@return
{
@code
true} if this binary input stream exists;
* {
@code
false} otherwise
*/
public
boolean
exists
()
{
return
in
!=
null
;
}
/**
* Returns true if this binary input stream is empty.
*
*
@return
{
@code
true} if this binary input stream is empty;
* {
@code
false} otherwise
*/
public
boolean
isEmpty
()
{
return
buffer
==
EOF
;
}
/**
* Reads the next bit of data from this binary input stream and return as a boolean.
*
*
@return
the next bit of data from this binary input stream as a {
@code
boolean}
*
@throws
NoSuchElementException if this binary input stream is empty
*/
public
boolean
readBoolean
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Reading from empty input stream”
);
n
—
;
boolean
bit
=
((
buffer
>>
n
)
&
1
)
==
1
;
if
(
n
==
0
)
fillBuffer
();
return
bit
;
}
/**
* Reads the next 8 bits from this binary input stream and return as an 8-bit char.
*
*
@return
the next 8 bits of data from this binary input stream as a {
@code
char}
*
@throws
NoSuchElementException if there are fewer than 8 bits available
*/
public
char
readChar
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Reading from empty input stream”
);
// special case when aligned byte
if
(
n
==
8
)
{
int
x
=
buffer
;
fillBuffer
();
return
(
char
)
(
x
&
0xff
);
}
// combine last N bits of current buffer with first 8-N bits of new buffer
int
x
=
buffer
;
x
<<=
(
8
-
n
);
int
oldN
=
n
;
fillBuffer
();
if
(
isEmpty
())
throw
new
NoSuchElementException
(
"Reading from empty input stream"
);
n
=
oldN
;
x
|=
(
buffer
>>>
n
);
return
(
char
)
(
x
&
0xff
);
// the above code doesn’t quite work for the last character if N = 8
// because buffer will be -1
}
/**
* Reads the next r bits from this binary input stream and return as an r-bit character.
*
*
@param
r number of bits to read
*
@return
the next {
@code
r} bits of data from this binary input streamt as a {
@code
char}
*
@throws
NoSuchElementException if there are fewer than {
@code
r} bits available
*
@throws
IllegalArgumentException unless {
@code
1 <= r <= 16}
*/
public
char
readChar
(
int
r
)
{
if
(
r
<
1
||
r
>
16
)
throw
new
IllegalArgumentException
(
“Illegal value of r = ”
+
r
);
// optimize r = 8 case
if
(
r
==
8
)
return
readChar
();
char
x
=
0
;
for
(
int
i
=
0
;
i
<
r
;
i
++
)
{
x
<<=
1
;
boolean
bit
=
readBoolean
();
if
(
bit
)
x
|=
1
;
}
return
x
;
}
/**
* Reads the remaining bytes of data from this binary input stream and return as a string.
*
*
@return
the remaining bytes of data from this binary input stream as a {
@code
String}
*
@throws
NoSuchElementException if this binary input stream is empty or if the number of bits
* available is not a multiple of 8 (byte-aligned)
*/
public
String
readString
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
"Reading from empty input stream"
);
StringBuilder
sb
=
new
StringBuilder
();
while
(
!
isEmpty
())
{
char
c
=
readChar
();
sb
.
append
(
c
);
}
return
sb
.
toString
();
}
/**
* Reads the next 16 bits from this binary input stream and return as a 16-bit short.
*
*
@return
the next 16 bits of data from this binary input stream as a {
@code
short}
*
@throws
NoSuchElementException if there are fewer than 16 bits available
*/
public
short
readShort
()
{
short
x
=
0
;
for
(
int
i
=
0
;
i
<
2
;
i
++
)
{
char
c
=
readChar
();
x
<<=
8
;
x
|=
c
;
}
return
x
;
}
/**
* Reads the next 32 bits from this binary input stream and return as a 32-bit int.
*
*
@return
the next 32 bits of data from this binary input stream as a {
@code
int}
*
@throws
NoSuchElementException if there are fewer than 32 bits available
*/
public
int
readInt
()
{
int
x
=
0
;
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
char
c
=
readChar
();
x
<<=
8
;
x
|=
c
;
}
return
x
;
}
/**
* Reads the next r bits from this binary input stream return as an r-bit int.
*
*
@param
r number of bits to read
*
@return
the next {
@code
r} bits of data from this binary input stream as a {
@code
int}
*
@throws
NoSuchElementException if there are fewer than r bits available
*
@throws
IllegalArgumentException unless {
@code
1 <= r <= 32}
*/
public
int
readInt
(
int
r
)
{
if
(
r
<
1
||
r
>
32
)
throw
new
IllegalArgumentException
(
“Illegal value of r = ”
+
r
);
// optimize r = 32 case
if
(
r
==
32
)
return
readInt
();
int
x
=
0
;
for
(
int
i
=
0
;
i
<
r
;
i
++
)
{
x
<<=
1
;
boolean
bit
=
readBoolean
();
if
(
bit
)
x
|=
1
;
}
return
x
;
}
/**
* Reads the next 64 bits from this binary input stream and return as a 64-bit long.
*
*
@return
the next 64 bits of data from this binary input stream as a {
@code
long}
*
@throws
NoSuchElementException if there are fewer than 64 bits available
*/
public
long
readLong
()
{
long
x
=
0
;
for
(
int
i
=
0
;
i
<
8
;
i
++
)
{
char
c
=
readChar
();
x
<<=
8
;
x
|=
c
;
}
return
x
;
}
/**
* Reads the next 64 bits from this binary input stream and return as a 64-bit double.
*
*
@return
the next 64 bits of data from this binary input stream as a {
@code
double}
*
@throws
NoSuchElementException if there are fewer than 64 bits available
*/
public
double
readDouble
()
{
return
Double
.
longBitsToDouble
(
readLong
());
}
/**
* Reads the next 32 bits from this binary input stream and return as a 32-bit float.
*
*
@return
the next 32 bits of data from this binary input stream as a {
@code
float}
*
@throws
NoSuchElementException if there are fewer than 32 bits available
*/
public
float
readFloat
()
{
return
Float
.
intBitsToFloat
(
readInt
());
}
/**
* Reads the next 8 bits from this binary input stream and return as an 8-bit byte.
*
*
@return
the next 8 bits of data from this binary input stream as a {
@code
byte}
*
@throws
NoSuchElementException if there are fewer than 8 bits available
*/
public
byte
readByte
()
{
char
c
=
readChar
();
return
(
byte
)
(
c
&
0xff
);
}
/**
* Unit tests the {
@code
BinaryIn} data type.
* Reads the name of a file or URL (first command-line argument)
* and writes it to a file (second command-line argument).
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
BinaryIn
in
=
new
BinaryIn
(
args
[
0
]);
BinaryOut
out
=
new
BinaryOut
(
args
[
1
]);
// read one 8-bit char at a time
while
(
!
in
.
isEmpty
())
{
char
c
=
in
.
readChar
();
out
.
write
(
c
);
}
out
.
flush
();
}
}
BinaryOut.java
BinaryOut.java
/******************************************************************************
* Compilation: javac BinaryOut.java
* Execution: java BinaryOut
* Dependencies: none
*
* Write binary data to an output stream, either one 1-bit boolean,
* one 8-bit char, one 32-bit int, one 64-bit double, one 32-bit float,
* or one 64-bit long at a time. The output stream can be standard
* output, a file, an OutputStream or a Socket.
*
* The bytes written are not aligned.
*
******************************************************************************/
import
java
.
io
.
BufferedOutputStream
;
import
java
.
io
.
FileOutputStream
;
import
java
.
io
.
IOException
;
import
java
.
io
.
OutputStream
;
import
java
.
net
.
Socket
;
/**
* Binary output. This class provides methods for converting
* primtive type variables ({
@code
boolean}, {
@code
byte}, {
@code
char},
* {
@code
int}, {
@code
long}, {
@code
float}, and {
@code
double})
* to sequences of bits and writing them to an output stream.
* The output stream can be standard output, a file, an OutputStream or a Socket.
* Uses big-endian (most-significant byte first).
*
* The client must {
@code
flush()} the output stream when finished writing bits.
*
* The client should not intermix calls to {
@code
BinaryOut} with calls
* to {
@code
Out}; otherwise unexpected behavior will result.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
BinaryOut
{
private
BufferedOutputStream
out
;
// the output stream
private
int
buffer
;
// 8-bit buffer of bits to write out
private
int
n
;
// number of bits remaining in buffer
/**
* Initializes a binary output stream from standard output.
*/
public
BinaryOut
()
{
out
=
new
BufferedOutputStream
(
System
.
out
);
}
/**
* Initializes a binary output stream from an {
@code
OutputStream}.
*
@param
os the {
@code
OutputStream}
*/
public
BinaryOut
(
OutputStream
os
)
{
out
=
new
BufferedOutputStream
(
os
);
}
/**
* Initializes a binary output stream from a file.
*
@param
filename the name of the file
*/
public
BinaryOut
(
String
filename
)
{
try
{
OutputStream
os
=
new
FileOutputStream
(
filename
);
out
=
new
BufferedOutputStream
(
os
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
/**
* Initializes a binary output stream from a socket.
*
@param
socket the socket
*/
public
BinaryOut
(
Socket
socket
)
{
try
{
OutputStream
os
=
socket
.
getOutputStream
();
out
=
new
BufferedOutputStream
(
os
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
/**
* Writes the specified bit to the binary output stream.
*
@param
x the bit
*/
private
void
writeBit
(
boolean
x
)
{
// add bit to buffer
buffer
<<=
1
;
if
(
x
)
buffer
|=
1
;
// if buffer is full (8 bits), write out as a single byte
n
++
;
if
(
n
==
8
)
clearBuffer
();
}
/**
* Writes the 8-bit byte to the binary output stream.
*
@param
x the byte
*/
private
void
writeByte
(
int
x
)
{
assert
x
>=
0
&&
x
<
256
;
// optimized if byte-aligned
if
(
n
==
0
)
{
try
{
out
.
write
(
x
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
return
;
}
// otherwise write one bit at a time
for
(
int
i
=
0
;
i
<
8
;
i
++
)
{
boolean
bit
=
((
x
>>>
(
8
–
i
–
1
))
&
1
)
==
1
;
writeBit
(
bit
);
}
}
// write out any remaining bits in buffer to the binary output stream, padding with 0s
private
void
clearBuffer
()
{
if
(
n
==
0
)
return
;
if
(
n
>
0
)
buffer
<<=
(
8
-
n
);
try
{
out
.
write
(
buffer
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
n
=
0
;
buffer
=
0
;
}
/**
* Flushes the binary output stream, padding 0s if number of bits written so far
* is not a multiple of 8.
*/
public
void
flush
()
{
clearBuffer
();
try
{
out
.
flush
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
/**
* Flushes and closes the binary output stream.
* Once it is closed, bits can no longer be written.
*/
public
void
close
()
{
flush
();
try
{
out
.
close
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
/**
* Writes the specified bit to the binary output stream.
*
@param
x the {
@code
boolean} to write
*/
public
void
write
(
boolean
x
)
{
writeBit
(
x
);
}
/**
* Writes the 8-bit byte to the binary output stream.
*
@param
x the {
@code
byte} to write.
*/
public
void
write
(
byte
x
)
{
writeByte
(
x
&
0xff
);
}
/**
* Writes the 32-bit int to the binary output stream.
*
@param
x the {
@code
int} to write
*/
public
void
write
(
int
x
)
{
writeByte
((
x
>>>
24
)
&
0xff
);
writeByte
((
x
>>>
16
)
&
0xff
);
writeByte
((
x
>>>
8
)
&
0xff
);
writeByte
((
x
>>>
0
)
&
0xff
);
}
/**
* Writes the r-bit int to the binary output stream.
*
*
@param
x the {
@code
int} to write
*
@param
r the number of relevant bits in the char
*
@throws
IllegalArgumentException unless {
@code
r} is between 1 and 32
*
@throws
IllegalArgumentException unless {
@code
x} is between 0 and 2r – 1
*/
public
void
write
(
int
x
,
int
r
)
{
if
(
r
==
32
)
{
write
(
x
);
return
;
}
if
(
r
<
1
||
r
>
32
)
throw
new
IllegalArgumentException
(
“Illegal value for r = ”
+
r
);
if
(
x
>=
(
1
<<
r
))
throw
new
IllegalArgumentException
(
"Illegal "
+
r
+
"-bit char = "
+
x
);
for
(
int
i
=
0
;
i
<
r
;
i
++
)
{
boolean
bit
=
((
x
>>>
(
r
–
i
–
1
))
&
1
)
==
1
;
writeBit
(
bit
);
}
}
/**
* Writes the 64-bit double to the binary output stream.
*
@param
x the {
@code
double} to write
*/
public
void
write
(
double
x
)
{
write
(
Double
.
doubleToRawLongBits
(
x
));
}
/**
* Writes the 64-bit long to the binary output stream.
*
@param
x the {
@code
long} to write
*/
public
void
write
(
long
x
)
{
writeByte
((
int
)
((
x
>>>
56
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
48
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
40
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
32
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
24
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
16
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
8
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
0
)
&
0xff
));
}
/**
* Writes the 32-bit float to the binary output stream.
*
@param
x the {
@code
float} to write
*/
public
void
write
(
float
x
)
{
write
(
Float
.
floatToRawIntBits
(
x
));
}
/**
* Write the 16-bit int to the binary output stream.
*
@param
x the {
@code
short} to write.
*/
public
void
write
(
short
x
)
{
writeByte
((
x
>>>
8
)
&
0xff
);
writeByte
((
x
>>>
0
)
&
0xff
);
}
/**
* Writes the 8-bit char to the binary output stream.
*
*
@param
x the {
@code
char} to write
*
@throws
IllegalArgumentException unless {
@code
x} is betwen 0 and 255
*/
public
void
write
(
char
x
)
{
if
(
x
<
0
||
x
>=
256
)
throw
new
IllegalArgumentException
(
“Illegal 8-bit char = ”
+
x
);
writeByte
(
x
);
}
/**
* Writes the r-bit char to the binary output stream.
*
*
@param
x the {
@code
char} to write
*
@param
r the number of relevant bits in the char
*
@throws
IllegalArgumentException unless {
@code
r} is between 1 and 16
*
@throws
IllegalArgumentException unless {
@code
x} is between 0 and 2r – 1
*/
public
void
write
(
char
x
,
int
r
)
{
if
(
r
==
8
)
{
write
(
x
);
return
;
}
if
(
r
<
1
||
r
>
16
)
throw
new
IllegalArgumentException
(
“Illegal value for r = ”
+
r
);
if
(
x
>=
(
1
<<
r
))
throw
new
IllegalArgumentException
(
"Illegal "
+
r
+
"-bit char = "
+
x
);
for
(
int
i
=
0
;
i
<
r
;
i
++
)
{
boolean
bit
=
((
x
>>>
(
r
–
i
–
1
))
&
1
)
==
1
;
writeBit
(
bit
);
}
}
/**
* Writes the string of 8-bit characters to the binary output stream.
*
*
@param
s the {
@code
String} to write
*
@throws
IllegalArgumentException if any character in the string is not
* between 0 and 255
*/
public
void
write
(
String
s
)
{
for
(
int
i
=
0
;
i
<
s
.
length
();
i
++
)
write
(
s
.
charAt
(
i
));
}
/**
* Writes the string of r-bit characters to the binary output stream.
*
@param
s the {
@code
String} to write
*
@param
r the number of relevants bits in each character
*
@throws
IllegalArgumentException unless r is between 1 and 16
*
@throws
IllegalArgumentException if any character in the string is not
* between 0 and 2r – 1
*/
public
void
write
(
String
s
,
int
r
)
{
for
(
int
i
=
0
;
i
<
s
.
length
();
i
++
)
write
(
s
.
charAt
(
i
),
r
);
}
/**
* Test client. Read bits from standard input and write to the file
* specified on command line.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// create binary output stream to write to file
String
filename
=
args
[
0
];
BinaryOut
out
=
new
BinaryOut
(
filename
);
BinaryIn
in
=
new
BinaryIn
();
// read from standard input and write to file
while
(
!
in
.
isEmpty
())
{
char
c
=
in
.
readChar
();
out
.
write
(
c
);
}
out
.
flush
();
}
}
BinaryStdIn.java
BinaryStdIn.java
/******************************************************************************
* Compilation: javac BinaryStdIn.java
* Execution: java BinaryStdIn < input > output
* Dependencies: none
*
* Supports reading binary data from standard input.
*
* % java BinaryStdIn < input > output
* % diff input output
*
******************************************************************************/
import
java
.
io
.
BufferedInputStream
;
import
java
.
io
.
IOException
;
import
java
.
util
.
NoSuchElementException
;
/**
* Binary standard input. This class provides methods for reading
* in bits from standard input, either one bit at a time (as a {
@code
boolean}),
* 8 bits at a time (as a {
@code
byte} or {
@code
char}),
* 16 bits at a time (as a {
@code
short}), 32 bits at a time
* (as an {
@code
int} or {
@code
float}), or 64 bits at a time (as a
* {
@code
double} or {
@code
long}).
*
* All primitive types are assumed to be represented using their
* standard Java representations, in big-endian (most significant
* byte first) order.
*
* The client should not intermix calls to {
@code
BinaryStdIn} with calls
* to {
@code
StdIn} or {
@code
System.in};
* otherwise unexpected behavior will result.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
BinaryStdIn
{
private
static
final
int
EOF
=
–
1
;
// end of file
private
static
BufferedInputStream
in
;
// input stream
private
static
int
buffer
;
// one character buffer
private
static
int
n
;
// number of bits left in buffer
private
static
boolean
isInitialized
;
// has BinaryStdIn been called for first time?
// don’t instantiate
private
BinaryStdIn
()
{
}
// fill buffer
private
static
void
initialize
()
{
in
=
new
BufferedInputStream
(
System
.
in
);
buffer
=
0
;
n
=
0
;
fillBuffer
();
isInitialized
=
true
;
}
private
static
void
fillBuffer
()
{
try
{
buffer
=
in
.
read
();
n
=
8
;
}
catch
(
IOException
e
)
{
System
.
out
.
println
(
“EOF”
);
buffer
=
EOF
;
n
=
–
1
;
}
}
/**
* Close this input stream and release any associated system resources.
*/
public
static
void
close
()
{
if
(
!
isInitialized
)
initialize
();
try
{
in
.
close
();
isInitialized
=
false
;
}
catch
(
IOException
ioe
)
{
throw
new
IllegalStateException
(
“Could not close BinaryStdIn”
,
ioe
);
}
}
/**
* Returns true if standard input is empty.
*
@return
true if and only if standard input is empty
*/
public
static
boolean
isEmpty
()
{
if
(
!
isInitialized
)
initialize
();
return
buffer
==
EOF
;
}
/**
* Reads the next bit of data from standard input and return as a boolean.
*
*
@return
the next bit of data from standard input as a {
@code
boolean}
*
@throws
NoSuchElementException if standard input is empty
*/
public
static
boolean
readBoolean
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Reading from empty input stream”
);
n
—
;
boolean
bit
=
((
buffer
>>
n
)
&
1
)
==
1
;
if
(
n
==
0
)
fillBuffer
();
return
bit
;
}
/**
* Reads the next 8 bits from standard input and return as an 8-bit char.
* Note that {
@code
char} is a 16-bit type;
* to read the next 16 bits as a char, use {
@code
readChar(16)}.
*
*
@return
the next 8 bits of data from standard input as a {
@code
char}
*
@throws
NoSuchElementException if there are fewer than 8 bits available on standard input
*/
public
static
char
readChar
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
“Reading from empty input stream”
);
// special case when aligned byte
if
(
n
==
8
)
{
int
x
=
buffer
;
fillBuffer
();
return
(
char
)
(
x
&
0xff
);
}
// combine last n bits of current buffer with first 8-n bits of new buffer
int
x
=
buffer
;
x
<<=
(
8
-
n
);
int
oldN
=
n
;
fillBuffer
();
if
(
isEmpty
())
throw
new
NoSuchElementException
(
"Reading from empty input stream"
);
n
=
oldN
;
x
|=
(
buffer
>>>
n
);
return
(
char
)
(
x
&
0xff
);
// the above code doesn’t quite work for the last character if n = 8
// because buffer will be -1, so there is a special case for aligned byte
}
/**
* Reads the next r bits from standard input and return as an r-bit character.
*
*
@param
r number of bits to read.
*
@return
the next r bits of data from standard input as a {
@code
char}
*
@throws
NoSuchElementException if there are fewer than {
@code
r} bits available on standard input
*
@throws
IllegalArgumentException unless {
@code
1 <= r <= 16}
*/
public
static
char
readChar
(
int
r
)
{
if
(
r
<
1
||
r
>
16
)
throw
new
IllegalArgumentException
(
“Illegal value of r = ”
+
r
);
// optimize r = 8 case
if
(
r
==
8
)
return
readChar
();
char
x
=
0
;
for
(
int
i
=
0
;
i
<
r
;
i
++
)
{
x
<<=
1
;
boolean
bit
=
readBoolean
();
if
(
bit
)
x
|=
1
;
}
return
x
;
}
/**
* Reads the remaining bytes of data from standard input and return as a string.
*
*
@return
the remaining bytes of data from standard input as a {
@code
String}
*
@throws
NoSuchElementException if standard input is empty or if the number of bits
* available on standard input is not a multiple of 8 (byte-aligned)
*/
public
static
String
readString
()
{
if
(
isEmpty
())
throw
new
NoSuchElementException
(
"Reading from empty input stream"
);
StringBuilder
sb
=
new
StringBuilder
();
while
(
!
isEmpty
())
{
char
c
=
readChar
();
sb
.
append
(
c
);
}
return
sb
.
toString
();
}
/**
* Reads the next 16 bits from standard input and return as a 16-bit short.
*
*
@return
the next 16 bits of data from standard input as a {
@code
short}
*
@throws
NoSuchElementException if there are fewer than 16 bits available on standard input
*/
public
static
short
readShort
()
{
short
x
=
0
;
for
(
int
i
=
0
;
i
<
2
;
i
++
)
{
char
c
=
readChar
();
x
<<=
8
;
x
|=
c
;
}
return
x
;
}
/**
* Reads the next 32 bits from standard input and return as a 32-bit int.
*
*
@return
the next 32 bits of data from standard input as a {
@code
int}
*
@throws
NoSuchElementException if there are fewer than 32 bits available on standard input
*/
public
static
int
readInt
()
{
int
x
=
0
;
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
char
c
=
readChar
();
x
<<=
8
;
x
|=
c
;
}
return
x
;
}
/**
* Reads the next r bits from standard input and return as an r-bit int.
*
*
@param
r number of bits to read.
*
@return
the next r bits of data from standard input as a {
@code
int}
*
@throws
NoSuchElementException if there are fewer than {
@code
r} bits available on standard input
*
@throws
IllegalArgumentException unless {
@code
1 <= r <= 32}
*/
public
static
int
readInt
(
int
r
)
{
if
(
r
<
1
||
r
>
32
)
throw
new
IllegalArgumentException
(
“Illegal value of r = ”
+
r
);
// optimize r = 32 case
if
(
r
==
32
)
return
readInt
();
int
x
=
0
;
for
(
int
i
=
0
;
i
<
r
;
i
++
)
{
x
<<=
1
;
boolean
bit
=
readBoolean
();
if
(
bit
)
x
|=
1
;
}
return
x
;
}
/**
* Reads the next 64 bits from standard input and return as a 64-bit long.
*
*
@return
the next 64 bits of data from standard input as a {
@code
long}
*
@throws
NoSuchElementException if there are fewer than 64 bits available on standard input
*/
public
static
long
readLong
()
{
long
x
=
0
;
for
(
int
i
=
0
;
i
<
8
;
i
++
)
{
char
c
=
readChar
();
x
<<=
8
;
x
|=
c
;
}
return
x
;
}
/**
* Reads the next 64 bits from standard input and return as a 64-bit double.
*
*
@return
the next 64 bits of data from standard input as a {
@code
double}
*
@throws
NoSuchElementException if there are fewer than 64 bits available on standard input
*/
public
static
double
readDouble
()
{
return
Double
.
longBitsToDouble
(
readLong
());
}
/**
* Reads the next 32 bits from standard input and return as a 32-bit float.
*
*
@return
the next 32 bits of data from standard input as a {
@code
float}
*
@throws
NoSuchElementException if there are fewer than 32 bits available on standard input
*/
public
static
float
readFloat
()
{
return
Float
.
intBitsToFloat
(
readInt
());
}
/**
* Reads the next 8 bits from standard input and return as an 8-bit byte.
*
*
@return
the next 8 bits of data from standard input as a {
@code
byte}
*
@throws
NoSuchElementException if there are fewer than 8 bits available on standard input
*/
public
static
byte
readByte
()
{
char
c
=
readChar
();
return
(
byte
)
(
c
&
0xff
);
}
/**
* Test client. Reads in a binary input file from standard input and writes
* it to standard output.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// read one 8-bit char at a time
while
(
!
BinaryStdIn
.
isEmpty
())
{
char
c
=
BinaryStdIn
.
readChar
();
BinaryStdOut
.
write
(
c
);
}
BinaryStdOut
.
flush
();
}
}
BinaryStdOut.java
BinaryStdOut.java
/******************************************************************************
* Compilation: javac BinaryStdOut.java
* Execution: java BinaryStdOut
* Dependencies: none
*
* Write binary data to standard output, either one 1-bit boolean,
* one 8-bit char, one 32-bit int, one 64-bit double, one 32-bit float,
* or one 64-bit long at a time.
*
* The bytes written are not aligned.
*
******************************************************************************/
import
java
.
io
.
BufferedOutputStream
;
import
java
.
io
.
IOException
;
/**
* Binary standard output. This class provides methods for converting
* primtive type variables ({
@code
boolean}, {
@code
byte}, {
@code
char},
* {
@code
int}, {
@code
long}, {
@code
float}, and {
@code
double})
* to sequences of bits and writing them to standard output.
* Uses big-endian (most-significant byte first).
*
* The client must {
@code
flush()} the output stream when finished writing bits.
*
* The client should not intermix calls to {
@code
BinaryStdOut} with calls
* to {
@code
StdOut} or {
@code
System.out}; otherwise unexpected behavior
* will result.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
BinaryStdOut
{
private
static
BufferedOutputStream
out
;
// output stream (standard output)
private
static
int
buffer
;
// 8-bit buffer of bits to write
private
static
int
n
;
// number of bits remaining in buffer
private
static
boolean
isInitialized
;
// has BinaryStdOut been called for first time?
// don’t instantiate
private
BinaryStdOut
()
{
}
// initialize BinaryStdOut
private
static
void
initialize
()
{
out
=
new
BufferedOutputStream
(
System
.
out
);
buffer
=
0
;
n
=
0
;
isInitialized
=
true
;
}
/**
* Writes the specified bit to standard output.
*/
private
static
void
writeBit
(
boolean
bit
)
{
if
(
!
isInitialized
)
initialize
();
// add bit to buffer
buffer
<<=
1
;
if
(
bit
)
buffer
|=
1
;
// if buffer is full (8 bits), write out as a single byte
n
++
;
if
(
n
==
8
)
clearBuffer
();
}
/**
* Writes the 8-bit byte to standard output.
*/
private
static
void
writeByte
(
int
x
)
{
if
(
!
isInitialized
)
initialize
();
assert
x
>=
0
&&
x
<
256
;
// optimized if byte-aligned
if
(
n
==
0
)
{
try
{
out
.
write
(
x
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
return
;
}
// otherwise write one bit at a time
for
(
int
i
=
0
;
i
<
8
;
i
++
)
{
boolean
bit
=
((
x
>>>
(
8
–
i
–
1
))
&
1
)
==
1
;
writeBit
(
bit
);
}
}
// write out any remaining bits in buffer to standard output, padding with 0s
private
static
void
clearBuffer
()
{
if
(
!
isInitialized
)
initialize
();
if
(
n
==
0
)
return
;
if
(
n
>
0
)
buffer
<<=
(
8
-
n
);
try
{
out
.
write
(
buffer
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
n
=
0
;
buffer
=
0
;
}
/**
* Flushes standard output, padding 0s if number of bits written so far
* is not a multiple of 8.
*/
public
static
void
flush
()
{
clearBuffer
();
try
{
out
.
flush
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
/**
* Flushes and closes standard output. Once standard output is closed, you can no
* longer write bits to it.
*/
public
static
void
close
()
{
flush
();
try
{
out
.
close
();
isInitialized
=
false
;
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
/**
* Writes the specified bit to standard output.
*
@param
x the {
@code
boolean} to write.
*/
public
static
void
write
(
boolean
x
)
{
writeBit
(
x
);
}
/**
* Writes the 8-bit byte to standard output.
*
@param
x the {
@code
byte} to write.
*/
public
static
void
write
(
byte
x
)
{
writeByte
(
x
&
0xff
);
}
/**
* Writes the 32-bit int to standard output.
*
@param
x the {
@code
int} to write.
*/
public
static
void
write
(
int
x
)
{
writeByte
((
x
>>>
24
)
&
0xff
);
writeByte
((
x
>>>
16
)
&
0xff
);
writeByte
((
x
>>>
8
)
&
0xff
);
writeByte
((
x
>>>
0
)
&
0xff
);
}
/**
* Writes the r-bit int to standard output.
*
@param
x the {
@code
int} to write.
*
@param
r the number of relevant bits in the char.
*
@throws
IllegalArgumentException if {
@code
r} is not between 1 and 32.
*
@throws
IllegalArgumentException if {
@code
x} is not between 0 and 2r – 1.
*/
public
static
void
write
(
int
x
,
int
r
)
{
if
(
r
==
32
)
{
write
(
x
);
return
;
}
if
(
r
<
1
||
r
>
32
)
throw
new
IllegalArgumentException
(
“Illegal value for r = ”
+
r
);
if
(
x
<
0
||
x
>=
(
1
<<
r
))
throw
new
IllegalArgumentException
(
"Illegal "
+
r
+
"-bit char = "
+
x
);
for
(
int
i
=
0
;
i
<
r
;
i
++
)
{
boolean
bit
=
((
x
>>>
(
r
–
i
–
1
))
&
1
)
==
1
;
writeBit
(
bit
);
}
}
/**
* Writes the 64-bit double to standard output.
*
@param
x the {
@code
double} to write.
*/
public
static
void
write
(
double
x
)
{
write
(
Double
.
doubleToRawLongBits
(
x
));
}
/**
* Writes the 64-bit long to standard output.
*
@param
x the {
@code
long} to write.
*/
public
static
void
write
(
long
x
)
{
writeByte
((
int
)
((
x
>>>
56
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
48
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
40
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
32
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
24
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
16
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
8
)
&
0xff
));
writeByte
((
int
)
((
x
>>>
0
)
&
0xff
));
}
/**
* Writes the 32-bit float to standard output.
*
@param
x the {
@code
float} to write.
*/
public
static
void
write
(
float
x
)
{
write
(
Float
.
floatToRawIntBits
(
x
));
}
/**
* Writes the 16-bit int to standard output.
*
@param
x the {
@code
short} to write.
*/
public
static
void
write
(
short
x
)
{
writeByte
((
x
>>>
8
)
&
0xff
);
writeByte
((
x
>>>
0
)
&
0xff
);
}
/**
* Writes the 8-bit char to standard output.
*
@param
x the {
@code
char} to write.
*
@throws
IllegalArgumentException if {
@code
x} is not betwen 0 and 255.
*/
public
static
void
write
(
char
x
)
{
if
(
x
<
0
||
x
>=
256
)
throw
new
IllegalArgumentException
(
“Illegal 8-bit char = ”
+
x
);
writeByte
(
x
);
}
/**
* Writes the r-bit char to standard output.
*
@param
x the {
@code
char} to write.
*
@param
r the number of relevant bits in the char.
*
@throws
IllegalArgumentException if {
@code
r} is not between 1 and 16.
*
@throws
IllegalArgumentException if {
@code
x} is not between 0 and 2r – 1.
*/
public
static
void
write
(
char
x
,
int
r
)
{
if
(
r
==
8
)
{
write
(
x
);
return
;
}
if
(
r
<
1
||
r
>
16
)
throw
new
IllegalArgumentException
(
“Illegal value for r = ”
+
r
);
if
(
x
>=
(
1
<<
r
))
throw
new
IllegalArgumentException
(
"Illegal "
+
r
+
"-bit char = "
+
x
);
for
(
int
i
=
0
;
i
<
r
;
i
++
)
{
boolean
bit
=
((
x
>>>
(
r
–
i
–
1
))
&
1
)
==
1
;
writeBit
(
bit
);
}
}
/**
* Writes the string of 8-bit characters to standard output.
*
@param
s the {
@code
String} to write.
*
@throws
IllegalArgumentException if any character in the string is not
* between 0 and 255.
*/
public
static
void
write
(
String
s
)
{
for
(
int
i
=
0
;
i
<
s
.
length
();
i
++
)
write
(
s
.
charAt
(
i
));
}
/**
* Writes the string of r-bit characters to standard output.
*
@param
s the {
@code
String} to write.
*
@param
r the number of relevants bits in each character.
*
@throws
IllegalArgumentException if r is not between 1 and 16.
*
@throws
IllegalArgumentException if any character in the string is not
* between 0 and 2r – 1.
*/
public
static
void
write
(
String
s
,
int
r
)
{
for
(
int
i
=
0
;
i
<
s
.
length
();
i
++
)
write
(
s
.
charAt
(
i
),
r
);
}
/**
* Tests the methods in this class.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
m
=
Integer
.
parseInt
(
args
[
0
]);
// write n integers to binary standard output
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
BinaryStdOut
.
write
(
i
);
}
BinaryStdOut
.
flush
();
}
}
Draw.java
Draw.java
/******************************************************************************
* Compilation: javac Draw.java
* Execution: java Draw
* Dependencies: none
*
* Drawing library. This class provides a basic capability for creating
* drawings with your programs. It uses a simple graphics model that
* allows you to create drawings consisting of points, lines, and curves
* in a window on your computer and to save the drawings to a file.
* This is the object-oriented version of standard draw; it supports
* multiple indepedent drawing windows.
*
* Todo
* ----
* - Add support for gradient fill, etc.
*
* Remarks
* -------
* - don't use AffineTransform for rescaling since it inverts
* images and strings
* - careful using setFont in inner loop within an animation -
* it can cause flicker
*
******************************************************************************/
import
java
.
awt
.
BasicStroke
;
import
java
.
awt
.
Color
;
import
java
.
awt
.
Component
;
import
java
.
awt
.
FileDialog
;
import
java
.
awt
.
Font
;
import
java
.
awt
.
FontMetrics
;
import
java
.
awt
.
Graphics
;
import
java
.
awt
.
Graphics2D
;
import
java
.
awt
.
Image
;
import
java
.
awt
.
MediaTracker
;
import
java
.
awt
.
RenderingHints
;
import
java
.
awt
.
Toolkit
;
import
java
.
awt
.
event
.
ActionEvent
;
import
java
.
awt
.
event
.
ActionListener
;
import
java
.
awt
.
event
.
MouseEvent
;
import
java
.
awt
.
event
.
MouseListener
;
import
java
.
awt
.
event
.
MouseMotionListener
;
import
java
.
awt
.
event
.
KeyEvent
;
import
java
.
awt
.
event
.
KeyListener
;
import
java
.
awt
.
geom
.
Arc2D
;
import
java
.
awt
.
geom
.
Ellipse2D
;
import
java
.
awt
.
geom
.
GeneralPath
;
import
java
.
awt
.
geom
.
Line2D
;
import
java
.
awt
.
geom
.
Rectangle2D
;
import
java
.
awt
.
image
.
BufferedImage
;
import
java
.
awt
.
image
.
DirectColorModel
;
import
java
.
awt
.
image
.
WritableRaster
;
import
java
.
io
.
File
;
import
java
.
io
.
IOException
;
import
java
.
net
.
MalformedURLException
;
import
java
.
net
.
URL
;
import
java
.
util
.
ArrayList
;
import
java
.
util
.
LinkedList
;
import
java
.
util
.
TreeSet
;
import
javax
.
imageio
.
ImageIO
;
import
javax
.
swing
.
ImageIcon
;
import
javax
.
swing
.
JFrame
;
import
javax
.
swing
.
JLabel
;
import
javax
.
swing
.
JMenu
;
import
javax
.
swing
.
JMenuBar
;
import
javax
.
swing
.
JMenuItem
;
import
javax
.
swing
.
KeyStroke
;
/**
* Draw. This class provides a basic capability for
* creating drawings with your programs. It uses a simple graphics model that
* allows you to create drawings consisting of points, lines, and curves
* in a window on your computer and to save the drawings to a file.
* This is the object-oriented version of standard draw; it supports
* multiple indepedent drawing windows.
*
* For additional documentation, see
* Section 3.1 of
* Computer Science: An Interdisciplinary Approach by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
Draw
implements
ActionListener
,
MouseListener
,
MouseMotionListener
,
KeyListener
{
/**
* The color black.
*/
public
static
final
Color
BLACK
=
Color
.
BLACK
;
/**
* The color blue.
*/
public
static
final
Color
BLUE
=
Color
.
BLUE
;
/**
* The color cyan.
*/
public
static
final
Color
CYAN
=
Color
.
CYAN
;
/**
* The color dark gray.
*/
public
static
final
Color
DARK_GRAY
=
Color
.
DARK_GRAY
;
/**
* The color gray.
*/
public
static
final
Color
GRAY
=
Color
.
GRAY
;
/**
* The color green.
*/
public
static
final
Color
GREEN
=
Color
.
GREEN
;
/**
* The color light gray.
*/
public
static
final
Color
LIGHT_GRAY
=
Color
.
LIGHT_GRAY
;
/**
* The color magenta.
*/
public
static
final
Color
MAGENTA
=
Color
.
MAGENTA
;
/**
* The color orange.
*/
public
static
final
Color
ORANGE
=
Color
.
ORANGE
;
/**
* The color pink.
*/
public
static
final
Color
PINK
=
Color
.
PINK
;
/**
* The color red.
*/
public
static
final
Color
RED
=
Color
.
RED
;
/**
* The color white.
*/
public
static
final
Color
WHITE
=
Color
.
WHITE
;
/**
* The color yellow.
*/
public
static
final
Color
YELLOW
=
Color
.
YELLOW
;
/**
* Shade of blue used in Introduction to Programming in Java.
* It is Pantone 300U. The RGB values are approximately (9, 90, 166).
*/
public
static
final
Color
BOOK_BLUE
=
new
Color
(
9
,
90
,
166
);
/**
* Shade of light blue used in Introduction to Programming in Java.
* The RGB values are approximately (103, 198, 243).
*/
public
static
final
Color
BOOK_LIGHT_BLUE
=
new
Color
(
103
,
198
,
243
);
/**
* Shade of red used in Algorithms, 4th edition.
* It is Pantone 1805U. The RGB values are approximately (150, 35, 31).
*/
public
static
final
Color
BOOK_RED
=
new
Color
(
150
,
35
,
31
);
/**
* Shade of orange used in Princeton’s identity.
* It is PMS 158. The RGB values are approximately (245, 128, 37).
*/
public
static
final
Color
PRINCETON_ORANGE
=
new
Color
(
245
,
128
,
37
);
// default colors
private
static
final
Color
DEFAULT_PEN_COLOR
=
BLACK
;
private
static
final
Color
DEFAULT_CLEAR_COLOR
=
WHITE
;
// boundary of drawing canvas, 0% border
private
static
final
double
BORDER
=
0.0
;
private
static
final
double
DEFAULT_XMIN
=
0.0
;
private
static
final
double
DEFAULT_XMAX
=
1.0
;
private
static
final
double
DEFAULT_YMIN
=
0.0
;
private
static
final
double
DEFAULT_YMAX
=
1.0
;
// default canvas size is SIZE-by-SIZE
private
static
final
int
DEFAULT_SIZE
=
512
;
// default pen radius
private
static
final
double
DEFAULT_PEN_RADIUS
=
0.002
;
// default font
private
static
final
Font
DEFAULT_FONT
=
new
Font
(
“SansSerif”
,
Font
.
PLAIN
,
16
);
// current pen color
private
Color
penColor
;
// canvas size
private
int
width
=
DEFAULT_SIZE
;
private
int
height
=
DEFAULT_SIZE
;
// current pen radius
private
double
penRadius
;
// show we draw immediately or wait until next show?
private
boolean
defer
=
false
;
private
double
xmin
,
ymin
,
xmax
,
ymax
;
// name of window
private
String
name
=
“Draw”
;
// for synchronization
private
final
Object
mouseLock
=
new
Object
();
private
final
Object
keyLock
=
new
Object
();
// current font
private
Font
font
;
// the JLabel for drawing
private
JLabel
draw
;
// double buffered graphics
private
BufferedImage
offscreenImage
,
onscreenImage
;
private
Graphics2D
offscreen
,
onscreen
;
// the frame for drawing to the screen
private
JFrame
frame
=
new
JFrame
();
// mouse state
private
boolean
isMousePressed
=
false
;
private
double
mouseX
=
0
;
private
double
mouseY
=
0
;
// keyboard state
private
final
LinkedList
<
Character
>
keysTyped
=
new
LinkedList
<
Character
>
();
private
final
TreeSet
<
Integer
>
keysDown
=
new
TreeSet
<
Integer
>
();
// event-based listeners
private
final
ArrayList
<
DrawListener
>
listeners
=
new
ArrayList
<
DrawListener
>
();
/**
* Initializes an empty drawing object with the given name.
*
*
@param
name the title of the drawing window.
*/
public
Draw
(
String
name
)
{
this
.
name
=
name
;
init
();
}
/**
* Initializes an empty drawing object.
*/
public
Draw
()
{
init
();
}
private
void
init
()
{
if
(
frame
!=
null
)
frame
.
setVisible
(
false
);
frame
=
new
JFrame
();
offscreenImage
=
new
BufferedImage
(
2
*
width
,
2
*
height
,
BufferedImage
.
TYPE_INT_ARGB
);
onscreenImage
=
new
BufferedImage
(
2
*
width
,
2
*
height
,
BufferedImage
.
TYPE_INT_ARGB
);
offscreen
=
offscreenImage
.
createGraphics
();
onscreen
=
onscreenImage
.
createGraphics
();
offscreen
.
scale
(
2.0
,
2.0
);
// since we made it 2x as big
setXscale
();
setYscale
();
offscreen
.
setColor
(
DEFAULT_CLEAR_COLOR
);
offscreen
.
fillRect
(
0
,
0
,
width
,
height
);
setPenColor
();
setPenRadius
();
setFont
();
clear
();
// add antialiasing
RenderingHints
hints
=
new
RenderingHints
(
RenderingHints
.
KEY_ANTIALIASING
,
RenderingHints
.
VALUE_ANTIALIAS_ON
);
hints
.
put
(
RenderingHints
.
KEY_RENDERING
,
RenderingHints
.
VALUE_RENDER_QUALITY
);
offscreen
.
addRenderingHints
(
hints
);
// frame stuff
RetinaImageIcon
icon
=
new
RetinaImageIcon
(
onscreenImage
);
draw
=
new
JLabel
(
icon
);
draw
.
addMouseListener
(
this
);
draw
.
addMouseMotionListener
(
this
);
frame
.
setContentPane
(
draw
);
frame
.
addKeyListener
(
this
);
// JLabel cannot get keyboard focus
frame
.
setResizable
(
false
);
// frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // closes all windows
frame
.
setDefaultCloseOperation
(
JFrame
.
DISPOSE_ON_CLOSE
);
// closes only current window
frame
.
setFocusTraversalKeysEnabled
(
false
);
// to recognize VK_TAB with isKeyPressed()
frame
.
setTitle
(
name
);
frame
.
setJMenuBar
(
createMenuBar
());
frame
.
pack
();
frame
.
requestFocusInWindow
();
frame
.
setVisible
(
true
);
}
/**
* Sets the upper-left hand corner of the drawing window to be (x, y), where (0, 0) is upper left.
*
*
@param
x the number of pixels from the left
*
@param
y the number of pixels from the top
*
@throws
IllegalArgumentException if the width or height is 0 or negative
*/
public
void
setLocationOnScreen
(
int
x
,
int
y
)
{
if
(
x
<=
0
||
y
<=
0
)
throw
new
IllegalArgumentException
();
frame
.
setLocation
(
x
,
y
);
}
/**
* Sets the default close operation.
*
*
@param
value the value, typically {
@code
JFrame.EXIT_ON_CLOSE}
* (close all windows) or {
@code
JFrame.DISPOSE_ON_CLOSE}
* (close current window)
*/
public
void
setDefaultCloseOperation
(
int
value
)
{
frame
.
setDefaultCloseOperation
(
value
);
}
/**
* Sets the canvas (drawing area) to be width-by-height pixels.
* This also erases the current drawing and resets the coordinate system, pen radius,
* pen color, and font back to their default values.
* Ordinarly, this method is called once, at the very beginning of a program.
*
*
@param
canvasWidth the width as a number of pixels
*
@param
canvasHeight the height as a number of pixels
*
@throws
IllegalArgumentException unless both {
@code
canvasWidth}
* and {
@code
canvasHeight} are positive
*/
public
void
setCanvasSize
(
int
canvasWidth
,
int
canvasHeight
)
{
if
(
canvasWidth
<
1
||
canvasHeight
<
1
)
{
throw
new
IllegalArgumentException
(
"width and height must be positive"
);
}
width
=
canvasWidth
;
height
=
canvasHeight
;
init
();
}
// create the menu bar (changed to private)
private
JMenuBar
createMenuBar
()
{
JMenuBar
menuBar
=
new
JMenuBar
();
JMenu
menu
=
new
JMenu
(
"File"
);
menuBar
.
add
(
menu
);
JMenuItem
menuItem1
=
new
JMenuItem
(
" Save... "
);
menuItem1
.
addActionListener
(
this
);
// Java 10+: replace getMenuShortcutKeyMask() with getMenuShortcutKeyMaskEx()
menuItem1
.
setAccelerator
(
KeyStroke
.
getKeyStroke
(
KeyEvent
.
VK_S
,
Toolkit
.
getDefaultToolkit
().
getMenuShortcutKeyMask
()));
menu
.
add
(
menuItem1
);
return
menuBar
;
}
/***************************************************************************
* User and screen coordinate systems.
***************************************************************************/
// throw an IllegalArgumentException if x is NaN or infinite
private
static
void
validate
(
double
x
,
String
name
)
{
if
(
Double
.
isNaN
(
x
))
throw
new
IllegalArgumentException
(
name
+
" is NaN"
);
if
(
Double
.
isInfinite
(
x
))
throw
new
IllegalArgumentException
(
name
+
" is infinite"
);
}
// throw an IllegalArgumentException if s is null
private
static
void
validateNonnegative
(
double
x
,
String
name
)
{
if
(
x
<
0
)
throw
new
IllegalArgumentException
(
name
+
" negative"
);
}
// throw an IllegalArgumentException if s is null
private
static
void
validateNotNull
(
Object
x
,
String
name
)
{
if
(
x
==
null
)
throw
new
IllegalArgumentException
(
name
+
" is null"
);
}
/**
* Sets the x-scale to be the default (between 0.0 and 1.0).
*/
public
void
setXscale
()
{
setXscale
(
DEFAULT_XMIN
,
DEFAULT_XMAX
);
}
/**
* Sets the y-scale to be the default (between 0.0 and 1.0).
*/
public
void
setYscale
()
{
setYscale
(
DEFAULT_YMIN
,
DEFAULT_YMAX
);
}
/**
* Sets the x-scale.
*
*
@param
min the minimum value of the x-scale
*
@param
max the maximum value of the x-scale
*
@throws
IllegalArgumentException if {
@code
(max == min)}
*
@throws
IllegalArgumentException if either {
@code
min} or {
@code
max} is either NaN or infinite
*/
public
void
setXscale
(
double
min
,
double
max
)
{
validate
(
min
,
"min"
);
validate
(
max
,
"max"
);
double
size
=
max
-
min
;
if
(
size
==
0.0
)
throw
new
IllegalArgumentException
(
"the min and max are the same"
);
xmin
=
min
-
BORDER
*
size
;
xmax
=
max
+
BORDER
*
size
;
}
/**
* Sets the y-scale.
*
*
@param
min the minimum value of the y-scale
*
@param
max the maximum value of the y-scale
*
@throws
IllegalArgumentException if {
@code
(max == min)}
*
@throws
IllegalArgumentException if either {
@code
min} or {
@code
max} is either NaN or infinite
*/
public
void
setYscale
(
double
min
,
double
max
)
{
validate
(
min
,
"min"
);
validate
(
max
,
"max"
);
double
size
=
max
-
min
;
if
(
size
==
0.0
)
throw
new
IllegalArgumentException
(
"the min and max are the same"
);
ymin
=
min
-
BORDER
*
size
;
ymax
=
max
+
BORDER
*
size
;
}
// helper functions that scale from user coordinates to screen coordinates and back
private
double
scaleX
(
double
x
)
{
return
width
*
(
x
-
xmin
)
/
(
xmax
-
xmin
);
}
private
double
scaleY
(
double
y
)
{
return
height
*
(
ymax
-
y
)
/
(
ymax
-
ymin
);
}
private
double
factorX
(
double
w
)
{
return
w
*
width
/
Math
.
abs
(
xmax
-
xmin
);
}
private
double
factorY
(
double
h
)
{
return
h
*
height
/
Math
.
abs
(
ymax
-
ymin
);
}
private
double
userX
(
double
x
)
{
return
xmin
+
x
*
(
xmax
-
xmin
)
/
width
;
}
private
double
userY
(
double
y
)
{
return
ymax
-
y
*
(
ymax
-
ymin
)
/
height
;
}
/**
* Clears the screen to the default color (white).
*/
public
void
clear
()
{
clear
(
DEFAULT_CLEAR_COLOR
);
}
/**
* Clears the screen to the given color.
*
*
@param
color the color to make the background
*
@throws
IllegalArgumentException if {
@code
color} is {
@code
null}
*/
public
void
clear
(
Color
color
)
{
validateNotNull
(
color
,
"color"
);
offscreen
.
setColor
(
color
);
offscreen
.
fillRect
(
0
,
0
,
width
,
height
);
offscreen
.
setColor
(
penColor
);
draw
();
}
/**
* Gets the current pen radius.
*
*
@return
the current pen radius
*/
public
double
getPenRadius
()
{
return
penRadius
;
}
/**
* Sets the pen size to the default (.002).
*/
public
void
setPenRadius
()
{
setPenRadius
(
DEFAULT_PEN_RADIUS
);
}
/**
* Sets the radius of the pen to the given size.
*
*
@param
radius the radius of the pen
*
@throws
IllegalArgumentException if {
@code
radius} is negative, NaN, or infinite
*/
public
void
setPenRadius
(
double
radius
)
{
validate
(
radius
,
"pen radius"
);
validateNonnegative
(
radius
,
"pen radius"
);
penRadius
=
radius
*
DEFAULT_SIZE
;
BasicStroke
stroke
=
new
BasicStroke
((
float
)
penRadius
,
BasicStroke
.
CAP_ROUND
,
BasicStroke
.
JOIN_ROUND
);
// BasicStroke stroke = new BasicStroke((float) penRadius);
offscreen
.
setStroke
(
stroke
);
}
/**
* Gets the current pen color.
*
*
@return
the current pen color
*/
public
Color
getPenColor
()
{
return
penColor
;
}
/**
* Sets the pen color to the default color (black).
*/
public
void
setPenColor
()
{
setPenColor
(
DEFAULT_PEN_COLOR
);
}
/**
* Sets the pen color to the given color.
*
*
@param
color the color to make the pen
*
@throws
IllegalArgumentException if {
@code
color} is {
@code
null}
*/
public
void
setPenColor
(
Color
color
)
{
validateNotNull
(
color
,
"color"
);
penColor
=
color
;
offscreen
.
setColor
(
penColor
);
}
/**
* Sets the pen color to the given RGB color.
*
*
@param
red the amount of red (between 0 and 255)
*
@param
green the amount of green (between 0 and 255)
*
@param
blue the amount of blue (between 0 and 255)
*
@throws
IllegalArgumentException if {
@code
red}, {
@code
green},
* or {
@code
blue} is outside its prescribed range
*/
public
void
setPenColor
(
int
red
,
int
green
,
int
blue
)
{
if
(
red
<
0
||
red
>=
256
)
throw
new
IllegalArgumentException
(
“red must be between 0 and 255”
);
if
(
green
<
0
||
green
>=
256
)
throw
new
IllegalArgumentException
(
“green must be between 0 and 255”
);
if
(
blue
<
0
||
blue
>=
256
)
throw
new
IllegalArgumentException
(
“blue must be between 0 and 255”
);
setPenColor
(
new
Color
(
red
,
green
,
blue
));
}
/**
* Turns on xor mode.
*/
public
void
xorOn
()
{
offscreen
.
setXORMode
(
DEFAULT_CLEAR_COLOR
);
}
/**
* Turns off xor mode.
*/
public
void
xorOff
()
{
offscreen
.
setPaintMode
();
}
/**
* Gets the current {
@code
JLabel} for use in some other GUI.
*
*
@return
the current {
@code
JLabel}
*/
public
JLabel
getJLabel
()
{
return
draw
;
}
/**
* Gets the current font.
*
*
@return
the current font
*/
public
Font
getFont
()
{
return
font
;
}
/**
* Sets the font to the default font (sans serif, 16 point).
*/
public
void
setFont
()
{
setFont
(
DEFAULT_FONT
);
}
/**
* Sets the font to the given value.
*
*
@param
font the font
*
@throws
IllegalArgumentException if {
@code
font} is {
@code
null}
*/
public
void
setFont
(
Font
font
)
{
validateNotNull
(
font
,
“font”
);
this
.
font
=
font
;
}
/***************************************************************************
* Drawing geometric shapes.
***************************************************************************/
/**
* Draws a line from (x0, y0) to (x1, y1).
*
*
@param
x0 the x-coordinate of the starting point
*
@param
y0 the y-coordinate of the starting point
*
@param
x1 the x-coordinate of the destination point
*
@param
y1 the y-coordinate of the destination point
*
@throws
IllegalArgumentException if any coordinate is either NaN or infinite
*/
public
void
line
(
double
x0
,
double
y0
,
double
x1
,
double
y1
)
{
validate
(
x0
,
“x0”
);
validate
(
y0
,
“y0”
);
validate
(
x1
,
“x1”
);
validate
(
y1
,
“y1”
);
offscreen
.
draw
(
new
Line2D
.
Double
(
scaleX
(
x0
),
scaleY
(
y0
),
scaleX
(
x1
),
scaleY
(
y1
)));
draw
();
}
/**
* Draws one pixel at (x, y).
*
*
@param
x the x-coordinate of the pixel
*
@param
y the y-coordinate of the pixel
*
@throws
IllegalArgumentException if {
@code
x} or {
@code
y} is either NaN or infinite
*/
private
void
pixel
(
double
x
,
double
y
)
{
validate
(
x
,
“x”
);
validate
(
y
,
“y”
);
offscreen
.
fillRect
((
int
)
Math
.
round
(
scaleX
(
x
)),
(
int
)
Math
.
round
(
scaleY
(
y
)),
1
,
1
);
}
/**
* Draws a point at (x, y).
*
*
@param
x the x-coordinate of the point
*
@param
y the y-coordinate of the point
*
@throws
IllegalArgumentException if either {
@code
x} or {
@code
y} is either NaN or infinite
*/
public
void
point
(
double
x
,
double
y
)
{
validate
(
x
,
“x”
);
validate
(
y
,
“y”
);
double
xs
=
scaleX
(
x
);
double
ys
=
scaleY
(
y
);
double
r
=
penRadius
;
// double ws = factorX(2*r);
// double hs = factorY(2*r);
// if (ws <= 1 && hs <= 1) pixel(x, y);
if
(
r
<=
1
)
pixel
(
x
,
y
);
else
offscreen
.
fill
(
new
Ellipse2D
.
Double
(
xs
-
r
/
2
,
ys
-
r
/
2
,
r
,
r
));
draw
();
}
/**
* Draws a circle of the specified radius, centered at (x, y).
*
*
@param
x the x-coordinate of the center of the circle
*
@param
y the y-coordinate of the center of the circle
*
@param
radius the radius of the circle
*
@throws
IllegalArgumentException if {
@code
radius} is negative
*
@throws
IllegalArgumentException if any argument is either NaN or infinite
*/
public
void
circle
(
double
x
,
double
y
,
double
radius
)
{
validate
(
x
,
“x”
);
validate
(
y
,
“y”
);
validate
(
radius
,
“radius”
);
validateNonnegative
(
radius
,
“radius”
);
double
xs
=
scaleX
(
x
);
double
ys
=
scaleY
(
y
);
double
ws
=
factorX
(
2
*
radius
);
double
hs
=
factorY
(
2
*
radius
);
if
(
ws
<=
1
&&
hs
<=
1
)
pixel
(
x
,
y
);
else
offscreen
.
draw
(
new
Ellipse2D
.
Double
(
xs
-
ws
/
2
,
ys
-
hs
/
2
,
ws
,
hs
));
draw
();
}
/**
* Draws a filled circle of the specified radius, centered at (x, y).
*
*
@param
x the x-coordinate of the center of the circle
*
@param
y the y-coordinate of the center of the circle
*
@param
radius the radius of the circle
*
@throws
IllegalArgumentException if {
@code
radius} is negative
*
@throws
IllegalArgumentException if any argument is either NaN or infinite
*/
public
void
filledCircle
(
double
x
,
double
y
,
double
radius
)
{
validate
(
x
,
“x”
);
validate
(
y
,
“y”
);
validate
(
radius
,
“radius”
);
validateNonnegative
(
radius
,
“radius”
);
double
xs
=
scaleX
(
x
);
double
ys
=
scaleY
(
y
);
double
ws
=
factorX
(
2
*
radius
);
double
hs
=
factorY
(
2
*
radius
);
if
(
ws
<=
1
&&
hs
<=
1
)
pixel
(
x
,
y
);
else
offscreen
.
fill
(
new
Ellipse2D
.
Double
(
xs
-
ws
/
2
,
ys
-
hs
/
2
,
ws
,
hs
));
draw
();
}
/**
* Draws an ellipse with the specified semimajor and semiminor axes,
* centered at (x, y).
*
*
@param
x the x-coordinate of the center of the ellipse
*
@param
y the y-coordinate of the center of the ellipse
*
@param
semiMajorAxis is the semimajor axis of the ellipse
*
@param
semiMinorAxis is the semiminor axis of the ellipse
*
@throws
IllegalArgumentException if either {
@code
semiMajorAxis}
* or {
@code
semiMinorAxis} is negative
*
@throws
IllegalArgumentException if any argument is either NaN or infinite
*/
public
void
ellipse
(
double
x
,
double
y
,
double
semiMajorAxis
,
double
semiMinorAxis
)
{
validate
(
x
,
“x”
);
validate
(
y
,
“y”
);
validate
(
semiMajorAxis
,
“semimajor axis”
);
validate
(
semiMinorAxis
,
“semiminor axis”
);
validateNonnegative
(
semiMajorAxis
,
“semimajor axis”
);
validateNonnegative
(
semiMinorAxis
,
“semiminor axis”
);
double
xs
=
scaleX
(
x
);
double
ys
=
scaleY
(
y
);
double
ws
=
factorX
(
2
*
semiMajorAxis
);
double
hs
=
factorY
(
2
*
semiMinorAxis
);
if
(
ws
<=
1
&&
hs
<=
1
)
pixel
(
x
,
y
);
else
offscreen
.
draw
(
new
Ellipse2D
.
Double
(
xs
-
ws
/
2
,
ys
-
hs
/
2
,
ws
,
hs
));
draw
();
}
/**
* Draws a filled ellipse with the specified semimajor and semiminor axes,
* centered at (x, y).
*
*
@param
x the x-coordinate of the center of the ellipse
*
@param
y the y-coordinate of the center of the ellipse
*
@param
semiMajorAxis is the semimajor axis of the ellipse
*
@param
semiMinorAxis is the semiminor axis of the ellipse
*
@throws
IllegalArgumentException if either {
@code
semiMajorAxis}
* or {
@code
semiMinorAxis} is negative
*
@throws
IllegalArgumentException if any argument is either NaN or infinite
*/
public
void
filledEllipse
(
double
x
,
double
y
,
double
semiMajorAxis
,
double
semiMinorAxis
)
{
validate
(
x
,
“x”
);
validate
(
y
,
“y”
);
validate
(
semiMajorAxis
,
“semimajor axis”
);
validate
(
semiMinorAxis
,
“semiminor axis”
);
validateNonnegative
(
semiMajorAxis
,
“semimajor axis”
);
validateNonnegative
(
semiMinorAxis
,
“semiminor axis”
);
double
xs
=
scaleX
(
x
);
double
ys
=
scaleY
(
y
);
double
ws
=
factorX
(
2
*
semiMajorAxis
);
double
hs
=
factorY
(
2
*
semiMinorAxis
);
if
(
ws
<=
1
&&
hs
<=
1
)
pixel
(
x
,
y
);
else
offscreen
.
fill
(
new
Ellipse2D
.
Double
(
xs
-
ws
/
2
,
ys
-
hs
/
2
,
ws
,
hs
));
draw
();
}
/**
* Draws a circular arc of the specified radius,
* centered at (x, y), from angle1 to angle2 (in degrees).
*
*
@param
x the x-coordinate of the center of the circle
*
@param
y the y-coordinate of the center of the circle
*
@param
radius the radius of the circle
*
@param
angle1 the starting angle. 0 would mean an arc beginning at 3 o’clock.
*
@param
angle2 the angle at the end of the arc. For example, if
* you want a 90 degree arc, then angle2 should be angle1 + 90.
*
@throws
IllegalArgumentException if {
@code
radius} is negative
*
@throws
IllegalArgumentException if any argument is either NaN or infinite
*/
public
void
arc
(
double
x
,
double
y
,
double
radius
,
double
angle1
,
double
angle2
)
{
validate
(
x
,
“x”
);
validate
(
y
,
“y”
);
validate
(
radius
,
“arc radius”
);
validate
(
angle1
,
“angle1”
);
validate
(
angle2
,
“angle2”
);
validateNonnegative
(
radius
,
“arc radius”
);
while
(
angle2
<
angle1
)
angle2
+=
360
;
double
xs
=
scaleX
(
x
);
double ys = scaleY(y);
double ws = factorX(2*radius);
double hs = factorY(2*radius);
if (ws <= 1 && hs <= 1) pixel(x, y);
else offscreen.draw(new Arc2D.Double(xs - ws/2, ys - hs/2, ws, hs, angle1, angle2 - angle1, Arc2D.OPEN));
draw();
}
/** * Draws a square of the specified size, centered at (x, y). * * @param x the x-coordinate of the center of the square * @param y the y-coordinate of the center of the square * @param halfLength one half the length of any side of the square * @throws IllegalArgumentException if {@code halfLength} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public void square(double x, double y, double halfLength) {
validate(x, “x”);
validate(y, “y”);
validate(halfLength, “halfLength”);
validateNonnegative(halfLength, “half length”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*halfLength);
double hs = factorY(2*halfLength);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.draw(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws a square of the specified size, centered at (x, y). * * @param x the x-coordinate of the center of the square * @param y the y-coordinate of the center of the square * @param halfLength one half the length of any side of the square * @throws IllegalArgumentException if {@code halfLength} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public void filledSquare(double x, double y, double halfLength) {
validate(x, “x”);
validate(y, “y”);
validate(halfLength, “halfLength”);
validateNonnegative(halfLength, “half length”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*halfLength);
double hs = factorY(2*halfLength);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.fill(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws a rectangle of the specified size, centered at (x, y). * * @param x the x-coordinate of the center of the rectangle * @param y the y-coordinate of the center of the rectangle * @param halfWidth one half the width of the rectangle * @param halfHeight one half the height of the rectangle * @throws IllegalArgumentException if either {@code halfWidth} or {@code halfHeight} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public void rectangle(double x, double y, double halfWidth, double halfHeight) {
validate(x, “x”);
validate(y, “y”);
validate(halfWidth, “halfWidth”);
validate(halfHeight, “halfHeight”);
validateNonnegative(halfWidth, “half width”);
validateNonnegative(halfHeight, “half height”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*halfWidth);
double hs = factorY(2*halfHeight);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.draw(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws a filled rectangle of the specified size, centered at (x, y). * * @param x the x-coordinate of the center of the rectangle * @param y the y-coordinate of the center of the rectangle * @param halfWidth one half the width of the rectangle * @param halfHeight one half the height of the rectangle * @throws IllegalArgumentException if either {@code halfWidth} or {@code halfHeight} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public void filledRectangle(double x, double y, double halfWidth, double halfHeight) {
validate(x, “x”);
validate(y, “y”);
validate(halfWidth, “halfWidth”);
validate(halfHeight, “halfHeight”);
validateNonnegative(halfWidth, “half width”);
validateNonnegative(halfHeight, “half height”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*halfWidth);
double hs = factorY(2*halfHeight);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.fill(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws a polygon with the vertices * (x0, y0), * (x1, y1), …, * (xn–1, yn–1). * * @param x an array of all the x-coordinates of the polygon * @param y an array of all the y-coordinates of the polygon * @throws IllegalArgumentException unless {@code x[]} and {@code y[]} * are of the same length * @throws IllegalArgumentException if any coordinate is either NaN or infinite * @throws IllegalArgumentException if either {@code x[]} or {@code y[]} is {@code null} */
public void polygon(double[] x, double[] y) {
validateNotNull(x, “x-coordinate array”);
validateNotNull(y, “y-coordinate array”);
for (int i = 0; i < x.length; i++) validate(x[i], "x[" + i + "]"); for (int i = 0; i < y.length; i++) validate(y[i], "y[" + i + "]"); int n1 = x.length; int n2 = y.length; if (n1 != n2) throw new IllegalArgumentException("arrays must be of the same length"); int n = n1; if (n == 0) return; GeneralPath path = new GeneralPath(); path.moveTo((float) scaleX(x[0]), (float) scaleY(y[0])); for (int i = 0; i < n; i++) path.lineTo((float) scaleX(x[i]), (float) scaleY(y[i])); path.closePath(); offscreen.draw(path); draw(); } /** * Draws a filled polygon with the vertices * (x0, y0), * (x1, y1), …, * (xn–1, yn–1). * * @param x an array of all the x-coordinates of the polygon * @param y an array of all the y-coordinates of the polygon * @throws IllegalArgumentException unless {@code x[]} and {@code y[]} * are of the same length * @throws IllegalArgumentException if any coordinate is either NaN or infinite * @throws IllegalArgumentException if either {@code x[]} or {@code y[]} is {@code null} */
public void filledPolygon(double[] x, double[] y) {
validateNotNull(x, “x-coordinate array”);
validateNotNull(y, “y-coordinate array”);
for (int i = 0; i < x.length; i++) validate(x[i], "x[" + i + "]"); for (int i = 0; i < y.length; i++) validate(y[i], "y[" + i + "]"); int n1 = x.length; int n2 = y.length; if (n1 != n2) throw new IllegalArgumentException("arrays must be of the same length"); int n = n1; if (n == 0) return; GeneralPath path = new GeneralPath(); path.moveTo((float) scaleX(x[0]), (float) scaleY(y[0])); for (int i = 0; i < n; i++) path.lineTo((float) scaleX(x[i]), (float) scaleY(y[i])); path.closePath(); offscreen.fill(path); draw(); } /*************************************************************************** * Drawing images. ***************************************************************************/ // get an image from the given filename private static Image getImage(String filename) { if (filename == null) throw new IllegalArgumentException(); // to read from file ImageIcon icon = new ImageIcon(filename); // try to read from URL if ((icon == null) || (icon.getImageLoadStatus() != MediaTracker.COMPLETE)) { try { URL url = new URL(filename); icon = new ImageIcon(url); } catch (MalformedURLException e) { /* not a url */ } } // in case file is inside a .jar (classpath relative to StdDraw) if ((icon == null) || (icon.getImageLoadStatus() != MediaTracker.COMPLETE)) { URL url = StdDraw.class.getResource(filename); if (url != null) icon = new ImageIcon(url); } // in case file is inside a .jar (classpath relative to root of jar) if ((icon == null) || (icon.getImageLoadStatus() != MediaTracker.COMPLETE)) { URL url = Draw.class.getResource("/" + filename); if (url == null) throw new IllegalArgumentException("image " + filename + " not found"); icon = new ImageIcon(url); } return icon.getImage(); } /** * Draws the specified image centered at (x, y). * The supported image formats are JPEG, PNG, and GIF. * As an optimization, the picture is cached, so there is no performance * penalty for redrawing the same image multiple times (e.g., in an animation). * However, if you change the picture file after drawing it, subsequent * calls will draw the original picture. * * @param x the center x-coordinate of the image * @param y the center y-coordinate of the image * @param filename the name of the image/picture, e.g., “ball.gif” * @throws IllegalArgumentException if the image filename is invalid * @throws IllegalArgumentException if either {@code x} or {@code y} is either NaN or infinite */
public void picture(double x, double y, String filename) {
validate(x, “x”);
validate(y, “y”);
validateNotNull(filename, “filename”);
Image image = getImage(filename);
double xs = scaleX(x);
double ys = scaleY(y);
int ws = image.getWidth(null);
int hs = image.getHeight(null);
if (ws < 0 || hs < 0) throw new IllegalArgumentException("image " + filename + " is corrupt"); offscreen.drawImage(image, (int) Math.round(xs - ws/2.0), (int) Math.round(ys - hs/2.0), null); draw(); } /** * Draws the specified image centered at (x, y), * rotated given number of degrees. * The supported image formats are JPEG, PNG, and GIF. * * @param x the center x-coordinate of the image * @param y the center y-coordinate of the image * @param filename the name of the image/picture, e.g., “ball.gif” * @param degrees is the number of degrees to rotate counterclockwise * @throws IllegalArgumentException if the image filename is invalid * @throws IllegalArgumentException if {@code x}, {@code y}, {@code degrees} is NaN or infinite * @throws IllegalArgumentException if {@code filename} is {@code null} */
public void picture(double x, double y, String filename, double degrees) {
validate(x, “x”);
validate(y, “y”);
validate(degrees, “degrees”);
validateNotNull(filename, “filename”);
Image image = getImage(filename);
double xs = scaleX(x);
double ys = scaleY(y);
int ws = image.getWidth(null);
int hs = image.getHeight(null);
if (ws < 0 || hs < 0) throw new IllegalArgumentException("image " + filename + " is corrupt"); offscreen.rotate(Math.toRadians(-degrees), xs, ys); offscreen.drawImage(image, (int) Math.round(xs - ws/2.0), (int) Math.round(ys - hs/2.0), null); offscreen.rotate(Math.toRadians(+degrees), xs, ys); draw(); } /** * Draws the specified image centered at (x, y), * rescaled to the specified bounding box. * The supported image formats are JPEG, PNG, and GIF. * * @param x the center x-coordinate of the image * @param y the center y-coordinate of the image * @param filename the name of the image/picture, e.g., “ball.gif” * @param scaledWidth the width of the scaled image (in screen coordinates) * @param scaledHeight the height of the scaled image (in screen coordinates) * @throws IllegalArgumentException if either {@code scaledWidth} * or {@code scaledHeight} is negative * @throws IllegalArgumentException if the image filename is invalid * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite * @throws IllegalArgumentException if {@code filename} is {@code null} */
public void picture(double x, double y, String filename, double scaledWidth, double scaledHeight) {
validate(x, “x”);
validate(y, “y”);
validate(scaledWidth, “scaled width”);
validate(scaledHeight, “scaled height”);
validateNotNull(filename, “filename”);
validateNonnegative(scaledWidth, “scaled width”);
validateNonnegative(scaledHeight, “scaled height”);
Image image = getImage(filename);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(scaledWidth);
double hs = factorY(scaledHeight);
if (ws < 0 || hs < 0) throw new IllegalArgumentException("image " + filename + " is corrupt"); if (ws <= 1 && hs <= 1) pixel(x, y); else { offscreen.drawImage(image, (int) Math.round(xs - ws/2.0), (int) Math.round(ys - hs/2.0), (int) Math.round(ws), (int) Math.round(hs), null); } draw(); } /** * Draws the specified image centered at (x, y), rotated * given number of degrees, and rescaled to the specified bounding box. * The supported image formats are JPEG, PNG, and GIF. * * @param x the center x-coordinate of the image * @param y the center y-coordinate of the image * @param filename the name of the image/picture, e.g., “ball.gif” * @param scaledWidth the width of the scaled image (in screen coordinates) * @param scaledHeight the height of the scaled image (in screen coordinates) * @param degrees is the number of degrees to rotate counterclockwise * @throws IllegalArgumentException if either {@code scaledWidth} * or {@code scaledHeight} is negative * @throws IllegalArgumentException if the image filename is invalid */
public void picture(double x, double y, String filename, double scaledWidth, double scaledHeight, double degrees) {
validate(x, “x”);
validate(y, “y”);
validate(scaledWidth, “scaled width”);
validate(scaledHeight, “scaled height”);
validate(degrees, “degrees”);
validateNotNull(filename, “filename”);
validateNonnegative(scaledWidth, “scaled width”);
validateNonnegative(scaledHeight, “scaled height”);
Image image = getImage(filename);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(scaledWidth);
double hs = factorY(scaledHeight);
if (ws < 0 || hs < 0) throw new IllegalArgumentException("image " + filename + " is corrupt"); if (ws <= 1 && hs <= 1) pixel(x, y); offscreen.rotate(Math.toRadians(-degrees), xs, ys); offscreen.drawImage(image, (int) Math.round(xs - ws/2.0), (int) Math.round(ys - hs/2.0), (int) Math.round(ws), (int) Math.round(hs), null); offscreen.rotate(Math.toRadians(+degrees), xs, ys); draw(); } /*************************************************************************** * Drawing text. ***************************************************************************/ /** * Writes the given text string in the current font, centered at (x, y). * * @param x the center x-coordinate of the text * @param y the center y-coordinate of the text * @param text the text to write * @throws IllegalArgumentException if {@code text} is {@code null} * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite */
public void text(double x, double y, String text) {
validate(x, “x”);
validate(y, “y”);
validateNotNull(text, “text”);
offscreen.setFont(font);
FontMetrics metrics = offscreen.getFontMetrics();
double xs = scaleX(x);
double ys = scaleY(y);
int ws = metrics.stringWidth(text);
int hs = metrics.getDescent();
offscreen.drawString(text, (float) (xs – ws/2.0), (float) (ys + hs));
draw();
}
/** * Writes the given text string in the current font, centered at (x, y) and * rotated by the specified number of degrees. * @param x the center x-coordinate of the text * @param y the center y-coordinate of the text * @param text the text to write * @param degrees is the number of degrees to rotate counterclockwise * @throws IllegalArgumentException if {@code text} is {@code null} * @throws IllegalArgumentException if {@code x}, {@code y}, or {@code degrees} is either NaN or infinite */
public void text(double x, double y, String text, double degrees) {
validate(x, “x”);
validate(y, “y”);
validate(degrees, “degrees”);
validateNotNull(text, “text”);
double xs = scaleX(x);
double ys = scaleY(y);
offscreen.rotate(Math.toRadians(-degrees), xs, ys);
text(x, y, text);
offscreen.rotate(Math.toRadians(+degrees), xs, ys);
}
/** * Writes the given text string in the current font, left-aligned at (x, y). * @param x the x-coordinate of the text * @param y the y-coordinate of the text * @param text the text * @throws IllegalArgumentException if {@code text} is {@code null} * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite */
public void textLeft(double x, double y, String text) {
validate(x, “x”);
validate(y, “y”);
validateNotNull(text, “text”);
offscreen.setFont(font);
FontMetrics metrics = offscreen.getFontMetrics();
double xs = scaleX(x);
double ys = scaleY(y);
// int ws = metrics.stringWidth(text); int hs = metrics.getDescent();
offscreen.drawString(text, (float) xs, (float) (ys + hs));
draw();
}
/** * Writes the given text string in the current font, right-aligned at (x, y). * * @param x the x-coordinate of the text * @param y the y-coordinate of the text * @param text the text to write * @throws IllegalArgumentException if {@code text} is {@code null} * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite */
public void textRight(double x, double y, String text) {
validate(x, “x”);
validate(y, “y”);
validateNotNull(text, “text”);
offscreen.setFont(font);
FontMetrics metrics = offscreen.getFontMetrics();
double xs = scaleX(x);
double ys = scaleY(y);
int ws = metrics.stringWidth(text);
int hs = metrics.getDescent();
offscreen.drawString(text, (float) (xs – ws), (float) (ys + hs));
draw();
}
/** * Copies the offscreen buffer to the onscreen buffer, pauses for t milliseconds * and enables double buffering. * @param t number of milliseconds * @deprecated replaced by {@link #enableDoubleBuffering()}, {@link #show()}, and {@link #pause(int t)} */
@Deprecated
public void show(int t) {
show();
pause(t);
enableDoubleBuffering();
}
/** * Pause for t milliseconds. This method is intended to support computer animations. * @param t number of milliseconds */
public void pause(int t) {
try {
Thread.sleep(t);
}
catch (InterruptedException e) {
System.out.println(“Error sleeping”);
}
}
/** * Copies offscreen buffer to onscreen buffer. There is no reason to call * this method unless double buffering is enabled. */
public void show() {
onscreen.drawImage(offscreenImage, 0, 0, null);
frame.repaint();
}
// draw onscreen if defer is false private void draw() {
if (!defer) show();
}
/** * Enable double buffering. All subsequent calls to * drawing methods such as {@code line()}, {@code circle()}, * and {@code square()} will be deferred until the next call * to show(). Useful for animations. */
public void enableDoubleBuffering() {
defer = true;
}
/** * Disable double buffering. All subsequent calls to * drawing methods such as {@code line()}, {@code circle()}, * and {@code square()} will be displayed on screen when called. * This is the default. */
public void disableDoubleBuffering() {
defer = false;
}
/** * Saves the drawing to using the specified filename. * The supported image formats are JPEG and PNG; * the filename suffix must be {@code } or {@code }. * * @param filename the name of the file with one of the required suffixes * @throws IllegalArgumentException if {@code filename} is {@code null} */
public void save(String filename) {
validateNotNull(filename, “filename”);
File file = new File(filename);
String suffix = filename.substring(filename.lastIndexOf(‘.’) + 1);
// png files if (“png”.equalsIgnoreCase(suffix)) {
try {
ImageIO.write(offscreenImage, suffix, file);
}
catch (IOException e) {
e.printStackTrace();
}
}
// need to change from ARGB to RGB for jpeg // reference: http://archives.java.sun.com/cgi-bin/wa?A2=ind0404&L=java2d-interest&D=0&P=2727 else if (“jpg”.equalsIgnoreCase(suffix)) {
WritableRaster raster = offscreenImage.getRaster();
WritableRaster newRaster;
newRaster = raster.createWritableChild(0, 0, width, height, 0, 0, new int[] {0, 1, 2});
DirectColorModel cm = (DirectColorModel) offscreenImage.getColorModel();
DirectColorModel newCM = new DirectColorModel(cm.getPixelSize(),
cm.getRedMask(),
cm.getGreenMask(),
cm.getBlueMask());
BufferedImage rgbBuffer = new BufferedImage(newCM, newRaster, false, null);
try {
ImageIO.write(rgbBuffer, suffix, file);
}
catch (IOException e) {
e.printStackTrace();
}
}
else {
System.out.println(“Invalid image file type: ” + suffix);
}
}
/** * This method cannot be called directly. */
@Override
public void actionPerformed(ActionEvent e) {
FileDialog chooser = new FileDialog(frame, “Use a or extension”, FileDialog.SAVE);
chooser.setVisible(true);
String filename = chooser.getFile();
if (filename != null) {
save(chooser.getDirectory() + File.separator + chooser.getFile());
}
}
/*************************************************************************** * Event-based interactions. ***************************************************************************/
/** * Adds a {@link DrawListener} to listen to keyboard and mouse events. * * @param listener the {\tt DrawListener} argument */
public void addListener(DrawListener listener) {
// ensure there is a window for listenting to events show();
listeners.add(listener);
frame.addKeyListener(this);
frame.addMouseListener(this);
frame.addMouseMotionListener(this);
frame.setFocusable(true); }
/*************************************************************************** * Mouse interactions. ***************************************************************************/
/** * Returns true if the mouse is being pressed. * * @return {@code true} if the mouse is being pressed; * {@code false} otherwise */
public boolean isMousePressed() {
synchronized (mouseLock) {
return isMousePressed;
}
}
/** * Returns true if the mouse is being pressed. * * @return {@code true} if the mouse is being pressed; * {@code false} otherwise * @deprecated replaced by {@link #isMousePressed()} */
@Deprecated
public boolean mousePressed() {
synchronized (mouseLock) {
return isMousePressed;
}
}
/** * Returns the x-coordinate of the mouse. * @return the x-coordinate of the mouse */
public double mouseX() {
synchronized (mouseLock) {
return mouseX;
}
}
/** * Returns the y-coordinate of the mouse. * * @return the y-coordinate of the mouse */
public double mouseY() {
synchronized (mouseLock) {
return mouseY;
}
}
/** * This method cannot be called directly. */
@Override
public void mouseEntered(MouseEvent e) {
// this body is intentionally left empty }
/** * This method cannot be called directly. */
@Override
public void mouseExited(MouseEvent e) {
// this body is intentionally left empty }
/** * This method cannot be called directly. */
@Override
public void mousePressed(MouseEvent e) {
synchronized (mouseLock) {
mouseX = userX(e.getX());
mouseY = userY(e.getY());
isMousePressed = true;
}
if (e.getButton() == MouseEvent.BUTTON1) {
for (DrawListener listener : listeners)
listener.mousePressed(userX(e.getX()), userY(e.getY()));
}
}
/** * This method cannot be called directly. */
@Override
public void mouseReleased(MouseEvent e) {
synchronized (mouseLock) {
isMousePressed = false;
}
if (e.getButton() == MouseEvent.BUTTON1) {
for (DrawListener listener : listeners)
listener.mouseReleased(userX(e.getX()), userY(e.getY()));
}
}
/** * This method cannot be called directly. */
@Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
for (DrawListener listener : listeners)
listener.mouseClicked(userX(e.getX()), userY(e.getY()));
}
}
/** * This method cannot be called directly. */
@Override
public void mouseDragged(MouseEvent e) {
synchronized (mouseLock) {
mouseX = userX(e.getX());
mouseY = userY(e.getY());
}
// doesn’t seem to work if a button is specified for (DrawListener listener : listeners)
listener.mouseDragged(userX(e.getX()), userY(e.getY()));
}
/** * This method cannot be called directly. */
@Override
public void mouseMoved(MouseEvent e) {
synchronized (mouseLock) {
mouseX = userX(e.getX());
mouseY = userY(e.getY());
}
}
/*************************************************************************** * Keyboard interactions. ***************************************************************************/
/** * Returns true if the user has typed a key. * * @return {@code true} if the user has typed a key; {@code false} otherwise */
public boolean hasNextKeyTyped() {
synchronized (keyLock) {
return !keysTyped.isEmpty();
}
}
/** * The next key typed by the user. * * @return the next key typed by the user */
public char nextKeyTyped() {
synchronized (keyLock) {
return keysTyped.removeLast();
}
}
/** * Returns true if the keycode is being pressed. *
* This method takes as an argument the keycode (corresponding to a physical key). * It can handle action keys (such as F1 and arrow keys) and modifier keys * (such as shift and control). * See {@link KeyEvent} for a description of key codes. * * @param keycode the keycode to check * @return {@code true} if {@code keycode} is currently being pressed; * {@code false} otherwise */
public boolean isKeyPressed(int keycode) {
synchronized (keyLock) {
return keysDown.contains(keycode);
}
}
/** * This method cannot be called directly. */
@Override
public void keyTyped(KeyEvent e) {
synchronized (keyLock) {
keysTyped.addFirst(e.getKeyChar());
}
// notify all listeners for (DrawListener listener : listeners)
listener.keyTyped(e.getKeyChar());
}
/** * This method cannot be called directly. */
@Override
public void keyPressed(KeyEvent e) {
synchronized (keyLock) {
keysDown.add(e.getKeyCode());
}
// notify all listeners for (DrawListener listener : listeners)
listener.keyPressed(e.getKeyCode());
}
/** * This method cannot be called directly. */
@Override
public void keyReleased(KeyEvent e) {
synchronized (keyLock) {
keysDown.remove(e.getKeyCode());
}
// notify all listeners for (DrawListener listener : listeners)
listener.keyPressed(e.getKeyCode());
}
/*************************************************************************** * For improved resolution on Mac Retina displays. ***************************************************************************/
private static class RetinaImageIcon extends ImageIcon {
public RetinaImageIcon(Image image) {
super(image);
}
public int getIconWidth() {
return super.getIconWidth() / 2;
}
/** * Gets the height of the icon. * * @return the height in pixels of this icon */
public int getIconHeight() {
return super.getIconHeight() / 2;
}
public synchronized void paintIcon(Component c, Graphics g, int x, int y) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2.scale(0.5, 0.5);
super.paintIcon(c, g2, x * 2, y * 2);
g2.dispose();
}
}
/** * Test client. * * @param args the command-line arguments */
public static void main(String[] args) {
// create one drawing window Draw draw1 = new Draw(“Test client 1”);
draw1.square(0.2, 0.8, 0.1);
draw1.filledSquare(0.8, 0.8, 0.2);
draw1.circle(0.8, 0.2, 0.2);
draw1.setPenColor(Draw.MAGENTA);
draw1.setPenRadius(0.02);
draw1.arc(0.8, 0.2, 0.1, 200, 45);
// create another one Draw draw2 = new Draw(“Test client 2”);
draw2.setCanvasSize(900, 200);
// draw a blue diamond draw2.setPenRadius();
draw2.setPenColor(Draw.BLUE);
double[] x = { 0.1, 0.2, 0.3, 0.2 };
double[] y = { 0.2, 0.3, 0.2, 0.1 };
draw2.filledPolygon(x, y);
// text draw2.setPenColor(Draw.BLACK);
draw2.text(0.2, 0.5, “bdfdfdfdlack text”);
draw2.setPenColor(Draw.WHITE);
draw2.text(0.8, 0.8, “white text”);
}
}
DrawListener.java
DrawListener.java
/******************************************************************************
* Compilation: javac DrawListener.java
* Execution: none
* Dependencies: none
*
* Interface that accompanies Draw.java.
******************************************************************************/
/**
* DrawListener. This interface provides a basic capability for
* responding to keyboard in mouse events from {
@link
Draw} via callbacks.
* You can see some examples in
* Section 3.6.
*
*
* For additional documentation, see
* Section 3.1 of
* Computer Science: An Interdisciplinary Approach by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
interface
DrawListener
{
/**
* Invoked when the mouse has been pressed.
*
*
@param
x the x-coordinate of the mouse
*
@param
y the y-coordinate of the mouse
*/
void
mousePressed
(
double
x
,
double
y
);
/**
* Invoked when the mouse has been dragged.
*
*
@param
x the x-coordinate of the mouse
*
@param
y the y-coordinate of the mouse
*/
void
mouseDragged
(
double
x
,
double
y
);
/**
* Invoked when the mouse has been released.
*
*
@param
x the x-coordinate of the mouse
*
@param
y the y-coordinate of the mouse
*/
void
mouseReleased
(
double
x
,
double
y
);
/**
* Invoked when the mouse has been clicked (pressed and released).
*
*
@param
x the x-coordinate of the mouse
*
@param
y the y-coordinate of the mouse
*/
void
mouseClicked
(
double
x
,
double
y
);
/**
* Invoked when a key has been typed.
*
*
@param
c the character typed
*/
void
keyTyped
(
char
c
);
/**
* Invoked when a key has been pressed.
*
*
@param
keycode the key combination pressed
*/
void
keyPressed
(
int
keycode
);
/**
* Invoked when a key has been released.
*
*
@param
keycode the key combination released
*/
void
keyReleased
(
int
keycode
);
}
GrayscalePicture.java
GrayscalePicture.java
/******************************************************************************
* Compilation: javac GrayscalePicture.java
* Execution: java GrayscalePicture imagename
* Dependencies: none
*
* Data type for manipulating individual pixels of a grayscale image. The
* original image can be read from a file in JPEG, GIF, or PNG format, or the
* user can create a blank image of a given dimension. Includes methods for
* displaying the image in a window on the screen or saving to a file.
*
* % java GrayscalePicture mandrill
*
* Remarks
* ——-
* – pixel (x, y) is column x and row y, where (0, 0) is upper left
*
* – uses BufferedImage.TYPE_INT_RGB because BufferedImage.TYPE_BYTE_GRAY
* seems to do some undesirable olor correction when calling getRGB() and
* setRGB()
*
******************************************************************************/
import
java
.
awt
.
Color
;
import
java
.
awt
.
FileDialog
;
import
java
.
awt
.
Toolkit
;
import
java
.
awt
.
event
.
ActionEvent
;
import
java
.
awt
.
event
.
ActionListener
;
import
java
.
awt
.
event
.
KeyEvent
;
import
java
.
awt
.
image
.
BufferedImage
;
import
java
.
io
.
File
;
import
java
.
io
.
IOException
;
import
java
.
net
.
URL
;
import
javax
.
imageio
.
ImageIO
;
import
javax
.
swing
.
ImageIcon
;
import
javax
.
swing
.
JFrame
;
import
javax
.
swing
.
JLabel
;
import
javax
.
swing
.
JMenu
;
import
javax
.
swing
.
JMenuBar
;
import
javax
.
swing
.
JMenuItem
;
import
javax
.
swing
.
JPanel
;
import
javax
.
swing
.
KeyStroke
;
/**
* This class provides methods for manipulating individual pixels of
* a grayscale image.
* The original image can be read from a {
@code
PNG}, {
@code
GIF},
* or {
@code
JPEG} file or the user can create a blank image of a given dimension.
* This class includes methods for displaying the image in a window on
* the screen or saving it to a file.
*
* Pixel (col, row) is column col and row row.
* By default, the origin (0, 0) is the pixel in the top-left corner,
* which is a common convention in image processing.
* The method {
@link
#setOriginLowerLeft()} change the origin to the lower left.
*
* The {
@code
get()} and {
@code
set()} methods use {
@link
Color} objects to get
* or set the color of the specified pixel. The {
@link
Color} objects are converted
* to grayscale if they have different values for the R, G, and B channels.
* The {
@code
getGrayscale()} and {
@code
setGrayscale()} methods use an
* 8-bit {
@code
int} to encode the grayscale value, thereby avoiding the need to
* create temporary {
@code
Color} objects.
*
* A W-by-H picture uses ~ 4 W H bytes of memory,
* since the color of each pixel is encoded as a 32-bit int
* (even though, in principle, only ~ W H bytes are needed).
*
* For additional documentation, see
* Section 3.1 of
* Computer Science: An Interdisciplinary Approach
* by Robert Sedgewick and Kevin Wayne.
* See {
@link
Picture} for a version that supports 32-bit RGB color images.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
GrayscalePicture
implements
ActionListener
{
private
BufferedImage
image
;
// the rasterized image
private
JFrame
frame
;
// on-screen view
private
String
filename
;
// name of file
private
boolean
isOriginUpperLeft
=
true
;
// location of origin
private
final
int
width
,
height
;
// width and height
/**
* Creates a {
@code
width}-by-{
@code
height} picture, with {
@code
width} columns
* and {
@code
height} rows, where each pixel is black.
*
*
@param
width the width of the picture
*
@param
height the height of the picture
*
@throws
IllegalArgumentException if {
@code
width} is negative
*
@throws
IllegalArgumentException if {
@code
height} is negative
*/
public
GrayscalePicture
(
int
width
,
int
height
)
{
if
(
width
<
0
)
throw
new
IllegalArgumentException
(
"width must be non-negative"
);
if
(
height
<
0
)
throw
new
IllegalArgumentException
(
"height must be non-negative"
);
this
.
width
=
width
;
this
.
height
=
height
;
image
=
new
BufferedImage
(
width
,
height
,
BufferedImage
.
TYPE_INT_RGB
);
}
/**
* Creates a new grayscale picture that is a deep copy of the argument picture.
*
*
@param
picture the picture to copy
*
@throws
IllegalArgumentException if {
@code
picture} is {
@code
null}
*/
public
GrayscalePicture
(
GrayscalePicture
picture
)
{
if
(
picture
==
null
)
throw
new
IllegalArgumentException
(
"constructor argument is null"
);
width
=
picture
.
width
();
height
=
picture
.
height
();
image
=
new
BufferedImage
(
width
,
height
,
BufferedImage
.
TYPE_INT_RGB
);
filename
=
picture
.
filename
;
isOriginUpperLeft
=
picture
.
isOriginUpperLeft
;
for
(
int
col
=
0
;
col
<
width
();
col
++
)
for
(
int
row
=
0
;
row
<
height
();
row
++
)
image
.
setRGB
(
col
,
row
,
picture
.
image
.
getRGB
(
col
,
row
));
}
/**
* Creates a grayscale picture by reading an image from a file or URL.
*
*
@param
name the name of the file ( , .gif, or ) or URL.
*
@throws
IllegalArgumentException if cannot read image
*
@throws
IllegalArgumentException if {
@code
name} is {
@code
null}
*/
public
GrayscalePicture
(
String
name
)
{
if
(
name
==
null
)
throw
new
IllegalArgumentException
(
"constructor argument is null"
);
this
.
filename
=
name
;
try
{
// try to read from file in working directory
File
file
=
new
File
(
name
);
if
(
file
.
isFile
())
{
image
=
ImageIO
.
read
(
file
);
}
else
{
// resource relative to .class file
URL url
=
getClass
().
getResource
(
name
);
// resource relative to classloader root
if
(
url
==
null
)
{
url
=
getClass
().
getClassLoader
().
getResource
(
name
);
}
// or URL from web
if
(
url
==
null
)
{
url
=
new
URL
(
name
);
}
image
=
ImageIO
.
read
(
url
);
}
if
(
image
==
null
)
{
throw
new
IllegalArgumentException
(
"could not read image: "
+
name
);
}
width
=
image
.
getWidth
(
null
);
height
=
image
.
getHeight
(
null
);
// convert to grayscale inplace
for
(
int
col
=
0
;
col
<
width
;
col
++
)
{
for
(
int
row
=
0
;
row
<
height
;
row
++
)
{
Color
color
=
new
Color
(
image
.
getRGB
(
col
,
row
));
Color
gray
=
toGray
(
color
);
image
.
setRGB
(
col
,
row
,
gray
.
getRGB
());
}
}
}
catch
(
IOException
ioe
)
{
throw
new
IllegalArgumentException
(
"could not open image: "
+
name
,
ioe
);
}
}
// Returns a grayscale version of the given color as a Color object.
private
static
Color
toGray
(
Color
color
)
{
int
r
=
color
.
getRed
();
int
g
=
color
.
getGreen
();
int
b
=
color
.
getBlue
();
int
y
=
(
int
)
(
Math
.
round
(
0.299
*
r
+
0.587
*
g
+
0.114
*
b
));
return
new
Color
(
y
,
y
,
y
);
}
/**
* Returns a {
@link
JLabel} containing this picture, for embedding in a {
@link
JPanel},
* {
@link
JFrame} or other GUI widget.
*
*
@return
the {
@code
JLabel}
*/
public
JLabel
getJLabel
()
{
if
(
image
==
null
)
return
null
;
// no image available
ImageIcon
icon
=
new
ImageIcon
(
image
);
return
new
JLabel
(
icon
);
}
/**
* Sets the origin to be the upper left pixel. This is the default.
*/
public
void
setOriginUpperLeft
()
{
isOriginUpperLeft
=
true
;
}
/**
* Sets the origin to be the lower left pixel.
*/
public
void
setOriginLowerLeft
()
{
isOriginUpperLeft
=
false
;
}
/**
* Displays the picture in a window on the screen.
*/
public
void
show
()
{
// create the GUI for viewing the image if needed
if
(
frame
==
null
)
{
frame
=
new
JFrame
();
JMenuBar
menuBar
=
new
JMenuBar
();
JMenu
menu
=
new
JMenu
(
"File"
);
menuBar
.
add
(
menu
);
JMenuItem
menuItem1
=
new
JMenuItem
(
" Save... "
);
menuItem1
.
addActionListener
(
this
);
// use getMenuShortcutKeyMaskEx() in Java 10 (getMenuShortcutKeyMask() deprecated)
menuItem1
.
setAccelerator
(
KeyStroke
.
getKeyStroke
(
KeyEvent
.
VK_S
,
Toolkit
.
getDefaultToolkit
().
getMenuShortcutKeyMask
()));
menu
.
add
(
menuItem1
);
frame
.
setJMenuBar
(
menuBar
);
frame
.
setContentPane
(
getJLabel
());
// f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame
.
setDefaultCloseOperation
(
JFrame
.
DISPOSE_ON_CLOSE
);
if
(
filename
==
null
)
frame
.
setTitle
(
width
+
"-by-"
+
height
);
else
frame
.
setTitle
(
filename
);
frame
.
setResizable
(
false
);
frame
.
pack
();
frame
.
setVisible
(
true
);
}
// draw
frame
.
repaint
();
}
/**
* Returns the height of the picture.
*
*
@return
the height of the picture (in pixels)
*/
public
int
height
()
{
return
height
;
}
/**
* Returns the width of the picture.
*
*
@return
the width of the picture (in pixels)
*/
public
int
width
()
{
return
width
;
}
private
void
validateRowIndex
(
int
row
)
{
if
(
row
<
0
||
row
>=
height
())
throw
new
IllegalArgumentException
(
“row index must be between 0 and ”
+
(
height
()
–
1
)
+
“: ”
+
row
);
}
private
void
validateColumnIndex
(
int
col
)
{
if
(
col
<
0
||
col
>=
width
())
throw
new
IllegalArgumentException
(
“column index must be between 0 and ”
+
(
width
()
–
1
)
+
“: ”
+
col
);
}
private
void
validateGrayscaleValue
(
int
gray
)
{
if
(
gray
<
0
||
gray
>=
256
)
throw
new
IllegalArgumentException
(
“grayscale value must be between 0 and 255”
);
}
/**
* Returns the grayscale value of pixel ({
@code
col}, {
@code
row}) as a {
@link
java.awt.Color}.
*
*
@param
col the column index
*
@param
row the row index
*
@return
the grayscale value of pixel ({
@code
col}, {
@code
row})
*
@throws
IllegalArgumentException unless both {
@code
0 <= col < width} and {
@code
0 <= row < height}
*/
public
Color
get
(
int
col
,
int
row
)
{
validateColumnIndex
(
col
);
validateRowIndex
(
row
);
Color
color
=
new
Color
(
image
.
getRGB
(
col
,
row
));
return
toGray
(
color
);
}
/**
* Returns the grayscale value of pixel ({
@code
col}, {
@code
row}) as an {
@code
int}
* between 0 and 255.
* Using this method can be more efficient than {
@link
#get(int, int)} because
* it does not create a {
@code
Color} object.
*
*
@param
col the column index
*
@param
row the row index
*
@return
the 8-bit integer representation of the grayscale value of pixel ({
@code
col}, {
@code
row})
*
@throws
IllegalArgumentException unless both {
@code
0 <= col < width} and {
@code
0 <= row < height}
*/
public
int
getGrayscale
(
int
col
,
int
row
)
{
validateColumnIndex
(
col
);
validateRowIndex
(
row
);
if
(
isOriginUpperLeft
)
return
image
.
getRGB
(
col
,
row
)
&
0xFF
;
else
return
image
.
getRGB
(
col
,
height
-
row
-
1
)
&
0xFF
;
}
/**
* Sets the color of pixel ({
@code
col}, {
@code
row}) to the given grayscale value.
*
*
@param
col the column index
*
@param
row the row index
*
@param
color the color (converts to grayscale if color is not a shade of gray)
*
@throws
IllegalArgumentException unless both {
@code
0 <= col < width} and {
@code
0 <= row < height}
*
@throws
IllegalArgumentException if {
@code
color} is {
@code
null}
*/
public
void
set
(
int
col
,
int
row
,
Color
color
)
{
validateColumnIndex
(
col
);
validateRowIndex
(
row
);
if
(
color
==
null
)
throw
new
IllegalArgumentException
(
"color argument is null"
);
Color
gray
=
toGray
(
color
);
image
.
setRGB
(
col
,
row
,
gray
.
getRGB
());
}
/**
* Sets the color of pixel ({
@code
col}, {
@code
row}) to the given grayscale value
* between 0 and 255.
*
*
@param
col the column index
*
@param
row the row index
*
@param
gray the 8-bit integer representation of the grayscale value
*
@throws
IllegalArgumentException unless both {
@code
0 <= col < width} and {
@code
0 <= row < height}
*/
public
void
setGrayscale
(
int
col
,
int
row
,
int
gray
)
{
validateColumnIndex
(
col
);
validateRowIndex
(
row
);
validateGrayscaleValue
(
gray
);
int
rgb
=
gray
|
(
gray
<<
8
)
|
(
gray
<<
16
);
if
(
isOriginUpperLeft
)
image
.
setRGB
(
col
,
row
,
rgb
);
else
image
.
setRGB
(
col
,
height
-
row
-
1
,
rgb
);
}
/**
* Returns true if this picture is equal to the argument picture.
*
*
@param
other the other picture
*
@return
{
@code
true} if this picture is the same dimension as {
@code
other}
* and if all pixels have the same color; {
@code
false} otherwise
*/
public
boolean
equals
(
Object
other
)
{
if
(
other
==
this
)
return
true
;
if
(
other
==
null
)
return
false
;
if
(
other
.
getClass
()
!=
this
.
getClass
())
return
false
;
GrayscalePicture
that
=
(
GrayscalePicture
)
other
;
if
(
this
.
width
()
!=
that
.
width
())
return
false
;
if
(
this
.
height
()
!=
that
.
height
())
return
false
;
for
(
int
col
=
0
;
col
<
width
();
col
++
)
for
(
int
row
=
0
;
row
<
height
();
row
++
)
if
(
this
.
getGrayscale
(
col
,
row
)
!=
that
.
getGrayscale
(
col
,
row
))
return
false
;
return
true
;
}
/**
* Returns a string representation of this picture.
* The result is a width
-by-height
matrix of pixels,
* where the grayscale value of a pixel is an integer between 0 and 255.
*
*
@return
a string representation of this picture
*/
public
String
toString
()
{
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
width
+
“-by-”
+
height
+
” grayscale picture (grayscale values given in hex)\n”
);
for
(
int
row
=
0
;
row
<
height
;
row
++
)
{
for
(
int
col
=
0
;
col
<
width
;
col
++
)
{
int
gray
=
0
;
if
(
isOriginUpperLeft
)
gray
=
0xFF
&
image
.
getRGB
(
col
,
row
);
else
gray
=
0xFF
&
image
.
getRGB
(
col
,
height
-
row
-
1
);
sb
.
append
(
String
.
format
(
"%3d "
,
gray
));
}
sb
.
append
(
"\n"
);
}
return
sb
.
toString
().
trim
();
}
/**
* This operation is not supported because pictures are mutable.
*
*
@return
does not return a value
*
@throws
UnsupportedOperationException if called
*/
public
int
hashCode
()
{
throw
new
UnsupportedOperationException
(
"hashCode() is not supported because pictures are mutable"
);
}
/**
* Saves the picture to a file in either PNG or JPEG format.
* The filetype extension must be either or .
*
*
@param
name the name of the file
*
@throws
IllegalArgumentException if {
@code
name} is {
@code
null}
*/
public
void
save
(
String
name
)
{
if
(
name
==
null
)
throw
new
IllegalArgumentException
(
"argument to save() is null"
);
save
(
new
File
(
name
));
filename
=
name
;
}
/**
* Saves the picture to a file in a PNG or JPEG image format.
*
*
@param
file the file
*
@throws
IllegalArgumentException if {
@code
file} is {
@code
null}
*/
public
void
save
(
File
file
)
{
if
(
file
==
null
)
throw
new
IllegalArgumentException
(
"argument to save() is null"
);
filename
=
file
.
getName
();
if
(
frame
!=
null
)
frame
.
setTitle
(
filename
);
String
suffix
=
filename
.
substring
(
filename
.
lastIndexOf
(
'.'
)
+
1
);
if
(
"jpg"
.
equalsIgnoreCase
(
suffix
)
||
"png"
.
equalsIgnoreCase
(
suffix
))
{
try
{
ImageIO
.
write
(
image
,
suffix
,
file
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
else
{
System
.
out
.
println
(
"Error: filename must end in or "
);
}
}
/**
* Opens a save dialog box when the user selects "Save As" from the menu.
*/
@
Override
public
void
actionPerformed
(
ActionEvent
e
)
{
FileDialog
chooser
=
new
FileDialog
(
frame
,
"Use a or extension"
,
FileDialog
.
SAVE
);
chooser
.
setVisible
(
true
);
if
(
chooser
.
getFile
()
!=
null
)
{
save
(
chooser
.
getDirectory
()
+
File
.
separator
+
chooser
.
getFile
());
}
}
/**
* Unit tests this {
@code
Picture} data type.
* Reads a picture specified by the command-line argument,
* and shows it in a window on the screen.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
GrayscalePicture
picture
=
new
GrayscalePicture
(
args
[
0
]);
StdOut
.
printf
(
"%d-by-%d\n"
,
picture
.
width
(),
picture
.
height
());
GrayscalePicture
copy
=
new
GrayscalePicture
(
picture
);
picture
.
show
();
copy
.
show
();
while
(
!
StdIn
.
isEmpty
())
{
int
row
=
StdIn
.
readInt
();
int
col
=
StdIn
.
readInt
();
int
gray
=
StdIn
.
readInt
();
picture
.
setGrayscale
(
row
,
col
,
gray
);
StdOut
.
println
(
picture
.
get
(
row
,
col
));
StdOut
.
println
(
picture
.
getGrayscale
(
row
,
col
));
}
}
}
In.java
In.java
/******************************************************************************
* Compilation: javac In.java
* Execution: java In (basic test --- see source for required files)
* Dependencies: none
*
* Reads in data of various types from standard input, files, and URLs.
*
******************************************************************************/
import
java
.
io
.
BufferedInputStream
;
import
java
.
io
.
File
;
import
java
.
io
.
FileInputStream
;
import
java
.
io
.
IOException
;
import
java
.
io
.
InputStream
;
import
java
.
net
.
URL
;
import
java
.
net
.
Socket
;
// import java.net.HttpURLConnection;
import
java
.
net
.
URLConnection
;
import
java
.
util
.
ArrayList
;
import
java
.
util
.
InputMismatchException
;
import
java
.
util
.
Locale
;
import
java
.
util
.
NoSuchElementException
;
import
java
.
util
.
Scanner
;
import
java
.
util
.
regex
.
Pattern
;
/**
* Input. This class provides methods for reading strings
* and numbers from standard input, file input, URLs, and sockets.
*
* The Locale used is: language = English, country = US. This is consistent
* with the formatting conventions with Java floating-point literals,
* command-line arguments (via {
@link
Double#parseDouble(String)})
* and standard output.
*
* For additional documentation, see
* Section 3.1 of
* Computer Science: An Interdisciplinary Approach
* by Robert Sedgewick and Kevin Wayne.
*
* Like {
@link
Scanner}, reading a token also consumes preceding Java
* whitespace, reading a full line consumes
* the following end-of-line delimeter, while reading a character consumes
* nothing extra.
*
* Whitespace is defined in {
@link
Character#isWhitespace(char)}. Newlines
* consist of \n, \r, \r\n, and Unicode hex code points 0x2028, 0x2029, 0x0085;
* Scanner.java (NB: Java 6u23 and earlier uses only \r, \r, \r\n).
*
*
@author
David Pritchard
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
In
{
///// begin: section (1 of 2) of code duplicated from In to StdIn.
// assume Unicode UTF-8 encoding
private
static
final
String
CHARSET_NAME
=
“UTF-8”
;
// assume language = English, country = US for consistency with System.out.
private
static
final
Locale
LOCALE
=
Locale
.
US
;
// the default token separator; we maintain the invariant that this value
// is held by the scanner’s delimiter between calls
private
static
final
Pattern
WHITESPACE_PATTERN
=
Pattern
.
compile
(
“\\p{javaWhitespace}+”
);
// makes whitespace characters significant
private
static
final
Pattern
EMPTY_PATTERN
=
Pattern
.
compile
(
“”
);
// used to read the entire input. source:
// http://weblogs.java.net/blog/pat/archive/2004/10/stupid_scanner_1.html
private
static
final
Pattern
EVERYTHING_PATTERN
=
Pattern
.
compile
(
“\\A”
);
//// end: section (1 of 2) of code duplicated from In to StdIn.
private
Scanner
scanner
;
/**
* Initializes an input stream from standard input.
*/
public
In
()
{
scanner
=
new
Scanner
(
new
BufferedInputStream
(
System
.
in
),
CHARSET_NAME
);
scanner
.
useLocale
(
LOCALE
);
}
/**
* Initializes an input stream from a socket.
*
*
@param
socket the socket
*
@throws
IllegalArgumentException if cannot open {
@code
socket}
*
@throws
IllegalArgumentException if {
@code
socket} is {
@code
null}
*/
public
In
(
Socket
socket
)
{
if
(
socket
==
null
)
throw
new
IllegalArgumentException
(
“socket argument is null”
);
try
{
InputStream
is
=
socket
.
getInputStream
();
scanner
=
new
Scanner
(
new
BufferedInputStream
(
is
),
CHARSET_NAME
);
scanner
.
useLocale
(
LOCALE
);
}
catch
(
IOException
ioe
)
{
throw
new
IllegalArgumentException
(
“Could not open ”
+
socket
,
ioe
);
}
}
/**
* Initializes an input stream from a URL.
*
*
@param
url the URL
*
@throws
IllegalArgumentException if cannot open {
@code
url}
*
@throws
IllegalArgumentException if {
@code
url} is {
@code
null}
*/
public
In
(
URL url
)
{
if
(
url
==
null
)
throw
new
IllegalArgumentException
(
“url argument is null”
);
try
{
URLConnection
site
=
url
.
openConnection
();
InputStream
is
=
site
.
getInputStream
();
scanner
=
new
Scanner
(
new
BufferedInputStream
(
is
),
CHARSET_NAME
);
scanner
.
useLocale
(
LOCALE
);
}
catch
(
IOException
ioe
)
{
throw
new
IllegalArgumentException
(
“Could not open ”
+
url
,
ioe
);
}
}
/**
* Initializes an input stream from a file.
*
*
@param
file the file
*
@throws
IllegalArgumentException if cannot open {
@code
file}
*
@throws
IllegalArgumentException if {
@code
file} is {
@code
null}
*/
public
In
(
File
file
)
{
if
(
file
==
null
)
throw
new
IllegalArgumentException
(
“file argument is null”
);
try
{
// for consistency with StdIn, wrap with BufferedInputStream instead of use
// file as argument to Scanner
FileInputStream
fis
=
new
FileInputStream
(
file
);
scanner
=
new
Scanner
(
new
BufferedInputStream
(
fis
),
CHARSET_NAME
);
scanner
.
useLocale
(
LOCALE
);
}
catch
(
IOException
ioe
)
{
throw
new
IllegalArgumentException
(
“Could not open ”
+
file
,
ioe
);
}
}
/**
* Initializes an input stream from a filename or web page name.
*
*
@param
name the filename or web page name
*
@throws
IllegalArgumentException if cannot open {
@code
name} as
* a file or URL
*
@throws
IllegalArgumentException if {
@code
name} is {
@code
null}
*/
public
In
(
String
name
)
{
if
(
name
==
null
)
throw
new
IllegalArgumentException
(
“argument is null”
);
try
{
// first try to read file from local file system
File
file
=
new
File
(
name
);
if
(
file
.
exists
())
{
// for consistency with StdIn, wrap with BufferedInputStream instead of use
// file as argument to Scanner
FileInputStream
fis
=
new
FileInputStream
(
file
);
scanner
=
new
Scanner
(
new
BufferedInputStream
(
fis
),
CHARSET_NAME
);
scanner
.
useLocale
(
LOCALE
);
return
;
}
// resource relative to .class file
URL url
=
getClass
().
getResource
(
name
);
// resource relative to classloader root
if
(
url
==
null
)
{
url
=
getClass
().
getClassLoader
().
getResource
(
name
);
}
// or URL from web
if
(
url
==
null
)
{
url
=
new
URL
(
name
);
}
URLConnection
site
=
url
.
openConnection
();
// in order to set User-Agent, replace above line with these two
// HttpURLConnection site = (HttpURLConnection) url.openConnection();
// site.addRequestProperty(“User-Agent”, “Mozilla/4.76”);
InputStream
is
=
site
.
getInputStream
();
scanner
=
new
Scanner
(
new
BufferedInputStream
(
is
),
CHARSET_NAME
);
scanner
.
useLocale
(
LOCALE
);
}
catch
(
IOException
ioe
)
{
throw
new
IllegalArgumentException
(
“Could not open ”
+
name
,
ioe
);
}
}
/**
* Initializes an input stream from a given {
@link
Scanner} source; use with
* {
@code
new Scanner(String)} to read from a string.
*
* Note that this does not create a defensive copy, so the
* scanner will be mutated as you read on.
*
*
@param
scanner the scanner
*
@throws
IllegalArgumentException if {
@code
scanner} is {
@code
null}
*/
public
In
(
Scanner
scanner
)
{
if
(
scanner
==
null
)
throw
new
IllegalArgumentException
(
“scanner argument is null”
);
this
.
scanner
=
scanner
;
}
/**
* Returns true if this input stream exists.
*
*
@return
{
@code
true} if this input stream exists; {
@code
false} otherwise
*/
public
boolean
exists
()
{
return
scanner
!=
null
;
}
//// begin: section (2 of 2) of code duplicated from In to StdIn,
//// with all methods changed from “public” to “public static”.
/**
* Returns true if input stream is empty (except possibly whitespace).
* Use this to know whether the next call to {
@link
#readString()},
* {
@link
#readDouble()}, etc will succeed.
*
*
@return
{
@code
true} if this input stream is empty (except possibly whitespace);
* {
@code
false} otherwise
*/
public
boolean
isEmpty
()
{
return
!
scanner
.
hasNext
();
}
/**
* Returns true if this input stream has a next line.
* Use this method to know whether the
* next call to {
@link
#readLine()} will succeed.
* This method is functionally equivalent to {
@link
#hasNextChar()}.
*
*
@return
{
@code
true} if this input stream has more input (including whitespace);
* {
@code
false} otherwise
*/
public
boolean
hasNextLine
()
{
return
scanner
.
hasNextLine
();
}
/**
* Returns true if this input stream has more input (including whitespace).
* Use this method to know whether the next call to {
@link
#readChar()} will succeed.
* This method is functionally equivalent to {
@link
#hasNextLine()}.
*
*
@return
{
@code
true} if this input stream has more input (including whitespace);
* {
@code
false} otherwise
*/
public
boolean
hasNextChar
()
{
scanner
.
useDelimiter
(
EMPTY_PATTERN
);
boolean
result
=
scanner
.
hasNext
();
scanner
.
useDelimiter
(
WHITESPACE_PATTERN
);
return
result
;
}
/**
* Reads and returns the next line in this input stream.
*
*
@return
the next line in this input stream; {
@code
null} if no such line
*/
public
String
readLine
()
{
String
line
;
try
{
line
=
scanner
.
nextLine
();
}
catch
(
NoSuchElementException
e
)
{
line
=
null
;
}
return
line
;
}
/**
* Reads and returns the next character in this input stream.
*
*
@return
the next {
@code
char} in this input stream
*
@throws
NoSuchElementException if the input stream is empty
*/
public
char
readChar
()
{
scanner
.
useDelimiter
(
EMPTY_PATTERN
);
try
{
String
ch
=
scanner
.
next
();
assert
ch
.
length
()
==
1
:
“Internal (Std)In.readChar() error!”
+
” Please contact the authors.”
;
scanner
.
useDelimiter
(
WHITESPACE_PATTERN
);
return
ch
.
charAt
(
0
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attempts to read a ‘char’ value from the input stream, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads and returns the remainder of this input stream, as a string.
*
*
@return
the remainder of this input stream, as a string
*/
public
String
readAll
()
{
if
(
!
scanner
.
hasNextLine
())
return
“”
;
String
result
=
scanner
.
useDelimiter
(
EVERYTHING_PATTERN
).
next
();
// not that important to reset delimeter, since now scanner is empty
scanner
.
useDelimiter
(
WHITESPACE_PATTERN
);
// but let’s do it anyway
return
result
;
}
/**
* Reads the next token from this input stream and returns it as a {
@code
String}.
*
*
@return
the next {
@code
String} in this input stream
*
@throws
NoSuchElementException if the input stream is empty
*/
public
String
readString
()
{
try
{
return
scanner
.
next
();
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attempts to read a ‘String’ value from the input stream, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from this input stream, parses it as a {
@code
int},
* and returns the {
@code
int}.
*
*
@return
the next {
@code
int} in this input stream
*
@throws
NoSuchElementException if the input stream is empty
*
@throws
InputMismatchException if the next token cannot be parsed as an {
@code
int}
*/
public
int
readInt
()
{
try
{
return
scanner
.
nextInt
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read an ‘int’ value from the input stream, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attemps to read an ‘int’ value from the input stream, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from this input stream, parses it as a {
@code
double},
* and returns the {
@code
double}.
*
*
@return
the next {
@code
double} in this input stream
*
@throws
NoSuchElementException if the input stream is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
double}
*/
public
double
readDouble
()
{
try
{
return
scanner
.
nextDouble
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read a ‘double’ value from the input stream, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attemps to read a ‘double’ value from the input stream, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from this input stream, parses it as a {
@code
float},
* and returns the {
@code
float}.
*
*
@return
the next {
@code
float} in this input stream
*
@throws
NoSuchElementException if the input stream is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
float}
*/
public
float
readFloat
()
{
try
{
return
scanner
.
nextFloat
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read a ‘float’ value from the input stream, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attemps to read a ‘float’ value from the input stream, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from this input stream, parses it as a {
@code
long},
* and returns the {
@code
long}.
*
*
@return
the next {
@code
long} in this input stream
*
@throws
NoSuchElementException if the input stream is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
long}
*/
public
long
readLong
()
{
try
{
return
scanner
.
nextLong
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read a ‘long’ value from the input stream, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attemps to read a ‘long’ value from the input stream, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from this input stream, parses it as a {
@code
short},
* and returns the {
@code
short}.
*
*
@return
the next {
@code
short} in this input stream
*
@throws
NoSuchElementException if the input stream is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
short}
*/
public
short
readShort
()
{
try
{
return
scanner
.
nextShort
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read a ‘short’ value from the input stream, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attemps to read a ‘short’ value from the input stream, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from this input stream, parses it as a {
@code
byte},
* and returns the {
@code
byte}.
*
* To read binary data, use {
@link
BinaryIn}.
*
*
@return
the next {
@code
byte} in this input stream
*
@throws
NoSuchElementException if the input stream is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
byte}
*/
public
byte
readByte
()
{
try
{
return
scanner
.
nextByte
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read a ‘byte’ value from the input stream, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attemps to read a ‘byte’ value from the input stream, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from this input stream, parses it as a {
@code
boolean}
* (interpreting either {
@code
“true”} or {
@code
“1”} as {
@code
true},
* and either {
@code
“false”} or {
@code
“0”} as {
@code
false}).
*
*
@return
the next {
@code
boolean} in this input stream
*
@throws
NoSuchElementException if the input stream is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
boolean}
*/
public
boolean
readBoolean
()
{
try
{
String
token
=
readString
();
if
(
“true”
.
equalsIgnoreCase
(
token
))
return
true
;
if
(
“false”
.
equalsIgnoreCase
(
token
))
return
false
;
if
(
“1”
.
equals
(
token
))
return
true
;
if
(
“0”
.
equals
(
token
))
return
false
;
throw
new
InputMismatchException
(
“attempts to read a ‘boolean’ value from the input stream, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attempts to read a ‘boolean’ value from the input stream, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads all remaining tokens from this input stream and returns them as
* an array of strings.
*
*
@return
all remaining tokens in this input stream, as an array of strings
*/
public
String
[]
readAllStrings
()
{
// we could use readAll.trim().split(), but that’s not consistent
// since trim() uses characters 0x00..0x20 as whitespace
String
[]
tokens
=
WHITESPACE_PATTERN
.
split
(
readAll
());
if
(
tokens
.
length
==
0
||
tokens
[
0
].
length
()
>
0
)
return
tokens
;
String
[]
decapitokens
=
new
String
[
tokens
.
length
–
1
];
for
(
int
i
=
0
;
i
<
tokens
.
length
-
1
;
i
++
)
decapitokens
[
i
]
=
tokens
[
i
+
1
];
return
decapitokens
;
}
/**
* Reads all remaining lines from this input stream and returns them as
* an array of strings.
*
*
@return
all remaining lines in this input stream, as an array of strings
*/
public
String
[]
readAllLines
()
{
ArrayList
<
String
>
lines
=
new
ArrayList
<
String
>
();
while
(
hasNextLine
())
{
lines
.
add
(
readLine
());
}
return
lines
.
toArray
(
new
String
[
lines
.
size
()]);
}
/**
* Reads all remaining tokens from this input stream, parses them as integers,
* and returns them as an array of integers.
*
*
@return
all remaining lines in this input stream, as an array of integers
*/
public
int
[]
readAllInts
()
{
String
[]
fields
=
readAllStrings
();
int
[]
vals
=
new
int
[
fields
.
length
];
for
(
int
i
=
0
;
i
<
fields
.
length
;
i
++
)
vals
[
i
]
=
Integer
.
parseInt
(
fields
[
i
]);
return
vals
;
}
/**
* Reads all remaining tokens from this input stream, parses them as longs,
* and returns them as an array of longs.
*
*
@return
all remaining lines in this input stream, as an array of longs
*/
public
long
[]
readAllLongs
()
{
String
[]
fields
=
readAllStrings
();
long
[]
vals
=
new
long
[
fields
.
length
];
for
(
int
i
=
0
;
i
<
fields
.
length
;
i
++
)
vals
[
i
]
=
Long
.
parseLong
(
fields
[
i
]);
return
vals
;
}
/**
* Reads all remaining tokens from this input stream, parses them as doubles,
* and returns them as an array of doubles.
*
*
@return
all remaining lines in this input stream, as an array of doubles
*/
public
double
[]
readAllDoubles
()
{
String
[]
fields
=
readAllStrings
();
double
[]
vals
=
new
double
[
fields
.
length
];
for
(
int
i
=
0
;
i
<
fields
.
length
;
i
++
)
vals
[
i
]
=
Double
.
parseDouble
(
fields
[
i
]);
return
vals
;
}
///// end: section (2 of 2) of code duplicated from In to StdIn */
/**
* Closes this input stream.
*/
public
void
close
()
{
scanner
.
close
();
}
/**
* Reads all integers from a file and returns them as
* an array of integers.
*
*
@param
filename the name of the file
*
@return
the integers in the file
*
@deprecated
Replaced by {
@code
new In(filename)}.{
@link
#readAllInts()}.
*/
@
Deprecated
public
static
int
[]
readInts
(
String
filename
)
{
return
new
In
(
filename
).
readAllInts
();
}
/**
* Reads all doubles from a file and returns them as
* an array of doubles.
*
*
@param
filename the name of the file
*
@return
the doubles in the file
*
@deprecated
Replaced by {
@code
new In(filename)}.{
@link
#readAllDoubles()}.
*/
@
Deprecated
public
static
double
[]
readDoubles
(
String
filename
)
{
return
new
In
(
filename
).
readAllDoubles
();
}
/**
* Reads all strings from a file and returns them as
* an array of strings.
*
*
@param
filename the name of the file
*
@return
the strings in the file
*
@deprecated
Replaced by {
@code
new In(filename)}.{
@link
#readAllStrings()}.
*/
@
Deprecated
public
static
String
[]
readStrings
(
String
filename
)
{
return
new
In
(
filename
).
readAllStrings
();
}
/**
* Reads all integers from standard input and returns them
* an array of integers.
*
*
@return
the integers on standard input
*
@deprecated
Replaced by {
@link
StdIn#readAllInts()}.
*/
@
Deprecated
public
static
int
[]
readInts
()
{
return
new
In
().
readAllInts
();
}
/**
* Reads all doubles from standard input and returns them as
* an array of doubles.
*
*
@return
the doubles on standard input
*
@deprecated
Replaced by {
@link
StdIn#readAllDoubles()}.
*/
@
Deprecated
public
static
double
[]
readDoubles
()
{
return
new
In
().
readAllDoubles
();
}
/**
* Reads all strings from standard input and returns them as
* an array of strings.
*
*
@return
the strings on standard input
*
@deprecated
Replaced by {
@link
StdIn#readAllStrings()}.
*/
@
Deprecated
public
static
String
[]
readStrings
()
{
return
new
In
().
readAllStrings
();
}
/**
* Unit tests the {
@code
In} data type.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
In
in
;
String
urlName
=
"https://introcs.cs.princeton.edu/java/stdlib/InTest.txt"
;
// read from a URL
System
.
out
.
println
(
"readAll() from URL "
+
urlName
);
System
.
out
.
println
(
"---------------------------------------------------------------------------"
);
try
{
in
=
new
In
(
urlName
);
System
.
out
.
println
(
in
.
readAll
());
}
catch
(
IllegalArgumentException
e
)
{
System
.
out
.
println
(
e
);
}
System
.
out
.
println
();
// read one line at a time from URL
System
.
out
.
println
(
"readLine() from URL "
+
urlName
);
System
.
out
.
println
(
"---------------------------------------------------------------------------"
);
try
{
in
=
new
In
(
urlName
);
while
(
!
in
.
isEmpty
())
{
String
s
=
in
.
readLine
();
System
.
out
.
println
(
s
);
}
}
catch
(
IllegalArgumentException
e
)
{
System
.
out
.
println
(
e
);
}
System
.
out
.
println
();
// read one string at a time from URL
System
.
out
.
println
(
"readString() from URL "
+
urlName
);
System
.
out
.
println
(
"---------------------------------------------------------------------------"
);
try
{
in
=
new
In
(
urlName
);
while
(
!
in
.
isEmpty
())
{
String
s
=
in
.
readString
();
System
.
out
.
println
(
s
);
}
}
catch
(
IllegalArgumentException
e
)
{
System
.
out
.
println
(
e
);
}
System
.
out
.
println
();
// read one line at a time from file in current directory
System
.
out
.
println
(
"readLine() from current directory"
);
System
.
out
.
println
(
"---------------------------------------------------------------------------"
);
try
{
in
=
new
In
(
"./InTest.txt"
);
while
(
!
in
.
isEmpty
())
{
String
s
=
in
.
readLine
();
System
.
out
.
println
(
s
);
}
}
catch
(
IllegalArgumentException
e
)
{
System
.
out
.
println
(
e
);
}
System
.
out
.
println
();
// read one line at a time from file using relative path
System
.
out
.
println
(
"readLine() from relative path"
);
System
.
out
.
println
(
"---------------------------------------------------------------------------"
);
try
{
in
=
new
In
(
"../stdlib/InTest.txt"
);
while
(
!
in
.
isEmpty
())
{
String
s
=
in
.
readLine
();
System
.
out
.
println
(
s
);
}
}
catch
(
IllegalArgumentException
e
)
{
System
.
out
.
println
(
e
);
}
System
.
out
.
println
();
// read one char at a time
System
.
out
.
println
(
"readChar() from file"
);
System
.
out
.
println
(
"---------------------------------------------------------------------------"
);
try
{
in
=
new
In
(
"InTest.txt"
);
while
(
!
in
.
isEmpty
())
{
char
c
=
in
.
readChar
();
System
.
out
.
print
(
c
);
}
}
catch
(
IllegalArgumentException
e
)
{
System
.
out
.
println
(
e
);
}
System
.
out
.
println
();
System
.
out
.
println
();
// read one line at a time from absolute OS X / Linux path
System
.
out
.
println
(
"readLine() from absolute OS X / Linux path"
);
System
.
out
.
println
(
"---------------------------------------------------------------------------"
);
try
{
in
=
new
In
(
"/n/fs/introcs/www/java/stdlib/InTest.txt"
);
while
(
!
in
.
isEmpty
())
{
String
s
=
in
.
readLine
();
System
.
out
.
println
(
s
);
}
}
catch
(
IllegalArgumentException
e
)
{
System
.
out
.
println
(
e
);
}
System
.
out
.
println
();
// read one line at a time from absolute Windows path System.out.println("readLine() from absolute Windows path");
System.out.println("---------------------------------------------------------------------------");
try {
in = new In("G:\\www\\introcs\\stdlib\\InTest.txt");
while (!in.isEmpty()) {
String s = in.readLine();
System.out.println(s);
}
System.out.println();
}
catch (IllegalArgumentException e) {
System.out.println(e);
}
System.out.println();
}
}
Out.java
Out.java
/******************************************************************************
* Compilation: javac Out.java
* Execution: java Out
* Dependencies: none
*
* Writes data of various types to: stdout, file, or socket.
*
******************************************************************************/
import
java
.
io
.
FileOutputStream
;
import
java
.
io
.
IOException
;
import
java
.
io
.
OutputStream
;
import
java
.
io
.
OutputStreamWriter
;
import
java
.
io
.
PrintWriter
;
import
java
.
net
.
Socket
;
import
java
.
util
.
Locale
;
/**
* This class provides methods for writing strings and numbers to
* various output streams, including standard output, file, and sockets.
*
* For additional documentation, see
* Section 3.1 of
* Computer Science: An Interdisciplinary Approach
* by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Out
{
// force Unicode UTF-8 encoding; otherwise it’s system dependent
private
static
final
String
CHARSET_NAME
=
“UTF-8”
;
// assume language = English, country = US for consistency with In
private
static
final
Locale
LOCALE
=
Locale
.
US
;
private
PrintWriter
out
;
/**
* Initializes an output stream from a {
@link
OutputStream}.
*
*
@param
os the {
@code
OutputStream}
*/
public
Out
(
OutputStream
os
)
{
try
{
OutputStreamWriter
osw
=
new
OutputStreamWriter
(
os
,
CHARSET_NAME
);
out
=
new
PrintWriter
(
osw
,
true
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
/**
* Initializes an output stream from standard output.
*/
public
Out
()
{
this
(
System
.
out
);
}
/**
* Initializes an output stream from a socket.
*
*
@param
socket the socket
*/
public
Out
(
Socket
socket
)
{
try
{
OutputStream
os
=
socket
.
getOutputStream
();
OutputStreamWriter
osw
=
new
OutputStreamWriter
(
os
,
CHARSET_NAME
);
out
=
new
PrintWriter
(
osw
,
true
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
/**
* Initializes an output stream from a file.
*
*
@param
filename the name of the file
*/
public
Out
(
String
filename
)
{
try
{
OutputStream
os
=
new
FileOutputStream
(
filename
);
OutputStreamWriter
osw
=
new
OutputStreamWriter
(
os
,
CHARSET_NAME
);
out
=
new
PrintWriter
(
osw
,
true
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
/**
* Closes the output stream.
*/
public
void
close
()
{
out
.
close
();
}
/**
* Terminates the current line by printing the line-separator string.
*/
public
void
println
()
{
out
.
println
();
}
/**
* Prints an object to this output stream and then terminates the line.
*
*
@param
x the object to print
*/
public
void
println
(
Object
x
)
{
out
.
println
(
x
);
}
/**
* Prints a boolean to this output stream and then terminates the line.
*
*
@param
x the boolean to print
*/
public
void
println
(
boolean
x
)
{
out
.
println
(
x
);
}
/**
* Prints a character to this output stream and then terminates the line.
*
*
@param
x the character to print
*/
public
void
println
(
char
x
)
{
out
.
println
(
x
);
}
/**
* Prints a double to this output stream and then terminates the line.
*
*
@param
x the double to print
*/
public
void
println
(
double
x
)
{
out
.
println
(
x
);
}
/**
* Prints a float to this output stream and then terminates the line.
*
*
@param
x the float to print
*/
public
void
println
(
float
x
)
{
out
.
println
(
x
);
}
/**
* Prints an integer to this output stream and then terminates the line.
*
*
@param
x the integer to print
*/
public
void
println
(
int
x
)
{
out
.
println
(
x
);
}
/**
* Prints a long to this output stream and then terminates the line.
*
*
@param
x the long to print
*/
public
void
println
(
long
x
)
{
out
.
println
(
x
);
}
/**
* Prints a byte to this output stream and then terminates the line.
*
* To write binary data, see {
@link
BinaryOut}.
*
*
@param
x the byte to print
*/
public
void
println
(
byte
x
)
{
out
.
println
(
x
);
}
/**
* Flushes this output stream.
*/
public
void
print
()
{
out
.
flush
();
}
/**
* Prints an object to this output stream and flushes this output stream.
*
*
@param
x the object to print
*/
public
void
print
(
Object
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a boolean to this output stream and flushes this output stream.
*
*
@param
x the boolean to print
*/
public
void
print
(
boolean
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a character to this output stream and flushes this output stream.
*
*
@param
x the character to print
*/
public
void
print
(
char
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a double to this output stream and flushes this output stream.
*
*
@param
x the double to print
*/
public
void
print
(
double
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a float to this output stream and flushes this output stream.
*
*
@param
x the float to print
*/
public
void
print
(
float
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints an integer to this output stream and flushes this output stream.
*
*
@param
x the integer to print
*/
public
void
print
(
int
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a long integer to this output stream and flushes this output stream.
*
*
@param
x the long integer to print
*/
public
void
print
(
long
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a byte to this output stream and flushes this output stream.
*
*
@param
x the byte to print
*/
public
void
print
(
byte
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a formatted string to this output stream, using the specified format
* string and arguments, and then flushes this output stream.
*
*
@param
format the format string
*
@param
args the arguments accompanying the format string
*/
public
void
printf
(
String
format
,
Object
…
args
)
{
out
.
printf
(
LOCALE
,
format
,
args
);
out
.
flush
();
}
/**
* Prints a formatted string to this output stream, using the specified
* locale, format string, and arguments, and then flushes this output stream.
*
*
@param
locale the locale
*
@param
format the format string
*
@param
args the arguments accompanying the format string
*/
public
void
printf
(
Locale
locale
,
String
format
,
Object
…
args
)
{
out
.
printf
(
locale
,
format
,
args
);
out
.
flush
();
}
/**
* A test client.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
Out
out
;
// write to stdout
out
=
new
Out
();
out
.
println
(
“Test 1”
);
out
.
close
();
// write to a file
out
=
new
Out
(
“test.txt”
);
out
.
println
(
“Test 2”
);
out
.
close
();
}
}
Picture.java
Picture.java
/******************************************************************************
* Compilation: javac Picture.java
* Execution: java Picture imagename
* Dependencies: none
*
* Data type for manipulating individual pixels of an image. The original
* image can be read from a file in JPG, GIF, or PNG format, or the
* user can create a blank image of a given dimension. Includes methods for
* displaying the image in a window on the screen or saving to a file.
*
* % java Picture mandrill
*
* Remarks
* ——-
* – pixel (x, y) is column x and row y, where (0, 0) is upper left
*
******************************************************************************/
import
java
.
awt
.
Color
;
import
java
.
awt
.
FileDialog
;
import
java
.
awt
.
Toolkit
;
import
java
.
awt
.
event
.
ActionEvent
;
import
java
.
awt
.
event
.
ActionListener
;
import
java
.
awt
.
event
.
KeyEvent
;
import
java
.
awt
.
image
.
BufferedImage
;
import
java
.
io
.
File
;
import
java
.
io
.
IOException
;
import
java
.
net
.
URL
;
import
javax
.
imageio
.
ImageIO
;
import
javax
.
swing
.
ImageIcon
;
import
javax
.
swing
.
JFrame
;
import
javax
.
swing
.
JLabel
;
import
javax
.
swing
.
JMenu
;
import
javax
.
swing
.
JMenuBar
;
import
javax
.
swing
.
JMenuItem
;
import
javax
.
swing
.
JPanel
;
import
javax
.
swing
.
KeyStroke
;
/**
* This class provides methods for manipulating individual pixels of
* an image using the RGB color format. The alpha component (for transparency)
* is not currently supported.
* The original image can be read from a {
@code
PNG}, {
@code
GIF},
* or {
@code
JPEG} file or the user can create a blank image of a given dimension.
* This class includes methods for displaying the image in a window on
* the screen or saving it to a file.
*
* Pixel (col, row) is column col and row row.
* By default, the origin (0, 0) is the pixel in the top-left corner,
* which is a common convention in image processing.
* The method {
@link
#setOriginLowerLeft()} change the origin to the lower left.
*
* The {
@code
get()} and {
@code
set()} methods use {
@link
Color} objects to get
* or set the color of the specified pixel.
* The {
@code
getRGB()} and {
@code
setRGB()} methods use a 32-bit {
@code
int}
* to encode the color, thereby avoiding the need to create temporary
* {
@code
Color} objects. The red (R), green (G), and blue (B) components
* are encoded using the least significant 24 bits.
* Given a 32-bit {
@code
int} encoding the color, the following code extracts
* the RGB components:
*
* int r = (rgb >> 16) & 0xFF; * int g = (rgb >> 8) & 0xFF; * int b = (rgb >> 0) & 0xFF; *
* Given the RGB components (8-bits each) of a color,
* the following statement packs it into a 32-bit {
@code
int}:
*
* int rgb = (r << 16) + (g << 8) + (b << 0); *
*
* A W-by-H picture uses ~ 4 W H bytes of memory,
* since the color of each pixel is encoded as a 32-bit int
.
*
* For additional documentation, see
* Section 3.1 of
* Computer Science: An Interdisciplinary Approach
* by Robert Sedgewick and Kevin Wayne.
* See {
@link
GrayscalePicture} for a version that supports grayscale images.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
Picture
implements
ActionListener
{
private
BufferedImage
image
;
// the rasterized image
private
JFrame
frame
;
// on-screen view
private
String
filename
;
// name of file
private
boolean
isOriginUpperLeft
=
true
;
// location of origin
private
final
int
width
,
height
;
// width and height
/**
* Creates a {
@code
width}-by-{
@code
height} picture, with {
@code
width} columns
* and {
@code
height} rows, where each pixel is black.
*
*
@param
width the width of the picture
*
@param
height the height of the picture
*
@throws
IllegalArgumentException if {
@code
width} is negative or zero
*
@throws
IllegalArgumentException if {
@code
height} is negative or zero
*/
public
Picture
(
int
width
,
int
height
)
{
if
(
width
<=
0
)
throw
new
IllegalArgumentException
(
"width must be positive"
);
if
(
height
<=
0
)
throw
new
IllegalArgumentException
(
"height must be positive"
);
this
.
width
=
width
;
this
.
height
=
height
;
image
=
new
BufferedImage
(
width
,
height
,
BufferedImage
.
TYPE_INT_RGB
);
// set to TYPE_INT_ARGB here and in next constructor to support transparency
}
/**
* Creates a new picture that is a deep copy of the argument picture.
*
*
@param
picture the picture to copy
*
@throws
IllegalArgumentException if {
@code
picture} is {
@code
null}
*/
public
Picture
(
Picture
picture
)
{
if
(
picture
==
null
)
throw
new
IllegalArgumentException
(
"constructor argument is null"
);
width
=
picture
.
width
();
height
=
picture
.
height
();
image
=
new
BufferedImage
(
width
,
height
,
BufferedImage
.
TYPE_INT_RGB
);
filename
=
picture
.
filename
;
isOriginUpperLeft
=
picture
.
isOriginUpperLeft
;
for
(
int
col
=
0
;
col
<
width
();
col
++
)
for
(
int
row
=
0
;
row
<
height
();
row
++
)
image
.
setRGB
(
col
,
row
,
picture
.
image
.
getRGB
(
col
,
row
));
}
/**
* Creates a picture by reading an image from a file or URL.
*
*
@param
name the name of the file ( , .gif, or ) or URL.
*
@throws
IllegalArgumentException if cannot read image
*
@throws
IllegalArgumentException if {
@code
name} is {
@code
null}
*/
public
Picture
(
String
name
)
{
if
(
name
==
null
)
throw
new
IllegalArgumentException
(
"constructor argument is null"
);
this
.
filename
=
name
;
try
{
// try to read from file in working directory
File
file
=
new
File
(
name
);
if
(
file
.
isFile
())
{
image
=
ImageIO
.
read
(
file
);
}
else
{
// resource relative to .class file
URL url
=
getClass
().
getResource
(
filename
);
// resource relative to classloader root
if
(
url
==
null
)
{
url
=
getClass
().
getClassLoader
().
getResource
(
name
);
}
// or URL from web
if
(
url
==
null
)
{
url
=
new
URL
(
name
);
}
image
=
ImageIO
.
read
(
url
);
}
if
(
image
==
null
)
{
throw
new
IllegalArgumentException
(
"could not read image: "
+
name
);
}
width
=
image
.
getWidth
(
null
);
height
=
image
.
getHeight
(
null
);
}
catch
(
IOException
ioe
)
{
throw
new
IllegalArgumentException
(
"could not open image: "
+
name
,
ioe
);
}
}
/**
* Creates a picture by reading the image from a PNG, GIF, or JPEG file.
*
*
@param
file the file
*
@throws
IllegalArgumentException if cannot read image
*
@throws
IllegalArgumentException if {
@code
file} is {
@code
null}
*/
public
Picture
(
File
file
)
{
if
(
file
==
null
)
throw
new
IllegalArgumentException
(
"constructor argument is null"
);
try
{
image
=
ImageIO
.
read
(
file
);
}
catch
(
IOException
ioe
)
{
throw
new
IllegalArgumentException
(
"could not open file: "
+
file
,
ioe
);
}
if
(
image
==
null
)
{
throw
new
IllegalArgumentException
(
"could not read file: "
+
file
);
}
width
=
image
.
getWidth
(
null
);
height
=
image
.
getHeight
(
null
);
filename
=
file
.
getName
();
}
/**
* Returns a {
@link
JLabel} containing this picture, for embedding in a {
@link
JPanel},
* {
@link
JFrame} or other GUI widget.
*
*
@return
the {
@code
JLabel}
*/
public
JLabel
getJLabel
()
{
if
(
image
==
null
)
return
null
;
// no image available
ImageIcon
icon
=
new
ImageIcon
(
image
);
return
new
JLabel
(
icon
);
}
/**
* Sets the origin to be the upper left pixel. This is the default.
*/
public
void
setOriginUpperLeft
()
{
isOriginUpperLeft
=
true
;
}
/**
* Sets the origin to be the lower left pixel.
*/
public
void
setOriginLowerLeft
()
{
isOriginUpperLeft
=
false
;
}
/**
* Displays the picture in a window on the screen.
*/
public
void
show
()
{
// create the GUI for viewing the image if needed
if
(
frame
==
null
)
{
frame
=
new
JFrame
();
JMenuBar
menuBar
=
new
JMenuBar
();
JMenu
menu
=
new
JMenu
(
"File"
);
menuBar
.
add
(
menu
);
JMenuItem
menuItem1
=
new
JMenuItem
(
" Save... "
);
menuItem1
.
addActionListener
(
this
);
// use getMenuShortcutKeyMaskEx() in Java 10 (getMenuShortcutKeyMask() deprecated)
menuItem1
.
setAccelerator
(
KeyStroke
.
getKeyStroke
(
KeyEvent
.
VK_S
,
Toolkit
.
getDefaultToolkit
().
getMenuShortcutKeyMask
()));
menu
.
add
(
menuItem1
);
frame
.
setJMenuBar
(
menuBar
);
frame
.
setContentPane
(
getJLabel
());
// f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame
.
setDefaultCloseOperation
(
JFrame
.
DISPOSE_ON_CLOSE
);
if
(
filename
==
null
)
frame
.
setTitle
(
width
+
"-by-"
+
height
);
else
frame
.
setTitle
(
filename
);
frame
.
setResizable
(
false
);
frame
.
pack
();
frame
.
setVisible
(
true
);
}
// draw
frame
.
repaint
();
}
/**
* Returns the height of the picture.
*
*
@return
the height of the picture (in pixels)
*/
public
int
height
()
{
return
height
;
}
/**
* Returns the width of the picture.
*
*
@return
the width of the picture (in pixels)
*/
public
int
width
()
{
return
width
;
}
private
void
validateRowIndex
(
int
row
)
{
if
(
row
<
0
||
row
>=
height
())
throw
new
IllegalArgumentException
(
“row index must be between 0 and ”
+
(
height
()
–
1
)
+
“: ”
+
row
);
}
private
void
validateColumnIndex
(
int
col
)
{
if
(
col
<
0
||
col
>=
width
())
throw
new
IllegalArgumentException
(
“column index must be between 0 and ”
+
(
width
()
–
1
)
+
“: ”
+
col
);
}
/**
* Returns the color of pixel ({
@code
col}, {
@code
row}) as a {
@link
java.awt.Color}.
*
*
@param
col the column index
*
@param
row the row index
*
@return
the color of pixel ({
@code
col}, {
@code
row})
*
@throws
IllegalArgumentException unless both {
@code
0 <= col < width} and {
@code
0 <= row < height}
*/
public
Color
get
(
int
col
,
int
row
)
{
validateColumnIndex
(
col
);
validateRowIndex
(
row
);
int
rgb
=
getRGB
(
col
,
row
);
return
new
Color
(
rgb
);
}
/**
* Returns the color of pixel ({
@code
col}, {
@code
row}) as an {
@code
int}.
* Using this method can be more efficient than {
@link
#get(int, int)} because
* it does not create a {
@code
Color} object.
*
*
@param
col the column index
*
@param
row the row index
*
@return
the integer representation of the color of pixel ({
@code
col}, {
@code
row})
*
@throws
IllegalArgumentException unless both {
@code
0 <= col < width} and {
@code
0 <= row < height}
*/
public
int
getRGB
(
int
col
,
int
row
)
{
validateColumnIndex
(
col
);
validateRowIndex
(
row
);
if
(
isOriginUpperLeft
)
return
image
.
getRGB
(
col
,
row
);
else
return
image
.
getRGB
(
col
,
height
-
row
-
1
);
}
/**
* Sets the color of pixel ({
@code
col}, {
@code
row}) to given color.
*
*
@param
col the column index
*
@param
row the row index
*
@param
color the color
*
@throws
IllegalArgumentException unless both {
@code
0 <= col < width} and {
@code
0 <= row < height}
*
@throws
IllegalArgumentException if {
@code
color} is {
@code
null}
*/
public
void
set
(
int
col
,
int
row
,
Color
color
)
{
validateColumnIndex
(
col
);
validateRowIndex
(
row
);
if
(
color
==
null
)
throw
new
IllegalArgumentException
(
"color argument is null"
);
int
rgb
=
color
.
getRGB
();
setRGB
(
col
,
row
,
rgb
);
}
/**
* Sets the color of pixel ({
@code
col}, {
@code
row}) to given color.
*
*
@param
col the column index
*
@param
row the row index
*
@param
rgb the integer representation of the color
*
@throws
IllegalArgumentException unless both {
@code
0 <= col < width} and {
@code
0 <= row < height}
*/
public
void
setRGB
(
int
col
,
int
row
,
int
rgb
)
{
validateColumnIndex
(
col
);
validateRowIndex
(
row
);
if
(
isOriginUpperLeft
)
image
.
setRGB
(
col
,
row
,
rgb
);
else
image
.
setRGB
(
col
,
height
-
row
-
1
,
rgb
);
}
/**
* Returns true if this picture is equal to the argument picture.
*
*
@param
other the other picture
*
@return
{
@code
true} if this picture is the same dimension as {
@code
other}
* and if all pixels have the same color; {
@code
false} otherwise
*/
public
boolean
equals
(
Object
other
)
{
if
(
other
==
this
)
return
true
;
if
(
other
==
null
)
return
false
;
if
(
other
.
getClass
()
!=
this
.
getClass
())
return
false
;
Picture
that
=
(
Picture
)
other
;
if
(
this
.
width
()
!=
that
.
width
())
return
false
;
if
(
this
.
height
()
!=
that
.
height
())
return
false
;
for
(
int
col
=
0
;
col
<
width
();
col
++
)
for
(
int
row
=
0
;
row
<
height
();
row
++
)
if
(
this
.
getRGB
(
col
,
row
)
!=
that
.
getRGB
(
col
,
row
))
return
false
;
return
true
;
}
/**
* Returns a string representation of this picture.
* The result is a width
-by-height
matrix of pixels,
* where the color of a pixel is represented using 6 hex digits to encode
* the red, green, and blue components.
*
*
@return
a string representation of this picture
*/
public
String
toString
()
{
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
width
+
“-by-”
+
height
+
” picture (RGB values given in hex)\n”
);
for
(
int
row
=
0
;
row
<
height
;
row
++
)
{
for
(
int
col
=
0
;
col
<
width
;
col
++
)
{
int
rgb
=
0
;
if
(
isOriginUpperLeft
)
rgb
=
image
.
getRGB
(
col
,
row
);
else
rgb
=
image
.
getRGB
(
col
,
height
-
row
-
1
);
sb
.
append
(
String
.
format
(
"#%06X "
,
rgb
&
0xFFFFFF
));
}
sb
.
append
(
"\n"
);
}
return
sb
.
toString
().
trim
();
}
/**
* This operation is not supported because pictures are mutable.
*
*
@return
does not return a value
*
@throws
UnsupportedOperationException if called
*/
public
int
hashCode
()
{
throw
new
UnsupportedOperationException
(
"hashCode() is not supported because pictures are mutable"
);
}
/**
* Saves the picture to a file in either PNG or JPEG format.
* The filetype extension must be either or .
*
*
@param
name the name of the file
*
@throws
IllegalArgumentException if {
@code
name} is {
@code
null}
*/
public
void
save
(
String
name
)
{
if
(
name
==
null
)
throw
new
IllegalArgumentException
(
"argument to save() is null"
);
save
(
new
File
(
name
));
filename
=
name
;
}
/**
* Saves the picture to a file in a PNG or JPEG image format.
*
*
@param
file the file
*
@throws
IllegalArgumentException if {
@code
file} is {
@code
null}
*/
public
void
save
(
File
file
)
{
if
(
file
==
null
)
throw
new
IllegalArgumentException
(
"argument to save() is null"
);
filename
=
file
.
getName
();
if
(
frame
!=
null
)
frame
.
setTitle
(
filename
);
String
suffix
=
filename
.
substring
(
filename
.
lastIndexOf
(
'.'
)
+
1
);
if
(
"jpg"
.
equalsIgnoreCase
(
suffix
)
||
"png"
.
equalsIgnoreCase
(
suffix
))
{
try
{
ImageIO
.
write
(
image
,
suffix
,
file
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
else
{
System
.
out
.
println
(
"Error: filename must end in or "
);
}
}
/**
* Opens a save dialog box when the user selects "Save As" from the menu.
*/
@
Override
public
void
actionPerformed
(
ActionEvent
e
)
{
FileDialog
chooser
=
new
FileDialog
(
frame
,
"Use a or extension"
,
FileDialog
.
SAVE
);
chooser
.
setVisible
(
true
);
if
(
chooser
.
getFile
()
!=
null
)
{
save
(
chooser
.
getDirectory
()
+
File
.
separator
+
chooser
.
getFile
());
}
}
/**
* Unit tests this {
@code
Picture} data type.
* Reads a picture specified by the command-line argument,
* and shows it in a window on the screen.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
Picture
picture
=
new
Picture
(
args
[
0
]);
System
.
out
.
printf
(
"%d-by-%d\n"
,
picture
.
width
(),
picture
.
height
());
picture
.
show
();
}
}
PlayMusic.java
PlayMusic.java
import
java
.
io
.
InputStream
;
import
java
.
io
.
IOException
;
import
java
.
applet
.
*
;
import
java
.
net
.
*
;
import
java
.
io
.
*
;
import
javax
.
sound
.
sampled
.
AudioFormat
;
import
javax
.
sound
.
sampled
.
AudioInputStream
;
import
javax
.
sound
.
sampled
.
AudioSystem
;
import
javax
.
sound
.
sampled
.
DataLine
;
import
javax
.
sound
.
sampled
.
LineUnavailableException
;
import
javax
.
sound
.
sampled
.
SourceDataLine
;
import
javax
.
sound
.
sampled
.
UnsupportedAudioFileException
;
public
class
PlayMusic
{
// play sound file using Applet.newAudioClip();
private
static
void
playApplet
(
String
filename
)
{
URL url
=
null
;
try
{
File
file
=
new
File
(
filename
);
if
(
file
.
canRead
())
url
=
file
.
toURI
().
toURL
();
}
catch
(
MalformedURLException
e
)
{
e
.
printStackTrace
();
}
// URL url = StdAudio.class.getResource(filename);
if
(
url
==
null
)
throw
new
RuntimeException
(
"audio "
+
filename
+
" not found"
);
AudioClip
clip
=
Applet
.
newAudioClip
(
url
);
clip
.
play
();
}
public
static
synchronized
void
play
(
final
String
filename
)
{
// code adapted from: http://stackoverflow.com/questions/26305/how-can-i-play-sound-in-java
try
{
System
.
out
.
println
(
"trying AudioSystem.getClip()"
);
// check if file format is supported
// (if not, will throw an UnsupportedAudioFileException)
InputStream
is
=
PlayMusic
.
class
.
getResourceAsStream
(
filename
);
AudioInputStream
ais
=
AudioSystem
.
getAudioInputStream
(
is
);
new
Thread
(
new
Runnable
()
{
@
Override
public
void
run
()
{
stream
(
filename
);
}
}).
start
();
}
// let's try Applet.newAudioClip() instead
catch
(
UnsupportedAudioFileException
e
)
{
System
.
out
.
println
(
"trying Applet.newAudioClip()"
);
playApplet
(
filename
);
System
.
out
.
println
(
"done 2"
);
return
;
}
// something else went wrong
catch
(
Exception
e
)
{
System
.
out
.
println
(
e
);
System
.
out
.
println
(
"Could not play "
+
filename
);
}
}
// https://www3.ntu.edu.sg/home/ehchua/programming/java/J8c_PlayingSound.html
// play a wav or aif file
// javax.sound.sampled.Clip fails for long clips (on some systems)
private
static
void
stream
(
String
filename
)
{
SourceDataLine
line
=
null
;
// int BUFFER_SIZE = 65526; // 64K buffer
int
BUFFER_SIZE
=
4096
;
// 4K buffer
try
{
InputStream
is
=
PlayMusic
.
class
.
getResourceAsStream
(
filename
);
AudioInputStream
ais
=
AudioSystem
.
getAudioInputStream
(
is
);
AudioFormat
audioFormat
=
ais
.
getFormat
();
DataLine
.
Info
info
=
new
DataLine
.
Info
(
SourceDataLine
.
class
,
audioFormat
);
line
=
(
SourceDataLine
)
AudioSystem
.
getLine
(
info
);
line
.
open
(
audioFormat
);
line
.
start
();
byte
[]
samples
=
new
byte
[
BUFFER_SIZE
];
int
count
=
0
;
while
((
count
=
ais
.
read
(
samples
,
0
,
BUFFER_SIZE
))
!=
-
1
)
{
line
.
write
(
samples
,
0
,
count
);
}
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
catch
(
UnsupportedAudioFileException
e
)
{
e
.
printStackTrace
();
}
catch
(
LineUnavailableException
e
)
{
e
.
printStackTrace
();
}
finally
{
if
(
line
!=
null
)
{
line
.
drain
();
line
.
close
();
}
}
}
public
static
void
main
(
String
[]
args
)
{
String
filename
=
args
[
0
];
play
(
filename
);
System
.
out
.
println
(
"done"
);
}
}
StdArrayIO.java
StdArrayIO.java
/******************************************************************************
* Compilation: javac StdArrayIO.java
* Execution: java StdArrayIO < input.txt
* Dependencies: StdOut.java
* Data files: https://introcs.cs.princeton.edu/java/22library/tinyDouble1D.txt
* https://introcs.cs.princeton.edu/java/22library/tinyDouble2D.txt
* https://introcs.cs.princeton.edu/java/22library/tinyBoolean2D.txt
*
* A library for reading in 1D and 2D arrays of integers, doubles,
* and booleans from standard input and printing them out to
* standard output.
*
* % more tinyDouble1D.txt
* 4
* .000 .246 .222 -.032
*
* % more tinyDouble2D.txt
* 4 3
* .000 .270 .000
* .246 .224 -.036
* .222 .176 .0893
* -.032 .739 .270
*
* % more tinyBoolean2D.txt
* 4 3
* 1 1 0
* 0 0 0
* 0 1 1
* 1 1 1
*
* % cat tinyDouble1D.txt tinyDouble2D.txt tinyBoolean2D.txt | java StdArrayIO
* 4
* 0.00000 0.24600 0.22200 -0.03200
*
* 4 3
* 0.00000 0.27000 0.00000
* 0.24600 0.22400 -0.03600
* 0.22200 0.17600 0.08930
* 0.03200 0.73900 0.27000
*
* 4 3
* 1 1 0
* 0 0 0
* 0 1 1
* 1 1 1
*
******************************************************************************/
/**
* Standard array IO. This class provides methods for reading
* in 1D and 2D arrays from standard input and printing out to
* standard output.
*
* For additional documentation, see
* Section 2.2 of
* Computer Science: An Interdisciplinary Approach
* by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
StdArrayIO
{
// it doesn’t make sense to instantiate this class
private
StdArrayIO
()
{
}
/**
* Reads a 1D array of doubles from standard input and returns it.
*
*
@return
the 1D array of doubles
*/
public
static
double
[]
readDouble1D
()
{
int
n
=
StdIn
.
readInt
();
double
[]
a
=
new
double
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
a
[
i
]
=
StdIn
.
readDouble
();
}
return
a
;
}
/**
* Prints an array of doubles to standard output.
*
*
@param
a the 1D array of doubles
*/
public
static
void
print
(
double
[]
a
)
{
int
n
=
a
.
length
;
StdOut
.
println
(
n
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
StdOut
.
printf
(
"%9.5f "
,
a
[
i
]);
}
StdOut
.
println
();
}
/**
* Reads a 2D array of doubles from standard input and returns it.
*
*
@return
the 2D array of doubles
*/
public
static
double
[][]
readDouble2D
()
{
int
m
=
StdIn
.
readInt
();
int
n
=
StdIn
.
readInt
();
double
[][]
a
=
new
double
[
m
][
n
];
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
a
[
i
][
j
]
=
StdIn
.
readDouble
();
}
}
return
a
;
}
/**
* Prints the 2D array of doubles to standard output.
*
*
@param
a the 2D array of doubles
*/
public
static
void
print
(
double
[][]
a
)
{
int
m
=
a
.
length
;
int
n
=
a
[
0
].
length
;
StdOut
.
println
(
m
+
" "
+
n
);
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
StdOut
.
printf
(
"%9.5f "
,
a
[
i
][
j
]);
}
StdOut
.
println
();
}
}
/**
* Reads a 1D array of integers from standard input and returns it.
*
*
@return
the 1D array of integers
*/
public
static
int
[]
readInt1D
()
{
int
n
=
StdIn
.
readInt
();
int
[]
a
=
new
int
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
a
[
i
]
=
StdIn
.
readInt
();
}
return
a
;
}
/**
* Prints an array of integers to standard output.
*
*
@param
a the 1D array of integers
*/
public
static
void
print
(
int
[]
a
)
{
int
n
=
a
.
length
;
StdOut
.
println
(
n
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
StdOut
.
printf
(
"%9d "
,
a
[
i
]);
}
StdOut
.
println
();
}
/**
* Reads a 2D array of integers from standard input and returns it.
*
*
@return
the 2D array of integers
*/
public
static
int
[][]
readInt2D
()
{
int
m
=
StdIn
.
readInt
();
int
n
=
StdIn
.
readInt
();
int
[][]
a
=
new
int
[
m
][
n
];
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
a
[
i
][
j
]
=
StdIn
.
readInt
();
}
}
return
a
;
}
/**
* Print a 2D array of integers to standard output.
*
*
@param
a the 2D array of integers
*/
public
static
void
print
(
int
[][]
a
)
{
int
m
=
a
.
length
;
int
n
=
a
[
0
].
length
;
StdOut
.
println
(
m
+
" "
+
n
);
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
StdOut
.
printf
(
"%9d "
,
a
[
i
][
j
]);
}
StdOut
.
println
();
}
}
/**
* Reads a 1D array of booleans from standard input and returns it.
*
*
@return
the 1D array of booleans
*/
public
static
boolean
[]
readBoolean1D
()
{
int
n
=
StdIn
.
readInt
();
boolean
[]
a
=
new
boolean
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
a
[
i
]
=
StdIn
.
readBoolean
();
}
return
a
;
}
/**
* Prints a 1D array of booleans to standard output.
*
*
@param
a the 1D array of booleans
*/
public
static
void
print
(
boolean
[]
a
)
{
int
n
=
a
.
length
;
StdOut
.
println
(
n
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
if
(
a
[
i
])
StdOut
.
print
(
"1 "
);
else
StdOut
.
print
(
"0 "
);
}
StdOut
.
println
();
}
/**
* Reads a 2D array of booleans from standard input and returns it.
*
*
@return
the 2D array of booleans
*/
public
static
boolean
[][]
readBoolean2D
()
{
int
m
=
StdIn
.
readInt
();
int
n
=
StdIn
.
readInt
();
boolean
[][]
a
=
new
boolean
[
m
][
n
];
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
a
[
i
][
j
]
=
StdIn
.
readBoolean
();
}
}
return
a
;
}
/**
* Prints a 2D array of booleans to standard output.
*
*
@param
a the 2D array of booleans
*/
public
static
void
print
(
boolean
[][]
a
)
{
int
m
=
a
.
length
;
int
n
=
a
[
0
].
length
;
StdOut
.
println
(
m
+
" "
+
n
);
for
(
int
i
=
0
;
i
<
m
;
i
++
)
{
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
if
(
a
[
i
][
j
])
StdOut
.
print
(
"1 "
);
else
StdOut
.
print
(
"0 "
);
}
StdOut
.
println
();
}
}
/**
* Unit tests {
@code
StdArrayIO}.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// read and print an array of doubles
double
[]
a
=
StdArrayIO
.
readDouble1D
();
StdArrayIO
.
print
(
a
);
StdOut
.
println
();
// read and print a matrix of doubles
double
[][]
b
=
StdArrayIO
.
readDouble2D
();
StdArrayIO
.
print
(
b
);
StdOut
.
println
();
// read and print a matrix of doubles
boolean
[][]
d
=
StdArrayIO
.
readBoolean2D
();
StdArrayIO
.
print
(
d
);
StdOut
.
println
();
}
}
StdAudio.java
StdAudio.java
/******************************************************************************
* Compilation: javac StdAudio.java
* Execution: java StdAudio
* Dependencies: none
*
* Simple library for reading, writing, and manipulating .wav files.
*
*
* Limitations
* -----------
* - Assumes the audio is monaural, little endian, with sampling rate
* of 44,100
* - check when reading .wav files from a .jar file ?
*
******************************************************************************/
import
javax
.
sound
.
sampled
.
Clip
;
import
java
.
io
.
File
;
import
java
.
io
.
ByteArrayInputStream
;
import
java
.
io
.
InputStream
;
import
java
.
io
.
IOException
;
import
java
.
net
.
URL
;
import
javax
.
sound
.
sampled
.
AudioFileFormat
;
import
javax
.
sound
.
sampled
.
AudioFormat
;
import
javax
.
sound
.
sampled
.
AudioInputStream
;
import
javax
.
sound
.
sampled
.
AudioSystem
;
import
javax
.
sound
.
sampled
.
DataLine
;
import
javax
.
sound
.
sampled
.
LineUnavailableException
;
import
javax
.
sound
.
sampled
.
SourceDataLine
;
import
javax
.
sound
.
sampled
.
UnsupportedAudioFileException
;
import
javax
.
sound
.
sampled
.
LineListener
;
import
javax
.
sound
.
sampled
.
LineEvent
;
/**
* Standard audio. This class provides a basic capability for
* creating, reading, and saving audio.
*
* The audio format uses a sampling rate of 44,100 Hz, 16-bit, monaural.
*
*
* For additional documentation, see Section 1.5 of
* Computer Science: An Interdisciplinary Approach by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
StdAudio
{
/**
* The sample rate: 44,100 Hz for CD quality audio.
*/
public
static
final
int
SAMPLE_RATE
=
44100
;
private
static
final
int
BYTES_PER_SAMPLE
=
2
;
// 16-bit audio
private
static
final
int
BITS_PER_SAMPLE
=
16
;
// 16-bit audio
private
static
final
double
MAX_16_BIT
=
32768
;
private
static
final
int
SAMPLE_BUFFER_SIZE
=
4096
;
private
static
final
int
MONO
=
1
;
private
static
final
int
STEREO
=
2
;
private
static
final
boolean
LITTLE_ENDIAN
=
false
;
private
static
final
boolean
BIG_ENDIAN
=
true
;
private
static
final
boolean
SIGNED
=
true
;
private
static
final
boolean
UNSIGNED
=
false
;
private
static
SourceDataLine
line
;
// to play the sound
private
static
byte
[]
buffer
;
// our internal buffer
private
static
int
bufferSize
=
0
;
// number of samples currently in internal buffer
private
StdAudio
()
{
// can not instantiate
}
// static initializer
static
{
init
();
}
// open up an audio stream
private
static
void
init
()
{
try
{
// 44,100 Hz, 16-bit audio, mono, signed PCM, little endian
AudioFormat
format
=
new
AudioFormat
((
float
)
SAMPLE_RATE
,
BITS_PER_SAMPLE
,
MONO
,
SIGNED
,
LITTLE_ENDIAN
);
DataLine
.
Info
info
=
new
DataLine
.
Info
(
SourceDataLine
.
class
,
format
);
line
=
(
SourceDataLine
)
AudioSystem
.
getLine
(
info
);
line
.
open
(
format
,
SAMPLE_BUFFER_SIZE
*
BYTES_PER_SAMPLE
);
// the internal buffer is a fraction of the actual buffer size, this choice is arbitrary
// it gets divided because we can’t expect the buffered data to line up exactly with when
// the sound card decides to push out its samples.
buffer
=
new
byte
[
SAMPLE_BUFFER_SIZE
*
BYTES_PER_SAMPLE
/
3
];
}
catch
(
LineUnavailableException
e
)
{
System
.
out
.
println
(
e
.
getMessage
());
}
// no sound gets made before this call
line
.
start
();
}
// get an AudioInputStream object from a file
private
static
AudioInputStream
getAudioInputStreamFromFile
(
String
filename
)
{
if
(
filename
==
null
)
{
throw
new
IllegalArgumentException
(
“filename is null”
);
}
try
{
// first try to read file from local file system
File
file
=
new
File
(
filename
);
if
(
file
.
exists
())
{
return
AudioSystem
.
getAudioInputStream
(
file
);
}
// resource relative to .class file
InputStream
is1
=
StdAudio
.
class
.
getResourceAsStream
(
filename
);
if
(
is1
!=
null
)
{
return
AudioSystem
.
getAudioInputStream
(
is1
);
}
// resource relative to classloader root
InputStream
is2
=
StdAudio
.
class
.
getClassLoader
().
getResourceAsStream
(
filename
);
if
(
is2
!=
null
)
{
return
AudioSystem
.
getAudioInputStream
(
is2
);
}
// give up
else
{
throw
new
IllegalArgumentException
(
“could not read ‘”
+
filename
+
“‘”
);
}
}
catch
(
IOException
e
)
{
throw
new
IllegalArgumentException
(
“could not read ‘”
+
filename
+
“‘”
,
e
);
}
catch
(
UnsupportedAudioFileException
e
)
{
throw
new
IllegalArgumentException
(
“file of unsupported audio format: ‘”
+
filename
+
“‘”
,
e
);
}
}
/**
* Closes standard audio.
*/
public
static
void
close
()
{
line
.
drain
();
line
.
stop
();
}
/**
* Writes one sample (between -1.0 and +1.0) to standard audio.
* If the sample is outside the range, it will be clipped.
*
*
@param
sample the sample to play
*
@throws
IllegalArgumentException if the sample is {
@code
Double.NaN}
*/
public
static
void
play
(
double
sample
)
{
if
(
Double
.
isNaN
(
sample
))
throw
new
IllegalArgumentException
(
“sample is NaN”
);
// clip if outside [-1, +1]
if
(
sample
<
-
1.0
)
sample
=
-
1.0
;
if
(
sample
>
+
1.0
)
sample
=
+
1.0
;
// convert to bytes
short
s
=
(
short
)
(
MAX_16_BIT
*
sample
);
if
(
sample
==
1.0
)
s
=
Short
.
MAX_VALUE
;
// special case since 32768 not a short
buffer
[
bufferSize
++
]
=
(
byte
)
s
;
buffer
[
bufferSize
++
]
=
(
byte
)
(
s
>>
8
);
// little endian
// send to sound card if buffer is full
if
(
bufferSize
>=
buffer
.
length
)
{
line
.
write
(
buffer
,
0
,
buffer
.
length
);
bufferSize
=
0
;
}
}
/**
* Writes the array of samples (between -1.0 and +1.0) to standard audio.
* If a sample is outside the range, it will be clipped.
*
*
@param
samples the array of samples to play
*
@throws
IllegalArgumentException if any sample is {
@code
Double.NaN}
*
@throws
IllegalArgumentException if {
@code
samples} is {
@code
null}
*/
public
static
void
play
(
double
[]
samples
)
{
if
(
samples
==
null
)
throw
new
IllegalArgumentException
(
“argument to play() is null”
);
for
(
int
i
=
0
;
i
<
samples
.
length
;
i
++
)
{
play
(
samples
[
i
]);
}
}
/**
* Reads audio samples from a file (in .wav or .au format) and returns
* them as a double array with values between -1.0 and +1.0.
* The audio file must be 16-bit with a sampling rate of 44,100.
* It can be mono or stereo.
*
*
@param
filename the name of the audio file
*
@return
the array of samples
*/
public
static
double
[]
read
(
String
filename
)
{
// make sure that AudioFormat is 16-bit, 44,100 Hz, little endian
final
AudioInputStream
ais
=
getAudioInputStreamFromFile
(
filename
);
AudioFormat
audioFormat
=
ais
.
getFormat
();
// require sampling rate = 44,100 Hz
if
(
audioFormat
.
getSampleRate
()
!=
SAMPLE_RATE
)
{
throw
new
IllegalArgumentException
(
"StdAudio.read() currently supports only a sample rate of "
+
SAMPLE_RATE
+
" Hz\n"
+
"audio format: "
+
audioFormat
);
}
// require 16-bit audio
if
(
audioFormat
.
getSampleSizeInBits
()
!=
BITS_PER_SAMPLE
)
{
throw
new
IllegalArgumentException
(
"StdAudio.read() currently supports only "
+
BITS_PER_SAMPLE
+
"-bit audio\n"
+
"audio format: "
+
audioFormat
);
}
// require little endian
if
(
audioFormat
.
isBigEndian
())
{
throw
new
IllegalArgumentException
(
"StdAudio.read() currently supports only audio stored using little endian\n"
+
"audio format: "
+
audioFormat
);
}
byte
[]
bytes
=
null
;
try
{
int
bytesToRead
=
ais
.
available
();
bytes
=
new
byte
[
bytesToRead
];
int
bytesRead
=
ais
.
read
(
bytes
);
if
(
bytesToRead
!=
bytesRead
)
{
throw
new
IllegalStateException
(
"read only "
+
bytesRead
+
" of "
+
bytesToRead
+
" bytes"
);
}
}
catch
(
IOException
ioe
)
{
throw
new
IllegalArgumentException
(
"could not read '"
+
filename
+
"'"
,
ioe
);
}
int
n
=
bytes
.
length
;
// little endian, mono
if
(
audioFormat
.
getChannels
()
==
MONO
)
{
double
[]
data
=
new
double
[
n
/
2
];
for
(
int
i
=
0
;
i
<
n
/
2
;
i
++
)
{
// little endian, mono
data
[
i
]
=
((
short
)
(((
bytes
[
2
*
i
+
1
]
&
0xFF
)
<<
8
)
|
(
bytes
[
2
*
i
]
&
0xFF
)))
/
((
double
)
MAX_16_BIT
);
}
return
data
;
}
// little endian, stereo
else
if
(
audioFormat
.
getChannels
()
==
STEREO
)
{
double
[]
data
=
new
double
[
n
/
4
];
for
(
int
i
=
0
;
i
<
n
/
4
;
i
++
)
{
double
left
=
((
short
)
(((
bytes
[
4
*
i
+
1
]
&
0xFF
)
<<
8
)
|
(
bytes
[
4
*
i
+
0
]
&
0xFF
)))
/
((
double
)
MAX_16_BIT
);
double
right
=
((
short
)
(((
bytes
[
4
*
i
+
3
]
&
0xFF
)
<<
8
)
|
(
bytes
[
4
*
i
+
2
]
&
0xFF
)))
/
((
double
)
MAX_16_BIT
);
data
[
i
]
=
(
left
+
right
)
/
2.0
;
}
return
data
;
}
// TODO: handle big endian (or other formats)
else
throw
new
IllegalStateException
(
"audio format is neither mono or stereo"
);
}
/**
* Saves the double array as an audio file (using .wav or .au format).
*
*
@param
filename the name of the audio file
*
@param
samples the array of samples
*
@throws
IllegalArgumentException if unable to save {
@code
filename}
*
@throws
IllegalArgumentException if {
@code
samples} is {
@code
null}
*
@throws
IllegalArgumentException if {
@code
filename} is {
@code
null}
*
@throws
IllegalArgumentException if {
@code
filename} extension is not {
@code
.wav}
* or {
@code
.au}
*/
public
static
void
save
(
String
filename
,
double
[]
samples
)
{
if
(
filename
==
null
)
{
throw
new
IllegalArgumentException
(
"filenameis null"
);
}
if
(
samples
==
null
)
{
throw
new
IllegalArgumentException
(
"samples[] is null"
);
}
// assumes 16-bit samples with sample rate = 44,100 Hz
// use 16-bit audio, mono, signed PCM, little Endian
AudioFormat
format
=
new
AudioFormat
(
SAMPLE_RATE
,
16
,
MONO
,
SIGNED
,
LITTLE_ENDIAN
);
byte
[]
data
=
new
byte
[
2
*
samples
.
length
];
for
(
int
i
=
0
;
i
<
samples
.
length
;
i
++
)
{
int
temp
=
(
short
)
(
samples
[
i
]
*
MAX_16_BIT
);
if
(
samples
[
i
]
==
1.0
)
temp
=
Short
.
MAX_VALUE
;
// special case since 32768 not a short
data
[
2
*
i
+
0
]
=
(
byte
)
temp
;
data
[
2
*
i
+
1
]
=
(
byte
)
(
temp
>>
8
);
// little endian
}
// now save the file
try
{
ByteArrayInputStream
bais
=
new
ByteArrayInputStream
(
data
);
AudioInputStream
ais
=
new
AudioInputStream
(
bais
,
format
,
samples
.
length
);
if
(
filename
.
endsWith
(
“.wav”
)
||
filename
.
endsWith
(
“.WAV”
))
{
AudioSystem
.
write
(
ais
,
AudioFileFormat
.
Type
.
WAVE
,
new
File
(
filename
));
}
else
if
(
filename
.
endsWith
(
“.au”
)
||
filename
.
endsWith
(
“.AU”
))
{
AudioSystem
.
write
(
ais
,
AudioFileFormat
.
Type
.
AU
,
new
File
(
filename
));
}
else
{
throw
new
IllegalArgumentException
(
“file type for saving must be .wav or .au”
);
}
}
catch
(
IOException
ioe
)
{
throw
new
IllegalArgumentException
(
“unable to save file ‘”
+
filename
+
“‘”
,
ioe
);
}
}
/**
* Plays an audio file (in .wav, .mid, or .au format) in a background thread.
*
*
@param
filename the name of the audio file
*
@throws
IllegalArgumentException if unable to play {
@code
filename}
*
@throws
IllegalArgumentException if {
@code
filename} is {
@code
null}
*/
public
static
synchronized
void
play
(
final
String
filename
)
{
new
Thread
(
new
Runnable
()
{
public
void
run
()
{
AudioInputStream
ais
=
getAudioInputStreamFromFile
(
filename
);
stream
(
ais
);
}
}).
start
();
}
// https://www3.ntu.edu.sg/home/ehchua/programming/java/J8c_PlayingSound.html
// play a wav or aif file
// javax.sound.sampled.Clip fails for long clips (on some systems), perhaps because
// JVM closes (see remedy in loop)
private
static
void
stream
(
AudioInputStream
ais
)
{
SourceDataLine
line
=
null
;
int
BUFFER_SIZE
=
4096
;
// 4K buffer
try
{
AudioFormat
audioFormat
=
ais
.
getFormat
();
DataLine
.
Info
info
=
new
DataLine
.
Info
(
SourceDataLine
.
class
,
audioFormat
);
line
=
(
SourceDataLine
)
AudioSystem
.
getLine
(
info
);
line
.
open
(
audioFormat
);
line
.
start
();
byte
[]
samples
=
new
byte
[
BUFFER_SIZE
];
int
count
=
0
;
while
((
count
=
ais
.
read
(
samples
,
0
,
BUFFER_SIZE
))
!=
–
1
)
{
line
.
write
(
samples
,
0
,
count
);
}
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
catch
(
LineUnavailableException
e
)
{
e
.
printStackTrace
();
}
finally
{
if
(
line
!=
null
)
{
line
.
drain
();
line
.
close
();
}
}
}
/**
* Loops an audio file (in .wav, .mid, or .au format) in a background thread.
*
*
@param
filename the name of the audio file
*
@throws
IllegalArgumentException if {
@code
filename} is {
@code
null}
*/
public
static
synchronized
void
loop
(
String
filename
)
{
if
(
filename
==
null
)
throw
new
IllegalArgumentException
();
final
AudioInputStream
ais
=
getAudioInputStreamFromFile
(
filename
);
try
{
Clip
clip
=
AudioSystem
.
getClip
();
// Clip clip = (Clip) AudioSystem.getLine(new Line.Info(Clip.class));
clip
.
open
(
ais
);
clip
.
loop
(
Clip
.
LOOP_CONTINUOUSLY
);
}
catch
(
LineUnavailableException
e
)
{
e
.
printStackTrace
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
// keep JVM open
new
Thread
(
new
Runnable
()
{
public
void
run
()
{
while
(
true
)
{
try
{
Thread
.
sleep
(
1000
);
}
catch
(
InterruptedException
e
)
{
e
.
printStackTrace
();
}
}
}
}).
start
();
}
/***************************************************************************
* Unit tests {
@code
StdAudio}.
***************************************************************************/
// create a note (sine wave) of the given frequency (Hz), for the given
// duration (seconds) scaled to the given volume (amplitude)
private
static
double
[]
note
(
double
hz
,
double
duration
,
double
amplitude
)
{
int
n
=
(
int
)
(
StdAudio
.
SAMPLE_RATE
*
duration
);
double
[]
a
=
new
double
[
n
+
1
];
for
(
int
i
=
0
;
i
<=
n
;
i
++
)
a
[
i
]
=
amplitude
*
Math
.
sin
(
2
*
Math
.
PI
*
i
*
hz
/
StdAudio
.
SAMPLE_RATE
);
return
a
;
}
/**
* Test client - play an A major scale to standard audio.
*
*
@param
args the command-line arguments
*/
/**
* Test client - play an A major scale to standard audio.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// 440 Hz for 1 sec
double
freq
=
440.0
;
for
(
int
i
=
0
;
i
<=
StdAudio
.
SAMPLE_RATE
;
i
++
)
{
StdAudio
.
play
(
0.5
*
Math
.
sin
(
2
*
Math
.
PI
*
freq
*
i
/
StdAudio
.
SAMPLE_RATE
));
}
// scale increments
int
[]
steps
=
{
0
,
2
,
4
,
5
,
7
,
9
,
11
,
12
};
for
(
int
i
=
0
;
i
<
steps
.
length
;
i
++
)
{
double
hz
=
440.0
*
Math
.
pow
(
2
,
steps
[
i
]
/
12.0
);
StdAudio
.
play
(
note
(
hz
,
1.0
,
0.5
));
}
// need to call this in non-interactive stuff so the program doesn't terminate
// until all the sound leaves the speaker.
StdAudio
.
close
();
}
}
StdDraw.java
StdDraw.java
/******************************************************************************
* Compilation: javac StdDraw.java
* Execution: java StdDraw
* Dependencies: none
*
* Standard drawing library. This class provides a basic capability for
* creating drawings with your programs. It uses a simple graphics model that
* allows you to create drawings consisting of points, lines, and curves
* in a window on your computer and to save the drawings to a file.
*
* Todo
* ----
* - Add support for gradient fill, etc.
* - Fix setCanvasSize() so that it can only be called once.
* - On some systems, drawing a line (or other shape) that extends way
* beyond canvas (e.g., to infinity) dimensions does not get drawn.
*
* Remarks
* -------
* - don't use AffineTransform for rescaling since it inverts
* images and strings
*
******************************************************************************/
import
java
.
awt
.
BasicStroke
;
import
java
.
awt
.
Color
;
import
java
.
awt
.
Component
;
import
java
.
awt
.
FileDialog
;
import
java
.
awt
.
Font
;
import
java
.
awt
.
FontMetrics
;
import
java
.
awt
.
Graphics
;
import
java
.
awt
.
Graphics2D
;
import
java
.
awt
.
Image
;
import
java
.
awt
.
MediaTracker
;
import
java
.
awt
.
RenderingHints
;
import
java
.
awt
.
Toolkit
;
import
java
.
awt
.
event
.
ActionEvent
;
import
java
.
awt
.
event
.
ActionListener
;
import
java
.
awt
.
event
.
MouseEvent
;
import
java
.
awt
.
event
.
MouseListener
;
import
java
.
awt
.
event
.
MouseMotionListener
;
import
java
.
awt
.
event
.
KeyEvent
;
import
java
.
awt
.
event
.
KeyListener
;
import
java
.
awt
.
geom
.
Arc2D
;
import
java
.
awt
.
geom
.
Ellipse2D
;
import
java
.
awt
.
geom
.
GeneralPath
;
import
java
.
awt
.
geom
.
Line2D
;
import
java
.
awt
.
geom
.
Rectangle2D
;
import
java
.
awt
.
image
.
BufferedImage
;
import
java
.
awt
.
image
.
DirectColorModel
;
import
java
.
awt
.
image
.
WritableRaster
;
import
java
.
io
.
File
;
import
java
.
io
.
IOException
;
import
java
.
net
.
MalformedURLException
;
import
java
.
net
.
URL
;
import
java
.
util
.
LinkedList
;
import
java
.
util
.
TreeSet
;
import
java
.
util
.
NoSuchElementException
;
import
javax
.
imageio
.
ImageIO
;
import
javax
.
swing
.
ImageIcon
;
import
javax
.
swing
.
JFrame
;
import
javax
.
swing
.
JLabel
;
import
javax
.
swing
.
JMenu
;
import
javax
.
swing
.
JMenuBar
;
import
javax
.
swing
.
JMenuItem
;
import
javax
.
swing
.
KeyStroke
;
/**
* The {
@code
StdDraw} class provides a basic capability for
* creating drawings with your programs. It uses a simple graphics model that
* allows you to create drawings consisting of points, lines, squares,
* circles, and other geometric shapes in a window on your computer and
* to save the drawings to a file. Standard drawing also includes
* facilities for text, color, pictures, and animation, along with
* user interaction via the keyboard and mouse.
*
* Getting started.
* To use this class, you must have {
@code
StdDraw.class} in your
* Java classpath. If you used our autoinstaller, you should be all set.
* Otherwise, either download
* and add to your Java classpath or download
* and put a copy in your working directory.
*
* Now, type the following short program into your editor:
*
* public class TestStdDraw { * public static void main(String[] args) { * StdDraw.setPenRadius(0.05); * StdDraw.setPenColor(StdDraw.BLUE); * StdDraw.point(0.5, 0.5); * StdDraw.setPenColor(StdDraw.MAGENTA); * StdDraw.line(0.2, 0.2, 0.8, 0.2); * } * } *
* If you compile and execute the program, you should see a window
* appear with a thick magenta line and a blue point.
* This program illustrates the two main types of methods in standard
* drawing—methods that draw geometric shapes and methods that
* control drawing parameters.
* The methods {
@code
StdDraw.line()} and {
@code
StdDraw.point()}
* draw lines and points; the methods {
@code
StdDraw.setPenRadius()}
* and {
@code
StdDraw.setPenColor()} control the line thickness and color.
*
* Points and lines.
* You can draw points and line segments with the following methods:
*
*
*
*
*
* The x– and y-coordinates must be in the drawing area
* (between 0 and 1 and by default) or the points and lines will not be visible.
*
* Squares, circles, rectangles, and ellipses.
* You can draw squares, circles, rectangles, and ellipses using
* the following methods:
*
*
*
*
*
*
*
* All of these methods take as arguments the location and size of the shape.
* The location is always specified by the x– and y-coordinates
* of its center.
* The size of a circle is specified by its radius and the size of an ellipse is
* specified by the lengths of its semi-major and semi-minor axes.
* The size of a square or rectangle is specified by its half-width or half-height.
* The convention for drawing squares and rectangles is parallel to those for
* drawing circles and ellipses, but may be unexpected to the uninitiated.
*
* The methods above trace outlines of the given shapes. The following methods
* draw filled versions:
*
*
*
*
*
*
*
* Circular arcs.
* You can draw circular arcs with the following method:
*
*
*
*
* The arc is from the circle centered at (x, y) of the specified radius.
* The arc extends from angle1 to angle2. By convention, the angles are
* polar (counterclockwise angle from the x-axis)
* and represented in degrees. For example, {
@code
StdDraw.arc(0.0, 0.0, 1.0, 0, 90)}
* draws the arc of the unit circle from 3 o’clock (0 degrees) to 12 o’clock (90 degrees).
*
* Polygons.
* You can draw polygons with the following methods:
*
*
*
*
*
* The points in the polygon are ({
@code
x[i]}, {
@code
y[i]}).
* For example, the following code fragment draws a filled diamond
* with vertices (0.1, 0.2), (0.2, 0.3), (0.3, 0.2), and (0.2, 0.1):
*
* double[] x = { 0.1, 0.2, 0.3, 0.2 }; * double[] y = { 0.2, 0.3, 0.2, 0.1 }; * StdDraw.filledPolygon(x, y); *
*
* Pen size.
* The pen is circular, so that when you set the pen radius to r
* and draw a point, you get a circle of radius r. Also, lines are
* of thickness 2r and have rounded ends. The default pen radius
* is 0.005 and is not affected by coordinate scaling. This default pen
* radius is about 1/200 the width of the default canvas, so that if
* you draw 100 points equally spaced along a horizontal or vertical line,
* you will be able to see individual circles, but if you draw 200 such
* points, the result will look like a line.
*
*
*
*
* For example, {
@code
StdDraw.setPenRadius(0.025)} makes
* the thickness of the lines and the size of the points to be five times
* the 0.005 default.
* To draw points with the minimum possible radius (one pixel on typical
* displays), set the pen radius to 0.0.
*
* Pen color.
* All geometric shapes (such as points, lines, and circles) are drawn using
* the current pen color. By default, it is black.
* You can change the pen color with the following methods:
*
*
*
*
*
* The first method allows you to specify colors using the RGB color system.
* This color picker
* is a convenient way to find a desired color.
* The second method allows you to specify colors using the
* {
@link
Color} data type that is discussed in Chapter 3. Until then,
* you can use this method with one of these predefined colors in standard drawing:
* {
@link
#BLACK}, {
@link
#BLUE}, {
@link
#CYAN}, {
@link
#DARK_GRAY}, {
@link
#GRAY},
* {
@link
#GREEN}, {
@link
#LIGHT_GRAY}, {
@link
#MAGENTA}, {
@link
#ORANGE},
* {
@link
#PINK}, {
@link
#RED}, {
@link
#WHITE}, {
@link
#YELLOW},
* {
@link
#BOOK_BLUE}, {
@link
#BOOK_LIGHT_BLUE}, {
@link
#BOOK_RED}, and
* {
@link
#PRINCETON_ORANGE}.
* For example, {
@code
StdDraw.setPenColor(StdDraw.MAGENTA)} sets the
* pen color to magenta.
*
* Canvas size.
* By default, all drawing takes places in a 512-by-512 canvas.
* The canvas does not include the window title or window border.
* You can change the size of the canvas with the following method:
*
*
*
*
* This sets the canvas size to be width-by-height pixels.
* It also erases the current drawing and resets the coordinate system,
* pen radius, pen color, and font back to their default values.
* Ordinarly, this method is called once, at the very beginning of a program.
* For example, {
@code
StdDraw.setCanvasSize(800, 800)}
* sets the canvas size to be 800-by-800 pixels.
*
* Canvas scale and coordinate system.
* By default, all drawing takes places in the unit square, with (0, 0) at
* lower left and (1, 1) at upper right. You can change the default
* coordinate system with the following methods:
*
*
*
*
*
*
* The arguments are the coordinates of the minimum and maximum
* x– or y-coordinates that will appear in the canvas.
* For example, if you wish to use the default coordinate system but
* leave a small margin, you can call {
@code
StdDraw.setScale(-.05, 1.05)}.
*
* These methods change the coordinate system for subsequent drawing
* commands; they do not affect previous drawings.
* These methods do not change the canvas size; so, if the x–
* and y-scales are different, squares will become rectangles
* and circles will become ellipses.
*
* Text.
* You can use the following methods to annotate your drawings with text:
*
*
*
*
*
*
*
* The first two methods write the specified text in the current font,
* centered at (x, y).
* The second method allows you to rotate the text.
* The last two methods either left- or right-align the text at (x, y).
*
* The default font is a Sans Serif font with point size 16.
* You can use the following method to change the font:
*
*
*
*
* You use the {
@link
Font} data type to specify the font. This allows you to
* choose the face, size, and style of the font. For example, the following
* code fragment sets the font to Arial Bold, 60 point.
*
* Font font = new Font("Arial", Font.BOLD, 60); * StdDraw.setFont(font); * StdDraw.text(0.5, 0.5, "Hello, World"); *
*
* Images.
* You can use the following methods to add images to your drawings:
*
*
*
*
*
*
*
* These methods draw the specified image, centered at (x, y).
* The supported image formats are JPEG, PNG, and GIF.
* The image will display at its native size, independent of the coordinate system.
* Optionally, you can rotate the image a specified number of degrees counterclockwise
* or rescale it to fit snugly inside a width-by-height bounding box.
*
* Saving to a file.
* You save your image to a file using the File → Save menu option.
* You can also save a file programatically using the following method:
*
*
*
*
* The supported image formats are JPEG and PNG. The filename must have either the
* extension or .
* We recommend using PNG for drawing that consist solely of geometric shapes and JPEG
* for drawings that contains pictures.
*
* Clearing the canvas.
* To clear the entire drawing canvas, you can use the following methods:
*
*
*
*
*
* The first method clears the canvas to white; the second method
* allows you to specify a color of your choice. For example,
* {
@code
StdDraw.clear(StdDraw.LIGHT_GRAY)} clears the canvas to a shade
* of gray.
*
* Computer animations and double buffering.
* Double buffering is one of the most powerful features of standard drawing,
* enabling computer animations.
* The following methods control the way in which objects are drawn:
*
*
*
*
*
*
*
* By default, double buffering is disabled, which means that as soon as you
* call a drawing
* method—such as {
@code
point()} or {
@code
line()}—the
* results appear on the screen.
*
* When double buffering is enabled by calling {
@link
#enableDoubleBuffering()},
* all drawing takes place on the offscreen canvas. The offscreen canvas
* is not displayed. Only when you call
* {
@link
#show()} does your drawing get copied from the offscreen canvas to
* the onscreen canvas, where it is displayed in the standard drawing window. You
* can think of double buffering as collecting all of the lines, points, shapes,
* and text that you tell it to draw, and then drawing them all
* simultaneously, upon request.
*
* The most important use of double buffering is to produce computer
* animations, creating the illusion of motion by rapidly
* displaying static drawings. To produce an animation, repeat
* the following four steps:
*
*
*
*
*
*
*
* The {
@link
#clear()}, {
@link
#show()}, and {
@link
#pause(int t)} methods
* support the first, third, and fourth of these steps, respectively.
*
* For example, this code fragment animates two balls moving in a circle.
*
* StdDraw.setScale(-2, +2); * StdDraw.enableDoubleBuffering(); * * for (double t = 0.0; true; t += 0.02) { * double x = Math.sin(t); * double y = Math.cos(t); * StdDraw.clear(); * StdDraw.filledCircle(x, y, 0.05); * StdDraw.filledCircle(-x, -y, 0.05); * StdDraw.show(); * StdDraw.pause(20); * } *
*
* Keyboard and mouse inputs.
* Standard drawing has very basic support for keyboard and mouse input.
* It is much less powerful than most user interface libraries provide, but also much simpler.
* You can use the following methods to intercept mouse events:
*
*
*
*
*
*
* The first method tells you whether a mouse button is currently being pressed.
* The last two methods tells you the x– and y-coordinates of the mouse’s
* current position, using the same coordinate system as the canvas (the unit square, by default).
* You should use these methods in an animation loop that waits a short while before trying
* to poll the mouse for its current state.
* You can use the following methods to intercept keyboard events:
*
*
*
*
*
*
* If the user types lots of keys, they will be saved in a list until you process them.
* The first method tells you whether the user has typed a key (that your program has
* not yet processed).
* The second method returns the next key that the user typed (that your program has
* not yet processed) and removes it from the list of saved keystrokes.
* The third method tells you whether a key is currently being pressed.
*
* Accessing control parameters.
* You can use the following methods to access the current pen color, pen radius,
* and font:
*
*
*
*
*
*
* These methods are useful when you want to temporarily change a
* control parameter and reset it back to its original value.
*
* Corner cases.
* Here are some corner cases.
*
*
* However, only the part of the object that appears inside the canvas
* will be visible.
*
* {
@link
IllegalArgumentException}.
*
* {
@link
Double#POSITIVE_INFINITY}, or {
@link
Double#NEGATIVE_INFINITY}
* argument will throw an {
@link
IllegalArgumentException}.
*
* y-coordinate that is way outside the canvas (such as the line segment
* from (0.5, –10^308) to (0.5, 10^308) may not be visible even in the
* part of the canvas where it should be.
*
*
* Performance tricks.
* Standard drawing is capable of drawing large amounts of data.
* Here are a few tricks and tips:
*
*
* number of objects.
* That is, call {
@link
#enableDoubleBuffering()} before
* the sequence of drawing commands and call {
@link
#show()} afterwards.
* Incrementally displaying a complex drawing while it is being
* created can be intolerably inefficient on many computer systems.
*
* only once per frame, not after drawing each individual object.
*
* Java will cache the image, so you do not incur the cost of reading
* from a file each time.
*
*
* Known bugs and issues.
*
*
* inside the canvas if the center point (x, y) is outside the
* canvas.
* This bug appears only on some systems.
*
*
* Reference.
* For additional documentation,
* see Section 1.5 of
* Computer Science: An Interdisciplinary Approach
* by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
StdDraw
implements
ActionListener
,
MouseListener
,
MouseMotionListener
,
KeyListener
{
/**
* The color black.
*/
public
static
final
Color
BLACK
=
Color
.
BLACK
;
/**
* The color blue.
*/
public
static
final
Color
BLUE
=
Color
.
BLUE
;
/**
* The color cyan.
*/
public
static
final
Color
CYAN
=
Color
.
CYAN
;
/**
* The color dark gray.
*/
public
static
final
Color
DARK_GRAY
=
Color
.
DARK_GRAY
;
/**
* The color gray.
*/
public
static
final
Color
GRAY
=
Color
.
GRAY
;
/**
* The color green.
*/
public
static
final
Color
GREEN
=
Color
.
GREEN
;
/**
* The color light gray.
*/
public
static
final
Color
LIGHT_GRAY
=
Color
.
LIGHT_GRAY
;
/**
* The color magenta.
*/
public
static
final
Color
MAGENTA
=
Color
.
MAGENTA
;
/**
* The color orange.
*/
public
static
final
Color
ORANGE
=
Color
.
ORANGE
;
/**
* The color pink.
*/
public
static
final
Color
PINK
=
Color
.
PINK
;
/**
* The color red.
*/
public
static
final
Color
RED
=
Color
.
RED
;
/**
* The color white.
*/
public
static
final
Color
WHITE
=
Color
.
WHITE
;
/**
* The color yellow.
*/
public
static
final
Color
YELLOW
=
Color
.
YELLOW
;
/**
* Shade of blue used in Introduction to Programming in Java.
* It is Pantone 300U. The RGB values are approximately (9, 90, 166).
*/
public
static
final
Color
BOOK_BLUE
=
new
Color
(
9
,
90
,
166
);
/**
* Shade of light blue used in Introduction to Programming in Java.
* The RGB values are approximately (103, 198, 243).
*/
public
static
final
Color
BOOK_LIGHT_BLUE
=
new
Color
(
103
,
198
,
243
);
/**
* Shade of red used in Algorithms, 4th edition.
* It is Pantone 1805U. The RGB values are approximately (150, 35, 31).
*/
public
static
final
Color
BOOK_RED
=
new
Color
(
150
,
35
,
31
);
/**
* Shade of orange used in Princeton University’s identity.
* It is PMS 158. The RGB values are approximately (245, 128, 37).
*/
public
static
final
Color
PRINCETON_ORANGE
=
new
Color
(
245
,
128
,
37
);
// default colors
private
static
final
Color
DEFAULT_PEN_COLOR
=
BLACK
;
private
static
final
Color
DEFAULT_CLEAR_COLOR
=
WHITE
;
// current pen color
private
static
Color
penColor
;
// default canvas size is DEFAULT_SIZE-by-DEFAULT_SIZE
private
static
final
int
DEFAULT_SIZE
=
512
;
private
static
int
width
=
DEFAULT_SIZE
;
private
static
int
height
=
DEFAULT_SIZE
;
// default pen radius
private
static
final
double
DEFAULT_PEN_RADIUS
=
0.002
;
// current pen radius
private
static
double
penRadius
;
// show we draw immediately or wait until next show?
private
static
boolean
defer
=
false
;
// boundary of drawing canvas, 0% border
// private static final double BORDER = 0.05;
private
static
final
double
BORDER
=
0.00
;
private
static
final
double
DEFAULT_XMIN
=
0.0
;
private
static
final
double
DEFAULT_XMAX
=
1.0
;
private
static
final
double
DEFAULT_YMIN
=
0.0
;
private
static
final
double
DEFAULT_YMAX
=
1.0
;
private
static
double
xmin
,
ymin
,
xmax
,
ymax
;
// for synchronization
private
static
Object
mouseLock
=
new
Object
();
private
static
Object
keyLock
=
new
Object
();
// default font
private
static
final
Font
DEFAULT_FONT
=
new
Font
(
“SansSerif”
,
Font
.
PLAIN
,
16
);
// current font
private
static
Font
font
;
// double buffered graphics
private
static
BufferedImage
offscreenImage
,
onscreenImage
;
private
static
Graphics2D
offscreen
,
onscreen
;
// singleton for callbacks: avoids generation of extra .class files
private
static
StdDraw
std
=
new
StdDraw
();
// the frame for drawing to the screen
private
static
JFrame
frame
;
// mouse state
private
static
boolean
isMousePressed
=
false
;
private
static
double
mouseX
=
0
;
private
static
double
mouseY
=
0
;
// queue of typed key characters
private
static
LinkedList
<
Character
>
keysTyped
=
new
LinkedList
<
Character
>
();
// set of key codes currently pressed down
private
static
TreeSet
<
Integer
>
keysDown
=
new
TreeSet
<
Integer
>
();
// singleton pattern: client can’t instantiate
private
StdDraw
()
{
}
// static initializer
static
{
init
();
}
/**
* Sets the canvas (drawing area) to be 512-by-512 pixels.
* This also erases the current drawing and resets the coordinate system,
* pen radius, pen color, and font back to their default values.
* Ordinarly, this method is called once, at the very beginning
* of a program.
*/
public
static
void
setCanvasSize
()
{
setCanvasSize
(
DEFAULT_SIZE
,
DEFAULT_SIZE
);
}
/**
* Sets the canvas (drawing area) to be width-by-height pixels.
* This also erases the current drawing and resets the coordinate system,
* pen radius, pen color, and font back to their default values.
* Ordinarly, this method is called once, at the very beginning
* of a program.
*
*
@param
canvasWidth the width as a number of pixels
*
@param
canvasHeight the height as a number of pixels
*
@throws
IllegalArgumentException unless both {
@code
canvasWidth} and
* {
@code
canvasHeight} are positive
*/
public
static
void
setCanvasSize
(
int
canvasWidth
,
int
canvasHeight
)
{
if
(
canvasWidth
<=
0
)
throw
new
IllegalArgumentException
(
"width must be positive"
);
if
(
canvasHeight
<=
0
)
throw
new
IllegalArgumentException
(
"height must be positive"
);
width
=
canvasWidth
;
height
=
canvasHeight
;
init
();
}
// init
private
static
void
init
()
{
if
(
frame
!=
null
)
frame
.
setVisible
(
false
);
frame
=
new
JFrame
();
offscreenImage
=
new
BufferedImage
(
2
*
width
,
2
*
height
,
BufferedImage
.
TYPE_INT_ARGB
);
onscreenImage
=
new
BufferedImage
(
2
*
width
,
2
*
height
,
BufferedImage
.
TYPE_INT_ARGB
);
offscreen
=
offscreenImage
.
createGraphics
();
onscreen
=
onscreenImage
.
createGraphics
();
offscreen
.
scale
(
2.0
,
2.0
);
// since we made it 2x as big
setXscale
();
setYscale
();
offscreen
.
setColor
(
DEFAULT_CLEAR_COLOR
);
offscreen
.
fillRect
(
0
,
0
,
width
,
height
);
setPenColor
();
setPenRadius
();
setFont
();
clear
();
// add antialiasing
RenderingHints
hints
=
new
RenderingHints
(
RenderingHints
.
KEY_ANTIALIASING
,
RenderingHints
.
VALUE_ANTIALIAS_ON
);
hints
.
put
(
RenderingHints
.
KEY_RENDERING
,
RenderingHints
.
VALUE_RENDER_QUALITY
);
offscreen
.
addRenderingHints
(
hints
);
// frame stuff
RetinaImageIcon
icon
=
new
RetinaImageIcon
(
onscreenImage
);
JLabel
draw
=
new
JLabel
(
icon
);
draw
.
addMouseListener
(
std
);
draw
.
addMouseMotionListener
(
std
);
frame
.
setContentPane
(
draw
);
frame
.
addKeyListener
(
std
);
// JLabel cannot get keyboard focus
frame
.
setFocusTraversalKeysEnabled
(
false
);
// allow VK_TAB with isKeyPressed()
frame
.
setResizable
(
false
);
frame
.
setDefaultCloseOperation
(
JFrame
.
EXIT_ON_CLOSE
);
// closes all windows
// frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // closes only current window
frame
.
setTitle
(
"Standard Draw"
);
frame
.
setJMenuBar
(
createMenuBar
());
frame
.
pack
();
frame
.
requestFocusInWindow
();
frame
.
setVisible
(
true
);
}
// create the menu bar (changed to private)
private
static
JMenuBar
createMenuBar
()
{
JMenuBar
menuBar
=
new
JMenuBar
();
JMenu
menu
=
new
JMenu
(
"File"
);
menuBar
.
add
(
menu
);
JMenuItem
menuItem1
=
new
JMenuItem
(
" Save... "
);
menuItem1
.
addActionListener
(
std
);
// Java 10+: replace getMenuShortcutKeyMask() with getMenuShortcutKeyMaskEx()
menuItem1
.
setAccelerator
(
KeyStroke
.
getKeyStroke
(
KeyEvent
.
VK_S
,
Toolkit
.
getDefaultToolkit
().
getMenuShortcutKeyMask
()));
menu
.
add
(
menuItem1
);
return
menuBar
;
}
/***************************************************************************
* User and screen coordinate systems.
***************************************************************************/
// throw an IllegalArgumentException if x is NaN or infinite
private
static
void
validate
(
double
x
,
String
name
)
{
if
(
Double
.
isNaN
(
x
))
throw
new
IllegalArgumentException
(
name
+
" is NaN"
);
if
(
Double
.
isInfinite
(
x
))
throw
new
IllegalArgumentException
(
name
+
" is infinite"
);
}
// throw an IllegalArgumentException if s is null
private
static
void
validateNonnegative
(
double
x
,
String
name
)
{
if
(
x
<
0
)
throw
new
IllegalArgumentException
(
name
+
" negative"
);
}
// throw an IllegalArgumentException if s is null
private
static
void
validateNotNull
(
Object
x
,
String
name
)
{
if
(
x
==
null
)
throw
new
IllegalArgumentException
(
name
+
" is null"
);
}
/**
* Sets the x-scale to be the default (between 0.0 and 1.0).
*/
public
static
void
setXscale
()
{
setXscale
(
DEFAULT_XMIN
,
DEFAULT_XMAX
);
}
/**
* Sets the y-scale to be the default (between 0.0 and 1.0).
*/
public
static
void
setYscale
()
{
setYscale
(
DEFAULT_YMIN
,
DEFAULT_YMAX
);
}
/**
* Sets the x-scale and y-scale to be the default
* (between 0.0 and 1.0).
*/
public
static
void
setScale
()
{
setXscale
();
setYscale
();
}
/**
* Sets the x-scale to the specified range.
*
*
@param
min the minimum value of the x-scale
*
@param
max the maximum value of the x-scale
*
@throws
IllegalArgumentException if {
@code
(max == min)}
*
@throws
IllegalArgumentException if either {
@code
min} or {
@code
max} is either NaN or infinite
*/
public
static
void
setXscale
(
double
min
,
double
max
)
{
validate
(
min
,
“min”
);
validate
(
max
,
“max”
);
double
size
=
max
–
min
;
if
(
size
==
0.0
)
throw
new
IllegalArgumentException
(
“the min and max are the same”
);
synchronized
(
mouseLock
)
{
xmin
=
min
–
BORDER
*
size
;
xmax
=
max
+
BORDER
*
size
;
}
}
/**
* Sets the y-scale to the specified range.
*
*
@param
min the minimum value of the y-scale
*
@param
max the maximum value of the y-scale
*
@throws
IllegalArgumentException if {
@code
(max == min)}
*
@throws
IllegalArgumentException if either {
@code
min} or {
@code
max} is either NaN or infinite
*/
public
static
void
setYscale
(
double
min
,
double
max
)
{
validate
(
min
,
“min”
);
validate
(
max
,
“max”
);
double
size
=
max
–
min
;
if
(
size
==
0.0
)
throw
new
IllegalArgumentException
(
“the min and max are the same”
);
synchronized
(
mouseLock
)
{
ymin
=
min
–
BORDER
*
size
;
ymax
=
max
+
BORDER
*
size
;
}
}
/**
* Sets both the x-scale and y-scale to the (same) specified range.
*
*
@param
min the minimum value of the x– and y-scales
*
@param
max the maximum value of the x– and y-scales
*
@throws
IllegalArgumentException if {
@code
(max == min)}
*
@throws
IllegalArgumentException if either {
@code
min} or {
@code
max} is either NaN or infinite
*/
public
static
void
setScale
(
double
min
,
double
max
)
{
validate
(
min
,
“min”
);
validate
(
max
,
“max”
);
double
size
=
max
–
min
;
if
(
size
==
0.0
)
throw
new
IllegalArgumentException
(
“the min and max are the same”
);
synchronized
(
mouseLock
)
{
xmin
=
min
–
BORDER
*
size
;
xmax
=
max
+
BORDER
*
size
;
ymin
=
min
–
BORDER
*
size
;
ymax
=
max
+
BORDER
*
size
;
}
}
// helper functions that scale from user coordinates to screen coordinates and back
private
static
double
scaleX
(
double
x
)
{
return
width
*
(
x
–
xmin
)
/
(
xmax
–
xmin
);
}
private
static
double
scaleY
(
double
y
)
{
return
height
*
(
ymax
–
y
)
/
(
ymax
–
ymin
);
}
private
static
double
factorX
(
double
w
)
{
return
w
*
width
/
Math
.
abs
(
xmax
–
xmin
);
}
private
static
double
factorY
(
double
h
)
{
return
h
*
height
/
Math
.
abs
(
ymax
–
ymin
);
}
private
static
double
userX
(
double
x
)
{
return
xmin
+
x
*
(
xmax
–
xmin
)
/
width
;
}
private
static
double
userY
(
double
y
)
{
return
ymax
–
y
*
(
ymax
–
ymin
)
/
height
;
}
/**
* Clears the screen to the default color (white).
*/
public
static
void
clear
()
{
clear
(
DEFAULT_CLEAR_COLOR
);
}
/**
* Clears the screen to the specified color.
*
*
@param
color the color to make the background
*
@throws
IllegalArgumentException if {
@code
color} is {
@code
null}
*/
public
static
void
clear
(
Color
color
)
{
validateNotNull
(
color
,
“color”
);
offscreen
.
setColor
(
color
);
offscreen
.
fillRect
(
0
,
0
,
width
,
height
);
offscreen
.
setColor
(
penColor
);
draw
();
}
/**
* Returns the current pen radius.
*
*
@return
the current value of the pen radius
*/
public
static
double
getPenRadius
()
{
return
penRadius
;
}
/**
* Sets the pen size to the default size (0.002).
* The pen is circular, so that lines have rounded ends, and when you set the
* pen radius and draw a point, you get a circle of the specified radius.
* The pen radius is not affected by coordinate scaling.
*/
public
static
void
setPenRadius
()
{
setPenRadius
(
DEFAULT_PEN_RADIUS
);
}
/**
* Sets the radius of the pen to the specified size.
* The pen is circular, so that lines have rounded ends, and when you set the
* pen radius and draw a point, you get a circle of the specified radius.
* The pen radius is not affected by coordinate scaling.
*
*
@param
radius the radius of the pen
*
@throws
IllegalArgumentException if {
@code
radius} is negative, NaN, or infinite
*/
public
static
void
setPenRadius
(
double
radius
)
{
validate
(
radius
,
“pen radius”
);
validateNonnegative
(
radius
,
“pen radius”
);
penRadius
=
radius
;
float
scaledPenRadius
=
(
float
)
(
radius
*
DEFAULT_SIZE
);
BasicStroke
stroke
=
new
BasicStroke
(
scaledPenRadius
,
BasicStroke
.
CAP_ROUND
,
BasicStroke
.
JOIN_ROUND
);
// BasicStroke stroke = new BasicStroke(scaledPenRadius);
offscreen
.
setStroke
(
stroke
);
}
/**
* Returns the current pen color.
*
*
@return
the current pen color
*/
public
static
Color
getPenColor
()
{
return
penColor
;
}
/**
* Sets the pen color to the default color (black).
*/
public
static
void
setPenColor
()
{
setPenColor
(
DEFAULT_PEN_COLOR
);
}
/**
* Sets the pen color to the specified color.
*
* The predefined pen colors are
* {
@code
StdDraw.BLACK}, {
@code
StdDraw.BLUE}, {
@code
StdDraw.CYAN},
* {
@code
StdDraw.DARK_GRAY}, {
@code
StdDraw.GRAY}, {
@code
StdDraw.GREEN},
* {
@code
StdDraw.LIGHT_GRAY}, {
@code
StdDraw.MAGENTA}, {
@code
StdDraw.ORANGE},
* {
@code
StdDraw.PINK}, {
@code
StdDraw.RED}, {
@code
StdDraw.WHITE}, and
* {
@code
StdDraw.YELLOW}.
*
*
@param
color the color to make the pen
*
@throws
IllegalArgumentException if {
@code
color} is {
@code
null}
*/
public
static
void
setPenColor
(
Color
color
)
{
validateNotNull
(
color
,
“color”
);
penColor
=
color
;
offscreen
.
setColor
(
penColor
);
}
/**
* Sets the pen color to the specified RGB color.
*
*
@param
red the amount of red (between 0 and 255)
*
@param
green the amount of green (between 0 and 255)
*
@param
blue the amount of blue (between 0 and 255)
*
@throws
IllegalArgumentException if {
@code
red}, {
@code
green},
* or {
@code
blue} is outside its prescribed range
*/
public
static
void
setPenColor
(
int
red
,
int
green
,
int
blue
)
{
if
(
red
<
0
||
red
>=
256
)
throw
new
IllegalArgumentException
(
“red must be between 0 and 255”
);
if
(
green
<
0
||
green
>=
256
)
throw
new
IllegalArgumentException
(
“green must be between 0 and 255”
);
if
(
blue
<
0
||
blue
>=
256
)
throw
new
IllegalArgumentException
(
“blue must be between 0 and 255”
);
setPenColor
(
new
Color
(
red
,
green
,
blue
));
}
/**
* Returns the current font.
*
*
@return
the current font
*/
public
static
Font
getFont
()
{
return
font
;
}
/**
* Sets the font to the default font (sans serif, 16 point).
*/
public
static
void
setFont
()
{
setFont
(
DEFAULT_FONT
);
}
/**
* Sets the font to the specified value.
*
*
@param
font the font
*
@throws
IllegalArgumentException if {
@code
font} is {
@code
null}
*/
public
static
void
setFont
(
Font
font
)
{
validateNotNull
(
font
,
“font”
);
StdDraw
.
font
=
font
;
}
/***************************************************************************
* Drawing geometric shapes.
***************************************************************************/
/**
* Draws a line segment between (x0, y0) and
* (x1, y1).
*
*
@param
x0 the x-coordinate of one endpoint
*
@param
y0 the y-coordinate of one endpoint
*
@param
x1 the x-coordinate of the other endpoint
*
@param
y1 the y-coordinate of the other endpoint
*
@throws
IllegalArgumentException if any coordinate is either NaN or infinite
*/
public
static
void
line
(
double
x0
,
double
y0
,
double
x1
,
double
y1
)
{
validate
(
x0
,
“x0”
);
validate
(
y0
,
“y0”
);
validate
(
x1
,
“x1”
);
validate
(
y1
,
“y1”
);
offscreen
.
draw
(
new
Line2D
.
Double
(
scaleX
(
x0
),
scaleY
(
y0
),
scaleX
(
x1
),
scaleY
(
y1
)));
draw
();
}
/**
* Draws one pixel at (x, y).
* This method is private because pixels depend on the display.
* To achieve the same effect, set the pen radius to 0 and call {
@code
point()}.
*
*
@param
x the x-coordinate of the pixel
*
@param
y the y-coordinate of the pixel
*
@throws
IllegalArgumentException if {
@code
x} or {
@code
y} is either NaN or infinite
*/
private
static
void
pixel
(
double
x
,
double
y
)
{
validate
(
x
,
“x”
);
validate
(
y
,
“y”
);
offscreen
.
fillRect
((
int
)
Math
.
round
(
scaleX
(
x
)),
(
int
)
Math
.
round
(
scaleY
(
y
)),
1
,
1
);
}
/**
* Draws a point centered at (x, y).
* The point is a filled circle whose radius is equal to the pen radius.
* To draw a single-pixel point, first set the pen radius to 0.
*
*
@param
x the x-coordinate of the point
*
@param
y the y-coordinate of the point
*
@throws
IllegalArgumentException if either {
@code
x} or {
@code
y} is either NaN or infinite
*/
public
static
void
point
(
double
x
,
double
y
)
{
validate
(
x
,
“x”
);
validate
(
y
,
“y”
);
double
xs
=
scaleX
(
x
);
double
ys
=
scaleY
(
y
);
double
r
=
penRadius
;
float
scaledPenRadius
=
(
float
)
(
r
*
DEFAULT_SIZE
);
// double ws = factorX(2*r);
// double hs = factorY(2*r);
// if (ws <= 1 && hs <= 1) pixel(x, y);
if
(
scaledPenRadius
<=
1
)
pixel
(
x
,
y
);
else
offscreen
.
fill
(
new
Ellipse2D
.
Double
(
xs
-
scaledPenRadius
/
2
,
ys
-
scaledPenRadius
/
2
,
scaledPenRadius
,
scaledPenRadius
));
draw
();
}
/**
* Draws a circle of the specified radius, centered at (x, y).
*
*
@param
x the x-coordinate of the center of the circle
*
@param
y the y-coordinate of the center of the circle
*
@param
radius the radius of the circle
*
@throws
IllegalArgumentException if {
@code
radius} is negative
*
@throws
IllegalArgumentException if any argument is either NaN or infinite
*/
public
static
void
circle
(
double
x
,
double
y
,
double
radius
)
{
validate
(
x
,
“x”
);
validate
(
y
,
“y”
);
validate
(
radius
,
“radius”
);
validateNonnegative
(
radius
,
“radius”
);
double
xs
=
scaleX
(
x
);
double
ys
=
scaleY
(
y
);
double
ws
=
factorX
(
2
*
radius
);
double
hs
=
factorY
(
2
*
radius
);
if
(
ws
<=
1
&&
hs
<=
1
)
pixel
(
x
,
y
);
else
offscreen
.
draw
(
new
Ellipse2D
.
Double
(
xs
-
ws
/
2
,
ys
-
hs
/
2
,
ws
,
hs
));
draw
();
}
/**
* Draws a filled circle of the specified radius, centered at (x, y).
*
*
@param
x the x-coordinate of the center of the circle
*
@param
y the y-coordinate of the center of the circle
*
@param
radius the radius of the circle
*
@throws
IllegalArgumentException if {
@code
radius} is negative
*
@throws
IllegalArgumentException if any argument is either NaN or infinite
*/
public
static
void
filledCircle
(
double
x
,
double
y
,
double
radius
)
{
validate
(
x
,
“x”
);
validate
(
y
,
“y”
);
validate
(
radius
,
“radius”
);
validateNonnegative
(
radius
,
“radius”
);
double
xs
=
scaleX
(
x
);
double
ys
=
scaleY
(
y
);
double
ws
=
factorX
(
2
*
radius
);
double
hs
=
factorY
(
2
*
radius
);
if
(
ws
<=
1
&&
hs
<=
1
)
pixel
(
x
,
y
);
else
offscreen
.
fill
(
new
Ellipse2D
.
Double
(
xs
-
ws
/
2
,
ys
-
hs
/
2
,
ws
,
hs
));
draw
();
}
/**
* Draws an ellipse with the specified semimajor and semiminor axes,
* centered at (x, y).
*
*
@param
x the x-coordinate of the center of the ellipse
*
@param
y the y-coordinate of the center of the ellipse
*
@param
semiMajorAxis is the semimajor axis of the ellipse
*
@param
semiMinorAxis is the semiminor axis of the ellipse
*
@throws
IllegalArgumentException if either {
@code
semiMajorAxis}
* or {
@code
semiMinorAxis} is negative
*
@throws
IllegalArgumentException if any argument is either NaN or infinite
*/
public
static
void
ellipse
(
double
x
,
double
y
,
double
semiMajorAxis
,
double
semiMinorAxis
)
{
validate
(
x
,
“x”
);
validate
(
y
,
“y”
);
validate
(
semiMajorAxis
,
“semimajor axis”
);
validate
(
semiMinorAxis
,
“semiminor axis”
);
validateNonnegative
(
semiMajorAxis
,
“semimajor axis”
);
validateNonnegative
(
semiMinorAxis
,
“semiminor axis”
);
double
xs
=
scaleX
(
x
);
double
ys
=
scaleY
(
y
);
double
ws
=
factorX
(
2
*
semiMajorAxis
);
double
hs
=
factorY
(
2
*
semiMinorAxis
);
if
(
ws
<=
1
&&
hs
<=
1
)
pixel
(
x
,
y
);
else
offscreen
.
draw
(
new
Ellipse2D
.
Double
(
xs
-
ws
/
2
,
ys
-
hs
/
2
,
ws
,
hs
));
draw
();
}
/**
* Draws a filled ellipse with the specified semimajor and semiminor axes,
* centered at (x, y).
*
*
@param
x the x-coordinate of the center of the ellipse
*
@param
y the y-coordinate of the center of the ellipse
*
@param
semiMajorAxis is the semimajor axis of the ellipse
*
@param
semiMinorAxis is the semiminor axis of the ellipse
*
@throws
IllegalArgumentException if either {
@code
semiMajorAxis}
* or {
@code
semiMinorAxis} is negative
*
@throws
IllegalArgumentException if any argument is either NaN or infinite
*/
public
static
void
filledEllipse
(
double
x
,
double
y
,
double
semiMajorAxis
,
double
semiMinorAxis
)
{
validate
(
x
,
“x”
);
validate
(
y
,
“y”
);
validate
(
semiMajorAxis
,
“semimajor axis”
);
validate
(
semiMinorAxis
,
“semiminor axis”
);
validateNonnegative
(
semiMajorAxis
,
“semimajor axis”
);
validateNonnegative
(
semiMinorAxis
,
“semiminor axis”
);
double
xs
=
scaleX
(
x
);
double
ys
=
scaleY
(
y
);
double
ws
=
factorX
(
2
*
semiMajorAxis
);
double
hs
=
factorY
(
2
*
semiMinorAxis
);
if
(
ws
<=
1
&&
hs
<=
1
)
pixel
(
x
,
y
);
else
offscreen
.
fill
(
new
Ellipse2D
.
Double
(
xs
-
ws
/
2
,
ys
-
hs
/
2
,
ws
,
hs
));
draw
();
}
/**
* Draws a circular arc of the specified radius,
* centered at (x, y), from angle1 to angle2 (in degrees).
*
*
@param
x the x-coordinate of the center of the circle
*
@param
y the y-coordinate of the center of the circle
*
@param
radius the radius of the circle
*
@param
angle1 the starting angle. 0 would mean an arc beginning at 3 o’clock.
*
@param
angle2 the angle at the end of the arc. For example, if
* you want a 90 degree arc, then angle2 should be angle1 + 90.
*
@throws
IllegalArgumentException if {
@code
radius} is negative
*
@throws
IllegalArgumentException if any argument is either NaN or infinite
*/
public
static
void
arc
(
double
x
,
double
y
,
double
radius
,
double
angle1
,
double
angle2
)
{
validate
(
x
,
“x”
);
validate
(
y
,
“y”
);
validate
(
radius
,
“arc radius”
);
validate
(
angle1
,
“angle1”
);
validate
(
angle2
,
“angle2”
);
validateNonnegative
(
radius
,
“arc radius”
);
while (angle2 < angle1) angle2 += 360; double xs = scaleX(x); double ys = scaleY(y); double ws = factorX(2*radius); double hs = factorY(2*radius); if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.draw(new Arc2D.Double(xs - ws/2, ys - hs/2, ws, hs, angle1, angle2 - angle1, Arc2D.OPEN)); draw(); } /** * Draws a square of the specified size, centered at (x, y). * * @param x the x-coordinate of the center of the square * @param y the y-coordinate of the center of the square * @param halfLength one half the length of any side of the square * @throws IllegalArgumentException if {@code halfLength} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public static void square(double x, double y, double halfLength) {
validate(x, “x”);
validate(y, “y”);
validate(halfLength, “halfLength”);
validateNonnegative(halfLength, “half length”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*halfLength);
double hs = factorY(2*halfLength);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.draw(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws a filled square of the specified size, centered at (x, y). * * @param x the x-coordinate of the center of the square * @param y the y-coordinate of the center of the square * @param halfLength one half the length of any side of the square * @throws IllegalArgumentException if {@code halfLength} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public static void filledSquare(double x, double y, double halfLength) {
validate(x, “x”);
validate(y, “y”);
validate(halfLength, “halfLength”);
validateNonnegative(halfLength, “half length”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*halfLength);
double hs = factorY(2*halfLength);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.fill(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws a rectangle of the specified size, centered at (x, y). * * @param x the x-coordinate of the center of the rectangle * @param y the y-coordinate of the center of the rectangle * @param halfWidth one half the width of the rectangle * @param halfHeight one half the height of the rectangle * @throws IllegalArgumentException if either {@code halfWidth} or {@code halfHeight} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public static void rectangle(double x, double y, double halfWidth, double halfHeight) {
validate(x, “x”);
validate(y, “y”);
validate(halfWidth, “halfWidth”);
validate(halfHeight, “halfHeight”);
validateNonnegative(halfWidth, “half width”);
validateNonnegative(halfHeight, “half height”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*halfWidth);
double hs = factorY(2*halfHeight);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.draw(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws a filled rectangle of the specified size, centered at (x, y). * * @param x the x-coordinate of the center of the rectangle * @param y the y-coordinate of the center of the rectangle * @param halfWidth one half the width of the rectangle * @param halfHeight one half the height of the rectangle * @throws IllegalArgumentException if either {@code halfWidth} or {@code halfHeight} is negative * @throws IllegalArgumentException if any argument is either NaN or infinite */
public static void filledRectangle(double x, double y, double halfWidth, double halfHeight) {
validate(x, “x”);
validate(y, “y”);
validate(halfWidth, “halfWidth”);
validate(halfHeight, “halfHeight”);
validateNonnegative(halfWidth, “half width”);
validateNonnegative(halfHeight, “half height”);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(2*halfWidth);
double hs = factorY(2*halfHeight);
if (ws <= 1 && hs <= 1) pixel(x, y); else offscreen.fill(new Rectangle2D.Double(xs - ws/2, ys - hs/2, ws, hs)); draw(); } /** * Draws a polygon with the vertices * (x0, y0), * (x1, y1), …, * (xn–1, yn–1). * * @param x an array of all the x-coordinates of the polygon * @param y an array of all the y-coordinates of the polygon * @throws IllegalArgumentException unless {@code x[]} and {@code y[]} * are of the same length * @throws IllegalArgumentException if any coordinate is either NaN or infinite * @throws IllegalArgumentException if either {@code x[]} or {@code y[]} is {@code null} */
public static void polygon(double[] x, double[] y) {
validateNotNull(x, “x-coordinate array”);
validateNotNull(y, “y-coordinate array”);
for (int i = 0; i < x.length; i++) validate(x[i], "x[" + i + "]"); for (int i = 0; i < y.length; i++) validate(y[i], "y[" + i + "]"); int n1 = x.length; int n2 = y.length; if (n1 != n2) throw new IllegalArgumentException("arrays must be of the same length"); int n = n1; if (n == 0) return; GeneralPath path = new GeneralPath(); path.moveTo((float) scaleX(x[0]), (float) scaleY(y[0])); for (int i = 0; i < n; i++) path.lineTo((float) scaleX(x[i]), (float) scaleY(y[i])); path.closePath(); offscreen.draw(path); draw(); } /** * Draws a filled polygon with the vertices * (x0, y0), * (x1, y1), …, * (xn–1, yn–1). * * @param x an array of all the x-coordinates of the polygon * @param y an array of all the y-coordinates of the polygon * @throws IllegalArgumentException unless {@code x[]} and {@code y[]} * are of the same length * @throws IllegalArgumentException if any coordinate is either NaN or infinite * @throws IllegalArgumentException if either {@code x[]} or {@code y[]} is {@code null} */
public static void filledPolygon(double[] x, double[] y) {
validateNotNull(x, “x-coordinate array”);
validateNotNull(y, “y-coordinate array”);
for (int i = 0; i < x.length; i++) validate(x[i], "x[" + i + "]"); for (int i = 0; i < y.length; i++) validate(y[i], "y[" + i + "]"); int n1 = x.length; int n2 = y.length; if (n1 != n2) throw new IllegalArgumentException("arrays must be of the same length"); int n = n1; if (n == 0) return; GeneralPath path = new GeneralPath(); path.moveTo((float) scaleX(x[0]), (float) scaleY(y[0])); for (int i = 0; i < n; i++) path.lineTo((float) scaleX(x[i]), (float) scaleY(y[i])); path.closePath(); offscreen.fill(path); draw(); } /*************************************************************************** * Drawing images. ***************************************************************************/ // get an image from the given filename private static Image getImage(String filename) { if (filename == null) throw new IllegalArgumentException(); // to read from file ImageIcon icon = new ImageIcon(filename); // try to read from URL if ((icon == null) || (icon.getImageLoadStatus() != MediaTracker.COMPLETE)) { try { URL url = new URL(filename); icon = new ImageIcon(url); } catch (MalformedURLException e) { /* not a url */ } } // in case file is inside a .jar (classpath relative to StdDraw) if ((icon == null) || (icon.getImageLoadStatus() != MediaTracker.COMPLETE)) { URL url = StdDraw.class.getResource(filename); if (url != null) icon = new ImageIcon(url); } // in case file is inside a .jar (classpath relative to root of jar) if ((icon == null) || (icon.getImageLoadStatus() != MediaTracker.COMPLETE)) { URL url = StdDraw.class.getResource("/" + filename); if (url == null) throw new IllegalArgumentException("image " + filename + " not found"); icon = new ImageIcon(url); } return icon.getImage(); } /*************************************************************************** * [Summer 2016] Should we update to use ImageIO instead of ImageIcon()? * Seems to have some issues loading images on some systems * and slows things down on other systems. * especially if you don't call ImageIO.setUseCache(false) * One advantage is that it returns a BufferedImage. ***************************************************************************/ /* private static BufferedImage getImage(String filename) { if (filename == null) throw new IllegalArgumentException(); // from a file or URL try { URL url = new URL(filename); BufferedImage image = ImageIO.read(url); return image; } catch (IOException e) { // ignore } // in case file is inside a .jar (classpath relative to StdDraw) try { URL url = StdDraw.class.getResource(filename); BufferedImage image = ImageIO.read(url); return image; } catch (IOException e) { // ignore } // in case file is inside a .jar (classpath relative to root of jar) try { URL url = StdDraw.class.getResource("/" + filename); BufferedImage image = ImageIO.read(url); return image; } catch (IOException e) { // ignore } throw new IllegalArgumentException("image " + filename + " not found"); }*/ /** * Draws the specified image centered at (x, y). * The supported image formats are JPEG, PNG, and GIF. * As an optimization, the picture is cached, so there is no performance * penalty for redrawing the same image multiple times (e.g., in an animation). * However, if you change the picture file after drawing it, subsequent * calls will draw the original picture. * * @param x the center x-coordinate of the image * @param y the center y-coordinate of the image * @param filename the name of the image/picture, e.g., “ball.gif” * @throws IllegalArgumentException if the image filename is invalid * @throws IllegalArgumentException if either {@code x} or {@code y} is either NaN or infinite */
public static void picture(double x, double y, String filename) {
validate(x, “x”);
validate(y, “y”);
validateNotNull(filename, “filename”);
// BufferedImage image = getImage(filename); Image image = getImage(filename);
double xs = scaleX(x);
double ys = scaleY(y);
// int ws = image.getWidth(); // can call only if image is a BufferedImage // int hs = image.getHeight(); int ws = image.getWidth(null);
int hs = image.getHeight(null);
if (ws < 0 || hs < 0) throw new IllegalArgumentException("image " + filename + " is corrupt"); offscreen.drawImage(image, (int) Math.round(xs - ws/2.0), (int) Math.round(ys - hs/2.0), null); draw(); } /** * Draws the specified image centered at (x, y), * rotated given number of degrees. * The supported image formats are JPEG, PNG, and GIF. * * @param x the center x-coordinate of the image * @param y the center y-coordinate of the image * @param filename the name of the image/picture, e.g., “ball.gif” * @param degrees is the number of degrees to rotate counterclockwise * @throws IllegalArgumentException if the image filename is invalid * @throws IllegalArgumentException if {@code x}, {@code y}, {@code degrees} is NaN or infinite * @throws IllegalArgumentException if {@code filename} is {@code null} */
public static void picture(double x, double y, String filename, double degrees) {
validate(x, “x”);
validate(y, “y”);
validate(degrees, “degrees”);
validateNotNull(filename, “filename”);
// BufferedImage image = getImage(filename); Image image = getImage(filename);
double xs = scaleX(x);
double ys = scaleY(y);
// int ws = image.getWidth(); // can call only if image is a BufferedImage // int hs = image.getHeight(); int ws = image.getWidth(null);
int hs = image.getHeight(null);
if (ws < 0 || hs < 0) throw new IllegalArgumentException("image " + filename + " is corrupt"); offscreen.rotate(Math.toRadians(-degrees), xs, ys); offscreen.drawImage(image, (int) Math.round(xs - ws/2.0), (int) Math.round(ys - hs/2.0), null); offscreen.rotate(Math.toRadians(+degrees), xs, ys); draw(); } /** * Draws the specified image centered at (x, y), * rescaled to the specified bounding box. * The supported image formats are JPEG, PNG, and GIF. * * @param x the center x-coordinate of the image * @param y the center y-coordinate of the image * @param filename the name of the image/picture, e.g., “ball.gif” * @param scaledWidth the width of the scaled image (in screen coordinates) * @param scaledHeight the height of the scaled image (in screen coordinates) * @throws IllegalArgumentException if either {@code scaledWidth} * or {@code scaledHeight} is negative * @throws IllegalArgumentException if the image filename is invalid * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite * @throws IllegalArgumentException if {@code filename} is {@code null} */
public static void picture(double x, double y, String filename, double scaledWidth, double scaledHeight) {
validate(x, “x”);
validate(y, “y”);
validate(scaledWidth, “scaled width”);
validate(scaledHeight, “scaled height”);
validateNotNull(filename, “filename”);
validateNonnegative(scaledWidth, “scaled width”);
validateNonnegative(scaledHeight, “scaled height”);
Image image = getImage(filename);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(scaledWidth);
double hs = factorY(scaledHeight);
if (ws < 0 || hs < 0) throw new IllegalArgumentException("image " + filename + " is corrupt"); if (ws <= 1 && hs <= 1) pixel(x, y); else { offscreen.drawImage(image, (int) Math.round(xs - ws/2.0), (int) Math.round(ys - hs/2.0), (int) Math.round(ws), (int) Math.round(hs), null); } draw(); } /** * Draws the specified image centered at (x, y), rotated * given number of degrees, and rescaled to the specified bounding box. * The supported image formats are JPEG, PNG, and GIF. * * @param x the center x-coordinate of the image * @param y the center y-coordinate of the image * @param filename the name of the image/picture, e.g., “ball.gif” * @param scaledWidth the width of the scaled image (in screen coordinates) * @param scaledHeight the height of the scaled image (in screen coordinates) * @param degrees is the number of degrees to rotate counterclockwise * @throws IllegalArgumentException if either {@code scaledWidth} * or {@code scaledHeight} is negative * @throws IllegalArgumentException if the image filename is invalid */
public static void picture(double x, double y, String filename, double scaledWidth, double scaledHeight, double degrees) {
validate(x, “x”);
validate(y, “y”);
validate(scaledWidth, “scaled width”);
validate(scaledHeight, “scaled height”);
validate(degrees, “degrees”);
validateNotNull(filename, “filename”);
validateNonnegative(scaledWidth, “scaled width”);
validateNonnegative(scaledHeight, “scaled height”);
Image image = getImage(filename);
double xs = scaleX(x);
double ys = scaleY(y);
double ws = factorX(scaledWidth);
double hs = factorY(scaledHeight);
if (ws < 0 || hs < 0) throw new IllegalArgumentException("image " + filename + " is corrupt"); if (ws <= 1 && hs <= 1) pixel(x, y); offscreen.rotate(Math.toRadians(-degrees), xs, ys); offscreen.drawImage(image, (int) Math.round(xs - ws/2.0), (int) Math.round(ys - hs/2.0), (int) Math.round(ws), (int) Math.round(hs), null); offscreen.rotate(Math.toRadians(+degrees), xs, ys); draw(); } /*************************************************************************** * Drawing text. ***************************************************************************/ /** * Writes the given text string in the current font, centered at (x, y). * * @param x the center x-coordinate of the text * @param y the center y-coordinate of the text * @param text the text to write * @throws IllegalArgumentException if {@code text} is {@code null} * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite */
public static void text(double x, double y, String text) {
validate(x, “x”);
validate(y, “y”);
validateNotNull(text, “text”);
offscreen.setFont(font);
FontMetrics metrics = offscreen.getFontMetrics();
double xs = scaleX(x);
double ys = scaleY(y);
int ws = metrics.stringWidth(text);
int hs = metrics.getDescent();
offscreen.drawString(text, (float) (xs – ws/2.0), (float) (ys + hs));
draw();
}
/** * Writes the given text string in the current font, centered at (x, y) and * rotated by the specified number of degrees. * @param x the center x-coordinate of the text * @param y the center y-coordinate of the text * @param text the text to write * @param degrees is the number of degrees to rotate counterclockwise * @throws IllegalArgumentException if {@code text} is {@code null} * @throws IllegalArgumentException if {@code x}, {@code y}, or {@code degrees} is either NaN or infinite */
public static void text(double x, double y, String text, double degrees) {
validate(x, “x”);
validate(y, “y”);
validate(degrees, “degrees”);
validateNotNull(text, “text”);
double xs = scaleX(x);
double ys = scaleY(y);
offscreen.rotate(Math.toRadians(-degrees), xs, ys);
text(x, y, text);
offscreen.rotate(Math.toRadians(+degrees), xs, ys);
}
/** * Writes the given text string in the current font, left-aligned at (x, y). * @param x the x-coordinate of the text * @param y the y-coordinate of the text * @param text the text * @throws IllegalArgumentException if {@code text} is {@code null} * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite */
public static void textLeft(double x, double y, String text) {
validate(x, “x”);
validate(y, “y”);
validateNotNull(text, “text”);
offscreen.setFont(font);
FontMetrics metrics = offscreen.getFontMetrics();
double xs = scaleX(x);
double ys = scaleY(y);
int hs = metrics.getDescent();
offscreen.drawString(text, (float) xs, (float) (ys + hs));
draw();
}
/** * Writes the given text string in the current font, right-aligned at (x, y). * * @param x the x-coordinate of the text * @param y the y-coordinate of the text * @param text the text to write * @throws IllegalArgumentException if {@code text} is {@code null} * @throws IllegalArgumentException if {@code x} or {@code y} is either NaN or infinite */
public static void textRight(double x, double y, String text) {
validate(x, “x”);
validate(y, “y”);
validateNotNull(text, “text”);
offscreen.setFont(font);
FontMetrics metrics = offscreen.getFontMetrics();
double xs = scaleX(x);
double ys = scaleY(y);
int ws = metrics.stringWidth(text);
int hs = metrics.getDescent();
offscreen.drawString(text, (float) (xs – ws), (float) (ys + hs));
draw();
}
/** * Copies the offscreen buffer to the onscreen buffer, pauses for t milliseconds * and enables double buffering. * @param t number of milliseconds * @deprecated replaced by {@link #enableDoubleBuffering()}, {@link #show()}, and {@link #pause(int t)} */
@Deprecated
public static void show(int t) {
validateNonnegative(t, “t”);
show();
pause(t);
enableDoubleBuffering();
}
/** * Pauses for t milliseconds. This method is intended to support computer animations. * @param t number of milliseconds */
public static void pause(int t) {
validateNonnegative(t, “t”);
try {
Thread.sleep(t);
}
catch (InterruptedException e) {
System.out.println(“Error sleeping”);
}
}
/** * Copies offscreen buffer to onscreen buffer. There is no reason to call * this method unless double buffering is enabled. */
public static void show() {
onscreen.drawImage(offscreenImage, 0, 0, null);
frame.repaint();
}
// draw onscreen if defer is false private static void draw() {
if (!defer) show();
}
/** * Enables double buffering. All subsequent calls to * drawing methods such as {@code line()}, {@code circle()}, * and {@code square()} will be deferred until the next call * to show(). Useful for animations. */
public static void enableDoubleBuffering() {
defer = true;
}
/** * Disables double buffering. All subsequent calls to * drawing methods such as {@code line()}, {@code circle()}, * and {@code square()} will be displayed on screen when called. * This is the default. */
public static void disableDoubleBuffering() {
defer = false;
}
/*************************************************************************** * Save drawing to a file. ***************************************************************************/
/** * Saves the drawing to using the specified filename. * The supported image formats are JPEG and PNG; * the filename suffix must be {@code } or {@code }. * * @param filename the name of the file with one of the required suffixes * @throws IllegalArgumentException if {@code filename} is {@code null} */
public static void save(String filename) {
validateNotNull(filename, “filename”);
File file = new File(filename);
String suffix = filename.substring(filename.lastIndexOf(‘.’) + 1);
// png files if (“png”.equalsIgnoreCase(suffix)) {
try {
ImageIO.write(onscreenImage, suffix, file);
}
catch (IOException e) {
e.printStackTrace();
}
}
// need to change from ARGB to RGB for JPEG // reference: http://archives.java.sun.com/cgi-bin/wa?A2=ind0404&L=java2d-interest&D=0&P=2727 else if (“jpg”.equalsIgnoreCase(suffix)) {
WritableRaster raster = onscreenImage.getRaster();
WritableRaster newRaster;
newRaster = raster.createWritableChild(0, 0, width, height, 0, 0, new int[] {0, 1, 2});
DirectColorModel cm = (DirectColorModel) onscreenImage.getColorModel();
DirectColorModel newCM = new DirectColorModel(cm.getPixelSize(),
cm.getRedMask(),
cm.getGreenMask(),
cm.getBlueMask());
BufferedImage rgbBuffer = new BufferedImage(newCM, newRaster, false, null);
try {
ImageIO.write(rgbBuffer, suffix, file);
}
catch (IOException e) {
e.printStackTrace();
}
}
else {
System.out.println(“Invalid image file type: ” + suffix);
}
}
/** * This method cannot be called directly. */
@Override
public void actionPerformed(ActionEvent e) {
FileDialog chooser = new FileDialog(StdDraw.frame, “Use a or extension”, FileDialog.SAVE);
chooser.setVisible(true);
String filename = chooser.getFile();
if (filename != null) {
StdDraw.save(chooser.getDirectory() + File.separator + chooser.getFile());
}
}
/*************************************************************************** * Mouse interactions. ***************************************************************************/
/** * Returns true if the mouse is being pressed. * * @return {@code true} if the mouse is being pressed; {@code false} otherwise */
public static boolean isMousePressed() {
synchronized (mouseLock) {
return isMousePressed;
}
}
/** * Returns true if the mouse is being pressed. * * @return {@code true} if the mouse is being pressed; {@code false} otherwise * @deprecated replaced by {@link #isMousePressed()} */
@Deprecated
public static boolean mousePressed() {
synchronized (mouseLock) {
return isMousePressed;
}
}
/** * Returns the x-coordinate of the mouse. * * @return the x-coordinate of the mouse */
public static double mouseX() {
synchronized (mouseLock) {
return mouseX;
}
}
/** * Returns the y-coordinate of the mouse. * * @return y-coordinate of the mouse */
public static double mouseY() {
synchronized (mouseLock) {
return mouseY;
}
}
/** * This method cannot be called directly. */
@Override
public void mouseClicked(MouseEvent e) {
// this body is intentionally left empty }
/** * This method cannot be called directly. */
@Override
public void mouseEntered(MouseEvent e) {
// this body is intentionally left empty }
/** * This method cannot be called directly. */
@Override
public void mouseExited(MouseEvent e) {
// this body is intentionally left empty }
/** * This method cannot be called directly. */
@Override
public void mousePressed(MouseEvent e) {
synchronized (mouseLock) {
mouseX = StdDraw.userX(e.getX());
mouseY = StdDraw.userY(e.getY());
isMousePressed = true;
}
}
/** * This method cannot be called directly. */
@Override
public void mouseReleased(MouseEvent e) {
synchronized (mouseLock) {
isMousePressed = false;
}
}
/** * This method cannot be called directly. */
@Override
public void mouseDragged(MouseEvent e) {
synchronized (mouseLock) {
mouseX = StdDraw.userX(e.getX());
mouseY = StdDraw.userY(e.getY());
}
}
/** * This method cannot be called directly. */
@Override
public void mouseMoved(MouseEvent e) {
synchronized (mouseLock) {
mouseX = StdDraw.userX(e.getX());
mouseY = StdDraw.userY(e.getY());
}
}
/*************************************************************************** * Keyboard interactions. ***************************************************************************/
/** * Returns true if the user has typed a key (that has not yet been processed). * * @return {@code true} if the user has typed a key (that has not yet been processed * by {@link #nextKeyTyped()}; {@code false} otherwise */
public static boolean hasNextKeyTyped() {
synchronized (keyLock) {
return !keysTyped.isEmpty();
}
}
/** * Returns the next key that was typed by the user (that your program has not already processed). * This method should be preceded by a call to {@link #hasNextKeyTyped()} to ensure * that there is a next key to process. * This method returns a Unicode character corresponding to the key * typed (such as {@code ‘a’} or {@code ‘A’}). * It cannot identify action keys (such as F1 and arrow keys) * or modifier keys (such as control). * * @return the next key typed by the user (that your program has not already processed). * @throws NoSuchElementException if there is no remaining key */
public static char nextKeyTyped() {
synchronized (keyLock) {
if (keysTyped.isEmpty()) {
throw new NoSuchElementException(“your program has already processed all keystrokes”);
}
return keysTyped.remove(keysTyped.size() – 1);
// return keysTyped.removeLast(); }
}
/** * Returns true if the given key is being pressed. *
* This method takes the keycode (corresponding to a physical key) * as an argument. It can handle action keys * (such as F1 and arrow keys) and modifier keys (such as shift and control). * See {@link KeyEvent} for a description of key codes. * * @param keycode the key to check if it is being pressed * @return {@code true} if {@code keycode} is currently being pressed; * {@code false} otherwise */
public static boolean isKeyPressed(int keycode) {
synchronized (keyLock) {
return keysDown.contains(keycode);
}
}
/** * This method cannot be called directly. */
@Override
public void keyTyped(KeyEvent e) {
synchronized (keyLock) {
keysTyped.addFirst(e.getKeyChar());
}
}
/** * This method cannot be called directly. */
@Override
public void keyPressed(KeyEvent e) {
synchronized (keyLock) {
keysDown.add(e.getKeyCode());
}
}
/** * This method cannot be called directly. */
@Override
public void keyReleased(KeyEvent e) {
synchronized (keyLock) {
keysDown.remove(e.getKeyCode());
}
}
/*************************************************************************** * For improved resolution on Mac Retina displays. ***************************************************************************/
private static class RetinaImageIcon extends ImageIcon {
public RetinaImageIcon(Image image) {
super(image);
}
public int getIconWidth() {
return super.getIconWidth() / 2;
}
/** * Gets the height of the icon. * * @return the height in pixels of this icon */
public int getIconHeight() {
return super.getIconHeight() / 2;
}
public synchronized void paintIcon(Component c, Graphics g, int x, int y) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2.scale(0.5, 0.5);
super.paintIcon(c, g2, x * 2, y * 2);
g2.dispose();
}
}
/** * Test client. * * @param args the command-line arguments */
public static void main(String[] args) {
StdDraw.square(0.2, 0.8, 0.1);
StdDraw.filledSquare(0.8, 0.8, 0.2);
StdDraw.circle(0.8, 0.2, 0.2);
StdDraw.setPenColor(StdDraw.BOOK_RED);
StdDraw.setPenRadius(0.02);
StdDraw.arc(0.8, 0.2, 0.1, 200, 45);
// draw a blue diamond StdDraw.setPenRadius();
StdDraw.setPenColor(StdDraw.BOOK_BLUE);
double[] x = { 0.1, 0.2, 0.3, 0.2 };
double[] y = { 0.2, 0.3, 0.2, 0.1 };
StdDraw.filledPolygon(x, y);
// text StdDraw.setPenColor(StdDraw.BLACK);
StdDraw.text(0.2, 0.5, “black text”);
StdDraw.setPenColor(StdDraw.WHITE);
StdDraw.text(0.8, 0.8, “white text”);
}
}
StdIn.java
StdIn.java
/******************************************************************************
* Compilation: javac StdIn.java
* Execution: java StdIn (interactive test of basic functionality)
* Dependencies: none
*
* Reads in data of various types from standard input.
*
******************************************************************************/
import
java
.
util
.
ArrayList
;
import
java
.
util
.
InputMismatchException
;
import
java
.
util
.
Locale
;
import
java
.
util
.
NoSuchElementException
;
import
java
.
util
.
Scanner
;
import
java
.
util
.
regex
.
Pattern
;
/**
* The {
@code
StdIn} class provides static methods for reading strings
* and numbers from standard input.
* These functions fall into one of four categories:
*
*
* and converting each to a number, string, or boolean
*
*
*
* and returning the values in an array
*
*
* Generally, it is best not to mix functions from the different
* categories in the same program.
*
* Getting started.
* To use this class, you must have {
@code
StdIn.class} in your
* Java classpath. If you used our autoinstaller, you should be all set.
* Otherwise, either download
* and add to your Java classpath or download
* and put a copy in your working directory.
*
* Reading tokens from standard input and converting to numbers and strings.
* You can use the following methods to read numbers, strings, and booleans
* from standard input one at a time:
*
*
*
*
*
*
*
*
*
*
*
*
* The first method returns true if standard input has no more tokens.
* Each other method skips over any input that is whitespace. Then, it reads
* the next token and attempts to convert it into a value of the specified
* type. If it succeeds, it returns that value; otherwise, it
* throws an {
@link
InputMismatchException}.
*
* Whitespace includes spaces, tabs, and newlines; the full definition
* is inherited from {
@link
Character#isWhitespace(char)}.
* A token is a maximal sequence of non-whitespace characters.
* The precise rules for describing which tokens can be converted to
* integers and floating-point numbers are inherited from
* Scanner,
* using the locale {
@link
Locale#US}; the rules
* for floating-point numbers are slightly different
* from those in {
@link
Double#valueOf(String)},
* but unlikely to be of concern to most programmers.
*
* As an example, the following code fragment reads integers from standard input,
* one at a time, and prints them one per line.
*
* while (!StdIn.isEmpty()) { * double value = StdIn.readDouble(); * StdOut.println(value); * } *
*
* Reading characters from standard input.
* You can use the following two methods to read characters from standard input one at a time:
*
*
*
*
*
* The first method returns true if standard input has more input (including whitespace).
* The second method reads and returns the next character of input on standard
* input (possibly a whitespace character).
*
* As an example, the following code fragment reads characters from standard input,
* one character at a time, and prints it to standard output.
*
* while (StdIn.hasNextChar()) { * char c = StdIn.readChar(); * StdOut.print(c); * } *
*
* Reading lines from standard input.
* You can use the following two methods to read lines from standard input:
*
*
*
*
*
* The first method returns true if standard input has more input (including whitespace).
* The second method reads and returns the remaining portion of
* the next line of input on standard input (possibly whitespace),
* discarding the trailing line separator.
*
* A line separator is defined to be one of the following strings:
* {
@code
\n} (Linux), {
@code
\r} (old Macintosh),
* {
@code
\r\n} (Windows),
* {
@code
\}{
@code
u2028}, {
@code
\}{
@code
u2029}, or {
@code
\}{
@code
u0085}.
*
* As an example, the following code fragment reads text from standard input,
* one line at a time, and prints it to standard output.
*
* while (StdIn.hasNextLine()) { * String line = StdIn.readLine(); * StdOut.println(line); * } *
*
* Reading a sequence of values of the same type from standard input.
* You can use the following methods to read a sequence numbers, strings,
* or booleans (all of the same type) from standard input:
*
*
*
*
*
*
*
*
*
* The first three methods read of all of remaining token on standard input
* and converts the tokens to values of
* the specified type, as in the corresponding
* {
@code
readDouble}, {
@code
readInt}, and {
@code
readString()} methods.
* The {
@code
readAllLines()} method reads all remaining lines on standard
* input and returns them as an array of strings.
* The {
@code
readAll()} method reads all remaining input on standard
* input and returns it as a string.
*
* As an example, the following code fragment reads all of the remaining
* tokens from standard input and returns them as an array of strings.
*
* String[] words = StdIn.readAllStrings(); *
*
* Differences with Scanner.
* {
@code
StdIn} and {
@link
Scanner} are both designed to parse
* tokens and convert them to primitive types and strings.
* The main differences are summarized below:
*
*
* reads input from only standard input. It is suitable for use before
* a programmer knows about objects.
* See {
@link
In} for an object-oriented version that handles
* input from files, URLs,
* and sockets.
*
* that separates tokens.
* {
@link
Scanner} supports arbitrary delimiter patterns.
*
* which is the most widely used character encoding for Unicode.
*
* for consistency with {
@link
StdOut}, {
@link
Double#parseDouble(String)},
* and floating-point literals.
*
* character; reading in sequences of integers, doubles, or strings;
* and reading in all of the remaining input.
*
*
* Historical note: {
@code
StdIn} preceded {
@code
Scanner}; when
* {
@code
Scanner} was introduced, this class was re-implemented to use {
@code
Scanner}.
*
* Using standard input.
* Standard input is a fundamental operating system abstraction on Mac OS X,
* Windows, and Linux.
* The methods in {
@code
StdIn} are blocking, which means that they
* will wait until you enter input on standard input.
* If your program has a loop that repeats until standard input is empty,
* you must signal that the input is finished.
* To do so, depending on your operating system and IDE,
* use either {
@code
@code
* If you are redirecting standard input from a file, you will not need
* to do anything to signal that the input is finished.
*
* Known bugs.
* Java’s UTF-8 encoding does not recognize the optional
* If the input begins with the optional byte-order mask, {
@code
StdIn}
* will have an extra character {
@code
\}{
@code
uFEFF} at the beginning.
*
* Reference.
* For additional documentation,
* see Section 1.5 of
* Computer Science: An Interdisciplinary Approach
* by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*
@author
David Pritchard
*/
public
final
class
StdIn
{
/*** begin: section (1 of 2) of code duplicated from In to StdIn. */
// assume Unicode UTF-8 encoding
private
static
final
String
CHARSET_NAME
=
“UTF-8”
;
// assume language = English, country = US for consistency with System.out.
private
static
final
Locale
LOCALE
=
Locale
.
US
;
// the default token separator; we maintain the invariant that this value
// is held by the scanner’s delimiter between calls
private
static
final
Pattern
WHITESPACE_PATTERN
=
Pattern
.
compile
(
“\\p{javaWhitespace}+”
);
// makes whitespace significant
private
static
final
Pattern
EMPTY_PATTERN
=
Pattern
.
compile
(
“”
);
// used to read the entire input
private
static
final
Pattern
EVERYTHING_PATTERN
=
Pattern
.
compile
(
“\\A”
);
/*** end: section (1 of 2) of code duplicated from In to StdIn. */
private
static
Scanner
scanner
;
// it doesn’t make sense to instantiate this class
private
StdIn
()
{
}
//// begin: section (2 of 2) of code duplicated from In to StdIn,
//// with all methods changed from “public” to “public static”
/**
* Returns true if standard input is empty (except possibly for whitespace).
* Use this method to know whether the next call to {
@link
#readString()},
* {
@link
#readDouble()}, etc will succeed.
*
*
@return
{
@code
true} if standard input is empty (except possibly
* for whitespace); {
@code
false} otherwise
*/
public
static
boolean
isEmpty
()
{
return
!
scanner
.
hasNext
();
}
/**
* Returns true if standard input has a next line.
* Use this method to know whether the
* next call to {
@link
#readLine()} will succeed.
* This method is functionally equivalent to {
@link
#hasNextChar()}.
*
*
@return
{
@code
true} if standard input has more input (including whitespace);
* {
@code
false} otherwise
*/
public
static
boolean
hasNextLine
()
{
return
scanner
.
hasNextLine
();
}
/**
* Returns true if standard input has more input (including whitespace).
* Use this method to know whether the next call to {
@link
#readChar()} will succeed.
* This method is functionally equivalent to {
@link
#hasNextLine()}.
*
*
@return
{
@code
true} if standard input has more input (including whitespace);
* {
@code
false} otherwise
*/
public
static
boolean
hasNextChar
()
{
scanner
.
useDelimiter
(
EMPTY_PATTERN
);
boolean
result
=
scanner
.
hasNext
();
scanner
.
useDelimiter
(
WHITESPACE_PATTERN
);
return
result
;
}
/**
* Reads and returns the next line, excluding the line separator if present.
*
*
@return
the next line, excluding the line separator if present;
* {
@code
null} if no such line
*/
public
static
String
readLine
()
{
String
line
;
try
{
line
=
scanner
.
nextLine
();
}
catch
(
NoSuchElementException
e
)
{
line
=
null
;
}
return
line
;
}
/**
* Reads and returns the next character.
*
*
@return
the next {
@code
char}
*
@throws
NoSuchElementException if standard input is empty
*/
public
static
char
readChar
()
{
try
{
scanner
.
useDelimiter
(
EMPTY_PATTERN
);
String
ch
=
scanner
.
next
();
assert
ch
.
length
()
==
1
:
“Internal (Std)In.readChar() error!”
+
” Please contact the authors.”
;
scanner
.
useDelimiter
(
WHITESPACE_PATTERN
);
return
ch
.
charAt
(
0
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attempts to read a ‘char’ value from standard input, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads and returns the remainder of the input, as a string.
*
*
@return
the remainder of the input, as a string
*
@throws
NoSuchElementException if standard input is empty
*/
public
static
String
readAll
()
{
if
(
!
scanner
.
hasNextLine
())
return
“”
;
String
result
=
scanner
.
useDelimiter
(
EVERYTHING_PATTERN
).
next
();
// not that important to reset delimeter, since now scanner is empty
scanner
.
useDelimiter
(
WHITESPACE_PATTERN
);
// but let’s do it anyway
return
result
;
}
/**
* Reads the next token and returns the {
@code
String}.
*
*
@return
the next {
@code
String}
*
@throws
NoSuchElementException if standard input is empty
*/
public
static
String
readString
()
{
try
{
return
scanner
.
next
();
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attempts to read a ‘String’ value from standard input, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from standard input, parses it as an integer, and returns the integer.
*
*
@return
the next integer on standard input
*
@throws
NoSuchElementException if standard input is empty
*
@throws
InputMismatchException if the next token cannot be parsed as an {
@code
int}
*/
public
static
int
readInt
()
{
try
{
return
scanner
.
nextInt
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read an ‘int’ value from standard input, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attemps to read an ‘int’ value from standard input, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from standard input, parses it as a double, and returns the double.
*
*
@return
the next double on standard input
*
@throws
NoSuchElementException if standard input is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
double}
*/
public
static
double
readDouble
()
{
try
{
return
scanner
.
nextDouble
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read a ‘double’ value from standard input, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attempts to read a ‘double’ value from standard input, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from standard input, parses it as a float, and returns the float.
*
*
@return
the next float on standard input
*
@throws
NoSuchElementException if standard input is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
float}
*/
public
static
float
readFloat
()
{
try
{
return
scanner
.
nextFloat
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read a ‘float’ value from standard input, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attempts to read a ‘float’ value from standard input, ”
+
“but there no more tokens are available”
);
}
}
/**
* Reads the next token from standard input, parses it as a long integer, and returns the long integer.
*
*
@return
the next long integer on standard input
*
@throws
NoSuchElementException if standard input is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
long}
*/
public
static
long
readLong
()
{
try
{
return
scanner
.
nextLong
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read a ‘long’ value from standard input, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attempts to read a ‘long’ value from standard input, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from standard input, parses it as a short integer, and returns the short integer.
*
*
@return
the next short integer on standard input
*
@throws
NoSuchElementException if standard input is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
short}
*/
public
static
short
readShort
()
{
try
{
return
scanner
.
nextShort
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read a ‘short’ value from standard input, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attempts to read a ‘short’ value from standard input, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from standard input, parses it as a byte, and returns the byte.
*
*
@return
the next byte on standard input
*
@throws
NoSuchElementException if standard input is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
byte}
*/
public
static
byte
readByte
()
{
try
{
return
scanner
.
nextByte
();
}
catch
(
InputMismatchException
e
)
{
String
token
=
scanner
.
next
();
throw
new
InputMismatchException
(
“attempts to read a ‘byte’ value from standard input, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attempts to read a ‘byte’ value from standard input, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads the next token from standard input, parses it as a boolean,
* and returns the boolean.
*
*
@return
the next boolean on standard input
*
@throws
NoSuchElementException if standard input is empty
*
@throws
InputMismatchException if the next token cannot be parsed as a {
@code
boolean}:
* {
@code
true} or {
@code
1} for true, and {
@code
false} or {
@code
0} for false,
* ignoring case
*/
public
static
boolean
readBoolean
()
{
try
{
String
token
=
readString
();
if
(
“true”
.
equalsIgnoreCase
(
token
))
return
true
;
if
(
“false”
.
equalsIgnoreCase
(
token
))
return
false
;
if
(
“1”
.
equals
(
token
))
return
true
;
if
(
“0”
.
equals
(
token
))
return
false
;
throw
new
InputMismatchException
(
“attempts to read a ‘boolean’ value from standard input, ”
+
“but the next token is \””
+
token
+
“\””
);
}
catch
(
NoSuchElementException
e
)
{
throw
new
NoSuchElementException
(
“attempts to read a ‘boolean’ value from standard input, ”
+
“but no more tokens are available”
);
}
}
/**
* Reads all remaining tokens from standard input and returns them as an array of strings.
*
*
@return
all remaining tokens on standard input, as an array of strings
*/
public
static
String
[]
readAllStrings
()
{
// we could use readAll.trim().split(), but that’s not consistent
// because trim() uses characters 0x00..0x20 as whitespace
String
[]
tokens
=
WHITESPACE_PATTERN
.
split
(
readAll
());
if
(
tokens
.
length
==
0
||
tokens
[
0
].
length
()
>
0
)
return
tokens
;
// don’t include first token if it is leading whitespace
String
[]
decapitokens
=
new
String
[
tokens
.
length
–
1
];
for
(
int
i
=
0
;
i
<
tokens
.
length
-
1
;
i
++
)
decapitokens
[
i
]
=
tokens
[
i
+
1
];
return
decapitokens
;
}
/**
* Reads all remaining lines from standard input and returns them as an array of strings.
*
@return
all remaining lines on standard input, as an array of strings
*/
public
static
String
[]
readAllLines
()
{
ArrayList
<
String
>
lines
=
new
ArrayList
<
String
>
();
while
(
hasNextLine
())
{
lines
.
add
(
readLine
());
}
return
lines
.
toArray
(
new
String
[
lines
.
size
()]);
}
/**
* Reads all remaining tokens from standard input, parses them as integers, and returns
* them as an array of integers.
*
@return
all remaining integers on standard input, as an array
*
@throws
InputMismatchException if any token cannot be parsed as an {
@code
int}
*/
public
static
int
[]
readAllInts
()
{
String
[]
fields
=
readAllStrings
();
int
[]
vals
=
new
int
[
fields
.
length
];
for
(
int
i
=
0
;
i
<
fields
.
length
;
i
++
)
vals
[
i
]
=
Integer
.
parseInt
(
fields
[
i
]);
return
vals
;
}
/**
* Reads all remaining tokens from standard input, parses them as longs, and returns
* them as an array of longs.
*
@return
all remaining longs on standard input, as an array
*
@throws
InputMismatchException if any token cannot be parsed as a {
@code
long}
*/
public
static
long
[]
readAllLongs
()
{
String
[]
fields
=
readAllStrings
();
long
[]
vals
=
new
long
[
fields
.
length
];
for
(
int
i
=
0
;
i
<
fields
.
length
;
i
++
)
vals
[
i
]
=
Long
.
parseLong
(
fields
[
i
]);
return
vals
;
}
/**
* Reads all remaining tokens from standard input, parses them as doubles, and returns
* them as an array of doubles.
*
@return
all remaining doubles on standard input, as an array
*
@throws
InputMismatchException if any token cannot be parsed as a {
@code
double}
*/
public
static
double
[]
readAllDoubles
()
{
String
[]
fields
=
readAllStrings
();
double
[]
vals
=
new
double
[
fields
.
length
];
for
(
int
i
=
0
;
i
<
fields
.
length
;
i
++
)
vals
[
i
]
=
Double
.
parseDouble
(
fields
[
i
]);
return
vals
;
}
//// end: section (2 of 2) of code duplicated from In to StdIn
// do this once when StdIn is initialized
static
{
resync
();
}
/**
* If StdIn changes, use this to reinitialize the scanner.
*/
private
static
void
resync
()
{
setScanner
(
new
Scanner
(
new
java
.
io
.
BufferedInputStream
(
System
.
in
),
CHARSET_NAME
));
}
private
static
void
setScanner
(
Scanner
scanner
)
{
StdIn
.
scanner
=
scanner
;
StdIn
.
scanner
.
useLocale
(
LOCALE
);
}
/**
* Reads all remaining tokens, parses them as integers, and returns
* them as an array of integers.
*
@return
all remaining integers, as an array
*
@throws
InputMismatchException if any token cannot be parsed as an {
@code
int}
*
@deprecated
Replaced by {
@link
#readAllInts()}.
*/
@
Deprecated
public
static
int
[]
readInts
()
{
return
readAllInts
();
}
/**
* Reads all remaining tokens, parses them as doubles, and returns
* them as an array of doubles.
*
@return
all remaining doubles, as an array
*
@throws
InputMismatchException if any token cannot be parsed as a {
@code
double}
*
@deprecated
Replaced by {
@link
#readAllDoubles()}.
*/
@
Deprecated
public
static
double
[]
readDoubles
()
{
return
readAllDoubles
();
}
/**
* Reads all remaining tokens and returns them as an array of strings.
*
@return
all remaining tokens, as an array of strings
*
@deprecated
Replaced by {
@link
#readAllStrings()}.
*/
@
Deprecated
public
static
String
[]
readStrings
()
{
return
readAllStrings
();
}
/**
* Interactive test of basic functionality.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
StdOut
.
print
(
"Type a string: "
);
String
s
=
StdIn
.
readString
();
StdOut
.
println
(
"Your string was: "
+
s
);
StdOut
.
println
();
StdOut
.
print
(
"Type an int: "
);
int
a
=
StdIn
.
readInt
();
StdOut
.
println
(
"Your int was: "
+
a
);
StdOut
.
println
();
StdOut
.
print
(
"Type a boolean: "
);
boolean
b
=
StdIn
.
readBoolean
();
StdOut
.
println
(
"Your boolean was: "
+
b
);
StdOut
.
println
();
StdOut
.
print
(
"Type a double: "
);
double
c
=
StdIn
.
readDouble
();
StdOut
.
println
(
"Your double was: "
+
c
);
StdOut
.
println
();
}
}
StdInTest.java
StdInTest.java
/**
* Test client for StdIn and In.
**/
import
java
.
util
.
Scanner
;
import
java
.
lang
.
reflect
.
Array
;
import
java
.
lang
.
reflect
.
Method
;
import
java
.
io
.
ByteArrayInputStream
;
public
class
StdInTest
{
private
static
boolean
testStdIn
;
private
static
Method
resyncMethod
;
private
static
int
testCount
=
0
;
// make a printable/readable version of an object
public
static
Object
escape
(
Object
original
)
{
if
(
original
instanceof
Character
)
{
char
u
=
(
char
)
((
Character
)
original
);
int
idx
=
"\b\t\n\f\r\"\'\\"
.
indexOf
(
u
);
if
(
idx
>=
0
)
return
“\\”
+
“btnfr\”\’\\”
.
charAt
(
idx
);
if
(
u
<
32
)
return
"\\"
+
Integer
.
toOctalString
(
u
);
if
(
u
>
126
)
return
“\\u”
+
String
.
format
(
“%04X”
,
(
int
)
u
);
return
original
;
}
else
if
(
original
instanceof
String
)
{
StringBuilder
result
=
new
StringBuilder
();
for
(
char
c
:
((
String
)
original
).
toCharArray
())
result
.
append
(
escape
(
c
));
return
“\””
+
result
.
toString
()
+
“\””
;
}
else
if
(
original
.
getClass
().
isArray
())
{
StringBuilder
result
=
new
StringBuilder
(
“[”
);
int
len
=
Array
.
getLength
(
original
);
for
(
int
i
=
0
;
i
<
len
;
i
++
)
result
.
append
(
" "
).
append
(
escape
(
Array
.
get
(
original
,
i
)));
return
result
.
append
(
"]"
).
toString
();
}
return
original
;
}
public
static
boolean
canResync
()
{
try
{
resyncMethod
=
StdIn
.
class
.
getMethod
(
"resync"
);
}
catch
(
NoSuchMethodException
e
)
{
return
false
;
}
return
true
;
}
/**
* In the two methods below, each Object[] of "steps" is a length-2
* array: the first is a String holding a method name, the second
* is the expected return value when that method is called in sequence.
*/
public
static
void
test
(
String
input
,
Object
[][]
steps
)
{
test
(
input
,
steps
,
false
);
// create Scanner from String
if
(
testStdIn
)
test
(
input
,
steps
,
true
);
// uses stdIn/System.setIn
testCount
++
;
}
public
static
void
test
(
String
input
,
Object
[][]
steps
,
boolean
useStdIn
)
{
In
in
=
null
;
if
(
useStdIn
)
{
try
{
System
.
setIn
(
new
ByteArrayInputStream
(
input
.
getBytes
(
"UTF-8"
)));
}
catch
(
java
.
io
.
UnsupportedEncodingException
e
)
{
throw
new
RuntimeException
(
e
.
toString
());
}
// in order for this to work, you need to change resync to public
try
{
//call StdIn.resync();
resyncMethod
.
invoke
(
null
);
}
catch
(
IllegalAccessException
e
)
{
throw
new
RuntimeException
(
e
.
toString
());
}
catch
(
java
.
lang
.
reflect
.
InvocationTargetException
e
)
{
throw
new
RuntimeException
(
e
.
toString
());
}
}
else
in
=
new
In
(
new
Scanner
(
input
));
int
count
=
0
;
for
(
Object
[]
step
:
steps
)
{
String
cmd
=
(
String
)
step
[
0
];
Object
expected
=
step
[
1
];
Object
result
;
String
preamble
=
"Failed input %s\nStep %d (%s)\n"
;
try
{
Method
method
;
// nice and easy since these methods take no arguments
if
(
useStdIn
)
method
=
StdIn
.
class
.
getMethod
(
cmd
);
else
method
=
in
.
getClass
().
getMethod
(
cmd
);
result
=
method
.
invoke
(
in
);
// fine to be null for static
}
catch
(
NoSuchMethodException
e
)
{
java
.
io
.
StringWriter
errors
=
new
java
.
io
.
StringWriter
();
e
.
printStackTrace
(
new
java
.
io
.
PrintWriter
(
errors
));
throw
new
RuntimeException
(
String
.
format
(
preamble
,
input
,
count
,
cmd
)
+
errors
.
toString
());
}
catch
(
IllegalAccessException
e
)
{
java
.
io
.
StringWriter
errors
=
new
java
.
io
.
StringWriter
();
e
.
printStackTrace
(
new
java
.
io
.
PrintWriter
(
errors
));
throw
new
RuntimeException
(
String
.
format
(
preamble
,
input
,
count
,
cmd
)
+
errors
.
toString
());
}
catch
(
java
.
lang
.
reflect
.
InvocationTargetException
e
)
{
java
.
io
.
StringWriter
errors
=
new
java
.
io
.
StringWriter
();
e
.
printStackTrace
(
new
java
.
io
.
PrintWriter
(
errors
));
e
.
getCause
().
printStackTrace
(
new
java
.
io
.
PrintWriter
(
errors
));
throw
new
RuntimeException
(
String
.
format
(
preamble
,
input
,
count
,
cmd
)
+
errors
.
toString
());
}
if
(
expected
.
getClass
().
isArray
())
{
if
(
!
(
result
.
getClass
().
isArray
()))
{
StdOut
.
printf
(
preamble
+
"Expected array, got %s\n"
,
input
,
count
,
cmd
,
result
);
continue
;
}
Object
r
=
result
,
e
=
expected
;
// to shorten lines below
int
rl
=
Array
.
getLength
(
r
);
int
el
=
Array
.
getLength
(
e
);
if
(
el
!=
rl
)
StdOut
.
printf
(
preamble
+
"Expected %d, got %d items:\n%s\n"
,
escape
(
input
),
count
,
cmd
,
el
,
rl
,
escape
(
r
));
else
{
for
(
int
i
=
0
;
i
<
rl
;
i
++
)
{
if
(
!
(
Array
.
get
(
r
,
i
).
equals
(
Array
.
get
(
e
,
i
))))
StdOut
.
printf
(
preamble
+
"\nExpected [%d]=%s, got %s\n"
,
escape
(
input
),
count
,
cmd
,
i
,
escape
(
Array
.
get
(
e
,
i
)),
escape
(
Array
.
get
(
r
,
i
)));
}
}
}
else
if
(
!
result
.
equals
(
expected
))
{
StdOut
.
printf
(
preamble
+
"Expected %s, got %s\n"
,
escape
(
input
),
count
,
cmd
,
escape
(
expected
),
escape
(
result
));
}
count
++
;
}
}
public
static
void
main
(
String
[]
args
)
{
testStdIn
=
canResync
();
if
(
testStdIn
)
StdOut
.
println
(
"Note: any errors appear duplicated since tests run 2x."
);
else
StdOut
.
println
(
"Note: StdIn.resync is private, only In will be tested."
);
test
(
"this is a test"
,
new
Object
[][]
{
{
"isEmpty"
,
false
},
{
"hasNextChar"
,
true
},
{
"hasNextLine"
,
true
},
{
"readAllStrings"
,
new
String
[]
{
"this"
,
"is"
,
"a"
,
"test"
}},
{
"isEmpty"
,
true
},
{
"hasNextChar"
,
false
},
{
"hasNextLine"
,
false
}
});
test
(
"\n\n\n"
,
new
Object
[][]
{
{
"isEmpty"
,
true
},
{
"hasNextChar"
,
true
},
{
"hasNextLine"
,
true
},
{
"readAll"
,
"\n\n\n"
}
});
test
(
""
,
new
Object
[][]
{
{
"isEmpty"
,
true
},
{
"hasNextChar"
,
false
},
{
"hasNextLine"
,
false
}
});
test
(
"\t\t \t\t"
,
new
Object
[][]
{
{
"isEmpty"
,
true
},
{
"hasNextChar"
,
true
},
{
"hasNextLine"
,
true
},
{
"readAll"
,
"\t\t \t\t"
}
});
test
(
"readLine consumes newline\nyeah!"
,
new
Object
[][]
{
{
"readLine"
,
"readLine consumes newline"
},
{
"readChar"
,
'y'
}
});
test
(
"readString doesn't consume spaces"
,
new
Object
[][]
{
{
"readString"
,
"readString"
},
{
"readChar"
,
' '
}
});
test
(
"\n\nblank lines test"
,
new
Object
[][]
{
{
"readLine"
,
""
},
{
"readLine"
,
""
},
{
"hasNextLine"
,
true
},
{
"readLine"
,
"blank lines test"
},
{
"hasNextLine"
,
false
}
});
test
(
" \n \t \n correct \n\t\n\t .trim replacement \n\t"
,
new
Object
[][]
{
{
"readAllStrings"
,
new
String
[]{
"correct"
,
".trim"
,
"replacement"
}},
{
"hasNextChar"
,
false
}
});
StringBuilder
sb
=
new
StringBuilder
();
Object
[][]
expected
=
new
Object
[
2000
][
2
];
for
(
int
i
=
0
;
i
<
1000
;
i
++
)
{
sb
.
append
((
char
)
i
);
sb
.
append
((
char
)
(
i
+
8000
));
// include weird non-breaking spaces
expected
[
2
*
i
][
0
]
=
"readChar"
;
expected
[
2
*
i
+
1
][
0
]
=
"readChar"
;
expected
[
2
*
i
][
1
]
=
(
char
)
i
;
expected
[
2
*
i
+
1
][
1
]
=
(
char
)(
i
+
8000
);
}
test
(
sb
.
toString
(),
expected
);
test
(
" this \n and \that \n "
,
new
Object
[][]
{
{
"readString"
,
"this"
},
{
"readString"
,
"and"
},
{
"readChar"
,
' '
},
{
"readString"
,
"hat"
},
{
"readChar"
,
' '
},
{
"isEmpty"
,
true
},
{
"hasNextLine"
,
true
},
{
"readLine"
,
""
},
{
"readLine"
,
" "
}
});
test
(
" 1 2 3 \n\t 4 5 "
,
new
Object
[][]
{
{
"readAllInts"
,
new
int
[]
{
1
,
2
,
3
,
4
,
5
}}
});
test
(
" 0 1 False true falsE True "
,
new
Object
[][]
{
{
"readBoolean"
,
false
},
{
"readBoolean"
,
true
},
{
"readBoolean"
,
false
},
{
"readBoolean"
,
true
},
{
"readBoolean"
,
false
},
{
"readBoolean"
,
true
}
});
test
(
" \240\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008"
+
"\u2009\u200A\u205F\u3000"
,
new
Object
[][]
{
{
"readString"
,
"\240"
},
// non-breaking space - not java whitespace
{
"readString"
,
"\u2007"
},
// similarly
{
"hasNextChar"
,
true
},
// there is some stuff left over
{
"isEmpty"
,
true
},
// but it is all whitespace
{
"readChar"
,
'\u2008'
}
// such as this one
});
// line sep, par sep, NEL, unit sep, vtab --- first 3 are newlines
// NB: \205 is treated as a line separator, but not whitespace!
test
(
"a\u2028b\u2029c\37d\13e\205f"
,
new
Object
[][]
{
{
"readAllStrings"
,
new
String
[]{
"a"
,
"b"
,
"c"
,
"d"
,
"e\205f"
}}
});
test
(
"a\u2028b\u2029c\37d\13e\205f"
,
new
Object
[][]
{
{
"readLine"
,
"a"
},
{
"readLine"
,
"b"
},
{
"readLine"
,
"c\37d\13e"
},
{
"readLine"
,
"f"
}
});
test
(
"\u2028\u2029"
,
// line separator, par separator
new
Object
[][]
{
{
"readLine"
,
""
},
{
"hasNextLine"
,
true
},
{
"hasNextChar"
,
true
},
{
"readLine"
,
""
},
{
"hasNextLine"
,
false
},
{
"hasNextChar"
,
false
}
});
test
(
"\n\n"
,
new
Object
[][]
{
{
"readLine"
,
""
},
{
"hasNextLine"
,
true
},
{
"hasNextChar"
,
true
},
{
"readLine"
,
""
},
{
"hasNextLine"
,
false
},
{
"hasNextChar"
,
false
}
});
test
(
"\r\n\r\n"
,
new
Object
[][]
{
{
"readLine"
,
""
},
{
"hasNextLine"
,
true
},
{
"hasNextChar"
,
true
},
{
"readLine"
,
""
},
{
"hasNextLine"
,
false
},
{
"hasNextChar"
,
false
}
});
test
(
"\n\r"
,
new
Object
[][]
{
{
"readLine"
,
""
},
{
"hasNextLine"
,
true
},
{
"hasNextChar"
,
true
},
{
"readLine"
,
""
},
{
"hasNextLine"
,
false
},
{
"hasNextChar"
,
false
}
});
test
(
"\r\n"
,
new
Object
[][]
{
{
"readLine"
,
""
},
{
"hasNextChar"
,
false
},
{
"hasNextLine"
,
false
}
});
test
(
"3E4 \t -0.5 \n \t +4"
,
new
Object
[][]
{
{
"readAllDoubles"
,
new
double
[]
{
30000
,
-
0.5
,
4
}}
});
test
(
" whitespace "
,
new
Object
[][]
{
{
"readString"
,
"whitespace"
},
{
"readChar"
,
' '
},
{
"hasNextLine"
,
false
}
});
test
(
" whitespace \n"
,
new
Object
[][]
{
{
"readString"
,
"whitespace"
},
{
"readChar"
,
' '
},
{
"readLine"
,
""
},
{
"hasNextLine"
,
false
}
});
test
(
" whitespace \n "
,
new
Object
[][]
{
{
"readString"
,
"whitespace"
},
{
"readChar"
,
' '
},
{
"readLine"
,
""
},
{
"hasNextLine"
,
true
},
{
"readLine"
,
" "
},
{
"hasNextLine"
,
false
}
});
test
(
" 34 -12983 3.25\n\t foo!"
,
new
Object
[][]
{
{
"readByte"
,
(
byte
)
34
},
{
"readShort"
,
(
short
)
-
12983
},
{
"readDouble"
,
3.25
},
{
"readAll"
,
"\n\t foo!"
}
});
test
(
"30000000000 3.5 3e4, foo \t\t ya"
,
new
Object
[][]
{
{
"readLong"
,
30000000000L
},
{
"readFloat"
,
(
float
)
3.5
},
{
"readAllStrings"
,
new
String
[]
{
"3e4,"
,
"foo"
,
"ya"
}}
});
// testing consistency of whitespace and read(All)String(s)
test
(
" \u0001 foo \u0001 foo \u0001 foo"
,
new
Object
[][]
{
{
"readAllStrings"
,
new
String
[]
{
"\u0001"
,
"foo"
,
"\u0001"
,
"foo"
,
"\u0001"
,
"foo"
}}
});
test
(
" \u2005 foo \u2005 foo \u2005 foo"
,
new
Object
[][]
{
{
"readAllStrings"
,
new
String
[]
{
"foo"
,
"foo"
,
"foo"
}}
});
test
(
" \u0001 foo \u0001 foo \u0001 foo"
,
new
Object
[][]
{
{
"readString"
,
"\u0001"
},
{
"readString"
,
"foo"
},
{
"readString"
,
"\u0001"
},
{
"readString"
,
"foo"
},
{
"readString"
,
"\u0001"
},
{
"readString"
,
"foo"
}
});
test
(
" \u2005 foo \u2005 foo \u2005 foo"
,
new
Object
[][]
{
{
"readString"
,
"foo"
},
{
"readString"
,
"foo"
},
{
"readString"
,
"foo"
}
});
StdOut
.
printf
(
"Ran %d tests.\n"
,
testCount
);
}
}
StdOut.java
StdOut.java
/******************************************************************************
* Compilation: javac StdOut.java
* Execution: java StdOut
* Dependencies: none
*
* Writes data of various types to standard output.
*
******************************************************************************/
import
java
.
io
.
OutputStreamWriter
;
import
java
.
io
.
PrintWriter
;
import
java
.
io
.
UnsupportedEncodingException
;
import
java
.
util
.
Locale
;
/**
* This class provides methods for printing strings and numbers to standard output.
*
* Getting started.
* To use this class, you must have {
@code
StdOut.class} in your
* Java classpath. If you used our autoinstaller, you should be all set.
* Otherwise, either download
* and add to your Java classpath or download
* and put a copy in your working directory.
*
* Here is an example program that uses {
@code
StdOut}:
*
* public class TestStdOut { * public static void main(String[] args) { * int a = 17; * int b = 23; * int sum = a + b; * StdOut.println("Hello, World"); * StdOut.printf("%d + %d = %d\n", a, b, sum); * } * } *
*
* Differences with System.out.
* The behavior of {
@code
StdOut} is similar to that of {
@link
System#out},
* but there are a few technical differences:
*
*
* which is a standard character encoding for Unicode.
*
* for consistency with {
@link
StdIn}, {
@link
Double#parseDouble(String)},
* and floating-point literals.
*
* {
@code
print()} so that text will appear immediately in the terminal.
*
*
* Reference.
* For additional documentation,
* see Section 1.5 of
* Computer Science: An Interdisciplinary Approach
* by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
StdOut
{
// force Unicode UTF-8 encoding; otherwise it’s system dependent
private
static
final
String
CHARSET_NAME
=
“UTF-8”
;
// assume language = English, country = US for consistency with StdIn
private
static
final
Locale
LOCALE
=
Locale
.
US
;
// send output here
private
static
PrintWriter
out
;
// this is called before invoking any methods
static
{
try
{
out
=
new
PrintWriter
(
new
OutputStreamWriter
(
System
.
out
,
CHARSET_NAME
),
true
);
}
catch
(
UnsupportedEncodingException
e
)
{
System
.
out
.
println
(
e
);
}
}
// don’t instantiate
private
StdOut
()
{
}
/**
* Terminates the current line by printing the line-separator string.
*/
public
static
void
println
()
{
out
.
println
();
}
/**
* Prints an object to this output stream and then terminates the line.
*
*
@param
x the object to print
*/
public
static
void
println
(
Object
x
)
{
out
.
println
(
x
);
}
/**
* Prints a boolean to standard output and then terminates the line.
*
*
@param
x the boolean to print
*/
public
static
void
println
(
boolean
x
)
{
out
.
println
(
x
);
}
/**
* Prints a character to standard output and then terminates the line.
*
*
@param
x the character to print
*/
public
static
void
println
(
char
x
)
{
out
.
println
(
x
);
}
/**
* Prints a double to standard output and then terminates the line.
*
*
@param
x the double to print
*/
public
static
void
println
(
double
x
)
{
out
.
println
(
x
);
}
/**
* Prints an integer to standard output and then terminates the line.
*
*
@param
x the integer to print
*/
public
static
void
println
(
float
x
)
{
out
.
println
(
x
);
}
/**
* Prints an integer to standard output and then terminates the line.
*
*
@param
x the integer to print
*/
public
static
void
println
(
int
x
)
{
out
.
println
(
x
);
}
/**
* Prints a long to standard output and then terminates the line.
*
*
@param
x the long to print
*/
public
static
void
println
(
long
x
)
{
out
.
println
(
x
);
}
/**
* Prints a short integer to standard output and then terminates the line.
*
*
@param
x the short to print
*/
public
static
void
println
(
short
x
)
{
out
.
println
(
x
);
}
/**
* Prints a byte to standard output and then terminates the line.
*
* To write binary data, see {
@link
BinaryStdOut}.
*
*
@param
x the byte to print
*/
public
static
void
println
(
byte
x
)
{
out
.
println
(
x
);
}
/**
* Flushes standard output.
*/
public
static
void
print
()
{
out
.
flush
();
}
/**
* Prints an object to standard output and flushes standard output.
*
*
@param
x the object to print
*/
public
static
void
print
(
Object
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a boolean to standard output and flushes standard output.
*
*
@param
x the boolean to print
*/
public
static
void
print
(
boolean
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a character to standard output and flushes standard output.
*
*
@param
x the character to print
*/
public
static
void
print
(
char
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a double to standard output and flushes standard output.
*
*
@param
x the double to print
*/
public
static
void
print
(
double
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a float to standard output and flushes standard output.
*
*
@param
x the float to print
*/
public
static
void
print
(
float
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints an integer to standard output and flushes standard output.
*
*
@param
x the integer to print
*/
public
static
void
print
(
int
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a long integer to standard output and flushes standard output.
*
*
@param
x the long integer to print
*/
public
static
void
print
(
long
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a short integer to standard output and flushes standard output.
*
*
@param
x the short integer to print
*/
public
static
void
print
(
short
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a byte to standard output and flushes standard output.
*
*
@param
x the byte to print
*/
public
static
void
print
(
byte
x
)
{
out
.
print
(
x
);
out
.
flush
();
}
/**
* Prints a formatted string to standard output, using the specified format
* string and arguments, and then flushes standard output.
*
*
*
@param
format the format string
*
@param
args the arguments accompanying the format string
*/
public
static
void
printf
(
String
format
,
Object
…
args
)
{
out
.
printf
(
LOCALE
,
format
,
args
);
out
.
flush
();
}
/**
* Prints a formatted string to standard output, using the locale and
* the specified format string and arguments; then flushes standard output.
*
*
@param
locale the locale
*
@param
format the format string
*
@param
args the arguments accompanying the format string
*/
public
static
void
printf
(
Locale
locale
,
String
format
,
Object
…
args
)
{
out
.
printf
(
locale
,
format
,
args
);
out
.
flush
();
}
/**
* Unit tests some of the methods in {
@code
StdOut}.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
// write to stdout
StdOut
.
println
(
“Test”
);
StdOut
.
println
(
17
);
StdOut
.
println
(
true
);
StdOut
.
printf
(
“%.6f\n”
,
1.0
/
7.0
);
}
}
StdRandom.java
StdRandom.java
/******************************************************************************
* Compilation: javac StdRandom.java
* Execution: java StdRandom
* Dependencies: StdOut.java
*
* A library of static methods to generate pseudo-random numbers from
* different distributions (bernoulli, uniform, gaussian, discrete,
* and exponential). Also includes a method for shuffling an array.
*
*
* % java StdRandom 5
* seed = 1316600602069
* 59 16.81826 true 8.83954 0
* 32 91.32098 true 9.11026 0
* 35 10.11874 true 8.95396 3
* 92 32.88401 true 8.87089 0
* 72 92.55791 true 9.46241 0
*
* % java StdRandom 5
* seed = 1316600616575
* 96 60.17070 true 8.72821 0
* 79 32.01607 true 8.58159 0
* 81 59.49065 true 9.10423 1
* 96 51.65818 true 9.02102 0
* 99 17.55771 true 8.99762 0
*
* % java StdRandom 5 1316600616575
* seed = 1316600616575
* 96 60.17070 true 8.72821 0
* 79 32.01607 true 8.58159 0
* 81 59.49065 true 9.10423 1
* 96 51.65818 true 9.02102 0
* 99 17.55771 true 8.99762 0
*
*
* Remark
* ——
* – Relies on randomness of nextDouble() method in java.util.Random
* to generate pseudo-random numbers in [0, 1).
*
* – This library allows you to set and get the pseudo-random number seed.
*
* – See http://www.honeylocust.com/RngPack/ for an industrial
* strength random number generator in Java.
*
******************************************************************************/
import
java
.
util
.
Random
;
/**
* The {
@code
StdRandom} class provides static methods for generating
* random number from various discrete and continuous distributions,
* including uniform, Bernoulli, geometric, Gaussian, exponential, Pareto,
* Poisson, and Cauchy. It also provides method for shuffling an
* array or subarray and generating random permutations.
*
* By convention, all intervals are half open. For example,
* uniform(-1.0, 1.0)
returns a random number between
* -1.0
(inclusive) and 1.0
(exclusive).
* Similarly, shuffle(a, lo, hi)
shuffles the hi - lo
* elements in the array a[]
, starting at index lo
* (inclusive) and ending at index hi
(exclusive).
*
* For additional documentation,
* see Section 2.2 of
* Computer Science: An Interdisciplinary Approach
* by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
StdRandom
{
private
static
Random
random
;
// pseudo-random number generator
private
static
long
seed
;
// pseudo-random number generator seed
// static initializer
static
{
// this is how the seed was set in Java 1.4
seed
=
System
.
currentTimeMillis
();
random
=
new
Random
(
seed
);
}
// don’t instantiate
private
StdRandom
()
{
}
/**
* Sets the seed of the pseudo-random number generator.
* This method enables you to produce the same sequence of “random”
* number for each execution of the program.
* Ordinarily, you should call this method at most once per program.
*
*
@param
s the seed
*/
public
static
void
setSeed
(
long
s
)
{
seed
=
s
;
random
=
new
Random
(
seed
);
}
/**
* Returns the seed of the pseudo-random number generator.
*
*
@return
the seed
*/
public
static
long
getSeed
()
{
return
seed
;
}
/**
* Returns a random real number uniformly in [0, 1).
*
*
@return
a random real number uniformly in [0, 1)
*/
public
static
double
uniform
()
{
return
random
.
nextDouble
();
}
/**
* Returns a random integer uniformly in [0, n).
*
*
@param
n number of possible integers
*
@return
a random integer uniformly between 0 (inclusive) and {
@code
n} (exclusive)
*
@throws
IllegalArgumentException if {
@code
n <= 0}
*/
public
static
int
uniform
(
int
n
)
{
if
(
n
<=
0
)
throw
new
IllegalArgumentException
(
"argument must be positive: "
+
n
);
return
random
.
nextInt
(
n
);
}
/**
* Returns a random long integer uniformly in [0, n).
*
*
@param
n number of possible {
@code
long} integers
*
@return
a random long integer uniformly between 0 (inclusive) and {
@code
n} (exclusive)
*
@throws
IllegalArgumentException if {
@code
n <= 0}
*/
public
static
long
uniform
(
long
n
)
{
if
(
n
<=
0L
)
throw
new
IllegalArgumentException
(
"argument must be positive: "
+
n
);
// https://docs.oracle.com/javase/8/docs/api/java/util/Random.html#longs-long-long-long-
long
r
=
random
.
nextLong
();
long
m
=
n
-
1
;
// power of two
if
((
n
&
m
)
==
0L
)
{
return
r
&
m
;
}
// reject over-represented candidates
long
u
=
r
>>>
1
;
while
(
u
+
m
–
(
r
=
u
%
n
)
<
0L
)
{
u
=
random
.
nextLong
()
>>>
1
;
}
return
r
;
}
///////////////////////////////////////////////////////////////////////////
// STATIC METHODS BELOW RELY ON JAVA.UTIL.RANDOM ONLY INDIRECTLY VIA
// THE STATIC METHODS ABOVE.
///////////////////////////////////////////////////////////////////////////
/**
* Returns a random real number uniformly in [0, 1).
*
*
@return
a random real number uniformly in [0, 1)
*
@deprecated
Replaced by {
@link
#uniform()}.
*/
@
Deprecated
public
static
double
random
()
{
return
uniform
();
}
/**
* Returns a random integer uniformly in [a, b).
*
*
@param
a the left endpoint
*
@param
b the right endpoint
*
@return
a random integer uniformly in [a, b)
*
@throws
IllegalArgumentException if {
@code
b <= a}
*
@throws
IllegalArgumentException if {
@code
b - a >= Integer.MAX_VALUE}
*/
public
static
int
uniform
(
int
a
,
int
b
)
{
if
((
b
<=
a
)
||
((
long
)
b
-
a
>=
Integer
.
MAX_VALUE
))
{
throw
new
IllegalArgumentException
(
“invalid range: [”
+
a
+
“, ”
+
b
+
“)”
);
}
return
a
+
uniform
(
b
–
a
);
}
/**
* Returns a random real number uniformly in [a, b).
*
*
@param
a the left endpoint
*
@param
b the right endpoint
*
@return
a random real number uniformly in [a, b)
*
@throws
IllegalArgumentException unless {
@code
a < b}
*/
public
static
double
uniform
(
double
a
,
double
b
)
{
if
(
!
(
a
<
b
))
{
throw
new
IllegalArgumentException
(
"invalid range: ["
+
a
+
", "
+
b
+
")"
);
}
return
a
+
uniform
()
*
(
b
-
a
);
}
/**
* Returns a random boolean from a Bernoulli distribution with success
* probability p.
*
*
@param
p the probability of returning {
@code
true}
*
@return
{
@code
true} with probability {
@code
p} and
* {
@code
false} with probability {
@code
1 – p}
*
@throws
IllegalArgumentException unless {
@code
0} ≤ {
@code
p} ≤ {
@code
1.0}
*/
public
static
boolean
bernoulli
(
double
p
)
{
if
(
!
(
p
>=
0.0
&&
p
<=
1.0
))
throw
new
IllegalArgumentException
(
"probability p must be between 0.0 and 1.0: "
+
p
);
return
uniform
()
<
p
;
}
/**
* Returns a random boolean from a Bernoulli distribution with success
* probability 1/2.
*
*
@return
{
@code
true} with probability 1/2 and
* {
@code
false} with probability 1/2
*/
public
static
boolean
bernoulli
()
{
return
bernoulli
(
0.5
);
}
/**
* Returns a random real number from a standard Gaussian distribution.
*
*
@return
a random real number from a standard Gaussian distribution
* (mean 0 and standard deviation 1).
*/
public
static
double
gaussian
()
{
// use the polar form of the Box-Muller transform
double
r
,
x
,
y
;
do
{
x
=
uniform
(
-
1.0
,
1.0
);
y
=
uniform
(
-
1.0
,
1.0
);
r
=
x
*
x
+
y
*
y
;
}
while
(
r
>=
1
||
r
==
0
);
return
x
*
Math
.
sqrt
(
–
2
*
Math
.
log
(
r
)
/
r
);
// Remark: y * Math.sqrt(-2 * Math.log(r) / r)
// is an independent random gaussian
}
/**
* Returns a random real number from a Gaussian distribution with mean μ
* and standard deviation σ.
*
*
@param
mu the mean
*
@param
sigma the standard deviation
*
@return
a real number distributed according to the Gaussian distribution
* with mean {
@code
mu} and standard deviation {
@code
sigma}
*/
public
static
double
gaussian
(
double
mu
,
double
sigma
)
{
return
mu
+
sigma
*
gaussian
();
}
/**
* Returns a random integer from a geometric distribution with success
* probability p.
* The integer represents the number of independent trials
* before the first success.
*
*
@param
p the parameter of the geometric distribution
*
@return
a random integer from a geometric distribution with success
* probability {
@code
p}; or {
@code
Integer.MAX_VALUE} if
* {
@code
p} is (nearly) equal to {
@code
1.0}.
*
@throws
IllegalArgumentException unless {
@code
p >= 0.0} and {
@code
p <= 1.0}
*/
public
static
int
geometric
(
double
p
)
{
if
(
!
(
p
>=
0
))
{
throw
new
IllegalArgumentException
(
“probability p must be greater than 0: ”
+
p
);
}
if
(
!
(
p
<=
1.0
))
{
throw
new
IllegalArgumentException
(
"probability p must not be larger than 1: "
+
p
);
}
// using algorithm given by Knuth
return
(
int
)
Math
.
ceil
(
Math
.
log
(
uniform
())
/
Math
.
log
(
1.0
-
p
));
}
/**
* Returns a random integer from a Poisson distribution with mean λ.
*
*
@param
lambda the mean of the Poisson distribution
*
@return
a random integer from a Poisson distribution with mean {
@code
lambda}
*
@throws
IllegalArgumentException unless {
@code
lambda > 0.0} and not infinite
*/
public
static
int
poisson
(
double
lambda
)
{
if
(
!
(
lambda
>
0.0
))
throw
new
IllegalArgumentException
(
“lambda must be positive: ”
+
lambda
);
if
(
Double
.
isInfinite
(
lambda
))
throw
new
IllegalArgumentException
(
“lambda must not be infinite: ”
+
lambda
);
// using algorithm given by Knuth
// see http://en.wikipedia.org/wiki/Poisson_distribution
int
k
=
0
;
double
p
=
1.0
;
double
expLambda
=
Math
.
exp
(
–
lambda
);
do
{
k
++
;
p
*=
uniform
();
}
while
(
p
>=
expLambda
);
return
k
–
1
;
}
/**
* Returns a random real number from the standard Pareto distribution.
*
*
@return
a random real number from the standard Pareto distribution
*/
public
static
double
pareto
()
{
return
pareto
(
1.0
);
}
/**
* Returns a random real number from a Pareto distribution with
* shape parameter α.
*
*
@param
alpha shape parameter
*
@return
a random real number from a Pareto distribution with shape
* parameter {
@code
alpha}
*
@throws
IllegalArgumentException unless {
@code
alpha > 0.0}
*/
public
static
double
pareto
(
double
alpha
)
{
if
(
!
(
alpha
>
0.0
))
throw
new
IllegalArgumentException
(
“alpha must be positive: ”
+
alpha
);
return
Math
.
pow
(
1
–
uniform
(),
–
1.0
/
alpha
)
–
1.0
;
}
/**
* Returns a random real number from the Cauchy distribution.
*
*
@return
a random real number from the Cauchy distribution.
*/
public
static
double
cauchy
()
{
return
Math
.
tan
(
Math
.
PI
*
(
uniform
()
–
0.5
));
}
/**
* Returns a random integer from the specified discrete distribution.
*
*
@param
probabilities the probability of occurrence of each integer
*
@return
a random integer from a discrete distribution:
* {
@code
i} with probability {
@code
probabilities[i]}
*
@throws
IllegalArgumentException if {
@code
probabilities} is {
@code
null}
*
@throws
IllegalArgumentException if sum of array entries is not (very nearly) equal to {
@code
1.0}
*
@throws
IllegalArgumentException unless {
@code
probabilities[i] >= 0.0} for each index {
@code
i}
*/
public
static
int
discrete
(
double
[]
probabilities
)
{
if
(
probabilities
==
null
)
throw
new
IllegalArgumentException
(
“argument array is null”
);
double
EPSILON
=
1.0E-14
;
double
sum
=
0.0
;
for
(
int
i
=
0
;
i
<
probabilities
.
length
;
i
++
)
{
if
(
!
(
probabilities
[
i
]
>=
0.0
))
throw
new
IllegalArgumentException
(
“array entry ”
+
i
+
” must be nonnegative: ”
+
probabilities
[
i
]);
sum
+=
probabilities
[
i
];
}
if
(
sum
>
1.0
+
EPSILON
||
sum
<
1.0
-
EPSILON
)
throw
new
IllegalArgumentException
(
"sum of array entries does not approximately equal 1.0: "
+
sum
);
// the for loop may not return a value when both r is (nearly) 1.0 and when the
// cumulative sum is less than 1.0 (as a result of floating-point roundoff error)
while
(
true
)
{
double
r
=
uniform
();
sum
=
0.0
;
for
(
int
i
=
0
;
i
<
probabilities
.
length
;
i
++
)
{
sum
=
sum
+
probabilities
[
i
];
if
(
sum
>
r
)
return
i
;
}
}
}
/**
* Returns a random integer from the specified discrete distribution.
*
*
@param
frequencies the frequency of occurrence of each integer
*
@return
a random integer from a discrete distribution:
* {
@code
i} with probability proportional to {
@code
frequencies[i]}
*
@throws
IllegalArgumentException if {
@code
frequencies} is {
@code
null}
*
@throws
IllegalArgumentException if all array entries are {
@code
0}
*
@throws
IllegalArgumentException if {
@code
frequencies[i]} is negative for any index {
@code
i}
*
@throws
IllegalArgumentException if sum of frequencies exceeds {
@code
Integer.MAX_VALUE} (231 – 1)
*/
public
static
int
discrete
(
int
[]
frequencies
)
{
if
(
frequencies
==
null
)
throw
new
IllegalArgumentException
(
“argument array is null”
);
long
sum
=
0
;
for
(
int
i
=
0
;
i
<
frequencies
.
length
;
i
++
)
{
if
(
frequencies
[
i
]
<
0
)
throw
new
IllegalArgumentException
(
"array entry "
+
i
+
" must be nonnegative: "
+
frequencies
[
i
]);
sum
+=
frequencies
[
i
];
}
if
(
sum
==
0
)
throw
new
IllegalArgumentException
(
"at least one array entry must be positive"
);
if
(
sum
>=
Integer
.
MAX_VALUE
)
throw
new
IllegalArgumentException
(
“sum of frequencies overflows an int”
);
// pick index i with probabilitity proportional to frequency
double
r
=
uniform
((
int
)
sum
);
sum
=
0
;
for
(
int
i
=
0
;
i
<
frequencies
.
length
;
i
++
)
{
sum
+=
frequencies
[
i
];
if
(
sum
>
r
)
return
i
;
}
// can’t reach here
assert
false
;
return
–
1
;
}
/**
* Returns a random real number from an exponential distribution
* with rate λ.
*
*
@param
lambda the rate of the exponential distribution
*
@return
a random real number from an exponential distribution with
* rate {
@code
lambda}
*
@throws
IllegalArgumentException unless {
@code
lambda > 0.0}
*/
public
static
double
exp
(
double
lambda
)
{
if
(
!
(
lambda
>
0.0
))
throw
new
IllegalArgumentException
(
“lambda must be positive: ”
+
lambda
);
return
–
Math
.
log
(
1
–
uniform
())
/
lambda
;
}
/**
* Rearranges the elements of the specified array in uniformly random order.
*
*
@param
a the array to shuffle
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*/
public
static
void
shuffle
(
Object
[]
a
)
{
validateNotNull
(
a
);
int
n
=
a
.
length
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
int
r
=
i
+
uniform
(
n
-
i
);
// between i and n-1
Object
temp
=
a
[
i
];
a
[
i
]
=
a
[
r
];
a
[
r
]
=
temp
;
}
}
/**
* Rearranges the elements of the specified array in uniformly random order.
*
*
@param
a the array to shuffle
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*/
public
static
void
shuffle
(
double
[]
a
)
{
validateNotNull
(
a
);
int
n
=
a
.
length
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
int
r
=
i
+
uniform
(
n
-
i
);
// between i and n-1
double
temp
=
a
[
i
];
a
[
i
]
=
a
[
r
];
a
[
r
]
=
temp
;
}
}
/**
* Rearranges the elements of the specified array in uniformly random order.
*
*
@param
a the array to shuffle
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*/
public
static
void
shuffle
(
int
[]
a
)
{
validateNotNull
(
a
);
int
n
=
a
.
length
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
int
r
=
i
+
uniform
(
n
-
i
);
// between i and n-1
int
temp
=
a
[
i
];
a
[
i
]
=
a
[
r
];
a
[
r
]
=
temp
;
}
}
/**
* Rearranges the elements of the specified array in uniformly random order.
*
*
@param
a the array to shuffle
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*/
public
static
void
shuffle
(
char
[]
a
)
{
validateNotNull
(
a
);
int
n
=
a
.
length
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
int
r
=
i
+
uniform
(
n
-
i
);
// between i and n-1
char
temp
=
a
[
i
];
a
[
i
]
=
a
[
r
];
a
[
r
]
=
temp
;
}
}
/**
* Rearranges the elements of the specified subarray in uniformly random order.
*
*
@param
a the array to shuffle
*
@param
lo the left endpoint (inclusive)
*
@param
hi the right endpoint (exclusive)
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*
@throws
IllegalArgumentException unless {
@code
(0 <= lo) && (lo < hi) && (hi <= a.length)}
*
*/
public
static
void
shuffle
(
Object
[]
a
,
int
lo
,
int
hi
)
{
validateNotNull
(
a
);
validateSubarrayIndices
(
lo
,
hi
,
a
.
length
);
for
(
int
i
=
lo
;
i
<
hi
;
i
++
)
{
int
r
=
i
+
uniform
(
hi
-
i
);
// between i and hi-1
Object
temp
=
a
[
i
];
a
[
i
]
=
a
[
r
];
a
[
r
]
=
temp
;
}
}
/**
* Rearranges the elements of the specified subarray in uniformly random order.
*
*
@param
a the array to shuffle
*
@param
lo the left endpoint (inclusive)
*
@param
hi the right endpoint (exclusive)
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*
@throws
IllegalArgumentException unless {
@code
(0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
public
static
void
shuffle
(
double
[]
a
,
int
lo
,
int
hi
)
{
validateNotNull
(
a
);
validateSubarrayIndices
(
lo
,
hi
,
a
.
length
);
for
(
int
i
=
lo
;
i
<
hi
;
i
++
)
{
int
r
=
i
+
uniform
(
hi
-
i
);
// between i and hi-1
double
temp
=
a
[
i
];
a
[
i
]
=
a
[
r
];
a
[
r
]
=
temp
;
}
}
/**
* Rearranges the elements of the specified subarray in uniformly random order.
*
*
@param
a the array to shuffle
*
@param
lo the left endpoint (inclusive)
*
@param
hi the right endpoint (exclusive)
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*
@throws
IllegalArgumentException unless {
@code
(0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
public
static
void
shuffle
(
int
[]
a
,
int
lo
,
int
hi
)
{
validateNotNull
(
a
);
validateSubarrayIndices
(
lo
,
hi
,
a
.
length
);
for
(
int
i
=
lo
;
i
<
hi
;
i
++
)
{
int
r
=
i
+
uniform
(
hi
-
i
);
// between i and hi-1
int
temp
=
a
[
i
];
a
[
i
]
=
a
[
r
];
a
[
r
]
=
temp
;
}
}
/**
* Returns a uniformly random permutation of n elements.
*
*
@param
n number of elements
*
@throws
IllegalArgumentException if {
@code
n} is negative
*
@return
an array of length {
@code
n} that is a uniformly random permutation
* of {
@code
0}, {
@code
1}, …, {
@code
n-1}
*/
public
static
int
[]
permutation
(
int
n
)
{
if
(
n
<
0
)
throw
new
IllegalArgumentException
(
"argument is negative"
);
int
[]
perm
=
new
int
[
n
];
for
(
int
i
=
0
;
i
<
n
;
i
++
)
perm
[
i
]
=
i
;
shuffle
(
perm
);
return
perm
;
}
/**
* Returns a uniformly random permutation of k of n elements.
*
*
@param
n number of elements
*
@param
k number of elements to select
*
@throws
IllegalArgumentException if {
@code
n} is negative
*
@throws
IllegalArgumentException unless {
@code
0 <= k <= n}
*
@return
an array of length {
@code
k} that is a uniformly random permutation
* of {
@code
k} of the elements from {
@code
0}, {
@code
1}, ..., {
@code
n-1}
*/
public
static
int
[]
permutation
(
int
n
,
int
k
)
{
if
(
n
<
0
)
throw
new
IllegalArgumentException
(
"argument is negative"
);
if
(
k
<
0
||
k
>
n
)
throw
new
IllegalArgumentException
(
“k must be between 0 and n”
);
int
[]
perm
=
new
int
[
k
];
for
(
int
i
=
0
;
i
<
k
;
i
++
)
{
int
r
=
uniform
(
i
+
1
);
// between 0 and i
perm
[
i
]
=
perm
[
r
];
perm
[
r
]
=
i
;
}
for
(
int
i
=
k
;
i
<
n
;
i
++
)
{
int
r
=
uniform
(
i
+
1
);
// between 0 and i
if
(
r
<
k
)
perm
[
r
]
=
i
;
}
return
perm
;
}
// throw an IllegalArgumentException if x is null
// (x can be of type Object[], double[], int[], ...)
private
static
void
validateNotNull
(
Object
x
)
{
if
(
x
==
null
)
{
throw
new
IllegalArgumentException
(
"argument is null"
);
}
}
// throw an exception unless 0 <= lo <= hi <= length
private
static
void
validateSubarrayIndices
(
int
lo
,
int
hi
,
int
length
)
{
if
(
lo
<
0
||
hi
>
length
||
lo
>
hi
)
{
throw
new
IllegalArgumentException
(
“subarray indices out of bounds: [”
+
lo
+
“, ”
+
hi
+
“)”
);
}
}
/**
* Unit tests the methods in this class.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
n
=
Integer
.
parseInt
(
args
[
0
]);
if
(
args
.
length
==
2
)
StdRandom
.
setSeed
(
Long
.
parseLong
(
args
[
1
]));
double
[]
probabilities
=
{
0.5
,
0.3
,
0.1
,
0.1
};
int
[]
frequencies
=
{
5
,
3
,
1
,
1
};
String
[]
a
=
“A B C D E F G”
.
split
(
” ”
);
StdOut
.
println
(
“seed = ”
+
StdRandom
.
getSeed
());
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
StdOut
.
printf
(
"%2d "
,
uniform
(
100
));
StdOut
.
printf
(
"%8.5f "
,
uniform
(
10.0
,
99.0
));
StdOut
.
printf
(
"%5b "
,
bernoulli
(
0.5
));
StdOut
.
printf
(
"%7.5f "
,
gaussian
(
9.0
,
0.2
));
StdOut
.
printf
(
"%1d "
,
discrete
(
probabilities
));
StdOut
.
printf
(
"%1d "
,
discrete
(
frequencies
));
StdOut
.
printf
(
"%11d "
,
uniform
(
100000000000L
));
StdRandom
.
shuffle
(
a
);
for
(
String
s
:
a
)
StdOut
.
print
(
s
);
StdOut
.
println
();
}
}
}
StdStats.java
StdStats.java
/******************************************************************************
* Compilation: javac StdStats.java
* Execution: java StdStats < input.txt
* Dependencies: StdOut.java
*
* Library of statistical functions.
*
* The test client reads an array of real numbers from standard
* input, and computes the minimum, mean, maximum, and
* standard deviation.
*
* The functions all throw a java.lang.IllegalArgumentException
* if the array passed in as an argument is null.
*
* The floating-point functions all return NaN if any input is NaN.
*
* Unlike Math.min() and Math.max(), the min() and max() functions
* do not differentiate between -0.0 and 0.0.
*
* % more tiny.txt
* 5
* 3.0 1.0 2.0 5.0 4.0
*
* % java StdStats < tiny.txt
* min 1.000
* mean 3.000
* max 5.000
* std dev 1.581
*
* Should these funtions use varargs instead of array arguments?
*
******************************************************************************/
/**
* The {
@code
StdStats} class provides static methods for computing
* statistics such as min, max, mean, sample standard deviation, and
* sample variance.
*
* For additional documentation, see
* Section 2.2 of
* Computer Science: An Interdisciplinary Approach
* by Robert Sedgewick and Kevin Wayne.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
final
class
StdStats
{
private
StdStats
()
{
}
/**
* Returns the maximum value in the specified array.
*
*
@param
a the array
*
@return
the maximum value in the array {
@code
a[]};
* {
@code
Double.NEGATIVE_INFINITY} if no such value
*/
public
static
double
max
(
double
[]
a
)
{
validateNotNull
(
a
);
double
max
=
Double
.
NEGATIVE_INFINITY
;
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
if
(
Double
.
isNaN
(
a
[
i
]))
return
Double
.
NaN
;
if
(
a
[
i
]
>
max
)
max
=
a
[
i
];
}
return
max
;
}
/**
* Returns the maximum value in the specified subarray.
*
*
@param
a the array
*
@param
lo the left endpoint of the subarray (inclusive)
*
@param
hi the right endpoint of the subarray (exclusive)
*
@return
the maximum value in the subarray {
@code
a[lo..hi)};
* {
@code
Double.NEGATIVE_INFINITY} if no such value
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*
@throws
IllegalArgumentException unless {
@code
(0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
public
static
double
max
(
double
[]
a
,
int
lo
,
int
hi
)
{
validateNotNull
(
a
);
validateSubarrayIndices
(
lo
,
hi
,
a
.
length
);
double
max
=
Double
.
NEGATIVE_INFINITY
;
for
(
int
i
=
lo
;
i
<
hi
;
i
++
)
{
if
(
Double
.
isNaN
(
a
[
i
]))
return
Double
.
NaN
;
if
(
a
[
i
]
>
max
)
max
=
a
[
i
];
}
return
max
;
}
/**
* Returns the maximum value in the specified array.
*
*
@param
a the array
*
@return
the maximum value in the array {
@code
a[]};
* {
@code
Integer.MIN_VALUE} if no such value
*/
public
static
int
max
(
int
[]
a
)
{
validateNotNull
(
a
);
int
max
=
Integer
.
MIN_VALUE
;
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
if
(
a
[
i
]
>
max
)
max
=
a
[
i
];
}
return
max
;
}
/**
* Returns the minimum value in the specified array.
*
*
@param
a the array
*
@return
the minimum value in the array {
@code
a[]};
* {
@code
Double.POSITIVE_INFINITY} if no such value
*/
public
static
double
min
(
double
[]
a
)
{
validateNotNull
(
a
);
double
min
=
Double
.
POSITIVE_INFINITY
;
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
if
(
Double
.
isNaN
(
a
[
i
]))
return
Double
.
NaN
;
if
(
a
[
i
]
<
min
)
min
=
a
[
i
];
}
return
min
;
}
/**
* Returns the minimum value in the specified subarray.
*
*
@param
a the array
*
@param
lo the left endpoint of the subarray (inclusive)
*
@param
hi the right endpoint of the subarray (exclusive)
*
@return
the maximum value in the subarray {
@code
a[lo..hi)};
* {
@code
Double.POSITIVE_INFINITY} if no such value
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*
@throws
IllegalArgumentException unless {
@code
(0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
public
static
double
min
(
double
[]
a
,
int
lo
,
int
hi
)
{
validateNotNull
(
a
);
validateSubarrayIndices
(
lo
,
hi
,
a
.
length
);
double
min
=
Double
.
POSITIVE_INFINITY
;
for
(
int
i
=
lo
;
i
<
hi
;
i
++
)
{
if
(
Double
.
isNaN
(
a
[
i
]))
return
Double
.
NaN
;
if
(
a
[
i
]
<
min
)
min
=
a
[
i
];
}
return
min
;
}
/**
* Returns the minimum value in the specified array.
*
*
@param
a the array
*
@return
the minimum value in the array {
@code
a[]};
* {
@code
Integer.MAX_VALUE} if no such value
*/
public
static
int
min
(
int
[]
a
)
{
validateNotNull
(
a
);
int
min
=
Integer
.
MAX_VALUE
;
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
if
(
a
[
i
]
<
min
)
min
=
a
[
i
];
}
return
min
;
}
/**
* Returns the average value in the specified array.
*
*
@param
a the array
*
@return
the average value in the array {
@code
a[]};
* {
@code
Double.NaN} if no such value
*/
public
static
double
mean
(
double
[]
a
)
{
validateNotNull
(
a
);
if
(
a
.
length
==
0
)
return
Double
.
NaN
;
double
sum
=
sum
(
a
);
return
sum
/
a
.
length
;
}
/**
* Returns the average value in the specified subarray.
*
*
@param
a the array
*
@param
lo the left endpoint of the subarray (inclusive)
*
@param
hi the right endpoint of the subarray (exclusive)
*
@return
the average value in the subarray {
@code
a[lo..hi)};
* {
@code
Double.NaN} if no such value
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*
@throws
IllegalArgumentException unless {
@code
(0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
public
static
double
mean
(
double
[]
a
,
int
lo
,
int
hi
)
{
validateNotNull
(
a
);
validateSubarrayIndices
(
lo
,
hi
,
a
.
length
);
int
length
=
hi
-
lo
;
if
(
length
==
0
)
return
Double
.
NaN
;
double
sum
=
sum
(
a
,
lo
,
hi
);
return
sum
/
length
;
}
/**
* Returns the average value in the specified array.
*
*
@param
a the array
*
@return
the average value in the array {
@code
a[]};
* {
@code
Double.NaN} if no such value
*/
public
static
double
mean
(
int
[]
a
)
{
validateNotNull
(
a
);
if
(
a
.
length
==
0
)
return
Double
.
NaN
;
int
sum
=
sum
(
a
);
return
1.0
*
sum
/
a
.
length
;
}
/**
* Returns the sample variance in the specified array.
*
*
@param
a the array
*
@return
the sample variance in the array {
@code
a[]};
* {
@code
Double.NaN} if no such value
*/
public
static
double
var
(
double
[]
a
)
{
validateNotNull
(
a
);
if
(
a
.
length
==
0
)
return
Double
.
NaN
;
double
avg
=
mean
(
a
);
double
sum
=
0.0
;
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
sum
+=
(
a
[
i
]
-
avg
)
*
(
a
[
i
]
-
avg
);
}
return
sum
/
(
a
.
length
-
1
);
}
/**
* Returns the sample variance in the specified subarray.
*
*
@param
a the array
*
@param
lo the left endpoint of the subarray (inclusive)
*
@param
hi the right endpoint of the subarray (exclusive)
*
@return
the sample variance in the subarray {
@code
a[lo..hi)};
* {
@code
Double.NaN} if no such value
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*
@throws
IllegalArgumentException unless {
@code
(0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
public
static
double
var
(
double
[]
a
,
int
lo
,
int
hi
)
{
validateNotNull
(
a
);
validateSubarrayIndices
(
lo
,
hi
,
a
.
length
);
int
length
=
hi
-
lo
;
if
(
length
==
0
)
return
Double
.
NaN
;
double
avg
=
mean
(
a
,
lo
,
hi
);
double
sum
=
0.0
;
for
(
int
i
=
lo
;
i
<
hi
;
i
++
)
{
sum
+=
(
a
[
i
]
-
avg
)
*
(
a
[
i
]
-
avg
);
}
return
sum
/
(
length
-
1
);
}
/**
* Returns the sample variance in the specified array.
*
*
@param
a the array
*
@return
the sample variance in the array {
@code
a[]};
* {
@code
Double.NaN} if no such value
*/
public
static
double
var
(
int
[]
a
)
{
validateNotNull
(
a
);
if
(
a
.
length
==
0
)
return
Double
.
NaN
;
double
avg
=
mean
(
a
);
double
sum
=
0.0
;
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
sum
+=
(
a
[
i
]
-
avg
)
*
(
a
[
i
]
-
avg
);
}
return
sum
/
(
a
.
length
-
1
);
}
/**
* Returns the population variance in the specified array.
*
*
@param
a the array
*
@return
the population variance in the array {
@code
a[]};
* {
@code
Double.NaN} if no such value
*/
public
static
double
varp
(
double
[]
a
)
{
validateNotNull
(
a
);
if
(
a
.
length
==
0
)
return
Double
.
NaN
;
double
avg
=
mean
(
a
);
double
sum
=
0.0
;
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
sum
+=
(
a
[
i
]
-
avg
)
*
(
a
[
i
]
-
avg
);
}
return
sum
/
a
.
length
;
}
/**
* Returns the population variance in the specified subarray.
*
*
@param
a the array
*
@param
lo the left endpoint of the subarray (inclusive)
*
@param
hi the right endpoint of the subarray (exclusive)
*
@return
the population variance in the subarray {
@code
a[lo..hi)};
* {
@code
Double.NaN} if no such value
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*
@throws
IllegalArgumentException unless {
@code
(0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
public
static
double
varp
(
double
[]
a
,
int
lo
,
int
hi
)
{
validateNotNull
(
a
);
validateSubarrayIndices
(
lo
,
hi
,
a
.
length
);
int
length
=
hi
-
lo
;
if
(
length
==
0
)
return
Double
.
NaN
;
double
avg
=
mean
(
a
,
lo
,
hi
);
double
sum
=
0.0
;
for
(
int
i
=
lo
;
i
<
hi
;
i
++
)
{
sum
+=
(
a
[
i
]
-
avg
)
*
(
a
[
i
]
-
avg
);
}
return
sum
/
length
;
}
/**
* Returns the sample standard deviation in the specified array.
*
*
@param
a the array
*
@return
the sample standard deviation in the array {
@code
a[]};
* {
@code
Double.NaN} if no such value
*/
public
static
double
stddev
(
double
[]
a
)
{
validateNotNull
(
a
);
return
Math
.
sqrt
(
var
(
a
));
}
/**
* Returns the sample standard deviation in the specified array.
*
*
@param
a the array
*
@return
the sample standard deviation in the array {
@code
a[]};
* {
@code
Double.NaN} if no such value
*/
public
static
double
stddev
(
int
[]
a
)
{
validateNotNull
(
a
);
return
Math
.
sqrt
(
var
(
a
));
}
/**
* Returns the sample standard deviation in the specified subarray.
*
*
@param
a the array
*
@param
lo the left endpoint of the subarray (inclusive)
*
@param
hi the right endpoint of the subarray (exclusive)
*
@return
the sample standard deviation in the subarray {
@code
a[lo..hi)};
* {
@code
Double.NaN} if no such value
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*
@throws
IllegalArgumentException unless {
@code
(0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
public
static
double
stddev
(
double
[]
a
,
int
lo
,
int
hi
)
{
validateNotNull
(
a
);
validateSubarrayIndices
(
lo
,
hi
,
a
.
length
);
return
Math
.
sqrt
(
var
(
a
,
lo
,
hi
));
}
/**
* Returns the population standard deviation in the specified array.
*
*
@param
a the array
*
@return
the population standard deviation in the array;
* {
@code
Double.NaN} if no such value
*/
public
static
double
stddevp
(
double
[]
a
)
{
validateNotNull
(
a
);
return
Math
.
sqrt
(
varp
(
a
));
}
/**
* Returns the population standard deviation in the specified subarray.
*
*
@param
a the array
*
@param
lo the left endpoint of the subarray (inclusive)
*
@param
hi the right endpoint of the subarray (exclusive)
*
@return
the population standard deviation in the subarray {
@code
a[lo..hi)};
* {
@code
Double.NaN} if no such value
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*
@throws
IllegalArgumentException unless {
@code
(0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
public
static
double
stddevp
(
double
[]
a
,
int
lo
,
int
hi
)
{
validateNotNull
(
a
);
validateSubarrayIndices
(
lo
,
hi
,
a
.
length
);
return
Math
.
sqrt
(
varp
(
a
,
lo
,
hi
));
}
/**
* Returns the sum of all values in the specified array.
*
*
@param
a the array
*
@return
the sum of all values in the array {
@code
a[]};
* {
@code
0.0} if no such value
*/
private
static
double
sum
(
double
[]
a
)
{
validateNotNull
(
a
);
double
sum
=
0.0
;
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
sum
+=
a
[
i
];
}
return
sum
;
}
/**
* Returns the sum of all values in the specified subarray.
*
*
@param
a the array
*
@param
lo the left endpoint of the subarray (inclusive)
*
@param
hi the right endpoint of the subarray (exclusive)
*
@return
the sum of all values in the subarray {
@code
a[lo..hi)};
* {
@code
0.0} if no such value
*
@throws
IllegalArgumentException if {
@code
a} is {
@code
null}
*
@throws
IllegalArgumentException unless {
@code
(0 <= lo) && (lo < hi) && (hi <= a.length)}
*/
private
static
double
sum
(
double
[]
a
,
int
lo
,
int
hi
)
{
validateNotNull
(
a
);
validateSubarrayIndices
(
lo
,
hi
,
a
.
length
);
double
sum
=
0.0
;
for
(
int
i
=
lo
;
i
<
hi
;
i
++
)
{
sum
+=
a
[
i
];
}
return
sum
;
}
/**
* Returns the sum of all values in the specified array.
*
*
@param
a the array
*
@return
the sum of all values in the array {
@code
a[]};
* {
@code
0.0} if no such value
*/
private
static
int
sum
(
int
[]
a
)
{
validateNotNull
(
a
);
int
sum
=
0
;
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
)
{
sum
+=
a
[
i
];
}
return
sum
;
}
/**
* Plots the points (0, a0), (1, a1), …,
* (n-1, an-1) to standard draw.
*
*
@param
a the array of values
*/
public
static
void
plotPoints
(
double
[]
a
)
{
validateNotNull
(
a
);
int
n
=
a
.
length
;
StdDraw
.
setXscale
(
–
1
,
n
);
StdDraw
.
setPenRadius
(
1.0
/
(
3.0
*
n
));
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
StdDraw
.
point
(
i
,
a
[
i
]);
}
}
/**
* Plots the line segments connecting
* (i, ai) to
* (i+1, ai+1) for
* each i to standard draw.
*
*
@param
a the array of values
*/
public
static
void
plotLines
(
double
[]
a
)
{
validateNotNull
(
a
);
int
n
=
a
.
length
;
StdDraw
.
setXscale
(
–
1
,
n
);
StdDraw
.
setPenRadius
();
for
(
int
i
=
1
;
i
<
n
;
i
++
)
{
StdDraw
.
line
(
i
-
1
,
a
[
i
-
1
],
i
,
a
[
i
]);
}
}
/**
* Plots bars from (0, ai) to
* (ai) for each i
* to standard draw.
*
*
@param
a the array of values
*/
public
static
void
plotBars
(
double
[]
a
)
{
validateNotNull
(
a
);
int
n
=
a
.
length
;
StdDraw
.
setXscale
(
–
1
,
n
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
StdDraw
.
filledRectangle
(
i
,
a
[
i
]
/
2
,
0.25
,
a
[
i
]
/
2
);
}
}
// throw an IllegalArgumentException if x is null
// (x is either of type double[] or int[])
private
static
void
validateNotNull
(
Object
x
)
{
if
(
x
==
null
)
throw
new
IllegalArgumentException
(
"argument is null"
);
}
// throw an exception unless 0 <= lo <= hi <= length
private
static
void
validateSubarrayIndices
(
int
lo
,
int
hi
,
int
length
)
{
if
(
lo
<
0
||
hi
>
length
||
lo
>
hi
)
throw
new
IllegalArgumentException
(
“subarray indices out of bounds: [”
+
lo
+
“, ”
+
hi
+
“)”
);
}
/**
* Unit tests {
@code
StdStats}.
* Convert command-line arguments to array of doubles and call various methods.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
double
[]
a
=
StdArrayIO
.
readDouble1D
();
StdOut
.
printf
(
” min %10.3f\n”
,
min
(
a
));
StdOut
.
printf
(
” mean %10.3f\n”
,
mean
(
a
));
StdOut
.
printf
(
” max %10.3f\n”
,
max
(
a
));
StdOut
.
printf
(
” stddev %10.3f\n”
,
stddev
(
a
));
StdOut
.
printf
(
” var %10.3f\n”
,
var
(
a
));
StdOut
.
printf
(
” stddevp %10.3f\n”
,
stddevp
(
a
));
StdOut
.
printf
(
” varp %10.3f\n”
,
varp
(
a
));
}
}
StopwatchCPU.java
StopwatchCPU.java
/******************************************************************************
* Compilation: javac StopwatchCPU.java
* Execution: none
* Dependencies: none
*
* A version of Stopwatch.java that measures CPU time on a single
* core or processor (instead of wall clock time).
*
******************************************************************************/
import
java
.
lang
.
management
.
ThreadMXBean
;
import
java
.
lang
.
management
.
ManagementFactory
;
/**
* The {
@code
StopwatchCPU} data type is for measuring
* the CPU time used during a programming task.
*
* See {
@link
Stopwatch} for a version that measures wall-clock time
* (the real time that elapses).
*
*
@author
Josh Hug
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
StopwatchCPU
{
private
static
final
double
NANOSECONDS_PER_SECOND
=
1000000000
;
private
final
ThreadMXBean
threadTimer
;
private
final
long
start
;
/**
* Initializes a new stopwatch.
*/
public
StopwatchCPU
()
{
threadTimer
=
ManagementFactory
.
getThreadMXBean
();
start
=
threadTimer
.
getCurrentThreadCpuTime
();
}
/**
* Returns the elapsed CPU time (in seconds) since the stopwatch was created.
*
*
@return
elapsed CPU time (in seconds) since the stopwatch was created
*/
public
double
elapsedTime
()
{
long
now
=
threadTimer
.
getCurrentThreadCpuTime
();
return
(
now
–
start
)
/
NANOSECONDS_PER_SECOND
;
}
}
Stopwatch.java
Stopwatch.java
/******************************************************************************
* Compilation: javac Stopwatch.java
* Execution: java Stopwatch n
* Dependencies: none
*
* A utility class to measure the running time (wall clock) of a program.
*
* % java8 Stopwatch 100000000
* 6.666667e+11 0.5820 seconds
* 6.666667e+11 8.4530 seconds
*
******************************************************************************/
/**
* The {
@code
Stopwatch} data type is for measuring
* the time that elapses between the start and end of a
* programming task (wall-clock time).
*
* See {
@link
StopwatchCPU} for a version that measures CPU time.
*
*
@author
Robert Sedgewick
*
@author
Kevin Wayne
*/
public
class
Stopwatch
{
private
final
long
start
;
/**
* Initializes a new stopwatch.
*/
public
Stopwatch
()
{
start
=
System
.
currentTimeMillis
();
}
/**
* Returns the elapsed CPU time (in seconds) since the stopwatch was created.
*
*
@return
elapsed CPU time (in seconds) since the stopwatch was created
*/
public
double
elapsedTime
()
{
long
now
=
System
.
currentTimeMillis
();
return
(
now
–
start
)
/
1000.0
;
}
/**
* Unit tests the {
@code
Stopwatch} data type.
* Takes a command-line argument {
@code
n} and computes the
* sum of the square roots of the first {
@code
n} positive integers,
* first using {
@code
Math.sqrt()}, then using {
@code
Math.pow()}.
* It prints to standard output the sum and the amount of time to
* compute the sum. Note that the discrete sum can be approximated by
* an integral – the sum should be approximately 2/3 * (n^(3/2) – 1).
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
int
n
=
Integer
.
parseInt
(
args
[
0
]);
// sum of square roots of integers from 1 to n using Math.sqrt(x).
Stopwatch
timer1
=
new
Stopwatch
();
double
sum1
=
0.0
;
for
(
int
i
=
1
;
i
<=
n
;
i
++
)
{
sum1
+=
Math
.
sqrt
(
i
);
}
double
time1
=
timer1
.
elapsedTime
();
StdOut
.
printf
(
"%e (%.2f seconds)\n"
,
sum1
,
time1
);
// sum of square roots of integers from 1 to n using Math.pow(x, 0.5).
Stopwatch
timer2
=
new
Stopwatch
();
double
sum2
=
0.0
;
for
(
int
i
=
1
;
i
<=
n
;
i
++
)
{
sum2
+=
Math
.
pow
(
i
,
0.5
);
}
double
time2
=
timer2
.
elapsedTime
();
StdOut
.
printf
(
"%e (%.2f seconds)\n"
,
sum2
,
time2
);
}
}
TestIntroCS.java
TestIntroCS.java
/******************************************************************************
* Compilation: javac-introcs TestIntroCS.java
* Execution: java-introcs TestIntroCS n
*
* Play chaos game to produce Barnsley's fern.
* This program is intended to test that stdlib.jar is properly installed.
*
* % java-introcs TestIntroCS 10000
*
******************************************************************************/
public
class
TestIntroCS
{
public
static
void
main
(
String
[]
args
)
{
int
n
=
10000
;
// number of points to draw (default 10000)
if
(
args
.
length
==
1
)
{
n
=
Integer
.
parseInt
(
args
[
0
]);
}
StdDraw
.
setScale
(
-
0.1
,
1.1
);
// leave a 10% border
StdDraw
.
clear
(
StdDraw
.
BOOK_LIGHT_BLUE
);
// background color
StdDraw
.
setPenColor
(
0
,
114
,
0
);
// a shade of green
// starting point
double
x
=
0.5
;
double
y
=
0.0
;
// repeated choose one of four update rules at random
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
double
tempx
,
tempy
;
double
r
=
StdRandom
.
uniform
(
0.0
,
1.0
);
// stem
if
(
r
<=
0.01
)
{
tempx
=
0.50
;
tempy
=
0.16
*
y
;
}
// largest left-hand leaflet
else
if
(
r
<=
0.08
)
{
tempx
=
0.20
*
x
-
0.26
*
y
+
0.400
;
tempy
=
0.23
*
x
+
0.22
*
y
-
0.045
;
}
// largest right-hand leaflet
else
if
(
r
<=
0.15
)
{
tempx
=
-
0.15
*
x
+
0.28
*
y
+
0.575
;
tempy
=
0.26
*
x
+
0.24
*
y
-
0.086
;
}
// successively smaller leaflets
else
{
tempx
=
0.85
*
x
+
0.04
*
y
+
0.075
;
tempy
=
-
0.04
*
x
+
0.85
*
y
+
0.180
;
}
// update (x, y) and draw point
x
=
tempx
;
y
=
tempy
;
StdDraw
.
point
(
x
,
y
);
}
}
}
UnicodeTest.java
UnicodeTest.java
/******************************************************************************
* Compilation: javac-introcs UnicodeTest.java
* Execution: java-introcs UnicodeTest
* Dependencies: StdOut.java
*
* This programs prints out all of the Unicode characters in the basic
* multilingual plane (U+0000 to U+FFFF) in a table. It skips the
* following types of characters:
* -
* - control characters
* - modifier symbols
* - non-spacing marks
* - Unicode formatting commands
* - reserved for surrogate pairs
* - reserved for private use
*
*
* % java-introcs UnicodeTest
* U+0020 ! " # $ % & ' ( ) * + , - . /
* U+0030 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
* U+0040 @ A B C D E F G H I J K L M N O
* U+0050 P Q R S T U V W X Y Z [ \ ] _
* U+0060 a b c d e f g h i j k l m n o
* U+0070 p q r s t u v w x y z { | } ~
* U+00A0 ¡ ¢ £ ¤ ¥ ¦ § © ª « ¬ ®
* U+00B0 ° ± ² ³ µ ¶ · ¹ º » ¼ ½ ¾ ¿
* U+00C0 À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï
* U+00D0 Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß
* U+00E0 à á â ã ä å æ ç è é ê ë ì í î ï
* U+00F0 ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ
* U+0100 Ā ā Ă ă Ą ą Ć ć Ĉ ĉ Ċ ċ Č č Ď ď
* …
*
* Depending on your system setup and font, not all of the Unicode
* characters may display properly.
*
* Quirks: when printing certain Hebrew or Arabic characters, the
* table may print right-to-left instead of left-to-right.
*
* For a description of Unicode terminology, see:
* http://docs.oracle.com/javase/tutorial/i18n/text/terminology.html
*
* For the Character API, see:
* http://docs.oracle.com/javase/7/docs/api/java/lang/Character.html
*
* To see what each Unicode character should look like, see:
* http://www.fileformat.info/info/unicode/index.htm
* http://www.fileformat.info/info/unicode/char/05D0/index.htm
*
*
******************************************************************************/
public
class
UnicodeTest
{
// number of Unicode characters to display per line
private
static
final
int
CHARS_PER_LINE
=
16
;
// number of Unicode characters to display (basic multilingual plane)
private
static
final
int
MAX_CHAR
=
65536
;
// do not instantiate
private
UnicodeTest
()
{
}
// Returns a string representation of the given codePoint, or a single
// space if the codePoint should not be suppressed when printing.
private
static
String
toString
(
int
codePoint
)
{
if
(
!
Character
.
isDefined
(
codePoint
))
return
” ”
;
if
(
Character
.
isISOControl
(
codePoint
))
return
” ”
;
if
(
Character
.
isWhitespace
(
codePoint
))
return
” ”
;
// if (Character.isSurrogate(codePoint) return ” “; // Java 1.7+ only
if
(
Character
.
isLowSurrogate
((
char
)
codePoint
))
return
” ”
;
// Java 1.5+
if
(
Character
.
isHighSurrogate
((
char
)
codePoint
))
return
” ”
;
// Java 1.5+
switch
(
Character
.
getType
(
codePoint
))
{
case
Character
.
MODIFIER_SYMBOL
:
return
” ”
;
case
Character
.
CONTROL
:
return
” ”
;
case
Character
.
MODIFIER_LETTER
:
return
” ”
;
case
Character
.
NON_SPACING_MARK
:
return
” ”
;
case
Character
.
FORMAT
:
return
” ”
;
case
Character
.
PRIVATE_USE
:
return
” ”
;
default
:
return
new
String
(
Character
.
toChars
(
codePoint
));
}
}
/**
* Prints Unicode characters to standard output.
*
*
@param
args the command-line arguments
*/
public
static
void
main
(
String
[]
args
)
{
for
(
int
line
=
0
;
line
<
2
*
Character
.
MAX_VALUE
/
CHARS_PER_LINE
;
line
++
)
{
StringBuilder
buffer
=
new
StringBuilder
();
for
(
int
i
=
0
;
i
<
CHARS_PER_LINE
;
i
++
)
{
int
codePoint
=
CHARS_PER_LINE
*
line
+
i
;
buffer
.
append
(
toString
(
codePoint
)
+
" "
);
}
String
output
=
buffer
.
toString
();
if
(
!
output
.
trim
().
equals
(
""
))
{
// U+202D is the Unicode override to force left-to-right direction
// but doesn't seem to work with Unix more
StdOut
.
printf
(
"U+%04X %s\n"
,
16
*
line
,
output
);
}
}
}
}
BinaryIn.class
public final synchronized class BinaryIn {
private static final int EOF = -1;
private java.io.BufferedInputStream in;
private int buffer;
private int n;
public void BinaryIn();
public void BinaryIn(java.io.InputStream);
public void BinaryIn(java.net.Socket);
public void BinaryIn(java.net.URL);
public void BinaryIn(String);
private void fillBuffer();
public boolean exists();
public boolean isEmpty();
public boolean readBoolean();
public char readChar();
public char readChar(int);
public String readString();
public short readShort();
public int readInt();
public int readInt(int);
public long readLong();
public double readDouble();
public float readFloat();
public byte readByte();
public static void main(String[]);
}
BinaryOut.class
public final synchronized class BinaryOut {
private java.io.BufferedOutputStream out;
private int buffer;
private int n;
public void BinaryOut();
public void BinaryOut(java.io.OutputStream);
public void BinaryOut(String);
public void BinaryOut(java.net.Socket);
private void writeBit(boolean);
private void writeByte(int);
private void clearBuffer();
public void flush();
public void close();
public void write(boolean);
public void write(byte);
public void write(int);
public void write(int, int);
public void write(double);
public void write(long);
public void write(float);
public void write(short);
public void write(char);
public void write(char, int);
public void write(String);
public void write(String, int);
public static void main(String[]);
static void
}
BinaryStdIn.class
public final synchronized class BinaryStdIn {
private static final int EOF = -1;
private static java.io.BufferedInputStream in;
private static int buffer;
private static int n;
private static boolean isInitialized;
private void BinaryStdIn();
private static void initialize();
private static void fillBuffer();
public static void close();
public static boolean isEmpty();
public static boolean readBoolean();
public static char readChar();
public static char readChar(int);
public static String readString();
public static short readShort();
public static int readInt();
public static int readInt(int);
public static long readLong();
public static double readDouble();
public static float readFloat();
public static byte readByte();
public static void main(String[]);
}
BinaryStdOut.class
public final synchronized class BinaryStdOut {
private static java.io.BufferedOutputStream out;
private static int buffer;
private static int n;
private static boolean isInitialized;
private void BinaryStdOut();
private static void initialize();
private static void writeBit(boolean);
private static void writeByte(int);
private static void clearBuffer();
public static void flush();
public static void close();
public static void write(boolean);
public static void write(byte);
public static void write(int);
public static void write(int, int);
public static void write(double);
public static void write(long);
public static void write(float);
public static void write(short);
public static void write(char);
public static void write(char, int);
public static void write(String);
public static void write(String, int);
public static void main(String[]);
static void
}
Draw.class
public final synchronized class Draw implements java.awt.event.ActionListener, java.awt.event.MouseListener, java.awt.event.MouseMotionListener, java.awt.event.KeyListener {
public static final java.awt.Color BLACK;
public static final java.awt.Color BLUE;
public static final java.awt.Color CYAN;
public static final java.awt.Color DARK_GRAY;
public static final java.awt.Color GRAY;
public static final java.awt.Color GREEN;
public static final java.awt.Color LIGHT_GRAY;
public static final java.awt.Color MAGENTA;
public static final java.awt.Color ORANGE;
public static final java.awt.Color PINK;
public static final java.awt.Color RED;
public static final java.awt.Color WHITE;
public static final java.awt.Color YELLOW;
public static final java.awt.Color BOOK_BLUE;
public static final java.awt.Color BOOK_LIGHT_BLUE;
public static final java.awt.Color BOOK_RED;
public static final java.awt.Color PRINCETON_ORANGE;
private static final java.awt.Color DEFAULT_PEN_COLOR;
private static final java.awt.Color DEFAULT_CLEAR_COLOR;
private static final double BORDER = 0.0;
private static final double DEFAULT_XMIN = 0.0;
private static final double DEFAULT_XMAX = 1.0;
private static final double DEFAULT_YMIN = 0.0;
private static final double DEFAULT_YMAX = 1.0;
private static final int DEFAULT_SIZE = 512;
private static final double DEFAULT_PEN_RADIUS = 0.002;
private static final java.awt.Font DEFAULT_FONT;
private java.awt.Color penColor;
private int width;
private int height;
private double penRadius;
private boolean defer;
private double xmin;
private double ymin;
private double xmax;
private double ymax;
private String name;
private final Object mouseLock;
private final Object keyLock;
private java.awt.Font font;
private javax.swing.JLabel draw;
private java.awt.image.BufferedImage offscreenImage;
private java.awt.image.BufferedImage onscreenImage;
private java.awt.Graphics2D offscreen;
private java.awt.Graphics2D onscreen;
private javax.swing.JFrame frame;
private boolean isMousePressed;
private double mouseX;
private double mouseY;
private final java.util.LinkedList keysTyped;
private final java.util.TreeSet keysDown;
private final java.util.ArrayList listeners;
public void Draw(String);
public void Draw();
private void init();
public void setLocationOnScreen(int, int);
public void setDefaultCloseOperation(int);
public void setCanvasSize(int, int);
private javax.swing.JMenuBar createMenuBar();
private static void validate(double, String);
private static void validateNonnegative(double, String);
private static void validateNotNull(Object, String);
public void setXscale();
public void setYscale();
public void setXscale(double, double);
public void setYscale(double, double);
private double scaleX(double);
private double scaleY(double);
private double factorX(double);
private double factorY(double);
private double userX(double);
private double userY(double);
public void clear();
public void clear(java.awt.Color);
public double getPenRadius();
public void setPenRadius();
public void setPenRadius(double);
public java.awt.Color getPenColor();
public void setPenColor();
public void setPenColor(java.awt.Color);
public void setPenColor(int, int, int);
public void xorOn();
public void xorOff();
public javax.swing.JLabel getJLabel();
public java.awt.Font getFont();
public void setFont();
public void setFont(java.awt.Font);
public void line(double, double, double, double);
private void pixel(double, double);
public void point(double, double);
public void circle(double, double, double);
public void filledCircle(double, double, double);
public void ellipse(double, double, double, double);
public void filledEllipse(double, double, double, double);
public void arc(double, double, double, double, double);
public void square(double, double, double);
public void filledSquare(double, double, double);
public void rectangle(double, double, double, double);
public void filledRectangle(double, double, double, double);
public void polygon(double[], double[]);
public void filledPolygon(double[], double[]);
private static java.awt.Image getImage(String);
public void picture(double, double, String);
public void picture(double, double, String, double);
public void picture(double, double, String, double, double);
public void picture(double, double, String, double, double, double);
public void text(double, double, String);
public void text(double, double, String, double);
public void textLeft(double, double, String);
public void textRight(double, double, String);
public void show(int);
public void pause(int);
public void show();
private void draw();
public void enableDoubleBuffering();
public void disableDoubleBuffering();
public void save(String);
public void actionPerformed(java.awt.event.ActionEvent);
public void addListener(DrawListener);
public boolean isMousePressed();
public boolean mousePressed();
public double mouseX();
public double mouseY();
public void mouseEntered(java.awt.event.MouseEvent);
public void mouseExited(java.awt.event.MouseEvent);
public void mousePressed(java.awt.event.MouseEvent);
public void mouseReleased(java.awt.event.MouseEvent);
public void mouseClicked(java.awt.event.MouseEvent);
public void mouseDragged(java.awt.event.MouseEvent);
public void mouseMoved(java.awt.event.MouseEvent);
public boolean hasNextKeyTyped();
public char nextKeyTyped();
public boolean isKeyPressed(int);
public void keyTyped(java.awt.event.KeyEvent);
public void keyPressed(java.awt.event.KeyEvent);
public void keyReleased(java.awt.event.KeyEvent);
public static void main(String[]);
static void
}
DrawListener.class
public abstract interface DrawListener {
public abstract void mousePressed(double, double);
public abstract void mouseDragged(double, double);
public abstract void mouseReleased(double, double);
public abstract void mouseClicked(double, double);
public abstract void keyTyped(char);
public abstract void keyPressed(int);
public abstract void keyReleased(int);
}
Draw$RetinaImageIcon.class
synchronized class Draw$RetinaImageIcon extends javax.swing.ImageIcon {
public void Draw$RetinaImageIcon(java.awt.Image);
public int getIconWidth();
public int getIconHeight();
public synchronized void paintIcon(java.awt.Component, java.awt.Graphics, int, int);
}
GrayscalePicture.class
public final synchronized class GrayscalePicture implements java.awt.event.ActionListener {
private java.awt.image.BufferedImage image;
private javax.swing.JFrame frame;
private String filename;
private boolean isOriginUpperLeft;
private final int width;
private final int height;
public void GrayscalePicture(int, int);
public void GrayscalePicture(GrayscalePicture);
public void GrayscalePicture(String);
private static java.awt.Color toGray(java.awt.Color);
public javax.swing.JLabel getJLabel();
public void setOriginUpperLeft();
public void setOriginLowerLeft();
public void show();
public int height();
public int width();
private void validateRowIndex(int);
private void validateColumnIndex(int);
private void validateGrayscaleValue(int);
public java.awt.Color get(int, int);
public int getGrayscale(int, int);
public void set(int, int, java.awt.Color);
public void setGrayscale(int, int, int);
public boolean equals(Object);
public String toString();
public int hashCode();
public void save(String);
public void save(java.io.File);
public void actionPerformed(java.awt.event.ActionEvent);
public static void main(String[]);
}
In.class
public final synchronized class In {
private static final String CHARSET_NAME = UTF-8;
private static final java.util.Locale LOCALE;
private static final java.util.regex.Pattern WHITESPACE_PATTERN;
private static final java.util.regex.Pattern EMPTY_PATTERN;
private static final java.util.regex.Pattern EVERYTHING_PATTERN;
private java.util.Scanner scanner;
public void In();
public void In(java.net.Socket);
public void In(java.net.URL);
public void In(java.io.File);
public void In(String);
public void In(java.util.Scanner);
public boolean exists();
public boolean isEmpty();
public boolean hasNextLine();
public boolean hasNextChar();
public String readLine();
public char readChar();
public String readAll();
public String readString();
public int readInt();
public double readDouble();
public float readFloat();
public long readLong();
public short readShort();
public byte readByte();
public boolean readBoolean();
public String[] readAllStrings();
public String[] readAllLines();
public int[] readAllInts();
public long[] readAllLongs();
public double[] readAllDoubles();
public void close();
public static int[] readInts(String);
public static double[] readDoubles(String);
public static String[] readStrings(String);
public static int[] readInts();
public static double[] readDoubles();
public static String[] readStrings();
public static void main(String[]);
static void
}
Out.class
public synchronized class Out {
private static final String CHARSET_NAME = UTF-8;
private static final java.util.Locale LOCALE;
private java.io.PrintWriter out;
public void Out(java.io.OutputStream);
public void Out();
public void Out(java.net.Socket);
public void Out(String);
public void close();
public void println();
public void println(Object);
public void println(boolean);
public void println(char);
public void println(double);
public void println(float);
public void println(int);
public void println(long);
public void println(byte);
public void print();
public void print(Object);
public void print(boolean);
public void print(char);
public void print(double);
public void print(float);
public void print(int);
public void print(long);
public void print(byte);
public transient void printf(String, Object[]);
public transient void printf(java.util.Locale, String, Object[]);
public static void main(String[]);
static void
}
Picture.class
public final synchronized class Picture implements java.awt.event.ActionListener {
private java.awt.image.BufferedImage image;
private javax.swing.JFrame frame;
private String filename;
private boolean isOriginUpperLeft;
private final int width;
private final int height;
public void Picture(int, int);
public void Picture(Picture);
public void Picture(String);
public void Picture(java.io.File);
public javax.swing.JLabel getJLabel();
public void setOriginUpperLeft();
public void setOriginLowerLeft();
public void show();
public int height();
public int width();
private void validateRowIndex(int);
private void validateColumnIndex(int);
public java.awt.Color get(int, int);
public int getRGB(int, int);
public void set(int, int, java.awt.Color);
public void setRGB(int, int, int);
public boolean equals(Object);
public String toString();
public int hashCode();
public void save(String);
public void save(java.io.File);
public void actionPerformed(java.awt.event.ActionEvent);
public static void main(String[]);
}
PlayMusic$1.class
final synchronized class PlayMusic$1 implements Runnable {
void PlayMusic$1(String);
public void run();
}
PlayMusic.class
public synchronized class PlayMusic {
public void PlayMusic();
private static void playApplet(String);
public static synchronized void play(String);
private static void stream(String);
public static void main(String[]);
}
StdArrayIO.class
public synchronized class StdArrayIO {
private void StdArrayIO();
public static double[] readDouble1D();
public static void print(double[]);
public static double[][] readDouble2D();
public static void print(double[][]);
public static int[] readInt1D();
public static void print(int[]);
public static int[][] readInt2D();
public static void print(int[][]);
public static boolean[] readBoolean1D();
public static void print(boolean[]);
public static boolean[][] readBoolean2D();
public static void print(boolean[][]);
public static void main(String[]);
}
StdAudio$1.class
final synchronized class StdAudio$1 implements Runnable {
void StdAudio$1(String);
public void run();
}
StdAudio$2.class
final synchronized class StdAudio$2 implements Runnable {
void StdAudio$2();
public void run();
}
StdAudio.class
public final synchronized class StdAudio {
public static final int SAMPLE_RATE = 44100;
private static final int BYTES_PER_SAMPLE = 2;
private static final int BITS_PER_SAMPLE = 16;
private static final double MAX_16_BIT = 32768.0;
private static final int SAMPLE_BUFFER_SIZE = 4096;
private static final int MONO = 1;
private static final int STEREO = 2;
private static final boolean LITTLE_ENDIAN = 0;
private static final boolean BIG_ENDIAN = 1;
private static final boolean SIGNED = 1;
private static final boolean UNSIGNED = 0;
private static javax.sound.sampled.SourceDataLine line;
private static byte[] buffer;
private static int bufferSize;
private void StdAudio();
private static void init();
private static javax.sound.sampled.AudioInputStream getAudioInputStreamFromFile(String);
public static void close();
public static void play(double);
public static void play(double[]);
public static double[] read(String);
public static void save(String, double[]);
public static synchronized void play(String);
private static void stream(javax.sound.sampled.AudioInputStream);
public static synchronized void loop(String);
private static double[] note(double, double, double);
public static void main(String[]);
static void
}
StdDraw.class
public final synchronized class StdDraw implements java.awt.event.ActionListener, java.awt.event.MouseListener, java.awt.event.MouseMotionListener, java.awt.event.KeyListener {
public static final java.awt.Color BLACK;
public static final java.awt.Color BLUE;
public static final java.awt.Color CYAN;
public static final java.awt.Color DARK_GRAY;
public static final java.awt.Color GRAY;
public static final java.awt.Color GREEN;
public static final java.awt.Color LIGHT_GRAY;
public static final java.awt.Color MAGENTA;
public static final java.awt.Color ORANGE;
public static final java.awt.Color PINK;
public static final java.awt.Color RED;
public static final java.awt.Color WHITE;
public static final java.awt.Color YELLOW;
public static final java.awt.Color BOOK_BLUE;
public static final java.awt.Color BOOK_LIGHT_BLUE;
public static final java.awt.Color BOOK_RED;
public static final java.awt.Color PRINCETON_ORANGE;
private static final java.awt.Color DEFAULT_PEN_COLOR;
private static final java.awt.Color DEFAULT_CLEAR_COLOR;
private static java.awt.Color penColor;
private static final int DEFAULT_SIZE = 512;
private static int width;
private static int height;
private static final double DEFAULT_PEN_RADIUS = 0.002;
private static double penRadius;
private static boolean defer;
private static final double BORDER = 0.0;
private static final double DEFAULT_XMIN = 0.0;
private static final double DEFAULT_XMAX = 1.0;
private static final double DEFAULT_YMIN = 0.0;
private static final double DEFAULT_YMAX = 1.0;
private static double xmin;
private static double ymin;
private static double xmax;
private static double ymax;
private static Object mouseLock;
private static Object keyLock;
private static final java.awt.Font DEFAULT_FONT;
private static java.awt.Font font;
private static java.awt.image.BufferedImage offscreenImage;
private static java.awt.image.BufferedImage onscreenImage;
private static java.awt.Graphics2D offscreen;
private static java.awt.Graphics2D onscreen;
private static StdDraw std;
private static javax.swing.JFrame frame;
private static boolean isMousePressed;
private static double mouseX;
private static double mouseY;
private static java.util.LinkedList keysTyped;
private static java.util.TreeSet keysDown;
private void StdDraw();
public static void setCanvasSize();
public static void setCanvasSize(int, int);
private static void init();
private static javax.swing.JMenuBar createMenuBar();
private static void validate(double, String);
private static void validateNonnegative(double, String);
private static void validateNotNull(Object, String);
public static void setXscale();
public static void setYscale();
public static void setScale();
public static void setXscale(double, double);
public static void setYscale(double, double);
public static void setScale(double, double);
private static double scaleX(double);
private static double scaleY(double);
private static double factorX(double);
private static double factorY(double);
private static double userX(double);
private static double userY(double);
public static void clear();
public static void clear(java.awt.Color);
public static double getPenRadius();
public static void setPenRadius();
public static void setPenRadius(double);
public static java.awt.Color getPenColor();
public static void setPenColor();
public static void setPenColor(java.awt.Color);
public static void setPenColor(int, int, int);
public static java.awt.Font getFont();
public static void setFont();
public static void setFont(java.awt.Font);
public static void line(double, double, double, double);
private static void pixel(double, double);
public static void point(double, double);
public static void circle(double, double, double);
public static void filledCircle(double, double, double);
public static void ellipse(double, double, double, double);
public static void filledEllipse(double, double, double, double);
public static void arc(double, double, double, double, double);
public static void square(double, double, double);
public static void filledSquare(double, double, double);
public static void rectangle(double, double, double, double);
public static void filledRectangle(double, double, double, double);
public static void polygon(double[], double[]);
public static void filledPolygon(double[], double[]);
private static java.awt.Image getImage(String);
public static void picture(double, double, String);
public static void picture(double, double, String, double);
public static void picture(double, double, String, double, double);
public static void picture(double, double, String, double, double, double);
public static void text(double, double, String);
public static void text(double, double, String, double);
public static void textLeft(double, double, String);
public static void textRight(double, double, String);
public static void show(int);
public static void pause(int);
public static void show();
private static void draw();
public static void enableDoubleBuffering();
public static void disableDoubleBuffering();
public static void save(String);
public void actionPerformed(java.awt.event.ActionEvent);
public static boolean isMousePressed();
public static boolean mousePressed();
public static double mouseX();
public static double mouseY();
public void mouseClicked(java.awt.event.MouseEvent);
public void mouseEntered(java.awt.event.MouseEvent);
public void mouseExited(java.awt.event.MouseEvent);
public void mousePressed(java.awt.event.MouseEvent);
public void mouseReleased(java.awt.event.MouseEvent);
public void mouseDragged(java.awt.event.MouseEvent);
public void mouseMoved(java.awt.event.MouseEvent);
public static boolean hasNextKeyTyped();
public static char nextKeyTyped();
public static boolean isKeyPressed(int);
public void keyTyped(java.awt.event.KeyEvent);
public void keyPressed(java.awt.event.KeyEvent);
public void keyReleased(java.awt.event.KeyEvent);
public static void main(String[]);
static void
}
StdDraw$RetinaImageIcon.class
synchronized class StdDraw$RetinaImageIcon extends javax.swing.ImageIcon {
public void StdDraw$RetinaImageIcon(java.awt.Image);
public int getIconWidth();
public int getIconHeight();
public synchronized void paintIcon(java.awt.Component, java.awt.Graphics, int, int);
}
StdIn.class
public final synchronized class StdIn {
private static final String CHARSET_NAME = UTF-8;
private static final java.util.Locale LOCALE;
private static final java.util.regex.Pattern WHITESPACE_PATTERN;
private static final java.util.regex.Pattern EMPTY_PATTERN;
private static final java.util.regex.Pattern EVERYTHING_PATTERN;
private static java.util.Scanner scanner;
private void StdIn();
public static boolean isEmpty();
public static boolean hasNextLine();
public static boolean hasNextChar();
public static String readLine();
public static char readChar();
public static String readAll();
public static String readString();
public static int readInt();
public static double readDouble();
public static float readFloat();
public static long readLong();
public static short readShort();
public static byte readByte();
public static boolean readBoolean();
public static String[] readAllStrings();
public static String[] readAllLines();
public static int[] readAllInts();
public static long[] readAllLongs();
public static double[] readAllDoubles();
private static void resync();
private static void setScanner(java.util.Scanner);
public static int[] readInts();
public static double[] readDoubles();
public static String[] readStrings();
public static void main(String[]);
static void
}
StdInTest.class
public synchronized class StdInTest {
private static boolean testStdIn;
private static reflect.Method resyncMethod;
private static int testCount;
public void StdInTest();
public static Object escape(Object);
public static boolean canResync();
public static void test(String, Object[][]);
public static void test(String, Object[][], boolean);
public static void main(String[]);
static void
}
StdOut.class
public final synchronized class StdOut {
private static final String CHARSET_NAME = UTF-8;
private static final java.util.Locale LOCALE;
private static java.io.PrintWriter out;
private void StdOut();
public static void println();
public static void println(Object);
public static void println(boolean);
public static void println(char);
public static void println(double);
public static void println(float);
public static void println(int);
public static void println(long);
public static void println(short);
public static void println(byte);
public static void print();
public static void print(Object);
public static void print(boolean);
public static void print(char);
public static void print(double);
public static void print(float);
public static void print(int);
public static void print(long);
public static void print(short);
public static void print(byte);
public static transient void printf(String, Object[]);
public static transient void printf(java.util.Locale, String, Object[]);
public static void main(String[]);
static void
}
StdRandom.class
public final synchronized class StdRandom {
private static java.util.Random random;
private static long seed;
private void StdRandom();
public static void setSeed(long);
public static long getSeed();
public static double uniform();
public static int uniform(int);
public static long uniform(long);
public static double random();
public static int uniform(int, int);
public static double uniform(double, double);
public static boolean bernoulli(double);
public static boolean bernoulli();
public static double gaussian();
public static double gaussian(double, double);
public static int geometric(double);
public static int poisson(double);
public static double pareto();
public static double pareto(double);
public static double cauchy();
public static int discrete(double[]);
public static int discrete(int[]);
public static double exp(double);
public static void shuffle(Object[]);
public static void shuffle(double[]);
public static void shuffle(int[]);
public static void shuffle(char[]);
public static void shuffle(Object[], int, int);
public static void shuffle(double[], int, int);
public static void shuffle(int[], int, int);
public static int[] permutation(int);
public static int[] permutation(int, int);
private static void validateNotNull(Object);
private static void validateSubarrayIndices(int, int, int);
public static void main(String[]);
static void
}
StdStats.class
public final synchronized class StdStats {
private void StdStats();
public static double max(double[]);
public static double max(double[], int, int);
public static int max(int[]);
public static double min(double[]);
public static double min(double[], int, int);
public static int min(int[]);
public static double mean(double[]);
public static double mean(double[], int, int);
public static double mean(int[]);
public static double var(double[]);
public static double var(double[], int, int);
public static double var(int[]);
public static double varp(double[]);
public static double varp(double[], int, int);
public static double stddev(double[]);
public static double stddev(int[]);
public static double stddev(double[], int, int);
public static double stddevp(double[]);
public static double stddevp(double[], int, int);
private static double sum(double[]);
private static double sum(double[], int, int);
private static int sum(int[]);
public static void plotPoints(double[]);
public static void plotLines(double[]);
public static void plotBars(double[]);
private static void validateNotNull(Object);
private static void validateSubarrayIndices(int, int, int);
public static void main(String[]);
}
Stopwatch.class
public synchronized class Stopwatch {
private final long start;
public void Stopwatch();
public double elapsedTime();
public static void main(String[]);
}
StopwatchCPU.class
public synchronized class StopwatchCPU {
private static final double NANOSECONDS_PER_SECOND = 1.0E9;
private final management.ThreadMXBean threadTimer;
private final long start;
public void StopwatchCPU();
public double elapsedTime();
}
TestIntroCS.class
public synchronized class TestIntroCS {
public void TestIntroCS();
public static void main(String[]);
}
UnicodeTest.class
public synchronized class UnicodeTest {
private static final int CHARS_PER_LINE = 16;
private static final int MAX_CHAR = 65536;
private void UnicodeTest();
private static String toString(int);
public static void main(String[]);
}
InTest.txt
This is a test file.
Here is line 2.
mandrill
We provide professional writing services to help you score straight A’s by submitting custom written assignments that mirror your guidelines.
Get result-oriented writing and never worry about grades anymore. We follow the highest quality standards to make sure that you get perfect assignments.
Our writers have experience in dealing with papers of every educational level. You can surely rely on the expertise of our qualified professionals.
Your deadline is our threshold for success and we take it very seriously. We make sure you receive your papers before your predefined time.
Someone from our customer support team is always here to respond to your questions. So, hit us up if you have got any ambiguity or concern.
Sit back and relax while we help you out with writing your papers. We have an ultimate policy for keeping your personal and order-related details a secret.
We assure you that your document will be thoroughly checked for plagiarism and grammatical errors as we use highly authentic and licit sources.
Still reluctant about placing an order? Our 100% Moneyback Guarantee backs you up on rare occasions where you aren’t satisfied with the writing.
You don’t have to wait for an update for hours; you can track the progress of your order any time you want. We share the status after each step.
Although you can leverage our expertise for any writing task, we have a knack for creating flawless papers for the following document types.
Although you can leverage our expertise for any writing task, we have a knack for creating flawless papers for the following document types.
From brainstorming your paper's outline to perfecting its grammar, we perform every step carefully to make your paper worthy of A grade.
Hire your preferred writer anytime. Simply specify if you want your preferred expert to write your paper and we’ll make that happen.
Get an elaborate and authentic grammar check report with your work to have the grammar goodness sealed in your document.
You can purchase this feature if you want our writers to sum up your paper in the form of a concise and well-articulated summary.
You don’t have to worry about plagiarism anymore. Get a plagiarism report to certify the uniqueness of your work.
Join us for the best experience while seeking writing assistance in your college life. A good grade is all you need to boost up your academic excellence and we are all about it.
We create perfect papers according to the guidelines.
We seamlessly edit out errors from your papers.
We thoroughly read your final draft to identify errors.
Work with ultimate peace of mind because we ensure that your academic work is our responsibility and your grades are a top concern for us!
Dedication. Quality. Commitment. Punctuality
Here is what we have achieved so far. These numbers are evidence that we go the extra mile to make your college journey successful.
We have the most intuitive and minimalistic process so that you can easily place an order. Just follow a few steps to unlock success.
We understand your guidelines first before delivering any writing service. You can discuss your writing needs and we will have them evaluated by our dedicated team.
We write your papers in a standardized way. We complete your work in such a way that it turns out to be a perfect description of your guidelines.
We promise you excellent grades and academic excellence that you always longed for. Our writers stay in touch with you via email.