نحوه راه اندازی گوشی های هوشمند و رایانه های شخصی پرتال اطلاعاتی

نمونه های کدگذاری Rle عدم وجود یک الگوریتم کامل

با استفاده از الگوریتم RLE، دنباله کاراکتر BBBBBBACCCABBBBBB را رمزگذاری کنید.

نتیجه را به صورت کدهای هگزادسیمال بنویسید (هر کاراکتر به صورت یک بایت کدگذاری می شود که با دو رقم هگزا دسیمال نشان داده می شود). نتیجه را با استفاده از برنامه RLE بررسی کنید.

دنباله RLE-packed را رمزگشایی کنید (کدهای هگزا دسیمال داده شده است): 01 4D 8E 41 01 4D 8E 4116. از جدول ASCII برای شناسایی کاراکترها با کد هگزا دسیمال آنها استفاده کنید. در جدول بالا، خط اول شامل رقم اول کد هگزادسیمال کاراکتر و خط دوم شامل رقم دوم است. برای مثال، کاراکتر & دارای کد هگزا دسیمال 2616 است.

تعداد بایت ها را در دنباله اصلی و بدون بسته بندی تعیین کنید و نسبت فشرده سازی را محاسبه کنید: نتیجه به دست آمده را در پاراگراف قبلی، با استفاده از برنامه RLE. دو راه برای بررسی پیشنهاد دهید. دنباله هایی بسازید که توسط الگوریتم RLE دقیقاً 2 بار، 4 بار، 5 بار فشرده شوند. پاسخ های خود را با برنامه RLE بررسی کنید. به سه دنباله فکر کنید که با استفاده از الگوریتم RLE نمی توان آنها را فشرده کرد: با استفاده از برنامه RLE، فشرده سازی RLE را روی فایل های زیر اعمال کنید و نسبت فشرده سازی هر یک از آنها را بیابید: نتایج به دست آمده در پاراگراف قبل را توضیح دهید:
    چرا نمی توانم تصاویر را فشرده کنم فرمت JPEG? چرا برای دو عکس در فرمت BMPنسبت تراکم RLE در اندازه یکسان بسیار متفاوت است؟ نکته: این تصاویر را در هر بیننده ای باز کنید.
حداکثر نسبت فشرده سازی قابل دستیابی را با استفاده از الگوریتم RLE که در آموزش توضیح داده شده است، تخمین بزنید. چه زمانی امکان دستیابی به آن وجود خواهد داشت؟
با استفاده از الگوریتم RLE، بدترین نسبت فشرده سازی را تخمین بزنید. این بدترین حالت را توصیف کنید.

  • آموزش

مدت ها پیش، زمانی که من هنوز یک دانش آموز ساده لوح بودم، ناگهان به شدت کنجکاو شدم: چگونه داده های آرشیو به طور جادویی فضای کمتری را اشغال می کنند؟ با زین کردن شماره گیری وفادار خود، شروع به گشت و گذار در اینترنت در جستجوی پاسخ کردم و مقالات زیادی با ارائه نسبتاً دقیق اطلاعاتی که به آنها علاقه داشتم پیدا کردم. اما درک هیچ یک از آنها برای من آسان به نظر نمی رسید - لیست کدها به نظر سواد چینی بود و تلاش برای درک اصطلاحات غیرمعمول و فرمول های مختلف ناموفق بود.

بنابراین، هدف این مقاله ارائه ایده ای از ساده ترین الگوریتم های فشرده سازی به کسانی است که با دانش و تجربه خود، هنوز به آنها اجازه نمی دهند فوراً ادبیات حرفه ای بیشتری را درک کنند یا مشخصات آنها از موضوعات مشابه دور است. آن ها من به شما در مورد برخی از ساده ترین الگوریتم ها می گویم و نمونه هایی از اجرای آنها را بدون لیست کدهای کیلومتر ارائه می کنم.

من فوراً به شما هشدار می دهم که جزئیات اجرای فرآیند رمزگذاری و تفاوت های ظریف را به عنوان جستجوی مؤثر برای وقوع یک رشته در نظر نخواهم گرفت. این مقاله فقط به خود الگوریتم ها و روش های ارائه نتیجه کار آنها می پردازد.

RLE - یکنواختی فشرده

الگوریتم RLEاحتمالاً ساده‌تر از همه است: ماهیت آن در تکرار کدگذاری نهفته است. به عبارت دیگر، ما دنباله هایی از عناصر یکسان را می گیریم و آنها را به جفت های کمیت/مقدار "جمع می کنیم". به عنوان مثال، رشته ای مانند "AAAAAAAABCCCC" می تواند به رشته ای مانند "8 × A, B, 4 × C" تبدیل شود. به طور کلی، این تمام چیزی است که در مورد الگوریتم باید بدانید.

مثال پیاده سازی

فرض کنید مجموعه ای از ضرایب صحیح داریم که می توانند مقادیری از 0 تا 255 را بگیرند. منطقاً به این نتیجه رسیدیم که منطقی است این مجموعه را به صورت آرایه ای از بایت ها ذخیره کنیم:
داده های کاراکتر بدون علامت = (0، 0، 0، 0، 0، 0، 4، 2، 0، 4، 4، 4، 4، 4، 4، 4، 80، 80، 80، 80، 0، 2، 2 , 2, 2, 255, 255, 255, 255, 255, 0, 0);

برای بسیاری، دیدن این داده ها در قالب یک هگزا بسیار آشناتر خواهد بود:
0000: 00 00 00 00 00 00 04 02 00 04 04 04 04 04 04 04
0010: 50 50 50 50 00 02 02 02 02 FF FF FF FF FF 00 00

پس از اندکی فکر، به این نتیجه رسیدیم که برای صرفه جویی در فضا، خوب است به نحوی چنین مجموعه هایی را فشرده کنیم. برای انجام این کار، ما آنها را تجزیه و تحلیل کردیم و یک الگو را شناسایی کردیم: اغلب دنباله هایی متشکل از عناصر مشابه وجود دارد. البته RLE برای این کار مفید است!

بیایید داده های خود را با استفاده از دانش تازه به دست آمده رمزگذاری کنیم: 6 × 0، 4، 2، 0، 7 × 4، 4 × 80، 0، 4 × 2، 5 × 255، 2×0.

وقت آن است که به نحوی نتیجه خود را به شکلی قابل فهم برای کامپیوتر ارائه کنیم. برای انجام این کار، در جریان داده، باید به نحوی تک بایت ها را از رشته های کدگذاری شده جدا کنیم. از آنجایی که کل محدوده مقادیر بایت توسط داده های ما استفاده می شود، نمی توان به سادگی هر محدوده ای از مقادیر را برای اهداف خود اختصاص داد.

حداقل دو راه برای خروج از این وضعیت وجود دارد:

  1. یک مقدار بایت را به عنوان نشانگر زنجیره فشرده انتخاب کنید و در صورت برخورد با داده های واقعی، از آنها فرار کنید. به عنوان مثال، اگر از مقدار 255 برای اهداف "خدمات" استفاده کنیم، وقتی این مقدار را در داده های ورودی مشاهده کنیم، باید "255,255" را بنویسیم و بعد از نشانگر حداکثر از 254 استفاده کنیم.
  2. برای ساختار داده‌های رمزگذاری‌شده، تعداد آن‌ها را نه تنها برای عناصر تک‌تکرار، بلکه بعدی نیز مشخص کنید. سپس ما از قبل می دانیم که چه داده هایی هستند.
روش اول در مورد ما موثر به نظر نمی رسد، بنابراین، شاید، ما به روش دوم متوسل شویم.

بنابراین اکنون دو نوع دنباله داریم: رشته‌هایی از عناصر منفرد (مانند "4، 2، 0") و رشته‌هایی از عناصر یکسان (مانند "0، 0، 0، 0، 0، 0"). بیایید یک بیت در بایت های "سرویس" برای نوع دنباله اختصاص دهیم: 0 - عناصر تک، 1 - یکسان. بیایید برای این، مثلا، مهم ترین بیت از یک بایت را در نظر بگیریم.

در 7 بیت باقی مانده، طول دنباله ها را ذخیره می کنیم، یعنی. حداکثر طول دنباله کدگذاری شده 127 بایت است. ما می‌توانیم برای نیازهای سرویس، مثلاً دو بایت تخصیص دهیم، اما در مورد ما چنین توالی‌های طولانی بسیار نادر هستند، بنابراین ساده‌تر و مقرون به صرفه‌تر است که آنها را به‌صورت کوتاه‌تر تقسیم کنیم.

معلوم می شود که در جریان خروجی ابتدا طول دنباله را می نویسیم و سپس یک مقدار تکراری یا زنجیره ای از عناصر غیر تکراری با طول مشخص شده را می نویسیم.

اولین چیزی که باید توجه شما را جلب کند این است که در این شرایط چند مقدار استفاده نشده داریم. دنباله هایی با طول صفر نمی توانند وجود داشته باشند، بنابراین می توانیم افزایش دهیم حداکثر طولتا 128 بایت، یک بایت از طول در هنگام رمزگذاری کم می کند و یک بایت در هنگام رمزگشایی اضافه می کند. بنابراین، می توانیم طول های 1 تا 128 را به جای طول های 0 تا 127 رمزگذاری کنیم.

دومین چیزی که می توان به آن توجه کرد این است که هیچ دنباله ای از عناصر یکسان با طول واحد وجود ندارد. بنابراین، در طول رمزگذاری، یک عدد دیگر از مقدار طول چنین دنباله‌هایی کم می‌کنیم و در نتیجه حداکثر طول آنها را به 129 افزایش می‌دهیم (حداکثر طول یک زنجیره از عناصر منفرد هنوز برابر با 128 است). آن ها زنجیره ای از عناصر یکسان می تواند از 2 تا 129 طول داشته باشد.

بیایید دوباره داده های خود را رمزگذاری کنیم، اما اکنون به شکلی قابل فهم برای رایانه. بایت های سربار را به صورت می نویسیم که در آن T نوع دنباله و L طول آن است. فوراً در نظر می گیریم که طول ها را به شکل اصلاح شده می نویسیم: در T = 0 یک را از L کم می کنیم و در T = 1 - دو.

0, , 4, 2, 0, , 4, , 80, , 0, , 2, , 255, , 0

بیایید سعی کنیم نتیجه خود را رمزگشایی کنیم:

  • ... T = 1، به این معنی که بایت بعدی L + 2 (4 + 2) بار تکرار می شود: 0، 0، 0، 0، 0، 0.
  • ... T = 0، بنابراین ما فقط بایت های L + 1 (2 + 1) را می خوانیم: 4، 2، 0.
  • ... T = 1، بایت بعدی را 5 + 2 بار تکرار می کنیم: 4، 4، 4، 4، 4، 4، 4.
  • ... T = 1، بایت بعدی را 2 + 2 بار تکرار می کنیم: 80، 80، 80، 80.
  • ... T = 0، خواندن 0 + 1 بایت: 0.
  • ... T = 1، بایت را 2 + 2 بار تکرار کنید: 2، 2، 2، 2.
  • ... T = 1، بایت را 3 + 2 بار تکرار می کنیم: 255، 255، 255، 255، 255.
  • ... T = 1، بایت را 0 + 2 بار تکرار می کنیم: 0، 0.

و حالا آخرین مرحله: نتیجه را به عنوان یک آرایه بایت ذخیره کنید. به عنوان مثال، یک جفت بسته بندی شده در بایت ها به شکل زیر است:

در نتیجه موارد زیر را بدست می آوریم:
0000: 84 00 02 04 02 00 85 04 82 80 00 00 82 02 83 FF
0010: 80 00

به این روش ساده در این مثالما 18 بایت از 32 بایت داده ورودی دریافت کردیم. نتیجه بدی نیست، به خصوص با توجه به اینکه در زنجیره های طولانی تر می تواند بسیار بهتر باشد.

بهبودهای احتمالی

کارایی یک الگوریتم نه تنها به خود الگوریتم، بلکه به نحوه اجرای آن نیز بستگی دارد. بنابراین، برای داده های مختلف، می توانید انواع مختلفی از رمزگذاری و نمایش داده های رمزگذاری شده را توسعه دهید. برای مثال، هنگام رمزگذاری تصاویر، می‌توانید زنجیره‌هایی با طول متغیر بسازید: یک بیت را برای نشان دادن یک زنجیره بلند اختصاص دهید، و اگر روی یک تنظیم شد، طول آن را در بایت بعدی نیز ذخیره کنید. بنابراین طول زنجیره های کوتاه (65 عنصر به جای 129) را قربانی می کنیم، اما از طرف دیگر، این فرصت را می دهیم که زنجیره هایی با طول 16385 عنصر (2 14 + 2) را تنها با سه بایت رمزگذاری کنیم!

