- •А. С. Третьяков алгоритмы
- •Структуры данных Оглавление
- •2.1 Введение 20
- •4.1 Введение 69
- •5.1 Введение 87
- •Предисловие
- •Раздел I структуры данных
- •Глава 1. Массивы
- •1.1 Введение
- •1.2.1 Метод деления
- •1.2.2 Метод умножения
- •1.3.1 Открытое хеширование
- •1.3.2 Закрытое хеширование
- •1.4 Ассоциативный массив
- •1.5 Динамический массив
- •Глава 2. Списки
- •2.1 Введение
- •2.2 Связный список
- •2.3 Стек
- •2.4 Очередь
- •2.4.1 Реализация очереди с помощью массива
- •2.4.2 Реализация очереди с помощью указателей
- •Глава 3. Графы
- •3.1 Основные понятия и виды графов
- •3.2 Матрица смежности
- •3.3 Список смежности
- •3.4 Список ребер
- •3.5 Матрица инцидентности
- •Глава 4. Деревья
- •4.1 Введение
- •4.2 Двоичное дерево
- •4.3 Двоичное дерево поиска
- •4.4 Куча
- •4.5.1 Балансировка
- •4.5.2 Добавление узлов
- •4.5.3 Удаление узлов
- •Раздел II алгоритмы
- •Глава 5. Анализ сложности алгоритмов
- •5.1 Введение
- •5.2 Асимптотический анализ
- •Глава 6. Сортировка
- •6.1 Сортировка пузырьком
- •6.2 Сортировка выбором
- •6.3 Сортировка вставками
- •6.4 Сортировка Шелла
- •6.5 Быстрая сортировка
- •6.5.1 Разбиение массива
- •6.5.2 Рекурсивная сортировка частей массива
- •6.6 Сортировка слиянием
- •6.7 Гномья сортировка
- •6.8 Шейкерная сортировка
- •Глава 7. Поиск
- •7.1 Линейный поиск
- •7.2 Двоичный поиск
- •7.3 Интерполяционный поиск
- •Глава 8. Теория чисел
- •8.1 Алгоритм Евклида
- •8.1.1 Метод вычитания
- •8.1.2 Метод деления
- •8.2 Бинарный алгоритм вычисления нод
- •8.3 Быстрое возведение в степень
- •8.4 Решето Эратосфена
- •8.5 Решето Сундарама
- •Глава. 9 Графы
- •9.1 Поиск в ширину
- •9.2 Поиск в глубину
- •9.3 Алгоритм Дейкстры
- •9.4 Алгоритм Флойда – Уоршелла
- •9.5 Алгоритм Беллмана — Форда
6.7 Гномья сортировка
Г
номья
сортировка
впервые была предложена 2 октября 2000
года Хамидом Сарбази-Азадом (Hamid
Sarbazi-Azad). Он назвал ее «Глупая сортировка,
простейший алгоритм сортировки всего
с одним циклом...». И действительно,
глупый этот метод или нет, но в нем
задействован, никак в большинстве
сортировок – два или более циклов, а
только один. Позже, голландский ученый
Дик Грун, на страницах одной из своих
книг, привел для гномьей сортировки
следующую аналогию.
«Gnome Sort is based on the technique used by the standard Dutch Garden Gnome (Du.: tuinkabouter). Here is how a garden gnome sorts a line of flower pots. Basically, he looks at the flower pot next to him and the previous one; if they are in the right order he steps one pot forward, otherwise he swaps them and steps one pot backwards. Boundary conditions: if there is no previous pot, he steps forwards; if there is no pot next to him, he is done».
Перевод:
«Гномья сортировка основана на технике, используемой обыкновенным голландским садовым гномом. Вот как садовый гном сортирует ряд цветочных горшков. По существу, он смотрит на два соседних цветочных горшка, если они находятся в правильном порядке, то он переходит на один горшок вперед, иначе он меняет их местами и возвращается на один горшок назад. Граничные условия: если позади нет ни одного горшка – он шагает вперед, а если нет следующего горшка, тогда он закончил».
Так описал основную идею алгоритма гномьей сортировки Дик Грун. Заменим гнома и горшки на более формальные объекты, например на указатель (номер текущего элемента) и элементы массива, и рассмотрим принцип работы алгоритма еще раз. Вначале указатель ставиться на 2-ый элемент массива (в C++ он имеет номер 1, а в Паскале номер 2). Затем происходит сравнение двух соседних элементов A[i] и A[i-1], т. е. сравниваются первый элемент (i-1) и второй (i). Если сравниваемые элементы стоят на своих позициях, то сдвигаем указатель на позицию i+1 и продолжаем сравнение с нового положения; иначе меняем элементы местами, и, поскольку в какой-то момент может оказаться, что элементы в левом подмассиве стоят не на своих местах, сдвигаем указатель на одну позицию влево, осуществляя следующее сравнение с новой позиции. Так алгоритм продолжает выполняться до тех пор, пока весь массив не будет упорядочен. Здесь следует выделить два важных момента. Во-первых, процесс упорядочивания заканчивается, тогда когда не выполняется условие i<n, где n – размер массива. Во-вторых, как было сказано, указатель перемещается как вперед по списку, так и назад, и в том случае если он окажется над первым элементом, его сразу же следует сместить на одну позицию вправо, т. к. в противном случае придется сравнивать два элемента, одного из которых не существует.
Перейдем собственно к коду. На своем сайте Дик Грун выложил следующий листинг:
void gnomesort(int n, int ar[])
{
int i = 0;
while (i < n)
{
if (i == 0 || ar[i-1] <= ar[i]) i++;
else
{
int tmp = ar[i];
ar[i]=ar[i-1];
ar[--i]=tmp;
}
}
}
Приведенный Груном код позволяет упорядочить массив, но все же он может быть немного улучшен. Оптимизация потребует небольшого редактирования, в частности, добавления одной вспомогательной переменной, что позволит избавиться от излишних сравнений. Далее показаны листинги программ, сортирующих элементы массива по возрастанию.
Код программы на C++:
int n;
void Gnome_sort(int i, int j, int *mas) //Гномья сортировка
{
while (i<n)
{
if (mas[i-1]<=mas[i]) { i=j; j++; }
else
{
int t=mas[i];
mas[i]=mas[i-1]; mas[i-1]=t;
i--;
if (i==0)
{
i=j;
j++;
}
}
}
for (i=0; i<n; i++) cout<<mas[i]<<" ";
}
void main() //главная функция
{
int m, k;
cout<<"Размер массива > "; cin>>n;
int *a=new int[n];
for (k=0; k<n; k++)
{
cout<<k+1<<" элемент > ";
cin>>a[k];
}
k=1; m=2;
Gnome_sort(k, m, a);
delete []a;
}
Код программы Pascal:
type massiv=array[1..100] of integer;
var k, m, n: integer;
a: massiv;
procedure PGnome_sort(i, j: integer; mas: massiv); {Гномья сортировка}
var t: integer;
begin
while i<=n do
begin
if mas[i-1]<=mas[i] then
begin
i:=j;
j:=j+1;
end
else
begin
t:=mas[i];
mas[i]:=mas[i-1];
mas[i-1]:=t;
i:=i-1;
if i=1 then
begin
i:=j;
j:=j+1;
end;
end;
end;
for i:=1 to n do write(mas[i], ' ');
end;
begin {основной блок программы}
write('Размер массива > '); read(n);
for k:=1 to n do
begin
write(k, ' элемент > ');
read(a[k]);
end;
k:=2;
m:=3;
PGnome_sort(k, m, a);
end.
Кажется немного необычным, тот факт, что алгоритм сортировки использует всего один цикл. Плюс к этому, на практике гномья сортировка не уступает в скорости сортировки вставками, что видно из таблицы трех случаев этих сортировок.
|
Гномья сортировка |
Сортировка вставками |
Худший случай |
O(n2) |
O(n2) |
Лучший случай |
O(n) |
O(n) |
Средний случай |
O(n2) |
O(n2) |
