হাফম্যান এনকোডিং (Huffman Encoding)
মোর্স কোড বা মোর্স সংকেতে, E অক্ষরটিকে একটি মাত্র ডট (·) দিয়ে প্রকাশ করা হয় কারণ ইংরেজি বর্ণমালার এটি সবচেয়ে বেশি ব্যবহৃত হয়। অন্যদিকে, Z কে ড্যাশ-ড্যাশ-ডট-ডট (−−··) দিয়ে প্রকাশ করা হয় কারণ এটি খুব কম ব্যবহৃত হয়। ঘন ঘন ব্যবহৃত অক্ষরগুলো ছোট কোড পায়; আর দুর্লভ অক্ষরগুলো পায় লম্বা কোড। এতে প্রতিটি অক্ষরই নির্ভুলভাবে চেনা যায়।
হাফম্যান এনকোডিং (Huffman encoding) এই একই ধারণার ওপর ভিত্তি করে তৈরি, যা গাণিতিকভাবে নিখুঁত। এটি প্রতিটি অক্ষরকে এমনভাবে বাইনারি কোড প্রদান করে যাতে একটি বার্তার মোট ব্যবহার হওয়া বিটের সংখ্যা সর্বনিম্ন হয় — এবং এটি এই নির্ভুলতা গাণিতিকভাবে নিশ্চিত করে।
প্রিফিক্স-ফ্রি কোড (Prefix-Free Codes)
এর মূল শর্তটি হলো: কোনো কোডওয়ার্ড অন্য কোনো কোডওয়ার্ডের প্রিফিক্স বা শুরু হতে পারবে না। যেমন যদি A-র কোড হয় ০১, তবে অন্য কোনো অক্ষর ০১ দিয়ে শুরু হতে পারবে না। এটি আমাদের ডিলিমিটার বা স্পেস ছাড়াই বিটের স্ট্রীম থেকে নির্ভুলভাবে অক্ষরগুলো পড়তে সাহায্য করে — যখনই আপনি একটি সম্পূর্ণ কোড হুবহু পাবেন, তখনই বুঝবেন যে অক্ষরটি শেষ হয়েছে। এতে ছোট কোডকে লম্বা কোডের শুরু বলে ভুল হওয়ার কোনো সম্ভাবনা থাকে না।
প্রতিটি প্রিফিক্স-ফ্রি কোড একটি পূর্ণ বাইনারি ট্রি (full binary tree)-র সাথে সাদৃশ্যপূর্ণ যেখানে প্রতিটি পাতা বা লিফ (leaf) হলো একটি অক্ষর। রুট থেকে পাতার পথটিই হলো সেই অক্ষরের কোডওয়ার্ড (বাম = ০, ডান = ১)। এনকোড করার খরচ হলো (অক্ষরের ফ্রিকোয়েন্সি × পাতার গভীরতা) এর সমষ্টি।
গ্রিডি অ্যালগরিদম (The Greedy Algorithm)
এর মূল ধারণাটি হলো: একটি নিখুঁত ট্রিতে, সবচেয়ে দুর্লভ বা কম ব্যবহৃত দুটি অক্ষর গাছের সবচেয়ে গভীর স্তরে এবং একে অপরের ভাই (siblings) হিসেবে থাকে। যদি তারা না থাকত, তবে আপনি সেগুলোকে অন্য যেকোনো গভীর পাতার সাথে বদল করে খরচ আরও কমাতে বা সমান রাখতে পারতেন।
এটি নিচে থেকে উপরে (bottom-up) ট্রি তৈরির একটি চমৎকার পদ্ধতি প্রদান করে:
১. প্রতিটি অক্ষরের জন্য একটি লিফ নোড তৈরি করুন এবং এদের ফ্রিকোয়েন্সি বা ব্যবহারের হার নির্ধারণ করুন। সব নোডকে একটি মিন-হিপ (min-heap)-এ রাখুন।
২. যতক্ষণ হিপে একের বেশি নোড থাকে: হিপ থেকে সবচেয়ে হালকা দুটি নোড A এবং B বের করুন। একটি নতুন ইন্টারনাল নোড তৈরি করুন যার ওজন হবে A.weight + B.weight এবং A ও B হবে এর দুই চাইল্ড। এই নতুন নোডটিকে আবার হিপে রাখুন।
৩. হিপে অবশিষ্ট শেষ নোডটিই হলো হাফম্যান ট্রির রুট (root)।
ট্রি তৈরি হয়ে গেলে, রুট থেকে বামে গেলে ০ এবং ডানে গেলে ১ ধরে প্রতিটি অক্ষরের কোড তৈরি করুন।
একটি উদাহরণ
ধরা যাক অক্ষরসমূহ: a(৫), b(৯), c(১২), d(১৩), e(১৬), f(৪৫)। ফ্রিকোয়েন্সির যোগফল ১০০ বিট। হাফম্যান ট্রি অনুযায়ী কোড হবে: f=০ (১ বিট), c=১০০ (৩ বিট), d=১০১ (৩ বিট), a=১১০০ (৪ বিট), b=১১০১ (৪ বিট), e=১১১ (৩ বিট)। এখন মোট ফাইলের আকার হবে = ৪৫×১ + ১২×৩ + ১৩×৩ + ৫×৪ + ৯×৪ + ১৬×৩ = ২২৪ বিট। সাধারণ ৩-বিট ফিক্সড কোড ব্যবহার করলে লাগত ৩০০ বিট। হাফম্যান এখানে প্রায় ২৫% জায়গা সাশ্রয় করেছে!
ডিকোডিং
ডিকোড করতে: বিটগুলো একে একে পড়ুন এবং ট্রি-র ওপর দিয়ে যাতায়াত করুন। ০ → বামে যান, ১ → ডানে যান। যখনই আপনি কোনো পাতায় পৌঁছাবেন, সেই অক্ষরটি লিখে আবার রুটে ফিরে যান। পরবর্তী বিটের জন্য একইভাবে শুরু করুন। প্রিফিক্স-ফ্রি হওয়ার কারণে এটি সব সময় একটি অনন্য বা ইউনিক ফলাফল দেয়।
হাফম্যান ট্রি — গঠন এবং কোড জেনারেশন
Complexity
ছোট কুইজ
পড়া চালিয়ে যান