- •1. Стиль 10
- •3. Проектирование и реализация 63
- •4. Интерфейсы 85
- •5. Отладка 115
- •6. Тестирование 134
- •7. Производительность 157
- •8. Переносимость 180
- •9. Нотация 203
- •Введение
- •Брайан в. Керниган
- •1.1. Имена
- •1.2. Выражения
- •Упражнение 1 -6
- •1.3. Стилевое единство и идиомы
- •1.4. Макрофункции
- •1.5. Загадочные числа
- •1.6. Комментарии
- •1.7. Стоит ли так беспокоиться?
- •Дополнительная литература
- •2.1. Поиск
- •2.2. Сортировка
- •2.3. Библиотеки
- •2.4. Быстрая сортировка на языке Java
- •2.5. "О большое"
- •2.6. Динамически расширяемые массивы
- •2.7. Списки
- •Упражнение 2-8
- •2.8. Деревья
- •Упражнение 2-15
- •2.10. Заключение
- •Дополнительная литература
- •Проектирование и реализация
- •3.1. Алгоритм цепей Маркова
- •3.2. Варианты структуры данных
- •3.3. Создание структуры данных в языке с
- •3.4. Генерация вывода
- •3.5.Java
- •Into the air. When water goes into the air it
- •3.7. Awk и Perl
- •3.8. Производительность
- •3.9. Уроки
- •Дополнительная литература
- •4. Интерфейсы
- •4.1. Значения, разделенные запятой
- •4.2. Прототип библиотеки
- •4.3. Библиотека для распространения
- •Упражнение 4-4
- •4.5 Принципы интерфейса
- •4.6. Управление ресурсами
- •4.7. Abort, Retry, Fail?
- •4.8. Пользовательские интерфейсы
- •Дополнительная литература
- •5. Отладка
- •5.1. Отладчики
- •5.2. Хорошие подсказки, простые ошибки
- •5.3, Трудные ошибки, нет зацепок
- •5.4. Последняя надежда
- •5.5. Невоспроизводимые ошибки
- •5.6. Средства отладки
- •5.7. Чужие ошибки
- •5.8. Заключение
- •Дополнительная литература
- •6. Тестирование
- •6.1. Тестируйте при написании кода
- •6.2. Систематическое тестирование
- •6.3. Автоматизация тестирования
- •6.4. Тестовые оснастки
- •6.5. Стрессовое тестирование
- •6.6. Полезные советы
- •6.7. Кто осуществляет тестирование?
- •6.8. Тестирование программы markov
- •6.9. Заключение
- •Дополнительная литература
- •7.Производительность
- •7.1. Узкое место
- •7.2. Замеры времени и профилирование
- •7.3. Стратегии ускорения
- •7.4. Настройка кода
- •7.5. Эффективное использование памяти
- •7.6. Предварительная оценка
- •7.7. Заключение
- •Дополнительная литература
- •8. Переносимость
- •8.1. Язык
- •8.2. Заголовочные файлы и библиотеки
- •8.3. Организация программы
- •8.4. Изоляция
- •8.5. Обмен данными
- •8.6. Порядок байтов
- •8.7. Переносимость и внесение усовершенствований
- •8.8. Интернационализация
- •8.9. Заключение
- •Дополнительная литература
- •9.1. Форматирование данных
- •9.2. Регулярные выражения
- •Упражнение 9-12
- •9.3. Программируемые инструменты
- •9.4. Интерпретаторы, компиляторы и виртуальные машины
- •9.5. Программы, которые пишут программы
- •9.6. Использование макросов для генерации кода
- •9.7. Компиляция "налету"
- •Дополнительная литература
- •Интерфейсы
- •Отладка
- •Тестирование
- •Производительность
- •Переносимость
2.4. Быстрая сортировка на языке Java
В Java ситуация другая. В ранних версиях не было стандартной функции сортировки, поэтому приходилось писать собственную. В последних версиях появилась такая функция, работающая с классами, реализующими интерфейс Comparable, поэтому теперь мы можем просить библиотеку сортировать то, что нам потребуется. Но поскольку используемые технологии полезны и в других ситуациях, в данном разделе мы опишем все детали реализации быстрой сортировки в Java.
Адаптировать быструю сортировку для каждого конкретного типа данных легко; однако же более поучительно написать обобщенную функцию для сортировки объектов любых типов, что больше похоже на интерфейс qsort.
Одно из крупных отличий от С и C++ заключается в том, что в Java мы не можем передать функцию сравнения в другую функцию — здесь не существует указателей на функции. Вместо этого мы создаем интерфейс (interface), единственным содержимым которого будет функция, сравнивающая два объекта типа Obj ect. Далее для каждого сортируемого типа данных мы создаем класс с функцией (методом), которая реализует интерфейс для этого типа данных. Мы передаем экземпляр класса в функцию сортировки, которая в свою очередь использует функцию сравнения из этого класса для сравнения элементов.
Сначала опишем интерфейс Cmp, который определяет единственную функцию стр, сравнивающую два значения типа Object:
interface Cmp {
int cmp(0bject x, Object y);
}
Теперь мы можем написать функции сравнения, которые реализуют этот интерфейс; например, следующий класс определяет функцию, сравнивающую объекты типа Integer:
// Icmp: сравнение целых
class Icmp implements Cmp {
public int cmp(0bject o1, Object o2)
{
int i1 = ((Integer) o1).intValue();
int i2 = ((Integer) o2).intValue();
if (i1< i2)
return –1;
else if (i1 == i2)
return 0;
else
return 1;
{
}
а эта функция сравнивает объекты типа St ring:
// Scmp: сравнение строк
class Scmp implements Cmp {
public int cmp(0bject o1, Object o2)
{
String s1 = (String) o1;
String s2 = (String) o2;
return s1,compareTo(s2);
}
}
Данным способом можно сортировать только типы, наследуемые от класса Object; подобный механизм нельзя применять для базовых типов, таких как int или double. Поэтому мы сортируем элементы типа Integer, а не int.
С этими компонентами мы теперь можем перенести функцию быстрой сортировки из языка С в Java и вызывать в ней функцию сравнения из объекта Cmp, переданного параметром. Наиболее существенное изменение — это использование индексов left и right, поскольку в Java нет указателей на массивы.
// Quicksort.sort: сортировать vfleft]..v[right]
// алгоритмом quicksort
static void sort(0bject[] v, int left, int right, Cmp cmp)
{
int i, last;
if (left >= right) // ничего делать не надо
return;
swap(v, left, rand(left, right)); // поместить разделитель
last = left; // в v[left]
for (i = left+1; i <= right; i++) // разделить массив
if (cmp.cmp(v[i], v[left]) < 0)
swap(v, ++last, i);
swap(v, left, last); // вернуть разделитель
sort(v, left, last-1, cmp); // рекурсивно отсортировать
sort(v, last+1, right, cmp); // обе части
}
Quicksort.sort использует cmp для сравнения двух объектов и, как и раньше, вызывает swap для их обмена.
// Quicksort.swap: обменять v[i] и v[j]
static void swap(0bject[] v, int i,.int j)
{
Object temp;
temp = v[i];
v[i] = v[j];
v[j] = temp;
}
Генерация случайного номера происходит в функции rand, которая возвращает случайное число в диапазоне с left пo right включительно:
static Random rgen = new Random();
// Quicksort.rand: возвращает случайное целое число
// из [left, right]
static int rand(int left, int right)
{
return left + Math.abs(rgen.nextlnt())%(right-left+1);
}
Мы вычисляем абсолютное значение (используя функцию Math.abs), поскольку в Java генератор случайных чисел возвращает как положительные, так и отрицательные значения.
Функции so rt, swap и rand, а также объект-генератор случайных чисел rgen являются членами класса Quicksort.
Наконец мы готовы написать вызов Quicksort, sort для сортировки массива типа String:
String[] sarr = new String[n];
// заполнить n элементов sarr...
Quicksort.sort(sarr, 0, sarr. length-1, newScmp0);
Так вызывается sort с объектом сравнения строк, созданным для этой цели.
Упражнение 2-2
Наша реализация быстрой сортировки в Java делает несколько преобразований типов, сначала переводя исходные данные из их первоначального типа (вроде Integer) в Object, а затем обратно. Поэкспериментируйте с версией Quicksort. sort, которая использует конкретный тип при сортировке, и попробуйте вычислить, какие потери производительности вызываются преобразованием типов.
