Сортировка Шейкерная-Перемешиванием (Shaker,Cocktail sort)

Cортировка перемешиванием, двунаправленная пузырьковая сортировка, шейкерная сортировка, пульсирующая сортировка (ripple sort), трансфертная сортировка (shuttle sort), и даже сортировка «счастливый час» (happy hour sort). Второй вариант (двунаправленная пузырьковая сортировка) наиболее точно описывает процесс работы алгоритма. Здесь, в его название, довольно-таки удачно включен термин «пузырьковая». Это действительно альтернативная версия известного метода, модификации в котором заключаются, по большей части, в реализации, упомянутой в названии, двунаправленности: алгоритм перемещается, ни как в обменной (пузырьковой) сортировке – строго снизу вверх (слева направо), а сначала снизу вверх, потом сверху вниз.

Образно алгоритм можно описать так: на каждом шаге основного цикла рассматривается массив a[Left]?a[Right], после выполнения двух внутренних циклов минимальный и максимальный элемент в исходном массиве перетекают к краям, минимальный в — a[Left], максимальный — в a[Right]. Пусть максимальный элемент имеет индекс k, тогда массив можно изобразить так: a[Left],a[1],..,a[k-1],A[k],a[k+1],..,a[Right];После сравнения A[k] с a[k+1] значение A[k] перейдет в k+1-ую ячейку,после сравнения k+1-й c k+2-й – в k+2-eю,и так далее,пока он не сместится в крайне правое положение с индексом Right. Аналогично для минимального. После выполнения цикла по всем подмассивам он отсортируется.

 

 

Худшее время

О(n2) сравнений, обменов



Лучшее время

O(n) сравнений, O(1) обмен

Среднее время

О(n2) сравнений, обменов

Реализация алгоритма на различных языках программирования:

 

Pascal

 

k:= 25; {Индекс последнего изменения}
s:= 1; {Первый элемент массива}
e:= 25; {Последний элемент массива}
while e > s do
begin
   for i:= e downto s+1 do if Arr[i] < Arr[i-1] then
   begin
      tmp := Arr[i];
      Arr[i] := Arr[i-1];
      Arr[i-1] := tmp;
      k := i;
   end;
   s:=k;
   for i:= s to e-1 do if Arr[i]>Arr[i+1] then
   begin
      tmp := Arr[i];
      Arr[i] := Arr[i+1];
      Arr[i+1] := tmp;
      k := i;
   end;
   e:=k;
end;

 

 

 

 

C++

 

#include "stdafx.h"
#include <iostream>
using namespace std;
//функция обмена
void Swap(int *Mas, int i)
{
int temp;
temp=Mas[i];
Mas[i]=Mas[i-1];
Mas[i-1]=temp;
}
//функция шейкерной сортировки
void ShakerSort(int *Mas, int Start, int N)
{
int Left, Right, i;
Left=Start;
Right=N-1;
while (Left<=Right)
{
for (i=Right; i>=Left; i--)
if (Mas[i-1]>Mas[i]) Swap(Mas, i);
Left++;
for (i=Left; i<=Right; i++)
if (Mas[i-1]>Mas[i]) Swap(Mas, i);
Right--;
}
}
//главная функция
void main()
{
setlocale(LC_ALL,"Rus");
int n, k;
cout<<"Размер массива > "; cin>>n;
int *A=new int[n];
for (k=0; k<n; k++)
{ cout<<k+1<<" элемент > "; cin>>A[k]; }
ShakerSort(A, 1, n);
cout<<"Результирующий массив: ";
for (k=0; k<n; k++)cout<<" "<<A[k];
system("pause>>void");
}

 

 

C#

 