با استفاده از تکنیک های کدگذاری اکتشافی می توان کارایی بیشتری به دست آورد. به عنوان مثال، بیایید رشته زیر را به روش خود رمزگذاری کنیم: "ABBA". ما "، A،، B،، A" را دریافت می کنیم - i.e. ما 4 بایت را به 6 تبدیل کردیم، داده های اصلی را به اندازه یک و نیم برابر افزایش دادیم! و هر چه تعداد این توالی های متناوب کوتاه از انواع مختلف بیشتر باشد، داده های اضافی بیشتر می شود. اگر این را در نظر بگیریم، می‌توان نتیجه را به صورت "، A، B، B، A" رمزگذاری کرد - فقط یک بایت اضافی صرف می‌کردیم.

LZ77 - کوتاهی در تکرار

LZ77 یکی از ساده ترین و شناخته شده ترین الگوریتم های خانواده LZ است. به نام خالقان آن: آبراهام لمپل (ابراهام Lامپل) و یعقوب زیوا (یعقوب ز IV). اعداد 77 در عنوان به معنای سال 1977 است که در آن مقاله ای در مورد این الگوریتم منتشر شده است.

ایده اصلی این است که همان توالی عناصر را رمزگذاری کنیم. به این معنا که اگر زنجیره ای از عناصر بیش از یک بار در داده های ورودی اتفاق بیفتد، آنگاه تمام رخدادهای بعدی آن را می توان با "پیوندها" به اولین نمونه آن جایگزین کرد.

مانند بقیه الگوریتم‌های این خانواده، LZ77 از فرهنگ لغتی استفاده می‌کند که توالی‌هایی که قبلاً با آن‌ها مواجه شده‌اند را ذخیره می‌کند. برای این، او اصل به اصطلاح را اعمال می کند. " پنجره کشویی": ناحیه ای که همیشه قبل از موقعیت کدگذاری فعلی است که در آن می توانیم لینک ها را آدرس دهی کنیم. این پنجره یک فرهنگ لغت پویا برای است این الگوریتم- هر عنصر در آن با دو ویژگی مطابقت دارد: موقعیت در پنجره و طول. اگرچه از نظر فیزیکی، فقط یک تکه از حافظه است که قبلاً آن را رمزگذاری کرده ایم.

مثال پیاده سازی

حالا بیایید سعی کنیم چیزی را کد کنیم. بیایید یک خط مناسب برای این ایجاد کنیم (پیشاپیش از پوچ بودن آن عذرخواهی می کنم):

"فشرده سازی ورفع فشار تاثیری بر جای می گذارد. هاهاهاهاها!"

به این صورت در حافظه به نظر می رسد (رمزگذاری ANSI):
0000: 54 68 65 20 63 6F 6D 70 72 65 73 73 69 6F 6E 20 فشرده سازی
0010: 61 6E 64 20 74 68 65 20 64 65 63 6F 6D 70 72 65 و تجزیه
0020: 73 73 69 6F 6E 20 6C 65 61 76 65 20 61 6E 20 69 ssion ترک یک i
0030: 6D 70 72 65 73 73 69 6F 6E 2E 20 48 61 68 61 68 mppression. هههه
0040: 61 68 61 68 61 21 آهاها!

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

فشرده سازی و ترک [an] i. هه!"

برای وضوح بیشتر، بیایید به نموداری نگاه کنیم که در آن مطابقت های دنباله های تکرار شده و اولین رخدادهای آنها قابل مشاهده است:

شاید تنها نکته مبهم در اینجا سکانس "هاهاهاهاها!" اما هیچ چیز غیرعادی در اینجا وجود ندارد، ما از ترفندی استفاده کردیم که به الگوریتم اجازه می دهد گاهی مانند RLE که قبلا توضیح داده شد رفتار کند.

واقعیت این است که هنگام باز کردن بسته بندی، تعداد مشخص شده کاراکترها را از فرهنگ لغت می خوانیم. و از آنجایی که کل دنباله دوره ای است، یعنی. از آنجایی که داده های موجود در آن با یک دوره معین تکرار می شوند و نمادهای دوره اول درست در مقابل موقعیت باز کردن قرار می گیرند، می توانیم به سادگی با کپی کردن نمادهای دوره قبل در آن، کل زنجیره را از آنها بازسازی کنیم. بعد.

با این مرتب شده است. اکنون بیایید موارد تکراری پیدا شده را با پیوندهایی به فرهنگ لغت جایگزین کنیم. پیوند را با فرمت می نویسیم، جایی که P موقعیت اولین رخداد زنجیره در رشته است، L طول آن است.

فشرده‌سازی و ترک i. هه!"

اما فراموش نکنید که ما با یک پنجره کشویی روبرو هستیم. برای درک بهتر، به طوری که پیوندها به اندازه پنجره بستگی ندارند، موقعیت های مطلق را با تفاوت بین آنها و موقعیت رمزگذاری فعلی جایگزین می کنیم.

فشرده‌سازی و ترک i. هه!"

اکنون فقط باید P را از موقعیت رمزگذاری فعلی کم کنیم تا موقعیت مطلق را در رشته بدست آوریم.

زمان تصمیم گیری در مورد اندازه پنجره و حداکثر طول عبارت رمزگذاری شده است. از آنجایی که ما با متن سروکار داریم، به ندرت دنباله های تکراری طولانی در آن وجود خواهد داشت. بنابراین بیایید برای طول آنها، مثلاً 4 بیت اختصاص دهیم - محدودیت 15 کاراکتر در یک زمان برای ما کافی است.

اما اندازه پنجره در حال حاضر بستگی به این دارد که ما تا چه حد به دنبال زنجیره های یکسان باشیم. از آنجایی که ما با متون کوچک سروکار داریم، درست است که تعداد بیت‌هایی را که استفاده می‌کنیم به دو بایت تکمیل کنیم: پیوندهایی در محدوده 4096 بایت، با استفاده از 12 بیت برای این کار، آدرس‌دهی می‌کنیم.

ما از تجربه با RLE می دانیم که نمی توان از همه مقادیر استفاده کرد. بدیهی است که یک پیوند می تواند حداقل مقدار 1 داشته باشد، بنابراین، برای آدرس دهی در محدوده 1..4096، باید در حین رمزگذاری، یکی را از پیوند کم کنیم و هنگام رمزگشایی به آن اضافه کنیم. در مورد طول دنباله ها هم همینطور است: به جای 0..15 از محدوده 2..17 استفاده می کنیم، زیرا با طول های صفر کار نمی کنیم و کاراکترهای منفرد دنباله نیستند.

بنابراین، بیایید متن رمزگذاری شده خود را با این اصلاحات ارائه کنیم:

فشرده‌سازی و ترک i. هه!"

