Как стать автором
Обновить

Сравнение алгоритмов сортировки обменами

Время на прочтение29 мин
Количество просмотров6.6K

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

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


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

→ Проверить здесь


Листинг
int counter;
int moduleSize = 10;

// paddle
int slider=1;

int vTemp;

//button
int buttonX=25, buttonY=325;
int buttonSize = 50;
boolean boolButton = false;

int count;
Module[] mods;

void setup() {
size(400, 400);
mods = new Module[moduleSize];
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() {
background(50);
buttonUpdate();
for (Module mod: mods) { mod.display(); }

// paddle
rect (slider*30, 85, 20, 5);
// rect (floatingStoper*30, 75, 20, 5);

textSize(25);
text(counter,300,350);
// draw button
fill(150);
rect(buttonX,buttonY,buttonSize,buttonSize);
if(boolButton && mousePressed)
{
fill(200);
rect(buttonX,buttonY,buttonSize,buttonSize);
}
}
class Module {
int xOffset;
int rectHight;

// Contructor
Module(int xOffsetTemp, int rectHightTemp) {
xOffset = xOffsetTemp;
rectHight=rectHightTemp;
}
// Custom method for drawing the object
void display() {
fill(255);
rect(xOffset, 100, 20, rectHight);
}
}

// кнопка
// нажатие
void mousePressed() {
if(boolButton)
{
counter++;
if(mods[slider].rectHight < mods[slider-1].rectHight)
{
vTemp= mods[slider-1].rectHight;
mods[slider-1].rectHight=mods[slider].rectHight;
mods[slider].rectHight=vTemp;
}
}
}
//отжатие
void mouseReleased() {
if(boolButton)
{
slider++;
if(slider>=moduleSize)
{
slider=1;
}
}
}

void buttonUpdate() {
if ( overButton(buttonX, buttonY, buttonSize, buttonSize) ) {
boolButton = true;
} else {
boolButton = false;
}
}
boolean overButton(int x, int y, int width, int height) {
if (mouseX >= x && mouseX <= x+width &&
mouseY >= y && mouseY <= y+height) {
return true;
} else {
return false;
}
}


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

Далее проверяем: находится ли ползунок на противоположной границе массива (тогда прыгаем в начало массива)

if(slider>=moduleSize) 
   { 
    slider=1;     
   }

далее сравниваем/меняем местами соседние элементы

if(mods[slider].rectHight < mods[slider-1].rectHight)  
    {     
     vTemp= mods[slider-1].rectHight;
     mods[slider-1].rectHight=mods[slider].rectHight;
     mods[slider].rectHight=vTemp;
    }

Поскольку нумерация элементов массива начинается с нуля, а ползунок изначально (при инициализации) находится в первой ячейке int slider=1;, то нам нужно сравнить текущий элемент mods[slider].rectHight с предыдущим mods[slider-1].rectHight

Код кнопки

// кнопка
// нажатие 
 void mousePressed() { 
 if(boolButton)
 {  
 counter++; 
  if(mods[slider].rectHight < mods[slider-1].rectHight)  
    {     
     vTemp= mods[slider-1].rectHight;
     mods[slider-1].rectHight=mods[slider].rectHight;
     mods[slider].rectHight=vTemp;
    }
  } 
}
//отжатие 
void mouseReleased() {
 if(boolButton)
  {    
   slider++;
   if(slider>=moduleSize)    { 
    slider=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();  }

Для нажатия на кнопку (прямоугольник в левом нижнем углу) необходимо сравнить координаты курсора и кнопки в булевой функции overButton(). Само нажатие обрабатывается в функции mousePressed(). Отжатие кнопки обрабатывается в функции mouseReleased().

Рандомные значения


Добавим функцию randFoo(), которая возвращает рандомные значения. Для того, чтобы значения не повторялись, будем добавлять их к ArrayList списку listRand, а в функции randFoo() проверять, не входит ли новое рандомное число в список listRand

int randFoo(){
  newRand = int(random(1,11));
  if(!listRand.contains(newRand) )  listRand.add(newRand );
 	 else newRand=randFoo();
		return newRand;
}


→ Проверить здесь
Листинг
ArrayList listRand;
int newRand;

int counter;
int moduleSize = 10;
//int floatingStoper = moduleSize;

// paddle
int incPaddle=1;

int vTemp;

//button
int buttonX=25, buttonY=325;
int buttonSize = 50;
boolean boolButton = false;

int count;
Module[] mods;

void setup() {
size(400, 400);
listRand = new ArrayList(10);
mods = new Module[moduleSize];

mods[0] = new Module(1*30, randFoo()*10 );
mods[1] = new Module(2*30, randFoo()*10 );
mods[2] = new Module(3*30, randFoo()*10 );
mods[3] = new Module(4*30, randFoo()*10 );
mods[4] = new Module(5*30, randFoo()*10 );
mods[5] = new Module(6*30, randFoo()*10 );
mods[6] = new Module(7*30, randFoo()*10 );
mods[7] = new Module(8*30, randFoo()*10 );
mods[8] = new Module(9*30, randFoo()*10 );
mods[9] = new Module(10*30, randFoo()*10 );
}

void draw() {
background(50);
buttonUpdate();
for (Module mod: mods) { mod.display(); }

// paddle
rect (incPaddle*30, 85, 20, 5);
// rect (floatingStoper*30, 75, 20, 5);

textSize(25);
text(counter,300,350);
// draw button
fill(150);
rect(buttonX,buttonY,buttonSize,buttonSize);
if(boolButton && mousePressed)
{
fill(200);
rect(buttonX,buttonY,buttonSize,buttonSize);
}
}
class Module {
int xOffset;
int rectHight;

// Contructor
Module(int xOffsetTemp, int rectHightTemp) {
xOffset = xOffsetTemp;
rectHight=rectHightTemp;
}
// Custom method for drawing the object
void display() {
fill(255);
rect(xOffset, 100, 20, rectHight);
}
}

// кнопка
// нажатие
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;
}
}
}

void buttonUpdate() {
if ( overButton(buttonX, buttonY, buttonSize, buttonSize) ) {
boolButton = true;
} else {
boolButton = false;
}
}
boolean overButton(int x, int y, int width, int height) {
if (mouseX >= x && mouseX <= x+width &&
mouseY >= y && mouseY <= y+height) {
return true;
} else {
return false;
}
}

int randFoo(){
newRand = int(random(1,11));
if(!listRand.contains(newRand) ) listRand.add(newRand );
else newRand=randFoo();
return newRand;
}


Пиксельная сортировка



Пиксельная сортировка является реализацией пузырьковой сортировки.
Будем сдвигать более тёплые/светлые пиксели в одну сторону, а более тёмные/холодные в другую


