1 / 25

ساختمان داده ها

ساختمان داده ها. صف و پشته. مهدی ایل بیگی دانشگاه آزاد اسلامی دماوند پاییز 89. مقدمه. مجموعه پويا ( Dynamic Set ): مجموعه اي است كه تركيب و تعداد عناصر آن ممكن است در طول زمان اجراي برنامه تغيير كند.

ravi
Download Presentation

ساختمان داده ها

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. ساختمان داده ها صف و پشته مهدی ایل بیگی دانشگاه آزاد اسلامی دماوند پاییز 89

  2. مقدمه • مجموعه پويا (Dynamic Set): مجموعه اي است كه تركيب و تعداد عناصر آن ممكن است در طول زمان اجراي برنامه تغيير كند. • مجموعه هاي پويا كاربردهاي زيادي در پياده سازي انواع الگوريتم هاي محاسباتي، نرم افزارهاي شبيه سازي و خود سيستم‌عامل كامپيوترها دارند. • عمليات مختلفي مانند حذف و اضافه نمودن اعضاء، پيدا كردن يك عضو يا عضو قبل و بعد آن، تعداد اعضاء، بزرگترين و كوچكترين عضو و ... بر روي مجموعه هاي پويا قابل انجام است. • پشته، صف، صف اولويت دار و ليست هاي پيوندي ساختمان داده هايي براي نگهداري و مديريت مجموعه هاي پويا هستند.

  3. مقدمه • هر عنصر جديدي كه به پشته وارد شود در بالاي آن قرار مي گيرد. • تنها بالاترين عضو پشته مجاز است از آن خارج شود. • پشته مثل همه ساختمان داده هاي ديگر، محدوديت اندازه دارد و ممكن است پر يا خالي باشد. • ساختار پشته Last In First Out است (LIFO)، بدین معنی که هر عنصری که آخر اضافه شود به هنگام عملیات Pop کردن این عنصر اولین عنصری است که Pop می شود.

  4. Stack ADT class Stack{ const int MAX-SIZE= 100 ; //Max stack size int top = -1 ; // default : stack is empty int members [MAX-SIZE]; int push(int x) { …} int pop() {..} int numElements() { return top + 1; } boolisEmpty() { return (top == -1) ; } boolisFull() { return (top == MAX-SIZE-1); } }

  5. تابع Push Int push(int x) { if (isFull() == 0){ top ++ ; members[top] = x; return 1; } else return -1; }

  6. تابع Pop int pop() { if (isEmpty() == 0) { int temp = members[top]; top -- ; return temp; } else return -1; }

  7. صف (Queue) • صف يک ليست است که تمامي جايگذاري آن از يک سمت و تمام حذف هاي آن از سمت ديگر انجام مي شود. • از آنجا که اولين وارد شده به يک صف، در هنگام خروج اولين عنصري است که خارج مي شود، صف را به عنوان ليست هاي FIFO(First In First Out) در نظر مي گيرند. • هر صف ابتدا و انتهايي دارد: • ابتداي صف (Head or Front): محلي است كه عضو موجود در آن كانديداي حذف است. • انتهاي صف (Tail or Rear): محلي است كه عضو جديدي كه وارد صف مي شود در آن قرار مي گيرد.

  8. پیاده سازی صف • هر صف ظرفيت محدودي دارد و مي توان در يكي از وضعيت هاي پر، نيمه پر يا خالي باشد. • برای پیاده سازی صف می توان از آرایه یک بعدی استفاده نمود، در این صورت برای صفی به طول n خواهیم داشت: • تعریف صف: int queue[n]; • در ابتدای کار: Front = Rear = -1; • شرط خالی بودن صف: if(Front == Rear) • شرط پر بودن صف: if(Rear == n)

  9. تابع Add برای صف خطی int add(int queue[], int item) { if(Rear == n) return -1; //صف پر می باشد else { queue[++Rear] = item; // return 1; } } ابتدا یک واحد به Rear افزوده می شود و سپس عنصر درون آرایه درج می گردد.

  10. تابع Delete برای صف خطی int delete(int queue[], int item) { if(Front == Rear) return -1; //صف خالی می باشد else { return queue[++Front]; // } } ابتدا یک واحد به Front افزوده می شود و سپس عنصر مورد نظر برگردانده می شود

  11. صف حلقوی • مشکل صف خطی اینست که با رسیدن Rear به انتهای صف دیگر نمی توان عنصری را در صف اضافه نمود. برای حل این مشکل از صف حلقوی استفاده می شود. • برای پیاده سازی صف حلقوی نیز می توان از آرایه یک بعدی استفاده نمود، در این صورت برای صفی به طول n خواهیم داشت: • تعریف صف: int queue[n]; • در ابتدای کار: Front = Rear = -1; • شرط خالی بودن صف: if(Front == Rear) • شرط پر بودن صف: Rear = (Rear + 1) % n if(Front == Rear)

  12. تابع Add برای صف حلقوی int add(int queue[], int item) { Rear = (Rear + 1) % n; if(Front == Rear) return -1; //صف پر می باشد else { queue[Rear] = item; return 1; } }

  13. تابع Delete برای صف حلقوی int delete(int queue[], int item) { if(Front == Rear) return -1; //صف خالی می باشد else { Front = (Front + 1) % n; return queue[Front]; } }

  14. نکات صف حلقوی • برای شناسایی صف در حالت پر و خالی از یک شرط مشابه استفاده می شود، فقط فرق در اینجاست که برای شناسایی صف پر ابتدا به متغیر Rear یک واحد اضافه می نماییم و سپس شرط (Front == Rear) را بررسی می کنیم. • در نتیجه برای مشخص شدن صف پر از صف خالی همیشه باید یک عنصر را خالی در نظر بگیریم. • پس صف حلقوی با طول n حداکثر می تواند n-1 عنصر را در خود جای دهد. • تعداد عناصر موجود در صف حلقوی از رابطه زیر بدست می آید: = Rear - Front , if(Rear > Front)تعداد عناصر موجود درصف = n – (Front – Rear) , if(Front > Rear)تعداد عناصر موجود درصف

  15. نکات صف حلقوی • در صف حلقوی برای حل این مشکل که شرط پر بودن با شرط خالی بودن مشابه است، همیشه یک خانه را خالی نگه می داریم. برای اینکه حتی این یک خانه را هم برای ذخیره سازی از دست ندهیم می توانیم شرط پر و خالی بودن صف را به صورت زیر تغییر دهیم. • شرط پر و خالی بودن در صف حلقوی بدونه در نظر گرفتن یک خانه خالی: Queue is empty iff (front == rear) && !lastOperationIsPut Queue is full iff (front == rear) && lastOperationIsPut • در واقع زمانی صف پر خواهد بود که (front == rear) شود و آخرین عملیات بر روی صف نیز درج یک عنصر در صف باشد. • با اعمال این تغییرات ظرفیت صف حلقوی به طول n برابر با n عنصر خواهد شد.

  16. مساله مسير پر پيچ و خم (MAZING) • در مسئله مسیر پر پیچ و خم باید راهی از ابتدای مسیر به انتهای مسیری که دارای پیچ و خم های زیادی است شناسایی گردد. • بهترين راه نمايش مسير فوق يک آرايه دو بعدي است که صفرهاي آن نشان دهنده پيچ و خم هاي مسير مي باشد. • يک مسير پر پيچ و خم (maze) با ابعاد m×p به يک آرايه (m+2)×(p+2) نياز دارد. ورودي در موقعيت [1][1] و خروجي در موقعيت [m][p] مي باشد. • برای یافتن مسیر درست، وقتی به سر هر چند راهی رسیدیم، تمامی انتخاب ها را در پشته ذخیره می نماییم. در صورت مسدود بودن مسیر، شروع یک مسیر دیگر از پشته استخراج می شود. (با صف نیز می توان این مسئله را حل کرد) • اندازه مسير پرپيچ و خم (maze) زمان اجراي مسير را تعيين مي کند. از آنجا که هر موقعيت درون مسير بيش از يک بار مشاهده نمي شود، بدترين حالت پيچيدگي الگوريتم به صورت O(mp)مي باشد به نحوي که m و p تعداد سطرها و ستون هاي مسير است.

  17. Parentheses Matching • اگر بخواهیم تعداد پرانتز های باز و بسته و همچنین ترتیب آن ها را بررسی نماییم تا از صحت پرانتز گذاری مطمئن شویم می تواننیم از ساختمان داده پشته استفاده نماییم. • الگوریتم شناسایی صحت پرانتز گذاری با استفاده از پشته: • عبارت را از چپ به راست بخوانید. • وقتی به Left parenthesis رسیدید آن را در پشته push کنید. • وقتی به right parenthesis رسیدید آن را از پشته pop کنید. • در انتها عبارت اگر پشته خالی باشد پرانتز گذاری صحیح بوده است.

  18. ارزشيابي عبارات • یکی دیگر از کاربردهای پشته ها، برای ارزشیابی عبارات محاسبه ای می باشد. • در هر زبان برنامه سازي براي ارزيابي صحيح عبارات، به هر عملگر اولويتي نسبت مي دهيم. حال در هر جفت پرانتز، اول عملگرهايي که داراي اولويت بالاتر هستند، ارزشيابي مي شوند. • روش استاندارد نوشتن عبارات به عنوان infix معرفي و شناخته مي شود چرا که در اين روش عملگرهاي دودويي را در بين دو عملوند قرار مي دهيم. • در کامپایلرها برای ارزشیابی عبارات از نمایش postfix استفاده می نمایند. • در نمایش postfix، هر عملگر بعد از عملوند هاي مربوطه ظاهر مي شود. • برای ارشیابی عبارات postfix می توان از ساختمان داده پشته استفاده نمود.

  19. ارزشیابی عبارات Postfix با استفاده از پشته • در جدول زیر چند عبارت infix و معادل postfix ان آورده شده است: • برای ارزیابی عبارات postfix از الگوریتم زیر استفاده می نماییم: • عبارات براي ارزيابي از چپ به راست پويش مي شوند. • عملوندها تا مشاهده يک عملگر، داخل پشته قرار مي گيرند. • سپس تعداد لازم از عملوندها را از پشته خارج و پس از انجام عملکرد مربوطه، نتيجه را دوباره به داخل پشته منتقل مي کنيم. • اين کار ادامه پيدا مي کند تا به انتهاي عبارت برسيم.

  20. مثال برای ارزشیابی عبارات Postfix

  21. تبدیل عبارت infix به postfix و prefix بروش دستی • الگوریتم تبدیل عبارت infix (میانوندی) به postfix (پسوندی): 1. عبارت كامل پرانتزگذاری می‌ شود. 2. هر عملگر به سمت راست پرانتز بسته خود منتقل می شود. 3. پرانتزها حذف می شوند. • تبدیل عبارت infix به prefix (پیشوندی): 1. عبارت كامل پرانتزگذاری می‌ شود. 2. هر عملگر به سمت چپ پرانتز باز خود منتقل می شود. 3. پرانتزها حذف می شوند. • تبدیل عبارت postfix به prefix: 1. ابتدا عبارت پسوندی را تبديل به ميانوندی می ‌كنيم. 2. عبارت ميانوندی حاصل را به پيشوندی تبديل می ‌كنيم. • نکته: در تبدیل عبارات ترتیب عملوندها تغییر نمی کند.

  22. الگوریتم تبدیل عبارت infix به postfix • برای تبدیل عبارات میانوندی به پسوندی توسط کامپیوتر، عبارت را از چپ به راست پویش می نماییم و سپس: • پرانتزهای سمت چپ را در پشته push می نماییم. • هنگامی که به یک عملوند می رسیم آن را در خروجی می نویسیم. • هنگامی که به یک عملگر رسیدیم آنگاه عملگرهای بالای پشته که اولویت یکسان یا بالاتر از این عملگر را دارند pop می نماییم و سپس عملگر مذکور را در پشته push می کنیم. • هنگامی که به پرانتز بسته (سمت راست) رسیدیم آنگاه عملگرهای بالای پشته را تا رسیدن به اولین پرانتز باز (سمت چپ)، pop کرده و در خروجی می نویسیم و سپس پرانتز باز را نیز از پشته pop می کنیم ولی در خروجی نمی نویسیم. • عملیات فوق را تا انتهای عبارت تکرار می نماییم.

  23. مثال برای تبدیل عبارت infix به postfix • عبارت (a+b*c-d)/(e*f) را بصورت postfix نمایش دهید.

  24. الگوریتم تبدیل عبارت infix به prefix • برای تبدیل عبارات میانوندی به پیشوندی توسط کامپیوتر، ابتدا عبارت را معکوس می نماییم و سپس از چپ به راست پویش می کنیم در ادامه: • پرانتزهای سمت راست (پرانتز بسته) را در پشته push می نماییم. • هنگامی که به یک عملوند می رسیم آن را در خروجی می نویسیم. • هنگامی که به یک عملگر رسیدیم آنگاه عملگرهای بالای پشته که اولویت یکسان یا بالاتر از این عملگر را دارند pop می نماییم و سپس عملگر مذکور را در پشته push می کنیم. • هنگامی که به پرانتز باز (سمت چپ) رسیدیم آنگاه عملگرهای بالای پشته را تا رسیدن به اولین پرانتز بسته (سمت راست)، pop کرده و در خروجی می نویسیم و سپس پرانتز بسته را نیز از پشته pop می کنیم ولی در خروجی نمی نویسیم. • عملیات فوق را تا انتهای عبارت تکرار می نماییم. و در نهایت خروجی را معکوس می کنیم.

  25. ?

More Related