اکنون دوباره باید زنجیره های فشرده شده را از بقیه داده ها جدا کنیم. متداول ترین راه استفاده مجدد از ساختار و مشخص کردن مستقیم این است که داده های فشرده کجا هستند و کجا نیستند. برای انجام این کار، داده های رمزگذاری شده را به گروه های هشت عنصری (نمادها یا پیوندها) تقسیم می کنیم و قبل از هر یک از این گروه ها یک بایت درج می کنیم که هر بیت مربوط به نوع عنصر است: 0 برای یک نماد و 1. برای یک لینک

ما به گروه ها تقسیم می کنیم:

  • "کامپیوتر"
  • "واکنش"
  • "و تی د"
  • "ترک کردن"
  • "من. هه "
ترکیب گروه ها:

"(0.0.0.0.0.0.0.0) پاسخ (0.0.0.0.0.0.0.0) (0.0.0.0.0.1 , 0,0) و t de (1,0,0,0,0,0,1) ,0) ترک (0,1,0,0,0,0,0,1) i. هاه (0)!"

بنابراین، اگر در حین باز کردن بسته بندی با بیت 0 مواجه شدیم، آنگاه به سادگی کاراکتر را در جریان خروجی می خوانیم، اگر بیت 1 را می خوانیم، پیوند را می خوانیم و با ارجاع دنباله را از فرهنگ لغت می خوانیم.

اکنون تنها کاری که باید انجام دهیم این است که نتیجه را در یک آرایه بایت گروه بندی کنیم. بیایید موافقت کنیم که از بیت ها و بایت ها به ترتیب مهم استفاده می کنیم. بیایید ببینیم که چگونه پیوندها با استفاده از یک مثال در بایت ها بسته بندی می شوند:

در نتیجه، جریان فشرده ما به شکل زیر خواهد بود:

0000: 00 54 68 65 20 63 6f 6d 70 00 72 65 73 73 69 6f #The comp # ressio
0010: 6e 20 04 61 6e 64 20 74 01 31 64 65 82 01 5a 6c n #and t ## de ### l
0020: 65 61 76 65 01 b1 20 41 69 02 97 2e 20 48 61 68 eave ## # i ##. هه
0030: 00 15 00 21 00 00 00 00 00 00 00 00 00 00 00 00 ###!

بهبودهای احتمالی

در اصل، هر آنچه برای RLE توضیح داده شد، در اینجا صادق خواهد بود. به طور خاص، برای نشان دادن مزایای کدگذاری اکتشافی، به مثال زیر توجه کنید:

"گووووونگ طولانی. محدودتر است."

بیایید دنباله هایی را فقط برای کلمه "looooooower" پیدا کنیم:

"گووووونگ طولانی. مقید شدند."

برای رمزگذاری چنین نتیجه ای، ما به چهار بایت برای پیوندها نیاز داریم. با این حال، انجام این کار مقرون به صرفه تر است:

"گووووونگ طولانی. من مقید بودم."

سپس یک بایت کمتر خرج می کردیم.

به جای نتیجه گیری

علیرغم سادگی و کارایی ظاهراً نه چندان زیاد، این الگوریتم ها هنوز به طور گسترده در حوزه های مختلف حوزه فناوری اطلاعات مورد استفاده قرار می گیرند.

مزیت آنها سادگی و سرعت است و الگوریتم‌های پیچیده‌تر و کارآمدتر را می‌توان بر اساس اصول و ترکیب آن‌ها استوار کرد.

من امیدوارم که ماهیت این الگوریتم های ارائه شده به این طریق به کسی کمک کند تا اصول اولیه را درک کند و شروع به جستجوی چیزهای جدی تر کند.

حتی 10 تا 15 سال پیش، آرشیوها عمدتاً برای صرفه جویی در فضا در هارد دیسک ها و به منظور قرار دادن حداکثر مقدار داده بر روی فلاپی دیسک استفاده می شدند. با این حال، زمان تغییر کرده است. هیچ کس مدت زیادی است که از فلاپی دیسک به عنوان وسیله ای برای انتقال و ذخیره اطلاعات استفاده نمی کند و هزینه درایوها به قدری کم شده است که هیچ کس حتی به فشرده سازی داده ها برای صرفه جویی در فضا فکر نمی کند. علاوه بر این، حجم داده ها به قدری زیاد شده است که بایگانی و حذف آنها به منظور صرفه جویی در فضا به سادگی غیرعملی است، زیرا زمان زیادی می برد. در واقع، امروزه حجم اطلاعات درایوهای کاربران بر حسب ترابایت اندازه گیری می شود. حال تصور کنید که آرشیو یک ترابایت داده چقدر طول می کشد. نه یک یا حتی دو ساعت، بلکه حداقل 10-12 ساعت طول می کشد، یعنی کامپیوتر باید تمام شب روشن بماند.

به نظر می رسد که آرشیوهای امروزی باید به تدریج ارتباط خود را از دست بدهند. اما هیچ اتفاقی از این دست نمی افتد. اکثریت قریب به اتفاق کاربران، در میان سایر برنامه ها، بایگانی را نصب کرده اند، یا از بایگانی داخلی در سیستم عامل ویندوز استفاده می کنند (ما سایر سیستم عامل ها را در این نشریه در نظر نمی گیریم).

واقعیت این است که هدف بایگانی ها تغییر کرده است. امروزه آنها عمدتاً برای بارگذاری داده ها در وب استفاده می شوند. بیشتر درایورهای وب‌سایت‌های تولیدکنندگان در آرشیو قرار می‌گیرند و بیشتر برنامه‌های منابع مختلف نیز بایگانی می‌شوند. به هر حال، خود کاربر، قبل از آپلود هر گونه داده در شبکه (مثلاً برای منابع اشتراک فایل)، داده ها را در یک آرشیو بسته بندی می کند.

مربوط به بازار روسیه، سپس ما رایج ترین سه بایگانی را داریم: WinRAR، WinZip و 7-Zip که در هر دو نسخه 32 و 64 بیتی ارائه شده اند. در این مقاله به مقایسه آنها خواهیم پرداخت. با این حال، ابتدا به اختصار برخی را بررسی می کنیم جنبه های نظریکار بایگانی ها

الگوریتم های فشرده سازی اطلاعات

ماهیت هر الگوریتم فشرده سازی اطلاعات این است که مجموعه خاصی را در خروجی به دست آوریم کوچکتر... علاوه بر این، تمام الگوریتم های تبدیل داده ها را می توان به طور مشروط به دو دسته تقسیم کرد: برگشت پذیر و غیر قابل برگشت.