void draw(){
  while (i <= height) { 
  c=get(i,j);  // получаем цвет пикселя
  cTemp=c;   // запоминаем цвет во временной переменной
  i++;            // переходим к следующему пикселю
  c=get(i,j);   // получаем цвет следующего пикселя
 if(cTemp>c)    { // сравниваем пиксели
   fill(c);               // меняем пиксели местами
   rect(i-1,j,1,1);  
   fill(cTemp);
  rect(i,j,1,1);   } 
 }  
  if(mousePressed) { if(j>=width) j=0; } // переходим к следующей колонке пикселей 
  if(i >= height) {j++; i=0;}
}

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

Чтобы начать сортировку, надо кликнуть на картинку и удерживать кнопку.
Ещё про пиксельные сортировки можно прочитать здесь.
Видео о пиксельной сортировке на канале The Coding Train здесь

Ограничитель и флаг



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

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


→ Проверить здесь
Листинг
int counter;
int moduleSize = 10;
int limiter = moduleSize;
int slider=1;

int vTemp;
//button
int buttonX=25, buttonY=325;
int buttonSize = 50;
boolean boolButton = false;

int count;
Module[] mods;

void setup() {
size(400, 400);
mods = new Module[moduleSize];
mods[0] = new Module(1*30, 100);
mods[1] = new Module(2*30, 50);
mods[2] = new Module(3*30, 30);
mods[3] = new Module(4*30, 60);
mods[4] = new Module(5*30, 20);
mods[5] = new Module(6*30, 40);
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, 10);
}

void draw() {
background(50);
buttonUpdate();
for (Module mod: mods) { mod.display(); }

// paddle
rect (slider*30, 85, 20, 5);
rect (limiter*30, 75, 20, 5);

textSize(25);
text(counter,300,350);
// draw button
fill(150);
rect(buttonX,buttonY,buttonSize,buttonSize);
if(boolButton && mousePressed)
{
fill(200);
rect(buttonX,buttonY,buttonSize,buttonSize);
}
}
class Module {
int xOffset;
int rectHight;

// Contructor
Module(int xOffsetTemp, int rectHightTemp) {
xOffset = xOffsetTemp;
rectHight=rectHightTemp;
}
// Custom method for drawing the object
void display() {
fill(255);
rect(xOffset, 100, 20, rectHight);
}
}

// button
void mouseReleased() {
if(boolButton)
{
slider++;
if(slider>=limiter)
{
slider=1;
limiter--;
if(limiter<1) limiter=1;
}
}
}

void mousePressed() {
if(boolButton)
{
counter++;
if(mods[slider].rectHight < mods[slider-1].rectHight)
{
vTemp= mods[slider-1].rectHight;
mods[slider-1].rectHight=mods[slider].rectHight;
mods[slider].rectHight=vTemp;
}
}
}

void buttonUpdate() {
if ( overButton(buttonX, buttonY, buttonSize, buttonSize) ) {
boolButton = true;
} else {
boolButton = false;
}
}
boolean overButton(int x, int y, int width, int height) {
if (mouseX >= x && mouseX <= x+width &&
mouseY >= y && mouseY <= y+height) {
return true;
} else {
return false;
}
}



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

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

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

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



→ Проверить здесь
Листинг
boolean flag;

int counter;
int moduleSize = 10;
int limiter = moduleSize;
int slider=1;
int vTemp;

//button
int buttonX=25, buttonY=325;
int buttonSize = 50;
boolean boolButton = false;

int count;
Module[] mods;

void setup() {
size(400, 400);
mods = new Module[moduleSize];
mods[0] = new Module(1*30, 10);
mods[1] = new Module(2*30, 50);
mods[2] = new Module(3*30, 30);
mods[3] = new Module(4*30, 60);
mods[4] = new Module(5*30, 20);
mods[5] = new Module(6*30, 40);
mods[6] = new Module(7*30, 70);
mods[7] = new Module(8*30, 80);
mods[8] = new Module(9*30, 90);
mods[9] = new Module(10*30, 100);
}

void draw() {
background(50);
buttonUpdate();
for (Module mod: mods) { mod.display(); }

// paddle
rect (slider*30, 85, 20, 5);
rect (limiter*30, 75, 20, 5);

textSize(25);
text(counter,300,300);
// draw button
fill(150);
rect(buttonX,buttonY,buttonSize,buttonSize);
if(boolButton && mousePressed)
{
fill(200);
rect(buttonX,buttonY,buttonSize,buttonSize);
}
println(flag);
}

class Module {
int xOffset;
int rectHight;

// Contructor
Module(int xOffsetTemp, int rectHightTemp) {
xOffset = xOffsetTemp;
rectHight=rectHightTemp;
}
// Custom method for drawing the object
void display() {
fill(255);
rect(xOffset, 100, 20, rectHight);
}
}

// button
void mouseReleased() {
if(boolButton)
{
slider++;
if(slider>=limiter)
{
// flag
slider=1;
limiter--;
if(limiter<1) limiter=1;
}
}
}

void mousePressed() {
if(boolButton)
{
counter++;

if(flag==false && slider==limiter-1)
{
limiter=1;
slider=1;
}
if(slider==limiter-1 && flag==true){flag=false;}

if(mods[slider].rectHight < mods[slider-1].rectHight)
{
flag=true;
vTemp= mods[slider-1].rectHight;
mods[slider-1].rectHight=mods[slider].rectHight;
mods[slider].rectHight=vTemp;
}
}
}

void buttonUpdate() {
if ( overButton(buttonX, buttonY, buttonSize, buttonSize) ) {
boolButton = true;
} else {
boolButton = false;
}
}
boolean overButton(int x, int y, int width, int height) {
if (mouseX >= x && mouseX <= x+width &&
mouseY >= y && mouseY <= y+height) {
return true;
} else {
return false;
}
}


Если поставить ограничитель слева и использовать элемент с ограничителем как опорный/минимальный, получим сортировку выбором.

Добавим переменную min, в которую будет загружаться минимальное значение. Пусть изначально крайний левый элемент является минимальным: при первом проходе массива, если попадается элемент меньше минимального, то сохраняем сам этот элемент в переменной min

if(mods[slider-1].rectHight < min){     
     min=mods[slider-1].rectHight;
    }

далее меняем местами первый элемент и минимальный

 if (mods[limiterL-1].rectHight>min) {     
     vTemp= mods[limiterL-1].rectHight;
     mods[limiterL-1].rectHight=mods[slider-1].rectHight;
     mods[slider-1].rectHight=vTemp;
    }    


Если ползунок достигает правого края массива, то ограничитель сдвигается на один шаг вправо, а ползунок перемещается к ограничителю

