【问题标题】:questions about binary search tree关于二叉搜索树的问题
【发布时间】:2013-08-04 18:12:12
【问题描述】:

表明每个 n 节点二叉搜索树的可能性不均等(假设项目以随机顺序插入),并且平衡树比直线树更有可能。

如何证明数学?

【问题讨论】:

  • 看看维基百科中的归纳证明。
  • Сan you show more details,如何在这里应用归纳法?

标签: binary-search-tree


【解决方案1】:

可能的树配置数量:参见With ' N ' no of nodes, how many different Binary and Binary Search Trees possible?

获得具有 n 个节点的单行、最不平衡、最深的树的方法数:2^(n-1) 解释: 获取第一个节点的 2 种方法(最大或最小) X 2 种获取第二个节点的方法(剩余 n-1 个节点中最大或最小的) ... X 2 种方式来获取第 (n-1) 个节点 X 1 方式获取最后一个节点

以平衡的方式将 n 项添加到二叉树的方法数: 令 g(n,m) 表示通过一次从一个列表或另一个列表中选择元素直到两个列表都为空来合并两个有序列表的方法数。 g(n,m) = g(n-1,m) + g(n,m-1) 这恰好对应于帕斯卡三角形中定义的数字。这将使 n+m 选择 n 或 n+m 选择 m = (n+m)! /n! (n+m-n)! = (n+m)!/(n!m!) 例子: 合并两个包含 2 个元素的有序列表的方法数 = 4!/(2!2!) = 24 / 4 = 6 假设这两个列表如下:

1 A
2 B

六种合并组合是:

1 1 1 A A A
2 A A B 1 1
A 2 B 1 B 2
B B 2 2 2 B

现在,让 f(n) 表示可以将 n 个已排序元素添加到空二叉树以使二叉树平衡的组合数。实现这一点的唯一方法是先添加

  • 如果 n 为奇数,则为中间元素。那将是元素上限(n / 2)。每边都有 n/2-1 个元素。
  • 元素 n/2 或元素 n/2+1(如果 n 为偶数)。一侧有 n/2-1 个元素,另一侧有 n/2 个元素,反之亦然。

一旦中间元素被选中,左边的所有元素总是落在左子树上,而右边的所有元素总是落在右子树上。假设右边的元素以左子树平衡的方式排序,而右边的元素也以右子树平衡的方式排序,以任何方式合并两个列表总是会导致两者子树是平衡的。这意味着对于每个分别落在左右子树上的 n 和 m 个元素的列表,使得两个子树都是平衡的,有 (n+m)!/(n!m!) 将它们合并以实现结果一样。

这将给我们 (n+m)!/(n!m!) x f(n) x f(m)

我们现在可以将其表述如下: 基本情况:

f(1) = 1
f(2) = 2

一般情况:

f(n) = (n-1)!/[((n-1)/2)!]^2 x [f((n-1)/2)]^2  | n odd
f(n) = (n-1)!/((n/2-1)! x (n/2)!) x 2 x f(n/2-1) x f(n/2) | n even

Rest 将其转换为 n 的非递归公式。也许从 n = 2^m - 1 的最简单情况开始会更容易(即删除一个节点并除以 2 将始终给出一个整数,并会产生一个完全平衡的树)。

注意:我在这里发布了一个相关的数学问题:https://math.stackexchange.com/questions/460767/recurrent-relation-for-number-of-ways-to-get-a-balanced-n-binary-tree

