تمارين OCaml

ضع في اعتبارك شجرة ثنائية متوازنة الارتفاع بارتفاع h. ما هو الحد الأقصى لعدد العقد التي يمكن أن تحتوي عليها؟ بوضوح ، max_nodes = ساعتان - 1.

# دع max_nodes h = 1 lsl h - 1 ؛؛ val max_nodes: int -> int = الحد الأدنى من العقد

ومع ذلك ، ما هو الحد الأدنى لعدد min_nodes؟ هذا السؤال أكثر صعوبة. حاول العثور على جملة متكررة وتحويلها إلى دالة min_nodes المحددة على النحو التالي: min_nodes h تُرجع الحد الأدنى لعدد العقد في شجرة ثنائية متوازنة الارتفاع بارتفاع h.

أدنى ارتفاع

من ناحية أخرى ، يمكن للمرء أن يسأل: ما هو الحد الأدنى (على التوالي. الحد الأقصى) للارتفاعات H لشجرة ثنائية متوازنة الارتفاع مع العقد N؟ min_height (على التوالي max_height n) يعرض الحد الأدنى (الحد الأقصى للتكرار) للارتفاع لشجرة ثنائية متوازنة الارتفاع مع عقد. بناء الأشجار

يمكننا الآن مواجهة المشكلة الرئيسية: إنشاء جميع الأشجار الثنائية المتوازنة من حيث الارتفاع مع عدد معين من العقد. تُرجع hbal_tree_nodes n قائمة بجميع الأشجار الثنائية المتوازنة مع العقد.

اكتشف عدد الأشجار المتوازنة ارتفاعًا لـ n = 15.

# List.length (hbal_tree_nodes 15) ؛؛ -: عدد صحيح = 1553 الحد الأدنى من العقد

الحل التالي يأتي مباشرة من ترجمة السؤال. # دعونا rec min_nodes h = إذا ح = عدد صحيح

ومع ذلك ، فهو ليس الأكثر فاعلية. استخدم القيمتين الأخيرتين كحالة لتجنب تكرار العودية المزدوجة. # دعونا rec min_nodes_loop m0 m1 h = إذا ح عدد صحيح -> عدد صحيح = val min_nodes: int -> int =

ليس من الصعب إظهار أن min_nodes h = Fh + 2‌ - 1 ، حيث (Fn) هي تسلسل فيبوناتشي. أدنى ارتفاع

من خلال عكس الصيغة max_nodes = 2h - 1 ، نجد مباشرة أن Hₘᵢₙ (n) = ⌈log₂ (n + 1) ⌉ والتي يمكن تنفيذها بسهولة: # let min_height n = int_of_float (ceil (log (float (n + 1)) /. log 2.)) ؛؛ val min_height: int -> int =

لنقدم دليلًا على أن صيغة Hₘᵢₙ صالحة. أولاً ، إذا كانت h = min_height n ، فهناك شجرة متوازنة الارتفاع بارتفاع h مع عدد n من العقد. وبالتالي 2ʰ - 1 = max_nodes h ≥ n أي h ≥ log₂ (n + 1). لتأسيس المساواة لـ Hₘᵢₙ (n) ، يجب على المرء أن يُظهر أنه ، لكل n ، توجد شجرة متوازنة الارتفاع بارتفاع Hₘᵢₙ (n). هذا بسبب العلاقة Hₘᵢₙ (n) = 1 + Hₘᵢₙ (n / 2) حيث n / 2 هي تقسيم عدد صحيح. بالنسبة لـ n الفردية ، يمكن إثبات ذلك بسهولة - حتى نتمكن من بناء شجرة بها عقدة علوية وشجرتان فرعيتان مع n / 2 من العقد Hₘᵢₙ (n) - 1. بالنسبة إلى n زوجي ، يعمل نفس الدليل إذا لاحظنا ذلك أولاً ، في هذه الحالة ، ⌈log₂ (n + 2) ⌉ = ⌈log₂ (n + 1) ⌉ - باستخدام log₂ (n + 1) ≤ h ∈ ℕ ⇔ 2ʰ ≥ n + 1 وحقيقة أن 2ʰ متساوية لهذا. هذا يجعل من الممكن الحصول على شجرة فرعية مع عدد n / 2 من العقد. بالنسبة للشجرة الفرعية الأخرى ذات العقد n / 2-1 ، من الضروري إثبات أن Hₘᵢₙ (n / 2-1) ≥ Hₘᵢₙ (n) - 2 وهو أمر سهل لأنه ، إذا كانت h = Hₘᵢₙ (n / 2-1) ، ثم h + 2 ≥ log₂ (2n) ≥ log₂ (n + 1)

ومع ذلك ، فإن الوظيفة المذكورة أعلاه ليست هي الأفضل. هذا لأنه لا يمكن تمثيل جميع الأعداد الصحيحة ذات 64 بت كرقم فاصلة عائمة. فيما يلي عملية تستخدم عمليات الأعداد الصحيحة فقط: # دعونا rec ceil_log2_loop log plus1 n = إذا كان n = 1 ثم إذا كان plus1 ثم سجل + 1 آخر سجل else ceil_log2_loop (log + 1) (plus1 || n land 1 0) (n / 2) دع ceil_log2 n = ceil_log2_loop 0 false n ؛؛ val ceil_log2_loop: int -> bool -> int -> int = val ceil_log2: int -> int =

ومع ذلك ، لا تزال هذه الخوارزمية ليست الأسرع. انظر على سبيل المثال Hacker's Delight ، القسم 5-3 (و11-4).

باتباع نفس الفكرة المذكورة أعلاه ، إذا كانت h = max_height n ، فإننا نستنتج بسهولة أن min_nodes h n # دعونا rec max_height_search h n = إذا كانت min_nodes h int -> int = val max_height: int -> int =

بالطبع ، نظرًا لأنه يتم حساب min_nodes بشكل متكرر ، فلا داعي لإعادة حساب كل شيء للانتقال من min_nodes h إلى min_nodes (h + 1):

# دع الأمر rec max_height_search h m_h m_h1 n = إذا m_h عدد صحيح ...

تمارين OCaml

ضع في اعتبارك شجرة ثنائية متوازنة الارتفاع بارتفاع h. ما هو الحد الأقصى لعدد العقد التي يمكن أن تحتوي عليها؟ بوضوح ، max_nodes = ساعتان - 1.

# دع max_nodes h = 1 lsl h - 1 ؛؛ val max_nodes: int -> int = الحد الأدنى من العقد

ومع ذلك ، ما هو الحد الأدنى لعدد min_nodes؟ هذا السؤال أكثر صعوبة. حاول العثور على جملة متكررة وتحويلها إلى دالة min_nodes المحددة على النحو التالي: min_nodes h تُرجع الحد الأدنى لعدد العقد في شجرة ثنائية متوازنة الارتفاع بارتفاع h.

أدنى ارتفاع

من ناحية أخرى ، يمكن للمرء أن يسأل: ما هو الحد الأدنى (على التوالي. الحد الأقصى) للارتفاعات H لشجرة ثنائية متوازنة الارتفاع مع العقد N؟ min_height (على التوالي max_height n) يعرض الحد الأدنى (الحد الأقصى للتكرار) للارتفاع لشجرة ثنائية متوازنة الارتفاع مع عقد. بناء الأشجار

يمكننا الآن مواجهة المشكلة الرئيسية: إنشاء جميع الأشجار الثنائية المتوازنة من حيث الارتفاع مع عدد معين من العقد. تُرجع hbal_tree_nodes n قائمة بجميع الأشجار الثنائية المتوازنة مع العقد.

اكتشف عدد الأشجار المتوازنة ارتفاعًا لـ n = 15.

# List.length (hbal_tree_nodes 15) ؛؛ -: عدد صحيح = 1553 الحد الأدنى من العقد

الحل التالي يأتي مباشرة من ترجمة السؤال. # دعونا rec min_nodes h = إذا ح = عدد صحيح

ومع ذلك ، فهو ليس الأكثر فاعلية. استخدم القيمتين الأخيرتين كحالة لتجنب تكرار العودية المزدوجة. # دعونا rec min_nodes_loop m0 m1 h = إذا ح عدد صحيح -> عدد صحيح = val min_nodes: int -> int =

ليس من الصعب إظهار أن min_nodes h = Fh + 2‌ - 1 ، حيث (Fn) هي تسلسل فيبوناتشي. أدنى ارتفاع

من خلال عكس الصيغة max_nodes = 2h - 1 ، نجد مباشرة أن Hₘᵢₙ (n) = ⌈log₂ (n + 1) ⌉ والتي يمكن تنفيذها بسهولة: # let min_height n = int_of_float (ceil (log (float (n + 1)) /. log 2.)) ؛؛ val min_height: int -> int =

لنقدم دليلًا على أن صيغة Hₘᵢₙ صالحة. أولاً ، إذا كانت h = min_height n ، فهناك شجرة متوازنة الارتفاع بارتفاع h مع عدد n من العقد. وبالتالي 2ʰ - 1 = max_nodes h ≥ n أي h ≥ log₂ (n + 1). لتأسيس المساواة لـ Hₘᵢₙ (n) ، يجب على المرء أن يُظهر أنه ، لكل n ، توجد شجرة متوازنة الارتفاع بارتفاع Hₘᵢₙ (n). هذا بسبب العلاقة Hₘᵢₙ (n) = 1 + Hₘᵢₙ (n / 2) حيث n / 2 هي تقسيم عدد صحيح. بالنسبة لـ n الفردية ، يمكن إثبات ذلك بسهولة - حتى نتمكن من بناء شجرة بها عقدة علوية وشجرتان فرعيتان مع n / 2 من العقد Hₘᵢₙ (n) - 1. بالنسبة إلى n زوجي ، يعمل نفس الدليل إذا لاحظنا ذلك أولاً ، في هذه الحالة ، ⌈log₂ (n + 2) ⌉ = ⌈log₂ (n + 1) ⌉ - باستخدام log₂ (n + 1) ≤ h ∈ ℕ ⇔ 2ʰ ≥ n + 1 وحقيقة أن 2ʰ متساوية لهذا. هذا يجعل من الممكن الحصول على شجرة فرعية مع عدد n / 2 من العقد. بالنسبة للشجرة الفرعية الأخرى ذات العقد n / 2-1 ، من الضروري إثبات أن Hₘᵢₙ (n / 2-1) ≥ Hₘᵢₙ (n) - 2 وهو أمر سهل لأنه ، إذا كانت h = Hₘᵢₙ (n / 2-1) ، ثم h + 2 ≥ log₂ (2n) ≥ log₂ (n + 1)

ومع ذلك ، فإن الوظيفة المذكورة أعلاه ليست هي الأفضل. هذا لأنه لا يمكن تمثيل جميع الأعداد الصحيحة ذات 64 بت كرقم فاصلة عائمة. فيما يلي عملية تستخدم عمليات الأعداد الصحيحة فقط: # دعونا rec ceil_log2_loop log plus1 n = إذا كان n = 1 ثم إذا كان plus1 ثم سجل + 1 آخر سجل else ceil_log2_loop (log + 1) (plus1 || n land 1 0) (n / 2) دع ceil_log2 n = ceil_log2_loop 0 false n ؛؛ val ceil_log2_loop: int -> bool -> int -> int = val ceil_log2: int -> int =

ومع ذلك ، لا تزال هذه الخوارزمية ليست الأسرع. انظر على سبيل المثال Hacker's Delight ، القسم 5-3 (و11-4).

باتباع نفس الفكرة المذكورة أعلاه ، إذا كانت h = max_height n ، فإننا نستنتج بسهولة أن min_nodes h n # دعونا rec max_height_search h n = إذا كانت min_nodes h int -> int = val max_height: int -> int =

بالطبع ، نظرًا لأنه يتم حساب min_nodes بشكل متكرر ، فلا داعي لإعادة حساب كل شيء للانتقال من min_nodes h إلى min_nodes (h + 1):

# دع الأمر rec max_height_search h m_h m_h1 n = إذا m_h عدد صحيح ...

What's Your Reaction?

like

dislike

love

funny

angry

sad

wow