if(slider==moduleSize){ 
      if(limiterL<moduleSize) limiterL++;
      min=mods[limiterL-1].rectHight;
      incPaddle=limiterL-1; 
      }

→ Проверить здесь
Листинг
int min;
int counter;
int moduleSize = 10;
int limiterL = 1;

int slider=1;

int vTemp;
//button
int buttonX=25, buttonY=325;
int buttonSize = 50;
boolean boolButton = false;

int count;
Module[] mods;

void setup() {
size(400, 400);
mods = new Module[moduleSize];
mods[0] = new Module(1*30, 80);
mods[1] = new Module(2*30, 50);
mods[2] = new Module(3*30, 30);
mods[3] = new Module(4*30, 60);
mods[4] = new Module(5*30, 20);
mods[5] = new Module(6*30, 40);
mods[6] = new Module(7*30, 100);
mods[7] = new Module(8*30, 70);
mods[8] = new Module(9*30, 90);
mods[9] = new Module(10*30, 10);
min = mods[0].rectHight;
}

void draw() {
background(50);
buttonUpdate();
for (Module mod: mods) { mod.display(); }

// paddle
rect (slider*30, 85, 20, 5);
rect (limiterL*30, 75, 20, 5);

textSize(25);
text(counter,300,350);
text(min,30,30);
// draw button
fill(150);
rect(buttonX,buttonY,buttonSize,buttonSize);
if(boolButton && mousePressed){
fill(200);
rect(buttonX,buttonY,buttonSize,buttonSize);
}
}

class Module {
int xOffset;
int rectHight;

// Contructor
Module(int xOffsetTemp, int rectHightTemp) {
xOffset = xOffsetTemp;
rectHight=rectHightTemp;
}
// Custom method for drawing the object
void display() {
fill(255);
rect(xOffset, 100, 20, rectHight);
}
}

// button
void mouseReleased() {
if(boolButton)
{
if (mods[limiterL-1].rectHight>min)
{
vTemp= mods[limiterL-1].rectHight;
mods[limiterL-1].rectHight=mods[slider-1].rectHight;
mods[slider-1].rectHight=vTemp;
}

if(slider==moduleSize){
if(limiterL<moduleSize) limiterL++;
min=mods[limiterL-1].rectHight;
slider=limiterL-1;
}
slider++;
}
}


void mousePressed() {
if(boolButton)
{
counter++;
if(mods[slider-1].rectHight < min){
min=mods[slider-1].rectHight;
}
}
}

void buttonUpdate() {
if ( overButton(buttonX, buttonY, buttonSize, buttonSize) ) {
boolButton = true;
} else {
boolButton = false;
}
}
boolean overButton(int x, int y, int width, int height) {
if (mouseX >= x && mouseX <= x+width &&
mouseY >= y && mouseY <= y+height) {
return true;
} else {
return false;
}
}


Количество тактов можно сократить, если в самом начале перебора сравнивать (менять местами) текущий элемент и крайний правый элемент массива

if(mods[limiterL-1].rectHight>mods[moduleSize-1].rectHight)     {
     vTemp=mods[limiterL-1].rectHight;
     mods[limiterL-1].rectHight=mods[moduleSize-1].rectHight;
     mods[moduleSize-1].rectHight=vTemp;        
     }

Тогда можно не проверять крайний правый элемент массива

//if(slider==moduleSize){       
     if(slider==moduleSize-1){
      //if(limiterL<moduleSize) limiterL++;
      limiterL++;      
      min=mods[limiterL-1].rectHight;
      slider=limiterL-1; 
      }
     // slider++;
    if(slider<moduleSize) slider++;    


→ Проверить здесь

Если сортировать правую часть массива по убыванию, добавив максимальный элемент max — получим шейкерную сортировку выбором. Раздел про шейкерную сортировку в конце статьи.

Быстрая сортировка



Этот алгоритм предполагает выбор начального опорного элемента, с которым сравниваются все остальные элементы массива. От выбора начального элемента зависит время выполнения алгоритма. На gif-ке, представленной выше, начальным является элемент с номером 3. Подробнее про выбор начального опорного элемента здесь (Википедия).
Видео, посвящённое быстрой сортировке
Вот здесь визуализация алгоритма
Если опорным является первый элемент, то перед ним вставляются элементы меньше опорного, тогда массив разделяется на две части: слева будут элементы меньше опорного, справа — больше. О таком способе см. раздел про сортировку вставками ниже.

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


По существу гном смотрит на следующий и предыдущий садовые горшки: если они в правильном порядке, он шагает на один горшок вперёд, иначе он меняет их местами и шагает на один горшок назад.

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

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

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


→ Проверитьздесь
Листинг
boolean flag;

int counter;
int moduleSize = 10;
int limiterR = moduleSize;
int slider=1;

int vTemp;
//button
int buttonX=25, buttonY=325;
int buttonSize = 50;
boolean boolButton = false;

int count;
Module[] mods;

void setup() {
size(400, 400);
mods = new Module[moduleSize];
mods[0] = new Module(1*30, 10);
mods[1] = new Module(2*30, 20);
mods[2] = new Module(3*30, 30);
mods[3] = new Module(4*30, 50);
mods[4] = new Module(5*30, 40);
mods[5] = new Module(6*30, 60);
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, 100);
}

void draw() {
background(50);
buttonUpdate();
for (Module mod: mods) { mod.display(); }

// paddle
rect (slider*30, 85, 20, 5);
rect (limiterR*30, 75, 20, 5);

textSize(25);
text(counter,300,350);
// draw button
fill(150);
rect(buttonX,buttonY,buttonSize,buttonSize);
if(boolButton && mousePressed)
{
fill(200);
rect(buttonX,buttonY,buttonSize,buttonSize);
}
println(flag);
}

class Module {
int xOffset;
int rectHight;

// Contructor
Module(int xOffsetTemp, int rectHightTemp) {
xOffset = xOffsetTemp;
rectHight=rectHightTemp;
}
// Custom method for drawing the object
void display() {
fill(255);
rect(xOffset, 100, 20, rectHight);
}
}

// button
void mouseReleased() {
if(boolButton)
{

if(!flag){
if(slider<moduleSize) slider++;
}
if(flag){
slider--;
if(slider==0){
flag=false;
slider=limiterR;
}
}
}
}

void mousePressed() {
if(boolButton)
{
counter++;
if(slider>=moduleSize) slider=moduleSize;
else{
if(mods[slider-1].rectHight > mods[slider].rectHight)
{ flag=true;
limiterR=slider;
vTemp= mods[slider-1].rectHight;
mods[slider-1].rectHight=mods[slider].rectHight;
mods[slider].rectHight=vTemp; }
}
}
}

void buttonUpdate() {
if ( overButton(buttonX, buttonY, buttonSize, buttonSize) ) {
boolButton = true;
} else {
boolButton = false;
}
}
boolean overButton(int x, int y, int width, int height) {
if (mouseX >= x && mouseX <= x+width &&
mouseY >= y && mouseY <= y+height) {
return true;
} else {
return false;
}
}



Изменив данный алгоритм, получим сортировку вставками
В сортировке вставками выбирается опорный/минимальный элемент, затем в неотсортированной части массива выбирается элемент, меньше опорного и вставляется перед опорным

Пусть у нас минимальный элемент обменивается местами с предыдущими, вплоть до опорного, и таким образом вставляется перед опорным
Добавим условие

  if(slider==limiterR-1 &&
     mods[slider-1].rectHight<mods[limiterR-1].rectHight){
   flag=false;            
   slider=limiterR;
   }


→ Проверить здесь

Сравнение с ограничителем
гномья сортировка вставками использует оба механизма
Поставим ограничитель слева и будем использовать элемент с ограничителем как опорный/минимальный, подобно тому, как это делается в сортировке выбором.
Если текущий элемент больше минимального, сдвигаем ползунок вправо

if(mods[slider-1].rectHight > mods[limiterL-1].rectHight) 
   slider++;  

Если текущий элемент меньше минимального, сохраняем координату ползунка в переменной limiterR и возвращаем ползунок в начало массива по шагам, подобно тому, как это делается в гномьей сортировке

 vTemp= mods[slider-1].rectHight;
     mods[slider-1].rectHight=mods[slider-2].rectHight;
     mods[slider-2].rectHight=vTemp;
     slider--;

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

if(flag && slider==limiterL)  {
      flag=false;
      slider=limiterR;
    }

Если ползунок выходит за правый край, сдвигаем ограничитель на один шаг вправо, возвращаем ползунок к ограничителю

if(slider==moduleSize+1)  {
    limiterL++;
    slider=limiterL+1;
    }


→ Проверить здесь

Добавим сравнение/обмен текущего и следующего за текущим элементы по методу пузырька

 if(slider<moduleSize)if(mods[slider].rectHight<mods[slider-1].rectHight){ 
     vTemp= mods[slider-1].rectHight;
     mods[slider-1].rectHight=mods[slider].rectHight;
     mods[slider].rectHight=vTemp;     
    }


→ Проверить здесь
Листинг
ArrayList listRand;
int newRand;

int counter;
int moduleSize = 15;

// paddle
int slider=2;
int limiterL = 1;

int vTemp;
int limiterR=moduleSize;

//button
int buttonX=25, buttonY=325;
int buttonSize = 50;

boolean boolButton = false;
boolean flag;

int count;
Module[] mods;

void setup() {
size(500, 400);
mods = new Module[moduleSize];
listRand = new ArrayList(moduleSize);

mods[0] = new Module(1*30, randFoo()*10 );
mods[1] = new Module(2*30, randFoo()*10 );
mods[2] = new Module(3*30, randFoo()*10 );
mods[3] = new Module(4*30, randFoo()*10 );
mods[4] = new Module(5*30, randFoo()*10 );
mods[5] = new Module(6*30, randFoo()*10 );
mods[6] = new Module(7*30, randFoo()*10 );
mods[7] = new Module(8*30, randFoo()*10 );
mods[8] = new Module(9*30, randFoo()*10 );
mods[9] = new Module(10*30, randFoo()*10 );
mods[10] = new Module(11*30, randFoo()*10 );
mods[11] = new Module(12*30, randFoo()*10 );
mods[12] = new Module(13*30, randFoo()*10 );
mods[13] = new Module(14*30, randFoo()*10 );
mods[14] = new Module(15*30, randFoo()*10 );
}

void draw() {
background(50);
buttonUpdate();
for (Module mod: mods) { mod.display(); }

// paddle
rect (slider*30, 85, 20, 5);
rect (limiterL*30, 75, 20, 5);
rect (limiterR*30, 65, 20, 5);


textSize(25);
text(counter,300,350);
// draw button
fill(150);
rect(buttonX,buttonY,buttonSize,buttonSize);
if(boolButton && mousePressed)
{
fill(200);
rect(buttonX,buttonY,buttonSize,buttonSize);
}
}
class Module {
int xOffset;
int rectHight;

// Contructor
Module(int xOffsetTemp, int rectHightTemp) {
xOffset = xOffsetTemp;
rectHight=rectHightTemp;
}
// Custom method for drawing the object
void display() {
fill(255);
rect(xOffset, 100, 20, rectHight);
}
}

// кнопка
// нажатие
void mousePressed() {
if(boolButton)
{
counter++;
if(slider<moduleSize)if(mods[slider].rectHight<mods[slider-1].rectHight)
{
vTemp= mods[slider-1].rectHight;
mods[slider-1].rectHight=mods[slider].rectHight;
mods[slider].rectHight=vTemp;
}


if(limiterL==moduleSize){
limiterL=moduleSize;
limiterR=moduleSize;
slider=moduleSize;
}
if(!flag)
{
if(mods[slider-1].rectHight < mods[limiterL-1].rectHight)
{
flag=true;
limiterR=slider;
}
if(mods[slider-1].rectHight > mods[limiterL-1].rectHight)
slider++;
}
if(flag && slider==limiterL)
{
flag=false;
slider=limiterR;
}
}
}
//отжатие
void mouseReleased() {
if(boolButton)
{
if(flag)
{
vTemp= mods[slider-1].rectHight;
mods[slider-1].rectHight=mods[slider-2].rectHight;
mods[slider-2].rectHight=vTemp;
slider--;
}
if(slider==moduleSize+1)
{
limiterL++;
slider=limiterL+1;
}

}///
}///

void buttonUpdate() {
if ( overButton(buttonX, buttonY, buttonSize, buttonSize) ) {
boolButton = true;
} else {
boolButton = false;
}
}
boolean overButton(int x, int y, int width, int height) {
if (mouseX >= x && mouseX <= x+width &&
mouseY >= y && mouseY <= y+height) {
return true;
} else {
return false;
}
}

int randFoo(){
newRand = int(random(1,moduleSize+1));
if(!listRand.contains(newRand) ) listRand.add(newRand );
else newRand=randFoo();
return newRand;
}



«Быстрая» сортировка вставками
В данном алгоритме массив разделяется опорным элементом на две части
Пускай опорным будет первый элемент: сравниваем, начиная со второго, элементы массива с опорным, если попадётся элемент меньше опорного

if(mods[slider-1].rectHight < mods[pivot-1].rectHight)

вставляем перед опорным найденный элемент

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

Если флаг поднят, сдвигаем ползунок влево по шагам, пока не встретим опорный элемент

