Python将列表打印为完全二叉树的图形


这里是一段防爬虫文本,请读者忽略。
本文原创首发于CSDN,作者IDYS
博客首页:https://blog.csdn.net/weixin_41633902/
本文链接:https://blog.csdn.net/weixin_41633902/article/details/107984910
未经授权,禁止转载!恶意转载,后果自负!尊重原创,远离剽窃!


写在开头的话

  • 请记住:实践是掌握知识的最快方法
  • 如果你只是怀着看看的态度去快速浏览文章,而不去认认真真的把文章里面讲的任何一个知识点去实践一遍,那么你永远也掌握不了它
  • 生命不息,折腾不止!

列表打印为一个完全二叉树

题目

  • 随便给出一个列表。将其打印为完全二叉树的形式

  • 如:将这样的一个列表打印为这个样子

在这里插入图片描述

  • 完全二叉树的特点:
    • 叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部
    • 满二叉树肯定是完全二叉树,而完全二叉树不一定是满二叉树

解析

方法一

  1. 思路
  • 因为每一个孩子结点都以父节点为中心对称,我们首先应该得出这个列表组成树时其层数
  • 针对这个层数,我们再决定分配给这个树的最大宽度
  • 第1层直接,直接将第一个数居中在这个最大宽度
  • 第2层。将最大宽度分为两份。然后依次将第2层的两个数居中放在这两份中间
  • 第3层,将最大宽度分为四份,然后依次将第3层的四个数居中放在这四份中间
  • 以此类推,直到结束为止
  • 注意:最小份数的长度应该能够容纳列表中宽度最长的数字。我将最小长度设置为最长数字的宽度的两倍

  • 代码演示
def fn(n):
    def _fn(n, k):
        if n == 0:
            return k-1
        else:
            return _fn(n//2, k+1)
    return _fn(n, 0)


def num_judge(n):
    k = 1
    judge = False
    while True:
        if k < n:
            k *= 2
        elif k == n:
            judge = True
            break
        else:
            break
    return judge


def print_tree(origin = [30, 20, 80]):
    length = len(origin)
    num_max_length = len(str(max(origin)))  # 确定最大数字的占用长度
    layer = fn(length+1)
    for i in range(length):
        print("{:^{}}".format(origin[i], 2*num_max_length*(2**(layer-fn(i+1)))), end="")   # 2*num_max_length 即是最下面一层,最小的分割长度
        if num_judge(i+2):  # 判断是否到达一层的末尾,如果到达一层中最后一个数,那么就换行
            print()
    print()  # 列表全部打印完时,换行


if __name__ == "__main__":
    print_tree()
    print("******************************")
    print_tree([12, 45, 67, 89, 12, 34, 67, 90, 67, 38, 29, 48, 68, 90, 12, 17, 19, 20])
    print("******************************")
    print_tree([12, 307, 17, 19, 20, 1, 901, 231, 45, 9, 9010])
    print("******************************")
  • 运行结果
       30       
   20      80   

******************************
                               12                               
               45                              67               
       89              12              34              67       
   90      67      38      29      48      68      90      12   
 17  19  20 
******************************
                               12                               
              307                              17               
       19              20              1              901       
  231      45      9      9010  
******************************


方法二

  1. 思路

在这里插入图片描述

  • 把二叉树上的所有点投影到一条线上来。将二叉树看成满二叉树,那么第一行的第一个数,前面应该有,7个元素。第二行第一个数,前面应该有3个元素,第三行第一数前面应该有一个元素,第四行第一数,前面有0个元素
  • 现在看每一行数字间隔的投影宽度,第一行只有一个数,所以为0。第二行为7,第三行为3,第四行为1

  • 代码演示1
import math


def print_tree(array, unit_with=2):
    unit_with = len(str(max(array)))
    length = len(array)
    depth = math.ceil(math.log2(length+1))
    index = 0
    width = 2 ** depth - 1
    for i in range(depth):
        for j in range(2**i):
            print("{:^{}}".format(array[index], width*unit_with), end=" "*unit_with) #因为首次长度为 15, 第二次长度 变为 两个 7, 与十五比少了1, 第三次长度变为 两个3,与15比少了3,所以每次end,都要带上一个长度间隔
            index +=1
            if index > length -1:
                break
        width //= 2
        print()


if __name__ == "__main__":
    print_tree([x+100 for x in range(13)])
  • 运行结果
                     100                        
         101                     102            
   103         104         105         106      
107   108   109   110   111   112      

  • 代码演示2
import math

def print_tree(array):
    index = 0
    depth =  math.ceil(math.log2(len(array)+1))
    sep = len(str(max(array))) * " "
    for i in range(depth):
        offset = 2 ** i
        print((2**(depth-i -1)-1) * sep, end="")
        line = array[index:index+offset]
        for j, x in enumerate(line):
            print("{}".format(x, len(str(max(array)))), end="")
            interval = 0 if i == 0 else 2 ** (depth - i) - 1
            if j < len(line) -1:
                print(sep * interval, end="")
        index += offset
        print()


if __name__ == "__main__":
    print_tree([x + 100 for x in range(13)])
    print("*******************************")
    print_tree([x+10 for x in range(15)])
    
  • 运行结果
                     100
         101                     102
   103         104         105         106
107   108   109   110   111   112
*******************************
              10
      11              12
  13      14      15      16
17  18  19  20  21  22  23  24


写在最后的话:

  • 无论每个知识点的难易程度如何,我都会尽力将它描绘得足够细致
  • 欢迎关注我的CSDN博客,IDYS’BLOG
  • 持续更新内容
    linux基础 | 数据通信(路由交换,WLAN) | Python基础 | 云计算
  • 如果你有什么疑问,或者是难题。欢迎评论或者私信我。你若留言,我必回复!
  • 虽然我现在还很渺小,但我会做好每一篇内容。谢谢关注!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值