برزدن فیشر یتس
بر زدن فیشر یتس الگوریتمی برای ایجاد جایگشت تصادفی از یک دنباله است. الگو:سخ فرض کنید به ما آرایهای داده شدهاست و میخواهیم جایگشتی تصادفی از اعضای آن آرایه به دست آوریم. این کار مانند بر زدن دستهای ورق است و بر زدن آرایه به این معناست که هر کدام از جایگشتهای ممکن، با احتمال مساوی بیایند و جایگشتی نااریب ایجاد شود. الگو:سخ نسخهٔ اولیه پیچیدگی زمانی دارد اما نسخهٔ جدید این الگوریتم بهینه است و زمان اجرای آن ضریبی از تعداد عناصر و خطی میباشد.[۱] همچنین درجا اجرا میشود و نیاز به حافظهٔ اضافی ندارد.
روش اصلی بر زدن فیشر یتس
نسخهٔ اولیه بر زدن فیشر-یتس در سال ۱۹۳۸ توسط رونالد فیشر و فرنک یتس در کتاب جداول آماری برای تحقیقات زیستی، زراعتی، پزشکی[۲] منتشر شد. الگو:سخ این الگوریتم بسیار ساده است و برای استفادهٔ مستقیم انسانها مناسب میباشد زیرا تنها به کاغذ و خودکار نیازمند است! اما به دلیل پیچیدگی زمانی بالا توسط کامپیوترها که با دنبالههای بزرگ سر و کار دارند به کار گرفته نمیشود.
در این نسخه خاصیت تصادفی توسط جدولی از اعداد تصادفی ایجاد میشود. روش ایجاد جایگشت تصادفی اعداد ۱ تا n به شرح زیر است: الگو:سخ ۱- اعداد یک تا n را بنویسید. الگو:سخ ۲- عدد تصادفی k را بین یک و تعداد اعداد خط نخورده انتخاب کنید. (k میتواند یک و تعداد اعداد باقیمانده نیز باشد) الگو:سخ ۳- k امین عدد خط نخورده را پیدا کنید و انتهای لیستی دیگر بنویسید. سپس آن را خط بزنید. الگو:سخ ۴- مراحل ۲ و ۳ را تکرار کنید تا تمامی اعداد خط بخورند. الگو:سخ ۵- دنبالهٔ اعداد ایجاد شده در لیست، جایگشتی از دنبالهٔ اولیه است. الگو:سخ با فرض اینکه عدد تصادفی انتخاب شده در مرحلهٔ ۲ واقعاً تصادفی و نااریب باشد جایگشت ایجاد شده نیز دارای این خواص است. همچنین فیشر و یتس دربارهٔ چگونگی تولید عدد تصادفی در هر بازهای توسط جداول از پیش مهیا شده توضیح دادند. این روش نااریب است.
مثال
فرض کنید میخواهیم جایگشتی از اعداد ۱ تا ۵ را به دست آوریم. آنها را روی تکه کاغذی مینویسیم:
| دامنه | عدد تصادفی | کاغذ | لیست نهایی |
|---|---|---|---|
| ۵ ۴ ۳ ۲ ۱ |
فرض کنید عدد تصادفی به دست آمده در مرحلهٔ دو ۳ باشد. با خط زدن ۳ و افزودن به لیست نهایی به نتیجهٔ زیر میرسیم:
| دامنه | عدد تصادفی | کاغذ | لیست نهایی |
|---|---|---|---|
| [۵ ،۱] | ۳ |
۵ ۴ الگو:Font color ۲ ۱ |
۳ |
به همین ترتیب ادامه میدهیم تا تمامی اعداد خط بخورند.
| دامنه | عدد تصادفی | کاغذ | لیست نهایی |
|---|---|---|---|
| [۴ ،۱] | ۱ | ۱ ۳ |
| دامنه | عدد تصادفی | کاغذ | لیست نهایی |
|---|---|---|---|
| [۳ ،۱] | ۳ | ۵ ۱ ۳ |
| دامنه | عدد تصادفی | کاغذ | لیست نهایی |
|---|---|---|---|
| [۲ ،۱] | ۱ |
الگو:Font color ۴ الگو:Font color الگو:Font color الگو:Font color |
۲ ۵ ۱ ۳ |
| دامنه | عدد تصادفی | کاغذ | لیست نهایی |
|---|---|---|---|
| [۱ ،۱] | ۱ |
الگو:Font color الگو:Font color الگو:Font color الگو:Font color الگو:Font color |
۴ ۲ ۵ ۱ ۳ |
نسخهٔ جدید الگوریتم فیشر یتس
نسخهٔ جدید بر زدن فیشر یتس برای استفادهٔ کامپیوترها طراحی شده. این نسخه در سال ۱۹۶۴ توسط ریچارد داستنفلد معرفی شد[۳] و توسط دونالد کنوت در کتاب هنر برنامهنویسی رایانه با عنوان «الگوریتم پی»[۴] به شهرت رسید. به نظر میرسد آنها از الگوریتم فیشر و یتس مطلع نبودهاند. الگو:سخ ایدهٔ نسخهٔ جدید مشابه نسخهٔ اصلی است و بر مبنای انتخاب تصادفی میباشد. اما تفاوت جزئی آن موجب کاهش چشمگیر زمان اجرا میشود. این الگوریتم با وجود سادگی نااریب است و از حافظهٔ اضافه استفاده نمیکند. الگو:سخ الگوریتم فشر یتس زمان غیرضروریای را صرف پیدا کردن k امین عدد خط نخورده میکند (خط ۳). داستنفلد برای آن راه حلی ارائه کرد. در هر بار اجرای حلقهٔ دستورات عدد خط خورده را با جابهجا کردن آن با آخرین عدد خط نخورده به انتهای آرایه منتقل کنیم. این راه حل پیچیدگی زمانی بر زدن را از به کاهش داد. الگو:سخ ۱- دنباله ایی به طول n از اعداد مورد نظر را در نظر بگیرید. الگو:سخ ۲- عددی تصادفی مانند در بازهٔ انتخاب کنید. k تعداد اعدادی است که روی آنها عملیات انجام شده؛ به عبارت دیگر تعداد حلقههای اجرا شده میباشد. الگو:سخ ۳- عنصر ام را با عنصر ام جابهجا کنید. الگو:سخ ۴- مراحل ۲ و ۳ را دفعه تکرار کنید. الگو:سخ ۵- دنبالهٔ شما به جایگشتی تصادفی از دنبالهٔ اولیه تبدیل شدهاست.
مثال
فرض کنید دنبالهٔ مورد نظر ۵عضوی باشد؛ مثلاً
| دامنه | عدد تصادفی | دنباله پیش از تغییر | دنباله پس از تغییر |
|---|---|---|---|
| [۵ ،۱] | ۲ |
| دامنه | عدد تصادفی | دنباله پیش از تغییر | دنباله پس از تغییر |
|---|---|---|---|
| [۴ ،۱] | ۳ |
| دامنه | عدد تصادفی | دنباله پیش از تغییر | دنباله پس از تغییر |
|---|---|---|---|
| [۳ ،۱] | ۳ |
| دامنه | عدد تصادفی | دنباله پیش از تغییر | دنباله پس از تغییر |
|---|---|---|---|
| [۲ ،۱] | ۱ |
نمونه کد
کد زیر به زبان پایتون نوشته شده:[۵] الگو:چپچین
# Python Program to shuffle a given array import random
# A function to generate a random permutation of arr[] def randomize (arr, n): # Start from the last element and swap one by one. We don't # need to run for the first element that's why i > 0 for i in range(n-1,0,-1): # Pick a random index from 0 to i j = random.randint(0,i+1)
# Swap arr[i] with the element at random index arr[i],arr[j] = arr[j],arr[i] return arr
# Driver program to test above function. arr = [1, 2, 3, 4, 5, 6, 7, 8] n = len(arr) print(randomize(arr, n))
# This code is contributed by Pratik Chhajer
الگو:پایان چپچین خروجی کد: الگو:چپچین
7 8 4 6 3 1 2 5
برخی کاربردها
مولدهای اعداد تصادفی سختافزاری
معمولاً بین بیتهای اعداد تولیدشده توسط مولدهای اعداد تصادفی که بهطور سختافزاری پیادهسازی شدهاند، همبستگی وجود دارد.[۶] الگو:سخ مهاجمها با یافتن این بیتها میتوانند به ما آسیب بزنند. برزدن بیتهای عدد تولید شده میتواند این مشکل را بر طرف کند زیرا هربار بیتهای همبسته به مکانهای متفاوتی میروند و مهاجم نمیتواند آنها را شناسایی کند. البته بر زدن یکی از مشکلات عمدهٔ مولدهای اعداد تصادفی سختافزاری که اریب بودن آنهاست را حل نمیکند. این مولدها بیت صفر را به احتمال ۰٫۵ تولید نمیکنند و با برزدن تعداد صفر و یکها تغییر نمیکند و مولد همچنان اریب باقی میماند.
مرتبسازی ساختگی
کلیت الگوریتم به هم ریختن تصادفی آرایه و تولید جایگشتهای تصادفی تا رسیدن به آرایهٔ مرتبشدهاست. این الگوریتم بهینه نیست و در بدترین حالت میتواند به اتمام نرسد و زمان بینهایت داشتهباشد.
تولید عدد تصادفی در بازهٔ دلخواه

علاوه بر توجه به الگوریتم فیشر یتس باید به الگوریتم به کارگرفتهشده برای تولید عدد تصادفی در مرحلهٔ دو نیز توجه کنیم. اریب بودن الگوریتم مذکور موجب اریب شدن جایگشت نهایی میشود. معمولاً مولدهای اعداد تصادفی، اعدادی در بازهٔ [ , ۰] تولید میکنند. یکی از روشهای معمول برای پیدا کردن عدد تصادفی در بازهٔ [ , ۱] استفاده از روش باقیمانده میباشد. ( میتواند تعداد اعداد خط نخورده در روش اصلی فیشر یتس یا تعداد حلقههای باقیمانده در نسخه جدید باشد) این روش در حالت کلی مناسب نمیباشد و نتیجهٔ نهایی ما را اریب میکند. الگو:سخ فرض کنید مولد، عدد تصادفی صحیح r را در بازهٔ [ , ۰] تولید کند. روش باقیمانده را به عنوان عدد تصادفی در بازهٔ [ , ۱] خروجی میدهد. ( باقیماندهٔ تقسیم بر میباشد) الگو:سخ بهطور مثال فرض کنید مولد، عددی در بازهٔ [۹۹ , ۰] تولید کند و ما عددی در بازهٔ [۱۵ , ۱] بخواهیم. اگر اعداد صحیح بازهٔ [۹۹ , ۰] را بر ۱۵ تقسیم و باقیمانده را با یک جمع کنیم، اعداد یک تا ده، ۷ مرتبه و سایر اعداد ۶ مرتبه ظاهر میشوند؛ زیرا ۱۰۰ بر ۱۵ بخشپذیر نیست. پس توزیع اعداد تصادفی تولید شده در بازهٔ [۱۵ , ۱] یکنواخت نیست و اریب میباشد.
لینکهای مرتبط
- Random Numbers Tables Due to Tippet, Fisher & Yates, Kendall & Smith and Rand Corporation[۷]
- video explanation of the Fisher-Yates by Prof Sedgewick
- Secure Multi-Party Shuffling
- تولید اعداد تصادفی
- مرتبسازی ساختگی
- نمونه جدول اعداد تصادفی