ট্র্যাক
/
Python
Python
/
অনুশীলনী
/
সরল লিংকড লিস্ট
সরল লিংকড লিস্ট

সরল লিংকড লিস্ট

সহজ

ভূমিকা

আপনি একটি মিউজিক স্ট্রিমিং কোম্পানিতে কাজ করেন।

আপনার মিউজিক প্লেয়ার অ্যাপ্লিকেশনের জন্য একটি প্লেলিস্ট ফিচার তৈরির দায়িত্ব দেওয়া হয়েছে।

নির্দেশনা

মিউজিক প্লেয়ার অ্যাপ্লিকেশনের একটি প্রোটোটাইপ লিখুন।

প্রোটোটাইপের জন্য প্রতিটি গানকে কেবল একটি সংখ্যা দিয়ে প্রকাশ করা হবে। সংখ্যার একটি রেঞ্জ (গানের ID) দেওয়া থাকলে, একটি সিঙ্গলি লিংকড লিস্ট তৈরি করুন।

একটি সিঙ্গলি লিংকড লিস্ট দেওয়া থাকলে, আপনি লিস্টটি উল্টে দিয়ে গানগুলো বিপরীত ক্রমে চালাতে পারবেন।

Note

লিংকড লিস্ট কম্পিউটার সায়েন্সের একটি মৌলিক ডেটা স্ট্রাকচার, যা প্রায়ই অন্য ডেটা স্ট্রাকচার তৈরি করতে ব্যবহৃত হয়।

সবচেয়ে সহজ ধরনের লিংকড লিস্ট হলো সিঙ্গলি লিংকড লিস্ট। এর মানে হলো প্রতিটি এলিমেন্ট (বা "নোড")-এ ডেটা থাকে, সাথে থাকে এমন কিছু যা লিস্টের পরের নোডের দিকে ইশারা করে।

লিংকড লিস্ট নিয়ে আরও গভীরে যেতে চাইলে, এই আর্টিকেলটি দেখুন, যেখানে সুন্দর ছবি দিয়ে বিষয়টি ব্যাখ্যা করা হয়েছে।

পাইথনে এই অনুশীলনীটি কীভাবে সাজানো হয়েছে

stacks ও queues lists, collections.deque, queue.LifoQueue এবং multiprocessing.Queue দিয়ে তৈরি করা গেলেও, এই অনুশীলনীতে প্রত্যাশা করা হয় একটি "Last in, First Out" (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 - next = node_4"। Node_5 থেকে একটি নিরেট তীর ডান দিকে 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) নিয়ে আরও বিস্তারিত জানতে:


পাইথনে ক্লাস

পাইথনে একটি লিংকড লিস্টের "ক্যানোনিকাল" ইমপ্লিমেন্টেশনে সাধারণত এক বা একাধিক classes লাগে। classes-এর একটি ভালো পরিচিতির জন্য দেখুন classes এবং সঙ্গের অনুশীলনী ellens-alien-game, অথবা অফিসিয়াল পাইথন টিউটোরিয়ালের ক্লাস অংশ।


পাইথনে বিশেষ মেথড

এই অনুশীলনীর টেস্টগুলো আপনার LinkedList-এর উপর len() কল করবে। len() কাজ করার জন্য আপনাকে একটি __len__ বিশেষ মেথড তৈরি করতে হবে। পাইথনে বিশেষ বা "dunder" মেথড ইমপ্লিমেন্ট করার বিস্তারিত জানতে দেখুন Python Docs: Basic Object Customization এবং Python Docs: object.len(self)।


একটি ইটারেটর তৈরি করা

আপনার LinkedList-এর মধ্য দিয়ে লুপ করা বা উল্টো দিকে চালানোর সুবিধার জন্য আপনাকে __iter__ বিশেষ মেথডটি ইমপ্লিমেন্ট করতে হবে। ইমপ্লিমেন্টেশনের বিস্তারিত জানতে দেখুন একটি ক্লাসের জন্য ইটারেটর ইমপ্লিমেন্ট করা।


এক্সসেপশন কাস্টমাইজ করা ও রেইজ করা

কখনও কখনও আপনার কোডে এক্সসেপশন কাস্টমাইজ করা এবং raise করা দুটোই প্রয়োজন হয়। এটা করার সময় আপনার সবসময় একটি অর্থবহ এরর মেসেজ যোগ করা উচিত, যাতে বোঝা যায় এররটির উৎস কী। এতে আপনার কোড আরও পাঠযোগ্য হয় এবং ডিবাগিংয়ে অনেক সাহায্য করে।

নতুন এক্সসেপশন ক্লাসের মাধ্যমে কাস্টম এক্সসেপশন তৈরি করা যায় (আরও বিস্তারিত জানতে দেখুন classes), যেগুলো সাধারণত Exception-এর সাবক্লাস হয়।

যেসব ক্ষেত্রে আপনি জানেন যে এররের উৎস নির্দিষ্ট কোনো এক্সসেপশন টাইপ-এর অন্তর্গত হবে, সেখানে আপনি Exception ক্লাসের অধীন built in error types-গুলোর একটি থেকে ইনহেরিট করতে পারেন। এররটি রেইজ করার সময়ও আপনার একটি অর্থবহ মেসেজ যোগ করা উচিত।

এই নির্দিষ্ট অনুশীলনীতে আপনার একটি কাস্টম এক্সসেপশন তৈরি করা প্রয়োজন, যা আপনার লিংকড লিস্ট খালি থাকলে রেইজ করা/"থ্রো" করা হয়। আপনি যথাযথ এক্সসেপশন কাস্টমাইজ করলে, সেই এক্সসেপশনগুলো raise করলে, এবং যথাযথ এরর মেসেজ যোগ করলে তবেই টেস্টগুলো পাস করবে।

একটি সাধারণ এক্সসেপশন কাস্টমাইজ করতে, Exception থেকে ইনহেরিট করা একটি class তৈরি করুন। মেসেজসহ কাস্টম এক্সসেপশন রেইজ করার সময়, মেসেজটি 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টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।