以下是一个 C# 控制台应用程序,它列出了可以将节点添加到二叉树以使其平衡的所有序列(运行它here):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AllBalancedTrees
{
    class Program
    {
        static void Main(string[] args)
        {
            char[] nodes = { 'A', 'B', 'C', 'D', 'E' };

            AllBalancedTrees<char> AllBalancedTrees = new AllBalancedTrees<char>(); 

            foreach (char[] a in AllBalancedTrees.allBalancedTreeCombinations(nodes))
            {
                foreach (char c in a)
                {
                    Console.Write(c + " ");
                }
                Console.WriteLine();
            }

            Console.ReadKey();
        }
    }

    class AllBalancedTrees<T>
    {
        public IEnumerable<T[]> allBalancedTreeCombinations(T[] nodes)
        {
            T[] result;
            if (nodes.Length == 1)
            {
                yield return nodes;
            }
            else if (nodes.Length == 2)
            {
                yield return nodes;
                T[] nodes2 = new T[2];
                nodes2[0] = nodes[1];
                nodes2[1] = nodes[0];
                yield return nodes2;
            }
            else if (nodes.Length % 2 == 1)
            {
                int mid = (nodes.Length - 1) / 2;
                T[] left = new T[mid];
                T[] right = new T[mid];
                Array.Copy(nodes, 0, left, 0, mid);
                Array.Copy(nodes, mid + 1, right, 0, mid);
                foreach (T[] l in allBalancedTreeCombinations(left))
                {
                    foreach (T[] r in allBalancedTreeCombinations(right))
                    {
                        result = new T[nodes.Length];
                        result[0] = nodes[mid];
                        foreach (T[] a in allMergeCombinations(l, r))
                        {
                            Array.Copy(a, 0, result, 1, a.Length);
                            yield return result;
                        }
                    }
                }
            }
            else
            {
                int mid = (nodes.Length) / 2;
                T[] left = new T[mid];
                T[] right = new T[mid - 1];
                Array.Copy(nodes, 0, left, 0, mid);
                Array.Copy(nodes, mid + 1, right, 0, mid - 1);
                foreach (T[] l in allBalancedTreeCombinations(left))
                {
                    foreach (T[] r in allBalancedTreeCombinations(right))
                    {
                        result = new T[nodes.Length];
                        result[0] = nodes[mid];
                        foreach (T[] a in allMergeCombinations(l, r))
                        {
                            Array.Copy(a, 0, result, 1, a.Length);
                            yield return result;
                        }
                    }
                }

                mid = nodes.Length / 2 - 1;
                left = new T[mid];
                right = new T[mid + 1];
                Array.Copy(nodes, 0, left, 0, mid);
                Array.Copy(nodes, mid + 1, right, 0, mid+1);
                foreach (T[] l in allBalancedTreeCombinations(left))
                {
                    foreach (T[] r in allBalancedTreeCombinations(right))
                    {
                        result = new T[nodes.Length];
                        result[0] = nodes[mid];
                        foreach (T[] a in allMergeCombinations(l, r))
                        {
                            Array.Copy(a, 0, result, 1, a.Length);
                            yield return result;
                        }
                    }
                }


            }
        }

        public IEnumerable<T[]> allMergeCombinations(T[] firstArray, T[] secondArray)
        {
            if (firstArray.Length == 0)
            {
                yield return secondArray;
            }
            else if (secondArray.Length == 0)
            {
                yield return firstArray;
            }
            else
            {
                T[] result;

                T[] firstMinusOne;
                firstMinusOne = new T[firstArray.Length - 1];
                Array.Copy(firstArray, 1, firstMinusOne, 0, firstMinusOne.Length);
                foreach (T[] a in allMergeCombinations(firstMinusOne, secondArray))
                {
                    result = new T[firstArray.Length + secondArray.Length];
                    result[0] = firstArray[0];
                    Array.Copy(a, 0, result, 1, a.Length);
                    yield return result;
                }

                T[] secondMinusOne;
                secondMinusOne = new T[secondArray.Length - 1];
                Array.Copy(secondArray, 1, secondMinusOne, 0, secondMinusOne.Length);
                foreach (T[] a in allMergeCombinations(firstArray, secondMinusOne))
                {
                    result = new T[firstArray.Length + secondArray.Length];
                    result[0] = secondArray[0];
                    Array.Copy(a, 0, result, 1, a.Length);
                    yield return result;
                }

            }
        }
    }
}

【讨论】:

  • 感谢您的帮助...我在本文中发现只有一个 n 大小的总计数二叉搜索树的公式。我对 n 大小的总计数平衡二叉搜索树的公式很感兴趣。直线树很简单,因为所有这些树都是 2 个变体。
  • 我一直在思考这个问题,我想我得到了一个递归公式,但没有公式。我需要一些时间来解释这个想法,而不仅仅是提供一个递归算法。
  • 直线二叉树确实可以有两种方式。然而,其他形式的完全不平衡的树可以有更多的组合,如前所述。你只关心直线树和平衡树吗?
  • 是的,我应该证明只有平衡树比直线树更有可能
  • 概率位置 n-node 二叉搜索树等于 1/n : 1-node 应该是 root => P(1)=1 ; 2-node less or more 1-node => P(2)=1/2; 3 节点,因为 3 个子节点是空闲的(空)P(3)=1/3。可能是,这个证明对于第一部分是否更好(表明每个 n 节点二叉搜索树的可能性不相等)?跨度>
【解决方案2】:

每个 n 节点二叉搜索树的可能性不均等,因为如果以随机顺序插入项目,则输入不会严格按升序或降序排列的可能性要大得多。只要项目不是升序或降序,直线树是不可能的。 例如,在键为 1、2、3 和 4 的四个记录的树中,有 4 个!或 24 种方式将这些项目作为输入进行排序。这些方法中只有两种可以生成直线树(4、3、2、1 和 1、2、3、4)。在这种情况下,直线树的概率约为 8.3%,而(有些)平衡树的概率为 91.6%。显然,概率与获得结果的直线树的机会相反。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-18
    • 2016-02-03
    • 1970-01-01
    相关资源
    最近更新 更多