هرم جفت‌شده

از ویکی‌پدیا، دانشنامهٔ آزاد

یک هرم جفت شده یک نوع داده ساختار هیپ با پیاده‌سازی نسبتاً ساده و عملکرد سرشکن شدهٔ عالی معرفی شده توسط Micheal Fredman، Robert Sedgewick، Daniel Sleator و Robert Tarjan در سال ۱۹۸۶ می‌باشد.[۱] هرمهای جفت شده ساختمان‌های درختی چند راهه می‌باشند که مانند هرم مرتب شده‌اند و می‌توانند هرمهای فیبوناچی ساده شده در نظر گرفته شوند. آن‌ها انتخابات قوی برای پیاده‌سازی الگوریتم‌هایی مانند الگوریتم پریم در نظر گرفته می‌شوند[۲] و از توابع زیر پیروی می‌کنند (با فرض اینکه مین-هیپ باشند):

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

تحلیل پیچیدگی زمانی هرمهای جفت شده ابتدا از درختان اسپلی الهام گرفته شده بود.[۱] اوردر سرشکن شدهٔ هر حذف کمینه O(log n) است و عملیات پیدا کردن حداقل، ادغام و درج در سرشکن شدهٔ O(1) انجام می‌گیرد.[۳]

تعیین زمان دقیق مجانبی هرمهای جفت شده زمانی که یک عملیات کاهش کلید نیاز است کمی دشوار می‌باشد. در ابتدا به صورت تجربی حدس می‌زدند که زمان پیچیدگی این عملیات O(1) باشد[۴] اما Fredman ثابت کرد که زمان سرشکن هر کاهش کلید برای توالی برخی عملیات حداقل است.[۵] با استفاده از متدهای مختلف استدلال استهلاکی Pettie پس از آن ثابت کرد که درج کردن و کاهش-کلید همه در سرشکن می‌شوند که برابر است.[۶] بعد از مدتی Elmasry یک نوع هرم جفت شده معرفی کرد که کاهش کلید آن به صورت سرشکن در انجام می‌شود و سایر عملیات مطابق هیپ فیبوناچی است[۷] اما برای داده ساختار اصلی درست نیست.[۳][۶] اما این یک سؤال بی جواب است که سرشکن برای کاهش-کلید و برای درج کردن را می‌توان به طور همزمان داشت یا خیر.[۸]

اگر چه این بدتر از دیگر الگوریتم‌های صف اولویت مانند هیپ فیبوناچی است که انجام کاهش کلیدشان در سرشکن است ولی در عمل بسیار عالی می‌باشند. Stasko و Vitter[۴] Moret و shapiro[۹] و larkin و sen و Tarjan[۸] روی هرمهای جفت شده و سایر ساختمان‌های دادهٔ هرم آزمایش‌هایی انجام دادند. آنها به این نتیجه رسیدند که هرمهای جفت شده اغلب در عمل سریع تر از هیپ‌های دودویی مبتنی بر آرایه و هیپ دی تایی و تقریباً همیشه عملاً سریع ترند نسبت به دیگر هرمهای مبتنی بر اشاره گر از جمله ساختارهای داده‌ای مثل هیپ فیبوناچی که به لحاظ نظری کارآمد ترند.

ساختار[ویرایش]

یک هرم جفت شده یا یک هرم خالی است یا یک جفت متشکل از یک ریشه و احتمالاً یک لیست خالی از هرمهای جفت شده. برای ویژگی ترتیب هرمها نیاز است که ریشه هیچ‌کدام از زیرهرمهای این هرم کوچکتر از ریشهٔ خود هرم نباشند. این توصیف صرفاً یک هرم تابعی را می‌دهد که از کاهش کلید پشتیبانی نمی‌کند.

type PairingHeap[Elem] = Empty | Heap(elem: Elem, subheaps: List[PairingHeap[Elem]])

یک پیاده‌سازی بر اساس اشاره گر برای ماشین‌های رم می‌توان ارائه داد که از کاهش کلید پشتیبانی می‌کند. این پیاده‌سازی در هر گره سه اشاره گر دارد: یکی به اولین فرزندش، یکی به برادرش و یکی به پدرش. همچنین اشاره به پدر می‌تواند حذف شود اگر برگ‌ها به جای فرزند به ریشه اشاره کنند و یک پرچم برای برگ‌ها گذاشته شود تا تشخیص داده شوند؛ که این یک ساختار جمع و جور تر است با همان سربار قبلی.[۱]

عملیات‌ها[ویرایش]

پیدا کردن مینیمم[ویرایش]

تابع پیدا کردن مینیمم فقط ریشهٔ هرم را برمی‌گرداند:

function find-min(heap)

 if heap == Empty
 error
 else
 return heap.elem

ادغام[ویرایش]

ادغام با یک هرم خالی هرم اول را برمی‌گرداند در غیر این صورت یک هرم جدید برگردانده می‌شود که ریشهٔ کوچکتر ریشهٔ آن بوده و هرم با ریشهٔ بزرگتر به فرزندان آن اضافه می‌شود:

function merge(heap1, heap2)

 if heap1 == Empty
 return heap2
 elsif heap2 == Empty
 return heap1
 elsif heap1.elem < heap2.elem
 return Heap(heap1.elem, heap2 :: heap1.subheaps)
 else
 return Heap(heap2.elem, heap1 :: heap2.subheaps)

درج[ویرایش]

ساده‌ترین راه برای درج یک آیتم در یک هرم این است که هرم اصلی را با یک هرم که فقط عنصر درج شده در آن قرار دارد ادغام کنیم:

function insert(elem, heap)

 return merge(Heap(elem, []), heap)

حذف[ویرایش]

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

function delete-min(heap)

 if heap == Empty
 error
 else
 return merge-pairs(heap.subheaps)

که این از تابع کمکی merge-pairs استفاده می‌کند:

function merge-pairs(l)

 if length(l) == ۰
 return Empty
 elsif length(l) == ۱
 return l[0]
 else
 return merge(merge(l[0], l[1]), merge-pairs(l[2.. ]))

که این در واقع ادغام دو طرفه چپ به راست و راست به چپ را پیاده‌سازی می‌کند:

merge-pairs([H1, H2, H3, H4, H5, H6, H7])

=> merge(merge(H1, H2), merge-pairs([H3, H4, H5, H6, H7]))
 # merge H1 and H2 to H12, then the rest of the list
=> merge(H12, merge(merge(H3, H4), merge-pairs([H5, H6, H7])))
 # merge H3 and H4 to H34, then the rest of the list
=> merge(H12, merge(H34, merge(merge(H5, H6), merge-pairs([H7]))))
 # merge H5 and H6 to H56, then the rest of the list
=> merge(H12, merge(H34, merge(H56, H7)))
 # switch direction, merge the last two resulting heaps, giving H567
=> merge(H12, merge(H34, H567))
 # merge the last two resulting heaps, giving H34567
=> merge(H12, H34567)
 # finally, merge the first merged pair with the result of merging the rest
=> H1234567

منابع[ویرایش]

  1. ۱٫۰ ۱٫۱ ۱٫۲ Fredman, Michael L.; Sedgewick, Robert; Sleator, Daniel D.; Tarjan, Robert E. (1986). "The pairing heap: a new form of self-adjusting heap" (PDF). Algorithmica. 1 (1): 111–129. doi:10.1007/BF01840439.
  2. Mehlhorn, Kurt; Sanders, Peter (2008). Algorithms and Data Structures: The Basic Toolbox (PDF). Springer. p. 231.
  3. ۳٫۰ ۳٫۱ Iacono, John (2000). Improved upper bounds for pairing heaps (PDF). Proc. 7th Scandinavian Workshop on Algorithm Theory. Lecture Notes in Computer Science. Vol. 1851. Springer-Verlag. pp. 63–77. arXiv:1110.4428. doi:10.1007/3-540-44985-X_5. ISBN 978-3-540-67690-4. Archived from the original (PDF) on 24 December 2012. Retrieved 6 May 2016.
  4. ۴٫۰ ۴٫۱ Stasko, John T.; Vitter, Jeffrey S. (1987), "Pairing heaps: experiments and analysis", Communications of the ACM, 30 (3): 234–249, doi:10.1145/214748.214759, CiteSeerX: 10.1.1.106.2988
  5. Fredman, Michael L. (1999). "On the efficiency of pairing heaps and related data structures" (PDF). Journal of the ACM. 46 (4): 473–501. doi:10.1145/320211.320214. Archived from the original (PDF) on 21 July 2011. Retrieved 6 May 2016.
  6. ۶٫۰ ۶٫۱ Pettie, Seth (2005), "Towards a final analysis of pairing heaps" (PDF), Proc. 46th Annual IEEE Symposium on Foundations of Computer Science, pp. 174–183, doi:10.1109/SFCS.2005.75, ISBN 0-7695-2468-0
  7. Elmasry, Amr (2009), "Pairing heaps with decrease cost" (PDF), Proc. 20th Annual ACM-SIAM Symposium on Discrete Algorithms, pp. 471–476, doi:10.1137/1.9781611973068.52, archived from the original (PDF) on 18 اكتبر 2012, retrieved 6 May 2016 {{citation}}: Check date values in: |archive-date= (help)
  8. ۸٫۰ ۸٫۱ Larkin, Daniel H.; Sen, Siddhartha; Tarjan, Robert E. (2014), "A back-to-basics empirical study of priority queues", Proceedings of the 16th Workshop on Algorithm Engineering and Experiments, pp. 61–72, arXiv:1403.0252, doi:10.1137/1.9781611973198.7
  9. Moret, Bernard M. E.; Shapiro, Henry D. (1991), "An empirical analysis of algorithms for constructing a minimum spanning tree", Proc. 2nd Workshop on Algorithms and Data Structures, Lecture Notes in Computer Science, vol. 519, Springer-Verlag, pp. 400–411, doi:10.1007/BFb0028279, ISBN 3-540-54343-0, CiteSeerX: 10.1.1.53.5960

پیوند به بیرون[ویرایش]