#include "stdafx.h"
#include <iostream>
using namespace std;
//функция обмена
void Swap(int *Mas, int i)
{
int temp;
temp=Mas[i];
Mas[i]=Mas[i-1];
Mas[i-1]=temp;
}
//функция шейкерной сортировки
void ShakerSort(int *Mas, int Start, int N)
{
int Left, Right, i;
Left=Start;
Right=N-1;
while (Left<=Right)
{
for (i=Right; i>=Left; i--)
if (Mas[i-1]>Mas[i]) Swap(Mas, i);
Left++;
for (i=Left; i<=Right; i++)
if (Mas[i-1]>Mas[i]) Swap(Mas, i);
Right--;
}
}
//главная функция
void main()
{
setlocale(LC_ALL,"Rus");
int n, k;
cout<<"Размер массива > "; cin>>n;
int *A=new int[n];
for (k=0; k<n; k++)
{ cout<<k+1<<" элемент > "; cin>>A[k]; }
ShakerSort(A, 1, n);
cout<<"Результирующий массив: ";
for (k=0; k<n; k++)cout<<" "<<A[k];
system("pause>>void");
}

 

 

Fortran

 

program cocktailsort
 
integer A(17)
integer i,t
logical::sort=.true.
open(1,file='massiv.txt',status='old')
	read(1,*) A
		do i=1,17
			write(*,*) A(i)
		enddo
do while(sort)
sort=.false.
	do i=1, 16
		if(A(i)>A(i+1)) then
			t=A(i)
			A(i)=A(i+1)
			A(i+1)=t
			sort=.true.
		endif
	enddo
sort=.false.
 
	do i=16, 1, -1
		if(A(i)>A(i+1)) then
			t=A(i)
			A(i)=A(i+1)
			A(i+1)=t
			sort=.true.
		endif
	enddo
enddo
write(*,*) '---'
do i=1,17
	write(*,*) A(i)
enddo
pause
end

 

 

PHP

 

<?php
function swap(&$a, &$b) {
    $a = $a ^ $b;
    $b = $a ^ $b;
    $a = $a ^ $b;
}
 
 
 
function sheker($mas, $n)
{
        $last = $n-1; $left = 1; $right = $n-1;
 
        do
        {
                for($j = $right; $j >= $left; $j--)
                {
                        if($mas[$j-1] > $mas[$j])
                        {
                                swap($mas[$j-1], $mas[$j]);
                                $last = $j;
                        }
                }
 
                $left = $last + 1;
 
                for($j = $left; $j <= $right; $j++)
                {
                        if($mas[$j-1] > $mas[$j])
                        {
                                swap($mas[$j-1], $mas[$j]);
                                $last = $j;
                        }
                }
 
                $right = $last-1;
 
        } while($left < $right);
}
//(sheker($array,count($array)));
?>

 

 

Perl

 

while ( $left < $right ) {
	for ( my $j = $right; $j >= $left; $j-- ) {
		if ( $array_for_sort[$j-1] > $array_for_sort[$j] ) {
			( $array_for_sort[$j-1],$array_for_sort[$j]) = ( $array_for_sort[$j],$array_for_sort[$j-1] );
			$last = $j;
		}
	}
	$left = $last + 1;
	for( my $j = $left; $j <= $right; $j++ ) {
		if ( $array_for_sort[$j-1] > $array_for_sort[$j] ) {
			( $array_for_sort[$j-1],$array_for_sort[$j] ) = ( $array_for_sort[$j],$array_for_sort[$j-1] );
			$last = $j;
		}
	}
	$right = $last - 1;
}

 

 

С++

#include <vcl.h>
#include <conio.h>
#include <iostream.h>
#pragma hdrstop
#pragma argsused
 
// Шейкер-сортировка
 
int main(int argc, TCHAR* argv[])
{
    const int Count = 10;
    int TestArr[Count] = {3, 1, 5, 8, 1, 0, 6, 4, 6, 7};
 
    ShakerSort(TestArr,0,Count);
    ArrayOutput(TestArr,0,Count);
 
    return 0;
}
 
//Поменять местами 2 элемента
void Swap(int* e1, int* e2)
{
    *e1 ^= *e2;
    *e2 ^= *e1;
    *e1 ^= *e2;
}
 
void ShakerSort(int Arr[], int Start, int N)
{
    int Left, Right; //границы сортировки
 
    Left = Start;
    Right = N - 1;
 
 
    do
    {
        //Сдвигаем к началу массива "легкие элементы"
        for (int i = Right; i > Left; i--)
        {
            if (Arr[i] < Arr[i - 1])
            {
                Swap(&Arr[i], &Arr[i-1]);
            }
        }
 
        Left = Left + 1;
 
        //Сдвигаем к концу массива "тяжелые элементы"
        for (int i = Left; i < Right; i++)
        {
            if (Arr[i] > Arr[i + 1])
            {
                Swap(&Arr[i], &Arr[i + 1]);
            }
        }
 
        Right = Right - 1;
    }
    while (Left <= Right);
}
 
