В данной статье рассматриваются различные варианты сортировки обменами, а также даётся описание простого графического приложения (processing.js) с примерами сортировок.

Перед прочтением рекомендую ознакомиться со статьями:

> Сортировка обменами
> Пузырьковая сортировка и все-все-все
> Глупая сортировка и некоторые другие, поумнее

Пузырьковая сортировка


Простейший вариант: перебирать массив от первого элемента к последнему, меняя местами (если потребуется) соседние элементы.

> Проверить можно здесь

Для того, чтобы передвинуть ползунок, надо нажать на серую кнопку в левом нижнем углу.
При нажатии на кнопку сдвигаем ползунок на один шаг вправо
incPaddle++;

Далее проверяем: не достигли ли мы конца массива (тогда прыгаем в начало), дальше сравниваем (меняем местами) соседние элементы:

Код кнопки

// кнопка
// нажатие 
 void mousePressed() { 
 if(boolButton) {  
 counter++; 
 // сравниваем соседние элементы
  if(mods[incPaddle].rectHight < mods[incPaddle-1].rectHight)   {     
     vTemp= mods[incPaddle-1].rectHight;
     mods[incPaddle-1].rectHight=mods[incPaddle].rectHight;
     mods[incPaddle].rectHight=vTemp;
    }
  } 
}
//отжатие 
void mouseReleased() {
 if(boolButton)  { 
  // передвигаем ползунок   
   incPaddle++;
  // прыгаем в начало массива 
   if(incPaddle>=moduleSize)    {     incPaddle=1;        }
  }   
 }


Processing.js использует структуры данных Java, потом код транслируется в javascript, поэтому
объявление массива экземпляров класса Module, отвечающего за отрисовку элементов и инициализация экземпляров происходит так:

Код

 Module[] mods;
...
 mods[0] = new Module(1*30,  30);
 mods[1] = new Module(2*30,  50);
 mods[2] = new Module(3*30,  10);
 mods[3] = new Module(4*30,  60);
 mods[4] = new Module(5*30,  20);
 mods[5] = new Module(6*30,  100);
 mods[6] = new Module(7*30,  80);
 mods[7] = new Module(8*30,  70);
 mods[8] = new Module(9*30,  90);
 mods[9] = new Module(10*30, 40);  
 


Основная функция отрисовки void draw() представляет собой бесконечный цикл, в котором перебираются экземпляры класса:

for (Module mod : mods) {  mod.display();  }



Можно уменьшить количество переборов, если не перебирать уже отсортированные элементы. Для этого добавим в конец массива limiter (ограничитель), который будет сдвигаться к началу массива после каждого перебора.

   if(incPaddle>=limiter) { 
    incPaddle=1;
    limiter--;
    if(limiter<1) limiter=1; 
   }


> Проверить можно здесь

Еще об одном способе уменьшить количество переборов можно прочитать в статье Cортировка пузырьком (Википедия). Если при проходе массива мы ни разу не поменяли соседние элементы местами, значит массив отсортирован и цикл можно завершать.

Добавим флаг flag, который поднимается, когда мы встречаем пару элементов, которые нужно поменять местами. Если флаг поднят, перебираем массив повторно. Если нет, заканчиваем цикл. Состояние флага выводится в консоль.

Проверка соседних элементов

 if(mods[incPaddle].rectHight < mods[incPaddle-1].rectHight)  
    { 
     flag=true;  // поднимаем флаг
     vTemp= mods[incPaddle-1].rectHight;
     mods[incPaddle-1].rectHight=mods[incPaddle].rectHight;
     mods[incPaddle].rectHight=vTemp;
    }


> Проверить можно здесь

Сортировка чёт-нечет


Будем сдвигать ползунок на два шага, сравнивая соседние элементы
incPaddle=incPaddle+2;

Т.о. мы сравниваем элементы 0 и 1, 2 и 3, 4 и 5, 6 и 7, и т.д.
Достигнув конца мвссива, сдвигаем ограничитель на один шаг влево, ползунок ставим в начало массива и сравниваем элементы 1 и 2, 3 и 4, 5 и 6, 7 и 8, и т.д.
Дойдя до ограничителя, сдвигаем его на одни шаг вправо, ползунок ставим в начало массива.

> Проверить можно здесь

Гномья сортировка


После поднятия флага сохраняем координату ползунка в переменной limiterR и возващаеми ползунок в начало массива по шагам.
incPaddle--;

Оказавшись в начале массива сбрасываем флаг и ставим ползунок в ячейку с координатой, которую мы сохранили в переменную limiterR

if(incPaddle==0){ 
    flag=false;            
    incPaddle=limiterR;
     }


> Проверить можно здесь

Сортировка расчёской


Изменив логику работы ограничителя, получим сортировку расчёской/гребёнкой. Сравниваем (меняем местами) элементы. Сдвигаем ограничитель влево на один шаг и сохраняем его индекс в переменой limiterStore.

if(limiter==moduleSize)   {
    limiter = limiterStore-1;
    limiterStore = limiter;
    incPaddle=1;
   }

Cдвигаем по шагам ползунок с ограничителем в конец массива

if(limiter!=moduleSize)   {   // пока limiter не достиг конца массива
   limiter++;
   incPaddle++;
  }


Дойдя ограничителем до конца массива, ставим ползунок в начало массива, а ограничитель ставим в limiterStore-1:

  if(limiter==moduleSize)   {
    limiter = limiterStore-1;
    limiterStore = limiter;
    incPaddle=1;
   }


> Проверить можно здесь

Шейкерная сортировка



Добавим ограничитель limiterL в начало массива.
Пусть флаг flag поднимается, когда ползунок достигает правого ограничителя limiterR, тогда ограничитель сдвигается влево на один шаг. Далее, когда флаг поднят, ползунок по шагам двигается обратно к левому ограничителю limiterL — ограничитель сдвигается вправо на один шаг — ползунок двигается по шагам вправо…

// отжатие
void mouseReleased() {
 if(boolButton)  {
  if(!flag)    { 
    incPaddle++;
     if(incPaddle==limiterR)  { 
       flag=true;      
       limiterR--;
       if(limiterR<=limiterL+1) limiterR=limiterL+1;   }
   }
  if(flag)    { 
     incPaddle--;
      if(incPaddle==limiterL) { 
       flag=false;     
       limiterL++;      
       if(limiterL>=limiterR-1) limiterL=limiterR-1;  }
     }
   }   
 }


> Проверить можно здесь

Комментарии (5)


  1. LoadRunner
    05.06.2019 09:39

    Я честно посмотрел всю анимацию на КДПВ. Можно её ускорить?


    1. demsp Автор
      05.06.2019 21:19
      +1

      gifка отсюда


  1. mefest
    05.06.2019 16:57

    Простите, но ИМХО как то скудно для хабра. И код под спойлером хорошо бы отформатировать.


    1. demsp Автор
      05.06.2019 21:20
      +1

      спасибо, отформатировал


  1. FForth
    05.06.2019 23:45

    Визуализация алгоритмов сортировки в танцах