**مرتب‌سازی کوکتلی** (به انگلیسی: Cocktail sort)، که با نام **مرتب‌سازی حبابی دوسویه**، **مرتب‌سازی تکان‌دهندهٔ کوکتلی**، **مرتب‌سازی تکان‌دهنده** (که به نوعی از مرتب‌سازی انتخابی هم اشاره می‌کند)، **مرتب‌سازی موج‌دار**، **مرتب‌سازی بی قرار**، یا **مرتب‌سازی رفت و برگشت** هم شناخته می‌شود، یک نوع الگوریتم مرتب‌سازی حبابی است که الگوریتم مرتب‌سازی پایدار است و همچنین به صورت مقایسه‌ای عمل مرتب‌سازی را انجام می‌دهد. این الگوریتم با الگوریتم مرتب‌سازی حبابی (bubble sort) که مرتب‌سازی در هر جهت لیست را مرتب می‌کند. پیاده‌سازی این الگوریتم مرتب‌سازی مشکل‌تر از الگوریتم مرتب‌سازی حبابی است.

شبه کد
------

پیاده‌سازی ساده‌ترین نوع مرتب‌سازی حبابی دوسویه بدین گونه است:

```
procedure bidirectionalbubbleSort( A : list of sortable items ) defined as:
 do
 swapped := false
 for each i in 0 to length( A ) - 2 do:
 if A[ i ]> A[ i + 1 ] then // test whether the two elements are in the wrong order
 swap( A[ i ], A[ i + 1 ] ) // let the two elements change places
 swapped := true
 end if
 end for
 if swapped = false then
 // we can exit the outer loop here if no swaps occurred.
 break do-while loop
 end if
 swapped := false
 for each i in length( A ) - 2 to 0 do:
 if A[ i ]> A[ i + 1 ] then
 swap( A[ i ], A[ i + 1 ] )
 swapped := true
 end if
 end for
 while swapped // if no elements have been swapped, then the list is sorted
end procedure

```

دراولین عبور از روی لیست به سمت راست بزرگترین عضو لیست به مکان صحیح خود منتقل می‌شود و در عبور بعدی 
از روی لیست به سمت چپ کوچکترین عنصر به جای اصلی خود در آغاز می‌رود. دومین عبور تکمیل‌کننده از روی لیست
دومین عنصر بزرگ و دومین عنصر کوچک را به جای خود می‌برد و به همین ترتیب. بعد از گذشت i عبور از روی 
لیست i امین عنصر اول و i امین عنصر درون لیست در جای صحیح خود قرار دارند و نیازی به چک کردن ندارند.
با کوچک کردن قسمتی از لیست که در قسمت مرتب می‌شود تعداد دستورها برای انجام الگوریتم نصف می‌شود.

```
procedure bidirectionalbubbleSort ( A : list of sortable items ) defined as:
 // `begin` and `end` marks the first and last index to check
 begin := -1
 end := length( A ) - 2
 do
 swapped := false
 // increases `begin` because the elements before `begin` are in correct order
 begin := begin + 1
 for each i in begin to end do:
 if A[ i ]> A[ i + 1 ] then
 swap( A[ i ], A[ i + 1 ] )
 swapped := true
 end if
 end for
 if swapped = false then
 break do-while loop
 end if
 swapped := false
 // decreases `end` because the elements after `end` are in correct order
 end := end - 1
 for each i in end to begin do:
 if A[ i ]> A[ i + 1 ] then
 swap( A[ i ], A[ i + 1 ] )
 swapped := true
 end if
 end for
 while swapped
end procedure

```

تفاوت‌های مرتب‌سازی حبابی دوسویه با مرتب‌سازی حبابی:
تفاوت این دو در این است که به جای اینکه در هر مرحله از ته تا سر لیست را برویم، به‌طور به‌طور تناوبی
از ته به سر و بعد از سر به ته لیست حرکت می‌کنیم. این الگوریتم کمی بهتر از مرتب‌سازی حبابی استاندارد
عمل می‌کند. دلیل این هم این است که الگوریتم مرتب‌سازی حبابی فقط در طول لیست در یک جهت حرکت می‌کند
بنابراین فقط می‌تواند عناصر در یک خانه در هر تکرار به جای اصلی خود نزدیک کند. 
به عنوان شاهد برای این قسمت می‌توان لیست زیر را در نظر گرفت 
(1 و 5 و 4 و 3 و 2) که با استفاده از الگوریتم مرتب‌سازی حبابی دوسویه یک مرحله اجرا دارد ولی انجام همین
کار با استفاده از الگوریتم مرتب‌سازی حبابی ۴ مرحله به طول می‌انجامد. نوعا زمان اجرای الگوریتم
مرتب‌سازی حبابی نسبت به الگوریتم مربت سازی حبابی دوسویه کمتر از دو برابر است. یک بهینه‌سازی دیگر
می‌توان انجام داد این است که می‌توان انجام داد این است که الگوریتم به نوعی مکان تقریبی آخرین
جابه جایی انجام شده را به یاد سپارد؛ و در تکرار بعد دیگر خارج از این بازه انجام نمی‌شود و
الگوریتم مسیر کوتاه تری دارد. از آنجا که مرتب‌سازی حبابی دوسویه در هر دو طرف حرکت می‌کند.
محدودهٔ جابه جایی ممکن که برای جابه جایی نیاز است که شرط جابه جایی چک شود، در هر مرحله گذر
کاهش می‌یابد که نتیجه کاهش یافتن کل زمان اجرای الگوریتم است.