//Вывод элементов массива на консоль
void ArrayOutput(int* Arr, int Start, int N)
{
    for (int i = Start; i < N; i++)
    {
        cout << Arr[i] << '\n';
    }
    getch();
}

 

 С#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace SortLab
{
    class Program
    {
 
        static void Main()
        {
            Sort(); 
        }
 
        /*Основная программа*/
        static void Sort()
        {
 
            int[] myint = { 99,88,77,66,55,44,33,22,11,8,5,3,1};
 
            WriteArray(myint);
            ShakerSort(myint);
            WriteArray(myint);
 
            Console.ReadLine();
 
        }
        /* Шейкер-сортировка */
        static void ShakerSort(int[] myint)
        {
            int beg, end;
            int count = 0;
 
            for (int i = 0; i < myint.Length/2; i++) //можно переберать за кол-во итераций, в 2 раза меньше
            {                                        //целочисленное деление округляет в меньшую сторону
                beg = 0;
                end = myint.Length - 1;
 
                do
                {
                    count += 2;
                    /* идем спереди */
                    if (myint[beg] > myint[beg + 1]) 
                        Swap(myint,beg,beg+1);    
                    beg++;//сдвигаем позицию вперед
 
 
                    /* идем сзади */
                    if (myint[end-1] > myint[end]) 
                        Swap(myint, end - 1, end);
                    end--;//сдвигаем позицию назад
 
                }
                while (beg <= end);// условия усреднения
             }
            Console.Write("\nКоличество сравнений = {0}\n",count);
        }
 
 
        /* Поменять элементы местами */
        static void Swap(int[] myint, int i, int j)
        {
            int glass;
            glass = myint[i];
            myint[i] = myint[j];
            myint[j] = glass;
        }
 
        /*Вывести массив*/
        static void WriteArray(int[] a)
        {
            foreach (int i in a)
                Console.Write("{0}|", i);
            Console.WriteLine("\n\n\n");
        }
    }
}

 

 

 PHP

function cocktailSorting(&$a) {
	$n = count($a);
	$left = 0;
	$right = $n - 1;
	do {
		for ($i = $left; $i < $right; $i++) {
			if ($a[$i] > $a[$i + 1]) {
				list($a[$i], $a[$i + 1]) = array($a[$i + 1], $a[$i]);
			}
		}
		$right -= 1;
		for ($i = $right; $i > $left; $i--) {
			if ($a[$i] < $a[$i - 1]) {
				list($a[$i], $a[$i - 1]) = array($a[$i - 1], $a[$i]);
			}
		}
		$left += 1;
	} while ($left <= $right);
}

 

 Java

public class CocktailSort
{
 
    public static void main(String[] args)
    {
        int[] array = {3, 1, 5, 8, 1, 0, 6, 4, 6, 7};
        int left = 0; // левая граница
        int right = array.length - 1; // правая граница
 
        do
        {
            //Сдвигаем к концу массива "тяжелые элементы"
            for (int i = left; i < right; i++)
            {
                if(array[i] > array[i+1])
                {
                    array[i] ^= array[i+1];
                    array[i+1] ^= array[i];
                    array[i] ^= array[i+1];
                }
            }
            right--; // уменьшаем правую границу
            //Сдвигаем к началу массива "легкие элементы"
            for (int i = right; i > left ; i--)
            {
                if(array[i] < array[i-1])
                {
                    array[i] ^= array[i-1];
                    array[i-1] ^= array[i];
                    array[i] ^= array[i-1];
                }
            }
            left++; // увеличиваем левую границу
        } while (left <= right);
 
        for (int i : array) System.out.print(i + " "); // вывод массива на экран
    }
}

 

При написании статьи были использованы открытые источники сети интернет :

Wikipedia

Kvodo

Youtube

 

 







Видеотека

-->

Яндекс.Метрика