مرتبسازی کوکتلی
مرتبسازی کوکتلی (به انگلیسی: 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(nاست؛ و این مرتبه پیچیدگی هم برای بدترین حالت و هم برای حالت میانگین است، ولی در بهترین حالت زمانی که لیست ورودی از قبل مرتب است مرتبه پیچیدگی از (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);
}
}
پانویس
- ↑ 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”
- http://max.cs.kzoo.edu/~abrady/java/sorting/BidirBubbleSort.html