مسیرها
/
Python
Python
/
تمرین‌ها
/
لیست پیوندی ساده
لیست پیوندی ساده

لیست پیوندی ساده

آسان

مقدمه

شما در یک شرکت پخش آنلاین موسیقی کار می‌کنید.

به شما سپرده شده است که برای اپلیکیشن پخش موسیقی‌تان قابلیت «پخش‌لیست» را بسازید.

دستورالعمل‌ها

نمونه‌ای اولیه از برنامه‌ی پخش‌کننده‌ی موسیقی بنویسید.

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

با داشتن یک لیست پیوندی یک‌طرفه، باید بتوانید لیست را معکوس کنید تا آهنگ‌ها را به ترتیب معکوس پخش کنید.

Note

لیست پیوندی یک ساختار داده‌ی بنیادی در علوم کامپیوتر است که اغلب در پیاده‌سازی ساختارهای داده‌ی دیگر به کار می‌رود.

ساده‌ترین نوع لیست پیوندی، لیست پیوندی یک‌طرفه است. یعنی هر عنصر (یا «گره») شامل داده است، همراه با چیزی که به گره‌ی بعدی در لیست اشاره می‌کند.

اگر می‌خواهید بیشتر در مورد لیست‌های پیوندی کاوش کنید، این مقاله را ببینید که آن را با تصاویر زیبا توضیح می‌دهد.

ساختار این تمرین در Python

هرچند stacks و queues را می‌توان با lists، collections.deque، queue.LifoQueue و multiprocessing.Queue پیاده‌سازی کرد، این تمرین انتظار یک پشته‌ی «آخرین ورودی، اولین خروجی» (LIFO) را دارد که با یک فهرست پیوندی یک‌طرفه دست‌ساز ساخته شده باشد:


نموداری که یک پشته‌ی پیاده‌سازی‌شده با فهرست پیوندی را نشان می‌دهد. دایره‌ای با حاشیه‌ی نقطه‌چین به نام New_Node در دورترین بخش سمت چپ قرار دارد و دو خط فلش نقطه‌چین به سمت راست اشاره می‌کنند. New_Node چنین خوانده می‌شود: «(becomes head) - New_Node - next = node_6». خط فلش نقطه‌چین بالایی برچسب «push» دارد و به Node_6 که بالاتر و سمت راست است اشاره می‌کند. Node_6 چنین خوانده می‌شود: «(current) head - Node_6 - next = node_5». خط فلش نقطه‌چین پایینی برچسب «pop» دارد و به جعبه‌ای اشاره می‌کند که چنین خوانده می‌شود: «gets removed on pop()». Node_6 یک فلش توپر دارد که به سمت راست به Node_5 اشاره می‌کند و Node_5 چنین خوانده می‌شود: «Node_5 - next = node_4». Node_5 فلش توپی دارد که به سمت راست به Node_4 اشاره می‌کند و Node_4 چنین خوانده می‌شود: «Node_4 - next = node_3». این الگو تا Node_1 ادامه می‌یابد که چنین خوانده می‌شود: «(current) tail - Node_1 - next = None». Node_1 فلش نقطه‌چینی دارد که به سمت راست به گره‌ای اشاره می‌کند که می‌گوید «None».


این را نباید با پشته‌ی LIFO که از یک آرایه یا فهرست پویا استفاده می‌کند اشتباه گرفت؛ آن یکی ممکن است در زیر از list، queue یا array بهره ببرد. stacksهای مبتنی بر آرایه‌ی پویا موقعیت head متفاوتی دارند و پیچیدگی زمانی (Big-O) و مصرف حافظه‌ی متفاوتی هم دارند.


نموداری که یک پشته‌ی پیاده‌سازی‌شده با آرایه/آرایه‌ی پویا را نشان می‌دهد. جعبه‌ای با حاشیه‌ی نقطه‌چین به نام New_Node در دورترین بخش سمت راست قرار دارد و دو خط فلش نقطه‌چین به سمت چپ اشاره می‌کنند. New_Node چنین خوانده می‌شود: «(becomes head) -  New_Node». خط فلش نقطه‌چین بالایی برچسب «append» دارد و به Node_6 که بالاتر و سمت چپ است اشاره می‌کند. Node_6 چنین خوانده می‌شود: «(current) head - Node_6». خط فلش نقطه‌چین پایینی برچسب «pop» دارد و به جعبه‌ای با خط دور نقطه‌چین اشاره می‌کند که چنین خوانده می‌شود: «gets removed on pop()». Node_6 یک فلش توپر دارد که به سمت چپ به Node_5 اشاره می‌کند. Node_5 یک فلش توپر دارد که به سمت چپ به Node_4 اشاره می‌کند. این الگو تا Node_1 ادامه می‌یابد که چنین خوانده می‌شود: «(current) tail - Node_1».


برای دیدن چند نکته‌ی قابل توجه، این دو پرسش Stack Overflow را ببینید: پشته‌ها و صف‌های مبتنی بر آرایه در برابر مبتنی بر فهرست و تفاوت‌های پشته‌ی آرایه‌ای، پشته‌ی پیوندی و پشته. برای جزئیات بیشتر درباره‌ی فهرست‌های پیوندی، پشته‌های LIFO و دیگر انواع داده‌ی انتزاعی (ADT) در Python:


کلاس‌ها در Python

پیاده‌سازی «متعارف» یک فهرست پیوندی در Python معمولاً به یک یا چند classes نیاز دارد. برای آشنایی خوب با classes، classes و تمرین همراه آن ellens-alien-game را ببینید، یا بخش کلاس‌ها در آموزش رسمی Python.


متدهای ویژه در Python

testهای این تمرین len() را روی LinkedList شما فراخوانی می‌کنند. برای اینکه len() کار کند، باید یک متد ویژه‌ی __len__ بسازید. برای جزئیات پیاده‌سازی متدهای ویژه یا «dunder» در Python، مستندات Python: سفارشی‌سازی پایه‌ی شیء و مستندات Python: object.len(self) را ببینید.


ساخت یک تکرارکننده

برای پشتیبانی از حلقه زدن روی LinkedList یا معکوس کردن آن، باید متد ویژه‌ی __iter__ را پیاده‌سازی کنید. برای جزئیات پیاده‌سازی، پیاده‌سازی یک تکرارکننده برای یک کلاس را ببینید.


سفارشی‌سازی و پرتاب استثناها

گاهی لازم است استثناها را هم سفارشی کنید و هم raise کنید. در چنین حالتی، همیشه باید یک پیام خطای معنادار بگنجانید تا منبع خطا را نشان دهد. این کار code شما را خواناتر می‌کند و در debug کمک زیادی می‌کند.

استثناهای سفارشی را می‌توان از طریق کلاس‌های استثنای تازه ساخت (برای جزئیات بیشتر classes را ببینید) که معمولاً زیرکلاس‌هایی از Exception هستند.

برای موقعیت‌هایی که می‌دانید منبع خطا مشتقی از یک نوع استثنای مشخص خواهد بود، می‌توانید ارث‌بری از یکی از built in error types زیر کلاس Exception را انتخاب کنید. هنگام پرتاب خطا، باز هم باید یک پیام معنادار بگنجانید.

این تمرین خاص می‌خواهد که یک استثنای سفارشی بسازید تا وقتی فهرست پیوندی‌تان خالی است، پرتاب/«thrown» شود. testها فقط زمانی قبول می‌شوند که استثناهای مناسب را سفارشی کنید، آن استثناها را raise کنید و پیام‌های خطای مناسب را بگنجانید.

برای سفارشی‌سازی یک استثنای عمومی، یک class بسازید که از Exception ارث‌بری کند. هنگام پرتاب استثنای سفارشی همراه با یک پیام، پیام را به عنوان آرگومان به نوع exception بدهید:

# subclassing Exception to create EmptyListException
class EmptyListException(Exception):
    """Exception raised when the linked list is empty.

    message: explanation of the error.

    """
    def __init__(self, message):
        self.message = message

# raising an EmptyListException
raise EmptyListException("The list is empty.")
ویرایش از طریق GitHub این لینک در پنجره یا زبانه‌ی جدیدی باز می‌شود
Python Exercism

آماده‌اید لیست پیوندی ساده را شروع کنید؟

در Exercism ثبت‌نام کنید تا Python را همراه با 17 مفهوم146 تمرین و مربی‌گری انسانی واقعی یاد بگیرید و در آن استاد شوید، همه‌ی این‌ها رایگان.