if(flag){ 
           slider--;
           if(slider<pivot){ 
                           flag=false; // опускаем флаг
                           pivot++; 
                           slider=pivot;
                           }
           }

Т.о. массив разделяется на две части, слева — элементы меньше опорного, справа — больше

→ Проверить здесь
Листинг
boolean flag;

int counter;
int moduleSize = 10;
int pivot = 1;
int slider=2;

int vTemp;
//button
int buttonX=25, buttonY=325;
int buttonSize = 50;
boolean boolButton = false;

int count;
Module[] mods;

void setup() {
size(400, 400);
mods = new Module[moduleSize];
mods[0] = new Module(1*30, 50);
mods[1] = new Module(2*30, 70);
mods[2] = new Module(3*30, 10);
mods[3] = new Module(4*30, 20);
mods[4] = new Module(5*30, 30);
mods[5] = new Module(6*30, 60);
mods[6] = new Module(7*30, 80);
mods[7] = new Module(8*30, 90);
mods[8] = new Module(9*30, 40);
mods[9] = new Module(10*30, 100);
}

void draw() {
background(50);
buttonUpdate();
for (Module mod: mods) { mod.display(); }

// paddle
rect (slider*30, 85, 20, 5);
rect (pivot*30, 75, 20, 5);

textSize(25);
text(counter,300,350);
// draw button
fill(150);
rect(buttonX,buttonY,buttonSize,buttonSize);
if(boolButton && mousePressed)
{
fill(200);
rect(buttonX,buttonY,buttonSize,buttonSize);
}
println(flag);
}

class Module {
int xOffset;
int rectHight;

// Contructor
Module(int xOffsetTemp, int rectHightTemp) {
xOffset = xOffsetTemp;
rectHight=rectHightTemp;
}
// Custom method for drawing the object
void display() {
fill(255);
rect(xOffset, 100, 20, rectHight);
}
}

// button
void mouseReleased() {
if(boolButton)
{

if(!flag){ if(slider<moduleSize+1) slider++; }
if(flag){
slider--;
if(slider<pivot){
flag=false;
pivot++;
slider=pivot;
}
}
}
if(slider==pivot-1 &&
mods[slider-1].rectHight<mods[pivot-1].rectHight){
flag=false;
slider=pivot;
}

}

void mousePressed() {
if(boolButton)
{
counter++;
if(slider>=moduleSize+1) slider=moduleSize+1;
else{
if(mods[slider-1].rectHight < mods[pivot-1].rectHight)
{ flag=true;
vTemp= mods[slider-1].rectHight;
mods[slider-1].rectHight=mods[slider-2].rectHight;
mods[slider-2].rectHight=vTemp; }
}
}
}

void buttonUpdate() {
if ( overButton(buttonX, buttonY, buttonSize, buttonSize) ) {
boolButton = true;
} else {
boolButton = false;
}
}
boolean overButton(int x, int y, int width, int height) {
if (mouseX >= x && mouseX <= x+width &&
mouseY >= y && mouseY <= y+height) {
return true;
} else {
return false;
}
}


Если после каждого перебора сохранять координаты опорного элемента в доп. массиве pivotsArr, то по достижении опорным элементом правого края мы получим массив, отсортированный по уровням/ступеням. Элементы на каждом следующем уровне будут больше элементов предыдущего уровня. Границы уровней будут содержаться в массиве pivotsArr
При каждом нажатии на кнопку будем выводить массив pivotsArr в консоль

for(int i=0;i<pivotsArr.length;i++){
        print(" ");
                 print(pivotsArr[i]);  
                               print(" ");   }

Добавим рандомную функцию randFoo() в конец программы

→ Проверить здесь
Листинг
int[] pivotsArr;

ArrayList listRand;
int newRand;

boolean flag;

int counter;
int moduleSize = 15;
int pivot = 1;
int slider=2;

int vTemp;
//button
int buttonX=25, buttonY=325;
int buttonSize = 50;
boolean boolButton = false;

int count;
Module[] mods;

void setup() {
size(500, 400);
listRand = new ArrayList(10);
pivotsArr=new int[0];
mods = new Module[moduleSize];

mods[0] = new Module(1*30, randFoo()*10 );
mods[1] = new Module(2*30, randFoo()*10 );
mods[2] = new Module(3*30, randFoo()*10 );
mods[3] = new Module(4*30, randFoo()*10 );
mods[4] = new Module(5*30, randFoo()*10 );
mods[5] = new Module(6*30, randFoo()*10 );
mods[6] = new Module(7*30, randFoo()*10 );
mods[7] = new Module(8*30, randFoo()*10 );
mods[8] = new Module(9*30, randFoo()*10 );
mods[9] = new Module(10*30, randFoo()*10 );
mods[10] = new Module(11*30, randFoo()*10 );
mods[11] = new Module(12*30, randFoo()*10 );
mods[12] = new Module(13*30, randFoo()*10 );
mods[13] = new Module(14*30, randFoo()*10 );
mods[14] = new Module(15*30, randFoo()*10 );
}

void draw() {
background(50);
buttonUpdate();
for (Module mod: mods) { mod.display(); }

// paddle
rect (slider*30, 85, 20, 5);
rect (pivot*30, 75, 20, 5);

textSize(25);
text(counter,300,350);
// draw button
fill(150);
rect(buttonX,buttonY,buttonSize,buttonSize);
if(boolButton && mousePressed)
{
fill(200);
rect(buttonX,buttonY,buttonSize,buttonSize);
}
// println(flag);
}

class Module {
int xOffset;
int rectHight;

// Contructor
Module(int xOffsetTemp, int rectHightTemp) {
xOffset = xOffsetTemp;
rectHight=rectHightTemp;
}
// Custom method for drawing the object
void display() {
fill(255);
rect(xOffset, 100, 20, rectHight);
}
}

// button
void mouseReleased() {
if(boolButton)
{

if(!flag){ if(slider<moduleSize+1) slider++; }
if(flag){
slider--;
if(slider<pivot){
flag=false;
pivot++;
slider=pivot;
}
}

if(slider==pivot-1 &&
mods[slider-1].rectHight<mods[pivot-1].rectHight){
flag=false;
slider=pivot;
}
}// button
}

void mousePressed() {
if(boolButton)
{
counter++;
for(int i=0;i<pivotsArr.length;i++){
print(" ");
print(pivotsArr[i]);
print(" ");}
println();
if(slider>=moduleSize+1) {
//pivotsArr.append(pivot);
pivotsArr=append(pivotsArr,pivot);
pivot++; slider=pivot;}
else{
if(mods[slider-1].rectHight < mods[pivot-1].rectHight)
{ flag=true;
vTemp= mods[slider-1].rectHight;
mods[slider-1].rectHight=mods[slider-2].rectHight;
mods[slider-2].rectHight=vTemp; }
}
} //button
}

