تکنیک Folding در جاوا — به زبان ساده

۱۲۰ بازدید
آخرین به‌روزرسانی: ۶ شهریور ۱۴۰۲
زمان مطالعه: ۴ دقیقه
تکنیک Folding در جاوا — به زبان ساده

این راهنما به بررسی تکنیک‌های هش کردن اختصاص دارد که در ساختمان‌های داده مختلف برای ایجاد زمان دسترسی ثابت به عناصرشان استفاده می‌شوند. در این مقاله به بررسی جزییات تکنیک Folding در جاوا می‌پردازیم و مقدمه‌ای کوتاه در مورد تکنیک‌های mid-square و «بسته‌بندی» (binning) ارائه می‌کنیم.

997696

مقدمه

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

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

برای حل این مشکل بسیاری از ساختمان‌های داده تلاش می‌کنند یک مقدار عددی انتساب دهند که به عنوان یک اندیس آرایه برای اشیا عمل می‌کند. ما این مقدار را یک مقدار هش یا صرفاً هش (hash) می‌نامیم.

هش کردن

هش کردن به معنی تبدیل یک شیء به یک مقدار عددی است. تابع‌هایی که این تبدیل‌ها را اجرا می‌کنند به نام توابع هش نامیده می‌شوند. به منظور ساده‌تر کردن موضوع تصور کنید تابع‌های هش رشته‌ها را به اندیس‌های آرایه تبدیل می‌کنند، یعنی به اعداد صحیح در بازه [0, N] تبدیل می‌شوند که N متناهی است.

به طور طبیعی یک تابع هش روی طیف وسیعی از رشته‌ها اعمال می‌شود. از این رو مشخصه‌های global آن مهم می‌شوند.

تکنیک Folding در جاوا

متأسفانه امکان این که یک تابع هش رشته‌های مختلف را به اعداد متفاوت هش کند وجود ندارد. این امکان وجود دارد که تعداد رشته‌ها بسیار بزرگ‌تر از تعداد اعداد صحیح در هر بازه [0, N] باشد. در این حالت ناگزیر یک جفت رشته نابرابر وجود خواهند داشت که برای آن‌ها مقادیر هش برابری تولید می‌شود. این پدیده به نام «تصادم» (collision) شناخته می‌شود.

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

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

تکنیک Folding در جاوا

هدف ما یافتن تابعی است که رشته‌ها را به اندیس‌های آرایه تبدیل کند. برای نمایش این ایده فرض کنید که می‌خواهیم این آرایه ظرفیتی برابر با 5^10 عنصر داشته باشد و از زبان جاوا به عنوان یک مثال استفاده می‌کنیم.

توصیف

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

Folding

اکنون اعدادی را که به دست آمده در گروه‌های با اندازه یکسان می‌چینیم. به طور کلی ما مقدار اندازه گروه را بر اساس اندازه آرایه خود انتخاب می‌کنیم که 5^10 است. از آنجا که اعدادی که رشته‌ها را به آن‌ها تبدیل کردیم شامل دو تا سه رقم هستند، بدون از دست دادن تعمیم‌پذیری قضیه می‌توانیم اندازه گروه را روی دو تنظیم کنیم:

Folding

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

Folding

اکنون باید گام نهایی را برداریم. بررسی می‌کنیم که آیا تعداد 348933 می‌تواند به عنوان یک اندیس برای آرایه با اندازه 5^10 عمل کند یا نه. به طور طبیعی این عدد از بیشینه مقدار مجاز یعنی 99999 بیشتر است. با به‌کارگیری عملگر همنهشتی برای یافتن نتیجه نهایی به صورت زیر می‌توان به سادگی بر این مشکل غلبه کرد:

348933% 10000 = 48933

توضیح نهایی

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

برای نمونه اگر بخواهیم از folding اجتناب کنیم و عملگر همنهشتی را مستقیماً روی رشته ورودی با قالب‌بندی ASCII عمال کنیم، با نادیده گرفتن مشکل سرریز نتیجه زیر به دست می‌آید:

749711897321089711010311797103101% 100000 = 3101

در این صورت چنین تابعی می‌تواند مقدار یکسانی را برای همه رشته‌های ورودی که دو کاراکتر پایانی یکسانی دارند برای نمونه برای age ،page ،large و غیره ایجاد کند.

از روی توصیف الگوریتم می‌دانیم که مصون از بروز تصادم نیست. برای نمونه الگوریتم مقدار هش یکسانی برای دو رشته Java language و vaJa language تولید می‌کند.

تکنیک‌های دیگر

تکنیک Folding کاملاً رایج است، اما تنها گزینه رایج محسوب نمی‌شود. برخی اوقات تکنیک‌های binning یا mid-square نیز می‌توانند مفید باشند.

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

تکنیک Binning

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

Folding

تکنیک Mid-Square

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

Folding

این الگوریتم را با یک مثال مناسب توضیح می‌دهیم. فرض کنید یک عدد چهاررقمی به صورت 1111 داریم. بر اساس این الگوریتم آن را به توان 2 می‌رسانیم. بدین ترتیب عدد 1234321 به دست می‌آید. برای نمونه چهار رقم میانی را استخراج می‌کنیم که 2343 است. این الگوریتم امکان تکرار این فرایند را تا زمانی که نتیجه مطلوب به دست آید فراهم کرده است.

سخن پایانی

در این راهنما چند تکنیک هش را مورد بررسی قرار دادیم. تکنیک folding را به تفصیل بررسی کردیم و توضیح کوتاهی در مورد تکنیک‌های binning و mid-square ارائه نمودیم. کدهای کامل الگوریتم‌های معرفی شده در این مقاله را می‌توانید در این صفحه (+) مشاهده کنید.

اگر این مطلب برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

==

بر اساس رای ۰ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
baeldung
نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *