Presentation is loading. Please wait.

Presentation is loading. Please wait.

ساختمان داده ها و الگوریتم ها

Similar presentations


Presentation on theme: "ساختمان داده ها و الگوریتم ها"— Presentation transcript:

1 ساختمان داده ها و الگوریتم ها

2 ساختمان داده ها (Data Structures)
ساختارهایی هستند که برای دریافت داده های خام توسط کامپیوتر و پیاده سازی و اجرای الگوریتم های مختلف روی آنها, مورد استفاده قرار می گیرند. ساختمان داده پویا ایستا نیمه ایستا خطی غیر خطی گراف درخت لیست پیوندی صف پشته اولیه غیر اولیه عدد صحیح عدد اعشاری اشاره گر آرایه رشته رکورد ساختمان داده های ایستا در طول حیاتشان تغییر نمی کنند ولی در مدل پویا تغییرات نامحدود و مجاز است.

3 فصل اول روش های تحلیل الگوریتم
فصل اول روش های تحلیل الگوریتم

4 اهداف و سوالات مهم اهداف سوالات مهم خصوصیات کلی یک الگوریتم
تعیین مرتبه زمانی یک الگوریتم تشریح نمادهای نشان دهنده کارایی یک الگوریتم الگوریتم های بازگشتی سوالات مهم چگونه می توان فهمید یک برنامه نوشته شده از برنامه دیگر بهتر عمل می کند؟ دلیل استفاده از الگوریتم بازگشتی به جای الگوریتم ترتیبی چیست؟

5 الگوریتم و ویژگی های آن الگوریتم: مجموعه محدودی ازدستورات و دستورالعمل هاست که اگر دنبال شوند، موجب انجام کار خاصی می گردند. ویژگی ها: ورودی ← هیچ یا چند کمیت ورودی داشته باشد. خروجی ← حداقل یک کمیت خروجی داشته باشد. قطعیت ← هر دستورالعمل باید بدون ابهام و کاملاً واضح باشد. پایان پذیر ← پس از طی تعداد مراحل محدودی خاتمه یابد. کارایی ← هر دستورالعمل انجام پذیر باشد. نکات: الگوریتم حتماً باید پایان پذیر باشد در حالیکه برنامه لزوماً پایان پذیر نیست (سیستم عامل، برنامه ایست که هیچگاه پایان نمی یابد و همواره در یک حلقه انتظار است تا برنامه بعدی وارد شود). الگوریتم ها توسط زبان های برنامه نویسی پیاده سازی می شوند و هر الگوریتم توسط یک برنامه (program) ارائه می گردد (با هر زبانی).

6 کدام الگوریتم برای حل یک مسئله خاص بهتر عمل می کند؟
مشخصات یک الگوریتم خوب: زمان اجرا میزان حافظه مصرفی سادگی وضوح ... عوامل دخیل در زمان اجرای برنامه: سرعت سخت افزار نوع کامپایلر اندازه داده ورودی ترکیب داده های ورودی: بررسی الگوریتم با توجه به نحوه ترکیب ورودی ها در بهترین، متوسط و بدترین حالات. پیچیدگی زمانی الگوریتم: تابعی است از اندازه مسئله پارامترهای دیگر که تأثیر ثابت در زمان اجرا دارند.

7 بررسی پیچیدگی زمانی الگوریتم ها یا زمان اجرای الگوریتم ها
تابع T(n): تابع زمانی الگوریتم است. برای بررسی زمان اجرای یک الگوریتم باید تابع T(n) را محاسبه کنیم. n اندازه ورودی مسئله است. مسئله ممکن است شامل چند ورودی باشد. مثل گراف: T(n,m) محاسبه تابع T(n) برای یک الگوریتم: زمان مربوط به اعمال جایگزینی زمان مربوط به اعمال محاسباتی زمان مربوط به ساختارif و else (اگر هر کدام زمانهای T1 و T2 را داشته باشند آنگاه زمان اجرای برنامه برابر با بیشترین مقدار آنها خواهد بود.) زمان مربوط به تکرار تعدادی از دستورالعمل ها (حلقه ها) زمان مربوط به توابع بازگشتی نکات: عمل اصلی: قطعه ای از برنامه است که افزایش زمان اجرا به آن بستگی مستقیم دارد. با تعیین تعداد دفعات اجرای یک عمل اصلی می توانیم تابع زمانی یک الگوریتم را محاسبه کنیم. زمان اجرای یک الگوریتم با افزایش اندازه داده ورودی (n) زیاد می شود و با تعداد تکرار عملیات اصلی تناسب دارد (بعبارتی: تعداد تکرار یک عمل اصلی، تابعی است از اندازه ورودی.) در محاسبه تابع زمانی لازم نیست تک تک دستورات اجرا شده را شمارش کنیم. فقط دستوراتی که مستقل از زبان برنامه نویسی هستند و بالاخص تعداد دفعاتی که یک عمل اصلی انجام می شود را مورد توجه قرار می دهیم.

