0% found this document useful (0 votes)
8 views82 pages

Algorithm Design Niroomand

Matrix Algorithm Design in Persian language

Uploaded by

parimahnemati
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views82 pages

Algorithm Design Niroomand

Matrix Algorithm Design in Persian language

Uploaded by

parimahnemati
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 82

‫به نام خدا‬

‫اللَهُمَّ إنّي اَعوذُ بِکَ مِن عِلمٍ الیَنفَع (خداوندا! پناه ميبرم به تو از علمي که نفعي نداشته باشد)‬

‫طراحی الگوریتم‬
‫‪Algorithm Design‬‬

‫حمیدرضا نیرومند‬
‫‪http://niroomand.ir‬‬
‫فهرست‬
‫فصل اول‪ :‬نقش الگوریتمها در پردازش ‪5 .............................................................................‬‬

‫‪ -1-1‬تعریف چند اصطالح ‪5 ........................................................................................‬‬


‫‪ -1-2‬برخي مسائل که با الگوریتمهای این کتاب‪ ،‬قابل حل هستند ‪7 .............................................‬‬
‫‪ -1-3‬ساختمانهای داده مورد بحث در این کتاب ‪8 ...............................................................‬‬
‫‪ -1-4‬تکنیک ‪8 .......................................................................................................‬‬
‫‪ -1-5‬مسائل سخت ‪9 .................................................................................................‬‬
‫‪ -1-7‬پردازش موازی ‪11 ............................................................................................‬‬
‫‪ 1-8-‬الگوریتم بهعنوان یک فناوری ‪11 ............................................................................‬‬
‫‪ 1-9-‬کارایي ‪12 .....................................................................................................‬‬
‫‪ -1-10‬الگوریتمها و دیگر فناوریها ‪12 .............................................................................‬‬
‫فصل دوم‪ :‬آغاز کار با الگوریتمها ‪15 .................................................................................‬‬

‫‪ -2-1‬مقدمه ‪15 .......................................................................................................‬‬


‫‪ -2-2‬الگوریتم مرتبسازی درجي ‪15 .............................................................................‬‬
‫‪ -2-4‬تحلیل الگوریتمها ‪22 .........................................................................................‬‬
‫‪ -2-5‬تحلیل الگوریتم مرتبسازی درجي ‪23 ......................................................................‬‬
‫‪ -2-7‬تحلیل بهترین و بدترین حالت ‪28 ............................................................................‬‬
‫‪ -2-8‬نرخ رشد ‪29 ...................................................................................................‬‬
‫فصل سوم‪ :‬نرخ رشد توابع ‪31 ..........................................................................................‬‬

‫‪ -3-1‬نرخ رشد توابع ‪31 .............................................................................................‬‬


‫‪ -3-2‬نمادهای تقریبي (یا نمادهای همبستگي یا نمادهای مُجانبي) ‪32 ............................................‬‬
‫‪32 ......................................................................................... 𝞱 –Notation‬‬ ‫‪-3-3‬‬
‫‪33 ......................................................................................... O –Notation‬‬ ‫‪-3-4‬‬
‫‪33 ......................................................................................... Ω –Notation‬‬ ‫‪-3-5‬‬
‫‪ -3-6‬ترتیب رشد توابع مختلف ‪34 .................................................................................‬‬
‫‪35 .......................................................................................... o –Notation‬‬ ‫‪-3-8‬‬
‫‪35 ......................................................................................... ω –Notation‬‬ ‫‪-3-9‬‬

‫‪2‬‬
‫‪ -3-10‬نمادهای استاندارد و توابع عمومي ‪36 ........................................................................‬‬
‫‪ -3-11‬یکنواختي ‪36 ..................................................................................................‬‬
‫‪ -3-12‬باقیمانده ‪38 ....................................................................................................‬‬
‫فصل چهارم‪ :‬الگوریتمهای بازگشتي ‪39 ...............................................................................‬‬

‫‪ -4-1‬الگوریتم بازگشتي ‪39 .........................................................................................‬‬


‫‪ -4-2‬مثالي از الگوریتم بازگشتي برنامهی محاسبه فاکتوریل ‪39 ..................................................‬‬
‫‪ -4-3‬جستجوی دودویي به صورت بازگشتي ‪39 ..................................................................‬‬
‫‪ 4-4-‬اعداد فیبوناچي ‪40 .............................................................................................‬‬
‫‪ -4-5‬مطالعه آزاد نسبت طالیي ‪42 .................................................................................‬‬
‫فصل پنجم‪ :‬تکنیکهای طراحي الگوریتم (‪ :)1‬روش تقسیم و غلبه ‪43 .............................................‬‬

‫‪ -5-1‬طراحي الگوریتمها ‪43 ........................................................................................‬‬


‫‪ -5-2‬روش تقسیم و غلبه ‪43 ........................................................................................‬‬
‫‪ -5-3‬جستجوی دودویي ‪48 .........................................................................................‬‬
‫فصل ششم‪ :‬تکنیکهای طراحي الگوریتم (‪ :)2‬روش حافظه پویا ‪49 ................................................‬‬

‫‪ -6-1‬مقدمه ‪49 .......................................................................................................‬‬


‫‪ -6-2‬الگوریتم مرتبسازی سریع ‪49 ...............................................................................‬‬
‫‪ -6-3‬مسأله ضرب ماتریسها ‪50 ....................................................................................‬‬
‫‪ -6-4‬الگوریتم ضرب ‪52 ............................................................................. Strasson‬‬
‫‪ -6-5‬ضرب اعداد بزرگ ‪53 ........................................................................................‬‬
‫‪ -6-6‬برنامهنویسي با حافظه پویا ‪54 .................................................................................‬‬
‫‪ -6-7‬محاسبه تراز چند دانشجو ‪54 .................................................................................‬‬
‫‪ -6-8‬مسأله انتخاب ‪ k‬شیئ از ‪ n‬شیئ ‪56 ...........................................................................‬‬
‫‪ -6-9‬حل مسأله فیبوناچي با استفاده از برنامهنویسي پویا‪58 .......................................................‬‬
‫‪ -6-10‬مسأله فلوید‪59 .................................................................................................‬‬
‫فصل هفتم‪ :‬تکنیکهای طراحي الگوریتم (‪ :)3‬روشهای حریصانه ‪63 .............................................‬‬

‫‪ -7-1‬مسأله خرد کردن پول ‪63 .....................................................................................‬‬


‫‪ -7-2‬مسأله کد هافمن ‪65 ...........................................................................................‬‬

‫‪3‬‬
‫‪ -7-3‬مسأله درخت پوشای کمینه ‪67 ...............................................................................‬‬
‫‪ -7-1‬مسأله فروشنده دورهگرد ‪69 ..................................................................................‬‬
‫‪ -7-2‬الگوریتم کراسکال ‪70 ........................................................................................‬‬
‫‪ -7-3‬الگوریتم دکسترا ‪71 ...........................................................................................‬‬
‫فصل هشتم‪ :‬تکنیکهای طراحي الگوریتم (‪ :)4‬الگوریتمهای عقبگرد ‪73 ..........................................‬‬

‫‪ -8-1‬مسأله ‪ 4‬وزیر ‪73 ...............................................................................................‬‬


‫‪ -8-2‬مسأله حاصل جمع زیرمجموعهها‪77 .........................................................................‬‬
‫‪ -8-3‬مسأله رنگآمیزی گراف با ‪ m‬رنگ (‪78 ............................................... )M–Coloring‬‬
‫‪ -8-4‬مسأله کولهپشتي ‪81 ...........................................................................................‬‬
‫‪ -8-5‬انواع مسأله کولهپشتي ‪82 .....................................................................................‬‬

‫‪4‬‬
‫فصل اول‬

‫نقش الگوریتمها در پردازش‬

‫تعریف چند اصطالح‪:‬‬ ‫‪-1-1‬‬


‫‪ -‬مسأله‪ 1:‬مانعي که رسیدن به هدف را مشکل ميکند‪.‬‬

‫‪ -‬انواع هدف‪:‬‬
‫‪( Purpose o‬مقصود)‪ :‬به هدف غایي و نهایي از انجام یک کار گفته ميشود؛ مانند «برنده‬
‫شدن» در یک بازی فوتبال‬
‫‪( Goal o‬هدف)‪ :‬به اهداف کوتاهمدتي که برای رسیدن به هدف نهایي تعریف ميشوند گفته‬
‫ميشود؛ مانند «گل زدن» در بازی فوتبال برای رسیدن به «برنده شدن»‬
‫‪( Objective o‬هدف عینی‪/‬مأموریت)‪ :‬اهداف قابلمشاهده که برای رسیدن به ‪Goal‬ها‬
‫تعریف ميشوند؛ مثالً برای گل زدن «باید در تیم چینش مناسبي داشت»‪.‬‬
‫‪( Policy o‬خط مشی)‪ :‬سیاستهایي که باید برای رسیدن به اهداف برنامهریزی شوند؛ مانند‬
‫«تأمین بودجه تیم»‪« ،‬آنالیز کردن قدرت تیم مقابل» و‪...‬‬

‫‪ -‬تعریف عمومی الگوریتم‪:‬‬


‫یک روش مؤثر برای حل یک مسأله که در قالب توالي محدودی‪2‬از دستورالعملها بیان شده است‪.‬‬

‫‪ -‬تعریف اختصاصی و کامپیوتری الگوریتم‪:‬‬


‫یک الگوریتم یک رویهی‪ 3‬محاسباتي خوببیانشده‪ 4‬است‪ ،‬که مقادیر یا مجموعهای‪ 5‬از مقادیر را به عنوان‬

‫‪1‬‬
‫‪Problem‬‬
‫‪2‬‬ ‫‪Finite‬‬
‫‪3‬‬ ‫‪Procedure‬‬
‫‪4 Well-defined‬‬
‫‪5 Set‬‬

‫‪5‬‬
‫ورودی‪ 1‬ميگیرد و مقادیر یا مجموعهای از مقادیر را به عنوان خروجي‪ 2‬تولید ميکند؛ بنابراین ميتواند گفت‪:‬‬
‫یک الگوریتم‪ ،‬یک توالي‪ 3‬از گامهای محاسباتي است که ورودی را به خروجي تبدیل ميکند‪.‬‬

‫ميتوان الگوریتم را ابزاری برای حل یک مسأله محاسباتي که جزئیات آن به خوبي بیان شده‪ ،‬دانست‪ ،‬و یا به‬
‫سادهترین بیان‪ :‬راهي برای کشف رابطهی بین ورودی و خروجي!‬

‫مثال‪ :‬فرض کنید‪ ،‬قرار است تعدادی عدد را مرتب کنید‪« .‬مسألهی مرتبسازی به شکل زیر تعریف ميشود»‪.‬‬

‫ورودی‪ :‬تواليای از ‪ n‬عدد ) 𝑛𝑎 ‪(𝑎1 , 𝑎2 , … ,‬‬

‫خروجي‪ :‬توالي مرتب اعداد ورودی ) 𝑛‪ (𝑎′1 , 𝑎′2 , … , 𝑎′‬با این شرط که‪:‬‬

‫) 𝑛‪(𝑎′1 ≤ 𝑎′ 2 ≤ ⋯ ≤ 𝑎′‬‬

‫برای مثال ورودی‪ )31, 41, 59, 26, 41, 58( :‬با توجه به الگوریتم مرتبسازی‪ ،‬خروجي زیر را‬
‫برميگرداند‪:‬‬

‫خروجي‪)26, 31, 41, 41, 58, 59( :‬‬

‫به آن توالي ورودی در اصطالح یک «نمونه»‪ 4‬از مسأله مرتبسازی گفته ميشود‪ .‬در کل یک نمونه از یک‬
‫مسأله شامل ورودیهایي است که نیاز دارند راهحلِ‪5‬مسأله روی آنها اعمال شود‪.‬‬

‫‪6‬‬
‫از آنجا که بسیاری از برنامهها از مرتبسازی به عنوان گام میاني استفاده ميکنند‪ ،‬الگوریتمهای مرتبسازی‬
‫یکي از عملیات پایهای و اساسي در علم کامپیوتر‪7‬هستند؛ بنابراین در این کتاب تعدادی الگوریتم مرتبسازیِ‬
‫خوب مورد بررسي قرار گرفته است‪.‬‬

‫اینکه کدام الگوریتمِ مرتبسازی برای یک کاربرد خاص مناسب است‪ ،‬بستگي دارد به‪:‬‬

‫‪ .1‬تعداد آیتمهایي که قرار است مرتب شوند‪.‬‬

‫‪1‬‬ ‫‪Input‬‬
‫‪2‬‬ ‫‪Output‬‬
‫‪3 Sequence‬‬
‫‪4‬‬
‫‪Instance‬‬
‫‪5 Solution‬‬
‫‪6 Sorting Algorithms‬‬
‫‪7 Computer Science‬‬

‫‪6‬‬
‫‪ .2‬آیتمهایي که از قبل مرتب شده بودهاند‪.‬‬
‫‪ .3‬محدودیتهای‪ 1‬احتمالي که روی آیتمها وجود دارد‪.‬‬
‫‪6‬‬
‫‪ .4‬معماری‪ 2‬کامپیوتر و نوع دستگاه ذخیرهسازی‪3‬که استفاده ميشود؛ مانند رَم‪4‬یا دیسک‪5‬یا نوار‪.‬‬

‫‪ -‬الگوریتم صحیح‪:‬‬
‫به الگوریتمي که بهازای هر نمونه از ورودی‪ ،‬یک خروجي صحیح در پایان‪7‬ارائه کند‪ ،‬الگوریتم صحیح‪ 8‬گفته‬
‫ميشود‪ .‬در اصطالح گفته ميشود‪ :‬یک الگوریتم صحیح‪ ،‬مسأله محاسباتي مدنظر را «حل»‪ 9‬ميکند‪ .‬یک‬
‫‪11‬‬
‫الگوریتم ناصحیح ممکن است بهازای برخي ورودیها هیچ پاسخي‪10‬برنگرداند و یا یک پاسخ اشتباه‬
‫برگرداند‪ .‬بر خالف آنچه انتظار دارید الگوریتمهای ناصحیح ميتوانند گاهي مفید واقع شوند‪ ،‬البتّه اگر‬
‫نرخخطای‪12‬آنها را کنترل کنیم‪.‬‬

‫‪14‬‬
‫یک الگوریتم ميتواند به زبان انگلیسي یا در قالب یک برنامهی کامپیوتری‪13‬و یا حتي در قالب یک طراحي‬
‫سختافزاری‪15‬توصیف شده باشد‪ .‬تنها محدودیت این است که توصیف‪16‬باید یک بیان دقیق از روال محاسباتي‬
‫که باید انجام شود‪ ،‬ارائه کند‪.‬‬

‫برخی مسائل که با الگوریتمهای این کتاب‪ ،‬قابل حل هستند‪:‬‬ ‫‪-1-2‬‬


‫تحلیل ژنهای روی ‪ DNA‬انسان که در پروژه ژن انساني‪ 17‬کاربرد فراواني داشته‬ ‫‪-1-6-1‬‬
‫است‪.‬‬
‫اینترنت دسترسي افراد به حجم عظیمي از اطالعات را آسان کرده‪ ،‬امّا مدیریت و‬ ‫‪-1-6-2‬‬
‫نگهداری این حجم از داده چالشي است که نیاز به الگوریتمهای پیچیده دارد‪ ،‬همینطور یافتن‬

‫‪1‬‬ ‫‪Restrictions‬‬
‫‪2‬‬ ‫‪Architecture‬‬
‫‪3 Storages Devices‬‬
‫‪4 Main Memory‬‬
‫‪5 Disk‬‬
‫‪6 Tape‬‬
‫‪7 Half‬‬
‫‪8 Correct‬‬
‫‪9 Solve‬‬
‫‪1 Answer‬‬ ‫‪0‬‬
‫‪1 Incorrect‬‬ ‫‪1‬‬
‫‪1 Error Rate‬‬ ‫‪2‬‬
‫‪1 Computer Program‬‬ ‫‪3‬‬
‫‪1 Design‬‬ ‫‪4‬‬
‫‪1 Hardware‬‬ ‫‪5‬‬
‫‪1 Specification‬‬ ‫‪6‬‬
‫‪1 Human Genome Project‬‬ ‫‪7‬‬

‫‪7‬‬
‫یک مسیر خوب بین ‪ Client‬و ‪ Server‬یک چالش دیگر به حساب ميآید که نیاز به‬
‫الگوریتمهای خاص خود دارد‪.‬‬
‫تجارت الکترونیک امکان ارائه کاال و خدمات به صورت الکترونیکي را فراهم کرده‬ ‫‪-1-6-3‬‬
‫است امّا چالشهایي مانند حفظ حریم خصوصي اشخاص (از قبیل شماره کارت اعتباری‪،‬‬
‫پسوردها و ‪ )...‬چالشي است که نیاز به الگوریتمهای خاص خود دارد‪.‬‬
‫شرکتهای تجاری مانند یک شرکت نفت (که نیاز به بهترین جا برای حفر چاه‬ ‫‪-1-6-4‬‬
‫دارد)‪ ،‬برای یافتن بهترین راهحلها جهت کسب سود بیشتر با الگوریتمهای خاص خود درگیرند‬
‫و یا حتي یک کاندیدای انتخابات سیاسي نیاز دارد بداند در چه کمپینهایي بیشتر هزینه کند‪ ،‬تا‬
‫شانس برنده شدن در انتخابات‪1‬را افزایش دهد‪.‬‬
‫مسائلي مانند یافتن کوتاهترین مسیر بین دو ‪ Node‬در یک شبکه‪ ،‬مسائل پرکاربردی‬ ‫‪-1-6-5‬‬
‫هستند که الگوریتمهای فراواني برای آنها ارائه شده است‪.‬‬
‫حتي مسأله سادهای مانند لیست کردن قطعات تشکیلدهندهی یک قطعه به شرط اینکه‬ ‫‪-1-6-6‬‬
‫هر قطعه فرزند‪ ،‬خود از قطعات دیگری تشکیل شده باشد‪ ،‬یک مسأله چالشي است که نیاز به‬
‫الگوریتمهای خاص خود دارد‪.‬‬

‫ساختمانهای داده‪2‬مورد بحث در این کتاب‪:‬‬ ‫‪-1-3‬‬


‫یک ساختمان داده روشي برای ذخیرهکردن و سازماندهي دادهها جهت آسانسازی دسترسي به آنها و ویرایش‬
‫آنهاست‪ .‬همیشه یک نوع ساختمان داده برای همین اهداف پاسخگو نیست؛ بنابراین‪ ،‬دانستن نقاط قوّت و‬
‫محدودیتهای ساختمان دادهها بسیار مهم است‪ .‬در این کتاب ساختمان دادههای مختلفي مورد استفاده قرار‬
‫ميگیرند‪.‬‬

‫تکنیک‪:‬‬ ‫‪-1-4‬‬
‫هرچند این کتاب ميتواند مانند یک «کتاب آشپزی»‪3‬برای الگوریتمها مورد استفاده قرار بگیرد امّا‪ ،‬بههرحال‬
‫ممکن است شما با مسألهای مواجه شوید که نميتوانید به راحتي یک الگوریتم از‪-‬پیش‪-‬منتشر‪-‬شده برای آن‬
‫پیدا کنید‪( .‬مانند بسیاری از مسائل و تمرینهای این کتاب)‪.‬‬

‫‪1‬‬ ‫‪Election‬‬
‫‪2‬‬ ‫‪Data Structures‬‬
‫‪3 Cookbook‬‬

‫‪8‬‬
‫این کتاب به شما تکنیکهای طراحي و تحلیل الگوریتم (یعني ماهیگیری) را یاد ميدهد؛ بنابراین شما ميتوانید‬
‫الگوریتمهای دلخواه خود را توسعه داده و نشان دهید که پاسخ صحیحي برميگردانند و کارایي آنها را نیز‬
‫درک کنید‪.‬‬

‫‪1‬‬
‫مسائل سخت‪:‬‬ ‫‪-1-5‬‬
‫اکثر این کتاب دربارهی الگوریتمهای کارا‪ 2‬است‪ .‬معیار‪ 3‬معمول ما برای کارایي‪« ،‬سرعت»‪ 4‬است؛ یعني چقدر‬
‫طول ميکشد تا یک الگوریتم نتیجهاش را تولید کند‪.‬‬

‫‪ -‬مسائل ‪ :NPC‬مسائلي هستند که هیچ راهحل کارایي برای آنها قابل تصور نیست‪ .‬به این مسائل در‬
‫اصطالح ‪ NPC‬یا ‪ NP-Complete‬گفته ميشود‪.‬‬
‫‪ -‬مسائل‪ :NP‬دسته مسائلي هستند که نميتوان در یک زمان چندجملهای‪ ،‬یک پاسخ قطعي برای آن پیدا‬
‫کرد‪ ،‬امّا اگر یک پاسخ کاندید برای آنها ارائه شود ميتوان‪ ،‬در یک زمان چندجملهای صحّت آن‬
‫پاسخ را تأیید یا رد نمود؛ مانند اینکه نميدانیم فرضاً با ‪ 10‬میلیون تومان پول چه شغلي راهاندازی کنیم‬
‫که به سوددهي بینجامد‪.‬‬
‫‪ -‬مسائل ‪ 5:P‬دسته مسائلي هستند که ميتوان در یک زمان چندجملهای‪ ،‬برای آن یک راهحل قطعي پیدا‬
‫کرد‪.‬‬

‫تمرین‪:‬‬ ‫‪-1-6‬‬
‫‪ -1‬دربارهی قانون مور تحقیق کنید‪.‬‬
‫‪ -2‬یک مثال از دنیای واقعي بزنید که نیاز به مرتبسازی داشته باشد و یک مثال از دنیای واقعي که نیاز به‬
‫مسیر پوشا داشته باشد‪.‬‬
‫پاسخ‪ :‬مانند دریافت حقوق بازنشستگان که بر اساس حروف الفبا مرتب شدهاند و یا مراحل پخت یک‬
‫غذا که حتماً باید به ترتیب انجام شوند‪.‬‬
‫مسیر پوشا هم مانند خرید کردن که ميتوان خرید لوازم را طوی انجام داد که ابتدا آنهایي که در یک‬
‫مسیر و به ترتیب هستند انجام شوند و بعد مابقي و یا مسافرت رفتن از یک شهر به شهر دیگر که ترتیب‬

‫‪1‬‬
‫‪Hard Problems‬‬
‫‪2‬‬ ‫‪Efficient‬‬
‫‪3‬‬ ‫‪Measure‬‬
‫‪4 Speed‬‬
‫‪5‬‬
‫‪Polynomial‬‬

‫‪9‬‬
‫در آن رعایت ميشود‪ .‬و یا خرید ماهیانه پوشاک و مواد غذایي و یا پرداخت قبوض و ‪ ...‬که همه را‬
‫باید با یک مبلغ مشخص انجام و پوشش داد‪.‬‬
‫‪ -3‬به جز سرعت چه معیار دیگری برای کارایي سراغ دارید که ممکن است شخص از آن در دنیای واقعي‬
‫استفاده کند‪.‬‬
‫پاسخ‪ :‬هزینه‪ ،‬کیفیّت‪ ،‬فضا و مکان و‪...‬‬
‫‪ -4‬یک ساختمان داده که قبالً با آن آشنا شدهاید انتخاب کنید و دربارهی نقاط قوّت و محدودیتهای آن‬
‫بحث کنید‪( .‬مثال‪ :‬دربارهی ساختمان داده شئ‪1‬صحبت کنید)‬
‫پاسخ‪ :‬مانند آرایهها‪ ،‬پشته‪ ،‬لیست پیوندی‪ ،‬متغیر‪ 2‬عددی‪ ،‬متغیر رشتهای و ‪...‬‬
‫یادآوری‪:‬‬

‫‪LIFO: Last Input Frist Output‬‬

‫ساختمان دادهای که در آن‪ ،‬آخرین ورودی‪ ،‬اولین خروجي است؛ مانند پشته‬

‫‪FIFO: First Input First Output‬‬

‫ساختمان دادهای که در آن‪ ،‬اولین ورودی‪ ،‬اولین خروجي است؛ مانند نوارکاسِت یا صف نانوایي‬

‫‪ -5‬مسأله کوتاهترین مسیر و مسأله فروشنده دورهگرد چه شباهتها و چه تفاوتهایي دارند؟‬


‫پاسخ‪ :‬شباهتها‪ :‬در هردو بحث کوتاهبودن مسیر بر اساس وزن یا همان مسافت مطرح است‪.‬‬
‫تفاوتها‪ :‬نقاط آغاز و پایان در مسأله فروشنده دورهگرد یکي است و همچنین پوشابودن مسیر در این‬
‫مسأله مطرح است در حاليکه در مسأله کوتاهترین مسیر‪ ،‬لزوماً اینطور نیست‪.‬‬
‫‪ -6‬مسألهای در دنیای واقعي بیان کنید که فقط بهترین راهحل است که پاسخ مسأله است‪ ،‬همینطور‬
‫مسألهای مثال بزنید که یک راهحل تقریبي‪ 3‬نیز پاسخگو است‪.‬‬
‫پاسخ‪ :‬مانند استفاده از روش شیميدرماني که در بعضي از موارد سرطاني‪ ،‬بهترین راهحل است و یا‬
‫شرکت در مزایده و یا آتشنشاني که از بهترین راهحلها برای خاموش کردن انواع آتشسوزیها‬
‫استفاده ميکند‪.‬‬

‫‪1‬‬ ‫‪Object‬‬
‫‪2‬‬ ‫‪Float‬‬
‫‪3 Approximately‬‬

‫‪10‬‬
‫‪1‬‬
‫پردازش موازی‪:‬‬ ‫‪-1-7‬‬
‫تا سالها ما روی افزایش سرعتِ کالک‪ 2‬پردازشگر حساب ميکردیم امّا محدودیتهای فیزیکي‪ 3‬باعث‬
‫ميشود این افزایش سرعت تا حد مشخصي ممکن باشد؛ برای مثال یکي از این محدودیتها این است که اگر‬
‫سرعت کالک بیش از حد افزایش پیدا کند‪ ،‬دمای پردازشگر به حدی باال خواهد رفت که خطر ذوبشدن‬
‫قطعات را درپي دارد؛ بنابراین امروزه برای محاسبات سنگین بهجای افزایش سرعت کالک از چندین هسته‪ 4‬در‬
‫پردازشگر استفاده ميشود‪ .‬این حالت را ميتوان چند کامپیوتر در یک چیپِ‪ 5‬واحد تصور کرد و در اصطالح‬
‫به آن «کامپیوتر موازی»‪ 6‬گفته ميشود‪ .‬برای اینکه از کامپیوترهای چند هستهای بهترین کارایي را استخراج‬
‫کنیم به الگوریتمهایي نیاز داریم که به آنها الگوریتمهای موازی یا الگوریتمهای چندرشتهای‪ 7‬گفته ميشود و‬
‫در فصل ‪ 27‬در این زمینه بحث خواهد شد‪.‬‬

‫الگوریتم بهعنوان یک فناوری‪:‬‬ ‫‪-1-8‬‬


‫در نظر بگیریدکامپیوترها بهطور نامحدود‪ ،‬سریع و حافظهی آنها آزاد است‪ .‬آیا دلیلي برای مطالعه الگوریتمها‬
‫وجود ميداشت؟ پاسخ بله است‪ .‬اگر بر فرض محال این دو محدودیت را نداشته باشیم امّا روش پیشنهادی در‬
‫این الگوریتم باالخره باید نمایش‪ 8‬داده شود و از آن مهمتر پیادهسازی شود و همینطور ثابت شود که این روش‬
‫پاسخ صحیحي برای مسأله است‪ ،‬اگر راهحل پیشنهادی بیشازحد پیچیده‪ 9‬باشد‪ ،‬در پیادهسازی‪10‬یا نمایش یا‬
‫اثبات درستي آن با مشکل مواجه خواهیم شد‪ .‬البتّه که کامپیوترها بهطور نامحدود‪ ،‬سریع و حافظهی آنها‬
‫بينهایت نیست؛ بنابراین محاسبه زمان و فضای حافظه اجرای یک الگوریتم یک منبع محدود‪ 11‬به حساب‬
‫ميآید‪ .‬شما باید از این منابع بهطور هوشمندانه استفاده کنید و از الگوریتمهایي استفاده کنید که در بحث زمان و‬
‫فضا کارا هستند‪.‬‬

‫تمرین‪ :‬دربارهی مسأله فضا‪-‬زمان‪12‬نیوتن تحقیق کنید‪.‬‬

‫‪1‬‬
‫‪Parallelism‬‬
‫‪2‬‬ ‫‪Clock‬‬
‫‪3‬‬ ‫‪Physical Limitations‬‬
‫‪4 Core‬‬
‫‪5 Chip‬‬
‫‪6 Parallel Computer‬‬
‫‪7 Multithreaded Algorithms‬‬
‫‪8 Demonstrate‬‬
‫‪9 Complex‬‬
‫‪1 Implementation‬‬ ‫‪0‬‬
‫‪1‬‬ ‫‪1‬‬
‫‪Resource Bounded‬‬
‫‪1 Time Space‬‬ ‫‪2‬‬

‫‪11‬‬
‫کارایی‪:1‬‬ ‫‪-1-9‬‬
‫الگوریتمهای مختلفي که برای حل یک مسأله مشابه پیشنهاد ميشود‪ ،‬معموالً در «کارایي» به شدّت با هم‬
‫متفاوتند‪ .‬این تفاوتها زماني که سختافزارها و نرمافزارهای دیگر مورد استفاده برای اجرای آنها با هم متفاوت‬
‫باشد بیشتر نیز خواهد شد؛ به عنوان مثال‪ ،‬در فصل ‪ 2‬ما دو الگوریتم برای مرتبسازی خواهیم دید که اولي به نام‬
‫«مرتبسازی درجي»‪ 2‬شناخته ميشود که این الگوریتم زمان ‪ C1n2‬را برای مرتبسازی ‪ n‬آیتم نیاز دارد‪C1( ،‬‬
‫عدد ثابتي است که وابسته به ‪ n‬نیست) که ميگوییم این الگوریتم با ‪ n2‬متناسب‪ 3‬است‪ ،‬دومین الگوریتم‬
‫«مرتبسازی ادغامي»‪ 4‬است که زمان ‪ C2nlogn‬دارد (‪ C2‬یک عدد ثابت غیر وابسته به ‪ n‬است و منظور از‬
‫‪ logn( log2n ،logn‬در مبنای ‪ )2‬است)‪ .‬مرتبسازی درجي معموالً عدد ثابت کمتری نسبت به مرتبسازی‬
‫ادغامي دارد (یعني ‪ C1 < C2‬است)‪ .‬خواهیم دید که عدد ثابت‪ ،‬تأثیر‪ 5‬بسیار کمي روی زمان دارد؛ بنابراین‬
‫ميتوان زمان اجرای‪ 6‬مرتبسازی درجي را ‪ n‬و زمان اجرای مرتبسازی ادغامي را ‪ logn‬تصور کرد‪ .‬هرچند‬
‫مرتبسازی درجي در تعداد کم سریعتر عمل ميکند؛ برای مثال فرض کنید یک کامپیوتر قوی (کامپیوتر ‪ A‬با‬
‫قدرت پردازش ‪ 10‬میلیارد دستورالعمل در ثانیه‪ )7‬الگوریتم مرتبسازی درجي را اجرا ميکند‪ ،‬و یک کامپیوتر‬
‫ضعیفتر (کامپیوتر ‪ B‬با قدرت پردازش ‪ 10‬میلیون دستورالعمل در ثانیه) الگوریتم مرتبسازی ادغامي را اجرا‬
‫ميکند‪ .‬هر دو قادر هستند ‪ 10‬میلیون عدد را مرتب کنند‪ ،‬در این حالت خواهیم دید که کامپیوتر ‪ 1000 ،A‬برابر‬
‫سریعتر از کامپیوتر ‪ B‬عمل خواهد کرد‪ ،‬در حاليکه نميتوان از این نتیجه گرفت که الگوریتم مرتبسازی‬
‫درجي سریعتر از الگوریتم مرتبسازی ادغامي عمل ميکند‪.‬‬

‫‪8‬‬
‫الگوریتمها و دیگر فناوریها‪:‬‬ ‫‪-1-10‬‬
‫مثال باال نشان داد که ما باید الگوریتمها را مانند سختافزار کامپیوتر بهعنوان یک فناوری در نظر بگیریم‪.‬‬
‫همانطور که انتخاب یک سختافزار سریع در کارایي سیستم موثر است‪ ،‬انتخاب الگوریتمهای کارا نیز در‬
‫کارایي سیستم تأثیر فراواني دارد‪ .‬همانطور که پیشرفتهای سریع در دیگر فناوریهای مرتبط با کامپیوتر پیش‬
‫ميآید‪ ،‬در الگوریتمها نیز پیشرفتهای سریع و مهمي به وجود ميآید‪.‬‬

‫ممکن است الزم باشد الگوریتمها را با توجه به دیگر فناوریهای پیشرفته مانند موارد زیر انتخاب کنیم‪:‬‬

‫‪1‬‬ ‫‪Efficiency‬‬
‫‪2‬‬ ‫‪Insertion Sort‬‬
‫‪3 Proportional‬‬
‫‪4 Merge Sort‬‬
‫‪5 Factor‬‬
‫‪6 Running Time‬‬
‫‪7 10 billion instructions per second‬‬
‫‪8 Algorithms and other Technologies‬‬

‫‪12‬‬
‫‪-1-15-1‬معماریهای پیشرفته کامپیوتر و تکنولوژیهای ساخت آنها‬
‫‪3‬‬
‫‪ -1-15-2‬رابطهای کاربری گرافیکي‪ 1‬با جلوههای‪ 2‬زیبا و کاربری آسان‬
‫‪4‬‬
‫‪-1-15-3‬سیستمهای شيگرا‬
‫‪-1-15-4‬فناوریهای یکپارچه‪ 5‬وب‬
‫‪-1-15-5‬شبکههای سریع (کابلي و بيسیم)‬

‫برای مثال یک سرویس تحت وب را تصور کنید که یک مسیر را بین دو نقطه یافته و به راننده پیشنهاد ميکند‬
‫این سرویس عالوه بر اینکه به الگوریتمهای خاصي برای یافتن کوتاهترین مسیر نیاز دارد با الگوریتمهای‬
‫دیگری برای «رِندِر کردن»‪(6‬آماده کردن خروجي نهایي) نقشه و تشخیص آدرسها و اماکن و دیگر الگوریتمها‬
‫درگیر است‪ .‬داشتن یک الگوریتم پایه و تکنیکهای طراحي الگوریتم یکي از ویژگيهایي است که‬
‫برنامهنویس ماهر‪ 7‬را در برنامهنویس تازهکار‪ 8‬متمایز ميکند‪ .‬امّا این ویژگي کافي نیست‪ ،‬آشنایي با دیگر‬
‫فناوریها که با الگوریتمها درگیر است نیز برای یک برنامهنویس ماهر الزم است‪.‬‬

‫هرچند ممکن است شما کارهای خود را بدون دانستن الگوریتمها انجام دهید‪ ،‬امّا داشتن یک پیشزمینهی‬
‫‪11‬‬
‫خوب‪ 9‬دربارهی الگوریتمها باعث ميشود‪ ،‬بهتر و بیشتر از قبل کار‪10‬انجام دهید ‪.‬‬

‫تمرین‪:‬‬ ‫‪-1-11‬‬
‫‪ -1‬یک مثال از یک برنامه کاربردی بزنید که نیاز به محتوای الگوریتمي در سطح اپیلیکیشن دارد و در‬
‫مورد الگوریتمهایي که در این زمینه مشکل خاص دارند‪ ،‬بحث کنید‪.‬‬
‫پاسخ‪ :‬مانند آپدیت کردن ساعت کنار ویندوز و یا نوع نمایش سهبُعدی پنجرهها در سطح اپلیکیشن‬
‫‪ -2‬فرض کنید قرار است در یک ماشین مشابه الگوریتمهای درجي و ادغامي را اجرا کنیم و بهازای ‪n‬‬
‫ورودی‪ ،‬الگوریتمدرجي ‪ 8n2‬گام طي کند و الگوریتم ادغامي𝑛‪ .64nlog‬برای چه مقادیری از ‪n‬‬
‫الگوریتمهای درجي بهتر از الگوریتمهای ادغامي عمل ميکنند؟‬

‫‪1‬‬ ‫‪Graphical User Interfaces = UFI: User-Friendly Interface‬‬


‫‪2‬‬ ‫‪Effects‬‬
‫‪3 Easy-to-Use‬‬
‫‪4 Object-Oriented System‬‬
‫‪5 Integrated‬‬
‫‪6 Rendering‬‬
‫‪7 Skilled Programmer‬‬
‫‪8 Novice Programmer‬‬
‫‪9 Good Background‬‬
‫‪1 Task‬‬ ‫‪0‬‬
‫‪1 Accomplish‬‬ ‫‪1‬‬

‫‪13‬‬
‫‪ -3‬کوچکترین عدد ‪ n‬در الگوریتمي که زمان اجرای آن ‪ 100n2‬بار است‪ ،‬و الگوریتمي که زمان‬
‫اجرای آن ‪ 2n‬است چیست‪ ،‬به شرطي که الگوریتم اول سریعتر از الگوریتم دوم عمل کند؟ (هر دو در‬
‫یک ماشین مشابه اجرا ميشوند‪).‬‬
‫پاسخ‪ :‬به جای ‪ n‬اعداد ‪ 1‬و بیشتر را قرار دهید تا زماني که ‪ 100n2‬کوچکتر ‪ 2n‬از شود‪ .‬خواهیم‬
‫دید که زماني که ‪ n‬برابر با ‪ 15‬باشد‪ ،‬اولي ‪ 22500‬خواهد شد و دومي ‪ 32768‬اما اگر ‪ n‬را ‪ 14‬بگیریم‪،‬‬
‫اولي ‪ 16600‬خواهد شد و دومي ‪ .16384‬پس کوچکترین ‪ ،n‬عدد که شرط مسأله را تأمین کند‪15 ،‬‬
‫خواهد بود‪.‬‬

‫‪14‬‬
‫فصل دوم‬

‫آغاز کار با الگوریتمها‬

‫مقدمه‪:‬‬ ‫‪-2-1‬‬
‫این فصل شما را با چارچوبي که ما در کتاب استفاده خواهیم کرد‪ ،‬آشنا ميکند تا یاد بگیرید چطور دربارهی‬
‫طراحي و تحلیل الگوریتمها بیندیشد‪:‬‬

‫الگوریتم مرتبسازی درجی‪:‬‬ ‫‪-2-2‬‬


‫اوّلین الگوریتم‪ ،‬مرتبسازی درجي است که مسأله مطرح شده در فصل قبل را حل ميکند‪:‬‬

‫ورودی‪ :‬یک توالي از ‪ n‬عدد ) 𝑛𝑎 ‪(𝑎1 , 𝑎2 , … ,‬‬

‫خروجي‪ :‬توالي مرتبي به شکل ) 𝑛‪ (𝑎′1 ≤ 𝑎′ 2 ≤ ⋯ ≤ 𝑎′‬بهطوریکه) 𝑛‪(𝑎′1 , 𝑎′2 , … , 𝑎′‬‬

‫اعدادی که قرار است مرتب کنیم به نام «کلید»‪ 1‬نیز شناخته ميشوند‪ .‬اعداد ورودی به شکل یک آرایهی ‪n‬‬
‫عنصری به ما داده ميشوند‪.‬‬

‫در این کتاب ما الگوریتمها را در غالب برنامههایي که به شکل «شبهکد»‪ 2‬نوشته شدهاند توصیف‪ 3‬ميکنیم‪.‬‬
‫شبهکدها شبیه زبانهای ‪ ،C++ ،C‬جاوا‪ ،‬پایثون‪4‬و پاسکال هستند‪ .‬اگر با یکي از این زبانها آشنا باشید با کمي‬
‫تالش ميتوانید شبهکدها را با آن زبان پیادهسازی کنید‪.‬‬

‫تفاوت شبهکد با کد واقعي‪ 5‬این است که در شبهکد شفافترین روش به شکلي مختصر و مفید برای هر‬
‫الگوریتم بیان ميشود‪ .‬تفاوت دیگر شبهکد با کد واقعي این است که شبهکد معموالً به چالشهای‪ 6‬مهندسي‬

‫‪1‬‬ ‫‪Key‬‬
‫‪2‬‬ ‫‪Pseudo Code‬‬
‫‪3 Describe‬‬
‫‪4‬‬
‫‪Python‬‬
‫‪5‬‬ ‫‪Real Code‬‬
‫‪6‬‬ ‫‪Issues‬‬

‫‪15‬‬
‫نرمافزار‪ 1‬چندان توجهي ندارد‪ .‬چالشهایي مانند انتزاعدادهای‪ 2،‬پیمانهای بودن «ماژوالریتي»‪ 3‬و برخورد با‬
‫خطاها‪4‬اغلب در شبهکد نادیده گرفته‪ 5‬ميشود تا ماهیّت‪ 6‬الگوریتم شفافتر‪ ،‬مختصرتر بیان شود‪.‬‬

‫ما با الگوریتم درجي شروع ميکنیم که یک الگوریتم کارا‪ 7‬برای مرتبسازی تعداد کمي عنصر‪ 8‬است‪.‬‬
‫مرتبسازی درجي روشي است که بسیاری از افراد برای مرتبکردن تعدادی کارت در بازی کارت استفاده‬
‫ميکنند‪ .‬اگر به روشي که افراد طي ميکنند‪ ،‬دقت کنیم آنها کارتها را روی میز پخش ميکنند و سپس‬
‫دست چپ خود را که در ابتدا خالي‪ 9‬است بهعنوان محلي برای مرتبسازی در نظر ميگیرند سپس در هر بار‬
‫یک کارت از روی میز برداشته و در محل صحیح‪ 10‬خود در دست چپشان درج ميکنند‪ .‬هر بار که یک‬
‫کارت برداشته ميشود برای یافتن محل صحیح آن از چپ به راست کارتهای موجود در دست چپ با کارت‬
‫فعلي مقایسه ميشود تا به محلي برسیم که کارت موردنظر بزرگتر از آن جایگاه و کوچکتر از جایگاه بعدی‬
‫آن است‪.‬‬

‫شکل ‪( 2-1‬الگوریتم مرتبسازی درجي شبیه به مرتبکردن کارتها در بازی کارت یا پاسور است)‬

‫‪1‬‬ ‫‪Software-Engineering‬‬
‫‪2‬‬ ‫منظور از انتزاع‪ ،‬موهومي و مفهومي بودن یک موضوع است (خیلي قابل لمس نیست) ‪Data Abstraction:‬‬
‫‪3‬‬ ‫‪Modularity‬‬
‫‪4‬‬‫‪Error Handing‬‬
‫نادیده گرفتن ‪5 Ignored‬‬

‫‪6‬‬ ‫‪Essence‬‬
‫‪7‬‬ ‫‪Efficient‬‬
‫‪8 Element‬‬
‫‪9 Empty‬‬
‫‪1 Correct Position‬‬ ‫‪0‬‬

‫‪16‬‬
‫ما شبهکد را در غالب یک رویه‪(1‬یا تابع) به نام‪ Insertion-Sort‬ارائه ميکنیم که بهعنوان پارامتر‪ 2‬ورودی‬
‫یک آرایه به شکل ]𝑛 ‪ 𝐴 [1. .‬دریافت ميکند که شامل توالي به طول ‪ n‬از اعدادی است که قرار است مرتب‬
‫شوند‪ .‬در کد ما طول آرایهی ‪ A‬به شکل ‪ A.Length‬نمایش داده شده است‪ .‬این الگوریتم اعداد ورودی را‬
‫درجا‪ 3‬مرتب ميکند؛ یعني همان آرایهی ‪ A‬را بدون نیاز به آرایهی دیگری آنقدر جابهجا ميکند تا مرتب‬
‫شوند‪ .‬شکل زیر مثالي از مرتبسازی درجي است و روالي را که طي ميشود‪ ،‬نشان ميدهد‪.‬‬

‫شبهکد زیر معروف به الگوریتم مرتبسازی درجي است‪.‬‬

‫مثال‪ :‬جدول تغییرات متغیرها فرضاً برای آرایهی } ‪:𝐴 = { 5, 2, 4, 6, 1, 3‬‬

‫‪1‬‬ ‫‪Procedure‬‬
‫‪2‬‬ ‫‪Parameter‬‬
‫‪3 In place‬‬

‫‪17‬‬
‫جدول تغییرات متغیرها‬
‫‪A‬‬ ‫‪J‬‬ ‫‪i‬‬ ‫‪Key‬‬
‫}‪{5,2,4,6,1,3‬‬ ‫‪1‬‬ ‫‪0‬‬ ‫‪2‬‬
‫}‪{5,5,4,6,1,3‬‬ ‫‪-1‬‬
‫}‪{2,5,4,6,1,3‬‬ ‫‪2‬‬ ‫‪1‬‬ ‫‪4‬‬
‫}‪{2,5,5,6,1,3‬‬ ‫‪0‬‬
‫}‪{2,4,5,6,1,3‬‬ ‫‪3‬‬ ‫‪2‬‬ ‫‪6‬‬
‫‪4‬‬ ‫‪1‬‬
‫}‪{2,4,5,6,6,3‬‬ ‫‪3‬‬
‫}‪{2,4,5,5,6,3‬‬ ‫‪1‬‬
‫}‪{2,4,4,5,6,3‬‬ ‫‪0‬‬
‫}‪{2,2,4,5,6,3‬‬ ‫‪-1‬‬
‫}‪{1,2,4,5,6,3‬‬ ‫‪5‬‬ ‫‪3‬‬
‫}‪{1,2,4,5,6,6‬‬ ‫‪4‬‬
‫}‪{1,2,4,5,5,6‬‬ ‫‪3‬‬
‫}‪{1,2,4,4,5,6‬‬ ‫‪2‬‬
‫}‪{1,2,3,4,5,6‬‬ ‫‪1‬‬
‫‪0‬‬
‫توضیحات مربوط به الگوریتم باال‪:‬‬
‫‪ ‬اندیس ‪ j‬کارت فعلي که قرار است در جای خود در دست چپ درج شود‪ ،‬مشخص ميکند‪.‬‬
‫‪ ‬در هر دور از حلقه ‪ 𝐴[1. . 𝑗 − 1] ،for‬بخشي از آرایه است که تا االن مرتب شده است و بقیه آرایه در‬
‫]𝑛 ‪ 𝐴[𝑗 + 1. .‬قرار دارد‪.‬‬
‫‪ ‬حلقهی ‪ while‬برای شیفت دادن عناصر به یک خانه بعد از خود استفاده ميشود تا خانهی مربوط به عنصر‬
‫فعلي خالي ميشود‪.‬‬
‫‪ ‬یادآوری‪ :‬هر حلقه شامل بخشهای زیر است‪:‬‬

‫)‪for(initialization, maintenance & termination, Iteration-Expression‬‬


‫{‬
‫‪//… body‬‬
‫}‬

‫‪ -1‬عملیات آغازی که در اصطالح به آن ‪Initialization‬گفته ميشود‪.‬‬

‫‪18‬‬
‫‪ -2‬شرط اجرای حلقه که در اصطالح به آن ‪ Maintenance‬به معني حفظ و نگهداری گفته ميشود‪.‬‬
‫‪ -3‬عملیات هر گام که در اصطالح به آن ‪ Iteration-Expression‬گفته ميشود‪.‬‬
‫‪ -4‬شرط پایان که در اصطالح به آن ‪ Termination‬گفته ميشود‪.‬‬
‫‪ -5‬بدنهی حلقه که حاوی کدهایي است که در صورت صحّت شرط‪ ،‬اجرا خواهد شد و در اصطالح به آن‬
‫‪ Body‬گفته ميشود‪.‬‬

‫تمرین‪:‬‬ ‫‪-2-3‬‬
‫‪ -1‬مانند شکل ‪ 2.2‬مدلي رسم کنید که عملیات الگوریتم مرتبسازی درجي را روی آرایه زیر نشان دهد‪.‬‬

‫} ‪𝐴 = { 31, 41, 59, 26, 41, 58‬‬

‫‪ -2‬تابع ‪ insertion-sort‬را طوری بنویسید که به جای مرتبسازی صعودی‪ ،‬مرتبسازی نزولي انجام‬
‫دهد‪.‬‬
‫‪ -3‬مسأله جستجو‪1‬را در نظر بگیرید‪:‬‬

‫ورودی‪ :‬توالي از ‪ n‬عدد به شکل )𝑛𝑎 ‪ 𝐴 = (𝑎1, 𝑎2, … ,‬و یک مقدار به نام ‪ V‬که در حال جستجوی آن‬
‫هستیم‪.‬‬

‫خروجي‪ :‬اندیس ‪ i‬بهطوریکه ]𝑖[𝐴 = 𝑉 یا مقدار ‪2NIL‬اگر ‪ V‬در آرایه پیدا نشود‪.‬‬

‫یک تابع برای جستجوی خطي‪3‬بنویسید که این مسأله را حل کند‪.‬‬

‫پاسخ‪:‬‬

‫‪1‬‬ ‫‪Searching Problem‬‬


‫‪2‬‬
‫صفر‬
‫‪3‬‬ ‫‪Linear Search‬‬

‫‪19‬‬
‫‪ -4‬فرض کنید دو آرایه باینری به طول ‪ n‬بیت به نام ‪ A‬و ‪ B‬داریم‪ .‬جمع هرکدام از خانههای دو آرایه را‬
‫در خانهی متناظر آنها در آرایه ‪ C‬ذخیره کنید و سپس آرایه ‪ C‬را چاپ کنید‪ .‬برای این مسأله یک تابع‬
‫تعریف کنید‪( .‬راهنما‪ :‬با توجه به اینکه ممکن است جمع دو عدد یک خانه اضافهتر نیاز داشته باشد‪،‬‬
‫آرایه ‪ C‬را ‪ n+1‬خانهای در نظر بگیرید‪).‬‬
‫پاسخ‪:‬‬

‫‪20‬‬
21
‫تحلیل الگوریتمها‪:‬‬ ‫‪-2-4‬‬
‫منظور از تحلیل‪1‬یک الگوریتم پیشبیني‪2‬منابع مورد نیاز الگوریتم است‪ .‬معموالً منابعي مانند حافظه‪3،‬پهنای باند‬
‫ارتباطي‪ 4،‬سختافزار کامپیوتر اصلي نگراني‪ 5‬ما هستند‪ ،‬امّا اغلباوقات زمان محاسبه‪ 6‬تنها چیزی است که ما‬
‫‪7‬‬
‫ميخواهیم اندازه بگیریم‪.‬‬

‫نکته‪ :‬منظور از ‪ Memory‬حافظه موقت و یا ‪ RAM‬ميباشد و منظور از ‪ Story‬حافظه جانبي و یا ‪Hard‬‬


‫‪ Disk‬است‪.‬‬

‫معموالً با تحلیل چند الگوریتم کاندید‪8‬برای یک مسأله ميتوانیم کاراترینشان را شناسایي کنیم‪9.‬ممکن است‬
‫تحلیل به این نتیجه برسد که بیش از یک کاندید قابل اعتماد‪10‬است‪ ،‬امّا اغلب ميتوانیم الگوریتمهای با سطح‬
‫پایینتر‪11‬را از رده خارج کنیم‪12.‬قبل از تحلیل یک الگوریتم باید یک مدل از فناوری پیادهسازی‪13‬الگوریتم که‬
‫در این کتاب استفاده کردهایم‪ ،‬ارائه کنیم؛ مدلي که منابع آن فناوری و هزینههای آن را مشخص کند‪ .‬در این‬
‫کتاب ما از یک پردازشگر‪14‬و ماشیني با حافظهی دسترسي تصادفي‪ )RAM(15‬برای مدل کردن محاسبات و‬
‫درک الگوریتم ها استفاده خواهیم کرد‪ .‬در مدل ‪ RAM‬دستورالعملها‪16‬یکي پس از دیگری پردازش ميشوند‬
‫و هیچ عملیات همزماني‪17‬اتفاق نميافتد‪ .‬مدل ‪ RAM‬شامل دستورالعملهایي است که در کامپیوترهای واقعي‬
‫وجود دارند؛ مانند دستورالعملهای محاسباتي‪(18‬جمع‪19،‬تفریق‪20،‬ضرب‪21،‬تقسیم‪22،‬باقیمانده‪23،‬جزءِصحیح‪24‬و‬

‫‪1‬‬ ‫‪Analyzing‬‬
‫‪2‬‬ ‫‪Predicting‬‬
‫‪3 Memory‬‬
‫‪4 Communication bandwidth‬‬
‫‪5 Concern‬‬
‫‪6 Computational time‬‬
‫‪7 Measure‬‬
‫‪8 Candidate‬‬
‫‪9 Identify‬‬
‫‪1 Viable‬‬ ‫‪0‬‬
‫‪1 Inferior Algorithms‬‬ ‫‪1‬‬

‫از رده خارج کردن =‪1 Discard‬‬ ‫‪2‬‬

‫‪1‬‬ ‫‪3‬‬
‫‪Implementation‬‬
‫‪1‬‬ ‫‪4‬‬
‫‪One Processor‬‬
‫‪1‬‬ ‫‪Random Access Machine 5‬‬
‫‪1‬‬ ‫‪6‬‬
‫‪Instructions‬‬
‫‪1‬‬ ‫‪7‬‬
‫‪Concurrent Operations‬‬
‫‪1‬‬ ‫‪8‬‬
‫‪Arithmetic‬‬
‫‪1‬‬ ‫‪9‬‬
‫‪Add‬‬
‫‪2‬‬ ‫‪0‬‬
‫‪Subtract‬‬
‫‪2‬‬ ‫‪1‬‬
‫‪Multiply‬‬
‫‪2‬‬ ‫‪2‬‬
‫‪Divide‬‬
‫‪2‬‬ ‫‪3‬‬
‫‪Remainder‬‬
‫‪ : Floor24‬منظور از کف یا جزءصحیح یک عدد اعشاری‪ ،‬بزرگترین عدد صحیح کوچکتر از آن عدد است؛ بهطورمثال کف عدد ‪ 5/7‬عدد ‪ 5‬ميشود‪.‬‬

‫‪22‬‬
‫سقف‪ 1‬و ‪ ،)...‬دستورالعملهای جابجایي داده‪( 2‬خواندن یا بارگذاری‪ 3،‬ذخیرهسازی‪ 4،‬کپي‪ )5‬و دستورالعملهای‬
‫کنترلي (دستورالعملهای شرطي‪ 6‬و انشعاب‪ 7‬غیر شرطي‪ 8،‬فراخواني و بازگشت‪ 9‬تودرتو)‪ .‬هر یک از این‬
‫دستورالعملها مقدار زماني ثابتي‪10‬نیاز دارد‪.‬‬

‫نمونه سؤال امتحان‪ :‬قطعه کد زیر مربوط به یک الگوریتم مرتبسازی است‪ ،‬آرایهی {‪ }4،2،1،10،9،7‬را با‬
‫توجه به کد مرتب کنید و در نهایت مشخص کنید قطعه کد مربوط به کدام الگوریتم مرتبسازی است؟ (رسم‬
‫جدول تغییرات متغیرها و شکل کلي مرتب شدن آرایه الزامي است)‪.‬‬

‫تحلیل الگوریتم مرتبسازی درجی‪:‬‬ ‫‪-2-5‬‬


‫زمانيکه الگوریتم مرتبسازی درجي نیاز دارد‪ ،‬به ورودی بستگي دارد؛ برای مثال‪ ،‬مرتبسازی ‪ 1000‬عدد‬
‫زمان بیشتری نسبت به مرتبسازی ‪ 3‬عدد صرف ميکند‪ .‬نکتهی دیگر اینکه این الگوریتم بهازای مقادیری که‬
‫مرتبتر هستند‪ ،‬زمان کمتری صرف ميکند‪ .‬عموماً زمانيکه توسط یک الگوریتم صرف ميشود‪ ،‬نسبت به‬
‫اندازهی ورودی رشد‪11‬ميکند؛ بنابراین مرسوم‪12‬است که زمان اجرای‪13‬یک برنامه را تابعي از اندازهی‬
‫ورودی‪14‬آن در نظر ميگیرند؛ بنابراین برای تحلیل الگوریتم باید ابتدا واژههای «زمان اجرا» و «اندازهی‬
‫ورودی»‪15‬را با دقت بیشتری‪16‬تعریف کنیم‪ .‬بهترین تعریف برای «اندازهی ورودی» به مسألهای که درحال تحلیل‬
‫هستیم‪ ،‬بستگي دارد؛ برای مثال در خیلي از مسائل مانند مرتبسازی اندازهی ورودی برابر است با تعداد‬
‫آیتمهای ورودی؛‪(17‬یعني اندازه ‪ n‬در مسائل مرتبسازی)‪ ،‬امّا در مسائل دیگر مانند ضرب دو عدد صحیح‪،‬‬
‫اندازهی ورودی عبارتاست از‪ :‬تعداد کل لیستهای‪18‬مورد نیاز برای نمایش اعداد ورودی در مبنای ‪.2‬‬

‫‪ : Ceiling1‬منظور از سقف یک عدد اعشاری‪ ،‬بزرگترین عدد صحیح بعد از آن عدد است؛ بهطور مثال سقف عدد ‪ 5/7‬عدد ‪ 6‬ميشود‪.‬‬
‫‪2‬‬ ‫‪Data movement‬‬
‫‪3‬‬ ‫‪Load‬‬
‫‪4 Store‬‬
‫‪5 Copy‬‬
‫‪6 Conditional‬‬
‫‪7 Branch‬‬
‫‪8 Unconditional‬‬
‫‪9 Call and return‬‬
‫‪1 Constant amount of time‬‬ ‫‪0‬‬
‫‪1 Grows‬‬ ‫‪1‬‬
‫‪1 Traditional‬‬ ‫‪2‬‬
‫‪1 Running time‬‬ ‫‪3‬‬
‫‪1 Function of the size of its input‬‬
‫‪4‬‬
‫‪1 Size of input‬‬ ‫‪5‬‬
‫‪1‬‬ ‫‪6‬‬
‫‪More carefully‬‬
‫‪1 Number of items the input‬‬ ‫‪7‬‬
‫‪1 Total number of bits‬‬ ‫‪8‬‬

‫‪23‬‬
‫در ابتدای تحلیل هر الگوریتم باید منظور از «اندازهی ورودی» بیان شود‪.‬‬

‫{مطالعه آزاد‪ :‬الگوریتم ژنتیک چیست؟ مزایا و معایب آن و ربط این الگوریتم را با قانون تکامل داروین بیان‬
‫کنید‪.‬‬

‫یک مسأله بیابید که با الگوریتم ژنتیک حل شود‪}.‬‬

‫منظور از «زمان اجرا»ی یک الگوریتم بهازای یک ورودی خاص تعداد عملیات اصلي‪ 1‬یا گامهایي‪ 2‬که در‬
‫‪3‬‬
‫اجرای برنامه طي شده است‪ ،‬ميباشد‪ .‬بهتر است زمان اجرا را تعداد گامها در نظر بگیریم تا غیروابسته به ماشین‬
‫باشد‪ .‬هرچند اجرای هر خط از شبکه زمان متفاوتي نیاز دارد‪ ،‬امّا با زمان اجرای «‪i‬مین» خط را ‪ C1‬در نظر‬
‫ميگیریم و منظور از ‪ C‬کلمه ‪ Constant‬به معني یک زمان ثابت است‪ .‬ما در الگوریتم مرتبسازی درجي‬
‫«هزینه»ی هر دستورالعمل را یک واحد در نظر ميگیریم و بهازای تعداد دفعاتي که آن دستورالعمل اجرا‬
‫ميشود‪ ،‬یک واحد به هزینه اضافه ميکنیم؛ بنابراین داریم‪:‬‬

‫زمان اجرای الگوریتم برابر است با جمع تعداد دفعات اجرای هر دستورالعمل‪ .‬توجه کنید که دستورالعملي که‬
‫‪ Ci‬گام برای اجرا طول ميکشد و ‪ n‬بار اجرا ميشود‪ ،‬کل زمان اجرایش ‪ Cin‬خواهد شد‪ .‬برای محاسبه )‪T(n‬‬
‫(یعني کل زمان اجرای الگوریتم) جمعِ ضربِ هزینه در تعداد دفعات اجرا را بدست آورید؛ بنابراین برای‬
‫الگوریتم باال داریم‪:‬‬

‫‪1‬‬ ‫‪Primitive operations‬‬


‫‪2‬‬ ‫‪Step‬‬
‫‪3 Machine independent‬‬

‫‪24‬‬
‫در این الگوریتم بهترین حالت‪1‬زماني رخ ميدهد همهی عناصر آرایهی ورودی مرتب باشند‪ .‬در این حالت با‬
‫توجه به اینکه𝑦𝑒𝐾 ≤ ] 𝑖 [ 𝐴 (یعني هر عنصر‪ ،‬کوچکتر یا مساوی عنصر بعدی خود است) حلقهی ‪while‬‬
‫هرگز اجرا نميشود؛ پس )‪ T(n‬در بهترین حالت بهصورت زیر خواهد بود؛‬

‫بنابراین ميتوان زمان اجرا را به شکل 𝑏 ‪ 𝑎𝑛 +‬نمایش داد که ثوابت اعداد ‪ b , a‬به ‪ Ci‬وابسته هستند؛ نتیجه‬
‫اینکه )‪ T(n‬یک تابع خطي از ‪ n‬است‪.‬‬

‫اگر آرایه بهطور برعکس باشد (یعني مرتب نزولي) بدترین حالت رخ ميدهد‪ .‬در این حالت حلقهی ‪ for‬بهازای‬
‫) ‪n ( n+1‬‬
‫= 𝑗 ‪ ∑𝑛𝑗=2‬و بهطور سادهتر ميتوان نوشت‪:‬‬ ‫تمام عناصر ورودی یکبار اجرا ميشود؛ یعني ‪− 1‬‬
‫‪2‬‬

‫𝑛‬ ‫)‪n(n−1‬‬
‫∑‬ ‫=)‪(𝑗−1‬‬
‫‪𝑗=2‬‬ ‫‪2‬‬

‫نتیجه اینکه )‪ T(n‬در بدترین حالت برای الگوریتم مرتبسازی درجي عبارتنداز‪:‬‬

‫‪1‬‬ ‫‪Best-case‬‬

‫‪25‬‬
‫ميتوان بدترین حالت را به شکل 𝑐 ‪ 𝑎𝑛2 + 𝑏𝑛 +‬نشان داد که ‪ b ,a‬و ‪ c‬ثوابتي هستند که وابسته به‬
‫هزینههای ‪ Ci‬ميباشند؛ بنابراین این زمان اجرا‪ ،‬توان ‪2‬ای از ‪1 n‬است‪.‬‬

‫مثال‪ T(n) :‬را برای الگوریتم جستجوی خطي بهازای ‪ n‬ورودی در بهترین و بدترین حالت به دست آورید‪.‬‬
‫پاسخ‪:‬‬

‫بهترین حالت‪:‬‬

‫هزینه‬ ‫دفعات اجرا‬


‫‪C1 = 0‬‬ ‫‪1‬‬
‫‪C2 = 0‬‬ ‫‪1‬‬
‫‪C3‬‬ ‫‪1‬‬
‫‪C4 = 0‬‬ ‫‪1‬‬
‫‪C5‬‬ ‫‪1‬‬
‫‪C6‬‬ ‫‪1‬‬
‫‪C7 = 0‬‬ ‫‪1‬‬
‫‪C8‬‬ ‫‪0‬‬
‫‪C9 = 0‬‬ ‫‪1‬‬

‫)‪𝑇(𝑛) = ( 0 ∗ 1 ) + ( 0 ∗ 1 ) + ( 𝑐3 ∗ 1 ) + ( 0 ∗ 1 ) + ( 𝑐5 ∗ 1‬‬
‫)‪+ ( 𝑐6 ∗ 1 ) + ( 0 ∗ 1 ) + ( 𝑐8 ∗ 0 ) + ( 0 ∗ 1‬‬
‫‪= 𝑐3 + 𝑐5 + 𝑐6‬‬

‫بدترین حالت‪:‬‬

‫هزینه‬ ‫دفعات اجرا‬


‫‪C1 = 0‬‬ ‫‪1‬‬
‫‪C2 = 0‬‬ ‫‪1‬‬
‫‪C3‬‬ ‫‪n‬‬
‫‪C4 = 0‬‬ ‫‪n–1‬‬
‫‪C5‬‬ ‫‪n–1‬‬
‫‪C6‬‬ ‫‪1‬‬
‫‪C7 = 0‬‬ ‫‪n–1‬‬
‫‪C8‬‬ ‫‪0‬‬
‫‪C9 = 0‬‬ ‫‪1‬‬

‫‪1‬‬ ‫‪Quadratic function‬‬

‫‪26‬‬
‫‪𝑇(𝑛) = ( 0 ∗ 1 ) + ( 0 ∗ 1 ) + ( 𝑐3 ∗ 𝑛 ) + ( 0 ∗ ( 𝑛 − 1 ) ) + ( 𝑐5 ∗ ( 𝑛 − 1 ) ) +‬‬
‫‪( 𝑐6 ∗ 1 ) + ( 0 ∗ ( 𝑛 − 1 ) ) + ( 𝑐8 ∗ 0 ) + ( 0 ∗ 1) = ( 𝑐3 ∗ 𝑛 ) + ( 𝑐5 ( 𝑛 −‬‬
‫𝑏 ‪1 ) ) + 𝑐6 = 𝑛 𝑐3 + 𝑛 𝑐5 – 𝑐5 + 𝑐6 = 𝑛 ( 𝑐3 + 𝑐5 ) + 𝑐6 – 𝑐5 = 𝑛𝑎 +‬‬

‫تمرین‪:‬‬ ‫‪-2-6‬‬
‫اگر هزینهی اجرای دستورات انتصاب را در آرایه ] ‪ 1 ،𝐴 = [ 31, 41, 59, 26, 41, 58‬در نظر بگیریم و‬
‫هزینهی اجرای حلقهها و ‪ if‬و ‪ else‬را ‪ 2‬و دیگر عملیات را هم ‪ 1‬در نظر بگیریم‪ ،‬حساب کنید بهازای آرایهی‬
‫زیر در بهترین و بدترین حالت‪ ،‬زمان اجرای الگوریتم مرتبسازی درجي چقدر خواهد بود؟‬

‫‪27‬‬
‫تحلیل بهترین و بدترین حالت‪:‬‬ ‫‪-2-7‬‬
‫هرچند در تحلیل الگوریتم مرتبسازی درجي ما بهترین و بدترین حالت را محاسبه کردیم‪ ،‬امّا ازاینپس فقط‬
‫روی به دست آوردن زمان اجرای بدترین حالت‪1‬متمرکز ميشویم که عبارت است از «طوالنيترین زمان اجرا‬
‫برای هر ورودی به اندازه ‪ » n‬؛ چراکه‪:‬‬

‫‪ -1‬زمان اجرای بدترین حالت یک الگوریتم‪ ،‬باالترین حدِ‪2‬زمان اجرا را برای هر ورودی به دست ما ميدهد و‬
‫یک ضمانت‪3‬برای این است که آن الگوریتم هرگز بیشتر از این زمان طول نخواهد کشید‪ .‬ما نیاز داریم که‬
‫یک برآورد تجربي‪ 4‬از بدترین زمان اجرا داشته باشیم که امیدوار باشیم که الگوریتم هیچوقت شرایط‬
‫بدتری را تجربه نميکند‪.‬‬
‫‪5‬‬
‫‪ -2‬در برخي الگوریتمها‪ ،‬بدترین حالت خیلي بهندرت رخ ميدهد‪( .‬برای مثال در جستجوی یک پایگاه داده‬
‫برای یک داده خاص درحاليکه آن داده در ‪ Database‬وجود ندارد)‪ ،‬امّا در برخي کاربردها جستجوها‬
‫مکرراً بهدنبال دادهای ميگردند که غایب است‪.‬‬
‫‪ -3‬حالت میانگین‪6‬نیز اغلب اوقات مانند بدترین حالت است‪ .‬برای مثال‪ ،‬فرض کنید ما ‪ n‬عدد تصادفي انتخاب‬
‫ميکنیم و الگوریتم مرتبسازی درجي را روی آنها اعمال ميکنیم‪ .‬چقدر طول خواهد کشید تا در زیر‬
‫آرایهی ]‪ 𝐴[1. . 𝑗 − 1‬عنصر ]𝑗[𝐴 درج شود؟ در حالت میانگین‪ ،‬نیمي از عناصر این زیر‪-‬آرایه کوچکتر‬
‫از ]𝑗[𝐴 و نیمي بزرگتر هستند؛ بنابراین‪ ،‬در حالت میانگین نیمي از عناصر این زیر‪-‬آرایه چک ميشود؛‬
‫بنابراین‪ tj ،‬برابر با ‪ j/2‬است‪ .‬در نتیجه زمان اجرای حالت میانگین نیز تابع درجه دومي‪7‬از اندازه ورودی‬
‫است؛ دقیقاً مانند زمان اجرای بدترین حالت است‪.‬‬
‫‪ -4‬در برخي مسائل ما بهدنبال زمان اجرای حالت میانگین یک الگوریتم هستیم‪ ،‬امّا همانطورکه در فصلهای‬
‫آینده در تکنیک تحلیل احتماالتي‪ 8‬صحبت خواهیم کرد‪ ،‬محدوده‪ 9‬تحلیل حالت میانگین محدود‪10‬است‬
‫چراکه گاهياوقات مشخص نیست مقدار ورودی میانگین یک مسأله خاص چیست‪ .‬در اکثر مواقع ما در‬
‫نظر ميگیریم که ورودیها تقریباً به یک اندازهی مساوی هستند‪ ،‬امّا درعمل‪11‬این فرضیه‪ 1‬ممکن است‬

‫‪1‬‬ ‫‪Longest running time‬‬


‫‪2‬‬ ‫‪Upper bound‬‬
‫‪3 Guarantee‬‬
‫‪4 Educated guess‬‬
‫‪5 Database‬‬
‫‪6‬‬
‫‪Average case‬‬
‫‪7‬‬
‫‪Quadratic function‬‬
‫‪8‬‬ ‫‪Probabilistic analysis‬‬
‫‪9‬‬ ‫‪Scope‬‬
‫‪1 limited‬‬ ‫‪0‬‬
‫‪11‬‬
‫‪In practice‬‬

‫‪28‬‬
‫نقض شود‪ 2.‬در این مواقع از الگوریتمهای تصادفي‪3‬استفاده ميکنیم تا انتخابهای تصادفي از کل دادهها با‬
‫اندازههای مختلف داشته باشد تا اجازه دهد که با کمک تحلیل احتماالتي زمان اجرای مورد انتظار را‬
‫پیشبیني کنیم‪.‬‬

‫‪4‬‬
‫نرخ رشد‪:‬‬ ‫‪-2-8‬‬
‫در تحلیل الگوریتم مرتبسازی درجي ما برای اینکه تحلیل الگوریتم سادهتر شود برخي مفاهیم را حذف‬
‫کردیم؛ مثالً در ابتدا هزینهی واقعي هر عبارت را نادیده گرفتیم و همه را مقدار ثابت ‪ Ci‬در نظر گرفتیم‪.‬‬

‫سپس مشاهده کردیم که در این حالت نیز جزئیات زیادی بهدست ميآید؛ برای مثال زمان اجرای بدترین حالت‬
‫بهصورت 𝑐 ‪ 𝑎𝑛2 + 𝑏𝑛 +‬به دست آمد که به ثوابت‪ b ,a 5‬و ‪ c‬وابسته است و آن ثوابت خود به‬
‫هزینههای ‪ Ci‬وابسته بودند؛ درنتیجه ثوابت وابسته به ‪ Ci‬را نیز نادیده گرفتیم‪.‬‬

‫در ادامه ما یک سادهسازی دیگر انجام ميدهیم که به آن نرخرشد‪6‬یا ترتیبرشد‪7‬گفته ميشود و عبارتاستاز‬
‫اینکه فقط جملهی آغازین‪8‬فرمول‪ an29‬را در نظر ميگیریم‪ .‬چراکه جمالت بعدی در اندازههای عظیم ‪ n‬ناچیز‬
‫خواهد بود‪ .‬همچنین ضریب‪10‬ثابت جملهی اول یعني ‪ 𝑎. 𝑎𝑛2‬را نیز بهدلیل تأثیر محاسباتي کمي که دارد‬
‫حذف ميکنیم‪.‬‬

‫در بدترین حالت الگوریتم مرتبسازی درجي با حذف این موارد تنها ‪ 𝑛2‬ميماند که آن را به شکل‬
‫‪𝜃𝑛2‬‬
‫‪ 11‬نشان ميدهیم و ميخوانیم «تِتای اِندو»‪.‬‬

‫از این پس وقتي گفته ميشود یک الگوریتم کاراتر از الگوریتم دیگر است‪ ،‬به این معني ميباشد که نرخ رشد‬
‫زمان اجرای بدترین حالت مربوط به الگوریتم اول کمتر از الگوریتم دوم است‪ .‬البته دقت کنید که با توجه به‬
‫ضرایب ثابت و جمالت دوم به بعد که حذف کردیم ممکن است الگوریتم دوم برای ورودیهای کوچک زمان‬

‫‪ : assumption1‬تفاوت فرضیه و تئوری این است که فرضیه چیزی است که اثبات نشده ولي تئوری چیزی است که روی آن کار و اثبات شده است‪.‬‬
‫‪2‬‬ ‫نقض شدن ‪Violated‬‬
‫‪3‬‬
‫‪Randomized algorithm‬‬
‫‪4‬‬
‫‪Order of growth‬‬
‫‪5‬‬‫‪Constants‬‬
‫‪6‬‬ ‫‪Rate of growth‬‬
‫‪7 Order of growth‬‬
‫‪8 Leading term‬‬
‫‪9 Formula‬‬
‫‪1 Factor‬‬ ‫‪0‬‬
‫‪1 𝜃 : theta of n-squared‬‬ ‫‪1‬‬

‫‪29‬‬
‫کمتری نسبت به الگوریتم اول صرف کند اما اگر ورودیها به اندازه کافي بزرگ باشد قطعا الگوریتمي که برای‬
‫مثال ) ‪ 𝛩(𝑛2‬است‪ ،‬سریعتر از الگوریتمي که ) ‪ 𝛩(𝑛3‬است عمل ميکند‪.‬‬

‫تمرین‪:‬‬ ‫‪-2-9‬‬
‫‪𝑛3‬‬
‫باشد ‪ θ‬را برای‬ ‫‪ -1‬اگر زمان اجرای یک الگوریتم در بدترین حالت ‪− 100𝑛2 − 100𝑛 + 3‬‬
‫‪100‬‬
‫آن نمایش دهید‪.‬‬
‫پاسخ‪ :‬طبق مطالب گفته شده در باال ضرایب ثابت و جمالت دوم به بعد را حذف ميکنیم؛ بنابراین‬

‫‪ 𝜃 = 𝑛3‬ميباشد‪.‬‬

‫‪ -2‬مرتبسازی ‪ n‬عدد که در آرایه ‪ A‬ذخیره شدهاند را به این شکل که ابتدا کوچکترین عدد را یافته و‬
‫با ]‪ 𝐴[1‬جا به جا کنید و سپس دومین عدد کوچک را با ]‪ 𝐴[2‬جا به جا کنید و این کار را تا عنصر‬
‫‪n-1‬ام ادامه دهید‪ ،‬در نظر بگیرید‪ .‬شبهکد این الگوریتم را بنویسید‪( .‬راهنما‪ :‬این الگوریتم بهنام‬
‫«الگوریتم انتخابي»‪ 1‬شناخته ميشود‪ ).‬چرا این الگوریتم فقط ‪ n-1‬عنصر را بررسي ميکند و نه همهی ‪n‬‬
‫عنصر را؟ بهترین و بدترین حالت را برای این الگوریتم بهدست آورید‪.‬‬

‫پاسخ‪ :‬زیرا با هر بار اجرای حلقه ‪ for‬عدد بزرگتر به سمت خانه ‪n‬اُم و در نهایت در خانه‪n‬اُم قرار ميگیرد‪ .‬به‬
‫همین دلیل در خانه آخر عدد بزرگتر قرار دارد و آن خانه مورد بررسي قرار نميگیرد‪.‬‬

‫‪ -3‬جستجوی خطي را در نظر بگیرید‪ .‬چند عنصر در حالت میانگین باید چِک شود تا عنصر موردنظر پیدا‬
‫شود؟ (فرض کنید که عنصر در آرایه موجود است‪ ).‬در بدترین حالت چطور؟ حالت میانگین و بدترین‬
‫حالت را به شکل ‪ θ‬نمایش دهید‪( .‬منظور از ‪ θ‬این است که ضرایب ثابت و جمالت دوم به بعد را‬
‫حذف کنید)‬

‫پاسخ‪ :‬در بهترین حالت یک بار (‪ ) 𝜃 = 1‬و در بدترین حالت و در حالت میانگین ‪ n‬بار ( 𝑛 = ‪) θ‬‬

‫‪ -4‬چطور ميتوان هر الگوریتمي را طوری تغییر داد که بهترین زمان اجرای خوبي داشته باشیم؟‬

‫‪1‬‬
‫‪Selection Sort‬‬

‫‪30‬‬
‫فصل سوم‬

‫نرخ رشد توابع‬

‫نرخ رشد توابع‪:‬‬ ‫‪-3-1‬‬


‫ترتیب یا نرخ رشد زمان اجرای یک الگوریتم که در فصل ‪ 2‬تعریف شد‪ ،‬یک ویژگي‪1‬ساده برای بیان کارایي‬
‫الگوریتم است و به ما اجازه مي دهد که کارایي نسبي الگوریتمهای جایگزین‪2‬با الگوریتم مدنظرمان را با هم‬
‫مقایسه کنیم‪.‬‬

‫اگر اندازه ورودی ‪ n‬به اندازه کافي بزرگ باشد‪ ،‬زمان اجرای بدترین حالت مرتبسازی ادغامي )𝑛 ‪𝛩(𝑛 lg‬‬
‫است؛ بنابراین‪ ،‬رقابت را نسبت به الگوریتم مرتبسازی درجي که زمان اجرای بدترین حالت آن ) ‪ 𝛩(𝑛2‬است‪،‬‬
‫خواهد برد‪ .‬هرچند گاهي اوقات ميتوان بهطور دقیق‪3‬زمان اجرای یک الگوریتم را مشخص کرد؛ (همانطور که‬
‫در مورد الگوریتم مرتبسازی درجي در فصل‪ 2‬این کار را کردیم) اما محاسبه دقیق زمان اجرا آنقدر زحمت‬
‫الزم دارد که معموالً ارزشش را ندارد‪.‬‬

‫اگر اندازهی ورودی خیلي بزرگ باشد‪ ،‬دیگر ضرایب و جمالت دوم به بعد چندجملهای آنقدر نسبت به‬
‫جملهی اول ناچیز خواهد بود که در نظر گرفته نميشود؛ بنابراین در این مواقع ما «کارایي تقریبي»‪ 4‬الگوریتمها‬
‫را مورد مطالعه قرار ميدهیم و معموالً الگوریتمي که کارایي تقریبي آن بهتر باشد‪ ،‬برای همه نوع ورودیها (به‬
‫جز ورودیهای خیلي کوچک‪ )5‬گزینه مناسبي خواهد بود‪.‬‬

‫این فصل روشهای استاندارد مختلفي برای سادهسازی تحلیل تقریبي الگوریتمها ارائه ميکند‪ .‬در ادامه نگاهي به‬
‫«نمادهای تقریبي»‪ 6‬خواهیم داشت‪.‬‬

‫‪1‬‬
‫‪characterization‬‬
‫‪2‬‬
‫‪Alternative‬‬
‫‪- Precision3‬‬
‫‪4‬‬
‫‪Asymptotic Efficiency‬‬
‫‪5‬‬
‫‪Very Small Inputs‬‬
‫‪6‬‬
‫‪Asymptotic Notation‬‬

‫‪31‬‬
‫نمادهای تقریبی (یا نمادهای همبستگی یا نمادهای مُجانبی)‪:‬‬ ‫‪- 3 -2‬‬
‫این نمادها برای توصیف زمان اجرای تقریبي یک الگوریتم که در قالب یک تابع تعریف شده و بر روی اعداد‬
‫طبیعي‪ 𝑁 = { 0, 1, 2, … }1‬عمل ميکند‪ ،‬استفاده ميشود‪.‬‬

‫‪: 𝞱 –Notation‬‬ ‫‪-3-3‬‬


‫برای تابع فرضي )‪ ،g(n‬نمادِ 𝞱 (()‪ )𝞱)g(n‬به صورت زیر تعریف ميشود‪:‬‬

‫‪θ(𝑔(𝑛)) = f(𝑛): ∃ 𝑐1 , 𝑐2 , 𝑛0 > 0 ∶ 0 < 𝑐1 𝑔(𝑛) < 𝑓 (𝑛) < 𝑐2 𝑔(𝑛), ∀𝑛 > 𝑛0‬‬

‫این رابطه به این معناست که آهنگ رشد ‪ f‬و ‪ g‬برای مقادیر بزرگ ‪ n‬یکسان است و هیچیک از این دو تابع از‬
‫دیگری جلو نميزند؛ بهطور مثال زمان اجرای مرتبسازی درجي 𝑐 ‪ 𝑎𝑛2 + 𝑏𝑛 +‬است بنابراین‪:‬‬
‫) ‪ . 𝑇(𝑛) = 𝜃(𝑛2‬زیرا ميتوان بهسادگي مقادیر مثبتي برای ‪ c1‬و ‪ c2‬یافت که‪:‬‬

‫‪𝑐1 𝑛2 < 𝑎𝑛2 + 𝑏𝑛 + 𝑐 < 𝑐2 𝑛2‬‬

‫مثال‪ :‬ثابت کنید ) ‪.100𝑛2 + 5𝑛 − 4 ≠ 𝜃(𝑛3‬‬

‫اثبات‪ :‬باید نشان داد که نميتوان مقادیر مثبتي برای ‪ c2 , c1‬و ‪ n0‬یافت که رابطهی‬

‫‪ 𝑐1 𝑛3 < 100𝑛2 + 5𝑛 − 4 < 𝑐2 𝑛3‬برای همه مقادیر ‪ n > n0‬برقرار باشد‪ ،‬به وضوح بهازای هر‬
‫مقدار ‪ c1 > 0‬و برای مقادیر بزرگ ‪ n‬خواهیم داشت‪.) 𝑐1 𝑛3 ≰ 100𝑛2 + 5𝑛 − 4( :‬‬

‫‪1‬‬
‫‪Natural Numbers‬‬

‫‪32‬‬
‫‪: O –Notation‬‬ ‫‪-3-4‬‬
‫نماد 𝞱 به صورت تقریبي‪ ،‬یک تابع را از باال به پایین محدود‪1‬ميکند‪ .‬وقتي ما فقط یک «حد باالی تقریبي»‬
‫‪2‬‬

‫داشته باشیم‪ ،‬از نماد ‪ O‬استفاده ميکنیم‪ .‬برای تابع فرضي )‪ ،g(n‬نماد ‪ (O(g(n))) O‬را (که به صورت بیگ اُ‬
‫جي اِن‪3‬یا ))‪ O(g(n‬تلفظ ميشود)‪ ،‬به صورت زیر تعریف ميشود‪:‬‬

‫‪O(𝑔(𝑛)) = f(𝑛): ∃ 𝑐1 𝑛0 > 0 ∶ 0 < 𝑓(𝑛) < c 𝑔(𝑛), ∀𝑛 > 𝑛0‬‬

‫یعني آهنگ رشد تابع )‪ g(n‬برای مقادیر بزرگ ‪ ،n‬بیشتر یا مساوی آهنگ رشد تابع )‪ f(n‬است‪ ،‬در این صورت‬
‫مي گوییم )‪ g(n‬کران باالی مجانبي‪4‬برای )‪ f(n‬است؛ بهطور مثال‪:‬‬

‫‪ n𝑙𝑜𝑔 𝑛 = 𝑂(𝑛2 ).‬یا ) ‪𝑛2 = 𝑂(𝑛2‬‬

‫نکته‪ :‬منظور از ))‪ f = O(g(n‬در واقع))‪ f Ꞓ O(g(n‬است‪.‬‬

‫‪: Ω –Notation‬‬ ‫‪-3-5‬‬


‫همانطورکه نماد ‪ O‬حد باالی تقریبي یک تابع را ارائه ميکند‪ ،‬نماد ‪ Ω‬حد پایین تقریبي یک تابع را ارائه‬
‫ميکند‪ .‬برای تابع فرضي )‪ ،g(n‬نماد )))‪ Ω (Ω (g(n‬را که به صورت بیگ اُمگای جي اِن‪5‬یا ))‪Ω (g(n‬‬

‫‪1‬‬
‫‪Bounds‬‬
‫‪2‬‬
‫‪Asymptotic Upper bound‬‬
‫‪3‬‬
‫”‪“Big-O of g of n‬‬
‫‪ 4‬حد باالی تقریبي‬
‫”‪“Big-Omega of g of n‬‬
‫‪5‬‬

‫‪33‬‬
‫تلفظ ميشود‪ .‬تعریف ریاضیاتي این عالمت به شکل زیر ميباشد که در آن تابع )‪ g(n‬کران پایین مجانبي برای‬
‫تابع )‪ f(n‬است‪.‬‬

‫‪Ω(𝑔(𝑛)) = f(𝑛): ∃ 𝑐1 𝑛0 > 0 ∶ 0 < c 𝑔(𝑛) < 𝑓(𝑛), ∀𝑛 > 𝑛0‬‬

‫برای مثال‪ 𝑛3 = Ω(𝑛2 ) :‬یا و )𝑛 𝑔𝑜𝑙(‪√𝒏 = Ω‬‬

‫ترتیب رشد توابع مختلف‪:‬‬ ‫‪-3-6‬‬

‫نکته مهم‪ :‬به زبان ساده‪ ،‬اگر زمان تقریبي دقیق اجرای یک الگوریتم خواسته شد‪ ،‬یعني 𝞱 و اگر حداکثر زمان‬
‫تقریبي خواسته شد‪ ،‬یعني ‪ O‬و اگر حداقل زمان تقریبي خواسته شد‪ ،‬یعني ‪.Ω‬‬

‫‪34‬‬
‫تمرین‪:‬‬ ‫‪-3-7‬‬
‫‪ -1‬فرض کنید (‪ f(n‬و )‪ g(n‬توابع غیرمنفي تقریبي باشند‪ ،‬با استفاده از تعریف نماد 𝞱 ثابت کنید‪:‬‬
‫))‪Max (f(n), g(n)) = 𝞱(f(n) + g(n‬‬
‫‪ -2‬ثابت کنید برای هر مقدار ثابت ‪ a‬و ‪ b‬برای هر مقدار داریم‪:‬‬
‫)‪(n + a)b = 𝞱 (nb‬‬
‫‪ -3‬ثابت کنید که این جمله غلط است‪« :‬زمان اجرای الگوریتم ‪ A‬حداقل )‪ O(n2‬است»‪.‬‬
‫‪ -4‬آیا عبارات زیر درست است؟‬
‫الف‪2n+1 = O(2n) :‬‬
‫ب‪22n = O(2n) :‬‬

‫‪1‬‬
‫‪:o –Notation‬‬ ‫‪-3-8‬‬
‫همانطورکه گفته شد نماد )‪ 2O (Big o‬ممکن است چندان به تابع اصلي نزدیک نباشد؛ برای مثال‬
‫)‪ 2n2 = O(n2‬به تابع اصلي نزدیک است امّا )‪ n2 ،2n = O(n2‬به ‪ 2n‬چندان نزدیک نیست‪ .‬برای نمایش‬
‫حد باالیي که به تابع موردنظر نچسبیده است‪ ،‬از نماد )‪ o (Little o‬استفاده ميکنیم و آن را به صورت زیر‬
‫تعریف ميکنیم‪:‬‬

‫‪𝑜(𝑔(𝑛)) = { 𝑓(𝑛) ∶ 𝑓𝑜𝑟 𝑎𝑛𝑦 𝑝𝑜𝑠𝑖𝑡𝑖𝑣𝑒 𝑐𝑜𝑛𝑠𝑡𝑎𝑛𝑡 𝑐 > 0,‬‬


‫𝑡𝑛𝑎𝑡𝑠𝑛𝑜𝑐 𝑎 𝑠𝑡𝑠𝑖𝑥𝑒 𝑒𝑟𝑒‪𝑡ℎ‬‬
‫‪𝑛0 > 0 𝑠𝑢𝑐ℎ 𝑡ℎ𝑎𝑡 0 ≤ 𝑓(𝑛) < 𝑐𝑔(𝑛) 𝑓𝑜𝑟 𝑎𝑙𝑙 𝑛 ≥ 𝑛0 }.‬‬

‫برای مثال ‪ o‬کوچک ‪ 2n‬برابر است با )‪ 2n = o(n2‬که اینطور مي خوانیم‪ ،2n :‬اُردِرِ ‪ n2‬است‪.‬‬

‫‪:ω –Notation‬‬
‫‪3‬‬
‫‪-3-9‬‬
‫‪ ɷ‬کوچک نسبت به ‪ Ω‬بزرگ همان نسبت ‪ o‬کوچک به ‪ O‬بزرگ است؛ یعني نماد ‪ ɷ‬کوچک حد پاییني را‬
‫‪𝑛2‬‬
‫برابر است با ‪n‬؛‬ ‫مشخص ميکند که به تابع مدنظر نچسبیده است؛ برای مثال اُمگای مربوط به‬
‫‪2‬‬

‫‪ ω‬را در قالب ریاضي به صورت زیر تعریف ميکنیم‪:‬‬

‫‪ɷ(𝑔(𝑛)) = { 𝑓(𝑛) ∶ 𝑓𝑜𝑟 𝑎𝑛𝑦 𝑝𝑜𝑠𝑖𝑡𝑖𝑣𝑒 𝑐𝑜𝑛𝑠𝑡𝑎𝑛𝑡 𝑐 > 0,‬‬


‫𝑡𝑛𝑎𝑡𝑠𝑛𝑜𝑐 𝑎 𝑠𝑡𝑠𝑖𝑥𝑒 𝑒𝑟𝑒‪𝑡ℎ‬‬

‫‪1‬‬
‫اُ کوچک‬
‫‪2‬‬
‫اُ بزرگ‬
‫‪3‬‬
‫اُمگای کوچک‬

‫‪35‬‬
‫‪𝑛0 > 0 𝑠𝑢𝑐ℎ 𝑡ℎ𝑎𝑡 0 ≤ 𝑐𝑔(𝑛) < 𝑓(𝑛) 𝑓𝑜𝑟 𝑎𝑙𝑙 𝑛 ≥ 𝑛0 }.‬‬

‫مثال‪ :‬اگر ‪ g(n) = 2n2 + n + 10‬داشته باشیم‪ ،‬نماد ‪ θ‬و ‪ Ω‬و ‪( O‬طبق شکل ترتیب رشد الگوریتم) به‬
‫صورت زیر است‪:‬‬

‫)‪2n2 + n +10 = θ(n2‬‬


‫)‪2n2 + n +10 = Ω(n logn‬‬
‫)‪2n2 + n +10 = ω (n‬‬
‫)‪2n2 + n +10 = O(2n‬‬
‫)!‪2n2 + n +10 = o(n‬‬

‫نمادهای استاندارد و توابع عمومی‪:‬‬ ‫‪-3-10‬‬


‫این بخش مروری دارد به برخي توابع و نمادهای ریاضي استاندارد و روابط بین آنها را کاوش ميکند و‬
‫همچنین کاربرد نمادهای تقریبي را مشخص ميکند‪.‬‬

‫‪1‬‬
‫یکنواختی‪:‬‬ ‫‪-3-11‬‬
‫تابع )‪ f(n‬را دارای «افزایش یکنواخت»‪ 2‬ميدانیم اگر ‪ n‬و ‪m‬ی داشته باشیم که‪:‬‬
‫)𝑛(𝑓 ≤ )𝑚(𝑓 و 𝑛 ≤ 𝑚‬

‫تابع )‪ f(n‬را دارای «کاهش یکنواخت»‪ 3‬ميدانیم اگر ‪ n‬و ‪m‬ی داشته باشیم که‪:‬‬
‫)𝑛(𝑓 ≥ )𝑚(𝑓 و 𝑛 ≤ 𝑚‬
‫تابع )‪ f(n‬را «به شدت افزایشي»‪ 1‬ميدانیم‪ ،‬اگر ‪ n‬و ‪ m‬به صورت )𝑛(𝑓 < )𝑚(𝑓 و باشد 𝑛 < 𝑚‪.‬‬

‫‪1‬‬
‫‪Monotonicity‬‬
‫‪2‬‬
‫‪Monotonically Increasing‬‬
‫‪3‬‬
‫‪Monotonically Decreasing‬‬

‫‪36‬‬
‫تابع )‪ f(n‬را «به شدت کاهشي»‪ 2‬مي دانیم‪ ،‬اگر ‪ n‬و ‪ m‬به صورت )𝑛(𝑓 > )𝑚(𝑓 و باشد 𝑛 < 𝑚‪.‬‬

‫برای مثال شکل زیر تابع افزایشي است‪ ،‬ولي به شدت افزایشي نیست چراکه ميتوان ‪ m‬و ‪n‬ی پیدا کرد‬
‫که )𝑛(𝑓 = )𝑚(𝑓 ولي 𝑛 < 𝑚‪.‬‬

‫‪1‬‬
‫‪Strictly Increasing‬‬
‫‪2‬‬
‫‪Strictly Decreasing‬‬

‫‪37‬‬
‫‪1‬‬
‫باقیمانده‪:‬‬ ‫‪-3-12‬‬
‫𝑎‬
‫برای هر عدد صحیح ‪ a‬و هر عدد صحیح مثبت ‪ n‬مُد یا باقیمانده تقسیم ‪ a‬بر ‪ n‬به صورت زیر نمایش‬
‫𝑛‬
‫‪2‬‬
‫داده ميشود‪:‬‬
‫𝑎‬
‫⌊ 𝑛 ‪𝑎 𝑚𝑜𝑑 𝑛 = 𝑎 −‬‬ ‫⌋‬
‫𝑛‬
‫یعني ‪ a‬منهای ‪ n‬در کفِ ‪ a‬بر ‪( n‬منظور از «کف»‪ ،‬حذف بخش اعشاری یک عدد است)‬
‫مثال‪:‬‬

‫‪10‬‬
‫⌊ ‪10 mod 3 = 10 − 3‬‬ ‫‪⌋ = 10 − 9 = 1‬‬
‫‪3‬‬
‫تمرین‬ ‫‪-3-13‬‬
‫‪ -1‬نشان دهید اگر )‪ f(n‬و )‪ g(n‬توبع افزایشي باشند‪ ،‬توابع )𝑛(‪ f(𝑛) + g‬و ))‪ f(g(n‬نیز افزایشي‬
‫است و اگر )‪ f(n‬و )‪ g(n‬عالوهبر افزایشي بودن منفي نباشند )‪ f(n‬در )‪ g(n‬یعني )𝑛(‪f(𝑛). g‬‬
‫افزایشي است‪.‬‬

‫‪ -2‬ثابت کنید که‪:‬‬


‫) 𝑛𝑛(‪( 𝑛! = o‬الف‬
‫) 𝑛‪( 𝑛! = 𝜔(2‬ب‬
‫‪ -3‬برنامهای بنویسید که دو ماتریس ‪ 2*2‬را از ورودی دریافت کند و ماتریس ضرب آنها را نمایش‬
‫دهد‪ .‬بررسي کنید که الگوریتم ‪ Strassen‬چطور نتیجه را به دست ميآورد‪.‬‬

‫‪1‬‬
‫‪Modular Arithmetic‬‬
‫⌈⌉ ‪ :‬عالمت سقف و ⌋⌊ ‪ :‬عالمت کف ميباشند‪.‬‬ ‫‪2‬‬

‫‪38‬‬
‫فصل چهارم‬

‫الگوریتمهای بازگشتی‬

‫‪1‬‬
‫الگوریتم بازگشتی‪:‬‬ ‫‪-4-1‬‬
‫اگر یک الگوریتم در حین اجرا‪ ،‬خودش‪2‬را فراخواني‪3‬کند به این الگوریتم‪ ،‬الگوریتم بازگشتي گفته ميشود‪.‬‬

‫الگوریتمهای بازگشتي از پرکاربردترین و گاهي پرهزینهترین الگوریتمها در پیادهسازی راه حل مسائل هستند‪.‬‬

‫مثالی از الگوریتم بازگشتی‪ :‬برنامهی محاسبه فاکتوریل‪:‬‬ ‫‪-4-2‬‬


‫یک عدد از ورودی بگیرید و به صورت بازگشتي فاکتوریل آن را حساب کنید‪.‬‬

‫جستجوی دودویی به صورت بازگشتی‪:‬‬ ‫‪-4-3‬‬

‫‪1‬‬
‫‪Recursive Algorithm‬‬
‫‪2‬‬
‫‪Itself‬‬
‫‪3‬‬
‫‪Call‬‬

‫‪39‬‬
‫‪1‬‬
‫اعداد فیبوناچی‪:‬‬ ‫‪-4-4‬‬
‫این اعداد به صورت زیر تعریف ميشوند‪:‬‬
‫‪𝑓0 = 0‬‬
‫‪𝑓1 = 1‬‬
‫‪𝑓𝑖 = 𝑓𝑖+1 + 𝑓𝑖−2‬‬ ‫‪𝑓𝑜𝑟 𝑖 ≥ 2‬‬
‫بنابراین توالي زیر تولید خواهد شد‪:‬‬
‫… ‪0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55,‬‬
‫به دست آوردن جمله ‪n‬ام از دنباله فیبوناچي یک مسأله بازگشتي مشهور است‪.‬‬
‫به طور مثال شکل محاسبه جمله هفتم این توالي یعني عدد ‪ ،8‬به صورت زیر است‪:‬‬

‫‪1‬‬
‫‪Fibonacci Numbers‬‬

‫‪40‬‬
‫این مسأله به سه روش قابل حل است‪:‬‬
‫‪ -1‬به صورت تکراری (بدون استفاده از الگوریتم بازگشتي)‪:‬‬

‫‪41‬‬
‫‪ -2‬به صورت بازگشتي‪:‬‬

‫‪ -3‬با استفاده از برنامهنویسي پویا‪ :‬این روش در فصلهای آینده توضیح داده خواهد شد‪.‬‬

‫‪1‬‬
‫مطالعه آزاد‪ :‬نسبت طالیی‪:‬‬ ‫‪-4-5‬‬
‫‪ φ‬هستند که دو ریشهی معادلهی ‪𝑥 2 = 𝑥 2 + 1‬‬
‫اعداد فیبوناچي مربوط به نسبت طالیي ‪ φ‬و مزدوج آن ̂‬
‫ميباشند‪.‬‬
‫نسبت طالیي یا عدد ‪ φ‬در ریاضیات و هنر هنگامي رخ ميدهد که‪« :‬نسبت بخش بزرگتر به بخش کوچکتر‬
‫برابر با نسبت کل به بخش بزرگتر» باشد‪.‬‬
‫تعریف دیگر آن از این قرار است که‪« :‬عددی مثبت است که اگر به آن یک واحد اضافه کنیم به مربع آن‬
‫خواهیم رسید»‪.‬‬
‫تعریف هندسي آن نیز چنین است‪« :‬طول مستطیلي به مساحت واحد که عرض آن یک واحد کمتر از طولش‬
‫باشد» و آن را به شکل زیر نمایش ميدهیم‪:‬‬
‫𝑏‪𝑎+‬‬ ‫𝑎‬
‫=‬ ‫𝜑 =‬
‫𝑎‬ ‫𝑏‬
‫که ‪ a‬همان طول و ‪ b‬همان عرض مستطیل است و در نهایت ‪ φ‬را برابر عدد زیر در نظر ميگیریم‪:‬‬
‫‪φ ≃ 1/6180339887‬‬
‫روانشناسان بر این باورند که زیباترین مستطیل به دید انسان مستطیلي است که نسبت طول به عرض آن برابر عدد‬
‫طالیي باشد‪ .‬دلیل این امر آن است که این نسبت در شبکیهی چشم انسان رعایت شده و هر مستطیلي که این‬
‫نسبت را دارا باشد به چشم انسان زیبا ميآید‪.‬‬

‫‪1‬‬
‫‪Golden Ratio‬‬

‫‪42‬‬
‫فصل پنجم‬

‫تکنیکهای طراحی الگوریتم (‪ :)1‬روش تقسیم و غلبه‬

‫طراحی الگوریتمها‪:‬‬ ‫‪-5-1‬‬


‫تکنیکهای طراحي الگوریتم بسیار زیاد هستند‪ .‬در فصلهای قبل با تکنیک «افزایشي»‪ 1‬در طراحي الگوریتم‬
‫مرتبسازی درجي آشنا شدیم‪ .‬در این بخش با یک روش‪2‬طراحي دیگر به نام «تقسیم و غلبه» آشنا ميشویم و‬
‫از این روش برای طراحي یک الگوریتم مرتبسازی استفاده ميکنیم که بدترین زمان اجرای آن بسیار کمتر از‬
‫مرتبسازی درجي است‪.‬‬

‫‪3‬‬
‫روش تقسیم و غلبه‪:‬‬ ‫‪-5-2‬‬
‫بسیاری از الگوریتمهای مفید در ساختار خود از حالت بازگشتي استفاده ميکنند؛ یعني برای حل یک مسألهی‬
‫فرضي‪ ،‬آن ساختار دائماً خودش را فراخواني ميکند تا به حد کافي مسأله کوچک شده و قابل حل شود‪ .‬این‬
‫فراخواني ممکن است یک یا چندینبار اتفاق بیفتد‪ .‬این نوع الگوریتمها نوعاً از روشي استفاده ميکنند که به‬
‫تقسیم و غلبه مشهور است؛ یعني مسأله را به چندین زیرمسأله ميشکند‪4‬که آن زیرمسأله شبیه مسألهی اصلي‪5‬در‬
‫اندازهی کوچکتری است‪ ،‬سپس زیرمسأله را حل ميکند و پاسخ زیرمسألهها را با هم ترکیب ميکند تا به حل‬
‫مسألهی اصلي بینجامد‪.‬‬

‫روش‪6‬تقسیم و غلبه با سه گام درگیر است‪:‬‬


‫‪ .1‬مرحله تقسیم‪7:‬مسأله به تعدادی مسأله کوچکتر شکسته ميشود‪.‬‬
‫‪ .2‬مرحله غلبه‪1:‬زیرمسألهها از طریق تقسیمهای بازگشتي خود را حل ميکنند‪ ،‬اگر یک زیرمسأله به‬
‫اندازهی کافي کوچک شده باشد بدون تقسیم اضافه حل ميشود‪.‬‬

‫‪1‬‬ ‫‪Incremental‬‬
‫‪2‬‬ ‫‪Approach‬‬
‫‪3‬‬
‫‪Divide-and-conquer‬‬
‫‪4‬‬ ‫‪Break‬‬
‫‪5‬‬ ‫‪Original problem‬‬
‫‪6 Paradigm‬‬
‫‪7 Divide‬‬

‫‪43‬‬
‫‪ .3‬مرحله ترکیب‪2:‬پاسخ زیرمسأله با هم ترکیب ميشود تا مسألهی اصلي حل شود‪.‬‬

‫مثال‪ :‬الگوریتم مرتبسازی ادغامي از روش تقسیم و غلبه استفاده ميکند؛ یعني داریم‪:‬‬
‫𝑛‬
‫‪ .4‬مرحله تقسیم‪ :‬توالي ‪ n‬عنصر را به دو زیر توالي‪3‬با عنصر تقسیم ميکند‪.‬‬
‫‪2‬‬
‫‪ .5‬مرحله غلبه‪ :‬دو زیر توالي را با استفاده از مرتبسازی ادغامي مرتب ميکند‪.‬‬
‫‪ .6‬مرحله ترکیب‪ :‬دو زیر توالي مرتب شده را با هم ادغام ميکند تا پاسخ مرتب شدهی نهایي را تولید کند‪.‬‬
‫عملیات تقسیم آنقدر ادامه پیدا ميکند تا تعداد عناصری که باید مرتب شوند ‪ 1‬باشد و البتّه طبیعتاً یک عنصر‬
‫نیازی به مرتبسازی ندارد؛ بنابراین اصل مرتبسازی زماني اتفاق ميافتد که دو عنصر با هم در مرحله بعد‬
‫ترکیب ميشوند‪ .‬مرتبسازی ادغامي را با تابع )𝑟 ‪ 𝑀𝐸𝑅𝐺𝐸 (𝐴, 𝑝, 𝑞,‬انجام ميدهیم که در آن‪ A ،‬آرایهای‬
‫است که باید مرتب شود و ‪ p,q,r‬اندیسهای آرایه هستند بهطوریکه 𝑟 < 𝑞 ≤ 𝑝 ‪.‬‬

‫تابع فرض ميکند زیر آرایه ] 𝑞 … 𝑝 [ 𝐴 و ] 𝑟 … ‪ 𝐴 [ 𝑞 + 1‬مرتب شده هستند‪ .‬تابع آنها را ادغام ميکند‬
‫تا زیرآرایهی ] 𝑟 … 𝑝 [ 𝐴 به دست آید‪.‬‬

‫تابع ‪ MERGE‬زمان )‪ 𝜃 (n‬را صرف ميکند که در آن ‪ 𝑛 = 𝑟 − 𝑝 + 1‬و در حقیقت تعداد عناصری‬


‫است که باید مرتب شوند‪.‬‬
‫شبهکد این تابع به صورت زیر است‪:‬‬

‫‪1‬‬ ‫‪Conquer‬‬
‫‪2‬‬ ‫‪Combine‬‬
‫‪3‬‬
‫‪Subsequence‬‬

‫‪44‬‬
‫و کد ‪ C++‬این تابع به صورت زیر است‪:‬‬

‫‪45‬‬
‫مرجع کدها‪ :‬سایت ‪http://www.geeksforgeeks.org/merge-sort/‬‬

‫مثال‪ :‬آرایهی ‪ A‬با عناصر ‪ 10 .82 .9 .3 .43 .27 .38‬را در نظر بگیرید‪ .‬با الگوریتم مرتبسازی ادغامي آن را‬
‫مرتب کنید‪.‬‬

‫)‪(𝑛−1‬‬
‫𝑡𝑛𝑖 = 𝑚 به دست آورید‪.‬‬ ‫راهنمایی‪ m :‬را از طریق فرمول‬
‫‪2‬‬

‫مثال‪ :‬آرایهی ‪ A‬با عناصر ‪ 5,2,4,7,1,3,2,6‬را در نظر بگیرید‪ .‬شکل کلي مرتبسازی آرایه ‪ A‬را با کمک‬
‫الگوریتم مرتبسازی ادغامي رسم کنید‪.‬‬

‫مثال ‪ :2‬آرایهی ‪ A‬با عناصر ‪ 38, 27, 43, 3, 9, 82, 10‬را در نظر بگیرید‪ .‬با الگوریتم مرتبسازی ادغامي‬
‫آن را مرتب کنید‪.‬‬

‫‪46‬‬
‫آرایهی ‪ A‬با عناصر}‪ {0, 10, 38, 7, 43, 8, 9, 1, 2, 10‬را در نظر بگیرید‪ .‬شکل کلی مرتبسازی آرایه ‪ A‬را با‬
‫کمک الگوریتم مرتبسازی ادغامی رسم کنید‪.‬‬

‫‪47‬‬
‫جستجوی دودویی‪:‬‬ ‫‪-5-3‬‬
‫در این جستجو یک آرایه مرتب داریم که در آن به دنبال یک عنصر ميگردیم‪ ،‬برای یافتن آن ابتدا آرایه را به‬
‫دو قسمت تقسیم ميکنیم و عنصر مورد جستجو را با عنصر وسط آرایه مقایسه ميکنیم‪ ،‬اگر عنصر مورد جستجو‬
‫بزرگتر از عنصر وسط آرایه بود‪ ،‬تِکهی دوم آرایه را به همین روش تا یافتن عنصر موردنظر به دو قسمت تقسیم‬
‫و مقایسه ميکنیم‪.‬‬

‫مثال‪ :‬با توجه به قطعه کد زیر که تابع جستجوی دودویي است‪ ،‬در آرایه زیر به دنبال عدد ‪ 30‬بگردید‪ .‬جدول‬
‫تغییرات متغیرها را رسم کنید‪.‬‬

‫جدول تغییرات متغیرها‪:‬‬

‫‪Start‬‬ ‫‪Stop‬‬ ‫‪Q‬‬ ‫‪Mid‬‬ ‫‪Result‬‬


‫‪0‬‬ ‫‪6‬‬ ‫‪30‬‬ ‫‪3‬‬
‫‪3‬‬ ‫‪6‬‬ ‫‪4‬‬
‫‪4‬‬ ‫‪6‬‬
‫‪5ar‬‬ ‫‪5‬‬
‫تمرین‪ :‬آرایه ای با ‪ 7‬عنصر تعریف کرده و مقادیر آن را از ورودی بخوانید‪ .‬سپس با مرتبسازی ادغامي آن را‬
‫مرتب کرده و سپس یک عدد از کاربر گرفته و با جستجوی دودویي مشخص کنید آن عدد در کدام خانه از‬
‫آرایه موجود است؟‬

‫‪48‬‬
‫فصل ششم‬

‫تکنیکهای طراحی الگوریتم (‪ :)2‬روش حافظه پویا‬

‫مقدمه‬ ‫‪-6-1‬‬
‫اگر به حل مسأله فیبوناچي به روش بازگشتي دقت کنیم‪ ،‬خواهید دید که اکثر جمالت (مانند )‪ ) Fib(3‬چندین‬
‫بار محاسبه ميشوند‪ ،‬برای جلوگیری از این پردازشهای تکراری ميتوان هر جملهای که به دست آمد را در‬
‫بخشي از حافظه ذخیره کرد و به محض نیاز به آن به جای محاسبه مجدد‪ ،‬از حافظه پاسخ را خواند‪ .‬به این روش‬
‫در اصطالح حافظه پویا گفته ميشود‪.‬‬

‫‪1‬‬
‫الگوریتم مرتبسازی سریع‪:‬‬ ‫‪-6-2‬‬
‫مثال‪ :‬اعداد زیر را با ‪ Quick Sort‬مرتب کنید‪:‬‬

‫‪15, 22, 13, 27, 12, 10, 20, 25‬‬

‫روش حل‪:‬‬

‫این الگوریتم را با دو تابع ‪ Quick Sort‬و ‪ Partition‬به شکل زیر ميتوان پیادهسازی کرد‪:‬‬

‫تابع ‪: Quick Sort‬‬

‫‪1‬‬
‫‪Quick Sort‬‬

‫‪49‬‬
‫تابع ‪: Partition‬‬

‫مسأله ضرب ماتریسها‪:‬‬ ‫‪-6-3‬‬


‫برای نگهداری عناصر یک ماتریس از یک آرایه دوبعدی و برای ضرب عناصر دو آرایه‪ ،‬از دو حلقهی تودرتو‬
‫استفاده ميکنیم‪.‬‬

‫مثال‪ :‬اگر ‪ arr1‬و ‪ arr2‬به صورت زیر داده شود‪ ،‬عناصر ‪ arr3‬که ضرب دو ماتریس است‪ ،‬به صورت‬

‫زیر محاسبه ميشوند‪:‬‬

‫‪10 5 3‬‬
‫]‪𝑎𝑟𝑟1 = [ 7 8 9‬‬
‫‪1 2 3‬‬
‫‪5‬‬ ‫‪1‬‬
‫‪𝑎𝑟𝑟2 = [1‬‬ ‫]‪2‬‬
‫‪0‬‬ ‫‪3‬‬
‫‪10 5‬‬ ‫‪3 5 1‬‬ ‫‪55 29‬‬
‫‪[7 8‬‬ ‫]‪9] [1 2] = [43 50‬‬
‫‪1 2‬‬ ‫‪3 0 3‬‬ ‫‪7 14‬‬
‫‪55 29‬‬
‫]‪𝑎𝑟𝑟3 = [43 50‬‬
‫‪7 14‬‬

‫‪50‬‬
‫ضرب دو ماتریس با استفاده از سه حلقه تودرتو قابل محاسبه است که در کد زیر در خط ‪ 46‬تا ‪ 56‬مشخص شده‬
‫است‪:‬‬

‫‪𝑎𝑟𝑟3[0][0] = 𝑎𝑟𝑟1[0][0] ∗ 𝑎𝑟𝑟2[0][0] +‬‬

‫‪𝑎𝑟𝑟1[0][1] ∗ 𝑎𝑟𝑟2[1][0] +‬‬

‫‪𝑎𝑟𝑟1[0][2] ∗ 𝑎𝑟𝑟2[2][0] +‬‬

‫‪𝑎𝑟𝑟3[0][1] = 𝑎𝑟𝑟1[0][0] ∗ 𝑎𝑟𝑟2[0][1] +‬‬

‫‪𝑎𝑟𝑟1[0][1] ∗ 𝑎𝑟𝑟2[1][1] +‬‬

‫‪𝑎𝑟𝑟1[0][2] ∗ 𝑎𝑟𝑟2[2][1] +‬‬

‫در حالت کلي داریم‪:‬‬

‫‪𝑎00‬‬ ‫‪𝑎01 𝑏00‬‬ ‫‪𝑐00‬‬


‫𝑎[‬ ‫]‬ ‫[‬
‫‪𝑎11 𝑏10‬‬ ‫]‬ ‫=‬ ‫[‬ ‫] ‪𝑐10‬‬
‫‪10‬‬

‫) ‪𝑐00 = ( 𝑎00 ∗ 𝑏00 ) + (𝑎01 ∗ 𝑏10‬‬

‫) ‪𝑐10 = ( 𝑎10 ∗ 𝑏00 ) + (𝑎11 ∗ 𝑏10‬‬

‫‪51‬‬
‫الگوریتم ضرب ‪: Strasson‬‬ ‫‪-6-4‬‬
‫همانطور که ميدانیم برای کامپیوتر محاسبه ضرب سختتر از محاسبه جمع است؛ بنابراین در حل یک مسأله‬
‫اگر بتوان از تعداد ضربها کاست‪ ،‬آن الگوریتم بهینهتر خواهد بود‪.‬‬

‫الگوریتم ‪ Strasson‬ماتریسها را به روشي ضرب ميکند که تعداد ضربها به ویژه در ابعاد باال بسیار کاهش‬
‫پیدا ميکند‪.‬‬

‫الگوریتم ضرب ‪ Strasson‬برای دو ماتریس ‪ 2*2‬به شکل زیر خواهد بود‪:‬‬

‫‪𝑎00‬‬ ‫‪𝑎01 𝑏00‬‬ ‫‪𝑏01‬‬ ‫‪𝑐00‬‬ ‫‪𝑐01‬‬


‫𝑎[‬ ‫‪𝑎11 ] [𝑏10‬‬ ‫𝑐[ = ]‬ ‫] ‪𝑐11‬‬
‫‪10‬‬ ‫‪𝑏11‬‬ ‫‪10‬‬

‫) ‪𝑚0 = (𝑎00 + 𝑎11 )(𝑏00 + 𝑏11‬‬

‫‪𝑚1 = (𝑎10 + 𝑎11 )𝑏00‬‬

‫) ‪𝑚2 = 𝑎00 (𝑏01 − 𝑏11‬‬

‫) ‪𝑚3 = 𝑎11 (𝑏10 − 𝑏00‬‬

‫‪𝑚4 = (𝑎00 + 𝑎01 )𝑏11‬‬

‫) ‪𝑚5 = (𝑎10 − 𝑎00 )(𝑏00 + 𝑏01‬‬

‫) ‪𝑚6 = (𝑎01 + 𝑎11 )(𝑏10 + 𝑏11‬‬

‫ماتریس ‪ c‬از روابط باال به این صورت حاصل ميگردد‪:‬‬

‫‪𝑚0 + 𝑚3 − 𝑚4 + 𝑚6‬‬ ‫‪𝑚2 + 𝑚4‬‬


‫[=𝑐‬ ‫‪𝑚1 + 𝑚3‬‬ ‫] ‪𝑚0 + 𝑚2 − 𝑚1 + 𝑚5‬‬

‫مثال‪:‬‬

‫‪5 3‬‬ ‫‪4 2‬‬ ‫‪23‬‬ ‫‪16‬‬


‫[‬ ‫[∗]‬ ‫[=]‬ ‫]‬
‫‪2 1‬‬ ‫‪1 2‬‬ ‫‪9‬‬ ‫‪6‬‬
‫‪𝑚0 = ( 5 + 1 )( 4 + 2 ) = 6 ∗ 6 = 36‬‬
‫‪𝑚1 = ( 2 + 1 ) * 4 = 3 * 4 = 12‬‬
‫‪𝑚2 = 5 ∗ ( 2 − 2 ) = 5 ∗ 0 = 0‬‬
‫‪𝑚3 = 1 ∗ ( 1 − 4 ) = 1 ∗ −3 = −3‬‬
‫‪𝑚4 = ( 5 + 3 ) ∗ 2 = 8 ∗ 2 = 16‬‬
‫‪𝑚5 = ( 2 − 5 )( 4 + 2 ) = −3 ∗ 6 = −18‬‬

‫‪52‬‬
‫‪𝑚6 = ( 3 − 1 ) ∗ ( 1 + 2 ) = 2 ∗ 3 = 6‬‬
‫در نتیجه ماتریس ‪ c‬خواهد بود‪:‬‬

‫‪36 + (−3) − 16 + 6‬‬ ‫‪0 + 16‬‬ ‫‪23‬‬ ‫‪16‬‬


‫[=𝑐‬ ‫[=]‬ ‫]‬
‫)‪12 + (−3‬‬ ‫)‪36 + 0 − 12 + (−18‬‬ ‫‪9‬‬ ‫‪6‬‬

‫شبهکد الگوریتم ‪: Strasson‬‬

‫نمونه سؤال‪ :‬الگوریتم ‪ Strasson‬چیست و چگونه مسأله را حل ميکند؟ از چه الگوریتمي برای حل‬
‫مسألهاش استفاده کرده است؟ چه مزایایي نسبت به حالت عادی حل مسأله دارد؟‬

‫پاسخ‪ :‬این لگوریتم روش جدیدی برای حل مسأله ضرب دو ماتریس ‪ n*n‬مربع است که با کاهش تعداد‬
‫ضربها باعث ميشود‪ ،‬پردازشها کاهش یافته و سریعتر نتایج به دست آید‪ .‬کاربرد عملي این الگوریتم در‬
‫ضرب ماتریسهای بزرگ است‪ ،‬هرچند که نسبت به الگوریتمهای جدیدتر کمي کندتر است‪.‬‬

‫تمرین‪ :‬یک الگوریتم جدیدتر و سریعتر نسبت به ‪ Strasson‬پیدا کنید‪.‬‬

‫ضرب اعداد بزرگ‪:‬‬ ‫‪-6-5‬‬


‫دو عدد ‪ u‬و ‪ v‬هر کدام ‪ n‬رقمي را در نظر بگیرید‪ .‬برای محاسبه ‪ u*v‬ميتوان به روش زیر عمل کرد‪:‬‬

‫𝑛‬
‫=𝑚‬
‫‪2‬‬
‫𝑦 ‪𝑢 = 𝑥 ∗ 10𝑚 +‬‬

‫‪53‬‬
‫𝑧 ‪𝑣 = 𝑤 ∗ 10𝑚 +‬‬

‫𝑦𝑧 ‪𝑢 ∗ 𝑣 = ( 𝑥 ∗ 10𝑚 + 𝑦 )( 𝑤 ∗ 10𝑚 + 𝑧) = 𝑥𝑤102𝑚 + (𝑥𝑧 + 𝑦𝑤) ∗ 10𝑚 +‬‬

‫مثال‪ :‬دو عدد ‪ 102436‬و ‪ 724300‬را با هم ضرب کنید‪.‬‬

‫𝑛‬ ‫‪6‬‬
‫=𝑚‬ ‫‪= =3‬‬
‫‪2‬‬ ‫‪2‬‬
‫‪𝑢 = 102436 = 102 ∗ 103 + 436 , 𝑣 = 724300 = 724 ∗ 103 + 300‬‬

‫)‪𝑢𝑣 = ( 102 ∗ 724 ) ∗ 106 + ( 102 ∗ 300 + 436 ∗ 724 ) ∗ 103 + ( 300 ∗ 436‬‬

‫‪1‬‬
‫برنامهنویسی با حافظه پویا‪:‬‬ ‫‪-6-6‬‬
‫برنامهنویسي پویا یک روش نوشتن الگوریتمهاست که در آن مسأله اصلي را به استفاده از یک فرمول بازگشتي‬
‫حل ميکنیم؛ یعني در ابتدا برای مسأله‪ ،‬یک ضابطه بازگشتي ميیابیم‪ .‬سپس با استفاده از یک حافظه سعي بر آن‬
‫داریم‪ .‬که در ابتدا مسأله را برای مقادیر اولیه حل کنیم سپس با ترکیب حلهای مقدماتيتر حل مسأله را در‬
‫حالت باالتر دنبال مينماییم‪ .‬این روند را تا آنجا ادامه ميدهیم که به پاسخي برای مسأله اصلي دست یابیم‪.‬‬

‫روش ‪ DP‬از آنجا ابداع گردید که بتواند راهحلهای تکراری را که ممکن است در روش ‪( D&C‬تقسیم و‬
‫غلبه) به وجود آید را حذف نماید‪.‬‬

‫در اینجا راهحل‪ ،‬راهحلي ‪ Button-Up‬است‪.‬‬

‫محاسبه تراز چند دانشجو‪:‬‬ ‫‪-6-7‬‬


‫فرمول محاسبه تراز‪:‬‬
‫‪𝑇 = 1000𝑧 + 5000‬‬
‫فرمول محاسبه ‪:z‬‬
‫𝑥‪𝑥−‬‬
‫=𝑧‬
‫𝑠‬
‫در این فرمول‪:‬‬
‫‪ x‬نمره خام داوطلب در درس موردنظر است‪.‬‬
‫̅‪ x‬میانگین نمرات کل داوطلبین در درس موردنظر است‪.‬‬
‫‪ s‬همان انحراف از معیار یا ‪ Standard Deviation‬است‪.‬‬

‫‪1‬‬
‫‪Dynamic Programming‬‬

‫‪54‬‬
‫فرمول محاسبه ‪:s‬‬
‫𝑧 )𝑥 ‪∑𝑛 (𝑥𝑖 −‬‬
‫‪𝑠 = √ 𝑖=0‬‬
‫𝑁‬
‫‪ N‬تعداد کل شرکتکنندگان است‪.‬‬

‫مثال‪ :‬فرض کنید سه نفر در یک درس فرضي‪ ،‬نمرههای ‪ 100‬و ‪ 200‬و ‪ 300‬را گرفتهاند‪ .‬تراز هر کدام از این سه‬
‫نفر را حساب کنید‪.‬‬

‫‪𝑛 = 3 , 𝑥1 = 100 , 𝑥2 = 200 , 𝑥3 = 300‬‬


‫‪100 + 200 + 300‬‬
‫=𝑥‬ ‫‪= 200‬‬
‫‪3‬‬
‫‪3‬‬‫‪(100 − 200 )2‬‬ ‫‪10000‬‬
‫= ∑‬ ‫=‬ ‫‪= 3333.33‬‬
‫‪1‬‬ ‫‪3‬‬ ‫‪3‬‬
‫‪3‬‬‫‪(200 − 200 )2‬‬ ‫‪0‬‬
‫= ∑‬ ‫‪= =0‬‬
‫‪2‬‬ ‫‪3‬‬ ‫‪3‬‬
‫‪3‬‬‫‪(300 − 200 )2‬‬ ‫‪10000‬‬
‫= ∑‬ ‫=‬ ‫‪= 3333.33‬‬
‫‪3‬‬ ‫‪3‬‬ ‫‪3‬‬

‫‪∑31( 𝑥𝑖 − 𝑥 )2‬‬
‫√=𝑠‬ ‫‪= √3333.33 + 3333.33 = 81.65‬‬
‫‪3‬‬

‫𝑥 ‪𝑥1 −‬‬ ‫‪100 − 200‬‬


‫= ‪𝑧1‬‬ ‫=‬ ‫‪= −1.22‬‬
‫𝑠‬ ‫‪81.65‬‬
‫𝑥 ‪𝑥2 −‬‬ ‫‪200 − 200‬‬
‫= ‪𝑧2‬‬ ‫=‬ ‫‪= 0‬‬
‫𝑠‬ ‫‪81.65‬‬
‫𝑥 ‪𝑥3 −‬‬ ‫‪300−200‬‬
‫= ‪𝑧3‬‬ ‫=‬ ‫‪= 1.22‬‬
‫𝑠‬ ‫‪81.65‬‬

‫‪𝑇1 = 1000( −1.22) + 5000 = 3780‬‬

‫‪𝑇2 = 1000( 0 ) + 5000 = 5000‬‬

‫‪𝑇3 = 1000(1.22) + 5000 = 6220‬‬

‫‪55‬‬
‫اگر به محاسبات باال دقت کنید؛ برای هر نفر به صورت تکراری ̅‪ x‬و ‪ s‬مجددا محاسبه شده است‪ .‬این درحالی‬
‫است که محاسبهی هر یک از اینها در آمار باال پردازش باالیی نیاز دارد‪ .‬برای رفع این مشکل میتوان از‬
‫برنامه نویسی پویا استفاده کنیم؛ به این صورت که وقتی برای نفر اول ̅‪ x‬و ‪ s‬محاسبه شد‪ ،‬در بخشی از حافظه‬
‫نگه داشته شود و برای نفرات بعد از همان دادهها استفاده شود‪.‬‬

‫مسأله انتخاب ‪ k‬شیئ از ‪ n‬شیئ (محاسبه )𝐤𝐧()‪:‬‬ ‫‪-6-8‬‬


‫فرض کنید در یک کیسه ‪ 4‬گوی با رنگهای مختلف (سیاه‪ ،‬سقید‪ ،‬قرمز و آبي) وجود دارد‪ ،‬به چند حالت‬
‫ميتوان ‪ 2‬گوی از کیسه خارج کرد؟‬

‫!𝑛‬
‫= )‪(nk‬‬ ‫!𝑘!)𝑘‪(𝑛−‬‬
‫فرمول ‪:‬‬

‫‪4‬‬ ‫!‪4‬‬ ‫!‪4 ∗ 3 ∗ 2‬‬ ‫‪4∗3‬‬


‫=) (‬ ‫=‬ ‫=‬ ‫‪=6‬‬
‫‪2‬‬ ‫!‪(4 − 2 )! 2‬‬ ‫!‪2 ∗ 1 ∗ 2‬‬ ‫‪2∗ 1‬‬

‫‪1‬‬ ‫𝑛 = 𝑘 𝑟𝑜 ‪𝑘 = 0‬‬
‫)‪(nk) = {(𝑛−1) + (𝑛−1‬‬ ‫𝑒𝑠𝑙𝑒‬ ‫برای نوشتن برنامه مسأله ثابت ميکنیم که‪:‬‬
‫𝑘‬ ‫‪𝑘−1‬‬

‫با مثال زیر ثابت ميشود که این رابطه صحیح است‪ ،‬در نتیجه با یک تابع بازگشتي ميتوان مسأله را پیادهسازی‬
‫کرد‪.‬‬

‫‪56‬‬
‫اما بدون استفاده از برنامهنویسي پویا‪ ،‬مسأله‪ ،‬بهینه نخواهد بود‪ ،‬چرا که برخي محاسبات چندین بار انجام شده‬
‫است‪ .‬برای بهینه کردن این مسأله‪ ،‬برنامهنویسي پویا را به شکل زیر پیادهسازی ميکنیم‪:‬‬

‫آرایهای به شکل زیر ایجاد ميکنیم که مقادیر به دست آمده از پردازشهای تکراری در آن ذخیره ميشود و‬
‫هرگاه به پاسخ آن پردازش نیاز بود‪ ،‬از آرایه خوانده و استفاده ميکنیم‪.‬‬

‫𝑛‬
‫) (‬
‫𝑘‬ ‫‪0‬‬ ‫‪1‬‬ ‫‪2‬‬ ‫‪3‬‬ ‫‪4‬‬ ‫‪5‬‬ ‫‪6‬‬

‫‪0‬‬ ‫‪1‬‬

‫‪1‬‬ ‫‪1‬‬ ‫‪1‬‬

‫‪2‬‬ ‫‪1‬‬ ‫‪2‬‬ ‫‪1‬‬

‫‪3‬‬ ‫‪1‬‬ ‫‪3‬‬ ‫‪3‬‬ ‫‪1‬‬

‫‪4‬‬ ‫‪1‬‬ ‫‪4‬‬ ‫‪6‬‬ ‫…‬ ‫‪1‬‬

‫‪5‬‬ ‫‪1‬‬ ‫‪5‬‬ ‫⋮‬ ‫‪1‬‬

‫‪6‬‬ ‫‪1‬‬ ‫‪6‬‬

‫پیادهسازی مسأله بدون استفاده از برنامهنویسي پویا‪:‬‬

‫پیادهسازی مسأله با استفاده از برنامهنویسي پویا‪:‬‬

‫‪57‬‬
‫حل مسأله فیبوناچی با استفاده از برنامهنویسی پویا‪:‬‬ ‫‪-6-9‬‬
‫برای حل این مسأله یک آرایه به تعداد جمله خواسته شده ( )‪n‬تعریف ميکنیم و یک بار برای همیشه جمع هر‬
‫دو خانه را در خانه بعد از آن ميریزیم (یا جمع هر دو خانه را در خانه قبل آنها ميریزیم)‪ ،‬با اینکار آرایهای به‬
‫شکل زیر خواهیم داشت‪:‬‬

‫… ‪0 1 1 2 3 5 8 13 21 33‬‬
‫که بهراحتي خانه ‪n‬اُم آرایه که برابر با پاسخ مسأله هست بدون نیاز به محاسبهِ تکراریِ جملههایِ قبل از آن به‬
‫دست ميآید‪.‬‬

‫‪58‬‬
‫تمرین‪ :‬برنامهی فیبوناچي را با استفاده از بازگشتي و برنامهنویسي پویا نوشته و از لحاظ زمان اجرا با هم مقایسه‬
‫کنید‪.‬‬

‫پاسخ‪ :‬بازگشتي‪ :‬با توجه به اینکه عملیات اصلي در تابع بازگشتي جمع )‪ fib(n – 1) + fib(n - 2‬و بهازای‬
‫‪ T(n - 1) + T(n - 2) + O(1) ،n‬بار اجرا ميشود؛ بنابراین این روش )‪ O(2n‬است‪.‬‬

‫در روش دوم‪ :‬با توجه به اینکه عملیات اصلي]‪ f [i] = f [i - 1] + f [i - 2‬است و این حلقه ‪ n*c‬بار تکرار‬
‫ميشود‪ .‬این روش نیز )‪ O(n‬است‪.‬‬

‫مسأله فلوید‪:‬‬ ‫‪-6-10‬‬


‫یکي از مهمترین مسائل در دنیای امروز یافتن کوتاهترین مسیر بین دو نقطه است؛ برای مثال در گراف جهتدار‬
‫ابرکوتاهترین مسیر بین دو روتر از الگوریتمهای یافتن مسیر استفاده ميشود‪.‬‬

‫الگوریتمهای بسیار زیادی برای یافتن کوتاهترین مسیر ارائه شده است که هر کدام از آنها مزایا و معایبي دارد؛‬
‫برای مثال یکي پیادهسازی آسان ولي )‪ T(n‬باالیي دارد و برعکس‪.‬‬

‫کاربرد فلوید در نرمافزارهایي مانند گوگل مپ و نرمافزارهای مشابه برای یافتن کوتاهترین مسیر بین دو شهر‬
‫است‪.‬‬

‫یکی از الگوریتمها فِلوید‪-‬وارشال است‪ .‬با یک مثال روش کار آن را توضیح میدهیم‪.‬‬

‫مثال‪ :‬کوتاهترین مسیر در گراف زیر را با روش فلوید به دست آورید‪.‬‬

‫گام ‪ :۱‬ماتریس مجاورت (‪ )m‬را برای همهی گرهها بهدست آورید‪( .‬ماتریس مجاورت‪ ،‬ماتریسی است که نشان‬
‫می دهد از هر گره به گره دیگر یک مسیر مستقیم وجود دارد یا خیر؟ اگر وجود داشت‪ ،‬وزن یال نوشته‬

‫‪59‬‬
‫میشود و اگر وجود نداشت عالمت ∞ و طبیعتا از هر گره به همان گره‪ ،‬وزن یال برابر با صفر خواهد بود‪).‬‬
‫‪ D0‬را برابر ‪ m‬بگیرید‪.‬‬

‫‪0‬‬ ‫∞ ‪5‬‬ ‫∞‬


‫‪5‬‬
‫‪D0 = 𝑚 = [ 50‬‬ ‫‪0 15‬‬ ‫]‬
‫‪30‬‬ ‫‪∞ 0‬‬ ‫‪15‬‬
‫‪15‬‬ ‫‪∞ 5‬‬ ‫‪0‬‬
‫دقت کنید که سطر و ستونها همان رأسها هستند؛ یعنی‪:‬‬

‫گام ‪ D1 :2‬را طوری بسازید که مشخصکننده مینیمم مسیرهایي باشد که فقط از ‪ v1‬ميگذرد و یا مسیر مستقیم‬
‫هستند‪.‬‬

‫‪0‬‬ ‫‪5‬‬ ‫∞‬ ‫∞‬ ‫‪0‬‬ ‫‪0‬‬ ‫∞‬ ‫∞‬


‫‪5‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬
‫‪D1 = [ 50‬‬ ‫‪0 15‬‬ ‫]‬ ‫[=‪P‬‬ ‫]‬
‫‪30‬‬ ‫‪35 0‬‬ ‫‪15‬‬ ‫‪0‬‬ ‫‪𝑣1‬‬ ‫‪0‬‬ ‫‪0‬‬
‫‪15‬‬ ‫‪20 5‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪𝑣1‬‬ ‫‪0‬‬ ‫‪0‬‬

‫گام ‪ D2 :3‬را طوری بسازید که شامل کوتاهترین مسیرهایي باشد که از ‪ v1‬یا ‪ v2‬عبور ميکنند و یا مستقیم‬
‫هستند‪.‬‬

‫‪0‬‬ ‫‪5 20‬‬ ‫‪10‬‬ ‫‪0‬‬ ‫‪0 𝑣2‬‬ ‫‪𝑣2‬‬


‫‪5‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬
‫‪D2 = [ 50‬‬ ‫‪0 15‬‬ ‫]‬ ‫[=‪P‬‬ ‫]‬
‫‪30‬‬ ‫‪35 0‬‬ ‫‪15‬‬ ‫‪0‬‬ ‫‪𝑣1 0‬‬ ‫‪0‬‬
‫‪15‬‬ ‫‪20 5‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪𝑣1 0‬‬ ‫‪0‬‬

‫گام ‪ D3 :4‬را طوری بسازید که شامل کوتاهترین مسیرهایي باشد که از ‪ v1‬یا ‪ v2‬یا ‪ v3‬ميگذرد و یا مستقیم‬
‫است‪.‬‬

‫‪0‬‬ ‫‪5 20‬‬ ‫‪10‬‬ ‫‪0‬‬ ‫‪0 𝑣2‬‬ ‫‪𝑣2‬‬


‫‪5‬‬ ‫𝑣‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪0‬‬
‫‪D3 = [ 45‬‬ ‫‪0 15‬‬ ‫]‬ ‫‪P=[ 3‬‬ ‫]‬
‫‪30‬‬ ‫‪35 0‬‬ ‫‪15‬‬ ‫‪0‬‬ ‫‪𝑣1 0‬‬ ‫‪0‬‬
‫‪15‬‬ ‫‪20 5‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪𝑣1 0‬‬ ‫‪0‬‬

‫‪60‬‬
‫گام ‪ D4 :5‬را طوری بسازید که شامل کوتاهترین مسیرهایي باشد که از ‪ v1‬یا ‪ v2‬یا ‪ v3‬یا ‪ v4‬عبور کند و یا‬
‫مستقیم باشد‪.‬‬

‫‪0‬‬ ‫‪5 15‬‬ ‫‪10‬‬ ‫‪0‬‬ ‫‪0 𝑣4‬‬ ‫‪𝑣2‬‬


‫‪5‬‬ ‫𝑣‬ ‫‪0 𝑣4‬‬ ‫‪0‬‬
‫‪D4 = [ 20‬‬ ‫‪0 10‬‬ ‫]‬ ‫‪P=[ 4‬‬ ‫]‬
‫‪30‬‬ ‫‪35 0‬‬ ‫‪15‬‬ ‫‪0‬‬ ‫‪𝑣1 0‬‬ ‫‪0‬‬
‫‪15‬‬ ‫‪20 5‬‬ ‫‪0‬‬ ‫‪0‬‬ ‫‪𝑣1 0‬‬ ‫‪0‬‬

‫گام ‪ :6‬ماتریس ‪ P‬را در حین ساختن ماتریسهای ‪ D‬به صورت زیر پر کنید‪( .‬همینطور که از ‪ D1‬به ‪ Dk‬پیش‬
‫ميروید)‪ ،‬وقتي کوتاهترین مسیر به دست آمد‪ ،‬رأس جدیدی که باعث به وجود آمدن مسیر کوتاهتر شده را در‬
‫‪ P‬یادداشت کنید‪ .‬اگر از یک رأس به رأس دیگر مسیر مستقیم وجود داشت و این مسیر کوتاهترین مسیر بود در‬
‫‪ ،P‬صفر قراردهید‪.‬‬

‫‪0‬‬ ‫‪0 𝑣4‬‬ ‫‪𝑣2‬‬


‫𝑣‬ ‫‪0 𝑣4‬‬ ‫‪0‬‬
‫‪P=[ 4‬‬ ‫]‬
‫‪0‬‬ ‫‪𝑣1 0‬‬ ‫‪0‬‬
‫‪0‬‬ ‫‪𝑣1 0‬‬ ‫‪0‬‬

‫گام آخر‪ :‬برای به دست آوردن کوتاهترین مسیر بین دو رأس به ماتریس ‪ P‬نگاه کنید‪ .‬اگر بین آن دو رأس نام‬
‫یک رأس دیگر نوشته شده‪ ،‬مسأله را برای یافتن کوتاهترین مسیر بین آن رأس و ردس مبدأ تبدیل کنید و آنقدر‬
‫این کار را تکرار کنید تا نهایتاً به صفر برسید و صفر به معني این است که بین رأس یک مانده به آخر و رأس‬
‫آخر مسیر مستقیمي وجود دارد که کوتاهترین مسیر است‪.‬‬

‫مثال‪ :‬کوتاهترین مسیر بین ‪ v1‬و ‪ v4‬را به دست آورید‪.‬‬

‫پاسخ‪ :‬طبق ماتریس‪ v1 ،P‬به ‪ v4‬از ‪ v2‬ميگذرد‪ ،‬پس داریم‪:‬‬

‫یعني مسأله از یافتن ‪ v1‬به ‪ v4‬به یافتن کوتاهترین مسیر از ‪ v2‬به ‪ v4‬تبدیل شد‪ .‬مجدداً طبق ماتریس ‪ P‬خانهی‬
‫مربوط به ‪ v2‬به ‪ v4‬صفر است؛ یعني از ‪ v2‬به ‪ v4‬مسیر مستقیمي وجود دارد که کوتاهترین مسیر است‪ ،‬پس در‬
‫نهایت کوتاهترین مسیر بین ‪ v1‬و ‪ v4‬مسیر زیر خواهد بود‪:‬‬

‫‪61‬‬
‫الگوریتم فلوید با سه حلقهی تو در تو به شکل زیر قابل پیادهسازی است‪:‬‬

‫‪62‬‬
‫فصل هفتم‬

‫‪1‬‬
‫تکنیکهای طراحی الگوریتم (‪ :)3‬روشهای حریصانه‬

‫دستهای از مسائل وجود دارد که برای حل آنها در طول اجرای برنامه باید همیشه کوچکترین یا بزرگترین‬
‫مقدار از یک مجموعه مقدار انتخاب شود‪ .‬این مسائل با استفاده از الگوریتمهای حریصانه حل ميشود‪.‬‬

‫مسأله خرد کردن پول‪:‬‬ ‫‪-7-1‬‬


‫مثال ‪ :1‬فرض کنید تعدادی سکه به صورت زیر داریم و ميخواهیم ‪ 36‬تومان با استفاده از این سکهها خرد‬
‫کنیم‪ ،‬با این شرط که کمترین تعداد سکه به دست آید‪:‬‬

‫برای حل این مسأله ابتدا سکهها را از بزرگ به کوچک مرتب ميکنیم و سپس بهطور حریصانه ابتدا بزرگترین‬
‫سکه را انتخاب ميکنیم و باقیمانده سکههای انتخاب شده تا مبلغ موردنظر را به دست آورده و مالک انتخاب‬
‫سکههای بعدی قرار ميدهیم؛ بنابراین مراحل به شکل زیر خواهد بود‪:‬‬

‫‪Greedy Algorithms‬‬
‫‪1‬‬

‫‪63‬‬
‫نکته مهم‪ :‬راهحل حریصانه همیشه بهترین پاسخ را به دست نميآورد‪ ،‬چرا که بزرگترین مشکل این روش‬
‫بهینهگی محلی‪1‬است‪ .‬بهینهگي محلي یعني ممکن است یک پاسخ در مقطعي از زمان درست به نظر برسد امّا‬
‫اگر بازهی زماني افزایش پیدا کند‪ ،‬آن پاسخ نسبت به کل‪ ،‬پاسخ صحیحي نیست‪ .‬به شکل زیر دقت کنید‪:‬‬

‫فرض کنید که قرار است برنامهای بنویسید که بلندترین قله را در میان یکسری عدد پیدا کند‪ ،‬اگر شما برنامه را‬
‫طوری نوشته باشید که به محض رسیدن به نقطهای که ]‪ 𝑛𝑢𝑚𝑠 [𝑖] < 𝑛𝑢𝑚𝑠 [𝑖 − 1‬است‪ ،‬آن را قله‬
‫اعالم کند‪ ،‬با توجه به شکل خواهید دید که در نقطهی ‪ A‬برنامه متوقف خواهد شد‪ ،‬در حاليکه نقطهی ‪ B‬نیز‬
‫این ویژگي را دارد و از نقطهی ‪ A‬بلندتر است‪.‬‬

‫مثال ‪ :2‬با استفاده از سکههای زیر ‪ 16‬تومان پول خرد به دست آورید‪ ،‬با همان شرط که حداقل سکهها به دست آید‪.‬‬

‫راهحل‪ :‬اگر با همان الگوریتم قبل مسأله را حل کنیم‪ ،‬خواهیم دید که پاسخ به صورت زیر خواهد بود‪:‬‬

‫در این حالت ميبینیم که پاسخ ‪ 12 ،1 ،1 ،1 ،1‬بهعنوان پاسخ نهایي انتخاب ميشود‪ ،‬در حالي که پاسخ بهینهتر‬
‫‪ 10 ،5 ،1‬است‪.‬‬

‫تمرین‪ :‬برای مسأله باال یک راهحل معتبر ارائه کنید‪.‬‬

‫‪1‬‬
‫‪Local Optima‬‬

‫‪64‬‬
‫‪1‬‬
‫مسأله کد هافمن‪:‬‬ ‫‪-7-2‬‬
‫الگوریتم هافمن برای فشردهسازی دادهها استفاده ميشود‪.‬‬

‫فرض کنید قرار است رشتهی زیر را فشرده کنیم‪:‬‬

‫𝑎𝑑𝑒𝑑𝑑𝑐𝑐𝑏𝑏𝑎𝑎𝑑𝑐𝑏𝑎𝑎𝑏𝑎‬

‫هافمن به روش زیر این رشتهها را فشرده ميکند‪:‬‬

‫گام ‪ :1‬فرکانس (تعداد تکرار) هر کاراکتر را به دست آورید‪ ،‬پس داریم‪:‬‬

‫‪𝑎: 6‬‬ ‫‪𝑏: 4‬‬ ‫‪𝑐: 3‬‬ ‫‪𝑑: 4‬‬ ‫‪𝑒: 1‬‬

‫(فرکانس‪ 2،‬تعداد تکرار هر چیز معموالً در واحد زمان است و نام فارسي آن بسامد ميباشد‪).‬‬

‫گام ‪ :2‬از سمت چپ دو کاراکتری را که کمترین تکرار را دارند انتخاب کنید و جمع آنها را به دست آورید‪.‬‬
‫(‪ d:4‬و ‪ b:4‬انتخاب شدهاند و جمع آنها یعني ‪ 8‬در باالی آنها نوشته شده است)‬

‫گام ‪ :3‬مجدداً از سمت چپ دو کاراکتر دیگر را که کمترین تکرار را دارند‪ ،‬انتخاب و جمع آنها را به دست‬
‫آورید‪ .‬فقط توجه کنید که دایرهی مربوط به جمعهای قبلي نیز بهعنوان یک کاراکتر قابل انتخاب خواهند بود‪.‬‬

‫گام ‪ :4‬این کار را تکرار کنید تا کاراکتری برای جمع باقي نماند‪.‬‬

‫گام ‪ :5‬با توجه به گامهای باال درخت هافمن به شکل زیر از پایین به باال ساخته خواهد شد‪ .‬از ریشه شروع کنید‬
‫و به یال سمت چپ‪ ،‬صفر و به یال سمت راست‪ ،‬یک نسبت دهید‪.‬‬

‫‪1‬‬
‫‪Hafman‬‬
‫‪2‬‬
‫‪Frequency: Cycles Per Time Unit‬‬

‫‪65‬‬
‫گام آخر‪ :‬کد هافمنِ هر کاراکتر‪ ،‬رشتهای از صفر و یکها از ریشه به سمت آن کاراکتر خواهد بود‪.‬‬

‫با توجه به توضیحات داده شده به جای ذخیره کردن یا ارسال کاراکتر ‪ a‬که ‪ 8‬بیت اشغال خواهد کرد‪ ،‬کد‬
‫هافمن آن یعني ‪ 00‬را ذخیره یا ارسال ميکنیم که مشخص است که حداقل ‪ 6‬بیت بهازای هر ‪ a‬فشردهسازی‬
‫داریم‪ .‬در بقیه حروف نیز به همین صورت‪.‬‬

‫نکته‪ :‬باید یک فضا هم برای ذخیره کردن کد هر حرف در نظر بگیریم که در مقصد بفهمیم که برای مثال‬
‫منظور از ‪ 00‬کاراکتر ‪ a‬بوده است‪.‬‬

‫‪66‬‬
‫‪1‬‬
‫مسأله درخت پوشای کمینه‪:‬‬ ‫‪-7-3‬‬
‫درخت پوشای کمینه با درخت فراگیر مینیمم در گرافهای ارزشدار (وزندار) ساخته ميشود‪.‬‬

‫فرض کنید گراف‪ ،‬یک گراف همبند باشد (یعني بین هر دو رأس متمایز آن‪ ،‬یک مسیر وجود داشته باشد)‬
‫منظور از یک درخت پوشا از این گراف‪ ،‬درختي است که شامل همه رئوس این گراف باشد ولي فقط بعضي از‬
‫یالهای آن را در برگیرد‪.‬‬

‫منظور از درخت پوشای مینیمم (برای گراف همبند وزندار) درختي است که بین درختهای پوشای آن‬
‫گراف‪ ،‬مجموع وزن یالهای آن‪ ،‬کمترین مقدار ممکن باشد‪.‬‬

‫مثال‪ :‬گراف همبند زیر را در نظر بگیرید‪ .‬گراف ‪( MST‬درخت پوشای کمینه) آن را به دست آورید‪.‬‬

‫راهحل‪ :‬برای حل مسأله از ‪ v1‬شروع ميکنیم و بهطور حریصانه یالي که کمترین وزن را دارد و به یکي از‬
‫رأسهای پیمایششده متصل است‪ ،‬به عنوان ادامه مسیر انتخاب ميکنیم‪ .‬فقط باید توجه کرد که مسیر الزم‬
‫نیست حتماً به صورت حلقه و بههم پیوسته باشد‪.‬‬

‫مراحل به شکل زیر خواهد بود‪:‬‬

‫‪1‬‬
‫‪Minimum Spanning Tree‬‬

‫‪67‬‬
‫‪1-‬‬

‫‪2-‬‬ ‫‪4-‬‬

‫‪3-‬‬
‫‪5-‬‬

‫با استفاده از تابع ‪ Prim‬به صورت زیر ميتوان این الگوریتم را پیادهسازی کرد‪:‬‬

‫‪68‬‬
‫تمرین‪ :‬در گراف همبند زیر درخت ‪ MST‬را به دست آورید‪.‬‬

‫‪1‬‬
‫مسأله فروشنده دورهگرد‪:‬‬ ‫‪-7-1‬‬

‫صورت این مسأله به این شکل است‪ :‬اگر یک فروشنده دورهگرد از نقطه ‪ A‬شروع کند و فواصل بین نقاط‬
‫مشخص باشد‪ ،‬کوتاهترین مسیر که از تمام نقاط یکبار بازدید کند و به ‪ A‬بازگردد‪ ،‬کدام است؟‬

‫در مسأله فروشنده دورهگرد باید از رأس ‪ v1‬به رأسهای دیگر مسیر بههم پیوستهای را پیدا کنید که ضمن گذر‬
‫از همه رئوس به رأس ‪ v1‬برگردد‪ .‬ضمناً این مسیر کمینه نیز باشد و خیلي مهم است که گراف جهتدار باشد‪.‬‬

‫مثال‪ :‬بهترین مسیر برای فروشنده دورهگرد در گراف زیر چیست؟‬

‫پاسخ‪:‬‬

‫‪1‬‬
‫‪Travelling Salesman Problem‬‬

‫‪69‬‬
‫الگوریتم کراسکال‪:‬‬ ‫‪-7-2‬‬
‫این الگوریتم نیز برای به دست آوردن درخت پوشای کمینه استفاده ميشود‪ ،‬با این تفاوت که مراحل آن با کمي‬
‫تفاوت به شکل زیر است‪:‬‬

‫مرحله ‪ :1‬یالها را برحسب وزنشان مرتب کنید‪.‬‬

‫)‪( 𝑣1 , 𝑣2 ∶ 1‬‬

‫)‪( 𝑣3 , 𝑣5 ∶ 2‬‬

‫)‪( 𝑣1 , 𝑣3 ∶ 3‬‬

‫)‪( 𝑣2 , 𝑣3 ∶ 3‬‬

‫)‪( 𝑣3 , 𝑣4 ∶ 4‬‬

‫)‪( 𝑣4 , 𝑣5 ∶ 5‬‬

‫)‪( 𝑣2 , 𝑣4 ∶ 6‬‬

‫‪70‬‬
‫مرحله ‪ :2‬هر یالي که ایجاد دور نکرد‪ ،‬انتخاب کنید‪.‬‬

‫الگوریتم دکسترا‪:‬‬ ‫‪-7-3‬‬


‫این الگوریتم نیز یکي از الگوریتمهای پیمایش گراف است که‪ ،‬مسأله «کوتاهترین مسیر از مبدأ واحد» را برای‬
‫گرافهای وزنداری که یال یا وزن منفي ندارند حل ميکند و در نهایت با ایجاد درخت کوتاهترین مسیر‪،‬‬
‫کوتاهترین مسیر از مبدأ به همه رأسهای گراف را به دست ميدهد‪.‬‬

‫توضیح‪:‬‬

‫از رأس ‪ v1‬شروع کنید و پس از آن رأسي را انتخاب کنید که مجموع یالهای رسیده تا آن رأس‪ ،‬کمینه شود‪.‬‬

‫‪71‬‬
‫مثال‪ :‬درخت پوشای کمینه را با استفاده از الگوریتم دکسترا به دست آورید‪.‬‬

‫تمرین‪ :‬با استفاده از الگوریتم دکسترا کوتاهترین مسیر بین ‪ v1‬و ‪ v5‬را در گراف زیر به دست آورید‪.‬‬

‫‪72‬‬
‫فصل هشتم‬

‫‪1‬‬
‫تکنیکهای طراحی الگوریتم (‪ :)4‬الگوریتمهای عقبگرد‬

‫بازگشت به عقب یا عقبگرد‪ ،‬تکنیکي در برنامهنویسي است که در آن برای حل یک مسأله‪ ،‬از یک گراف‬
‫جهتدار (درخت جهتدار) استفاده ميشود‪ .‬در این مسائل ابتدا یک فضای حالت برای مسائل در نظر گرفته‬
‫ميشود و آن فضای حالت به صورت گرافي که‪ ،‬هر رأس آن یک حالت و هر یال آن یک انتخاب از آن حالت‬
‫به حالت بعد است‪ ،‬نمایش داده ميشود‪ .‬مهمترین مسأله در مسائل عقبگرد‪ ،‬تشخیص بنبست در یک شاخه و‬
‫هرس کردن‪2‬آن شاخه است‪.‬‬

‫مسائلي وجود دارند که نه با تقسیم و غلبه و نه با برنامهنویسي پویا حل نميشوند‪ .‬الگوریتم حریصانه نیز در این‬
‫مسائل به جواب بهینه منتهي نميشود‪ .‬تنها راهِ یافتنِ راهحلِ بهینه‪ ،‬تولید کردن تمام راهحلها و آزمایش‬
‫آنهاست‪ ،‬که روشهای عقبگرد به این صورت عمل ميکند‪ .‬در راهبرد عقبگرد سعي ميکنیم بنبستها را‬
‫شناسایي کنیم و از دنبال کردن مسیرهای تکراری جلوگیری کنیم‪ .‬بهطور خالصه راهبرد عقبگرد عبارت است از‬
‫انتخاب دنبالهای از اشیا از یک مجموعه توأم با برآورده کردن یک شرط یا محدودیت‪.‬‬

‫راهبرد عقبگرد در حقیقت نوعي جستجو است‪.‬‬

‫مسأله ‪ 4‬وزیر‪:‬‬ ‫‪-8-1‬‬


‫صورت مسأله‪ :‬فرض کنید یک صفحه شطرنج ‪ 4*4‬داریم و ميخواهیم ‪ 4‬وزیر را بهطوری روی صفحه قرار‬
‫دهیم که هیچ وزیری امکان زدن وزیر دیگر را نداشته باشد؛ یعني هیچ وزیری نباید در دید مستقیم افقي یا‬
‫عمودی یا قطری وزیرهای دیگر باشد‪.‬‬

‫‪Back Tracking‬‬
‫‪1‬‬

‫‪2‬‬
‫‪Pruning‬‬

‫‪73‬‬
‫راهحل‪:‬‬

‫‪ .1‬درخت فضای حالت‪1‬را به شکل زیر رسم کنید‪.‬‬

‫‪ .2‬همانطور که مشخص است‪ ،‬این درخت ‪ 4*4*4*4 = 256‬برگ خواهد داشت‪.‬‬


‫‪ .3‬هر سطر برای یک وزیر در نظر گرفته ميشود؛ یعني سطر شماره ‪ i‬برای وزیر ‪i‬اُم‪.‬‬
‫‪ .4‬در حقیقت مسأله اصلي این است که چه شماره ستوني (‪ )j‬را برای وزیر ‪i‬اُم انتخاب کنیم‪.‬‬
‫‪ .5‬هر مسیر از ریشه تا برگ یک راهحل کاندید است که ممکن است صحیح یا غلط باشد‪.‬‬
‫‪ .6‬بنابراین این مسأله در واقع به مسأله جستجوی درخت فضای حالت تغییر ميکند و تبدیل ميشود‪.‬‬

‫‪State Space Tree‬‬


‫‪1‬‬

‫‪74‬‬
‫‪ .7‬به دو صورت ميتوان یک درخت را پیمایش کرد‪:‬‬
‫‪ ‬جستجوی ساده‪:‬‬
‫یعني همه گرهها را تک به تک بررسي کنیم و ببینیم که پاسخ صحیح هست یا خیر‪ ،‬که در این حالت‬
‫پردازش بسیاری الزم دارد‪.‬‬
‫‪ ‬جستجوی با راهبرد عقبگرد‪:‬‬
‫یعني گره ای که در آن احتمال پاسخ وجود ندارد را باز نکنید و آن شاخه را از نقطهای که احتمال پاسخ‬
‫بودن را نقض ميکند‪ ،‬هرس کنید‪ ،‬که در این حالت خواهیم دید بسیاری از پردازشها با هرس کردن‬
‫شاخهها حذف خواهد شد‪.‬‬
‫‪ ‬به گرهای که احتمال رسیدن به پاسخ وجود داشته باشد‪« ،‬گره امید بخش» گفته ميشود‪.‬‬

‫با توجه به نکات باال پاسخ این مسأله به شکل زیر خواهد بود‪:‬‬

‫‪75‬‬
‫یعني‪:‬‬

‫‪1‬‬
‫‪2‬‬
‫‪4‬‬
‫‪3‬‬

‫الگوریتم کلی مسأله ‪ 4‬وزیر‪:‬‬

‫الگوریتم ‪ 4‬وزیر به صورت بهینه شده‪:‬‬

‫در این الگوریتم گرههایي که احتمال پاسخ ندارند‪ ،‬باز نميشوند‪.‬‬

‫‪76‬‬
‫ميتوان این مسأله را به مسأله ‪ n‬وزیر تعمیم داد‪.‬‬

‫تمرین‪ :‬تابع ‪ Promising‬را به زبان فارسي توصیف کنید؛ یعني منظور از امید بخش بودن یک گره چیست؟‬

‫پاسخ‪ :‬تفاضل شماره ستون فرزند (‪ )k‬و والد (‪ )i‬نباید از ‪ 1‬کمتر باشد؛ یعني‪:‬‬

‫‪| 𝑐𝑜𝑙 (𝑖) − 𝑐𝑜𝑙 (𝑘)| > 1‬‬

‫مسأله حاصل جمع زیرمجموعهها‪:‬‬ ‫‪-8-2‬‬


‫صورت مسأله‪ :‬مجموعهای مانند } 𝑛𝑤 ‪ {𝑤1 , 𝑤2 , … ,‬داریم که ميخواهیم زیرمجموعهای از این مجموعه‬
‫انتخاب کنیم؛ به این شرط که 𝑤 = 𝑖𝑤 ∑ ‪.‬‬

‫مثال‪ :‬از مجموعهی زیر‪ ،‬زیر مجموعهای انتخاب کنید که جمع آنها ‪ 6‬شود‪:‬‬

‫}‪{2, 4, 5‬‬

‫راهحل‪ :‬درخت حالت این مسأله به صورت زیر است‪:‬‬

‫}‪{𝑤1: 2, 𝑤2: 4, 𝑤3: 5‬‬

‫‪77‬‬
‫همانطور که مشاهده ميکنیم درخت فضای حالت این مسأله بسیار پیچیده خواهد شد‪ ،‬ميتوان مسأله را به‬
‫صورت درخت دودویي در نظر گرفت که در هر حال‪ ،‬یکي از عناصر انتخاب ميشود یا نميشود؛ بنابراین‬
‫داریم‪:‬‬

‫مسأله رنگآمیزی گراف با ‪ m‬رنگ (‪:)M–Coloring‬‬ ‫‪-8-3‬‬


‫صورت مسأله‪ :‬گراف زیر را با سه رنگ طوری رنگ کنید که هیچ دو رنگي مجاور هم قرار نگیرند‪.‬‬

‫‪78‬‬
‫این مسأله در رنگآمیزی نقطههای جغرافیایي یا سلولبندی شبکههای مخابراتي کاربرد دارد‪ .‬برای به دست‬
‫آوردن پاسخ مسأله‪ ،‬درخت فضای حالت را به صورت زیر رسم ميکنیم‪:‬‬

‫پس از ساخت گراف‪ ،‬تکتکِ مسیرها بررسي ميشوند و با توجه به یالهای گراف تصمیم ميگیریم که این‬
‫مسیر پاسخگوی مسأله هست یا خیر‪ .‬به طور مثال‪ ،‬مسیر اول عبارت است از‪:‬‬

‫‪m1,m1,m1,m1‬‬

‫که قطعاً پاسخ مسأله نیست (چون طبق گراف نباید رنگ ‪ v1‬و ‪ v2‬یکسان باشد‪ .‬مسیر دوم‪:‬‬

‫‪m1,m1,m1,m2‬‬

‫این نیز پاسخ درستي نخواهد بود و به همین صورت تمام مسیرها بررسي ميشود‪.‬‬

‫اما این گراف ميتواند طبق الگوریتم عقبگرد‪ ،‬هرس شود و به طور مثال وقتي بعد از ‪ m1‬دوباره ‪ m1‬انتخاب‬
‫ميشود‪ ،‬این شاخه‪« ،‬غیر امیدبخش» تشخیص داده شود و هرس شود و برگهای آن بررسي نشود‪...‬‬

‫مثال‪ :‬نقشهی زیر حداقل به چند رنگ نیاز دارد تا مسأله ‪ M–Coloring‬در مورد آن صدق کند‪.‬‬

‫راهحل‪ :‬برای حل مسأله‪ ،‬آن را به گراف زیر تبدیل ميکنیم‪:‬‬

‫‪79‬‬
‫بنابراین به یک مسأله ‪ M–Coloring‬تبدیل شد که باید درخت حالت مسأله آن را رسم کنیم‪ .‬مسأله را‬
‫یکبار‪ ،‬با یک رنگ حل ميکنیم‪ ،‬که داریم‪:‬‬

‫سپس با دو رنگ‪:‬‬

‫سپس سه رنگ و سپس چهار رنگ‪.‬‬

‫‪80‬‬
‫اگر به همین صورت با دو‪ ،‬سه و چهار رنگ ادامه دهیم‪ ،‬به این نتیجه خواهیم رسید که فقط با چهار رنگ‪ ،‬امکان‬
‫انتخاب رنگهایي وجود دارد که مجاور نباشد‪.‬‬

‫‪1‬‬
‫مسأله کولهپشتی‪:‬‬ ‫‪-8-4‬‬
‫صورت مسأله‪ :‬فرض کنید قرار است یک جهانگرد از بین اشیاء زیر حداقل اشیائي را انتخاب کند که وزن‬
‫آنها بیش از ‪ 15‬کیلوگرم نشود و در عین حال سودمندترین اشیاء باشد‪( .‬منظور از ارزش هر شیئ میزان نیازمندی‬
‫جهانگرد به آن شیئ است)‬

‫مسأله را به صورت زیر در نظر بگیریم قابل فهمتر است‪:‬‬

‫برای حل مسأله ابتدا تناسب سود به وزن را به صورت زیر محاسبه ميکنیم‪:‬‬
‫‪4‬‬
‫= ‪𝑤1‬‬ ‫‪= 0.3‬‬
‫‪12‬‬
‫‪2‬‬
‫= ‪𝑤2‬‬ ‫‪=2‬‬
‫‪1‬‬
‫‪1‬‬
‫= ‪𝑤3‬‬ ‫‪=1‬‬
‫‪1‬‬
‫‪10‬‬
‫= ‪𝑤4‬‬ ‫‪= 2.5‬‬
‫‪4‬‬
‫‪2‬‬
‫= ‪𝑤5‬‬ ‫‪=1‬‬
‫‪2‬‬

‫‪1‬‬
‫‪Knapsack‬‬

‫‪81‬‬
‫درخت فضای حالت را بهصورت زیر رسم میکنیم‪:‬‬

‫تمرین‪ :‬این مسأله را با روش حریصانه حل کنید‪.‬‬

‫انواع مسأله کولهپشتی‪:‬‬ ‫‪-8-5‬‬


‫کولهپشتی صفر و یک (‪ :)0 ، 1‬در این دسته مسائل کلِ یک شیئ را ميتوانیم یا نميتوانیم انتخاب کنیم‪.‬‬

‫کولهپشتی کسری‪ :‬در این دسته مسائل ميتوانیم‪ ،‬کسری از یک شیئ را انتخاب کنیم‪.‬‬

‫تمرین‪ :‬برای کولهپشتي کسری یک مثال از دنیای واقعي بزنید‪...‬‬

‫‪82‬‬

You might also like