الگوریتم فشرده سازی اطلاعات برگشت ناپذیر به معنای چنین تغییر شکلی از توالی بیت اصلی است که در آن توالی خروجی با اندازه کوچکتر اجازه نمی دهد توالی ورودی به طور دقیق بازسازی شود. از الگوریتم‌های فشرده‌سازی برگشت‌ناپذیر برای مثال در رابطه با داده‌های گرافیکی، تصویری و صوتی استفاده می‌شود و این همیشه منجر به از دست دادن کیفیت آنها می‌شود. طبیعتاً الگوریتم های فشرده سازی برگشت ناپذیر داده ها در بایگانی کننده ها استفاده نمی شود و بنابراین در آینده آنها را در نظر نخواهیم گرفت.

الگوریتم‌های فشرده‌سازی داده‌های برگشت‌پذیر به شما این امکان را می‌دهند که توالی داده‌های اصلی را از دنباله فشرده‌شده به‌طور دقیق بازسازی کنید. این الگوریتم ها هستند که در بایگانی ها استفاده می شوند. مشخصات کلیاز همه الگوریتم‌های فشرده‌سازی عبارتند از: نسبت فشرده‌سازی (نسبت حجم توالی داده‌های اصلی و فشرده)، نرخ فشرده‌سازی (زمانی که برای آرشیو مقدار معینی از داده‌ها طول می‌کشد) و کیفیت فشرده‌سازی (مقداری که نشان می‌دهد چقدر قوی است. توالی داده با اعمال فشرده سازی مجدد روی آن یا الگوریتم دیگری فشرده می شود.

نظریه فشرده سازی اطلاعات، که به عنوان نظریه کدگذاری اقتصادی اطلاعات گسسته نیز شناخته می شود، شاخه نسبتاً پیچیده ای از علوم ریاضی است. البته ارائه حتی مبانی آن بسیار فراتر از حوصله این مقاله است و بنابراین ما فقط به صورت سطحی الگوریتم های مختلف فشرده سازی اطلاعات را بدون پرداختن به جزئیات بررسی خواهیم کرد. علاوه بر این، امروزه الگوریتم‌های فشرده‌سازی داده‌های زیادی توسعه یافته‌اند و در نظر گرفتن آنها نیز در وظیفه ما گنجانده شده است. بنابراین، ما فقط در سطح کیفی در مورد چندین الگوریتم صحبت خواهیم کرد که به شما امکان می دهد یک ایده کلی از روش های فشرده سازی اطلاعات به دست آورید.

الگوریتم RLE

یکی از قدیمی‌ترین و ساده‌ترین روش‌های فشرده‌سازی اطلاعات، الگوریتم RLE (Run Length Encoding) است، یعنی الگوریتمی برای رمزگذاری یک سری دنباله‌ها. پیاده سازی این روش بسیار ساده است و یکی از الگوریتم های آرشیو است و ماهیت آن جایگزینی یک سری (گروهی) از بایت های تکراری با یک بایت رمزگذاری و شمارنده تعداد تکرارهای آنهاست. یعنی گروهی از بایت های یکسان با یک جفت جایگزین می شوند:<счетчик повторений, значение>، که باعث کاهش افزونگی داده ها می شود.

در این الگوریتم شمارنده با آنهایی که در دو بیت بالای بایت خوانده شده نشان داده می شود. به عنوان مثال، اگر دو بیت اول 11 باشد، 6 بیت باقی مانده به یک شمارنده اختصاص داده می شود که می تواند مقادیری از 1 تا 64 داشته باشد. بر این اساس، یک سری از 64 بایت تکراری را می توان تنها با دو بایت تعیین کرد، که است، 32 بار فشرده شده است.

نوع دیگری از اجرای این الگوریتم وجود دارد، زمانی که ویژگی شمارنده 1 در بایت اول شمارنده باشد. در این مورد، شمارنده می تواند حداکثر مقداربرابر با 127 - و بنابراین حداکثر نسبت تراکم 64 خواهد بود.

واضح است که الگوریتم RLE تنها زمانی مؤثر است که تعداد زیادی گروه طولانی از بایت های یکسان وجود داشته باشد. اگر بایت ها تکرار نشدند، استفاده از روش RLE باعث افزایش حجم فایل می شود.

RLE به طور کلی برای فشرده سازی گرافیک های بیت مپ (BMP، PCX، TIF، GIF) بسیار موثر است، زیرا آنها حاوی تعداد زیادی سری طولانی از توالی بایت های تکراری هستند.

محدودیت الفبای اطلاعات

یکی دیگر از راه های نسبتاً ساده برای فشرده سازی اطلاعات را می توان محدودیت نامید الفبای اطلاعات... بلافاصله متذکر می شویم که چنین الگوریتمی در عمل پیاده سازی نشده است، اما ارائه این روش به درک بهتر روش کدهای طول متغیر کمک می کند.

در ادامه، در زیر الفبای اطلاعات، منظور مجموعه کاراکترهایی است که برای رمزگذاری توالی اطلاعات استفاده می شود. به عنوان مثال، فرض کنید یک پیام متنی وجود دارد. یک جدول ASCII از 256 کاراکتر برای رمزگذاری هر حرف این پیام استفاده می شود. در این حالت دقیقاً 8 بیت (1 بایت) برای رمزگذاری هر کاراکتر اختصاص داده می شود. در این مورد، الفبای اطلاعات تمام 256 کاراکتر جدول رمزگذاری ASCII است.

واضح است که تمام 256 کاراکتر جدول ASCII ممکن است در پیام متنی اصلی استفاده نشود. به عنوان مثال، اگر می آیددر مورد یک پیام متنی به زبان روسی، که در آن هیچ عددی وجود ندارد، سپس 64 کاراکتر کافی است (33 حرف کوچک و 31 حرف بزرگ). اگر علائم نگارشی، پاراگراف ها و خطوط جدید را به این اضافه کنید، مشخص می شود که تعداد کاراکترها از 100 تجاوز نمی کند. در این حالت، می توانید از رمزگذاری نویسه نه 8، بلکه 7 بیتی استفاده کنید که به شما امکان می دهد جدول 128 کاراکتری یعنی به نوعی الفبای اطلاعات را محدود می‌کنیم، به همین دلیل می‌توانیم عمق بیت هر کاراکتر را کاهش دهیم. می توانید بیشتر بروید - برای تعیین دقیق تعداد کاراکترهای استفاده شده در یک پیام متنی. برای مثال، اگر معلوم شود که فقط 30 کاراکتر در پیام دخیل است (از جمله کاراکترهای خط جدید)، می توانید از یک جدول رمزگذاری 5 بیتی حاوی 32 کاراکتر استفاده کنید و سپس نسبت فشرده سازی پیام متنی حتی بیشتر می شود. . در واقع، اگر پیام اصلی از کدنویسی کاراکتر 8 بیتی و پیام فشرده شده از 5 بیت استفاده کند، نسبت فشرده سازی 8/5 خواهد بود.

با وجود سادگی ظاهری روش محدود کردن الفبا، در عمل از آن استفاده نمی شود. واقعیت این است که روش توصیف شده به شما اجازه نمی دهد پیام اصلی را بدون ارسال به درستی رمزگشایی کنید اطلاعات اضافی... در واقع، بدون دانستن جداول رمزگذاری مورد استفاده برای فشرده سازی اطلاعات، رمزگشایی آن غیرممکن است. یعنی در کنار توالی اطلاعات کدگذاری شده، انتقال جداول کدگذاری ضروری است. واضح است که در این صورت سود استفاده از الفبای محدود به صفر می رسد.

روش الفبای محدود معایب دیگری نیز دارد. اگر پیام اطلاعات اصلی حاوی تعداد زیادی کاراکتر مختلف باشد، امکان کاهش عمق بیت کاراکترهای الفبا وجود نخواهد داشت و این روش به سادگی کار نخواهد کرد. برای مثال فرض کنید پیام داده اصلی حاوی 129 کاراکتر از یک الفبای 256 کاراکتری است. در این حالت استفاده از رمزگذاری کاراکترهای 7 بیتی امکان پذیر نخواهد بود، زیرا 7 بیت تنها اجازه رمزگذاری 128 کاراکتر را می دهد. بنابراین، برای 129 کاراکتر، باید به همان رمزگذاری 8 بیتی مانند الفبای 256 کاراکتری اصلی برگردید.

کدهای با طول متغیر

یکی از معایب اصلی روش فرضی محدود کردن الفبای که در نظر گرفته‌ایم این است که زمانی از یک کد یکنواخت استفاده می‌کند که تمام کاراکترهای الفبای اطلاعات دارای طول یکسان (۸، ۷ بیت یا کمتر) باشند. منطقی تر است که از چنین سیستم کدگذاری استفاده کنیم که در آن طول کد کاراکتر به دفعات وقوع آن در پیام اطلاعاتی بستگی دارد. یعنی اگر در پیام اصلی اطلاعات برخی از کاراکترها بیشتر از سایرین یافت شوند، استفاده از آنها بهینه است کدهای کوتاهو برای موارد نادر، طولانی تر.

به عنوان یک مثال فرضی، پیام اطلاعاتی زیر را در نظر بگیرید: "سانحه هوایی" که شامل 14 کاراکتر است. فرض کنید یک الفبای 14 کاراکتری داریم که به ما امکان می دهد این پیام را رمزگذاری کنیم. اگر از یک کد یکنواخت استفاده شود، برای هر کاراکتر الفبا 4 بیت لازم است (طول کد 4 بیتی امکان تشکیل 16 کاراکتر را فراهم می کند). با این حال، به راحتی می توان فهمید که در پیام اطلاعاتی ما نماد "a" پنج بار، نماد "t" دو بار و بقیه نمادها یک بار رخ می دهد. اگر برای کاراکتر "a" از کدی با طول 2 بیت، برای کاراکتر "t" - طول 3 بیت و برای کاراکترهای باقی مانده - طول 4 بیت استفاده کنیم، مطمئناً می توانیم در هزینه صرفه جویی کنیم. فقط لازم است درک کنیم که دقیقاً چگونه کدهایی با طول متغیر ایجاد کنیم و دقیقاً چگونه طول کد باید به فراوانی ظاهر نماد در پیام اطلاعاتی بستگی داشته باشد.

اگر همه کاراکترها پیام اطلاعاتی را با فرکانس یکسان وارد کنند (به همان اندازه احتمال دارد)، سپس با یک الفبای اطلاعاتی N کاراکتر، برای رمزگذاری هر کاراکتر، دقیقاً log 2 را وارد کنید. نبیت در واقع، این مورد یک کد یکنواخت است.

اگر نمادها در پیام اطلاعاتی احتمال وقوع متفاوتی داشته باشند، بر اساس نظریه K. شانون، نمادی که احتمال آن برابر با p است، بهینه است و آنچه اهمیت ویژه دارد، از لحاظ نظری مجاز است که کد طول – log 2 پ... برگردیم به مثال خود با پیام اطلاعاتی "سقوط هواپیما" و با توجه به اینکه احتمال ظهور نماد "a" (p (a)) 5/14 است، احتمال ظهور نماد "t" برابر 2 است. /14، و احتمال ظهور همه نمادهای دیگر 1 / 14 است، دریافت می کنیم که: برای کاراکتر "a" طول کد بهینه –log 2 (5/14) = 1.48 بیت است. برای نماد "t" -log 2 (2/14) = 2.8 بیت و برای همه نمادهای دیگر -log 2 (1/14) = 3.8 است. از آنجایی که در مورد ما طول کد فقط می تواند یک مقدار صحیح داشته باشد، پس با گرد کردن، دریافت می کنیم که برای کاراکتر "a" بهتر است از یک کد با طول 2 بیت برای کاراکتر "t" استفاده شود. - طول 3 بیت، و برای بقیه - طول 4 بیت.

بیایید نسبت فشرده سازی را هنگام استفاده از این رمزگذاری محاسبه کنیم. اگر از یک کد یکنواخت مبتنی بر الفبای 14 کاراکتری استفاده شود، برای رمزگذاری کلمه "سقوط هواپیما" به 56 بیت نیاز است. کدهای با طول متغیر به 5x2 بیت + 2x3 بیت + 7x4 بیت = 44 بیت برای نسبت فشرده سازی 1.27 نیاز دارند.

حالا بیایید الگوریتم های بدست آوردن کدهای طول متغیر را بررسی کنیم.

رمزگذاری پیشوند

اکثر روش سادهدریافت کدهای با طول متغیر به اصطلاح کدگذاری پیشوندی است که به شما امکان می دهد کدهای طول صحیح را بدست آورید. ویژگی اصلیکدهای پیشوندی این است که در هر یک از سیستم های آنها، طول کدهای کوتاه تر با آغاز (پیشوند) کدهای طولانی تر منطبق نیست. این ویژگی کدهای پیشوندی است که رمزگشایی اطلاعات را بسیار آسان می کند.

اجازه دهید این ویژگی کدهای پیشوند را با یک مثال خاص توضیح دهیم. اجازه دهید یک سیستم از سه کد پیشوند وجود داشته باشد: (0، 10، 11). همانطور که می بینید، کد کوتاهتر 0 با ابتدای کدهای طولانی تر 10 و 11 منطبق نیست. اجازه دهید کد 0 کاراکتر "a"، کد 10 - کاراکتر "m" و کد 11 - کاراکتر را مشخص کند. پ". سپس کلمه "frame" با دنباله 110100 رمزگذاری می شود. بیایید سعی کنیم این دنباله را رمزگشایی کنیم. از آنجایی که بیت اول 1 است، کاراکتر اول فقط می تواند "m" یا "p" باشد و با مقدار بیت دوم تعیین می شود. از آنجایی که بیت دوم 1 است، کاراکتر اول "p" است. بیت سوم 0 است و به طور منحصر به فردی با کاراکتر "a" مطابقت دارد. بیت چهارم 1 است، یعنی باید به مقدار بیت بعدی نگاه کنید که 0 است، سپس کاراکتر سوم "m" است. آخرین بیت 0 است که به طور منحصر به فرد با کاراکتر "a" مطابقت دارد. بنابراین، خاصیت کدهای پیشوندی که کدهای کوتاهتر نمی توانند با آغاز کدهای طولانی تر منطبق شوند، رمزگشایی بدون ابهام یک پیام اطلاعاتی رمزگذاری شده با کدهای پیشوند طول متغیر را ممکن می سازد.

کدهای پیشوند معمولاً با ساخت کد (for سیستم دودویی) درختان. هر گره داخلی چنین درخت باینری دارای دو یال خروجی است که یک یال آن مربوط به کاراکتر باینری "0" و دیگری "1" است. برای قطعیت، می توانیم توافق کنیم که لبه سمت چپ باید با نماد "0" و لبه سمت راست - نماد "1" مرتبط باشد.

از آنجایی که هیچ چرخه ای در درخت وجود ندارد، همیشه می توانید یک مسیر واحد از گره ریشه به گره برگ ایجاد کنید. اگر لبه های درخت شماره گذاری شده باشند، هر یک از این مسیرها به دنباله ای باینری منحصر به فرد مربوط می شود. مجموعه تمام این توالی ها یک سیستم کد پیشوندی را تشکیل می دهند.

برای مثال در نظر گرفته شده از یک سیستم از سه کد پیشوند: (0، 10، 11)، که نمادهای "a"، "m" و "p" را تعریف می کنند، درخت کد در شکل نشان داده شده است. 1.

برنج. 1. درخت کد برای سیستم
از سه کد پیشوند: (0، 10، 11)

راحتی نمایش درخت مانند کدهای پیشوند در این واقعیت نهفته است که ساختار درخت مانند است که امکان تولید کدهای با طول متغیر را فراهم می کند که شرایط اصلی کدهای پیشوندی را برآورده می کند، یعنی شرایطی که کدهای کوتاه تر را برآورده می کند. با شروع کدهای طولانی تر همخوانی ندارد.

تا کنون، ما فقط به ایده کدهای پیشوند با طول متغیر نگاه کرده ایم. در مورد الگوریتم های به دست آوردن کدهای پیشوند، تعداد کمی از آنها وجود دارد، اما معروف ترین آنها دو روش است: شانون-فانو و هافمن.

الگوریتم شانون-فانو

این الگوریتم برای به دست آوردن کدهای پیشوند به طور مستقل توسط R. Fano و K. Shannon ارائه شده است که در ادامه آمده است. در مرحله اول، تمام نمادهای توالی اطلاعات اصلی بر حسب کاهش یا افزایش احتمال ظهور (تکرار ظهور آنها) مرتب می شوند و پس از آن ردیف مرتب نمادها در جایی به دو قسمت تقسیم می شود تا در هر یک از آنها مجموع فرکانس های نماد تقریباً یکسان است. به عنوان یک نمایش، کلمه ای را که قبلاً برای ما آشنا است در نظر بگیرید "سانحه هوایی" .

اگر شخصیت ها را تشکیل می دهند کلمه داده شده، به ترتیب نزولی فراوانی وقوع آنها مرتب می شوند، دنباله زیر را دریافت می کنیم: (a (5)، t (2)، در (1)، و (1)، تا (1)، c (1)، p ( 1)، o (1)، ф (1)) (تکرار یک کاراکتر در یک کلمه در پرانتز نشان داده شده است). در مرحله بعد، باید این دنباله را به دو قسمت تقسیم کنیم تا در هر یک از آنها مجموع فرکانس های نماد تقریباً یکسان باشد (تا حد امکان). واضح است که این بخش از بین نمادهای "t" و "b" عبور می کند که در نتیجه دو دنباله تشکیل می شود: (a (5) ، t (2)) و (در (1) و (1). )، به (1)، c (1)، p (1)، o (1)، φ (1)). همچنین مجموع دفعات تکرار نمادها در سکانس اول و دوم یکسان و برابر با 7 خواهد بود.

در اولین مرحله از تقسیم یک دنباله از کاراکترها، اولین رقم کد هر کاراکتر را به دست می آوریم. قانون ساده است: برای آن دسته از کاراکترهایی که در دنباله سمت چپ ظاهر می شوند، کد با "0" شروع می شود و برای کسانی که در سمت راست هستند - با "1".

به طور خاص، دنباله (a (5)، m (2)) به دو کاراکتر جداگانه تقسیم می شود: a (5) و m (2) (تقسیمات دیگری وجود ندارد). سپس رقم دوم کد برای نماد "a" "0" و برای نماد "t" - "1" است. از آنجا که، در نتیجه تقسیم دنباله، به دست آوردیم عناصر فردی، سپس آنها دیگر تقسیم نمی شوند و برای کاراکتر "a" کد 00 و برای کاراکتر "t" - کد 01 را می گیریم.

دنباله (در (1)، u (1)، تا (1)، c (1)، p (1)، o (1)، f (1)) را می توان به دنباله هایی تقسیم کرد (در (1)، و (1)، k (1)) و (c (1)، p (1)، o (1)، φ (1))، یا در (در (1)، u (1)، k (1) )، (c (1)) و (p (1)، o (1)، φ (1)).

در حالت اول، مجموع نرخ های تکرار نمادها در سکانس اول و دوم به ترتیب 3 و 4 و در حالت دوم، 4 و 3 خواهد بود. برای وضوح، از گزینه اول استفاده می کنیم.

برای کاراکترهای دنباله جدید حاصل (در (1)، و (1)، تا (1)) (این دنباله سمت چپ است)، دو رقم اول کد 10 خواهد بود و برای دنباله (c ( 1)، p (1)، o (1)، φ (1)) - 11.

در مثال ما (شکل 2 و 3) سیستم کدهای پیشوند زیر به دست آمده است: "a" - 00، "t" - 01، "b" - 100، "u" - 1010، "k" - 1011، " c" - 1100، "p" - 1101، "o" - 1110، "f" - 1111. همانطور که می بینید، کدهای کوتاهتر آغاز کدهای طولانی تر نیستند، یعنی خاصیت اصلی کدهای پیشوند برآورده شده است.

برنج. 2. نمایش الگوریتم شانون-فانو

برنج. 3. درخت کد کلمه "سقوط هواپیما"
در الگوریتم شانون-فانو

الگوریتم هافمن

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

در مرحله اول، مانند الگوریتم شانون-فانو، دنباله اصلی کاراکترها به ترتیب نزولی فراوانی تکرار کاراکترها (عناصر دنباله) مرتب می شوند. برای مثال بالا با کلمه "سانحه هوایی" دنباله مرتب شده زیر را از عناصر بدست می آوریم: (a (5)، t (2)، در (1)، u (1)، k (1)، c (1)، p (1)، o (1)، φ (1)).

سپس، دو عنصر آخر دنباله با یک عنصر جدید S1 جایگزین می‌شوند که تکرارپذیری برابر با مجموع تکرارپذیری به آن اختصاص داده می‌شود. عناصر اصلی... سپس، عناصر دنباله مجدداً مطابق با تکرارپذیری آنها مرتب می شوند. در مورد ما، دو عنصر آخر o (1) و φ (1) با عنصر S1 (2) جایگزین می‌شوند و دنباله مرتب‌سازی شده جدید به شکل زیر خواهد بود: (a (5)، m (2)، S1 ( 2)، در (1)، u (1)، k (1)، c (1)، p (1)).

ادامه این روش، جایگزین دو آخرین آیتم هادنباله به یک عنصر جدید با قابلیت تکرار کلی و مرتب سازی مجدد بعدی دنباله مطابق با تکرارپذیری عناصر، به وضعیتی خواهیم رسید که تنها یک عنصر در دنباله وجود خواهد داشت (شکل 4).

برنج. 4. نمایش الگوریتم هافمن
با استفاده از مثال کلمه "سقوط هواپیما"

همزمان با جایگزینی عناصر و مرتب سازی مجدد توالی، یک درخت کد باینری ساخته می شود. الگوریتم ساخت درخت بسیار ساده است: عملیات ترکیب (جایگزینی) دو عنصر دنباله یک گره جدید در درخت کد ایجاد می کند. یعنی اگر از پایین به بالا به درخت نگاه کنید، لبه‌های درخت کد همیشه از عناصر جایگزین شده می‌آیند و در یک عنصر گره جدید مطابق با عنصر دنباله‌ای که با جایگزینی به دست می‌آید همگرا می‌شوند (شکل 5). در این حالت، لبه سمت چپ درخت کد را می توان مقدار "0" و به سمت راست - "1" اختصاص داد. این مقادیر بیشتر به عنوان عناصر عمل خواهند کرد کد پیشوند.

برنج. 5. ساختن درخت کد
در الگوریتم هافمن
(به جای عناصر "o" و "f"
عنصر جدید S1)

درخت کد هافمن را برای یک کلمه کامل کنید "سانحه هوایی" ، در شکل نشان داده شده است. 6.

برنج. 6. درخت کد کامل کلمه "سقوط هواپیما"
توسط الگوریتم هافمن ساخته شده است

با قدم زدن در لبه های درخت کد از بالا به پایین، به راحتی می توان کدهای پیشوندی را برای همه نمادهای الفبای اطلاعات ما دریافت کرد:

اگر اکنون سعی کنید یک کلمه بنویسید "سانحه هوایی" در رمزگذاری هافمن، دنباله 41 بیتی 0 1101 11000 0 11001 0 111 0 1010 111 1011 1000 1001 0 را دریافت می کنیم. جالب است توجه داشته باشید که هنگام استفاده از Shannon-Fano، کدهای پیشوند 1-bit را نیز برای کدهای 4 دریافت می کنیم. کلمه "سقوط هواپیما". یعنی در یک مثال خاص، بازده کدگذاری هافمن و شانون فانو یکسان است. اما اگر در نظر بگیریم که الفبای اطلاعات واقعی 256 کاراکتر است (و نه 14 کاراکتر، مانند مثال ما)، و دنباله های اطلاعات واقعی فایل هایی با هر محتوا و طولی هستند، در این صورت این سوال در مورد کد پیشوند بهینه مطرح می شود، یعنی: کدی که به شما امکان می دهد حداقل طول دنباله خروجی را بدست آورید.

می توان ثابت کرد که سیستم کدهای به دست آمده با استفاده از الگوریتم هافمن در بین تمام سیستم های ممکن کدهای پیشوندی بهترین است به این معنا که طول توالی اطلاعات رمزگذاری شده به دست آمده حداقل است. یعنی الگوریتم هافمن بهینه است.

نقطه ضعف اصلی الگوریتم هافمن پیچیدگی فرآیند ساخت سیستم کدها است. با این وجود، این الگوریتم بهینه هافمن است که رایج ترین الگوریتم تولید کد با طول متغیر است و در اکثر ابزارهای فشرده سازی و بایگانی اطلاعات گنجانده شده است.

کدگذاری حسابی

همانطور که قبلاً اشاره کردیم، طبق معیار شانون، کد بهینه کدی است که در آن یک کد با طول –log 2 برای هر کاراکتر تخصیص داده شود. پبیت و اگر، برای مثال، احتمال یک کاراکتر خاص 0.2 باشد، طول بهینه کد آن -log 2 0.2 = 2.3 بیت خواهد بود. واضح است که کدهای پیشوندی نمی توانند چنین طول کدی را ارائه دهند و بنابراین بهینه نیستند. به طور کلی، طول کد تعیین شده توسط معیار شانون تنها یک محدودیت نظری است. تنها سوال این است که کدام روش کدگذاری به شما امکان می دهد تا حد امکان به این حد تئوریک نزدیک شوید. کدهای پیشوند با طول متغیر کارآمد و آسان برای پیاده سازی هستند، اما تعداد بیشتری نیز وجود دارد راه های موثرکدگذاری، به ویژه الگوریتم کدگذاری حسابی.

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

ایده پشت الگوریتم کدگذاری حسابی به شرح زیر است. مانند تمام روش های کدگذاری که قبلاً در نظر گرفته شد، هر نماد از توالی اطلاعات اصلی با احتمال مشخص می شود. به دنباله بدون کد اصلی یک نیم فاصله اختصاص داده می شود)

مقالات مرتبط برتر