تحلیل پیچیدگی الگوریتم
----------------------

مرتبهٔ پیچیدگی مرتب‌سازی حبابی دو سویه از (O(n2است؛ و این مرتبه پیچیدگی هم برای بدترین حالت
و هم برای حالت میانگین است، ولی در بهترین حالت زمانی که لیست ورودی از قبل مرتب است مرتبه پیچیدگی
از (O(n خواهد بود. به عنوان مثال اگر هر عنصر در حالت اولیه در نسبت به جای صحیح خود k خانه فاصله
داشته باشد مرتبه پیچیدگی الگوریتم (O(k \* n.

به‌زبان جاوا
------------

```
class BidirBubbleSortAlgorithm extends SortAlgorithm {
 void sort(int a[]) throws Exception {
 int j;
 int limit = a.length;
 int st = -1;
 while (st <limit) {
 boolean flipped = false;
 st++;
 limit--;
 for (j = st; j <limit; j++) {
 if (stopRequested) {
 return;
 }
 if (a[j]> a[j + 1]) {
 int T = a[j];
 a[j] = a[j + 1];
 a[j + 1] = T;
 flipped = true;
 pause(st, limit);
 }
 }
 if (!flipped) {
 return;
 }
 for (j = limit; --j>= st;) {
 if (stopRequested) {
 return;
 }
 if (a[j]> a[j + 1]) {
 int T = a[j];
 a[j] = a[j + 1];
 a[j + 1] = T;
 flipped = true;
 pause(st, limit);
 }
 }
 if (!flipped) {
 return;
 }
 }
 pause(st, limit);
 }
}

```

پانویس
------

1. ↑  Martin Duhl: Die schrittweise Entwicklung und Beschreibung einer Shuffle-Sort-Array Schaltung in HYPERKARL aus der Algorithmischen Darstellung des BUBBLE-SORT-ALGORITHMUS, Projektarbeit, 1986, Technical University of Kaiserslautern

منابع
-----

* کتاب "The Art of Computer Programming"
* 

| * ن
* ب
* و
الگوریتم‌های مرتب‌سازی |
| --- |
| تئوری | 
* نظریه پیچیدگی محاسباتی
* نمادهای O و Ω و Θ
* ترتیب کامل
* الگوریتم مرتب‌سازی
* شبکه مرتب‌سازی
* مرتب‌سازی مقایسه‌ای

 |  |
| گونه‌های تعویضی | 
* حبابی
* دست‌نشانده
* زوج و فرد
* ساختگی
* سریع
* شانه‌ای
* کوکتلی
* گورزاد

 |
| گونه‌های انتخابی | 
* انتخابی
* دایره‌ای
* درخت دکارتی
* روان
* مسابقه‌ای
* هرمی

 |
| گونه‌های درجی | 
* درجی
* درختی
* شکیبانه
* صدفی
* کتابخانه‌ای
* گسترده

 |
| گونه‌های ادغامی | 
* ادغامی آبشاری
* ادغامی چندمرحله‌ای
* ادغامی نوسانی
* ادغامی
* رشته‌ای

 |
| گونه‌های توزیعی | 
* انفجاری
* پایه‌ای
* پرچم آمریکا
* مجاور-نگاشت (پروکس‌مپ)
* سطلی
* شمارشی
* فلش
* لانه‌کبوتری
* مهره‌ای

 |
| گونه‌های همرو | 
* ادغامی دسته‌ای فرد-زوج
* بایتونیک
* جفتی

 |
| گونه‌های دوگانه | 
* آن‌شافل
* تیم
* جی‌سورت
* درونگرا
* گسترش‌یافته

 |
| گونه‌های دیگر | 
* اسپاگتی
* توپولوژیکی
* کلوچه‌ای

 |