Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Beginning Algorithms (2006)

.pdf
Скачиваний:
255
Добавлен:
17.08.2013
Размер:
9.67 Mб
Скачать

Appendix D

Chapter 4

Exercises

1.Implement a thread-safe queue that performs no waiting. Sometimes all you need is a queue that will work in a multi-threaded environment without the blocking.

2.Implement a queue that retrieves values in random order. This could be used for dealing cards from a deck or any other random selection process.

Exercise 1 Solution

package com.wrox.algorithms.queues;

public class SynchronizedQueue implements Queue { private final Object _mutex = new Object(); private final Queue _queue;

public SynchronizedQueue(Queue queue) {

assert queue != null : “queue can’t be null”; _queue = queue;

}

public void enqueue(Object value) { synchronized (_mutex) {

_queue.enqueue(value);

}

}

public Object dequeue() throws EmptyQueueException { synchronized (_mutex) {

return _queue.dequeue();

}

}

public void clear() { synchronized (_mutex) {

_queue.clear();

}

}

public int size() { synchronized (_mutex) {

return _queue.size();

}

}

public boolean isEmpty() { synchronized (_mutex) {

return _queue.isEmpty();

}

}

}

504

Answers to Exercises

Exercise 2 Solution

package com.wrox.algorithms.queues;

import com.wrox.algorithms.lists.LinkedList; import com.wrox.algorithms.lists.List;

public class RandomListQueue implements Queue { private final List _list;

public RandomListQueue() { this(new LinkedList());

}

public RandomListQueue(List list) {

assert list != null : “list can’t be null”; _list = list;

}

public void enqueue(Object value) { _list.add(value);

}

public Object dequeue() throws EmptyQueueException { if (isEmpty()) {

throw new EmptyQueueException();

}

return _list.delete((int) (Math.random() * size()));

}

public void clear() { _list.clear();

}

public int size() { return _list.size();

}

public boolean isEmpty() { return _list.isEmpty();

}

}

Chapter 6

Exercises

1.Write a test to prove that each of the algorithms can sort a randomly generated list of double objects.

2.Write a test to prove that the bubble sort and insertion sort algorithms from this chapter are stable.

505

Appendix D

3.Write a comparator that can order strings in dictionary order, with uppercase and lowercase letters considered equivalent.

4.Write a driver program to determine how many objects are moved by each algorithm during a sort operation.

Exercise 1 Solution

public class ListSorterRandomDoublesTest extends TestCase { private static final int TEST_SIZE = 1000;

private final List _randomList = new ArrayList(TEST_SIZE);

private final NaturalComparator _comparator = NaturalComparator.INSTANCE;

protected void setUp() throws Exception { super.setUp();

for (int i = 1; i < TEST_SIZE; ++i) {

_randomList.add(new Double((TEST_SIZE * Math.random())));

}

}

public void testsortingRandomDoublesWithBubblesort() {

ListSorter listSorter = new BubblesortListSorter(_comparator); List result = listSorter.sort(_randomList); assertSorted(result);

}

public void testsortingRandomDoublesWithSelectionsort() {

ListSorter listSorter = new SelectionSortListSorter(_comparator); List result = listSorter.sort(_randomList); assertSorted(result);

}

public void testsortingRandomDoublesWithInsertionsort() {

ListSorter listSorter = new InsertionSortListSorter(_comparator); List result = listSorter.sort(_randomList); assertSorted(result);

}

private void assertSorted(List list) {

for (int i = 1; i < list.size(); i++) { Object o = list.get(i);

assertTrue(_comparator.compare(list.get(i - 1), list.get(i)) <= 0);

}

}

}

Exercise 2 Solution

import com.wrox.algorithms.lists.ArrayList; import com.wrox.algorithms.lists.List; import junit.framework.TestCase;

public class ListSorterStabilityTest extends TestCase {

506

 

Answers to Exercises

 

 

private static final int

TEST_SIZE = 1000;

private final List _list

= new ArrayList(TEST_SIZE);

private final Comparator

_comparator = new FractionComparator();

protected void setUp() throws Exception {

super.setUp();

 

for (int i = 1; i < TEST_SIZE; ++i) { _list.add(new Fraction(i % 20, i));

}

}

public void testStabilityOfBubblesort() {

ListSorter listSorter = new BubblesortListSorter(_comparator); List result = listSorter.sort(_list); assertStableSorted(result);

}

public void testStabilityOfInsertionsort() {

ListSorter listSorter = new InsertionSortListSorter(_comparator); List result = listSorter.sort(_list); assertStableSorted(result);

}

private void assertStableSorted(List list) { for (int i = 1; i < list.size(); i++) {

Fraction f1 = (Fraction) list.get(i - 1); Fraction f2 = (Fraction) list.get(i); if(!(f1.getNumerator() < f2.getNumerator()

|| f1.getDenominator() < f2.getDenominator())) { fail(“what?!”);

}

}

}

private static class Fraction { private final int _numerator; private final int _denominator;

public Fraction(int numerator, int denominator) { _numerator = numerator;

_denominator = denominator;

}

public int getNumerator() { return _numerator;

}

public int getDenominator() { return _denominator;

}

}

private static class FractionComparator implements Comparator {

507

Appendix D

public int compare(Object left, Object right) throws ClassCastException { return compare((Fraction) left, (Fraction) right);

}

private int compare(Fraction l, Fraction r) throws ClassCastException { return l.getNumerator() - r.getNumerator();

}

}

}

Exercise 3 Solution

public final class CaseInsensitiveStringComparator implements Comparator { public int compare(Object left, Object right) throws ClassCastException {

assert left != null : “left can’t be null”; assert right != null : “right can’t be null”;

String leftLower = ((String) left).toLowerCase(); String rightLower = ((String) right).toLowerCase(); return leftLower.compareTo(rightLower);

}

}

Exercise 4 Solution

public class ListSorterCallCountingListTest extends TestCase { private static final int TEST_SIZE = 1000;

private final List _sortedArrayList = new ArrayList(TEST_SIZE); private final List _reverseArrayList = new ArrayList(TEST_SIZE); private final List _randomArrayList = new ArrayList(TEST_SIZE);

private Comparator _comparator = NaturalComparator.INSTANCE;

protected void setUp() throws Exception { super.setUp();

for (int i = 1; i < TEST_SIZE; ++i) { _sortedArrayList.add(new Integer(i));

}

for (int i = TEST_SIZE; i > 0; --i) { _reverseArrayList.add(new Integer(i));

}

for (int i = 1; i < TEST_SIZE; ++i) {

_randomArrayList.add(new Integer((int)(TEST_SIZE * Math.random())));

}

}

public void testWorstCaseBubblesort() {

List list = new CallCountingList(_reverseArrayList); new BubblesortListSorter(_comparator).sort(list); reportCalls(list);

508

Answers to Exercises

}

public void testWorstCaseSelectionSort() {

List list = new CallCountingList(_reverseArrayList); new SelectionSortListSorter(_comparator).sort(list); reportCalls(list);

}

public void testWorstCaseInsertionSort() { List list = _reverseArrayList;

List result = new CallCountingList(new ArrayList());

new InsertionSortListSorter(_comparator).sort(list, result); reportCalls(result);

}

public void testBestCaseBubblesort() {

List list = new CallCountingList(_sortedArrayList); new BubblesortListSorter(_comparator).sort(list); reportCalls(list);

}

public void testBestCaseSelectionSort() {

List list = new CallCountingList(_sortedArrayList); new SelectionSortListSorter(_comparator).sort(list); reportCalls(list);

}

public void testBestCaseInsertionSort() { List list = _sortedArrayList;

List result = new CallCountingList(new ArrayList());

new InsertionSortListSorter(_comparator).sort(list, result); reportCalls(result);

}

public void testAverageCaseBubblesort() {

List list = new CallCountingList(_randomArrayList); new BubblesortListSorter(_comparator).sort(list); reportCalls(list);

}

public void testAverageCaseSelectionSort() {

List list = new CallCountingList(_randomArrayList); new SelectionSortListSorter(_comparator).sort(list); reportCalls(list);

}

public void testAverageCaseInsertionSort() { List list = _randomArrayList;

List result = new CallCountingList(new ArrayList());

new InsertionSortListSorter(_comparator).sort(list, result); reportCalls(result);

}

private void reportCalls(List list) {

509

Appendix D

System.out.println(getName() + “: “ + list);

}

}

Chapter 7

Exercises

1.Implement mergesort iteratively, rather than recursively.

2.Implement quicksort iteratively, rather than recursively.

3.Count the number of list manipulations (for example, set(), add(), insert()) during quicksort and shellsort.

4.Implement an in-place version of insertion sort.

5.Create a version of quicksort that uses insertion sort for sublists smaller than five items.

Exercise 1 Solution

public class IterativeMergesortListSorter implements ListSorter { private final Comparator _comparator;

public IterativeMergesortListSorter(Comparator comparator) { assert comparator != null : “comparator cannot be null”; _comparator = comparator;

}

public List sort(List list) {

assert list != null : “list cannot be null”;

return mergeSublists(createSublists(list));

}

private List mergeSublists(List sublists) { List remaining = sublists;

while (remaining.size() > 1) {

remaining = mergeSublistPairs(remaining);

}

return (List) remaining.get(0);

}

private List mergeSublistPairs(List remaining) {

List result = new ArrayList(remaining.size() / 2 + 1);

Iterator i = remaining.iterator(); i.first();

while (!i.isDone()) {

List left = (List) i.current(); i.next();

if (i.isDone()) {

510

Answers to Exercises

result.add(left); } else {

List right = (List) i.current(); i.next(); result.add(merge(left, right));

}

}

return result;

}

private List createSublists(List list) { List result = new ArrayList(list.size());

Iterator i = list.iterator(); i.first();

while (!i.isDone()) {

List singletonList = new ArrayList(1); singletonList.add(i.current()); result.add(singletonList);

i.next();

}

return result;

}

private List merge(List left, List right) { List result = new ArrayList();

Iterator l = left.iterator();

Iterator r = right.iterator();

l.first();

r.first();

while (!(l.isDone() && r.isDone())) { if (l.isDone()) {

result.add(r.current());

r.next();

}else if (r.isDone()) { result.add(l.current()); l.next();

}else if (_comparator.compare(l.current(), r.current()) <= 0) { result.add(l.current());

l.next();

}else {

result.add(r.current());

r.next();

}

}

return result;

}

}

511

Appendix D

Exercise 2 Solution

public class IterativeQuicksortListSorter implements ListSorter { private final Comparator _comparator;

public IterativeQuicksortListSorter(Comparator comparator) { assert comparator != null : “comparator cannot be null”; _comparator = comparator;

}

public List sort(List list) {

assert list != null : “list cannot be null”;

quicksort(list);

return list;

}

private void quicksort(List list) { Stack jobStack = new ListStack();

jobStack.push(new Range(0, list.size() - 1));

while (!jobStack.isEmpty()) {

Range range = (Range) jobStack.pop(); if (range.size() <= 1) {

continue;

}

int startIndex = range.getStartIndex(); int endIndex = range.getEndIndex();

Object value = list.get(endIndex);

int partition = partition(list, value, startIndex, endIndex - 1); if (_comparator.compare(list.get(partition), value) < 0) {

++partition;

}

swap(list, partition, endIndex);

jobStack.push(new Range(startIndex, partition - 1)); jobStack.push(new Range(partition + 1, endIndex));

}

}

private int partition(List list, Object value, int leftIndex, int rightIndex) { int left = leftIndex;

int right = rightIndex;

while (left < right) {

if (_comparator.compare(list.get(left), value) < 0) { ++left;

continue;

}

if (_comparator.compare(list.get(right), value) >= 0) {

512

Answers to Exercises

--right; continue;

}

swap(list, left, right); ++left;

}

return left;

}

private void swap(List list, int left, int right) { if (left == right) {

return;

}

Object temp = list.get(left); list.set(left, list.get(right)); list.set(right, temp);

}

private static final class Range { private final int _startIndex; private final int _endIndex;

public Range(int startIndex, int endIndex) { _startIndex = startIndex;

_endIndex = endIndex;

}

public int size() {

return _endIndex - _startIndex + 1;

}

public int getStartIndex() { return _startIndex;

}

public int getEndIndex() { return _endIndex;

}

}

}

Exercise 3 Solution

public class AdvancedListSorterCallCountingListTest extends TestCase { private static final int TEST_SIZE = 1000;

private final List _sortedArrayList = new ArrayList(TEST_SIZE); private final List _reverseArrayList = new ArrayList(TEST_SIZE);

private final List _randomArrayList = new ArrayList(TEST_SIZE);

private Comparator _comparator = NaturalComparator.INSTANCE;

protected void setUp() throws Exception {

513