Complete Binary Search Tree 完全二叉搜索树,python实现

题目:

        输入: 完全二叉树序列(数组表示)

        输出: 完全二叉搜索树序列(数组表示)

关键难点是如何计算左孩子的个数,因为给定一个长度为n的序列,只要知道左孩子个数,就可以根结点的位置,以及右孩子个数等等关键数据。

计算左孩子个数:

        设下图总结点个数为N,得出①N = 2^{H} - 1 + X

        化简后可以求得,②H ≈ log(N+1) 

        已知H后,左孩子数目就可以求出来了 ③Llen = 2^{H-1} - 1 + X

        X的值可以根据公式①求出来,需要注意的是X大于 2^{H-1}时,即X长到右子树那边去了,只能取2^{H-1}(左子树的最大值),即 X = min{N+1-2^{H},  2^{H-1} }

 

下面用两种方式实现,分别是递归法以及堆栈法

  • 递归实现
class CompleteBinarySearchTree():

    def __init__(self, A):
        self.A = self.to_sort(A)
        self.T = [ -1 for i in A]

    def to_sort(self, order:list):
        return sorted(order)

    def getLeftLength(self, n):
        """
        获取左子树长度
        """
        length = 0
        H = math.floor(math.log2(n+1))
        X = n + 1 - pow(2, H)
        maxX = pow(2, H-1)
        X = min(X, maxX)
        length = pow(2, H-1) - 1 + X
        return  length


    def solove(self, Aleft, Aright, Troot):
        """
        Aleft: 序列最左下标
        Aright: 序列最右下标
        Troot: 根结点下标
        """
        # 下标为0开始,所以要+1
        n = Aright - Aleft + 1
        if n == 0:
            return

        L = self.getLeftLength(n)
        leftTroot = Troot * 2 + 1  # 下标从0开始,所以要加+1
        rightTroot = leftTroot + 1
        self.T[Troot] = self.A[Aleft+L]  # 更新根的值, 下标从0开始,所以不用+1
        self.solove(Aleft, Aleft+L-1, leftTroot)  # 左孩子
        self.solove(Aleft+L+1, Aright, rightTroot)

        return self.T
  • 堆栈实现
class CompleteBinarySearchTree():

    def __init__(self, A):
        self.A = self.to_sort(A)
        self.T = [ -1 for i in A]

    def to_sort(self, order:list):
        return sorted(order)

    def getLeftLength(self, n):
        """
        获取左子树长度
        """
        length = 0
        H = math.floor(math.log2(n+1))
        X = n + 1 - pow(2, H)
        maxX = pow(2, H-1)
        X = min(X, maxX)
        length = pow(2, H-1) - 1 + X
        return  length

    def solve2(self):
        if not self.A:
            return []

        if len(self.A) == 1:
            return self.A

        Troot = 0
        Aleft = 0
        Aright = len(self.A) - 1
        n = Aright - Aleft + 1
        s = []
        while n or s:
            while n:
                L = self.getLeftLength(n)
                self.T[Troot] = self.A[Aleft+L]
                s.append((Troot, Aleft, Aright))

                Troot = Troot * 2 + 1
                Aleft = Aleft
                Aright = Aleft + L - 1
                n = Aright - Aleft + 1

            Troot, Aleft, Aright = s.pop()
            # 跳到右子树
            L = self.getLeftLength(Aright - Aleft + 1)
            Troot = Troot * 2 + 2
            Aleft = Aleft + L + 1
            Aright = Aright
            n = Aright - Aleft + 1

        return self.T

  调试用例:

if __name__ == '__main__':
    data = [0,1,2,3,4,5,6,7,8,9]
    c1 = CompleteBinarySearchTree(data)
    t = c1.solove(0, len(data)-1, 0)
    a = 123

    c2 = CompleteBinarySearchTree(data)
    t = c2.solve2()
    a = 123

结果:

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值