void buttonUpdate() {
if ( overButton(buttonX, buttonY, buttonSize, buttonSize) ) {
boolButton = true;
} else {
boolButton = false;
}
}
boolean overButton(int x, int y, int width, int height) {
if (mouseX >= x && mouseX <= x+width &&
mouseY >= y && mouseY <= y+height) {
return true;
} else {
return false;
}
}

int randFoo(){
newRand = int(random(1,16));
if(!listRand.contains(newRand) ) listRand.add(newRand );
else newRand=randFoo();
return newRand;
}


Теперь надо отсортировать элементы каждого уровня по отдельности (остаётся только добавить условие завершения цикла)

→ Проверить здесь
Листинг
int[] pivotsArr;

ArrayList listRand;
int newRand;

boolean flag;

int counter;
int moduleSize = 15;
int limiterR = moduleSize+1;
int pivot = 1;
int slider=2;

int vTemp;
//button
int buttonX=25, buttonY=325;
int buttonSize = 50;
boolean boolButton = false;

int count;
Module[] mods;

void setup() {
size(510, 400);
listRand = new ArrayList(10);
pivotsArr = new int[0];
mods = new Module[moduleSize];

mods[0] = new Module(1*30, randFoo()*10 );
mods[1] = new Module(2*30, randFoo()*10 );
mods[2] = new Module(3*30, randFoo()*10 );
mods[3] = new Module(4*30, randFoo()*10 );
mods[4] = new Module(5*30, randFoo()*10 );
mods[5] = new Module(6*30, randFoo()*10 );
mods[6] = new Module(7*30, randFoo()*10 );
mods[7] = new Module(8*30, randFoo()*10 );
mods[8] = new Module(9*30, randFoo()*10 );
mods[9] = new Module(10*30, randFoo()*10 );
mods[10] = new Module(11*30, randFoo()*10 );
mods[11] = new Module(12*30, randFoo()*10 );
mods[12] = new Module(13*30, randFoo()*10 );
mods[13] = new Module(14*30, randFoo()*10 );
mods[14] = new Module(15*30, randFoo()*10 );
}

void draw() {
background(50);
buttonUpdate();
for (Module mod: mods) { mod.display(); }

// paddle
rect (slider*30, 85, 20, 5);
rect (pivot*30, 75, 20, 5);
rect (limiterR*30, 65, 20, 5);

textSize(25);
text(counter,300,350);
// draw button
fill(150);
rect(buttonX,buttonY,buttonSize,buttonSize);
if(boolButton && mousePressed)
{
fill(200);
rect(buttonX,buttonY,buttonSize,buttonSize);
}
// println(flag);
}

class Module {
int xOffset;
int rectHight;

// Contructor
Module(int xOffsetTemp, int rectHightTemp) {
xOffset = xOffsetTemp;
rectHight=rectHightTemp;
}
// Custom method for drawing the object
void display() {
fill(255);
rect(xOffset, 100, 20, rectHight);
}
}

// button
void mouseReleased() {
if(boolButton)
{

if(!flag){ if(slider<moduleSize+1) slider++; }
if(flag){
slider--;
if(slider<pivot){
flag=false;
pivot++;
slider=pivot;
}
}

if(slider==pivot-1 &&
mods[slider-1].rectHight<mods[pivot-1].rectHight){
flag=false;
slider=pivot;
}
}// button
}

void mousePressed() {
if(boolButton)
{
counter++;
for(int i=0;i<pivotsArr.length;i++){
print(" ");
print(pivotsArr[i]);
print(" "); }
println();
if(pivot==limiterR)
{
//limiterR= pivotsArr.pop();
limiterR=pivotsArr[pivotsArr.length-1];
pivotsArr=shorten(pivotsArr);
// if(pivotsArr.size()!=0)pivot=pivotsArr.get(pivotsArr.size()-1);
if(pivotsArr.length!=0) pivot=pivotsArr[pivotsArr.length-1];
else pivot=1;
slider=pivot;
}

if(slider>=limiterR) {
if(pivotsArr.length==0) pivotsArr=append(pivotsArr,pivot);
else if( pivot!=pivotsArr[pivotsArr.length-1] ) pivotsArr=append(pivotsArr,pivot);
// pivotsArr.append(pivot);
pivot++; slider=pivot;}
else{
if(mods[slider-1].rectHight < mods[pivot-1].rectHight)
{ flag=true;
vTemp= mods[slider-1].rectHight;
mods[slider-1].rectHight=mods[slider-2].rectHight;
mods[slider-2].rectHight=vTemp; }
}
} //button
}

void buttonUpdate() {
if ( overButton(buttonX, buttonY, buttonSize, buttonSize) ) {
boolButton = true;
} else {
boolButton = false;
}
}
boolean overButton(int x, int y, int width, int height) {
if (mouseX >= x && mouseX <= x+width &&
mouseY >= y && mouseY <= y+height) {
return true;
} else {
return false;
}
}
int randFoo(){
newRand = int(random(1,16));
if(!listRand.contains(newRand) ) listRand.add(newRand );
else newRand=randFoo();
return newRand;
}


Такая сортировка реализует распределение числовых данных по уровням
Каждый уровень характеризуется тем, что максимальное число, принадлежащее какому-либо уровню меньше минимального числа, принадлежащего следующего за ним уровня

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


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

slider=slider+2;

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

→ Проверить здесь
Листинг
boolean flag;

int counter;
int moduleSize = 10;
int limiter = moduleSize;
int slider=1;
int vTemp;

//button
int buttonX=25, buttonY=325;
int buttonSize = 50;
boolean boolButton = false;

int count;
Module[] mods;

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

}

void draw() {
background(50);
buttonUpdate();
for (Module mod: mods) { mod.display(); }

// paddle
rect (slider*30, 85, 20, 5);
rect (limiter*30, 75, 20, 5);

textSize(25);
text(counter,300,300);
// draw button
fill(150);
rect(buttonX,buttonY,buttonSize,buttonSize);
if(boolButton && mousePressed)
{
fill(200);
rect(buttonX,buttonY,buttonSize,buttonSize);
}
println(flag);
}

class Module {
int xOffset;
int rectHight;

// Contructor
Module(int xOffsetTemp, int rectHightTemp) {
xOffset = xOffsetTemp;
rectHight=rectHightTemp;
}
// Custom method for drawing the object
void display() {
fill(255);
rect(xOffset, 100, 20, rectHight);
}
}

// button
void mouseReleased() {
if(boolButton)
{
slider=slider+2;
if(flag==false && slider>=limiter)
{ flag=true; limiter--; slider=2; }
if(flag==true && slider>=limiter)
{ flag=false; limiter++; slider=1; }
}
}

