Solutions PDF
Solutions PDF
for
Data Structures
with Java
John R. Hubbard
Anita Huray
University of Richmond
Chapter 1
Object-Oriented Programming
Exercises
1.1
The requirements stage would generate a user manual like that shown here:
User Manual
Enter the string:
java CelsiusToFahrenheit <first> <last> <incr>
at the command line, where <first> is the first Celsius temperature to be
converted, <first> is the last Celsius temperature, and <incr> is the Celsius
increment for the table. The output will be a conversion table with that range
and increment.
Example:
Input:
java Convert 0 40 10
Output: 032
1050
2068
3086
40104
The design stage could adapt the same class as shown in Listing 1.1.
The implementation stage could adapt the same class as shown in Listing 1.2.
The testing stage could run a test driver like this:
public class CelsiusToFahrenheit {
public static void main(String[] args) {
if (args.length!=3) exit();
double first = Double.parseDouble(args[0]);
double last = Double.parseDouble(args[1]);
double incr = Double.parseDouble(args[2]);
for (double i=first; i<=last; i += incr)
System.out.println(i + \t + new MyTemperature(value,'F') );
}
1.2
Testing
1.3
CombinationLock
-n1:int
-n2:int
-n3:int
-open:boolean
+changeComb(int,int,int,int,int,int):boolean
+close()
+isOpen():boolean
+open(int,int,int):boolean
1.4
If d is a divisor of n that is greater than n , then m = n/d must be a whole number (i.e., an
integer), and therefore another divisor of n. But since d > n , we have m = n/d < n/ n =
n . So by checking for divisors only among those integers that are less than n ,
the existence of the divisor d > n will be found indirectly from m = n/d < n .
1.5
Course
Section
Instructor
Student
Person
Solutions
1.6
Department
Course
Chair
Section
Instructor
Student
Person
1.7
Course
Undergraduate
Section
Instructor
Graduate
Person
Student
1.8
Vehicle
Bus
Car
Driver
Owner
Person
1.9
Bank
Manager
Person
BankBranch
Customer
CheckingAccount
Account
Credit
SavingsAccount
Transaction
1.10
Debit
Media
BroadcastMedia
RadioProgram
TVProgram
Journal
PrintMedia
Periodical
Magazine
Website
Book
Newspaper
Programming Problems
1.1
/**
*
*
*
*
*/
Solutions
1.2
}
public class MyTemperature implements Temperature {
private double celsius; // stores temperature as a Celsius value
private int digits;
// number of digits to right of decimal
public MyTemperature(double value, char scale, int digits) {
if (scale=='C') setCelsius(value);
else setFahrenheit(value);
this.digits = digits;
}
public double getCelsius() {
return celsius;
}
public double getFahrenheit() {
return 9*celsius/5 + 32.0;
}
public void setCelsius(double celsius) {
this.celsius = celsius;
}
public void setDigits(int digits) {
this.digits = digits;
}
public void setFahrenheit(double fahrenheit) {
this.celsius = 5*(fahrenheit - 32)/9;
}
public String toString() {
// Example: "25.0 C = 77.0 F"
return round(getCelsius())+" C = "+round(getFahrenheit())+" F";
}
private double round(double x) {
// returns x, rounded to one digit on the right of the decimal:
double p = Math.pow(10,digits);
return Math.round(p*x)/p;
}
}
Solutions
1.3
Solutions
1.4
1.5
10
Solutions
11
}
public void setTime(String time) {
this.time = time;
}
public void setInstructor(Instructor instructor) {
this.instructor = instructor;
}
public void setStudents(Student[] students) {
int n = students.length;
// duplicate the array object:
this.students = new Student[n];
// but do not duplicate the Student objects:
for (int i=0; i<n; i++)
this.students[i] = students[i];
}
public String toString() {
return course + ": " + term + ", " + place + ", " + time + ", "
+ instructor;
}
public static void main(String[] args) {
Course course = new Course("CMSC", "221", "Data Structures", 4);
Section section = new Section(course, "Fall 2004", null, null);
System.out.println(section);
}
}
import java.util.*;
public class Person {
protected int yob;
protected String email;
protected String id;
protected boolean male;
protected String name;
public Person(String name, String id, String sex, int yob) {
this.id = id;
this.male = (sex.substring(0,1).toUpperCase() == "M");
this.name = name;
this.yob = yob;
}
public int getYob() {
return yob;
}
12
Solutions
13
super(name, id, s, y);
this.country = c;
}
public int getCredits() {
return credits;
}
public double getGpa() {
return gpa;
}
public String getCountry() {
return country;
}
public void setCredits(int credits) {
this.credits = credits;
}
public void setGpa(double gpa) {
this.gpa = gpa;
}
public void setCountry(List record) {
this.country = country;
}
public static void main(String[] args) {
Student student =
new Student("Anne Miller", "200491", "F", 1985, "US");
System.out.println(student);
}
}
import java.util.*;
public class Instructor extends Person {
protected String dept;
protected String office;
protected String tel;
public Instructor(String name, String id, String sex, int yob) {
super(name, id, sex, yob);
}
public String getDept() {
return office;
}
public String getOffice() {
return office;
}
14
1.6
}
public class ComboLock {
private int n1, n2, n3;
private boolean open;
public ComboLock(int n1, int n2, int n3) {
this.n1 = n1;
this.n2 = n2;
this.n3 = n3;
}
public boolean changeComb(int n1, int n2, int n3, int n4,
int n5, int n6) {
if (this.n1 != n1 || this.n2 != n2 || this.n3 != n3) return false;
this.n1 = n4;
this.n2 = n5;
this.n3 = n6;
open = false;
return true;
Solutions
15
}
public void close() {
open = false;
}
public boolean isOpen() {
return open;
}
public boolean open(int n1, int n2, int n3) {
if (this.n1 == n1 && this.n2 == n2 && this.n3 == n3) open = true;
else open = false;
return open;
}
1.7
16
1.8
class Phone {
private String areaCode, number;
public Phone(String areaCode, String number) {
this.areaCode = areaCode;
this.number = number;
}
public Phone(Phone that) {
this.areaCode = that.areaCode;
this.number = that.number;
}
public void setAreaCode(String areaCode) {
this.areaCode = areaCode;
Solutions
17
}
public String toString() {
return "(" + areaCode + ")" + number.substring(0, 3)
+ "-" + number.substring(3);
}
}
public class Person {
private final boolean male;
private final String name;
private final Phone phone;
private final int yob;
public Person(String name, boolean male, int yob, Phone phone) {
this.name = name;
this.male = male;
this.yob = yob;
this.phone = new Phone(phone);
}
public String getName() {
return name;
}
public Phone getPhone() {
return phone;
}
public int getYob() {
return yob;
}
public boolean isMale() {
return male;
}
public String toString() {
return (male?"Mr. ":"Ms. ") + name+" ("+yob+"), tel. "+phone;
}
public static void main(String[] args) {
Phone tel = new Phone("808", "4561414");
Person gwb = new Person("G. W. Bush", true, 1946, tel);
System.out.println(gwb);
tel.setAreaCode("202");
System.out.println(gwb);
}
}
Chapter 2
Abstract Data Types
Exercises
2.1
ADT: Int
interface
An Int is an immutable object that represents a whole
Int
number, such as 44 or 7.
+Int(long)
Int(long n)
+isLessThan(Int)
Constructs: an Integer that is equivalent to n.
+minus(Int):Int
+plus(Int):Int
boolean isLessThan(Integer x)
+times(Int):Int
Returns: true if this integer is less than x; otherwise false.
Integer minus(Integer x)
Returns: an Integer that represents the difference of this integer minus x.
Integer plus(Integer x)
Returns: an Integer that represents the sum of this integer and x.
Integer times(Integer x)
Returns: an Integer that represents the product of this integer and x.
package chap02.exer01;
public interface Integer {
public Integer plus(Integer x);
public Integer minus(Integer x);
public Integer times(Integer x);
}
18
Solutions
2.2
19
ADT: Counter
A Counter is an object that keeps a non-negative
integer count.
Counter()
Constructs:a Counter that is initialized to 0.
integer getCount()
Postcondition:this date is unchanged.
Returns:the count.
void increment()
Postcondition:the count has been increased by 1.
void reset()
Postcondition:the count is 0.
interface
Counter
+Counter()
+getCount():int
+increment()
+reset()
package chap02.exer02;
public interface Counter {
public void add(Number x);
public void subtract(Number x);
public void multiply(Number x);
public void divide(Number x);
public Number sum(Number x);
public Number difference(Number x);
public Number product(Number x);
public Number quotient(Number x);
}
2.3
ADT: Date
A Date represents a calendar date, such as July 4,
1776.
void add(integer days)
Postcondition: this date is advanced by the
specified number of days.
integer getDay()
Returns:the day number of this date.
Postcondition:this date is unchanged.
integer getMonth()
Returns:the month number of this date.
Postcondition:this date is unchanged.
integer getYear()
Returns:the year number of this date.
Postcondition:this date is unchanged.
interface
Date
+add(int)
+getDay():int
+getMonth():int
+getYear():int
+numDays(Date):int
+setDay(int)
+setMonth(int)
+setYear(int)
20
2.4
2.5
Solutions
2.6
2.7
2.8
2.9
21
interface
Card
+Card(Suit,int)
+getRank():int
+getSuit():Suit
+toString():String
Die
-random:Random
+Die()
+Die(Random)
+nextToss():int
22
2.10
Dice
-random:Random
+Dice()
+Dice(Random)
+nextToss():int
2.11
a. ADT: Number
A Number object represents a real number.
void add(Number x)
Postcondition: x has been added to this number.
void subtract(Number x)
Postcondition: x has been subtracted from this number.
void multiply(Number x)
Postcondition: this number has been multiplied by x.
void divide(Number x)
Postcondition: this number has been divided by x.
Number sum(Number x)
Postcondition: this number is unchanged.
Returns: the sum of x and this number.
Number difference(Number x)
Postcondition: this number is unchanged.
Returns: the difference of x from this number.
Number product(Number x)
Postcondition: this number is unchanged.
Returns: the sum of x and this number.
Number quotient(Number x)
Postcondition: this number is unchanged.
Returns: the quotient of this number divided by x.
Solutions
2.12
23
a. ADT: Point
A Point object represents a point (x, y) in two-dimensional coordinate space.
double getX()
Postcondition: this point is unchanged.
Returns: the x-coordinate of this point.
double getY()
Postcondition: this point is unchanged.
Returns: the y-coordinate of this point.
void setX(double x)
Postcondition: the x-coordinate of this point equals x.
void setY(double y)
Postcondition: the y-coordinate of this point equals y.
void moveTo(double x, double y)
Postconditions: the x-coordinate of this point equals x;
the y-coordinate of this point equals y.
b. public interface Point {
public
public
public
public
public
double getX();
double getY();
void setX(double x);
void setY(double y);
void moveTo(double x, double y);
2.13
a. ADT: Vector
A Vector is an ordered container of objects.
Object getAtIndex(integer i)
Postcondition: this vector is unchanged.
Returns: the object at index i.
void setAtIndex(Object x, integer i)
Postcondition: the object x is at index i.
integer size()
Postcondition: this vector is unchanged.
Returns: the number of objects in this vector.
b. public interface Vector {
public interface Vector {
public Object getAtIndex(int i);
public void setAtIndex(Object x, int i);
public integer size();
}
24
2.14
2.15
a. ADT: Polynomial
A Polynomial is a mathematical function that is determined by its sequence of
coefficients and exponents.
Polynomial derivative()
Postcondition: this polynomial is unchanged.
Returns: a new polynomial that is the derivative of this polynomial.
integer getDegree()
Postcondition: this polynomial is unchanged.
Returns: the highest exponent of this polynomial.
String toString()
Postcondition: this polynomial is unchanged.
Returns: a string representation of this polynomial.
double valueAt(double x)
Postcondition: this polynomial is unchanged.
Returns: the y-value of this polynomial evaluated at x.
Solutions
25
Polynomial derivative();
int getDegree();
String toString();
double valueAt(double x);
2.16
a. ADT: Purse
A Purse is a container of coins.
integer getNumCoinsOf(integer c)
Postcondition: this purse is unchanged.
Returns: the number of c-cent coins in this purse.
void addNumCoinsOf(integer c, integer n)
Postcondition: increases the number of c-cent coins in this purse by n.
integer totalNumCoins()
Postcondition: this purse is unchanged.
Returns: the total number of coins in this purse.
double totalValue()
Postcondition: this polynomial is unchanged.
Returns: the total dollar value of all the coins in this purse.
b. public interface Purse {
public
public
public
public
}
26
2.17
b.
Set
+add(Object):boolean
+clear()
+contains(Object):boolean
+equals(Object):boolean
+remove(Object):boolean
+size():int
Solutions
2.18
27
a. ADT: Map
A Map is a container of key-value pairs, where the keys are unique.
void clear()
Postcondition: this map is empty.
boolean containsKey(Object key)
Postcondition: this map is unchanged.
Returns: true if and only if this map contains the specified key.
Object get(Object key)
Postcondition: this map is unchanged.
Returns: the value for the specified key if it is in this map,
otherwise null is returned.
Set keySet()
Postcondition: this map is unchanged.
Returns: a new set whose elements are the keys in this map.
Object put(Object key, Object value)
Postcondition: the specified key-value pair is in this map.
Returns: the previous value stored in this map for the specified key if
that key is in this map; otherwise null is returned.
boolean remove(Object key)
Postcondition: no key-value pair with the specified key is in this map.
Returns: true if and only if this map is changed.
integer size()
Postcondition: this map is unchanged.
Returns: the number of elements in this map.
b.
Map
+clear()
+containsKey(Object):boolean
+get(Object):Object
+keySet():Set
+put(Object,Object):Object
+remove(Object):boolean
+size():int
28
2.19
Solutions
29
Programming Problems
2.1
2.2
}
public class ArraySet implements Set {
private Object[] objects = new Object[1000];
private int size, i;
public boolean add(Object object) {
if (contains(object)) return false; // no duplicates
objects[size++] = object;
return true;
}
public boolean contains(Object object) {
for (int i=0; i<size; i++)
if (objects[i]==object) return true;
return false;
}
public Object getFirst() {
i = 0;
return objects[i++];
}
public Object getNext() {
return objects[i++];
}
public boolean remove(Object object) {
for (int i=0; i<size; i++)
if (objects[i]==object) {
System.arraycopy(objects, i+1, objects, i, size-i-1);
objects[--size] = null;
return true;
}
return false;
}
public int size() {
return size;
}
30
2.3
2.4
Solutions
2.5
2.6
31
32
Chapter 3
Arrays
Exercises
3.1
3.2
33
34
3.3
3.4
3.5
3.6
3.7
Chapter 3 Arrays
Algorithm Sequential Search
Input: a sequence {a0 , a1 , a2 , ..., an1 } and a target value x.
Output: an index value i.
Postconditions: Either ai = x, or i = n and each aj x.
If ai = x, then aj x for all j > i.
1. For each i from n1 down to 0, do step 2:
2.
If ai = x, return i.
3. Return n.
If the algorithm returns i at step 2, then ai = x, as required by the first alternative of the
postcondition.
If the algorithm returns n at step 3, then the condition ai = x at step 2 was never true
for any of the values of i in the range 0 to n1. That is the second alternative of the postcondition.
Algorithm Maximum Element
Input: a sequence {a0 , a1 , a2 , ..., an1 } of comparable elements.
Output: an element am .
Postconditions: am ai , for all i.
1. Repeat Step 2 for i = n 1 down to 1:
2.
If ai > ai1 , swap ai with ai1 .
3. Return a0 .
On the first iteration of the loop in steps 1-2, i = n 1. If an1 an2, then no swap occurs
in step 2, and an2 = max{an2 , an1 }. But if an1 > an2 , then the swap occurs, thereby
making an2 the larger. Thus, in either case, after the first iteration has finished, an2 =
max{an2 , an1 }.
On the second iteration, i = n 2. If an2 an3 , then no swap occurs, and therefore
an3 an2 = max{an2 , an1 }. But if an1 > an2 , then the swap occurs, thereby making
an3 the larger of those two, and thus again an3 an2 = max{an2 , an1 }. Therefore, in
either case, after the second iteration, an3 = max{an3 , an2 , an1 }.
Similarly, on the jth iteration, anj1 = max{anj1 , ..., an2 , an1 }. This is a loop
invariant for the algorithm. Note that j = n i, so i = n j and the loop invariant can be
expressed as ai1 = max{ai1 , ..., an2 , an1 }. Since this is true for each i from n 1 down
to 1, it is true when i = 1; i.e., a0 = max{a0 , ..., an2, an1 }. Thus the correct value is
returned at step 3.
The assignment b = a merely makes b an alias for the array named a; i.e., there is still
only one array.
In order to return a separate array, we must allocate new storage for that array
int[] b = new int[a.length];
Solutions
3.8
35
This has no effect upon the array a[] (or even on the variables passed to i and j).
Here is a correct version:
public static void swap(double[] a, int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
3.9
This doesnt work because everythin gets swapped twice, thereby putting it back where it
started. The only change required is to run the for loop only half-way through the array:
for (int i = 0; i < n/2; i++)
swap(a, i, n-1-i);
3.10
3.11
3.12
3.13
The first two output statements merely show that x and y are arrays and that they are
stored at different locations in memory. Consequently, the boolean value eqeq is false
because the == operator tests for identity. But the java.util.Arrays.equals() method
tests for equality of content, so its value is true.
The assignment y = x changes y to an alias for the x array. So then x and y are identically equal, and thus the last output is true.
The Binary Search algorithm requires the array to be in ascending order. So, if the target is
found, all other elements that contain it must be adjacent to the element where it is found.
So to find the smallest index among those elements that contain the same value, we can
simply decrement the index until its element is no longer equal to the target:
Algorithm Modified Binary Search
Input: a sequence {a0 , a1 , a2 , ..., an1 } and a target value x.
Output: an index value i.
Precondition: The sequence is sorted: a0 a1 a2 an1 .
Postcondition: Either ai = x;
or i = p 1, where aj < x for all j < p, and aj > x for all j p.
1. Let p = 0 and q = n 1.
2. Repeat steps 3-5 while p q:
3.
Let i = (p + q)/2.
4.
If ai = x, then decrement i until i < 0 or ai x, and then return i + 1.
5.
If ai < x, let p = i + 1; otherwise let q = i 1.
6. Return p 1.
To change the Binary Search to the Interpolation Search, replace step 3 with:
3. Let i = p + r (q p), where r = (x ap )/(aq ap ).
f (g) f(n)/g(n) is bounded and g(n)/f(n) is bounded f (g) and g (f).
36
3.14
3.15
3.16
3.17
3.18
Chapter 3 Arrays
f o(g) f(n)/g(n) 0 f(n)/g(n) is bounded and g(n)/f(n) is not bounded
f (g) and f (g) f (g) (g).
f (g) g(n)/f(n) 0 g(n)/f(n) is bounded and f(n)/g(n) is not bounded
f (g) and f (g) f o(g) (g).
The functions f(n), g(n), f(n)/g(n), and g(n)/f(n) have the values shon in this table:
n
f(n)
g(n)
f(n)/g(n)
g(n)/f(n)
1/2
1/4
64
1/8
64
64
64
1024
1/16
16
When n is even, both ratios equal 1; thus, f(n)/g(n) does not approach 0, and so f o(g).
When n is odd, g(n)/f(n) grows exponentially; thus, g(n)/f(n) is not bounded, so f (g).
But f(n)/g(n) never exceeds 1; thus f(n)/g(n) is bounded, and so f O(g).
Thus, f O(g) (g) o(g).
f O(g) f(n)/g(n) is bounded g (f).
f o(g) f(n)/g(n) 0 g (f).
Programming Problems
3.1
Solutions
37
private double[] randomDoubles(int n) {
double[] a = new double[n];
for (int i=0; i<n; i++)
a[i] = random.nextDouble();
return a;
}
private void print(double[] a) {
printf(a[0], "{#.###");
for (int i=1; i<a.length; i++)
printf(a[i], "','#.###");
System.out.println("}");
}
private void printf(double x, String fs) {
System.out.print(new java.text.DecimalFormat(fs).format(x));
}
public static void main(String[] args) {
new Main(Integer.parseInt(args[0]));
}
3.2
38
Chapter 3 Arrays
System.out.println("x:\t" + x);
}
public static void main(String[] args) {
new Main();
}
}
3.3
3.4
3.5
3.6
Solutions
39
+ IntArrays.isSorted(a));
a = IntArrays.randomInts(8, 100);
IntArrays.print(a);
System.out.println("IntArrays.isSorted(a): "
+ IntArrays.isSorted(a));
a = IntArrays.resize(a, 12);
IntArrays.print(a);
IntArrays.swap(a, 2, 6);
IntArrays.print(a);
}
3.7
3.8
3.9
40
Chapter 3 Arrays
break;
}
}
return a;
}
3.10
3.11
/**
* Determines whether the specified array is in descending order.
*
* @param a the array.
* @return true if a[] is in descending order, otherwise false.
*/
public static boolean isDescending(int[] a) {
for (int i=1; i<a.length; i++)
if (a[i] > a[i-1]) return false;
return true;
}
/**
* Determines whether the specified array is sorted, either
* in ascending order or in descending order.
*
* @param a the array.
* @return true if a[] is sorted, otherwise false.
*/
public static boolean isSorted(int[] a) {
return isAscending(a) || isDescending(a);
}
3.12
Solutions
41
System.out.println("search(a," + 50 + "): " + k);
int i = -k-1;
System.out.println("i: " + i);
System.out.println("a[" + (i-1) + "]: " + a[i-1]);
System.out.println("a[" + i + "]: " + a[i]);
}
static int search(int[] a, int x) {
int p = 0, q = a.length-1;
while (p <= q) {
// search the segment a[p..q]
int i = (p+q)/2;
// index of element in the middle
if (a[i] == x) return i;
if (a[i] < x) p = i+1;
// search upper half
else q = i-1;
// search lower half
}
return -p-1;
// not found
}
}
/* Output:
search(a,50): -4
i: 3
a[2]: 44
a[3]: 55
*/
}
3.13
void bubble(int[] a) {
for (int i=1; i<a.length; i++)
if (a[i] < a[i-1]) IntArrays.swap(a, i-1, i);
}
3.14
void select(int[] a) {
int m=0;
for (int i=1; i<a.length; i++)
if (a[i] > a[m]) m = i;
IntArrays.swap(a, m, a.length-1);
}
3.15
void insert(int[] a) {
int i = a.length - 1;
int ai = a[i], j = i;
for (j=i; j>0 && a[j-1]>ai; j--)
a[j] =a[j-1];
42
Chapter 3 Arrays
a[j] = ai;
}
3.16
void merge(int[] a) {
int n=a.length, m=n/2;
int i=0, j=m, k=0;
int[] aa = new int[n];
while (i < m && j < n)
if (a[i] < a[j]) aa[k++] = a[i++];
else aa[k++] = a[j++];
if (i < m) System.arraycopy(a, i, a, k, m-i);
System.arraycopy(aa, 0, a, 0, k);
}
3.17
3.18
3.19
int partition(int[] a) {
int a0 = a[0], i = 0, j = a.length;
while (i < j) {
while (i < j && a[--j] >= a0)
;
if (i < j) a[i] = a[j];
while (i < j && a[++i] <= a0)
;
if (i < j) a[j] = a[i];
}
Solutions
43
a[j] = a0;
return j;
3.20
3.21
3.22
3.23
3.24
44
Chapter 3 Arrays
for (int i=0; i<size; i++)
if (objects[i].equals(x)) return i;
return -1;
}
3.25
3.26
3.27
Solutions
45
}
3.28
3.29
3.30
3.31
46
Chapter 3 Arrays
for (int i=1; i<n; i++) {
if (a[i] == null || !a[i].getClass().equals(c))
return false;
}
}
return true;
}
3.32
3.33
Solutions
47
}
static void print(int n, int w) {
// prints n right-justified in a field on width w:
String s = "" + n, blanks = "
";
int len = s.length();
System.out.print(blanks.substring(0, w-len) + s);
}
3.34
48
Chapter 3 Arrays
static void print(int n, int w) {
// prints n right-justified in a field on width w:
String s = "" + n, blanks = "
";
int len = s.length();
System.out.print(blanks.substring(0, w-len) + s);
}
}
3.35
3.36
Solutions
49
try {
BufferedReader in = new BufferedReader(new FileReader(file));
String line = in.readLine();
while(line!=null) {
StringTokenizer parser
= new StringTokenizer(line," ,:;-.?!");
while (parser.hasMoreTokens()) {
++words;
String word = parser.nextToken().toUpperCase();
chars += word.length();
}
line = in.readLine();
}
in.close();
} catch(IOException e) { System.out.println(e); }
System.out.println("words: " + words);
System.out.println("characters: " + chars);
}
public static void main(String[] args) {
new Main(args[0]);
}
Chapter 4
Linked Structures
Exercises
4.1
44
22
55
33
66
50
40
free
4.2
a
44
22
55
33
66
50
free
50
Solutions
4.3
Programming Problems
4.1
4.2
4.3
4.4
51
52
4.5
4.6
4.7
4.8
Solutions
53
q = q.next;
}
p=list2;
while (p != null) {
q.next = new Node(p.data);
p = p.next;
q = q.next;
}
return list3.next; // discard dummy head node
4.9
4.10
4.11
}
void replace(Node list, int i, int x)
// replaces the value of element number i with x;
String msg = "The list must have at least " + i + " elements.";
if (list == null) throw new IllegalArgumentException(msg);
for (int j = 0; j < i; j++) {
if (list.next == null)
throw new IllegalArgumentException(msg);
list = list.next;
}
list.data = x;
}
void swap(Node list, int i, int j) {
// swaps the ith element with the jth element;
if (i < 0 || j < 0) throw new IllegalArgumentException();
if (i == j) return;
Node p=list, q=list;
for (int ii=0; ii<i; ii++) {
if (p == null) throw new IllegalStateException();
p = p.next;
}
for (int jj=0; jj<j; jj++) {
if (q == null) throw new IllegalStateException();
q = q.next;
}
int pdata=p.data, qdata=q.data;
p.data = qdata;
q.data = pdata;
return;
}
Node merged(Node list1, Node list2)
// precondition: list1 and list2 are both in ascending order;
// returns: a new list that contains all the elements of list1 and
54
4.12
}
private void shuffle(Node list) {
// performs a perfect shuffle on the specified list;
Node p=list, q=list;
while (p != null) {
p = p.next;
if (p != null) p = p.next;
q = q.next;
}
// now q = middle node:
Node m = q;
p = list;
Node t=p.next, tt=m.next;
while (m.next != null) {
tt = m.next;
p.next = m;
p = m.next = t;
t = p.next;
m = tt;
}
p.next = m;
}
Chapter 5
Stacks
Exercises
5.1
5.2
5.3
a.
b.
c.
a.
b.
c.
x
x
*
x
x
x
Monday
Tuesday
Monday
Wednesday
Tuesday
Monday
Tuesday
Monday
Monday
Thursday
Monday
Friday
Thursday
Monday
Thursday
Monday
Saturday
Thursday
Monday
Sunday
Saturday
Thursday
Monday
Saturday
Thursday
Monday
Thursday
Monday
4 + y 8 z + /
6 y / 5 z * /
/ x / 2 y 7 z
+ 4 / y 3 + z; i.e., (x + 4)/(y 3) + z
9 + y * 6 z; i.e., x (9 + y)*(6 z)
/ 3 / y / 2 / z; i.e., x/(3/(y/(2/z)))
55
56
Chapter 5 Stacks
Programming Problems
5.1
Solutions
5.2
57
import chap05.list01.Stack;
import java.util.ArrayList;
public class ArrayListStack implements Stack {
private ArrayList a;
public ArrayListStack(int capacity) {
a = new ArrayList(capacity);
}
public boolean isEmpty() {
return (a.isEmpty());
}
public Object peek() {
int n = a.size();
if (n == 0) throw new IllegalStateException("stack is empty");
return a.get(n-1);
}
public Object pop() {
int n = a.size();
if (n == 0) throw new IllegalStateException("stack is empty");
return a.remove(n-1);
}
public void push(Object object) {
a.add(object);
}
public int size() {
return a.size();
}
5.3
}
public String toString() {
if (size == 0) return "()";
int i = size;
StringBuffer buf = new StringBuffer("(" + a[--i]);
while (i > 0)
buf.append("," + a[--i]);
return buf + ")";
}
58
5.4
5.5
5.6
5.7
5.8
Chapter 5 Stacks
public String toString() {
if (size == 0) return "()";
StringBuffer buf = new StringBuffer("(" + top.object);
for (Node p=top.next; p!=null; p = p.next)
buf.append("," + p.object);
return buf + ")";
}
public boolean equals(Object obj) {
if (obj == this) return true;
if (!(obj instanceof ArrayStack)) return false;
ArrayStack that = (ArrayStack)obj;
if (that.size != this.size) return false;
for (int i=0; i<size; i++)
if (!that.a[i].equals(this.a[i])) return false;
return true;
}
public boolean equals(Object obj) {
if (obj == this) return true;
if (!(obj instanceof LinkedStack)) return false;
LinkedStack that = (LinkedStack)obj;
if (that.size != this.size) return false;
Node p=this.top, q = that.top;
while (p != null && q != null) {
if (!p.object.equals(q.object)) return false;
p = p.next;
q = q.next;
}
return true;
}
public Object[] toArray() {
Object[] a = new Object[size];
int i = 0;
for (Node p=top; p!=null; p = p.next)
a[i++] = p.object;
return a;
}
public ArrayStack toArrayStack() {
ArrayStack temp = new ArrayStack(2*size);
for (Node p=top; p!=null; p = p.next)
temp.push(p.object);
ArrayStack s = new ArrayStack(2*size);
for (Node p=top; p!=null; p = p.next)
Solutions
59
s.push(temp.pop());
return s;
5.9
5.10
5.11
5.12
5.13
5.14
}
public LinkedStack toLinkedStack() {
LinkedStack s = new LinkedStack();
for (int i=0; i<size; i++)
s.push(a[i]);
return s;
}
public Object peekSecond() {
if (size < 2) throw new java.util.NoSuchElementException();
return top.next.object;
}
public Object popSecond() {
if (size < 2) throw new java.util.NoSuchElementException();
--size;
Object second = a[size-1];
a[size-1] = a[size];
a[size] = null;
return second;
}
public Object bottom() {
if (size == 0) throw new java.util.NoSuchElementException();
Node p = top;
while (p.next != null)
p =p.next;
return p.object;
}
public Object popBottom() {
if (size == 2) throw new java.util.NoSuchElementException();
Object bottom = a[0];
System.arraycopy(a, 1, a, 0, --size);
a[size] = null;
return bottom;
}
public void reverse() {
if (size < 2) return;
LinkedStack stack1 = new LinkedStack();
LinkedStack stack2 = new LinkedStack();
while (this.size > 0)
stack1.push(this.pop());
while (stack1.size > 0)
60
Chapter 5 Stacks
stack2.push(stack1.pop());
while (stack2.size > 0)
this.push(stack2.pop());
5.15
5.16
5.17
5.18
}
Object removeSecondFromTop(Stack stack) {
int n = stack.size();
if (n<2) throw new IllegalArgumentException("stack is empty");
Object top1 = stack.pop();
Object top2 = stack.pop();
stack.push(top1);
return top2;
}
Object removeBottom(Stack stack) {
int n = stack.size();
if (n<1) throw new IllegalArgumentException("stack is empty");
if (n<2) return stack.pop();
Stack auxStack = new LinkedStack();
for (int i=0; i<n-1; i++)
auxStack.push(stack.pop());
Object bottom = stack.pop();
for (int i=0; i<n-1; i++)
stack.push(auxStack.pop());
return bottom;
}
void reverse(Stack stack) {
if (stack.size() < 2) return;
Stack stack1 = new LinkedStack();
Stack stack2 = new LinkedStack();
while (stack.size() > 0)
stack1.push(stack.pop());
while (stack1.size() > 0)
stack2.push(stack1.pop());
while (stack2.size() > 0)
stack.push(stack2.pop());
}
Stack reversed(Stack stack) {
Stack stack1 = new LinkedStack();
Stack stack2 = new LinkedStack();
while (stack.size() > 0) {
stack1.push(stack.peek());
stack2.push(stack.pop());
}
Solutions
61
while (stack2.size() > 0)
stack.push(stack2.pop());
return stack1;
5.19
5.20
5.21
}
public void push(Object object) {
if (contains(object)) return;
if (size == a.length) resize();
a[size++] = object;
}
private boolean contains(Object x) {
for (int i=0; i<size; i++)
if (a[i]==x) return true;
return false;
}
public void push(Object object) {
if (object == null)
throw new IllegalArgumentException("object is null");
if (size == a.length) resize();
a[size++] = object;
}
/**
* The <code>ArrayStack</code> class implements the
* <code>Stack</code> interface defined in the
* <code>chap05.list01</code> package. Its instances are
* last-in-first-out (LIFO) containers that store their
* elements in a backing array.
*/
public class ArrayStack implements Stack { ...
/**
* Creates an empty stack with a specified capacity.
*
* @param capacity the length of the backing array.
*/
public ArrayStack(int capacity) { ...
/**
* Reports whether this stack is empty.
*
* @return <code>true</code> if and only if this stack contains
*
no elements.
*/
62
Chapter 5 Stacks
public boolean isEmpty() { ...
/**
* Returns a reference to the top element on this stack, leaving
* the stack unchanged.
*
* @return
the top element on this stack.
* @exception IllegalStateException if this stack is empty.
*/
public Object peek() { ...
/**
* Removes the top element on this stack and returns it.
*
* @return
the top element on this stack.
* @exception IllegalStateException if this stack is empty.
*/
public Object pop() { ...
/**
* Inserts the specified object onto the top of this stack.
*
* @param object the element to be pushed onto this stack.
*/
public void push(Object object) { ...
5.22
/**
* Returns the number of elements in this stack.
*
* @return
the number of elements in this stack.
*/
public int size() { ...
/**
* The <code>LinkedStack</code> class implements the
* <code>Stack</code> interface defined in the
* <code>chap05.list01</code> package. Its instances are
* last-in-first-out (LIFO) containers that store their
* elements in a backing array.
*/
public class LinkedStack implements Stack { ...
Solutions
63
/**
* Reports whether this stack is empty.
*
* @return <code>true</code> if and only if this stack contains
*
no elements.
*/
public boolean isEmpty() { ...
/**
* Returns a reference to the top element on this stack, leaving
* the stack unchanged.
*
* @return
the top element on this stack.
* @exception IllegalStateException if this stack is empty.
*/
public Object peek() { ...
/**
* Removes the top element on this stack and returns it.
*
* @return
the top element on this stack.
* @exception IllegalStateException if this stack is empty.
*/
public Object pop() { ...
/**
* Inserts the specified object onto the top of this stack.
*
* @param object the element to be pushed onto this stack.
*/
public void push(Object object) { ...
/**
* Returns the number of elements in this stack.
*
* @return the number of elements in this stack.
*/
public int size() { ...
Chapter 6
Queues
Exercises
6.1
6.2
DE
DE PA
DE PA NJ
PA NJ
NJ
NJ GA
NJ GA CT
GA CT
GA CT MA
GA CT MA MD
DE MA MD
CT
MA MD
creates the specified new node. The value of that expression is a reference to that new
node. The permuted statement first assigns that reference to head.prev . That changes the
value of head.prev . So when the second (chained) assignment is performed, the new
node reference gets assigned to the next field of that new node, since head.prev refers to
it. Thus, the new nodes next field ends up refering to itself.
64
Solutions
6.3
65
Bought
Feb 20
200@ $20
Apr 15
Jun 25
150@ $25
Aug 10
250@ $24
Sep 20
Nov 15
6.4
Sold
Gain
100@ $22
100@ $2 = $200
100@ $28
100@ $8 = $800
150@ $28
150@ $3 = $450
50@ $28
50@ $4 = $200
200@ $32
200@ $8 = $1600
With the following implementation, the worst case would be alternating calls to add()
and remove(). In that case, both operations run in linear time:
void add(Object x) {
while (!stack2.isEmpty())
stack1.push(stack2.pop());
stack1.push(x);
}
Object remove() {
while (!stack1.isEmpty())
stack2.push(stack1.pop());
return stack2.pop();
}
int size() {
return stack1.size() + syack2.size();
}
66
Chapter 6 Queues
Programming Problems
6.1
import chap06.list01.Queue;
public class ArrayQueue implements Queue {
private Object[] a;
private int front, back;
public ArrayQueue(int capacity) {
a = new Object[capacity];
}
public void add(Object object) {
if (back == a.length) resize();
a[back++] = object;
}
public Object first() {
if (size()==0) throw new IllegalStateException("queue is empty");
return a[front];
}
public boolean isEmpty() {
return (size() == 0);
}
public Object remove() {
if (size()==0) throw new IllegalStateException("queue is empty");
Object object=a[front];
a[front++] = null;
return object;
}
public int size() {
return back - front;
}
private void resize() {
Object[] aa = a;
a = new Object[2*aa.length];
System.arraycopy(aa, front, a, 0, size());
}
}
Solutions
6.2
67
/**
* The <code>ArrayQueue</code> class implements the
* <code>Queue</code> interface defined in the
* <code>chap06.list01</code> package. Its instances are
* first-in-first-out (FIFO) containers that store their
* elements in a backing array.
*/
public class ArrayQueue implements Queue { ...
/**
* Creates an empty queue with a specified capacity.
*
* @param capacity the length of the backing array.
*/
public ArrayQueue(int capacity) { ...
/**
* Adds the specified element to the back of this queue.
*
* @param object the element to be added to this queue.
*/
public void add(Object object) { ...
/**
* Returns the element at the front of this queue.
*
* @return the element at the front of this queue.
* @throws IllegalStateException if this queue is empty
*/
public Object first() { ...
/**
* Reports whether this queue is empty.
*
* @return <code>true</code> if and only if this queue contains
*
no elements.
*/
public boolean isEmpty() { ...
68
Chapter 6 Queues
/**
* Removes and returns the element at the front of this queue.
*
* @return the element at the front of this queue.
* @throws IllegalStateException if this queue is empty
*/
public Object remove() { ...
/**
* Returns the number of elements in this queue.
*
* @return the number of elements in this queue.
*/
public int size() { ...
6.3
6.4
/**
* The <code>LinkedQueue</code> class implements the
* <code>Queue</code> interface defined in the
* <code>chap06.list01</code> package. Its instances are
* first-infirst-out (FIFO) containers that store their
* elements in a linked list.
*/
public class LinkedQueue implements Queue { ...
The rest is the same as in Problem 6.2 above.
import chap06.list01.Queue;
import java.util.ArrayList;
public class ArrayListQueue implements Queue {
private ArrayList a;
public ArrayListQueue(int capacity) {
a = new ArrayList(capacity);
}
public void add(Object object) {
a.add(object);
}
public Object first() {
if (size()==0) throw new IllegalStateException("queue is empty");
return a.get(0);
}
Solutions
69
public boolean isEmpty() {
return a.isEmpty();
}
public Object remove() {
if (size()==0) throw new IllegalStateException("queue is empty");
return a.remove(0);
}
public int size() {
return a.size();
}
6.7
6.8
6.10
}
public String toString() {
if (size == 0) return "()";
StringBuffer buf = new StringBuffer("(" + head.object);
for (Node p=head.next; p!=null; p = p.next)
buf.append("," + p.object);
return buf + ")";
}
public boolean equals(Object obj) {
if (obj == this) return true;
if (!(obj instanceof LinkedQueue)) return false;
LinkedQueue that = (LinkedQueue)obj;
if (that.size != this.size) return false;
Node p=this.head, q = that.head;
while (p != null && q != null) {
if (!p.object.equals(q.object)) return false;
p = p.next;
q = q.next;
}
return true;
}
public Object[] toArray() {
Object[] a = new Object[size];
int i = 0;
for (Node p=head; p!=null; p = p.next)
a[i++] = p.object;
return a;
}
70
6.11
6.12
6.13
6.14
6.15
6.16
Chapter 6 Queues
public ArrayQueue toArrayQueue() {
ArrayQueue q = new ArrayQueue(2*size);
for (Node p=head; p!=null; p = p.next)
q.add(p.object);
return q;
}
public Object getSecond() {
if (size < 2) throw new java.util.NoSuchElementException();
return head.next.object;
}
public Object removeSecond() {
if (size < 2) throw new java.util.NoSuchElementException();
Object object=head.prev.object;
head.next.next = head.next.next.next;
head.next.next.prev = head;
--size;
return object;
}
public Object last() {
if (size == 0) throw new java.util.NoSuchElementException();
return head.prev.object;
}
public void reverse() {
Node p = head.next;
while (p != head) {
Node temp = p.next;
p.next = p.prev;
p = p.prev = temp;
}
head.next = p.prev;
}
Object removeSecond(Queue q) {
int n = q.size();
if (n<2) throw new IllegalArgumentException();
q.add(q.remove());
Object x = q.remove();
for (int i=2; i<n; i++)
q.add(q.remove());
return x;
}
}
Solutions
6.17
6.18
6.19
71
Chapter 7
Collections
Exercises
7.1
7.2
7.3
7.4
7.5
7.6
[CH,
[NZ,
[NZ,
[NZ,
[CA,
[MX,
[CA,
[MX,
[CA,
[MX,
[CA,
AR
[CA,
[US,
[US,
[CA,
[CA,
[CA,
[CA,
[CA,
[CA,
[CA,
JP,
JP,
AU,
AU,
US,
AR,
US,
CO,
US,
CO,
US,
IN,
IN,
IN,
IN]
MX,
BR]
MX,
BR]
MX,
VE]
MX,
US,
MX,
BR]
US,
US,
US,
US,
MX,
AR,
AR,
a. The list's size increases from 0 to 5; content are: 0, 10, 20, 30, 40 in ascending order.
b. "[0]0, [1]10, [2]20, [3]30, [4]40"
c. Three more items are inserted so that size increases from 5 to 8, and 80 precedes 0,
70 precedes 10, 60 precedes 20.
d. Three items are removed so that size increases from 8 to 5; line 16 removes 0, line
17 removes 20, and line 18 removes 40.
72
Solutions
73
e. initial size is 0
empty
**current size is 5
[0]0, [1]10, [2]20, [3]30, [4]40
****current size is 8
[0]-80, [1]0, [2]-70, [3]10, [4]-60, [5]20, [6]30, [7]40
removing 0
removing 20
removing 40
******current size is 5
[0]-80, [1]-70, [2]10, [3]-60, [4]30
7.7
a. Each time line 9 executes itr.nextIndex() returns a higher index. So the values 6.6
5.5 2.2 4.4 9.9 are inserted at indexes 0, 1, 2, 3, 4. Output from line 10 will be this:
current size is 5
b. Method printA() prints the values in order of their indexes. Method printB()
prints the values in reverse order of their indexes.
c. The ListIterator itr is moved from the end back to beginning of dList. All of
the values in the list are negated, changed to these: 6.6, 5.5, 2.2, 4.4, and 9.9.
d. Since itr is at the beginning of dList, the item at index 0 with value 6.6 is
removed, i.e. values are changed to these: 5.5, 2.2, 4.4, 9.9.
e. testing itr.add()
current size is 5
calling printB( dList )
[4]9.9
[3]-4.4
[2]-2.2
[1]5.5
[0]6.6
testing itr.set()
changing node at index 4
changing node at index 3
changing node at index 2
changing node at index 1
changing node at index 0
**current size is 5
calling printA( dList )
[0]-6.6
[1]-5.5
[2]2.2
[3]4.4
[4]-9.9
testing itr.remove()
current size is 4
calling printA( dList )
[0]-5.5
[1]2.2
[2]4.4
[3]-9.9
to
to
to
to
to
-9.9
4.4
2.2
-5.5
-6.6
74
Chapter 7 Collections
Programming Problems
7.1
7.2
7.3
public ArrayCollection() {
}
public ArrayCollection(int capacity) {
a = new Object[capacity];
}
public ArrayCollection(Object[] objects) {
a = new Object[objects.length];
for (int i=0; i<objects.length; i++)
if (objects[i] != null) a[size++] = objects[i];
}
public Object getLast() {
// returns a reference to the last element of this collection;
// or returns null if this collection is empty;
for (int i=a.length-1; i>=0; i--)
if (a[i] != null) return a[i];
return null;
}
public Object getLast(Collection collection) {
// returns a reference to the last element of the collection;
// or returns null if the given collection is empty;
Iterator it = collection.iterator();
Object object = null;
while (it.hasNext())
object = it.next();
return object;
}
7.4
for
Solutions
7.5
75
7.6
7.7
7.8
}
public int frequency(Collection collection, Object object) {
// returns the number of occurrences of the given object
// in the given collection;
Iterator it = collection.iterator();
int f=0;
while (it.hasNext())
if (it.next().equals(object)) ++f;
return f;
}
public boolean removeOdd() {
// removes every other element (the first, the third, etc.) from
// this collection; returns true iff this collection is changed;
if (size < 2) return false;
Node p=head.next;
while (p.next!=head) {
p = p.next = p.next.next;
--size;
}
return true;
}
76
7.9
7.10
Chapter 7 Collections
public boolean removeOdd(Collection collection) {
// removes every other element (the first, the third, etc.)
// from the given collection; returns true iff it is changed;
if (collection.size() < 2) return false;
Iterator it = collection.iterator();
while (it.hasNext()) {
it.next();
if (it.hasNext()) {
it.next();
it.remove();
}
}
return true;
}
public class LinkedCollection extends AbstractCollection {
private static class Node {
Object object;
Node prev, next;
Node() { prev = next = this; }
Node(Object o, Node p, Node n) { object=o; prev=p; next=n; }
}
private int size;
private Node head = new Node(); // dummy head node
private Node tail = new Node(); // dummy tail node
public LinkedCollection() {
head.next = head.prev = tail;
tail.next = tail.prev = head;
}
public boolean add(Object object) {
tail.prev = tail.prev.next = new Node(object, tail.prev, tail);
++size;
return true; // no object is rejected
}
public Iterator iterator() {
return new Iterator() {
// anonymous inner class
private Node cursor=head.next; // current element node
private boolean okToRemove=false;
public boolean hasNext() { return cursor != tail; }
Solutions
77
public Object next() {
if (cursor == head) throw new RuntimeException();
okToRemove = true;
Object object=cursor.object;
cursor = cursor.next;
return object;
}
public void remove() {
if (!okToRemove) throw new IllegalStateException();
cursor.prev = cursor.prev.prev;
cursor.prev.next = cursor;
--size;
okToRemove = false; // must call next() again before remove()
}
};
}
public int size() {
return size;
}
7.11
7.12
7.13
7.14
78
Chapter 7 Collections
}
return changed;
}
7.15
Chapter 8
Lists
Exercises
8.1
8.2
8.3
8.4
One.
It depends upon the initial contents of the list. If it has fewer than six elements, then the
call set(6, "BE") will throw an IndexOutOfBoundsException. Otherwise, the end
result would be to insert "BE" at position 6 while shifting the existing elements that are in
positions 26 down to positions 15. The existing element at position 2 will be returned.
a. See Figure 8.1 on the next page.
b. See Figure 8.2 on the next page.
a. There are n + 1 terms. The average exponent for the n non-constant terms is n/2. So
the total number of operations averages n(n/2) = (n 2 ).
b. With Horners method, there are only n multiplications and n additions. So the total
number of operations is 2n = (n).
Programming Problems
8.1
8.2
79
80
Chapter 8 Lists
print(g8);
g8.remove(6);
print(g8);
}
void print(Sequence s) {
for (Iterator it = s.iterator(); it.hasNext(); )
System.out.print(it.next() + " ");
System.out.println();
}
public static void main(String[] args) {
new TestSequence();
}
}
head
Polynomial
term
next
Node
head
Polynomial
term
coef
next
exp
Node
term
next
Node
term
next
Node
term
next
Node
Figure 8.1
0.0
-1
Term
Term
Term
Term
next
term
next
Node
coef 6.71
exp
term
Node
coef -9.4
exp
next
Node
coef 7.83
exp
term
term
next
Node
Figure 8.2
coef
exp
0.0
-1
Term
coef 1.83
exp
Term
coef
exp
6.0
4
Term
coef -9.4
exp
Term
coef 6.71
exp
Term
Solutions
8.3
8.4
81
82
Chapter 8 Lists
System.out.println("p3: " + p3);
System.out.println("p3.degree(): " + p3.degree());
p1 = p1.times(new Polynomial(-5.0, 3));
System.out.println(p1);
System.out.println("p1.degree(): " + p1.degree());
System.out.println("p1.valueAt(1.0): " + p1.valueAt(1.0));
System.out.println("p1.valueAt(-1.0): " + p1.valueAt(-1.0));
System.out.println("p1.valueAt(2.0): " + p1.valueAt(2.0));
p1 = p1.times(new Polynomial(5.0, -3));
}
public static void main(String[] args) {
new TestPolynomial();
}
8.5
8.6
8.7
}
public Polynomial(double[] c) {
Node p = head;
for (int i = c.length - 1; i >= 0; i--)
if (c[i] != 0.0) p = p.next = new Node(new Term(c[i], i), head);
}
public double[] toArray() {
int n = degree() + 1;
double[] a = new double[n];
for (int i=0; i<n; i++)
a[i] = 0.0;
for (Node p = head.next; p != head; p = p.next)
a[p.exp] = p.coef;
return a;
}
public Polynomial derivative() {
if (degree() < 1) return ZERO;
Polynomial poly = new Polynomial();
for (Node p = head.next; p != head; p = p.next) {
double coef = p.exp*p.coef;
if (coef != 0 && p.exp > 0)
poly = poly.plus(new Polynomial(coef, p.exp-1));
}
return poly;
}
Solutions
8.8
83
public class Polynomial {
private Node head = new Node(); // dummy node;
public static final Polynomial ZERO = new Polynomial();
private Polynomial() {
}
public Polynomial(double coef, int exp) {
head.next = new Node(coef, exp, head);
}
public Polynomial(Polynomial that) { // copy constructor
Node p = this.head, q = that.head.next;
while (q != that.head) {
p = p.next = new Node(q);
p.next = head;
q = q.next;
}
}
public int degree() {
return head.next.exp;
}
public boolean equals(Object object) {
if (!(object instanceof Polynomial)) return false;
Polynomial that = (Polynomial)object;
Node p = this.head.next, q = that.head.next;
while (q != that.head) {
if (p.coef != q.coef || p.exp != q.exp) return false;
p = p.next;
q = q.next;
}
return p == head;
}
public Polynomial plus(Polynomial that) {
if (this.equals(ZERO)) return new Polynomial(that);
if (that.equals(ZERO)) return new Polynomial(this);
Polynomial sum = new Polynomial(this);
Node p = sum.head, q = that.head.next;
while (p.next != sum.head && q != that.head) {
84
Chapter 8 Lists
if (p.next.exp <= q.exp) {
if (p.next.exp == q.exp) p.next.coef += q.coef;
else p.next = new Node(q.coef, q.exp, p.next);
q = q.next;
}
p = p.next;
}
if (q != that.head) p.next = new Node(q.coef, q.exp, p.next);
return sum;
}
public Polynomial times(double factor) {
if (this.equals(ZERO) || factor==0.0) return ZERO;
Polynomial result = new Polynomial(this);
for (Node p = result.head.next; p != result.head; p = p.next)
p.coef *= factor;
return result;
}
public Polynomial times(Polynomial that) {
if (this.equals(ZERO) || that.equals(ZERO)) return ZERO;
Polynomial result = ZERO;
for (Node p = this.head.next; p != this.head; p = p.next) {
Polynomial temp = new Polynomial(that);
for (Node q = temp.head.next; q != temp.head; q = q.next){
q.coef *= p.coef;
q.exp += p.exp;
}
result = result.plus(temp);
}
return result;
}
public double[] toArray() {
int n = degree() + 1;
double[] a = new double[n];
for (int i=0; i<n; i++)
a[i] = 0.0;
for (Node p = head.next; p != head; p = p.next)
a[p.exp] = p.coef;
return a;
}
Solutions
85
Chapter 9
Lists
Exercises
9.1
9.2
9.3
9.4
9.5
No.
Suppose Ann and Bob both hash to 5 in an empty hash table with open addressing.
If Ann is inserted first, it will be put in slot 5, and Bob will be put in slot 6. But if
Bob is inserted first, it will be put in slot 5, and Ann will be put in slot 6.
See the solution on page 515.
a. Let f(x) = lnx and g(x) = (x1/x)/2 for x 1. Then f(x) = 1/x and g(x) = (1+1/x2)/2.
Since 0 (1x)2 = 1 2x + x2, we have 2x 1 + x2, so 1/x (1+1/x2)/2. Thus, f(x)
g(x) for all x 1, and f(1) = 0 = g(1). Therefore f(x) g(x) for all x 1; i.e., lnx (x
1/x)/2. Letting q = x and r = 11/x (so that q = 1/(1r)), we have lnq (x1/x)/2 = (x2
1)/(2x) = r(2r)/(2(1r)). Thus, lnq rlnq = (1r)lnq r(2r)/2 = r r2/2, lnq r +
rlnq r2/2 = r(1 + lnq r/2), so (lnq)/r 1 + lnq r/2.
b. This is true because (lnq)/r = 1 + r/2 + r2/3 + ... 1 + r/2.
c. This is true because 0 < r < 1, so r(1r) < 1 and r < 1/(1r) = q.
d. This is true because 0 < r < 1, so (1r) < 1 and q = 1/(1r) > 1; thus q2 > q and
(1 + q2)/2 > (1 + q)/2.
e. Ths follows directly from the fact that q = 1 + r + r2 + r3 + ...
f. Ths follows directly from the fact that (lnq)/r = 1 + r/2 + r2/3 + r3/4 + ...
With linear probing, we dont need more than n = size probes. After finding n other elements, we will have checked them all and well know that the key is not in the table. You
cant have more than n collisions.
The same is true with quadratic probing, although the put() method may fail once the
load factor exceeds 50%, since the probe sequence reaches only half the slots.
The same is true with double hashing.
The worst case would be where all the keys are in one contiguous block.
86
Solutions
87
9.6
This design would occupy a very large file. For example, if the keys are 100-byte strings,
it would occupoy 200 GB. So this design would be very wasteful of space unless the table
size were in the range of a hundred million.
This hash function is not perfect because the Java hashCode() method is not one-to-one.
9.7
With double hashing, the probe sequence is arithmetic, with a constant difference equal to
the secondary hash value. If the array length is prime, then the probe sequence will reach
every index of the array.
As an example of what can go wrong when the length is not prime, suppose it is 12. If the
secondary hash value is a divisor (1, 2, 3, 4, or 6), then the probe sequence will not reach all
the table slots. For example, suppose the primary hash value is 5 and the secondary hash
value is 4. Then the probe sequence is 5, 9, 1, 5, 9, 1, 5, ... If slots 1, 5, and 9 are occupied,
then the insert will fail even if the table is only 25% full.
Programming Problems
9.1
9.2
9.5
// Quadratic Probing
88
9.6
Chapter 9 Lists
public class HashTable implements Map { // open addressing
private Entry[] entries;
private int size, used;
private float loadFactor;
private final Entry NIL = new Entry(null,null); // dummy
public HashTable(int capacity, float loadFactor) {
entries = new Entry[capacity];
this.loadFactor = loadFactor;
}
public HashTable(int capacity) {
this(capacity,0.75F);
}
public HashTable() {
this(101);
}
public Object get(Object key) {
int h=hash(key);
int h2=hash2(key);
for (int i=0; i<entries.length; i++) {
int j = nextProbe(h, h2, i);
Entry entry=entries[j];
if (entry==null) break;
if (entry==NIL) continue;
if (entry.key.equals(key)) return entry.value;
}
return null; // failure: key not found
}
public Object put(Object key, Object value) {
if (used>loadFactor*entries.length) rehash();
int h=hash(key);
int h2=hash2(key);
for (int i=0; i<entries.length; i++) {
int j = nextProbe(h, h2, i);
Entry entry=entries[j];
if (entry==null) {
entries[j] = new Entry(key,value);
++size;
// success
Solutions
89
++used;
return null;
// insertion success
}
if (entry==NIL) continue;
if (entry.key.equals(key)) {
Object oldValue=entry.value;
entries[j].value = value;
return oldValue; // update success
}
}
return null;
}
public Object remove(Object key) {
int h=hash(key);
int h2=hash2(key);
for (int i=0; i<entries.length; i++) {
int j = nextProbe(h, h2, i);
Entry entry=entries[j];
if (entry==null) break;
if (entry==NIL) continue;
if (entry.key.equals(key)) {
Object oldValue=entry.value;
entries[j] = NIL;
--size;
return oldValue; // success
}
}
return null; // failure: key not found
}
public int size() {
return size;
}
public String toString() {
StringBuffer buf = new StringBuffer();
for (int i=0; i<entries.length; i++)
if (entries[i] != null)
buf.append(entries[i].key + ": " + entries[i].value + "\n");
return buf.toString();
}
90
Chapter 9 Lists
Solutions
9.7
91
92
Chapter 9 Lists
while (table[k] != null && j<m) {
++c;
k = quad(h, ++j);
System.out.print(" -> " + k);
}
table[k] = s;
System.out.println();
}
System.out.println(c + " collisions.");
}
public static void main(String[] args) {
new Main();
}
9.8
}
public class Main {
int m = 17; // table size
String[] data = {"AT","BE","DE","DK","ES","FR","IT","LU","SE"};
int n = data.length;
private int hash(String key) {
return key.hashCode() % m;
}
private int hash2(String key) {
return 1 + key.hashCode() % (m-1);
}
private int lin(int h, int i) {
return (h + i) % m;
}
private int doub(int h, int h2, int i) {
return (h + i*h2) % m;
}
public Main() {
System.out.println("Linear Probing:");
String[] table = new String[m];
int c=0;
for (int i=0; i<n; i++) {
String s = data[i];
Solutions
93
int j=0, h=hash(s), k = h;
System.out.print((i<9?"
":" ") + (i+1) + ". " + s +" -> "+h);
while (table[k] != null && j<m) {
++c;
k = lin(h, ++j);
System.out.print(" -> " + k);
}
table[k] = s;
System.out.println();
}
System.out.println(c + " collisions.");
System.out.println("Double Hashing:");
table = new String[m];
c=0;
for (int i=0; i<n; i++) {
String s = data[i];
int j=0, h=hash(s), k = h, h2=hash2(s);
System.out.print((i<9?"
":" ") + (i+1) + ". " + s +" -> "+h);
while (table[k] != null && j<m) {
++c;
k = doub(h, h2, ++j);
System.out.print(" -> " + k);
}
table[k] = s;
System.out.println();
}
System.out.println(c + " collisions.");
}
public static void main(String[] args) {
new Main();
}
Chapter 10
Recursion
Exercises
10.1
10.2
10.3
a.
b.
c.
-6
search(a,3,6,905)
7
search(a,0,10,905)
-6
search(a,5,6,905)
-6
search(a,3,6,910)
-6
7
search(a,6,10,905)
search(a,3,6,910)
7
search(a,6,8,905)
10.4
print(3,'A','B','C')
print(2,'A','C','B')
print(1,'A','B','C')
print(2,'C','B','A')
print(1,'C','A','B')
print(1,'B','C','A')
print(3,'A','B','C')
94
Solutions
10.5
10.6
10.7
10.8
10.9
95
a. 15.
b. 31.
c. 2n 1.
Let f(n) be the number of moves for n disks, and let g(n) = 2n 1.
If n = 1, it makes 1 move, and g(1) = 21 1 = 1. Thus, f(1) = g(1).
If n > 1, then it makes f(n 1) + 1 + f(n 1) moves; i.e., f(n) = 2f(n 1) + 1. By the inductive hypothesis, f(n 1) = g(n 1) = 2n1 1. Thus, f(n) = 2(2n1 1) + 1 = 2n 1 = g(n).
Thus, f(n) = g(n) for all n 1.
40.
Let f(n) = n! and let g(n) = 2n.
Then f(4) = 4! = 24 > 16 = 24 = g(4).
If n > 4, then f(n) = n! = n (n 1)! = n f(n 1) > n g(n 1), by the inductive hypothesis.
Thus, f(n) > n g(n 1) > 2g(n 1), since n > 2. Thus, f(n) > 2g(n 1) = 2 2n1 = 2n =
g(n). Thus, f(n) > g(n) for all n 4. Thus, g(n)/f(n) < 1 for all n 4; i.e., g(n)/f(n) is
bounded.
F1 + F2 + F3 + + F10 = 1 + 1 + 2 + 3 + 5 + 8 + 13 + 21 + 34 + 55 = 143 = 144 1
= F12 1. More generally:
F0 + F1 + F2 + + Fn = (F2 F1 ) + (F3 F2 ) + (F4 F3 ) + + (Fn +2 Fn 1 )
The sum on the right telescopes, leaving Fn +2 F1 . Thus:
F0 + F1 + F2 + + Fn = Fn +2 F1 = Fn +2 1
Let T(n) be the run time for the recursive Fibonacci function f(n). Then:
T(n ) = c + T(n 1) + T(n 2)
> c + 2T ( n 2 )
> c + 2 [ c + 2T ( n 4 ) ]
= 3c + 4T ( n 4 )
> 3c + 4 [ c + 2T ( n 2 ) ]
= 7c + 8T ( n 6 )
= ( 2 1 )c + 2 T ( n 2k )
96
Chapter 10 Recursion
10.10
1+ 5
= ---------------2
1 5
= ---------------2
1+ 5 1 5
2
+ = ---------------- + ---------------- = --- = 1
2
2
2
1+ 5 1 5
2 5
= ---------------- ---------------- = ---------- =
2
2
2
2
1+ 5 2
1+2 5+5
6+2 5
3+ 5
1+ 5 2
= ---------------- = ----------------------------- = ------------------- = ---------------- = ---------------- + --- = + 1
2
4
4
2
2
2
2
1 5 2
12 5+5
62 5
3 5
1 5 2
= ---------------- = ---------------------------- = ------------------- = ---------------- = ---------------- + --- = + 1
2
4
4
2
2
2
a.
f n = -----------------5
11
f 0 = ------------------ = ------------ = 0
5
5
5
f 1 = ------------------ = ------------- = ------- = 1
5
5
5
( + 1) ( + 1)
b.
n1
n1
n2
n2
f n 1 + f n 2 = -------------------------------- + -------------------------------5
5
n1
n2
n1
n2
1
= ------- [ (
+
) (
+
)]
5
1
n2
n2
= ------- [ ( + 1 )
( + 1 )
]
5
1
2 n2
2
n2
= ------- [ ( )
( )
]
5
1 n
n
= ------- [ ]
5
= fn
10.11
On each iteration x is halved. Therefore, the number of iterations that it takes to reduce x
from 1.0 to 0.01 is lg(1.0/0.01) = lg(1/0.01). More generally, the number of iterations to
reduce x to 1/t will be lg(1/t); i.e., the run-time is T = (lg(1/t)) Thus, if t = t2, then
T = (lg(1/t)) = (lg(1/t2)) = (lg((1/t)2)) = (2lg(1/t)) = 2(lg(1/t)) = 2T.
Solutions
10.12
97
If n is even, then T(n) = c1 + T(n/2), and (since then n + 1 will be odd), then T(n + 1) =
c2 + T(n) = c2 + c1 + T(n/2). Thus, on average, T(n) = c + T(n/2). The same analysis as on
page 314 then applies to obtain T(n) = (lgn).
10.13
2100
exp(2,100)
250
exp(2,50)
225
exp(2,25)
224
exp(2,24)
212
exp(2,12)
26
exp(2,6)
23
exp(2,3)
22
exp(2,2)
21
exp(2,1)
98
Chapter 10 Recursion
Programming Problems
10.1
10.2
10.3
Solutions
99
public static void main(String[] args) {
BigInteger f0 = new BigInteger("0");
BigInteger f1 = new BigInteger("1");
BigInteger f2 = new BigInteger("1");
for (int i=3; i<=1000; i++) {
f0 = f1;
f1 = f2;
f2 = f0.add(f1);
if (i > 997)
System.out.println("f(" + i + ") =\t" + f2);
}
}
10.4
10.5
}
public class TestBinarySearch {
TestBinarySearch() {
int[] a = {22, 33, 44, 55, 66, 77, 88, 99};
int n = a.length;
System.out.println("search(" + 55 + "): " + search(a, 0, n, 55));
System.out.println("search(" + 50 + "): " + search(a, 0, n, 50));
}
int search(int[] a, int p, int q, int x) {
if (q <= p) return -p-1; // base
int m = (p + q)/2;
if (a[m] == x) return m;
if (a[m] < x) return search(a, m+1, q, x);
return search(a, p, m, x);
}
public static void main(String[] args) {
new TestBinarySearch();
}
}
public class TestExp {
TestExp() {
System.out.println("exp1(3, 4): " + exp1(3, 4));
System.out.println("exp2(3, 4): " + exp2(3, 4));
System.out.println("exp1(5, -2): " + exp1(5, -2));
System.out.println("exp2(5, -2): " + exp2(5, -2));
System.out.println("exp1(2, -5): " + exp1(2, -5));
System.out.println("exp2(2, -5): " + exp2(2, -5));
}
100
Chapter 10 Recursion
double exp1(double x, int n) {
if (n == 0) return 1.0;
if (n < 0) return 1.0/exp1(x, -n);
double y = 1.0;
for (int i = 0; i < n; i++)
y *= x;
return y;
}
double exp2(double x, int n) {
if (n == 0) return 1.0;
if (n < 0) return 1.0/exp2(x, -n);
double factor = (n%2 == 0 ? 1.0 : x);
if (n < 2) return factor;
// base
return factor*exp2(x*x, n/2);
// recursion
}
public static void main(String[] args) {
new TestExp();
}
10.6
10.7
}
public double valueAt(double x) {
if (this.equals(ZERO)) return 0.0;
double y = 0.0;
int e = exp;
Poly p = this;
while (p != null) {
for (int i=1; i < e - p.exp; i++)
y *= x;
y += p.coef;
e = p.exp;
p = p.next;
}
return y;
}
String commaString(long n) {
String s="";
int c = 0;
while (n > 0) {
if (c>0 && c%3==0) s = "," + s;
s = (n%10) + s;
n /= 10;
++c;
}
Solutions
10.8
10.9
10.10
10.11
10.12
return s;
}
String commaString(long n) {
String s="";
if (n==0) return "0";
for (int i=0; i<3; i++) {
s = (n%10) + s;
n /= 10;
if (n==0) return s;
}
return commaString(n) + "," + s; // recursion
}
int max(int[] a, int p, int q) {
if (q - p == 1) return a[p];
int m = (p + q)/2;
int max1 = max(a, p, m); // recursion
int max2 = max(a, m, q); // recursion
return ( max1 > max2 ? max1 : max2 );
}
int intBinLog(int n) {
if (n < 2) return 0;
return 1 + intBinLog(n/2); // recursion
}
boolean isPalindrome(String s) {
int n = s.length();
if (n < 2) return true;
if (s.charAt(0) != s.charAt(n-1)) return false;
return (isPalindrome(s.substring(1,n-1))); // recursion
}
String bin(int n) {
if (n == 0) return "0";
if (n == 1) return "1";
return bin(n/2) + bin(n%2); // recursion
}
String hex(int n) {
if (n < 10) return String.valueOf(n) ;
if (n < 16) {
switch (n) {
case 10: return "A";
case 11: return "B";
case 12: return "C";
case 13: return "D";
101
102
Chapter 10 Recursion
case 14: return "E";
case 15: return "F";
}
}
return hex(n/16) + hex(n%16);
10.13
10.14
10.15
10.16
10.17
// recursion
}
String reverse(String s) {
if (s.length() < 2) return new String(s);
return reverse(s.substring(1)) + s.charAt(0);
}
// recursion
// base
// recursion
// base
// recursion
Solutions
103
static double mathCos(double x) {
return Math.cos(x);
}
10.18
}
public class TestTrigFunctions {
public static void main(String[] args) {
for (double x=0.0; x<1.0; x+=0.1)
System.out.println(sin(x) + "\t" + mathSin(x));
for (double x=0.0; x<1.0; x+=0.1)
System.out.println(cos(x) + "\t" + mathCos(x));
}
static double sin(double x) {
if (-0.01<x && x<0.01) return x*(1 - x*x/6*(1 - x*x/20)); // base
return 2*sin(x/2)*cos(x/2);
// recursion
}
static double cos(double x) {
if (-0.01<x && x<0.01) return 1 - x*x/2*(1 - x*x/12); // base
double y = sin(x/2);
// recursion
return 1 - 2*y*y;
}
static double mathSin(double x) {
return Math.sin(x);
}
static double mathCos(double x) {
return Math.cos(x);
}
10.19
}
public class TestHyperbolicFunctions {
public static void main(String[] args) {
for (double x=0.0; x<1.0; x+=0.1)
System.out.println(sinh(x) + "\t" + mathSinh(x));
for (double x=0.0; x<1.0; x+=0.1)
System.out.println(cosh(x) + "\t" + mathCosh(x));
}
static double sinh(double x) {
if (-0.01<x && x<0.01) return x + x*x*x/6;
return 2*sinh(x/2)*cosh(x/2);
}
// base
// recursion
104
Chapter 10 Recursion
// base
// recursion
10.20
10.21
}
static double tan(double x) {
if (-0.01<x && x<0.01) return x + x*x*x/3; // base
double t = tan(x/2);
return 2*t/(1.0 - t*t);
// recursion
}
public class Timing {
static double tol = 0.01;
public static void main(String[] args) {
System.out.println(time(1e-2));
System.out.println(time(1e-3));
System.out.println(time(1e-4));
System.out.println(time(1e-5));
System.out.println(time(1e-6));
System.out.println(time(1e-7));
}
static long time(double t) {
long t1 = System.currentTimeMillis();
for (double x=0.0; x<1.0; x+=0.00001)
sin(x);
for (double x=0.0; x<1.0; x+=0.00001)
cos(x);
long t2 = System.currentTimeMillis();
return t2 - t1;
}
Solutions
105
static double sin(double x) {
if (-tol<x && x<tol) return x - x*x*x/6;
return 2*sin(x/2)*cos(x/2);
}
static double cos(double x) {
if (-tol<x && x<tol) return 1.0 - x*x/2;
double s = sin(x/2);
return 1 - 2*s*s;
}
// base
// recursion
// base
Chapter 11
Trees
Exercises
11.1
11.2
a.
b.
c.
d.
e.
f.
g.
h.
i.
j.
k.
l.
m.
a.
Depth=2; 2 ancestors
c.
d.
y
x
e.
Depth=1
Depth=2
Root is a leaf
Depth=1
Depth=2
f.
All 4 leaves are also leaves of T
h
106
Solutions
107
g.
h.
Root of subtree is not root of T
i.
j.
3 internal nodes; 2 leaves
A leaf has no children
k.
l.
All leaves at level 3
11.3
a.
b.
c.
d.
e.
11.4
11.5
11.6
11.7
11.8
final
a.
b.
c.
d.
e.
f.
g.
h.
i.
j.
C, F, H, J, L, M, N, O, P
G
2
4
D, A
J, K, L, M, O, P
H, I, J, K, L, M
4
6
4
m.
108
11.9
Chapter 11 Trees
a.
b.
c.
d.
129
85
1,111
1,398,101
11.10
h+1
d
1
n = -------------------d1
n(d 1) = d
h+1
nd n + 1 = d
h+1
log d ( nd n + 1 ) = h + 1
= logd ( nd n + 1 ) 1
h
11.11
11.12
w = number of leaves = d h
path length = 0 1 + 1 d + 2 d 2 + 3 d 3 + + h d h =
h
jd
j=0
jd
j=1i=1
i=1 j=i
d d
i hi
k=0
i=1
ji
j=i
i=1
hi+1
d
1
--------------------------d1
i=1
= (d 1)
1 h
(d
h+1
d )
i=1
h+1
1
h + 1 d
1
= ( d 1 ) hd
--------------------- 1
d1
= ( d 1 ) ( ( d 1 )hd
h+2
h+1
h+1
((d
hd
(h + 1) d
+ d= ------------------------------------------------------------2
(d 1)
h+1
1) + (d 1)))
Solutions
11.13
11.14
11.15
11.16
109
a. A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P
b. A, B, E, H, I, N, F, C, D, G, J, K, O, P, L, M
c. H, N, I, E, F, B, C, J, O, P, K, L, M, G, D, A
a. level order and preorder
b. postorder
c. postorder
d. preorder
Algorithm. Iterative Preorder Traversal
1. Create an empty stack.
2. Push the tree (root) onto the stack.
3. While the stack is not empty, do steps 4-6:
4.
Pop the stack to obtain x.
5.
Visit the root of x.
6.
Traverse the subtree list of x in reverse order, pushing each subtree onto
the stack
Let x by any internal node of a full tree of degree d. Let l be the level of node x, and let y
be the left-most node at that same level. Then, by Formula 11.4, the index of y is
i(y) = (d l 1)/(d 1), and the index of the first child y of y is i(y) = (d l+1 1)/(d 1).
Let k be the number of nodes on the left of x at the same level l. Then x has index
i(x) = (d l 1)/(d 1) + k. Since the tree is full, each node at level l had d children. Thus,
there are dk children on the left of the first child of x (at level l+1). Thus, the first child x
of x has index i(x) = (d l+1 1)/(d 1) + dk = (d l+1 1 + d 2k dk)/(d 1). This is the
same as di(x) + 1 = d[(d l 1)/(d 1) + k] + 1 = (d l+1 1 + d 2k dk)/(d 1). Thus the
index of the first child of x is di(x) + 1. Thus the indexes of all d children of x are
di(x) + 1, di(x) + 2, di(x) + 3, ..., di(x) + d.
110
Chapter 11 Trees
Programming Problems
11.1
import java.util.*;
public class OrderedTree {
private Object root;
private List subtrees;
private int size;
public OrderedTree() { // constructs the empty tree
}
public OrderedTree(Object root) { // constructs a singleton
this.root = root;
subtrees = new LinkedList(); // constructs the empty list
size = 1;
}
public OrderedTree(Object root, List trees) {
this(root);
for (Iterator it=trees.iterator(); it.hasNext(); ) {
Object object=it.next();
if (object instanceof OrderedTree) {
OrderedTree tree = (OrderedTree)object;
subtrees.add(tree);
size += tree.size();
}
}
}
public int size() {
return size;
}
11.2
}
public void levelOrderPrint() {
LinkedList queue = new LinkedList();
queue.addLast(this);
while (!queue.isEmpty()) {
OrderedTree tree = (OrderedTree)queue.removeFirst();
System.out.print(tree.root + " ");
for (Iterator it=tree.subtrees.iterator(); it.hasNext(); )
queue.addLast(it.next());
}
}
Solutions
11.3
11.4
11.5
111
Chapter 12
Binary Trees
Exercises
12.1
12.2
12.3
12.4
12.5
Let T be a binary tree of height h and size n. Having height h means that it must contain at
least one root-to-leaf path of length h. Any such path has h + 1 elements. Thus, n h + 1.
By Formula 12.1, the full binary tree of height h has 2 h+1 1 elements. If T is not full,
then it can be transformed into that full binary tree by adding elements. Thus, n 2 h+1 1.
By Formula 12.2, we have n 2 h+1 1. Thus n < n 1 2 h+1, so lg n < h + 1. Since
x x (see Formula C.1.3 on page 565), we have lg n lg n. Thus, lg n < h + 1. But
both lg n and h are integers. Thus, lg n h.
Let T be a complete binary tree of height h and size n. By Formula 12.1, n 2 h+1 1.
Moreover, T contains the full binary tree of height h 1 because T includes all the elements of the full binary tree of height h except possibly for some missing leaf elements at
level h. Therefore, n 2 (h 1)+1 1 = 2 h 1. But by having height h, T must include at
least one element at level h, which means that it must have at least one element more than
the complete binary tree of height h 1. Thus, n > 2 h 1. Therefore, n 2 h (since n and 2 h
are integers).
Let T be a complete binary tree of height h and size n. Then T includes all the elements of
the full binary tree of height h except possibly for some missing leaf elements at level h.
Therefore, T has more elements than the full binary tree of height h 1, but not more than
the full binary tree of height h. Thus, by Formula 12.1, 2 h = 2 (h 1)+1 < n 2 h+1 1. Thus,
h < lg n < h + 1. Therefore, by Formula C.1.4 on page 565, we have h = lg n.
Let n be the number of nodes at lebel l in a binary tree. If l = 0, then n = 1, since the only
node at that level is the root node. If l = 1, then n = 1 or 2, since the only nodes at that level
are the children of the root, and in a binary tree each node has at most 2 children. Similary,
at any level l, n is the number of children of the nodes at level l 1. By the induction
hypothesis, there are between 1 and 2 l 1 nodes at level l 1. Therefore, n must be
between 1 and 2(2 l 1) = 2 l.
112
Solutions
113
complete
12.6
12.7
complete
12.8
12.9
12.10
12.11
114
12.12
12.13
12.14
12.15
12.16
A
C
E
False. Every proper subtree of this binary tree is full, but the tree itself is not:
a. Level order: A B C D E F G H I J K L M N O P Q R S T U V
b. Preorder: A B D H E I J N O S C F K P T U G L M O V R
c. Inorder: D H B I E N J S O A F T P U K C L G V O M R
d. Postorder: H D I N S O J E B T U P K F L V O R M G C A
Prefix: - * 2 - 8 / 9 3 4
Infix: 2 * 8 - 9 / 3 - 4
4
*
Postfix: 2 8 9 3 / - * 4 Value: 6
2
8
/
9 3
12.17
Postfix: 8 7 5 - - 3 /
Infix: 8 - 7 - 5 / 3
/
3
(8 - (7 - 5)) / 3
Value: 2
12.18
Prefix: / - 0 1 + 1 3
Infix: 9 - 1 / 1 + 3
(9 - 1) / ( 1 + 3)
Value: 2
5
/
+
Solutions
12.20
115
Let T be complete binary tree of size n, and let p be the number of the first leaf and q be
the number of its last leaf. (For example, the tree in Figure 12.13 has n = 11, p = 5 and
q = 10.) Then clearly, q = n 1. Moreover, the parent of the last leaf is the last internal
node of the complete tree. By Formula 12.6, that internal node has number (q 1)/2. The
node to its right is the first leaf node, so p = (q 1)/2 + 1 = (q + 1)/2 = n/2.
12.21
A
B
D
K
P
C
T
12.22
A
B
D
H
E
CI
L
C
F
M
G
N
O
P
S
Q
C
T
U
V
116
Programming Problems
12.1
Solutions
117
this.left = tree;
return oldLeft;
}
public BinaryTree setRight(BinaryTree tree) {
BinaryTree oldRight = this.right;
this.right = tree;
return oldRight;
}
12.2
12.3
12.4
12.5
12.6
12.7
118
12.8
12.9
12.10
12.11
12.12
12.13
Solutions
12.14
12.15
12.16
12.17
119
return -1;
}
public boolean isDisjointFrom(BinaryTree that) {
if (that==null) return true;
if (this.contains(that.root)) return false;
return this.isDisjointFrom(that.left)
&& this.isDisjointFrom(that.right);
}
public boolean isValid() {
if (left==null && right==null) return true;
if (left==null) // so right!=null
if (right.contains(this.root) || !right.isValid())
return false;
if (right==null) // so left!=null
if (left.contains(this.root) || !left.isValid())
return false;
return left.isDisjointFrom(right);
}
public boolean equals(Object object) {
if (this == object) return true;
if (!(object instanceof BinaryTree)) return false;
BinaryTree that = (BinaryTree)object;
if (!this.root.equals(that.root)) return false;
boolean leftEqual = this.left==null && that.left==null
|| this.left!=null && this.left.equals(that.left);
boolean rightEqual = this.right==null && that.right==null
|| this.right!=null && this.right.equals(that.right);
return leftEqual && rightEqual;
}
public void preorderPrint() {
if (left!=null) left.preorderPrint();
System.out.print(root + " ");
if (right!=null) right.preorderPrint();
}
public void inorderPrint() {
if (left!=null) left.inorderPrint();
System.out.print(root + " ");
if (right!=null) right.inorderPrint();
}
public void postorderPrint() {
if (left!=null) left.postorderPrint();
if (right!=null) right.postorderPrint();
120
12.18
Chapter 13
Lists
Exercises
121
122
Chapter 13 Lists
13.1
55
22
77
18
44
70
30
27
60
33
88
74
80
94
66
63
69
55
50
22
77
18
44
30
27
70
50
60
33
88
74
80
94
66
63
69
55
20
22
77
18
44
20
30
27
70
50
60
33
88
74
80
94
66
63
69
55
90
22
77
18
44
20
30
27
70
50
60
33
74
66
63
88
80
94
90
69
Solutions
123
13.2
55
22
77
18
44
70
30
27
88
60
33
74
80
94
66
63
69
55
-18
22
77
44
70
30
27
60
33
74
80
63
69
27
77
44
70
30
60
33
88
74
80
94
66
63
69
55
-70
27
77
44
74
30
88
60
33
80
94
66
63
55
-77
27
69
80
44
30
94
66
55
-22
88
74
60
33
94
66
63
88
69
124
Chapter 13 Lists
13.3
44
44
88
44
55
44
88
88
55
44
44
77
88
33
33
88
55
55
77
77
44
99
44
33
88
66
55
33
88
99
55
99
77
77
66
44
22
44
33
88
22
55
25
99
77
33
88
55
99
25
55
99
77
66
44
22
22
88
25
66
75
33
77
66
75
Solutions
13.4
13.5
125
If y is the inorder successor of x in a BST, then the result of deleting x and y is independent
of the order in which they are deleted.
a. True: the BST property holds for all the elements of the subtree.
b. False: the root key may not be less than all the keys in the right subtree.
c. False: here are the two
(different) BSTs resulting
44
44
88
44
from inserting 44 and 88
88
in different orders:
d. True: the balance number
of a node depends entirely
88
88
44
88
on the heights of its two
44
subtrees.
e. False: the two subtrees
could have heights that differ by more than 1.
13.6
13.7
13.8
T2
There is 1 AVL tree of height 1 and 3 AVL trees of height 2. So the number of AVL trees
of height 3 is 33 + 2(31) = 15. Thus, the number of AVL trees of height 4 is
1515 + 2(153) = 315.
T4
T5
126
Chapter 13 Lists
13.9
h2
Th 2 2
h2
1.5
h1
Th 1 2
h1
Th = Th 1 + Th 2 + 1
2
<2
h1
h1
+2
T h 1.5
> 1.5
h1
+2
h2
h1
+ 1.5
+2
+1
h2
= 2
h2
+1
+ 1.5
h2
h2
= 2.5 ( 1.5
h2
) = 1.5
h2
13.10
1
A ( n ) = --n
n1
1
= --n
n1
Ai ( n )
i=0
i=0
1
= ----2n
1--- --ini1
+ [ 1 + A ( i ) ] + ------------------- [ 1 + A ( n i 1 ) ]
n n
n
n1
n1
n1
i=0
i=0
i=0
1
= ----2- n + 2
n
1 2
= --- + ----2n n
n1
i [1 + A(i )]
i=0
n1
n1
i=0
i=0
i + i A( i)
1 2 ( n 1 )n
= --- + ----2- -------------------- +
n n
2
2
= 1 + ----2n
n1
i A( i)
i=0
n1
i A(i)
i=0
Solutions
127
13.11
2
A ( n ) = 1 + ----2n
2
n1
i A(i)
i=0
n A(n) = n + 2
n1
i A(i)
i=0
2
(n + 1 ) A(n + 1) = (n + 1 ) + 2
i A(i)
i=0
(n + 1 ) A(n + 1) n A(n ) = [ (n + 1) n ] + 2
i A( i)
i=0
2
( n + 1 ) A ( n + 1 ) n A ( n ) = [ 2n + 1 ] + 2 [ nA ( n ) ]
2
( n + 1 ) A ( n + 1 ) ( n + 2n )A ( n ) = 2n + 1
n + 2n )A ( n )2n + 1
(---------------------------------------n + 1 ) A ( n + 1 )- (---------------------------------
= ---------------------------------(n + 1)(n + 2)
(n + 1)(n + 2)
( n + 1 )( n + 2 )
(-------------------------------------n + 1 ) A ( n + 1 )- n--------------A(n)
2n + 1
= ---------------------------------n+2
n+1
(n + 1)(n + 2)
n----------+ 1n
2n + 1
A ( n + 1 ) ------------ A ( n ) = ---------------------------------n+2
n+1
(n + 1)(n + 2)
2n + 1
n
+ 1-
n----------A ( n + 1 ) = ------------ A ( n ) + --------------------------------- n + 1
n + 2
(n + 1 )(n + 2 )
n1
i A(i)
i=0
128
Chapter 13 Lists
13.12
m
f ( m ) = ------------- A ( m )
m + 1
1
1
1
f ( 1 ) = --- A ( 1 ) = --- ( 1 ) = --2
2
2
2n + 1
f ( n + 1 ) = f ( n ) + ---------------------------------( n + 1 )( n + 2 )
2(1) + 1
1
3
f ( 2 ) = f ( 1 ) + -------------------------------------------- = --- + ---------( (1 ) + 1 )( (1 ) + 2 )
2 23
5
2(2) + 1
1
3
f ( 3 ) = f ( 2 ) + -------------------------------------------- = --- + ---------- + ---------34
( (2 ) + 1 )( (2 ) + 2 )
2 23
2(3) + 1
1
3
5
7
f ( 4 ) = f ( 3 ) + -------------------------------------------- = --- + ---------- + ---------- + --------- 2 2 3 3 4 4 5
( (3 ) + 1 )( (3 ) + 2 )
etc .
1
3
5
7
2n 1
f ( n ) = ---------- + ---------- + ---------- + ---------- + + -------------------12 23 34 45
n(n + 1 )
f( n) =
2k 1
------------------k( k + 1)
k=1
Solutions
129
13.13
f(n) =
2k 1
------------------k(k + 1)
k=1
= 2
k=1
= 2
k=1
k=1
-
-- k----------+1 k
k=1
= 3
--- ------------
-
k----------+ 1 k k + 1
k=1
= 3
------------------ k------------------( k + 1) k( k + 1)
n+1
k=1
--k- --k-
k=2
k=1
n + 1
n + 1
1
1
1
= 3 --- 1 --- ------------
k
k n + 1
k = 1
k = 1
1
= 3 ( H n + 1 1 ) H n + 1 ------------
n + 1
1
= 2H n + 1 3 + -----------n+1
130
13.14
Chapter 13 Lists
The largest B-tree of degree m and height h has the maximum m 1 keys in each node,
and every internal node has the maximum m children. Thus, it has 1 node at level 0, m
nodes at level 1, m2 nodes at level 2, m3 nodes at level 3, etc. The total number of nodes is:
h+1
2
3
h
1
m
1 + m + m + m + + m = ----------------------m1
Since each node has m 1 keys, the total maximum number of keys is m h +1 1.
The smallest B-tree of degree m and height h has 1 key in its root and the minimum
m/2 keys in every other node. Let x = m/2. Then this minimal B-tree has 1 node at
level 0, 2 nodes at level 1, 2x nodes at level 2, 2x2 nodes at level 3, etc. The total number
of non-root nodes is:
2
2 + 2x + 2x + + 2x
h1
= 2 ( 1 + 2x + 2x + + 2x
h1
x 1
= 2 --------------
x1
Since each non-root node has x 1 keys, the total number of keys in all of the non-root
nodes is:
h
x 1
h
( x 1 ) 2 -------------- = 2 ( x 1 )
x 1
h
= 2x 2
13.15
There is one key in the root. Thus the total minimum number of keys is 2 m/2 h 1.
Let x = m/2. Then we have from Formula 13.8: 2 x h 1 n. Solving for x h:
h
2x 1 n
h
2x n + 1
h n+1
x -----------2
Solutions
131
Programming Problems
13.1
13.2
13.3
13.4
13.5
132
Chapter 13 Lists
if (x < key) return left.get(x);
return right.get(x);
13.6
13.7
}
public boolean equals(Object object) {
if (object == this) return true;
if (!(object instanceof AVLTree)) return false;
AVLTree that = (AVLTree)object;
if (that.key != this.key) return false;
if (that.height != this.height) return false;
return that.left.equals(this.left) &&
that.right.equals(this.right);
}
public AVLTree(int[] a) {
this(a[0]);
for (int i=1; i<a.length; i++)
add(a[i]);
}
Chapter 14
Heaps and Priority Queues
Exercises
14.1
14.2
14.3
14.4
14.5
14.6
133
134
14.7
44
44
44
66
66
66
44
66
88
66
33
44
88
44
33
88
66
88
33
77
66
44
44
88
33
77
88
77
44
33
33
55
88
77
66
44
33
66
77
55
44
55
66
33
88
22
77
44
14.8
14.9
14.10
14.11
14.12
55
66
33
22
44
44
33
66 44 33
77
88 77 33 44 66
22
88 77 33 44 66 55 22
66
66 44
88
88 66 33 44
55
88 77 33 44 66 55
Solutions
14.13
14.14
14.15
14.16
135
If elements A, B, C, and D with keys 44, 44, 33, and 22, are inserted in that order, A will
be removed before B. But if their keys are 44, 44, 33, and 66, then B will be removed
before A.
Each iteration of the loop moves the larger child up to become the parent of its sibling.
The loop stops when neither child is greater than the original x value, which is copied into
the last position vacated by the loop. This renders the affected path descending, all the way
down to the leaf level. Since the first step of the loop moves the maximum element up into
the root, the precondition guarantees that all other root-to-leaf paths are now descending.
If S is a subtree of T, then every root-to-leaf path in S is part of some root-to-leaf path in T.
So if T is a heap, then every root-to-leaf path in S must be descending.
The derivation on page 419 shows that W(n) is the greatest number of comparisons that
the Build Heap algorithm can make on a hep of size n, where W(n) = 2W(n) + 2 lgn. We
show by direct substitution that f(n) = 5n 2 lgn 4 is a solution to this recurrence equation:
f(n 2) =
=
=
=
2f ( n 2 ) + 2lgn =
=
=
=
14.17
14.18
5 ( n 2 ) 2lg ( n 2 ) 4
5n 2 2 ( lgn lg2 ) 4
5n 2 2 ( lgn 1 ) 4
5n 2 2lgn 2
2 ( 5n 2 2lgn 2 ) + 2lgn
5n 4lgn 4 + 2lgn
5n 2lgn 4
f( n)
136
Programming Problems
14.1
14.2
14.3
Solutions
137
public Object remove() {
Object best = best();
list.remove(best);
return best;
}
public int size() {
return list.size();
}
14.4
import java.util.*;
public class SortedListPriorityQueue implements PriorityQueue {
private List list = new LinkedList();
public void add(Object object) {
if (!(object instanceof Comparable))
throw new IllegalArgumentException();
if (list.isEmpty()) {
list.add(object);
return;
}
Iterator it=list.iterator();
Comparable x = (Comparable)object;
int i=0;
while (it.hasNext()) {
Comparable y = (Comparable)it.next();
if (y.compareTo(x) <= 0) break;
++i;
}
list.add(i, x);
}
public Object best() {
if (list.isEmpty()) throw new IllegalMonitorStateException();
return list.get(0);
}
public Object remove() {
return list.remove(0);
}
public int size() {
return list.size();
}
}
138
14.5
14.6
Solutions
139
IntArrays.print(a);
}
public static void main(String[] args) {
new TestHeapify();
}
void heapify(int[] a, int i, int n) {
if (i >= n/2) return;
// a[i] is a leaf
int j = 2*i + 1;
if (j+1 < n && a[j+1] > a[j]) ++j;
if (a[j] <= a[i]) return;
int ai = a[i];
a[i] = a[j];
a[j] = ai;
heapify(a, j, n);
}
14.7
}
public class PQStack implements Stack {
private PriorityQueue pq = new HeapPriorityQueue();
private static int nextIndex;
private static class PQElement implements Comparable {
Object object;
int index;
PQElement(Object object) {
this.object = object;
this.index = PQStack.nextIndex++;
}
public int compareTo(Object object) {
PQElement that = (PQElement)object;
Long diff = new Long(this.index - that.index);
return diff.intValue();
}
}
public void push(Object object) {
pq.add(new PQElement(object));
}
public Object peek() {
PQElement e = (PQElement)pq.best();
return e.object;
}
public boolean isEmpty() {
return pq.size()==0;
}
140
14.8
}
public class PQQueue implements Queue {
private PriorityQueue pq = new HeapPriorityQueue();
private static int nextIndex;
private static class PQElement implements Comparable {
Object object;
int index;
PQElement(Object object) {
this.object = object;
this.index = PQQueue.nextIndex++;
}
public int compareTo(Object object) {
PQElement that = (PQElement)object;
Long diff = new Long(that.index - this.index);
return diff.intValue();
}
}
public void add(Object object) {
pq.add(new PQElement(object));
}
public Object first() {
PQElement e = (PQElement)pq.best();
return e.object;
}
public boolean isEmpty() {
return pq.size()==0;
}
public Object remove() {
PQElement e = (PQElement)pq.remove();
return e.object;
}
public int size() {
return pq.size();
}
}
Solutions
14.9
141
14.10
}
public class PriorityQueue {
private Node start = new Node(0, null);
private int size;
public void add(int x) {
start.next = new Node(x, start.next);
++size;
}
public int best() {
return predecessorOfBest().next.key;
}
// dummy
142
Chapter 15
Sorting
Exercises
15.1
a. Bubble Sort:
a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7]
C
O
M
P
U
T
E
R
1
M
O
2
T
U
3
E
U
4
R
U
5
E
T
6
R
T
7
E
P
8
E
O
9
C
E
M
O
P
R
T
U
0
b. Selection Sort:
a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7]
C
O
M
P
U
T
E
R
1
R
U
2
E
T
3
E
R
4
E
P
5
C
E
M
O
P
R
T
U
0
143
144
Chapter 15 Sorting
c. Insertion Sort:
a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7]
C
O
M
P
U
T
E
R
1
M
O
2
T
U
3
E
M
O
P
T
U
4
C
E
M
O
P
R
T
U
0
d. Shell Sort:
a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7]
C
O
M
P
U
T
E
R
1
E
M
2
M
U
3
R
T
4
E
O
5
M
O
P
6
C
E
M
O
P
R
T
U
0
e. Merge Sort:
a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7]
C
O
M
P
U
T
E
R
1
T
U
2
M
O
E
R
T
U
3
C
E
M
O
P
R
T
U
0
f. Quick Sort:
a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7]
C
O
M
P
U
T
E
R
1
C
2
E
O
P
3
R
U
4
C
E
M
O
P
R
T
U
0
g. Heap Sort:
a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7]
0
1
3
5
6
7
2
4
P
R
U
C
T
E
U
R
R
P
M
O
P
C
U
C
T
Solutions
145
15.2
R
C
P
C
O
C
M
C
E
C
O
R
C
P
C
O
C
M
C
E
h. Bucket Sort:
a = 'A', b 1 = 'Z', b a = 26, n = 8, x = 26/8 = 3.25:
C, O, M, P, U, T, E, R
Bucket #0 ('A' through 'C'): C
Bucket #1 ('D' through 'F'): E
Bucket #2 ('G' through 'I'):
Bucket #3 ('J' through 'L'):
Bucket #4 ('M' through 'P'): O, M, P M, O, P
Bucket #5 ('Q' through 'S'): R
Bucket #6 ('T' through 'V'): U, T T, U
Bucket #7 ('W' through 'Z'):
C, E, M, O, P, R, T, U
a. Bubble Sort:
0
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
a[8]
I
G
G
I
C
O
T
U
E
1
2
4
5
6
U
R
T
R
11
12
13
14
15
U
S
10
16
E
G
E
I
I
E
M
M
E
O
T
S
146
Chapter 15 Sorting
b. Selection Sort:
0
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
a[8]
U
S
2
3
E
O
E
I
6
7
8
E
P
S
U
T
S
C
E
G
G
c. Insertion Sort:
0
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
a[8]
I
G
C
G
I
G
O
U
T
S
U
T
1
2
T
P
U
T
R
R
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
a[8]
P
E
4
5
6
7
d. Shell Sort:
0
1
E
P
G
C
U
S
I
G
M
I
O
M
P
P
R
R
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
a[8]
I
G
G
I
I
E
O
T
P
P
U
R
R
S
S
T
T
U
U
4
5
6
7
8
9
S
S
e. Merge Sort:
0
1
2
3
4
5
6
Solutions
147
f. Quick Sort:
0
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
a[8]
I
E
C
O
I
G
O
1
2
3
S
R
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
a[8]
M
S
3
4
T
T
U
U
g. Heap Sort:
0
1
7
8
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
U
G
T
G
S
E
R
B
P
C
O
G
M
B
I
B
G
C
E
B
C
B
U
T
S
M
R
O
T
I
I
B
U
G
T
G
S
E
R
M
B
P
C
O
G
M
B
I
B
G
C
E
B
C
148
15.3
Chapter 15 Sorting
h. Bucket Sort:
a = 'A', b 1 = 'Z', b a = 26, n = 12, x = 26/12 = 3.17:
B, I, G, C, O, M, P, U, T, E, R, S
Bucket #0 ('A' and 'B'):B
Bucket #1 ('C' and 'D'):C
Bucket #2 ('E' and 'F'):E
Bucket #3 ('G' and 'H'):G
Bucket #4 ('I' and 'J'):I
Bucket #5 ('K', 'L', and 'M'):M
Bucket #6 ('N' and 'O'):O
Bucket #7 ('P' and 'Q'): P
Bucket #8 ('R' and 'S'):R, S
Bucket #9 ('T' and 'U'):U, T T, U
Buckets #10 ('V' and 'W') and #11 ('X', 'Y', and 'Z') are empty
B, C, E, G, I, M, O, P, R, S, T, U
a. Bubble Sort:
0
1
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
77
44
44
77
22
22
88
99
55
33
66
55
99
33
99
66
99
77
3
4
5
6
22
44
55
7
8
88
33
55
10
11
77
33
12
77
66
77
88
22
33
33
44
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
77
44
22
88
99
66
55
33
66
99
13
14
88
66
55
55
66
77
88
99
b. Selection Sort:
0
1
33
2
3
4
55
33
5
6
22
88
77
55
22
33
44
44
55
66
77
88
99
Solutions
149
c. Insertion Sort:
0
1
2
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
77
44
22
44
77
44
22
88
99
55
33
66
22
33
33
77
55
44
44
77
55
55
88
77
66
99
88
77
99
88
99
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
77
44
22
88
66
99
55
33
66
88
3
4
5
d. Shell Sort:
0
1
2
22
77
33
77
55
33
44
22
33
44
55
66
66
77
77
88
99
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
77
44
22
44
77
44
22
88
99
55
33
66
99
55
77
66
88
99
99
5
6
7
99
66
e. Merge Sort:
0
1
2
77
22
33
44
55
55
33
66
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
77
66
55
33
22
22
44
22
88
33
99
55
66
55
77
33
99
66
88
33
33
44
44
66
77
88
99
3
4
5
f. Quick Sort:
0
1
2
3
4
5
55
55
150
Chapter 15 Sorting
g. Heap Sort:
0
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
77
44
22
55
88
99
55
22
33
66
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
15.4
99
66
88
33
77
22
66
22
55
33
44
22
33
22
99
88
77
44
77
66
66
33
99
88
77
44
22
66
22
55
33
33
22
33
44
44
55
66
77
88
99
h. Bucket Sort:
a = 0, b = 100, b a = 100, n = 8, x = 100/8 = 12.5:
77, 44, 22, 88, 99, 55, 33, 66
Bucket #0 (0 12):
Bucket #1 (13 24):22
Bucket #2 (25 37):33
Bucket #3 (38 49):44
Bucket #4 (50 62):55
Bucket #6 (63 74):66
Bucket #7 (75 87):77
Bucket #8 (88 99):88, 99
22, 33, 44, 55, 66, 77, 88, 99
a. Bubble Sort:
0
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
61
83
38
38
83
52
52
94
47
29
76
47
94
29
94
76
94
1
2
3
4
5
6
38
61
83
Solutions
151
a[0]
7
a[1]
a[2]
52
61
a[3]
a[4]
47
83
29
9
10
47
11
12
47
29
29
38
52
29
47
47
a[0]
a[1]
61
83
13
14
15
16
61
29
a[5]
a[6]
83
76
83
a[7]
61
52
52
61
76
83
94
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
38
52
94
76
47
29
76
94
47
61
76
b. Selection Sort:
0
1
29
83
3
4
5
6
47
38
29
38
47
47
52
61
76
83
94
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
61
38
38
83
61
52
47
47
52
94
47
29
76
29
29
83
61
52
47
38
38
83
61
52
52
83
61
61
94
83
76
94
83
94
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
61
83
47
38
52
94
47
83
29
76
c. Insertion Sort:
0
1
2
3
4
5
d. Shell Sort:
0
1
29
61
38
2
3
29
38
61
6
7
94
76
29
38
38
47
47
52
61
76
83
83
94
152
Chapter 15 Sorting
e. Merge Sort:
0
1
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
61
38
83
52
38
61
52
83
94
47
29
76
94
47
76
76
83
94
94
29
38
47
52
47
29
61
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
61
29
38
52
94
61
47
94
29
83
76
29
83
47
38
38
47
47
52
61
76
83
94
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
61
83
38
52
76
94
47
29
76
52
2
3
4
f. Quick Sort:
0
1
2
3
g. Heap Sort:
0
1
47
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
94
52
83
29
76
38
61
29
52
29
47
29
38
29
38
94
83
83
61
94
76
52
83
61
52
44
29
76
38
61
38
33
29
38
29
52
29
47
47
52
61
76
83
94
Solutions
15.5
153
h. Bucket Sort:
a = 0, b = 100, b a = 100, n = 8, x = 100/8 = 12.5:
61, 83, 38, 52, 94, 47, 29, 76
Bucket #0 (0 12):
Bucket #1 (13 24):
Bucket #2 (25 37):29
Bucket #3 (38 49):38, 47
Bucket #4 (50 62):61, 52 52, 61
Bucket #6 (63 74):
Bucket #7 (75 87):83, 76 76, 83
Bucket #8 (88 99):94
29, 38, 47, 52, 61, 76, 83, 94
a. Bubble Sort:
0
1
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
22
22
33
33
44
44
55
55
66
66
77
77
88
88
99
99
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
22
22
33
33
44
44
55
55
66
66
77
77
88
88
99
99
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
22
22
33
33
44
44
55
55
66
66
77
77
88
88
99
99
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
22
22
33
33
44
44
55
55
66
66
77
77
88
88
99
99
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
22
22
33
33
44
44
55
55
66
66
77
77
88
88
99
99
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
22
22
33
33
44
44
55
55
66
66
77
77
88
88
99
99
b. Selection Sort:
0
1
c. Insertion Sort:
0
1
d. Shell Sort:
0
1
e. Merge Sort:
0
1
f. Quick Sort:
0
1
154
Chapter 15 Sorting
g. Heap Sort:
0
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
22
33
44
55
99
66
77
88
99
55
88
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
99
33
88
44
77
33
66
22
55
22
44
22
33
22
99
66
44
55
33
22
99
77
33
88
44
77
55
33
33
22
55
66
22
44
22
33
44
55
h. Bucket Sort:
a = 0, b = 100, b a = 100, n = 8, x = 100/8 = 12.5:
22, 33, 44, 55, 66, 77, 88, 99
Bucket #0 (0 12):
Bucket #1 (13 24):22
Bucket #2 (25 37):33
Bucket #3 (38 49):44
Bucket #4 (50 62):55
Bucket #6 (63 74):66
Bucket #7 (75 87):77
Bucket #8 (88 99):88, 99
22, 33, 44, 55, 66, 77, 88, 99
66
77
88
99
Solutions
15.6
155
a. Bubble Sort:
0
1
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
99
88
88
99
77
77
66
55
44
33
22
99
22
99
2
3
99
66
99
55
99
44
99
33
7
8
77
88
66
10
88
55
11
88
44
12
88
33
13
14
66
15
77
55
16
77
44
17
77
33
18
19
55
20
66
44
21
66
33
22
23
44
55
33
77
66
55
22
44
22
33
44
44
55
66
77
88
99
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
99
22
88
77
66
55
44
33
22
99
66
77
77
25
33
27
28
88
55
22
24
26
66
22
77
22
88
22
b. Selection Sort:
0
1
33
2
3
4
22
33
88
44
44
55
88
99
156
Chapter 15 Sorting
c. Insertion Sort:
0
1
2
3
4
5
6
7
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
99
88
77
66
55
44
33
22
88
99
88
77
66
55
44
33
77
66
55
44
33
22
99
88
77
66
55
44
99
88
77
66
55
99
88
77
66
99
88
77
99
88
99
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
99
55
88
77
66
55
99
44
33
22
d. Shell Sort:
0
1
44
88
33
3
5
77
22
33
66
55
77
22
66
8
9
22
88
33
10
44
55
22
33
44
55
66
66
77
77
88
99
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
99
88
88
99
77
66
55
44
33
22
66
77
44
55
22
33
11
12
99
44
e. Merge Sort:
0
1
2
3
4
5
66
77
88
99
22
33
44
55
22
66
33
77
44
88
55
99
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
99
22
88
77
66
55
44
33
22
99
66
77
77
6
7
f. Quick Sort:
0
1
33
2
3
4
22
33
88
44
44
55
88
99
Solutions
157
g. Heap Sort:
0
1
2
3
4
5
6
7
8
9
10
11
12
13
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
99
22
88
33
77
33
66
33
55
22
44
22
33
22
88
77
66
55
44
33
22
99
66
22
88
44
33
77
55
33
66
33
55
33
22
33
22
44
44
55
h. Bucket Sort:
a = 0, b = 100, b a = 100, n = 8, x = 100/8 = 12.5:
99, 88, 77, 66, 55, 44, 33, 22
Bucket #0 (0 12):
Bucket #1 (13 24):22
Bucket #2 (25 37):33
Bucket #3 (38 49):44
Bucket #4 (50 62):55
Bucket #6 (63 74):66
Bucket #7 (75 87):77
Bucket #8 (88 99):88, 99
22, 33, 44, 55, 66, 77, 88, 99
66
77
88
99
158
15.7
Chapter 15 Sorting
a. Selection Sort:
0
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
1
0
0
0
1
1
1
2
3
b. Insertion Sort:
0
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
1
0
0
1
0
1
2
3
1
0
1
1
0
0
5
6
1
0
c. Merge Sort:
0
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
1
0
0
1
1
2
0
1
0
1
1
5
6
0
1
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
1
0
0
0
1
1
0
1
d. Quick Sort:
0
1
2
3
Solutions
159
e. Counting Sort:
a = {0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0}, n = 16, m = 2,
c = {7, 9} c = {7, 16}
15.8
k = ai
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
0
1
1
1
1
1
0
0
1
0
1
1
0
0
1
0
c0
c1
7
6
16
j = ck bj = k
6
15
14
13
12
11
5
4
10
3
9
8
2
1
7
0
15
14
13
12
11
5
4
10
3
9
8
2
1
7
0
0
1
1
1
1
1
0
0
1
0
1
1
0
0
1
0
b = {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1}
a. Selection Sort:
0
US CA CN US
1 ES
2
AU
3
4
5
6
7
8
9
10 CN
11
12 AU CA CN CN
0
10 11 12 13 14 15 16 17 18 19
GB JA FR CN US DE JA GB US CN US IT AU ES US US
US
US
IT
US
CN US
CN
JA
GB JA
GB
IT
DE
GB
CN FR
ES
CN DE
CN DE ES FR GB GB IT JA JA US US US US US US US
160
Chapter 15 Sorting
b. Insertion Sort:
0
US CA
1 CA US
2
CN
3
4
5
6
7
8
9
10
11
12 AU CA
13 AU CA
0
10 11 12 13 14 15 16 17 18 19
CN US GB JA FR CN US DE JA GB US CN US IT AU ES US US
US
GB
US
JA
US
FR GB JA
US
CN FR GB JA
US
DE FR GB JA
US
JA
US
GB
JA
US
CN DE FR
GB
JA
US
IT
JA
US
CN DE FR
GB IT
JA
US
CN CN CN DE ES FR GB GB IT JA JA US US US US US US US
c. Merge Sort:
0
US CA CN US
1 CA US
2
GB
3
CN GB US
4
5
6
7
CN DE
8
9
10
11
11
12
13
14 AU CA CN CN
0
10 11 12 13 14 15 16 17 18 19
GB JA FR CN US DE JA GB US CN US IT AU ES US US
US
FR JA
DE US
CN DE FR JA
FR GB JA US US
GB JA
CN US
CN GB JA
AU IT
ES IT
AU CN ES GB IT JA US US
CN DE ES FR GB GB IT JA JA US US US US US US US
d. Quick Sort:
0
10 11 12 13 14 15 16 17 18 19
US CA CN US GB JA FR CN US DE JA GB US
1 ES
2 AU
CN DE CN ES FR
JA
3
CN DE
4
IT
5
GB GB IT JA
6 AU CA CN CN CN DE ES FR GB GB IT JA JA
0
CN US IT AU ES US US
US
GB
US
US
JA
US US US US US US US
Solutions
161
e. Counting Sort:
a = {US, CA, CN, US, GB, JA, FR, CN, US, DE, JA, GB, US, CN, US, IT, AU, ES, US, US},
n = 20, m = 10:
i
19
18
17
16
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
15.9
ai
US
US
ES
AU
IT
US
CN
US
GB
JA
DE
US
CN
FR
JA
GB
US
CN
CA
US
k
9
9
4
0
7
9
2
9
6
8
3
9
2
5
8
6
9
2
1
9
Key
ck
ck.
0
1
2
3
4
5
6
7
8
9
AU
CA
CN
DE
ES
FR
GB
IT
JA
US
1
1
3
1
1
1
2
1
2
7
1
2
5
6
7
8
10
11
13
20
c0
c1
c2
c3
c4
c5
c6
c7
c8
c9 j = ck bj = ai
10
11
13
20
19
18
6
0
10
17
4
16
9
12
5
15
3
7
11
8
14
2
1
13
19
18
6
0
10
17
4
16
9
12
5
15
3
7
11
8
14
2
1
13
b = {AU, CA, CN, CN, CN, DE, ES, FR, GB, GB, IT, JA, JA, US, US, US, US, US, US, US}
If t = c n2 and n = 2n, then t = c(n)2 = c(2n)2 = (4)(c n2 ) = 4t;
i.e., the time for an array of length 2n will be about 4 times as long.
a. 4(5 ms) = 20 ms
b. 4(20) ms = 80 ms
c. 4(80) ms = 320 ms
d. 4(320) ms = 1280 ms = 1.26 s
US
US
ES
AU
IT
US
CN
US
GB
JA
DE
US
CN
FR
JA
GB
US
CN
CA
US
162
15.10
15.11
15.12
15.13
Chapter 15 Sorting
If t = c n lgn and n = n2, then t = c n lgn = c (n2)lg(n2) = (2n)(c n lgn) = (2n) t;
i.e., the time for an array of length n2 will be about 2n times as long.
a. 2(200)(3 s) = 1200 s = 1.2 ms
b. 2(40,000)(1.2 ms) = 96,000 ms = 1600 s = 26 min 40 s
If t = c n and n = 2n, then t = c(n) = c(2n) = (2)(c n) = 2t ;
i.e., the time for an array of length 2n will be about twice as long.
a. 2(7 ms) = 14 ms
b. 2(14 ms) = 28 ms
c. 2(28 ms) = 56 ms
d. 2(56 ms) = 112 ms
If t = c n lgn and n = 2n,
then t = c n lgn = c (2n)lg(2n) = 2(c n lgn)(lg(2n)/lgn = 2t lg(2n)/lgn.
But lg(2n) = lg2 + lgn = 1 + lgn, so lg(2n)/lgn = (1 + lgn)/lgn = 1 + 1/lgn.
Thus, t = 2t (1 + 1/lgn).
With n = 1,000,000, 1/lgn = log 2/logn = 0.301/6 = 0.05.
Thus, t = 2t (1 + 0.05) = 2(20 ms)(1.05) = 42 ms.
Here is Listing 15.3:
void sort(int[] a) {
for (int i = a.length-1; i > 0; i--) {
3
for (int j = 0; j < i; j++)
4
if (a[j] > a[j+1]) swap(a, j, j+1);
5
// INVARIANTS: a[i] = max{a[0..i]};
6
}
7
// INVARIANT: a[i..a.length) is in ascending order;
8
}
From lines 34, we know that a[j] a[j+1] for all j < i.
Thus: a[0] a[1] a[2] ... a[i].
Therefore, a[i] = max{a[0], a[1], a[2], ..., a[i]} = max{a[0..i]}.
1
2
15.14
15.15
Solutions
15.16
15.17
15.18
15.19
163
164
Chapter 15 Sorting
k[j] = k[j-1];
k[j] = ai;
8
9
10
11
15.20
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
Solutions
165
pp.next = (p==null? q: p);
44
45
15.21
15.22
}
void sort(int[] a, int p, int q) {
for (int d = (q-p)/2; d > 0; d /= 2)
for (int c = p; c < p+d; c++)
iSort(a, c, d);
}
void sort(int[] a) {
for (int i = (a.length-1)/2; i >= 0; i--)
heapify(a, i, a.length);
for (int j = a.length-1; j > 0; j--) {
swap(a, 0, j);
heapify(a, 0, j);
}
}
The steps in the trace in Figure 15.11 are numbered. This line that each is executing is
shown in the following table:
Step
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Line
3:
3:
3:
5:
6:
5:
6:
5:
6:
5:
6:
5:
6:
5:
heapify() at a[3]
heapify() at a[1]
heapify() at a[0]
swap() a[0] with a[7]
heapify() at a[0]
swap() a[0] with a[6]
heapify() at a[0]
swap() a[0] with a[5]
heapify() at a[0]
swap() a[0] with a[4]
heapify() at a[0]
swap() a[0] with a[3]
heapify() at a[0]
swap() a[0] with a[2]
166
15.23
15.24
15.25
15.26
Chapter 15 Sorting
Solutions
15.27
15.28
15.29
15.30
15.31
167
168
15.32
15.33
15.34
15.35
Chapter 15 Sorting
This is comparable to the Bubble Sort. The loop in steps 69 makes n1 comparisons and
n1 copies.
Among the ten sorting algorithms presented in this book, only the Selection Sort, the
Quick Sort, and the Heap Sort are unstable. Moreover, the Selection Sort can easily be
modified to make it stable.
The Shell Sort, Merge Sort, Quick Sort, Bucket Sort, and Counting Sort are parallelizable.
Anns program crashes because it is using the Quick Sort on a large array that contains at
least 99,000 duplicates. That array is nearly sorted already, causing the Quick Sort to run
in nearly (n 2 ) time.
The main loop of the Selection Sort iterates n 1 times. On iteration i, it finds the maximum element among the subsequence {a0, ..., ai} and then swaps it with ai . That requires
searching through all i + 1 elements of the subsequence. Thus the total number of comparisons made is C = (n 1) + (n 1) + ... + 2 + 1 = n(n 1)/2 = (n 2 ). [See Formula C.6
on page 572.]
Solutions
169
Programming Problems
15.1
package chap15.prob01;
import chap03.list08.IntArrays;
public class TestBubbleSort {
public TestBubbleSort() {
int[] a = {66, 33, 99, 88, 44, 55, 22, 77};
IntArrays.print(a);
sort(a);
}
void sort(int[] a) {
for (int i = a.length-1; i > 0; i--)
for (int j = 0; j < i; j++)
if (a[j] > a[j+1]) {
IntArrays.swap(a, j, j+1);
IntArrays.print(a);
}
}
public static void main(String[] args) {
new TestBubbleSort();
}
15.2
}
package chap15.prob02;
import chap03.list08.IntArrays;
public class TestSelectionSort {
public TestSelectionSort() {
int[] a = {66, 33, 99, 88, 44, 55, 22, 77};
IntArrays.print(a);
sort(a);
}
void sort(int[] a) {
for (int i = a.length-1; i > 0; i--) {
int m=0;
for (int j = 1; j <= i; j++) {
if (a[j] > a[m]) m = j;
}
IntArrays.swap(a, i, m);
170
Chapter 15 Sorting
IntArrays.print(a);
}
}
public static void main(String[] args) {
new TestSelectionSort();
}
}
15.3
15.4
15.5
void sort(int[] a) {
for (int i = a.length-1; i > 0; i--)
bubbleUp(a, i);
}
void bubbleUp(int[] a, int i) {
for (int j = 0; j < i; j++)
if (a[j] > a[j+1])
IntArrays.swap(a, j, j+1);
}
public TestBubbleSort() {
int[] a = IntArrays.randomInts(N, N);
System.out.println("sorted: " + IntArrays.isSorted(a));
sort(a);
System.out.println("sorted: " + IntArrays.isSorted(a));
}
package chap15.prob05;
import chap03.list08.IntArrays;
public class TestBubbleSort {
final int N = 4000;
public TestBubbleSort() {
int[] a = IntArrays.randomInts(N, N);
System.out.println("sorted: " + IntArrays.isSorted(a));
sort(a);
System.out.println("sorted: " + IntArrays.isSorted(a));
}
void sort(int[] a) {
for (int i = a.length-1; i > 0; i--)
for (int j = 0; j < i; j++)
if (a[j] > a[j+1])
IntArrays.swap(a, j, j+1);
Solutions
171
}
public static void main(String[] args) {
new TestBubbleSort();
}
15.6
15.7
void sort(int[] a) {
boolean done = false;
for (int i = a.length-1; i > 0 && !done; i--) {
done = true;
for (int j = 0; j < i; j++) {
if (a[j] > a[j+1]) {
IntArrays.swap(a, j, j+1);
done = false;
}
}
}
}
package chap15.prob07;
import chap03.list08.IntArrays;
public class TestBubbleSort {
final int N = 4000;
public TestBubbleSort() {
int[] a = IntArrays.randomInts(N, N);
System.out.println("sorted: " + IntArrays.isSorted(a));
System.out.println("sort1() time: " + sort1(a));
System.out.println("sorted: " + IntArrays.isSorted(a));
a = IntArrays.randomInts(N, N);
System.out.println("sorted: " + IntArrays.isSorted(a));
System.out.println("sort2() time: " + sort2(a));
System.out.println("sorted: " + IntArrays.isSorted(a));
}
long sort1(int[] a) {
long t1 = System.currentTimeMillis();
boolean done = false;
for (int i = a.length-1; i > 0 && !done; i--) {
done = true;
for (int j = 0; j < i; j++) {
if (a[j] > a[j+1]) {
172
Chapter 15 Sorting
IntArrays.swap(a, j, j+1);
done = false;
}
}
}
long t2 = System.currentTimeMillis();
return t2 - t1;
}
long sort2(int[] a) {
long t1 = System.currentTimeMillis();
boolean done = false;
for (int i = a.length-1; i > 0 && !done; i--) {
done = true;
for (int j = 0; j < i; j++) {
if (a[j] > a[j+1]) {
IntArrays.swap(a, j, j+1);
done = false;
}
}
}
long t2 = System.currentTimeMillis();
return t2 - t1;
}
public static void main(String[] args) {
new TestBubbleSort();
}
}
15.8
15.9
void sort(int[] a) {
sort(a, a.length);
}
void sort(int[] a, int n) {
if (n < 1) return;
for (int j = 0; j < n-1; j++)
if (a[j] > a[j+1]) IntArrays.swap(a, j, j+1);
sort(a, n-1);
}
void sort(int[] a) {
for (int i = a.length-1; i > 0; i--) {
for (int j = 0; j < i; j++) {
Solutions
173
if (a[j] > a[j+1]) IntArrays.swap(a, j, j+1);
if (!invariant1(a, j))
throw new RuntimeException("INVARIANT 1 VIOLATED");
}
if (!invariant2(a, i))
throw new RuntimeException("INVARIANT 2 VIOLATED");
}
}
boolean invariant1(int[] a, int j) {
for (int k=0; k<j; k++)
if (a[j+1] < a[k]) return false;
return true;
}
15.10
15.11
174
Chapter 15 Sorting
for (int j = 1; j <= i; j++) {
if (a[j] > a[m]) m = j;
}
IntArrays.swap(a, i, m);
15.12
15.13
15.14
15.15
}
void sort(int[] a) {
sort(a, a.length);
}
void sort(int[] a, int n) {
if (n < 2) return;
int m=0;
for (int j=1; j<n; j++)
if (a[j] > a[m]) m = j;
IntArrays.swap(a, n-1, m);
sort(a, n-1);
}
void sort(int[] a) {
for (int i=1; i<a.length; i++)
insert(a, i);
}
void insert(int[] a, int i) {
// inserts a[i] into a[0..i] leaving it in ascending order:
int ai=a[i], j=i;
for (j=i; j>0 && a[j-1]>ai; j--)
a[j] = a[j-1];
a[j] = ai;
}
void sort(int[] a) {
sort(a, a.length);
}
void sort(int[] a, int n) {
if (n < 2) return;
sort(a, n-1);
int ai=a[n-1], j=n-1;
for (j=n-1; j>0 && a[j-1]>ai; j--)
a[j] = a[j-1];
a[j] = ai;
}
package chap15.prob15;
import chap03.list08.IntArrays;
public class TestMergeSort {
Solutions
175
public TestMergeSort(int size) {
int[] a = IntArrays.randomInts(size, 100);
IntArrays.print(a);
System.out.println("sorted: " + IntArrays.isSorted(a));
sort(a, 0, a.length);
IntArrays.print(a);
System.out.println("sorted: " + IntArrays.isSorted(a));
}
void sort(int[] a, int p, int q) {
// PRECONDITION: 0 < p < q <= a.length
// POSTCONDITION: a[p..q-1] is in ascending order
if (q-p < 2) return;
int m = (p+q)/2;
sort(a, p, m);
sort(a, m, q);
merge(a, p, m, q);
}
void merge(int[] a, int p, int m, int q) {
// PRECONDITIONS: a[p..m-1] and a[m..q-1] are in ascending order;
// POSTCONDITION: a[p..q-1] is in ascending order;
if (a[m-1] <= a[m]) return; // a[p..q-1] is already sorted
int i = p, j = m, k = 0;
int[] aa = new int[q-p];
while (i < m && j < q)
if (a[i]<a[j]) aa[k++] = a[i++];
else aa[k++] = a[j++];
if (i < m) System.arraycopy(a,i,a,p+k,m-i); //shift a[i..m-1]
System.arraycopy(aa,0,a,p,k); // copy aa[0..k-1] to a[p..p+k-1];
}
public static void main(String[] args) {
for (int i=10; i<=20; i++)
new TestMergeSort(i);
}
15.16
176
Chapter 15 Sorting
b. void sort(int[] a, int p, int q) {
for (int i = q-1; i > p; i--) {
int m=0;
for (int j = 1; j <= i; j++)
if (a[j] > a[m]) m = j;
IntArrays.swap(a, i, m);
}
}
15.17
}
package chap15.prob17;
abstract class AbstractTester {
protected int[] a;
private java.util.Random random;
private final int N = 100;
public AbstractTester() { // initializes a[] and random
a = new int[N];
random = new java.util.Random();
for (int i=0; i<N; i++)
a[i] = 100 + random.nextInt(900);
}
public void randomize() { // randomly permutes a[]
for (int i=0; i<N; i++) {
int j = random.nextInt(N);
swap(a, i, j);
}
}
public void reverse() { // reverses the order of a[]
for (int i=0; i<N/2; i++)
swap(a, i, N-i);
}
abstract public void sort();
// sorts a[]
Solutions
177
Chapter 16
Graphs
Exercises
16.1
16.2
16.3
If e is an edge between vertex i and veretex j in an undirected graph, then there is one 1
at location aij and a one 1 at location aji in the adjacency matrix. Thus, there are two 1s
for each edge.
If e is an edge between vertex i and veretex j in an undirected graph, then there is a node
to j in list i and a node to i in list j in the adjacency list. Thus, there are two nodes for
each edge.
a. n = 6
b. V = {A, B, C, D, E, F}
c. E = {AB, BC, BD, CD, CE, CF, DE, DF}
d.
x:
d(x)
e. ABCD
f. ABCEDF
g. BCEDB
h.
A
178
Solutions
179
i.
A
B
C
D
E
F
v
j.
2
3
4
4
B
1
0
1
1
0
0
C
0
1
0
1
1
1
D
0
1
1
0
1
1
E
0
0
1
1
0
0
F
0
0
1
1
1
0
A
B
C
D
E
F
0
1
16.4
A
0
1
0
0
0
0
0
a. n = 6
b. V = {A, B, C, D, E, F}
c. E = {AD, BA, BD, CB, CD, CE, CF, DE, EC, FE}
d.
x:
d(x):
e. ADEC
f. FCBADE
g. BDECB
h.
B
F
D
i.
A
B
C
D
E
F
j.
A
0
1
0
0
0
0
v
0
1
2
3
4
4
A
B
C
D
E
F
B
0
0
1
0
0
0
C
0
0
0
0
1
0
D
1
1
1
0
0
0
E
0
0
1
1
0
1
F
0
0
1
0
0
0
a
0
180
16.5
Chapter 16 Graphs
a.
K4
K5
K2
Solutions
181
f.
16.6
4
2
4
2
1
1
4
2
4
1
E
182
Chapter 16 Graphs
16.7
4B
4
2
5
D7
I4
1
1
5 J
1H
16.8
a. Preorder traversal.
a.
A B C D E F
A
B
C
D
E
F
G
b.
0 4 0 0 0 1 2
4 0 2 0 0 0 5
0 2 0 4 0 0 1
0 0 4 0 1 0 2
0 0 0 2 0 3 4
1 0 0 0 3 0 3
2 5 1 2 4 3 0
A B C D E F G
A
B
C
D
E
F
G
c.
0 1 0 0 0 1 1
1 0 1 0 0 0 1
0 1 0 1 0 0 1
0 0 1 0 1 0 1
0 0 0 1 0 1 1
1 0 0 0 1 0 1
1 1 1 1 1 1 0
v
0
1
2
3
4
5
6
A
B
C
D
E
F
G
a
0
Solutions
Programming Problems
16.1
16.2
183
184
Chapter 16 Graphs
String vi = vertices[i];
int i1 = this.index(vi);
int i2 = that.index(vi);
for (int j=0; j<size; j++) {
String vj = vertices[i];
int j1 = this.index(vj);
int j2 = that.index(vj);
if (this.a[i1][j1] != that.a[i2][j2]) return false;
}
}
return true;
16.3
}
public class Graph {
private int size;
private List[] a; // adjacency list
private String[] v; // vertex list
public Graph(String[] args) {
size = args.length;
a = new List[size];
for (int i=0; i<size; i++)
a[i] = new List();
v = new String[size];
System.arraycopy(args, 0, v, 0, size);
}
public void add(String v, String w) {
a[index(v)].add(index(w));
a[index(w)].add(index(v));
}
public String toString() {
if (size == 0) return "{}";
StringBuffer buf = new StringBuffer("{" + v[0] + ":" + a[0]);
for (int i = 1; i < size; i++)
buf.append("," + v[i] + ":" + a[i]);
return buf + "}";
}
private int index(String vertex) {
for (int i = 0; i < size; i++)
if (vertex.equals(v[i])) return i;
Solutions
185
return a.length;
}
private class List {
String vertex;
Node edges;
public void add(int j) {
edges = new Node(j, edges);
}
public String toString() {
if (edges==null) return "";
StringBuffer buf = new StringBuffer();
for (Node p = edges; p != null; p = p.next)
buf.append(Graph.this.v[p.to]);
return buf.toString();
}
private class Node {
int to;
Node next;
Node(int to, Node next) {
this.to = to;
this.next = next;
}
}
16.4
16.5
}
}
public boolean[][] getAdjacencyMatrix() {
return a;
}
public String[] getVertices() {
return vertices;
}
public int size() {
return size;
}
public int[] degrees() {
int[] d = new int[size];
for (int i=0; i<size; i++) {
d[i]=0;
186
Chapter 16 Graphs
for (int j=0; j<size; j++)
if (a[i][j]) ++d[i];
}
return d;
16.6
16.7
16.8
16.9
}
public int[] degrees() {
int[] d = new int[size];
for (int i=0; i<size; i++) {
d[i]=0;
for (List.Node p=a[i].edges; p != null; p = p.next)
++d[i];
}
return d;
}
public boolean isComplete() {
for (int i=0; i<size; i++)
for (int j=0; j<size; j++)
if (j != i && !a[i][j]) return false;
return true;
}
public boolean isComplete() {
for (int i=0; i<size; i++) {
boolean[] e = new boolean[size];
for (List.Node p=a[i].edges; p != null; p = p.next)
e[p.to] = true;
for (int j=0; j<size; j++)
if (j != i && !e[j]) return false;
}
return true;
}
public Graph(boolean[][] aa) {
size = aa.length;
a = new List[size];
for (int i=0; i<size; i++)
a[i] = new List();
v = new String[size];
for (int i=0; i<size; i++)
v[i] = String.valueOf((char)('A'+i));
for (int i=0; i<size; i++)
for (int j=0; j<size; j++)
if (aa[i][j]) a[i].add(j);
}
Solutions
16.10
16.11
16.12
187
188
Chapter 16 Graphs
if (q.to == i) {
a[j].edges = q.next;
found = true;
} else {
while (q.next != null) {
if (q.next.to == i) {
q.next = q.next.next;
found = true;
break;
}
q = q.next;
}
}
return found;
}