这里是一段防爬虫文本,请读者忽略。
本文原创首发于CSDN,作者IDYS
博客首页:https://blog.csdn.net/weixin_41633902/
本文链接:https://blog.csdn.net/weixin_41633902/article/details/107984910
未经授权,禁止转载!恶意转载,后果自负!尊重原创,远离剽窃!
写在开头的话
- 请记住:实践是掌握知识的最快方法
- 如果你只是怀着看看的态度去快速浏览文章,而不去认认真真的把文章里面讲的任何一个知识点去实践一遍,那么你永远也掌握不了它
- 生命不息,折腾不止!
列表打印为一个完全二叉树
题目
-
随便给出一个列表。将其打印为完全二叉树的形式
-
如:将这样的一个列表打印为这个样子
- 完全二叉树的特点:
- 叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部
- 满二叉树肯定是完全二叉树,而完全二叉树不一定是满二叉树
解析
方法一
- 思路
- 因为每一个孩子结点都以父节点为中心对称,我们首先应该得出这个列表组成树时其层数
- 针对这个层数,我们再决定分配给这个树的最大宽度
- 第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
******************************
方法二
- 思路
- 把二叉树上的所有点投影到一条线上来。将二叉树看成满二叉树,那么第一行的第一个数,前面应该有,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基础 | 云计算 - 如果你有什么疑问,或者是难题。欢迎评论或者私信我。你若留言,我必回复!
- 虽然我现在还很渺小,但我会做好每一篇内容。谢谢关注!