Сортировка Шейкерная-Перемешиванием (Shaker,Cocktail sort)
defaultValue- Подробности
- Категория: Сортировка и поиск
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 + " "); // вывод массива на экран
}
}
При написании статьи были использованы открытые источники сети интернет :
defaultValue

