Presentation is loading. Please wait.

Presentation is loading. Please wait.

روش حریصانه در طراحی الگوریتم

Similar presentations


Presentation on theme: "روش حریصانه در طراحی الگوریتم"— Presentation transcript:

1 روش حریصانه در طراحی الگوریتم
فصل چهارم: روش حریصانه در طراحی الگوریتم

2 الگوریتم حریصانه ، به ترتیب عناصر را گرفته ، هر بار آن عنصری را که طبق ملاکی معین ”بهترین“ به نظر می رسد، بدون توجه به انتخاب هایی که قبلا انجام داده یا در آینده انجام خواهد داد، بر می دارد.

3 الگوریتم حریصانه ، همانند برنامه نویسی پویا غالبا برای حل مسائل بهینه سازی به کار می روند، ولی روش حریصانه صراحت بیشتری دارد. در روش حریصانه ، تقسیم به نمونه های کوچک تر صورت نمی پذیرد.

4 الگوریتم حریصانه با انجام یک سری انتخاب، که هر یک در لحظه ای خاص ،بهترین به نظر می رسد عمل می کند، یعنی انتخاب در جای خود بهینه است.امید این است که یک حل بهینه سرتاسری یافت شود، ولی همواره چنین نیست. برای یک الگوریتم مفروض باید تعیین کرد که آیا حل همواره بهینه است یا خیر.

5 الگوریتم حریصانه ، کار را با یک مجموعه تهی آغاز کرده به ترتیب عناصری به مجموعه اضافه می کند تا این مجموعه حلی برای نمونه ای از یک مسئله را نشان دهد. هر دور تکرار ، شامل مولفه های زیر است:

6 1- روال انتخاب، عنصربعدی را که باید به مجموعه اضافه شود،انتخاب می کند
1- روال انتخاب، عنصربعدی را که باید به مجموعه اضافه شود،انتخاب می کند.انتخاب طبق یک ملاک حریصانه است. 2- بررسی امکان سنجی ، تعیین می کند که آیا مجموعه جدید برای رسیدن به حل،عملی است یا خیر. 3- بررسی راه حل ، تعیین می کند که آیا مجموعه جدید ، حل نمونه را ارائه می کند یا خیر.

7 1-4 درخت های پو شای کمینه فرض کنید طراح شهری می خواهد چند شهر معین را با جاده به هم وصل کند، به قسمی که مردم بتوانند از هر شهر به شهر دیگر بروند. اگر محدودیت بودجه ای در کار باشد ، ممکن است طراح بخواهد این کار را با حداقل مقدار جاده کشی انجام دهد. برای این مسئله دو الگوریتم حریصانه متفاوت : پریم و کروسکال بررسی می شود.

8 هر یک از این الگوریتم ها از یک ویژگی بهینه محلی استفاده می کند.
تضمینی وجود ندارد که یک الگوریتم حریصانه همواره حل بهینه بدهد، ثابت می شود که الگوریتم های کروسکال و پریم همواره درخت های پوشای کمینه را ایجاد می کنند.

9 1-1-4الگوریتم پریم الگوریتم پریم با زیر مجموعه ای تهی از یال های F و زیرمجموعه ای از رئوس Y آغاز می شود، زیرمجموعه حاوی یک راس دلخواه است. به عنوان مقداراولیه، {v1}را به Y می دهیم . نزدیک ترین را س به Y ، راسی در V – Y است که توسط یالی با وزن کمینه به راسی در Y متصل است.

10 الگوریتم 1-4: الگوریتم پریم
void prim ( int n, const number W[ ] [ ], set_ of_edges & F ) { index i , vnear; number min; edge e; index nearest [2..n];

11 number distance [2..n]; F = Ø ; for ( i = 2 ; i ≤ n ; i ++) { narest [i] = 1 ; distance [i] = W [1] [i] ; } repeat ( n-1 times ) { min = ∞ ; for ( i = 2 ; i < = n ; i ++) if ( 0 ≤ distance [i] < min ) {

12 min = distance [i] ; vnear = i ; } e = edge connecting vertices indexed by vnear and nearest [ vnear ] ; add e to F ; distance [ vnear ] = -1 ; for ( i = 2 ; i ≤ n ; i ++)

13 if ( W[i] [ vnear ] < distance [i]) {
distance [i] = W [i] [ vnear ] ; nearest [i] = vnear ; }

14 تحلیل پیچیدگی زمانی در حالت معمول برای ا لگوریتم 1-4(الگوریتم پریم)
عمل اصلی: در حلقه repeat دو حلقه وجود دارد که هر یک (n – 1 ) بار تکرار می شود . اجرای دستورات داخل هر یک از آن ها را می توان به عنوان یک بار اجرای عمل اصل در نظر گرفت. اندازه ورودی: n ، تعداد رئوس. T (n) = 2 ( n – 1) ( n – 1) Є θ ( n²)

15 قضیه 1 اگر G یک گراف موزون بدون جهت و متصل باشد، F یک زیر مجموعه امیدبخش از E یالهای گراف باشد، Y تمام رئوس متصل شده بهم با F باشد، اگر e یال کمینهای باشد که یک سر آن در Y و سر دیگر آن در V-{Y} باشد در آن صورت F+{e} امیدبخش است. امیدبخش: زیر مجموعه ای از درخت پوشای کمینه

16 قضیه 2 الگوریتم پریم همواره یک درخت پوشای کمینه تولید می کند.

17 الگوریتم 4-2: الگوریتم کروسکال
void kruskal ( int n , int m, set _ of _ edges E, set _ of _edges & F ) { index i , j ; set _pointer p , q; edge e ; sort the m edges in E by weight in non-decreasing order; F = Ø ; intitial (n) ;

18 e = edge with least weight not yet considered ;
while( number of edges in F is less than n-1){ e = edge with least weight not yet considered ; i , j = indices of vertices connected by e; p = find (i) ; q = find (j) ; if (! equal ( p, q )) { merge ( p , q ) ; add e to F ; }

19 تحلیل پیچیدگی زمانی در بدترین حالت برای ا لگوریتم 2-4(الگوریتم کروسکال)
عمل اصلی: یک دستور مقایسه. اندازه ورودی : n ، تعداد رئوس و m تعداد یال ها. درباره این الگوریتم سه نکته را باید در نظر داشت: 1- زمان لازم برای مرتب سازی یال ها . W (m) Є θ ( m lg m) 2- زمان در حلقه while . 3- زمان لازم برا ی مقدار دهی اولیه به n مجموعه متمایز. W ( m, n ) Є θ( m lg m) در نتیجه ، بدترین حالت: ( n² lg n² ) = θ ( n²lg n ) W ( m, n ) Є θ

20 پیاده سازی مجموعه های جدا ازهم
الگوريتم كروسكال مستلزم اين است كه زير مجموعه هاي از هم جدا ايجاد كنيم كه هر كدام حاوي رأس متمايزي در گراف باشند و زير مجموعه ها را مكررأ ادغام كنيم تا تمام رأس ها در يك مجموعه باشند براي پياده سازي اين الگوريتم ، به ساختمان داده اي براي مجموعه هاي از هم جدا نياز داريم . كاربردهاي ديگري از مجموعه هاي از هم جدا وجود دارد . به عنوان مثال ، مي توانند در بخش 3-4 براي بهبود پيچيدگي زماني زمان بندي با مهلت معين به كار روند .

21 تعریف مجموعه ی مرجع به ياد داشته باشيد كه نوع داده انتزاعي شامل مجموعه اي از اشياء و عمليات مجاز بر روي آن ها است . قبل از پياده سازي نوع داده انتزاعي مجموعه از هم جدا ، بايد اشياء و عمليات مورد نياز را مشخص كنيم . با مجموعه جهاني U شروع مي كنيم . به عنوان مثال ، مي توانيم داشته باشيم : U = ( A , B , C , D , E )

22 روايه اي به نام makeset مجموعه اي از هر عنصر U توليد مینمايد.
سازنده ی مجموعه ی اولیه روايه اي به نام makeset مجموعه اي از هر عنصر U توليد مینمايد. مجموعه هاي از هم جدا بايد با فراخواني هاي زير ايجاد شوند : For (each x € U) makeset (x) ; مثال : ایجاد پنج مجموعه جدا از هم U = ( A , B , C , D , E ) {A} {B} {C} {D} {E}

23 تابع find نياز به نوع set_pointer تابع find داريم ، به طوري كه اگر p و q از نوع set_pointer باشد ، و فراخواني هاي زير را داشته باشيم : P = find (‘B’ ) ; q = find (‘C ‘ ) ; مثال {A} {B} {C} {D} {E} p q

24 تابع Merge همچنين به رويه Merge نياز داريم تا دو مجموعه را در يك مجموعه ادغام كند . به عنوان مثال ، فرض كنيد اعمال زير را انجام دهيم : P = find ( ‘B ‘ ) ; q = find ( ‘C ‘ ) ; merge (p , q) ; پس از ادغام {B} , {C} چهار مجموعه از هم جدا وجود دارد . {A} {B,C} {D} {E}

25 رویه Equal سرانجام ، به رويه equal نياز داريم تا بررسي كند كه آيا دو مجموعه يكسان اند؟ مثال: فرض كنيد مجموعه هاي زیر را داشته باشيم {A} {B,C} {D} {E} و فراخواني هاي زير را انجام دهيم : P = find (‘B’ ) : q = find (‘C’ ) : r = find (‘A’): در اين صورت ، (p , q) equal بايد مقدار true و (p , r) equal بايد مقدار false را برگرداند .

26 ساختمان داده پیشنهادی يك نوع داده انتزاعي را مشخص كرديم كه اشياي آن شامل عناصر مجموعه جهاني و مجموعه هاي از هم جداي آن عناصر است و عمليات آن equal , merge , find , makset مي باشند . يك روش نمايش مجموعه هاي از هم جدا ، استفاده از درخت هايي با اشاره گرهاي معكوس است . در اين درخت ها هر گروه غير ريشه ، به والد خود اشاره مي كند . در حالي كه هر ريشه به خودش اشاره مي نمايد . براي پياده سازي ساده اين درخت ها ، فرض مي كنم مجموعه جهاني فقط حاوي انديس ها (از نوع صحيح) است . براي بسط اين پياده سازي به مجموعه جهاني متناهي ديگر ، فقط كافي است انديسي به عناصر موجود در آن مجموعه جهاني داشته باشيم. درخت ها را مي توان با استفاده از آرايه U نشان داد كه در آن ، هر انديس به U ، انديسي در مجموعه جهاني است . اگر انديس i گره غیر ریشه را نشان دهد [i] U نشان دهنده والد آن است . اگر انديس I نشان دهنده ريشه باشد ، مقدار [i] U برابر با I است .

27 (الف)پنج مجموعه از هم جدا که توسط درخت های معکوس نشان داده شده اند (ب) درخت های معکوس پس از ادغام [b] , [c] A B C D E A B C D E

28 ساختمان داده مجموعه جدا از هم (1)
const int n = the number of elements in the univers ; typedef int index ; typedef index set_pointer ; typedef index universe (1..n ) ; // universe is indexed from 1 to n universe U ; void makeser (index i) } U (i) = i ; {

29 ساختمان داده مجموعه جدا از هم (1)
set_pointer find (index i) { index j; J=I; while (U]j[!=j) J=U]j [; return j; } void merge (set_pointer p , set-pointer q) if (p<q) // p points to merged set ; U[q] = p; // q no longer points to a set . else U[p] = q; // q points to merged set; } // p no longer points to a set .

30 ساختمان داده مجموعه جدا از هم (1)
bool equal (set_pointer p , set_pointer q) { if (p= = q ) return true ; else return flase ; } Void initial (int n) Index i; For (i=l ; i<=n; i ++) Makeset (i) ;

31 شکل ج-3 پیاده سازی آرایه نمایش درخت های ساختمان داده مجموعه از هم جدا u[1] u[2] u[3] u[4] u[5] u[6] u[7] u[8] u[9] u[10] (الف) درخت های معکوس و پیاده سازی آرایه ای مربوط به 10 مجموعه جدا از هم u[1] u[2] u[3] u[4] u[5] u[6] u[7] u[8] u[9] u[10] (ب) مجموعه های{4}و{0} در بخش(الف) ادغام شده اند . اکنون مقدار محل دهم آرایه 4 است u[1] u[2] u[3] u[4] u[5] u[6] u[7] u[8] u[9] u[10] (ج) درختهای معکوس و پیاده سازی آرایه ای پس از چند ادغام . ترتیب ادغام ها ساختار درختها را تعیین می کند . 1 2 3 4 5 6 7 8 9 10 10 9 8 7 6 5 4 3 2 1 1 2 3 4 6 7 8 9 5 10 4 9 8 7 6 5 3 2 1 1 2 3 5 4 6 9 10 8 7 4 9 8 7 6 5 3 2 1

32 تحلیل پیچیدگی در بسياري از الگوريتم هايي كه از مجموعه هاي از هم جدا استفاده مي كنند ، n مجموعه از هم جدا را مقدار اوليه مي دهيم و سپس m بار از حلقه عبور مي كنيم (لازم نيست مقادير m و n يكسان باشند ) . در داخل حلقه ، رويه هاي merge , find , equal به تعداد ثابتي ازدفعات فراخواني مي شوند . هنگام تحليل الگوريتم ، به پيچيدگي زماني مقدار دهي اوليه و حلقه تكرار بر حسب n و m نياز داريم . بديهي است كه پيچيدگي زماني رويه initial در (n) θ است . چون ، مرتبه در اثر ضرب شدن در مقدار ثابت تغيير نمي كند ، فرض مي كنيم رويه هاي merge , find , equal در هر m گذر از حلقه ، يك بار فراخواني مي شوند . بديهي است كه merge , equal در زمان ثابتي اجرا مي شوند . فقط تابع find حاوي حلقه است . لذا ، مرتبه پيچيدگي زماني تمام فراخواني ها تحت تاثير تابع find قرار مي گيرند . تعداد دفعات مقايسه در find را در بدترين حالت محاسبه مي كنيم .

33 بدترین حالت وقتی رخ می دهد که دنباله هایی از ادغام زیر رخ دهد و پس از هر ادغام ، تابع Find را برای جست و جوی اندیس 6 فرا خوانی می کنیم : Merge ({5},{6}); Merge ({4},{5,6}); Merge ({3},{4,5,6}); Merge ({2},{3,4,5,6}); Merge ({1},{2,3,4,5,6}); 1 2 3 4 5 6 تابع find برای یافتن اشاره گر به مجموعه حاوی 6، به 6 مقایسه نیاز دارد . U[1] u[2] u[3] u[4] u[5] u[6] 6 5 4 3 2 1

34 تحلیل پیچیدگی تابع find بر اساس مثال قبل
با تعميم اين نتيجه به يك مقدار دلخواه m ، نتيجه مي گيريم كه تعداد مقايسه ها در بدترين حالت رابرابر است با : … + (m + 1) € θ (m2) بدترين حالت وقتي رخ مي دهد كه مرتبه اي كه در آن ادغام را انجام مي دهيم ، درختي را ايجاد كند كه عمق آن يك واحد كمتر از تعداد گره هاي درخت باشد . ا گر رويه merge را طوري اصلاح كنيم كه اين وضعيت رخ ندهد ، مي توانيم كارايي را بهبود ببخشيم . اين كار را مي توانيم با نگهداري عمق هر درخت و انتخاب درختي با عمق كمتر به عنوان ريشه ، انجام دهيم . توجه كنيد كه روش جديد ، درختي با عمق كمتر را ايجاد مي كند. براي پياده سازي اين روش ،‌لازم است عمق هر درخت در ريشه درخت ذخيره شود .

35 ساختمان داده مجموعه جدا از هم (2)
Const int n = the number of elements in the universe ; typedef int index ; typedef index set_pointer ; struct nodetype { index parent ; int depth ; } typedef nodetype universe [1..n] ; // universe in indexed // from 1 to n . universe U; void makeset (index i); U[i].parent = i; U[i].depth = o;

36 ساختمان داده مجموعه جدا از هم (2)
Set_pointer find (index i) { Index j ; J = I ; While (U[j].parent ! =j J=U([j].parent; return j; } Void merge (set_pointer p , set_pointer q) if (U[p].depth = = U[q].depth) { U[p].depth = U[p] . depth + 1 ; // tree ,s depth U[q].parent = p ; // must increase. else if (U[p].depth < U[q].depth) // make tree with lesser U[p].parent = q; else U[q].parent = p;

37 bool equal (set_pointer p , set_pointer q)
{ if (p = = q) return true ; else return false ; } Void initial (int n) Index i; for (i = 1 ; i < = n ; i + + ) makeset (i) ;

38 مي توان نشان داد كه تعداد مقايسه ها در بدترين حالت كه در m گذر ازحلقه حاوي تعداد ثابتي از فراخواني هاي رويه هاي merge , find , equal است ، برابر است با : θ (m lg m) در روش جدید ادغام ، ریشه ای از درخت با عمق کوچک تر را به عنوان فرزند ریشه درخت دیگر در نظر می گیریم 1 3 1 5 5 3 ادغام جدید 4 10 7 4 10 7 1 3 3 ادغام جدید 5 4 1 4 10 10 7 5 7

39 پیاده سازی با شرط خاص دربعضي از كاربردها ، لازم است كوچك ترين عضومجموعه باكارايي مناسبي پيدا شود . به راحتي مي توانيم آن پياده سازي را اصلاح كنيم تا كوچك ترين عضومجموعه را با كارآيي مناسبي برگرداند . براي اين كار ، در ريشه هر درخت متغيري به نام smallest را قرار مي دهيم . اين متغير حاوي كوچك ترين اندیس در درخت است . پياده سازي زير اين كار را انجام مي دهد .

40 ساختمان داده مجموعه جدا از هم (3)
const int n = the number elements in the universe typedef int index ; typedef index set_pointer ; struct nodetype { index parent ; int depth ; int smallest ; } ; Typedef nodetype universe (1..n); // universe is indexed // from 1 to n. Universe U; void makeset (index i) U[i].parent = i; U[i].depth = o; U[j].smallest =i; // the only index I is smallest . }

41 void merge (set_pointer p , set_pointer q)
{ if (U[p].depth = = U[q].depth) { U[p].depth = U[p].depth+1; // tree’s depth must increase . U [q].parent = p ; if (U[q].smallest <U[p]..smallest) // q , s tree contains smallest U[p].smallest =U[q].smallest ; // index . } Else If (u[p].depth<u[q].depth){ //make tree with lesser depth U[p].parent=q; // the child If u[p].smallest<u[q].smallest) // p , s tree contains U[q].smallest =U[p].smallest ; // smallest index . Else{ U[q].parent=p; If (u[q].smallest<u[p].smallest) //q , s tree contains U[p].smallest=u[q].smallest; //smallest index int small (set_pointer p) return U[p].smallest.

42 قضیه 2-4 الگوریتم کروسکال همواره یک درخت پوشای کمینه تولید می کند. اثبات : اثبات از طریق استقرا با شروع از مجموعه ای تهی از یال ها آغاز می شود.


Download ppt "روش حریصانه در طراحی الگوریتم"

Similar presentations


Ads by Google