8 نکات مورد نیاز در حل مسائل
ابتدا تعیین کنید که هدف، یافتن تعداد تکرار یک دستورالعمل ویژه است یا تعداد گام های کل برنامه؟ فرمول های مورد نیاز برای محاسبه تعداد دفعات اجرای دستورات درون حلقه ها (در استفاده از نماد Σ توجه به تعداد حلقه های for و وابستگی متغیرهای درون حلقه ها به یکدیگر الزامی است.)

9 نکته در محاسبه حلقه ها for (i=0; i ≤ n; i++):
تعداد تکرار عملیات اصلی داخل حلقه: 1+ مقدار ابتدایی متغیر- مقدار انتهایی متغیر n-0+1=n+1 for (i=0; i < n; i++): مقدار ابتدایی متغیر- مقدار انتهایی متغیر N-0=n در تمام موارد، تعداد تکرار داخل حلقه یک واحد از تعداد تکرار خود حلقه، کمتر است.

10 مثال1: یافتن تابع زمانی الگوریتم ها
float sum (float list[], int n) { float s=0; int i; for (i=0; i<n; i++) s=s+list[i]; return s; } خطوط 1، 2، 8(تعریف تابع)، 4 (تعریف متغیر) دستوراتی هستند که توسط CPU اجرا نمی شوند پس مرحله اجرایی آنها صفر است. هدف از محاسبه یک الگوریتم بدست آوردن زمان، در تعداد تکرارهای بزرگ یا خیلی بزرگ است. ضرایب در تعداد تکرارهای بالا تاثیرگذاری کمی دارند. تعداد زمان سطر - 1 2 C1 3 4 n+1 C2 5 n C3 6 C4 7 8 2n+3 = مجموع تعداد تکرار T(n)=C1*1 + C2*(n+1) +C3*n + C4*1= (C1+C2+C4) + n*(C2+C3)= D + C*n = C*n اندازه داده ورودی: n عمل اصلی: s=s+list[i];

11 مثال2: یافتن تابع زمانی الگوریتم ها
تعداد زمان سطر 1 C1 n+1 C2 2 n*(n+1) C3 3 n*n C4 4 = مجموع تعداد تکرار x=0; for(i=0; i<n; i++) for (j=0; j<n; j++) x++; نکته: از طریق تریس کردن نیز می توان به تعداد تکرار قطعه کدهای داده شده پی برد.

12 مثال3: یافتن تابع زمانی الگوریتم ها
تعداد اجرا شدن دستور اصلی تغییرات i j 1بار 1 2بار 1,2 2 3بار 1,2,3 3 nبار 1,2,3,…,n n For(j=1; j≤n; j++) for (i=1; i≤j; i++) x++;

13 مثال4: یافتن تابع زمانی الگوریتم ها
i:=n; while (i>1) do begin x:=x+1; i:=i div 2; end; اگر n=16 باشد: تعداد اجرا شدن دستور اصلی شرط i>1 i 1بار درست 16 8 4 2 - غلط 1 جمعا 4 بار اگر n=14 باشد: تعداد اجرا شدن دستور اصلی شرط i>1 i 1بار درست 14 7 3 - غلط 1 جمعا 3 بار

14 پیچیدگی زمانی الگوریتم ها در یک نگاه
نماد Big-oh (نماد O): T(n)≤Cf(n) نماد Big-Omega (نماد Ω): T(n) ≥ Cf(n) نماد دلتا (نماد θ): C1f(n) ≤T(n) ≤ C2f(n) با استفاده از نمادهای فوق، مرتبه زمانی الگوریتم ها را با هم مقایسه می کنیم.

15 تحلیل پیچیدگی زمانی الگوریتم ها در بدترین حالت
نماد Big-oh: گوییم T(n)∈O(f(n)) (T(n) متعلق به اوی بزرگ f(n)) اگر و تنها اگر ثابت های صحیح C و n0 وجود داشته باشند که برای همه مقادیر n≥n0، داشته باشیم T(n)≤Cf(n): نماد O یک کران بالا برای تابع T(n) تعیین می کند. f(n) مرتبه زمانی الگوریتم (یا پیچیدگی زمانی الگوریتم)

16 مثال (Big-oh) مرتبه زمانی مربوط به زمان اجراهای داده شده را محاسبه کنید: برای حل سریع مسائل : در تابع زمانی، جمله با بیشترین مرتبه را در نظر می گیریم. ضرایب جملات عملاً تاثیری در مرتبه زمانی الگوریتم ندارند.

17 قضیه (Big-oh) اگر زمان اجرای یک الگوریتم(T(n)) به صورت زیر باشد آنگاه داریم: اثبات:

18 تحلیل پیچیدگی زمانی الگوریتم ها در بهترین حالت
نماد Big-Omega: گوییم T(n)∈Ω(f(n)) (T(n) متعلق به امگای بزرگ f(n)) اگر و تنها اگر ثابت های صحیح C و n0 وجود داشته باشند که برای همه مقادیر n≥n0، داشته باشیم T(n) ≥ Cf(n) نماد Ω یک کران پایین برای تابع T(n) تعیین می کند. قضیه: اگر زمان اجرای یک الگوریتم(T(n)) به صورت زیر باشد و am>0 باشد، آنگاه داریم:

19 مثال ((Big-Omega مرتبه زمانی مربوط به زمان اجراهای داده شده را محاسبه کنید:

20 تحلیل پیچیدگی زمانی الگوریتم ها در حالت متوسط
نماد θ: گوییم T(n)∈θ(f(n)) اگر و تنها اگر ثابت های صحیح C1 و C2 و ثابت صحیح n0 وجود داشته باشند بطوریکه برای همه مقادیر n≥n0: C1f(n) ≤T(n) ≤ C2f(n) نماد θ تابع T(n) را هم از بالا و هم از پایین محدود می کند. نکته: درجه رشد تابع T(n) و f(n) یکسان است. قضیه: اگر زمان اجرای یک الگوریتم(T(n)) به صورت زیر باشد و am>0 باشد، آنگاه داریم:

21 مثال (θ) مرتبه زمانی مربوط به زمان اجرای داده شده را محاسبه کنید:

22 تحلیل پیچیدگی زمانی برای حالات بهترین، بدترین و متوسط (1)
برخی از مسائل برای همه موارد، تنها یک تابع پیچیدگی دارند مثل: A: array [1..n] of integer; s:=0; for i:=1 to n do s:=s+A[i]; در برنامه فوق عمل اصلی یعنی s:=s+A[i];به تعداد n بار اجرا شده و همواره T(n)=n است.

23 تحلیل پیچیدگی زمانی برای حالات بهترین، بدترین و متوسط (2)
دسته ای از مسائل وجود دارند که تابع پیچیدگی آنها به ازای حالات مختلف ورودی، مقادیر متفاوتی را ارائه می دهند مثل الگوریتم جستجوی خطی (ترتیبی): A: array [1..n] of integer; for i:=1 to n do if (x=A[i]) { Write (‘YES’); Exit (); } Write (‘NO’);

24 تحلیل پیچیدگی زمانی برای حالات بهترین، بدترین و متوسط (ادامه اسلاید قبل)
در بدترین حالت عدد x در خانه آخر آرایه قرار دارد و یا اصلا در آرایه وجود ندارد که در این حالت T(n)=n و T(n)=n+1است. در بهترین حالت عدد x در اولین خانه قرار دارد و تنها یک بار عمل if مورد نیاز است. در این حالت T(n)=1 است. در حالت متوسط: فرض: عدد x درون آرایه وجود دارد. احتمال حضور x در خانه i ام برابر با 1/n است و تعداد دفعات آزمایش در این حالت برابر با : بنابراین بطور متوسط نیمی از عناصر آرایه باید جستجو شوند. احتمال وجود x در آرایه برابر با P است پس احتمال وجود x در یکی از خانه های آرایه P/n و احتمال نبودن x در آرایه 1-P :

25 نکات مورد نیاز در حل مسائل
نکته در مورد حلقه ها: در حلقه while که بطور طبیعی شمارنده آن از n تا 1 تغییر می کند اگر مرتباً شمارنده آن با دستور i:=i div k; بر عدد k تقسیم شود مرتبه اجرایی آن و اگر شمارنده دستور i:=i * k; از 1 تا n تغییر کند باز هم مرتبه اجرایی آن است: نکته فوق در مورد سایر حلقه ها هم صدق می کند. در جدول زیر مرتبه اجرایی چند تابع به ترتیب صعودی از چپ به راست نوشته شده است:

26 دو شیوه تحلیل و برنامه نویسی
الگوریتم های ترتیبی (غیر بازگشتی) غیر ساخت یافته و قدیمی است. بیشتر بر نکات صحیح کدنویسی تأکید دارد. برنامه نویس یک طرح کلی برای پروژه خود ندارد. برنامه اغلب ارتباطات ضعیف و بخش های پرخطایی دارد. الگوریتم های بازگشتی (برنامه نویسی رویه ای یا ماژولار) برنامه ابتدا به بخش ها و بلوک های مشخص تقسیم می شود. سپس, هر قسمت و بلوک نوشته می شود. خوانایی زیادی دارند. آزمایش و اشکال زدایی و اصلاح آنها نیز آسان است .

27 الگوریتم های ترتیبی (غیر بازگشتی)
نحوه محاسبه: همانند محاسبات ارائه شده در اسلایدهای قبل مرتبه زمان اجرای یک الگوریتم، مرتبه تکه ای از برنامه است که بیشترین زمان را دارا است. مثال: پیچیدگی زمانی پیدا کردن بیشترین مقدار در یک آرایه را تحلیل کنید. ورودی: آرایه A، n تعداد عناصر خروجی بیشترین مقدار در آرایه

28 زیربرنامه های بازگشتی (Recursive)
مسئله را به دو یا چند زیرمسئله کوچکتر تقسیم می کنیم. عمل تقسیم مسئله به زیر مسئله های را تا زمانیکه اندازه زیرمسئله ها به اندازه کافی کوچک شوند ادامه می دهیم. بعد از انجام عملیات تقسیم، برای حل زیرمسئله ها از خود الگوریتم استفاده می کنیم. حاصل زیرمسئله ها را با هم ترکیب می کنیم تا راه حل مسئله بزرگتر حاصل شود. ترکیب زیرمسئله ها را تا زمانیکه مسئله اصلی حل نشده باشد ادامه می دهیم. مراحل الگوریتم های بازگشتی: عمل فراخوانی بازگشت از یک فراخوانی فراخوانی مستقیم: هر تابع بصورت مستقیم خودش را فراخوانی می کند. فراخوانی غیرمستقیم: تابعی مثل F1 تابع F2 را و F2 نیز F1 را فراخوانی می کنند.

29 زیربرنامه های بازگشتی(2)
اعمالی که در مرحله فراخوانی انجام می شوند: کلیه متغیرهای محلی (local variable) و مقادیر آنها در پشته(stack) سیستم قرار می گیرند. آدرس بازگشت به پشته منتقل می شود. عمل انتقال پارامترها (parameter passing) صورت می گیرد. کنترل برنامه (program counter) بعد از انجام مراحل بالا به ابتدای پردازه جدید اشاره می کند. در بازگشت، عکس عملیات فوق انجام می شود: متغیرهای محلی از سر پشته حذف و در خود متغیرها قرار می گیرند. آدرس بازگشت از بالای پشته بدست می آید. آخرین اطلاعات از پشته حذف(Pop) می شود. کنترل برنامه از آدرس بازگشت بند 2 ادامه می یابد.

30 نکات زیربرنامه های بازگشتی
ویژگی های زیربرنامه های بازگشتی: زیربرنامه, خودش , خودش را فراخوانی می کند (اغلب با آرگومان کمتر). یک شرط جهت اتمام فراخوانی وجود دارد. معمولاً مسائلی را به کمک تکنیک بازگشتی حل می کنیم که حالت nام آن به کمک حالت n-1ام آن قابل بدست آوردن باشد. مزیت روش بازگشتی نسبت به روش معمولی: سادگی برنامه نویسی آن عیب آن: مصرف زیاد حافظه (بدلیل مصرف حافظه پشته و فراخوانی های مکرر) و نیز مصرف زمان زیادی است که برای فراخوانی ها صرف می شود اگر زیربرنامه ای مرتباً خودش را صدا بزند و شرطی برای اتمام فراخوانی ها نداشته باشد, پس از مدتی پیام خطای Stack Overflow در زمان اجرا صادر شده و اجرای برنامه متوقف می شود. فراخوانی مستقیم: هر تابع بصورت مستقیم خودش را فراخوانی می کند. فراخوانی غیرمستقیم: تابعی مثل F1 تابع F2 را و F2 نیز F1 را فراخوانی می کنند.

31 مثال1: محاسبه n! با استفاده از تابع بازگشتی (در پاسکال):
function fact (n : Integer) : Integer; Begin if n <=1 then fact := 1 else fact := n * fact(n-1) End; Readln(x); writeln(fact(x)); End. با استفاده از تابع غیر بازگشتی (در پاسکال): Var x:Integer; function fact1(n : Integer) : Integer; Var i, f: integer; Begin f :=1; for i :=1 to n do f := f * i; fact1 :=f; End; با استفاده از تابع بازگشتی (در C): int fact (int n) { if (n <=1) return 1; else return (n * fact(n-1)); }

32 استفاده از پشته در محاسبه بازگشتی n! (ادامه از اسلاید قبل)
حافظه پشته بصورت Last In First Out است. زماینکه از وسط اجرای یک تابع به یک تابع دیگر پرش می کنیم, دستوراتی که هنوز اجرا نشده اند را در درون پشته ذخیره می کنیم. function fact (n : Integer) : Integer; Begin if n <=1 then fact := 1 else fact := n * fact(n-1) End; 1 2 6 fact(2):=2*fact(1) fact(3):=3*fact(2) fact(4):=4*fact(3) fact(4):=4*fact(3) fact(3):=4*fact(2) fact(4):=4*fact(3) fact(3):=3*fact(2) fact(4):=4*fact(3) fact(4):=4*fact(3)

33 مثال2 با توجه به فرمول زیر, یک تابع بازگشتی بنویسید که مقدار a*b (ضرب اعداد طبیعی)را محاسبه کند. a if b = 1 a*b = a + a * (b-1) if b>1 function multiply (a,b : integer) : integer; Begin if b=1 multiply := a else multiply := a+ multiply (a,b-1); End;

34 مثال3 در برنامه زیر خروجی F(3,6) چه می شود (تابع فیبوناچی)؟
پاسخ: 4 نکته: در درخت زیر، فراخوانی ها بصورت عمقی انجام می شوند. function F(m,n : integer) : integer; Begin if (m=1) OR (n=0) OR (m=n) then f:=1 else F := F (m-1,n) + F(m-1 , n-1) End; int F(int m, int n) { if (m==1 || n==0 || m==n) return 1; else return F (m-1,n) + F(m-1 , n-1); }

35 مسأله کلاسیک برج هانوی (برهما):
A B C 4 3 2 1 n حلقه باید از ستون A به ستونC انتقال یابند بطوریکه در ستون C نیز همان ترتیب ستون A را داشته باشند. محدودیت ها: در هر بار انتقال فقط یک حلقه می تواند جابجا شود. در هیچ مرحله ای نمی توان یک حلقه بزرگتر را بر روی حلقه کوچکتر قرار داد.

36 مسأله کلاسیک برج هانوی با 2 حلقه:
B C A to B A to C B to C 2 2 1 2 1 A

37 مسأله کلاسیک برج هانوی با 3 حلقه:
B C A to C A to B C to B B to A B to C B to A 3 3 2 3 2 1 3 2 1 3 A

38 مسأله کلاسیک برج هانوی با n حلقه:
B C A to B A to C 1 1 A پیچیدگی مسأله برج های هانوی با افزایش تعداد حلقه ها بصورت نمایی زیاد می شود. ابتدا n-1 حلقه از A به B منتقل می شود.سپس، یک حلقه از A به C و در ادامه n-1 حلقه باقیمانده بکمک A از B به C منتقل می شود.

39 مسأله کلاسیک برج هانوی با n حلقه:
مقصد کمکی مبدا مقصد کمکی مبدا مقصد کمکی مبدا برای حل مسائل برج های هانوی با n دیسک به جابجایی نیاز است.

40 مسأله برج هانوی با 3 حلقه را به صورت تشریحی و با استفاده از نمودار درختی حل کنید.

41 محاسبه تابع زمانی الگوریتم های بازگشتی
محاسبه فاکتوریل (ارائه شده در اسلایدهای 24 و 25): زمان اجرای دستور if را محاسبه می کنیم. O(1) در خط دوم زمان مربوط به عمل ضرب و فراخوانی تابع است. حل با استفاده از روش تکرار با جایگذاری:

42 توجه کنید که سوال از شما چه می خواهد؟
تعیین تابع زمانی با استفاده از الگوریتم داده شده تعیین پیچیدگی زمانی تابع زمانی داده شده حل مسئله با استفاده از ورودی های داده شده

43 چند مثال:

44 تست ارزشیابی پاسخ: 125

45 تست ارزشیابی پاسخ: 55

46 تست ارزشیابی پاسخ: F1(4)=42024, F2(4)=5313


Download ppt "ساختمان داده ها و الگوریتم ها"

Similar presentations


Ads by Google