void mousePressed() {
if(boolButton)
{
counter++;

if(mods[slider].rectHight < mods[slider-1].rectHight)
{
vTemp= mods[slider-1].rectHight;
mods[slider-1].rectHight=mods[slider].rectHight;
mods[slider].rectHight=vTemp;
}
}
}

void buttonUpdate() {
if ( overButton(buttonX, buttonY, buttonSize, buttonSize) ) {
boolButton = true;
} else {
boolButton = false;
}
}
boolean overButton(int x, int y, int width, int height) {
if (mouseX >= x && mouseX <= x+width &&
mouseY >= y && mouseY <= y+height) {
return true;
} else {
return false;
}
}


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


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

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


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

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


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

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


→ Проверить здесь
Листинг
int counter;
int moduleSize = 10;
// limiter
int limiter = moduleSize;
int limiterStore = moduleSize;

int slider=1;
int vTemp;
//button
int buttonX=25, buttonY=325;
int buttonSize = 50;
boolean boolButton = false;
int count;

Module[] mods;

void setup() {
size(400, 400);
mods = new Module[moduleSize];
mods[0] = new Module(1*30, 100);
mods[1] = new Module(2*30, 50);
mods[2] = new Module(3*30, 30);
mods[3] = new Module(4*30, 60);
mods[4] = new Module(5*30, 20);
mods[5] = new Module(6*30, 40);
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, 10);
}

void draw() {
background(50);
buttonUpdate();
for (Module mod: mods) { mod.display(); }
// paddle
rect (slider*30, 85, 20, 5);
rect (limiter*30, 75, 20, 5);

textSize(25);
text(counter,300,350);
// draw button
fill(150);
rect(buttonX,buttonY,buttonSize,buttonSize);
if(boolButton && mousePressed)
{
fill(200);
rect(buttonX,buttonY,buttonSize,buttonSize);
}
}

class Module {
int xOffset;
int rectHight;
// Contructor
Module(int xOffsetTemp, int rectHightTemp) {
xOffset = xOffsetTemp;
rectHight=rectHightTemp;
}
// Custom method for drawing the object
void display() {
fill(255);
rect(xOffset, 100, 20, rectHight);
}
}

// button
void mousePressed() {
if(boolButton)
{
counter++;
if(limiter!=moduleSize)
{
limiter++;
slider++;
}
if(slider==limiter)
{
slider=1;
limiter=1;
}
}
}

void mouseReleased() {
if(boolButton)
{
if(mods[slider-1].rectHight > mods[limiter-1].rectHight)
{
vTemp= mods[slider-1].rectHight;
mods[slider-1].rectHight=mods[limiter-1].rectHight;
mods[limiter-1].rectHight=vTemp;
}
if(limiter==moduleSize)
{
limiter = limiterStore-1;
limiterStore = limiter;
slider=1;
}
}
}

void buttonUpdate() {
if ( overButton(buttonX, buttonY, buttonSize, buttonSize) ) {
boolButton = true;
} else {
boolButton = false;
}
}
boolean overButton(int x, int y, int width, int height) {
if (mouseX >= x && mouseX <= x+width &&
mouseY >= y && mouseY <= y+height) {
return true;
} else {
return false;
}
}


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




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

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



→ Проверить здесь
Листинг
boolean flag;

int counter;
int moduleSize = 10;
int limiterL = 1;
int limiterR = moduleSize;
int slider=1;

int vTemp;
//button
int buttonX=25, buttonY=325;
int buttonSize = 50;
boolean boolButton = false;

int count;
Module[] mods;

void setup() {
size(400, 400);
mods = new Module[moduleSize];
mods[0] = new Module(1*30, 100);
mods[1] = new Module(2*30, 50);
mods[2] = new Module(3*30, 30);
mods[3] = new Module(4*30, 60);
mods[4] = new Module(5*30, 20);
mods[5] = new Module(6*30, 40);
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, 10);
}

void draw() {
background(50);
buttonUpdate();
for (Module mod: mods) { mod.display(); }

// paddle
rect (slider*30, 85, 20, 5);
rect (limiterR*30, 75, 20, 5);
rect (limiterL*30, 75, 20, 5);

textSize(25);
text(counter,300,350);
// draw button
fill(150);
rect(buttonX,buttonY,buttonSize,buttonSize);
if(boolButton && mousePressed)
{
fill(200);
rect(buttonX,buttonY,buttonSize,buttonSize);
}
println(flag);
}

class Module {
int xOffset;
int rectHight;

// Contructor
Module(int xOffsetTemp, int rectHightTemp) {
xOffset = xOffsetTemp;
rectHight=rectHightTemp;
}
// Custom method for drawing the object
void display() {
fill(255);
rect(xOffset, 100, 20, rectHight);
}
}

// button
void mouseReleased() {
if(boolButton)
{
if(!flag)
{
slider++;
if(slider==limiterR)
{
flag=true;
limiterR--;
if(limiterR<=limiterL+1) limiterR=limiterL+1;
}
}
if(flag)
{
slider--;
if(slider==limiterL)
{
flag=false;
limiterL++;
if(limiterL>=limiterR-1) limiterL=limiterR-1;
}
}
}
}

void mousePressed() {
if(boolButton)
{
counter++;
if(mods[slider].rectHight < mods[slider-1].rectHight)
{
vTemp= mods[slider-1].rectHight;
mods[slider-1].rectHight=mods[slider].rectHight;
mods[slider].rectHight=vTemp;
}
}
}

void buttonUpdate() {
if ( overButton(buttonX, buttonY, buttonSize, buttonSize) ) {
boolButton = true;
} else {
boolButton = false;
}
}
boolean overButton(int x, int y, int width, int height) {
if (mouseX >= x && mouseX <= x+width &&
mouseY >= y && mouseY <= y+height) {
return true;
} else {
return false;
}
}


Шейкерная сортировка выбором
Добавим к пузырьковой сортировке с правым ограничителем левый ограничитель. При каждом сдвиге ползунка вправо проверяем (меняем местами), что больше — текущий элемент или ограничитель

if(mods[slider-1].rectHight<mods[limiterL-1].rectHight){
    vTemp= mods[slider-1].rectHight;
     mods[slider-1].rectHight=mods[limiterL-1].rectHight;
     mods[limiterL-1].rectHight=vTemp;
  }

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

if(slider>=limiterR){ 
     limiterL++; 
     slider=limiterL;
     limiterR--;
    }


→ Проверить здесь
Листинг
boolean flag;

int counter;
int moduleSize = 10;
int limiterL = 1;
int limiterR = moduleSize;
int slider=1;

int vTemp;
//button
int buttonX=25, buttonY=325;
int buttonSize = 50;
boolean boolButton = false;

int count;
Module[] mods;

void setup() {
size(400, 400);
mods = new Module[moduleSize];
mods[0] = new Module(1*30, 70);
mods[1] = new Module(2*30, 50);
mods[2] = new Module(3*30, 30);
mods[3] = new Module(4*30, 60);
mods[4] = new Module(5*30, 20);
mods[5] = new Module(6*30, 10);
mods[6] = new Module(7*30, 80);
mods[7] = new Module(8*30, 100);
mods[8] = new Module(9*30, 90);
mods[9] = new Module(10*30, 40);
}

void draw() {
background(50);
buttonUpdate();
for (Module mod: mods) { mod.display(); }

// paddle
rect (slider*30, 85, 20, 5);
rect (limiterR*30, 75, 20, 5);
rect (limiterL*30, 75, 20, 5);

textSize(25);
text(counter,300,350);
// draw button
fill(150);
rect(buttonX,buttonY,buttonSize,buttonSize);
if(boolButton && mousePressed)
{
fill(200);
rect(buttonX,buttonY,buttonSize,buttonSize);
}
println(flag);
}

class Module {
int xOffset;
int rectHight;

// Contructor
Module(int xOffsetTemp, int rectHightTemp) {
xOffset = xOffsetTemp;
rectHight=rectHightTemp;
}
// Custom method for drawing the object
void display() {
fill(255);
rect(xOffset, 100, 20, rectHight);
}
}

// button
void mouseReleased() {
if(boolButton)
{
if(flag) {limiterR=limiterL; limiterL=limiterR;}
else
{
slider++;
if(slider>=limiterR)
{
limiterL++;
slider=limiterL;
limiterR--;
}
}
}
} //end

void mousePressed() {
if(boolButton)
{
counter++;
if(limiterR<limiterL) {flag=true;}

if(mods[slider].rectHight < mods[slider-1].rectHight)
{
vTemp= mods[slider-1].rectHight;
mods[slider-1].rectHight=mods[slider].rectHight;
mods[slider].rectHight=vTemp;
}
}

if(mods[slider-1].rectHight<mods[limiterL-1].rectHight){
vTemp= mods[slider-1].rectHight;
mods[slider-1].rectHight=mods[limiterL-1].rectHight;
mods[limiterL-1].rectHight=vTemp;
}
}

void buttonUpdate() {
if ( overButton(buttonX, buttonY, buttonSize, buttonSize) ) {
boolButton = true;
} else {
boolButton = false;
}
}
boolean overButton(int x, int y, int width, int height) {
if (mouseX >= x && mouseX <= x+width &&
mouseY >= y && mouseY <= y+height) {
return true;
} else {
return false;
}
}


Еще один способ сортировки обменами, использующий двойной цикл, приведён в третьем томе монографии Дональда Кнута «Искусство программирования», о чём можно прочитать в статье «Is this the simplest (and most surprising) sorting algorithm ever?», перевод которой есть на Хабре в блоге компании Спортмастер.
В псевдокоде этот алгоритм можно представить так
for i = 1 to n do
for j = 1 to n do
if A[i] < A[j] then
swap A[i] and A[j]

Здесь в двойном цикле перебираются и меняются местами элементы с индексами i и j.
На языке Processing этот алгоритм можно представлен так:
Алгоритм
int counter;
int moduleSize = 10;
int slider_i = 1;
int slider_j=1;

int vTemp;
//button
int buttonX=25, buttonY=325;
int buttonSize = 50;
boolean boolButton = false;

int count;
Module[] mods;

void setup() {
size(400, 400);
mods = new Module[moduleSize];
mods[0] = new Module(1*30, 100);
mods[1] = new Module(2*30, 50);
mods[2] = new Module(3*30, 30);
mods[3] = new Module(4*30, 60);
mods[4] = new Module(5*30, 20);
mods[5] = new Module(6*30, 40);
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, 10);
}

void draw() {
background(50);
buttonUpdate();
for (Module mod: mods) { mod.display(); }

// paddle
rect (slider_i*30, 85, 20, 5);
rect (slider_j*30, 75, 20, 5);

textSize(25);
text(counter,300,350);
// draw button
fill(150);
rect(buttonX,buttonY,buttonSize,buttonSize);
if(boolButton && mousePressed)
{
fill(200);
rect(buttonX,buttonY,buttonSize,buttonSize);
}
}
class Module {
int xOffset;
int rectHight;

// Contructor
Module(int xOffsetTemp, int rectHightTemp) {
xOffset = xOffsetTemp;
rectHight=rectHightTemp;
}
// Custom method for drawing the object
void display() {
fill(255);
rect(xOffset, 100, 20, rectHight);
}
}

// button
void mouseReleased() {
if(boolButton)
{
slider_j++;
if(slider_j>moduleSize)
{
slider_i++;
slider_j=1;
}
}
}

void mousePressed() {
if(boolButton)
{
counter++;
if(mods[slider_i-1].rectHight < mods[slider_j-1].rectHight)
{
vTemp= mods[slider_j-1].rectHight;
mods[slider_j-1].rectHight=mods[slider_i-1].rectHight;
mods[slider_i-1].rectHight=vTemp;
}
}
}

void buttonUpdate() {
if ( overButton(buttonX, buttonY, buttonSize, buttonSize) ) {
boolButton = true;
} else {
boolButton = false;
}
}
boolean overButton(int x, int y, int width, int height) {
if (mouseX >= x && mouseX <= x+width &&
mouseY >= y && mouseY <= y+height) {
return true;
} else {
return false;
}
}

Проверить здесь.

P.S.
Большая коллекция сортировок, в том числе сортировок обменами, собрана у пользователя valemak

Вот тут описывается приложение, которое делает изучение алгоритмов и структур данных гораздо интереснее.

Еще одна визуализация ряда алгоритмов и структур данных.

В этой статье упоминается ещё один сайт, на котором можно посмотреть, как сортируются данные разными алгоритмами.

В этой статье даётся оценка сложности пузырьковой сортировки.
Ещё про оценку сложности
здесь,
здесь.
Теги:
Хабы:
Всего голосов 22: ↑14 и ↓8+6
Комментарии7

Публикации

Истории

Работа

Java разработчик
394 вакансии
React разработчик
82 вакансии

Ближайшие события

27 августа – 7 октября
Премия digital-кейсов «Проксима»
МоскваОнлайн
28 сентября – 5 октября
О! Хакатон
Онлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн
10 – 11 октября
HR IT & Team Lead конференция «Битва за IT-таланты»
МоскваОнлайн
25 октября
Конференция по росту продуктов EGC’24
МоскваОнлайн
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн