Двоичный поиск в упорядоченном массиве 33 0 1 2 3 1 3 4 8 10 14 16 21 24 27 31 33 36 38 42 44 50 51 53 59 l 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 m private static int bin. Search(int[] data, int key) { int l = 0, h = data. length-1; while (l < h) { int m = (l + h) / 2; // (l <= m < h) if (data[m] < key) l = m + 1; else h = m; } return (data[l] == key ? l : -1); } Инвариант цикла: l <= h && «если key == data[k], то l <= k <= h» 19 h
Сортировки массива 1. Сортировка «пузырьком» public static void bubble. Sort(int[] data) { int n = data. length; for (int i = 1; i < n; i++) { for (int j = 0; j < n-i; j++) { if (data[j] > data [j+1]) { int tmp = data[j]; data[j] = data[j+1]; data[j+1] = tmp; } } 4 27 51 14 31 42 1 4 27 14 31 42 1 4 14 27 31 1 4 14 27 1 4 14 1 8 24 3 59 33 44 53 16 10 38 50 21 36 8 24 3 51 33 44 53 16 10 38 50 21 36 59 8 24 3 42 33 44 51 16 10 38 50 21 36 53 59 8 24 3 31 33 42 44 16 10 38 50 21 36 51 53 59 8 24 3 27 31 33 42 16 10 38 44 21 36 50 51 53 59 8 14 3 24 27 31 33 16 10 38 42 21 36 44 50 51 53 59
2. Сортировка простыми вставками 4 27 51 14 31 42 1 8 24 3 59 33 44 53 16 10 38 50 21 36 4 14 27 51 31 42 1 8 24 3 59 33 44 53 16 10 38 50 21 36 4 14 27 31 51 42 1 8 24 3 59 33 44 53 16 10 38 50 21 36 4 14 27 31 42 51 1 8 24 3 59 33 44 53 16 10 38 50 21 36 public static void simple. Sort(int[] data) { int i, j; for (i = 1; i < data. length; i++) { int c = data[i]; for (j = i-1; j >= 0 && data[j] > c; j--) { data[j+1] = data[j]; } data[j+1] = c; } }
3. Сортировка двоичными вставками public static void bin. Insert. Sort(int[] data) { int n = data. length; // Длина массива for (int i = 1; i < n; i++) { int c = data[i]; // Вставляемое значение // Организация поиска места для вставки значения c int low = 0, high = i; // Inv : (low <= high) && место для c - внутри data[low: high] while (low < high) { int m = (low+high) >> 1; // low <= m < high if (data[m] < c) low = m+1; else high = m; } // Найдено место вставки - low // Сдвигаем элементы в сторону больших индексов. for (int j = i-1; j >= low; j--) { data[j+1] = data[j]; } // Заносим значение на найденное место data[low] = c; } }
4. Сортировка Шелла 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 4 27 51 14 31 42 1 8 24 3 59 33 44 53 16 10 38 50 21 36 4 10 3 14 21 36 1 8 24 38 50 31 42 53 16 27 51 59 33 44 step=7 step=3 1 8 3 4 10 36 14 21 24 27 44 31 33 50 16 38 51 59 42 53 1 4 3 8 10 21 14 27 16 31 24 36 33 38 42 50 44 53 51 59 1 3 4 8 10 14 16 21 24 27 31 33 36 38 42 44 50 51 53 59 step=2 step=1
4. Сортировка Шелла public static void Shell. Sort(int[] data) { int n = data. length; // Длина массива int step = n; // Шаг поисков и вставки int i, j; do { // Вычисляем новый шаг step = step / 3 + 1; // Производим сортировку простыми вставками с заданным шагом for (i = step; i < n; i++) { int c = data[i]; for (j = i-step; j >= 0 && data[j] > c; j -= step) { data[j+step] = data[j]; } data[j+step] = c; } } while (step != 1); } Количество перестановок элементов (по результатам экспериментов со случайным массивом) n = 25 n = 100000 Сортировка Шелла 50 7700 2 100 000 Сортировка простыми вставками 150 240 000 2. 5 млрд.
5. Алгоритм слияния упорядоченных массивов 4 14 27 51 1 3 8 24 31 42 59 public static int[] merge(int[] a, int[] b) { int na = a. length, nb = b. length, nc; int[] c = new int[nc = na + nb]; int ia = 0, ib = 0, ic = 0; while (ia < na && ib < nb) { if (a[ia] < b[ib]) c[ic++] = a[ia++]; else c[ic++] = b[ib++]; } while (ia < na) c[ic++] = a[ia++]; while (ib < nb) c[ic++] = b[ib++]; return c; }
6. Сортировка фон Неймана (слиянием) 0 1 2 3 4 5 6 4 27 51 14 31 42 1 И так далее… 7 8 9 10 11 12 13 14 15 16 17 18 19 8 24 3 59 33 44 53 16 10 38 50 21 36
Алгоритм сортировки фон Неймана public static void merge. Sort(int[] data) { int n = data. length; // Длина массива int[] alt. Data = new int[n]; // Дополнительный массив int[] from = data, // Указатели "откуда" и "куда" происходит слияние to = alt. Data; int len = 1; // Длина сливаемого фрагмента do { int start = 0; while (start < n) { // Сливаем участки from[start: (start+ len-1)] и from[(start+len): (start+2*len-1)] // в to[start: (start+2*len-1)] merge. Section( from, start, Math. min(start+ len, n), from, Math. min(start+len, n), Math. min(start+(len<<1), n), to, start); start += (len << 1); } // Меняем направление слияния int[] interm = from; from = to; to = interm; } while ((len <<= 1) < n); // Если последнего слияния результат оказался "не там", // то переносим результат "куда надо" if (from != data) { merge. Section(from, 0, n, from, n, n, data, 0); } }
7. Пирамидальная сортировка (сортировка «кучей» ) 0 1 2 3 4 5 6 7 4 27 51 14 31 42 1 8 9 10 11 12 13 14 15 16 17 0 27 51 1 2 14 31 42 1 3 4 5 6 8 24 3 59 33 44 53 16 7 15 8 9 10 11 12 13 14 38 50 21 36 16 17 18 19 8 24 3 59 33 44 53 16 10 38 50 21 36 4 10 18 19 И так далее…
7. Пирамидальная сортировка (продолжение) 59 0 51 53 1 2 50 36 42 44 3 4 5 6 24 38 31 7 8 9 4 10 8 21 16 17 18 10 27 33 1 16 11 12 13 14 3 15 14 19 И так далее…
Алгоритм пирамидальной сортировки public static void heap. Sort(int[] data) { int n = data. length; // Длина массива build. Pyramid: // Построение пирамиды for (int i = 1; i < n; i++) { // Inv: Элементы data[0: i-1] уже образуют пирамиду; int c = data[i]; // "Протаскиваемое" значение int p = i, q; // Индексы для "протаскивания" вверх к вершине do { q = p; if ((p = (q-1) >> 1) >= 0 && data[p] < c) data[q] = data[p]; else { data[q] = c; continue build. Pyramid; } } while (true); } melt. Pyramid: // Постепенное разрушение пирамиды for (int i = n-1; i > 0; i--) { int c = data[i]; data[i] = data[0]; int q, p = 0; // Индексы для протаскивания do { q = p; p = (q << 1) | 1; if (p >= i) { // Вышли за границу пирамиды data[q] = c; continue melt. Pyramid; } if (p < i-1 && data[p+1] > data[p]) p++; if (data[p] > c) data[q] = data[p]; else { data[q] = c; continue melt. Pyramid; } } while (true); } }
8. Быстрая сортировка 0 1 2 3 4 5 6 4 27 51 14 31 42 1 7 8 9 10 11 12 13 14 15 16 17 18 19 8 24 3 59 33 44 53 16 10 38 50 21 36 h l 1 3 4 10 8 14 51 42 24 27 59 33 44 53 16 31 38 50 21 36 1 3 4 8 10 14 36 42 24 27 21 33 44 50 16 31 38 51 53 59 1 3 4 8 10 14 31 16 24 27 21 33 36 50 44 42 38 51 53 59 1 3 4 8 10 14 21 16 24 27 31 33 36 38 44 42 50 51 53 59 1 3 4 8 10 14 16 21 24 27 31 33 36 38 42 44 50 51 53 59
Дополнения и улучшения алгоритма ØПервый элемент в сортируемом куске выбирается случайно и запоминается; ØУчастки, меньшие определенного размера, сортируются простыми способами; ØИногда исключение рекурсивных вызовов приводит к повышению эффективности.
Программа быстрой сортировки public static void quick. Sort(int[] data) { quick. Sort(data, 0, data. length-1); } private static void quick. Sort(int[] data, int from, int to) { if (to-from < 50) // Небольшие фрагменты быстрее сортировать методом простых вставок simple. Sort(data, from, to); else { int c = data[from]; // Выбираем некоторый элемент // Распределяем элементы массива на значения меньшие и большие c. int low = from, high = to+1; // Inv: (low <= high) && data[from: (low-1)] <= c && data[high: to] >= c while (low < high) { while (low < high && data[--high] >= c) ; data[low] = data[high]; while (low < high && data[++low] <= c) ; data[high] = data[low]; } // Вставляем элемент на свое место data[low] = c; // Независимо сортируем верхнюю и нижнюю половины массива quick. Sort(data, from, low-1); quick. Sort(data, low+1, to); } }
9. Поиск α-медианы public static int mediana(int[] data, double alpha) { int n = data. length; // Длина массива int m = (int)(alpha*(n-1)); // Номер alpha-медианы в упорядоченном массиве // Ищем элемент номер m в участке массива с индексами от low до high. // Для этого выбираем произвольный элемент и делим массив на две части так, // как это делалось в алгоритме быстрой сортировки. int low = 0, high = n-1; // Границы обрабатываемого участка массива do { int c = data[low]; // Выбранный элемент int ndx. Low = low, ndx. High = high; // "Сдвигающиеся" индексы // Цикл фильтрации элементов на меньшие c и большие c. while (ndx. Low < ndx. High) { while (ndx. Low < ndx. High && data[ndx. High] >= c) ndx. High--; data[ndx. Low] = data[ndx. High]; while (ndx. Low < ndx. High && data[ndx. Low] <= c) ndx. Low++; data[ndx. High] = data[ndx. Low]; } // Нашли порядковый номер элемента c. data[ndx. Low] = c; if (ndx. Low == m) return data[m]; // Продолжаем поиск в одной из двух половин массива if (m < ndx. Low) high = ndx. Low-1; else low = ndx. Low+1; } while (true); }
10. Сортировка подсчетом 0 1 2 3 4 5 6 7 8 9 0 1 2 2 3 5 6 4 6 7 1 10 7 8 9 3 10 11 12 13 14 4 14 0 14 15 16 2 16 17 18 19 20 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 4 0 1 7 1 4 1 2 1 8 4 3 9 3 4 3 6 0 8 0 1 6
Программа для сортировки подсчетом public static void count. Sort (int[] src, int[] dest) { // Предполагается, что все элементы src[i] из диапазона 0. . 15 int n = src. length; // Длина массива int[] count = new int[16]; // Массив для подсчета элементов // 1. Подсчет for (int i = 0; i < n; i++) { count[src[i]]++; } // 2. Суммирование for (int i = 1; i < 16; i++) { count[i] += count[i-1]; } // 3. Расстановка for (int i = n-1; i >= 0; i--) { dest[--count[src[i]]] = src[i]; } }
11. Цифровая сортировка 4 27 51 14 31 42 1 8 24 3 59 33 44 53 16 10 39 50 21 36 После сортировки по последней цифре: 10 50 51 31 1 21 42 3 33 53 4 14 24 44 16 36 27 8 59 39 После устойчивой сортировки по первой цифре: 1 3 4 8 10 14 16 21 24 27 31 33 36 39 42 44 50 51 53 59
Программа для цифровой сортировки public static void digit. Sort(int[] data) { int n = data. length; // Длина массива int[] data 2 = new int[n]; // Вспомогательный массив for (int step = 0; step < 8; step++) { // step - номер "цифры" // Сортировка "подсчетом" по цифре с заданным номером count. Sort(data, step, data 2); // Меняем указатели на массивы int[] temp = data; data = data 2; data 2 = temp; } } private static void count. Sort (int[] src, int n. Dig, int[] dest) { int n = src. length; // Длина массива int[] count = new int[16]; // Массив для подсчета элементов // 1. Подсчет n. Dig <<= 2; for (int i = 0; i < n; i++) { count[(src[i] & (0 x. F << n. Dig)) >> n. Dig]++; } // 2. Суммирование for (int i = 1; i < 16; i++) { count[i] += count[i-1]; } // 3. Расстановка for (int i = n-1; i >= 0; i--) { dest[--count[(src[i] & (0 x. F << n. Dig)) >> n. Dig]] = src[i]; } }


