الگوریتم فلوید وارشال (Floyd Warshall) – راهنمای کاربردی

۷۵۳۱
۱۴۰۳/۰۳/۸
۱۱ دقیقه
PDF
آموزش متنی جامع
امکان دانلود نسخه PDF

در علوم کامپیوتر، «الگوریتم فلوید وارشال» (Floyd Warshall Algorithm) که با اسامی «الگوریتم فلوید» (Floyd's Algorithm)، «الگوریتم روی وارشال» (Roy–Warshall Algorithm)، «الگوریتم روی فلوید» (Roy–Floyd Algorithm) یا «الگوریتم دابلیواف‌آی» (WFI Algorithm) نیز شناخته شده است، از جمله الگوریتم‌های پیدا کردن کوتاه‌ترین مسیر در گراف وزن‌دار با وزن یال‌های مثبت یا منفی محسوب می‌شود (اما چرخه منفی وجود ندارد).

الگوریتم فلوید وارشال (Floyd Warshall) – راهنمای کاربردیالگوریتم فلوید وارشال (Floyd Warshall) – راهنمای کاربردی
997696

یک اجرای الگوریتم منجر به پیدا کردن طول‌های (مجموع وزن‌ها) کوتاه‌ترین مسیر بین همه جفت یال‌ها می‌شود. اگرچه، این مورد منجر به بازگرداندن جزئیاتی از خود مسیرها نمی‌شود، ولی این امکان وجود دارد که مسیرها با ویرایش‌های کوچکی در الگوریتم، بازسازی شوند. از نسخه‌های گوناگون این الگوریتم می‌توان برای پیدا کردن بستار تعدی رابطه R یا (در ارتباط با روش شولتسه) بزرگترین مسیر بین همه جفت یال‌ها در گراف وزن‌دار استفاده کرد.

در این مطلب، روش نوشتن الگوریتم فلوید وارشال بیان و پیاده‌سازی آن در زبان‌های برنامه‌نویسی گوناگون شامل «سی» (C)، «سی‌پلاس‌پلاس» (++C)، «جاوا» (Java)، «پایتون» (Python)، «سی‌شارپ» (#C) و «پی‌اچ پی» (PHP) انجام شده است.

پیاده‌سازی الگوریتم فلوید وارشال

الگوریتم فلوید وارشال برای یافتن همه جفت کوتاه‌ترین مسیرها است. در واقع، مسئله پیدا کردن کوتاه‌ترین فاصله بین هر جفت از راس‌ها در گراف جهت‌دار وزن‌دار است. مثال زیر برای درک بهتر مطلب، قابل توجه است.

مثال: حل مسئله کوتاه‌ترین مسیر با الگوریتم فلوید وارشال

ورودی به صورت زیر است.

graph[][] = { {0,   5,  INF, 10},
                    {INF,  0,  3,  INF},
                    {INF, INF, 0,   1},
                    {INF, INF, INF, 0} }

ورودی بالا گرافی را نشان می‌دهد که در زیر قابل مشاهده است.

             10
       (0)------->(3)
        |         /|\
      5 |          |
        |          | 1
       \|/         |
       (1)------->(2)
            3

شایان توجه است که مقدار graph[i][j]‎ در صورتی که i برابر با j باشد، مساوی صفر است و اگر هیچ یالی از راس i به j وجود نداشته باشد، graph[i][j]‎ بی‌نهایت است. ماتریس کوتاه‌ترین مسیرها به صورت زیر است.

    0      5      8      9
    INF      0      3      4
    INF    INF      0      1
    INF    INF    INF      0

الگوریتم فلوید وارشال

ابتدا ماتریس پاسخ با مقادیر موجود در ماتریس گراف ورودی، مقداردهی اولیه می‌شود. سپس، ماتریس خروجی با در نظر گرفتن همه راس‌ها به عنوان یک راس میانی، به روز رسانی می‌شود. هدف، پیدا کردن یک به یک رأس‌ها و به روز رسانی همه کوتاه‌ترین مسیرهایی است که شامل راس‌های انتخاب شده به عنوان راس میانی در کوتاه‌ترین مسیر می‌شوند.

هنگامی که رأس شماره k به عنوان یک راس میانی انتخاب می‌شود، پیش‌تر، رأس‌های {0,1,2,..k1}\left\{0, 1, 2, .. k-1\right\} به عنوان راس‌های میانی انتخاب شده‌اند. برای هر جفت (i, j) از رأس‌های مبدأ و مقصد، دو حالت ممکن وجود دارد.

  1. k یک رأس میانی در کوتاه‌ترین مسیر از i به j نیست. مقدار dist[i][j]‎ به صورتی که هست، حفظ می‌شود.
  2. k یک رأس میانی در کوتاه‌ترین مسیر از i به j است. اگر dist[i][j] > dist[i][k] + dist[k][j]‎، مقادیر dist[i][j]‎ به صورت dist[i][k] + dist[k][j]‎ به روز رسانی می‌شود.

تصویری که در ادامه آمده است، نشان‌دهنده خصوصیات زیر ساختار بهینه بالا در مسئله کوتاه‌ترین مسیر برای همه جفت‌ها است.

الگوریتم فلوید وارشال (Floyd Warshall)

در ادامه، پیاده‌سازی الگوریتم فلوید وارشال در زبان‌های برنامه‌نویسی گوناگون انجام شده است.

الگوریتم فلوید وارشال در ++C

الگوریتم فلوید وارشال در C

الگوریتم فلوید وارشال در جاوا

الگوریتم فلوید وارشال در پایتون

الگوریتم فلوید وارشال در C#‎

الگوریتم فلوید وارشال در PHP

خروجی قطعه کدهای بالا به صورت زیر است.

Following matrix shows the shortest distances between every pair of vertices
      0      5      8      9
    INF      0      3      4
    INF    INF      0      1
    INF    INF    INF      0

پیچیدگی زمانی روش بالا از درجه O(V3)‎ است. برنامه بالا، فقط کوتاه‌ترین مسیر را چاپ می‌کند. می‌توان این برنامه را به گونه‌ای ویرایش کرد که کوتاه‌ترین مسیرها را با ذخیره‌سازی اطلاعات اجداد آن‌ها در یک ماتریس دوبُعدی، نمایش دهد. همچنین، مقدار INF (بی‌نهایت) را می‌توان از limits.h به عنوان INT_MAX به دست آورد تا اطمینان حاصل شود که با بزرگ‌ترین مقدار ممکن کار شده است. هنگامی که INF به عنوان INT_MAX قرار داده می‌شود، نیاز به تغییر شرط if در برنامه بالا است تا از سرریز محاسباتی جلوگیری شود.

#include 

#define INF INT_MAX
..........................
if ( dist[i][k] != INF && 
     dist[k][j] != INF && 
     dist[i][k] + dist[k][j] < dist[i][j]
    )
 dist[i][j] = dist[i][k] + dist[k][j];
...........................

اگر نوشته بالا برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

^^

بر اساس رای ۲۰ نفر
آیا این مطلب برای شما مفید بود؟
اگر پرسشی درباره این مطلب دارید، آن را با ما مطرح کنید.
منابع:
GeeksforGeeksویکی‌پدیای انگلیسی
PDF
مطالب مرتبط
۳ دیدگاه برای «الگوریتم فلوید وارشال (Floyd Warshall) – راهنمای کاربردی»

سلام؛ این الگوریتم فقط مقدار کوتاه ترین مسیر رو نشون میده؟ یعنی خود مسیر رو نمیشه مشخص کرد؟

با سلام و تشکر.
من کد خط 55 رو کامل متوجه نشدم. منظور از print “%7s” %(“INF”) چیه دقیقن و چرا اینجوری نوشته شده؟

با سلام؛

از همراهی شما با مجله فرادرس سپاس‌گزاریم. این دستور، به طول هفت کاراکتر، مقدار INF را چاپ می‌کند. در واقع، هفت جای خالی می‌گذارد، بعد مقدار INF را در آنجا قرار می‌دهد. البته، اخیرا از روش‌های دیگری برای فرمت کردن خروجی استفاده می‌شود که مهم‌ترین آن‌ها استفاده از ()format است و روش موجود در این کد عملا قدیمی شده است.

پیروز، شاد و تندرست باشید.

نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *