এটি রুবি দিয়ে বিভিন্ন সর্টিং অ্যালগরিদম ইমপ্লিমেন্ট করার সিরিজের পার্ট 3। পার্ট 1-এ বাবল সর্ট এবং পার্ট 2-এ সিলেকশন সর্ট আলোচনা করা হয়েছিল।
যেমন أننا সিরিজের পূর্ববর্তী পোস্টগুলোতে আলোচনা করেছি, ডেটা সর্ট করার পদ্ধতি বুঝা যেকোনো সফটওয়্যার ইঞ্জিনিয়ারের টুলকিটের অপরিহার্য অংশ। সৌভাগ্যবশত, অধিকাংশ হাই-লেভেল ল্যাঙ্গুয়েজ, যেমন রুবি, ইতিমধ্যে বিল্ট-ইন মেথড দিয়ে থাকে যা অ্যারে সর্ট করার জন্য দক্ষ। উদাহরণস্বরূপ, আপনি যখন অ্যারেতে .sort কল করেন, তবে আপনি হুডের নিচে কুইকসর্ট ব্যবহার করছেন। এই পোস্টে, আমরা কুইক সর্টের মত একটি অনুরূপ অ্যালগরিদম শিখব — মার্জ সর্ট। এই দুটি অ্যালগরিদমই "ডিভাইড অ্যান্ড কনকর" পদ্ধতি ব্যবহার করে। মার্জ সর্ট ১৯৪৫ সালে জন ভন নয়মান আবিষ্কার করেন। নয়মান একজন বিখ্যাত কম্পিউটার সায়েন্টিস্ট এবং ফিজিসিস্ট যিনি ম্যানহ্যাটান প্রজেক্ট, "মিনি-ম্যাক্স" থিওরেম, মন্টে কার্লো মেথড এবং আরও অনেক কিছুর ওপর কাজ করেছেন।
উচ্চ স্তরে, মার্জ সর্ট অ্যালগরিদম অ্যারেকে বারবার দুটি সাব-অ্যারেতে ভাগ করে (রিকার্শন ব্যবহার করে) যতক্ষণ না শুধু একটি এলিমেন্ট باقی থাকে। তারপর, এলিমেন্টগুলো "মার্জ" করা হয় ফাইনাল, সর্টেড অ্যারে ফর্ম করার জন্য। বাবল সর্ট এবং অন্যান্য সাদৃশ্য অ্যালগরিদমের বিপরীতে, মার্জ সর্ট ভিজ্যুয়ালাইজেশন ছাড়া বুঝতে কঠিন। নিচের ডায়াগ্রামটি উইকিপিডিয়া থেকে একটি স্টেপ-বাই-স্টেপ ইলাস্ট্রেশন যা দেখাচ্ছে মার্জ সর্ট কীভাবে কাজ করে। তবে চিন্তা করবেন না যদি আপনি এখনও কিছুটা কনফিউজড থাকেন; আমরা কোডের মাধ্যমে কাজ করব।

আমরা পূর্বে যে অ্যালগরিদমগুলো আলোচনা করেছি (বাবল এবং সিলেকশন), সেগুলো বাস্তব টাস্কের জন্য প্রায় অনুপযোগী ছিল, কিন্তু মার্জ সর্ট Big-O নোটেশনের দৃষ্টিতে অনেক ভালো পারফর্ম করে। আপনি যদি Big-O নোটেশনের সাথে পরিচিত ন হন, তবে এটি বিভিন্ন অ্যালগরिदমের ওৰ্স্ট-কেস পারফর্মেন্স রিপ্রেজেন্ট করে। এটি আমাদের আসল দিক থেকে অ্যালগরিদমগুলো সহজে কমপেয়ার করতে দেয়। উদাহরণস্বরূপ, O(1) Big-O অর্থাৎ ওৰ্স্ট-কেস রান-টাইম কনস্ট্যান্ট থাকে এলিমেন্টের সংখ্যা "n" বড়লেও, আর O(n) Big-O অর্থাৎ ওৰ্স্ট-কেস রান-টাইম লিনিয়ারলি বড়ে n বড়লে। এর মানে আপনার যদি ১০০ এলিমেন্টের অ্যারে থাকে এবং আপনাকে O(n) এবং O(1) সর্টিং অ্যালগরিদমের মধ্যে বেছে নিতে হয়, তবে আপনি O(1) বেছে নেবেন কারণ O(1) অবশ্যই O(100)-কে হারাবে। বাবল এবং সিলেকশন সর্ট অ্যালগরিদম দুটির ওৰ্স্ট-কেস O(n²)। এটি খুব উপযোগী নয় কারণ এর মানে এলিমেন্ট সংখ্যা বড়লেই অ্যালগরিদম অত্যন্ত ধীরে কাজ করবে। বিপরীতে, মার্জ সর্ট n log(n)-এ পারফর্ম করে, অর্থাৎ বাবল বা সিলেকশন সর্টের চেয়ে এফিশিয়েন্সি কম হারায়।
চলুন ডায়াগ্রামের উদাহরণটি ওয়াক থ্রু করি। আমরা [38, 27, 43, 3, 9, 82, 10] অ্যারে দিয়ে শুরু করি এবং অ্যারেকে বারবার হাফ করি যতক্ষণ না সিংগল এলিমেন্ট থাকে।
- শুরুর অ্যারেকে দুটি হälfte ভাগ করি:
[38, 27, 43, 3]এবং[9, 82, 10]। - প্রথম হälfte আবার ভাগ করি:
[38, 27]এবং[43, 3]। - প্রথম হälfteকে সিংগল এলিমেন্টে ভাগ করি:
[38],[27],[43], এবং[3]। - ৩৮ এবং ২৭ সর্ট করি
[27, 38]বানাতে এবং ৪৩ এবং ৩ সর্ট করি[3, 43]বানাতে। - এগুলো একসাথে করি:
[3, 27, 38, 43]। - এখন, মূল অ্যারের দ্বিতীয় হälfte যেটি ছিল
[9, 82, 10]। এটাকে হাফ করি এবং পাই[9, 82]এবং[10]। [9, 82]-কে[9]এবং[82]-এ ভাগ করি, এবং[10]ইতিমধ্যে সিংগুলার।[9, 82]-কে আবার একসাথে সর্ট করি এবং[10]-কে মার্জ করি, ফলাফল[9, 10, 82]।- শেষে,
[3, 27, 38, 43]এবং[9, 10, 82]মার্জ করি পাই[3, 9, 10, 27, 38, 43, 82]।
একটি রুবি ইমপ্লিমেন্টেশন
নিচে রুবিতে লেখা একটি মার্জ সর্ট অ্যালগরিদম দেওয়া হলো:
class MergeSort def sort(numbers) num_elements = numbers.length if num_elements <= 1 return numbers end half_of_elements = (num_elements / 2).round left = numbers.take(half_of_elements) right = numbers.drop(half_of_elements) sorted_left = sort(left) sorted_right = sort(right) merge(sorted_left, sorted_right) end def merge(left_array, right_array) if right_array.empty? return left_array end if left_array.empty? return right_array end smallest_number = if left_array.first <= right_array.first left_array.shift else right_array.shift end recursive = merge(left_array, right_array) [smallest_number].concat(recursive) end end
চলুন দেখি এখানে কী হচ্ছে। প্রথমে, উপরের sort মেথডটিতে ফোকাস করি।
def sort(numbers) num_elements = numbers.length if num_elements <= 1 return numbers end half_of_elements = (num_elements / 2).round left = numbers.take(half_of_elements) right = numbers.drop(half_of_elements) sorted_left = sort(left) sorted_right = sort(right) merge(sorted_left, sorted_right) end
এই কোড অংশটির লক্ষ্য হলো দিয়ে गये নম্বরগুলো হাফ করে ভাগ করা যতক্ষণ না প্রতিটিতে শুধু একটি আইটেম থাকে। এটি একশনে দেখতে, শেষ লাইন (merge(sorted_left, sorted_right)) কমেন্ট আউট করুন এবং বদলে sorted_left এবং sorted_right প্রিন্ট করুন। প্রোগ্রাম রান করুন আমাদের উদাহরণ অ্যারে পাস করে, আপনার টার্মিনালে এটা দেখতে পাবেন:
merge_sort = MergeSort.new puts merge_sort.sort([38, 27, 43, 3, 9, 82, 10])
ruby ruby-merge-sort.rb
27 43 38 3 9 82 10
বাজে! আমাদের কোড আমাদের প্রাথমিক অ্যারেকে হাফ করে ভাগ করেছে। এখন merge অংশটি দেখি।
def merge(left_array, right_array) if right_array.empty? return left_array end if left_array.empty? return right_array end smallest_number = if left_array.first <= right_array.first left_array.shift else right_array.shift end recursive = merge(left_array, right_array) [smallest_number].concat(recursive) end
প্রথমে, আমরা চেক করি দুটি সাব-অ্যারের যেকোনো একটি খালি কিনা। যদি হয়, তবে আমরা অন্যটি রিটার্ন করতে পারি। অন্যথায়, যেহেতু দুটি সাব-অ্যারে খালি নয়, আমরা প্রতিটি অ্যারের প্রথম এলিমেন্টের ভ্যালু কমপেয়ার করি এবং তারপর কমপেয়ার করা ভ্যালুগুলো শিফ্ট করি ইনফাইনাইট লুপ রোধের জন্য। এরপর, আমরা রিকার্শন ব্যবহার করি (এখানেও আরো!) মূল অ্যারেতে যতক্ষণ না আমরা দুটি অ্যারে একসাথে সুন্দরভাবে সর্টেড করে কানেক্ট করতে পারি।
রিকার্শন সম্পর্কে আরও কিছু
আমাদের কোডে যদি কিছু অদ্ভুত লাগে, আমার অনুমান সেটা হলো এই লাইন: recursive = merge(left_array, right_array) আমরা আমাদের merge মেথডকে নিজের ভেতর থেকে কল করছি। ওহ! এটাকেই আমরা রিকার্শন বলি — একটি টেকনিক যেখানে একটি ফাংশন নিজেরে এক বা একাধিক বার কল করে যতক্ষণ না একটি নির্দিষ্ট কন্ডিশন মেট হয়। আমাদের কেসে, merge কল করা থাকবে যতক্ষণ না লেফট বা রাইট অ্যারে খালি হয়। আপনি যদি রিকার্শন সম্পর্কে আরও জানতে চান, তবে ফিবোনাচি সিকোয়েন্সের জন্য রুবি এবং রিকার্শন ব্যবহার করে ফাংশন লেখার একটি উদাহরণ এখানে রয়েছে।
র্যাপ-আপ
আশা করি আপনি মার্জ সর্ট সম্পর্কে আরও জানতে পেরে আনন্দিত! এটি কীভাবে হাই লেভেলে কাজ করে এবং কেন বাবল বা সিলেকশন সর্টের চেয়ে এটি আরও দক্ষ পছন্দ — এই জ্ঞান জব ইন্টারভিউ বা আপনার দিনদিনের কাজে কাজে লাগবে। এছাড়া, মার্জ সর্টের অনেক ভেরিয়েন্ট রয়েছে जिनके সম্পর্কে আপনি উইকিপিডিয়া থেকে জানতে পারেন আপনি যদি আগ্রহী হন। পরের বার পর্যন্ত ... হ্যাপি সর্টিং!