如何修复Python中二叉搜索树(BST)显示右侧不平衡问题
二叉搜索树可视化不平衡问题修复
问题场景
自定义的二叉搜索树可视化方法_displayRec在测试时出现右侧显示不平衡的问题,测试代码插入了键值对(4,"four")、(5,"five")、(1,"one")、(2,"two")、(3,"three"),得到的可视化结果右侧结构偏移,难以阅读。
原可视化代码:
def display(self): print("Displaying tree:") print("----------------") lines, *_ = self._displayRec(self._root) for line in lines: print(line) print("----------------") def _displayRec(self, node): if node is None: line = "Empty" width = len(line) height = 1 middle = width // 2 return [line], width, height, middle else: key = str(node.getKey()) value = str(node.getValue()) label = f"{key} ({value})" left_lines, left_width, left_height, left_middle = self._displayRec(node.getLeft()) right_lines, right_width, right_height, right_middle = self._displayRec(node.getRight()) node_label = label node_label_width = len(node_label) first_line = (left_middle + 1) * " " + (left_width // 2) * "_" + node_label + (right_width // 2) * "_" second_line = left_middle * " " + "/" + (left_middle + node_label_width + right_middle) * " " + "\\" + (right_width - right_middle - 1) * " " if left_height < right_height: left_lines += [left_width * " "] * (right_height - left_height) elif right_height < left_height: right_lines += [right_width * " "] * (left_height - right_height) zipped_lines = zip(left_lines, right_lines) lines = [first_line, second_line] + [a + " " * (node_label_width + 1) + b for a, b in zipped_lines] width = left_width + node_label_width + right_width + 1 height = max(left_height, right_height) + 2 middle = width // 2 return lines, width, height, middle
错误的可视化结果:
Inserted key 4 with value four Inserted key 5 with value five Inserted key 1 with value one Inserted key 2 with value two Inserted key 3 with value three Displaying tree: ---------------- _______________________4 (four)_________ / \ __1 (one)________________ __5 (five)__ / \ / \ Empty __2 (two)__________ Empty Empty / \ Empty __3 (three)__ / \ Empty Empty ----------------
修复后的代码
def display(self): print("Displaying tree:") print("----------------") lines, *_ = self._displayRec(self._root) for line in lines: print(line) print("----------------") def _displayRec(self, node): if node is None: line = "Empty" width = len(line) height = 1 middle = width // 2 return [line], width, height, middle else: key = str(node.getKey()) value = str(node.getValue()) label = f"{key} ({value})" left_lines, left_width, left_height, left_middle = self._displayRec(node.getLeft()) right_lines, right_width, right_height, right_middle = self._displayRec(node.getRight()) node_label = label node_label_width = len(node_label) # 修正第一行:左侧下划线匹配左子树右侧剩余空间,右侧下划线匹配右子树左侧空间 first_line = (left_middle + 1) * " " + (left_width - left_middle - 1) * "_" + node_label + right_middle * "_" # 修正第二行:斜线紧贴标签两侧,右侧斜线后填充右子树剩余空格 second_line = left_middle * " " + "/" + (node_label_width - 2) * " " + "\\" + (right_width - right_middle - 1) * " " # 对齐左右子树高度 if left_height < right_height: left_lines += [left_width * " "] * (right_height - left_height) elif right_height < left_height: right_lines += [right_width * " "] * (left_height - right_height) # 用单个空格分隔左右子树,避免过度偏移 zipped_lines = zip(left_lines, right_lines) lines = [first_line, second_line] + [a + " " + b for a, b in zipped_lines] # 修正总宽度和中间位置计算 width = left_width + node_label_width + right_width + 1 height = max(left_height, right_height) + 2 middle = left_width + node_label_width // 2 return lines, width, height, middle
关键修改点
- 第一行下划线对齐:替换原固定比例的下划线计算,改为基于子树中间位置的剩余空间生成下划线,确保节点标签与左右子树的连接对称。
- 斜线位置修正:调整斜线之间的空格数,让斜线紧贴标签左右边缘,避免多余空格导致整体偏移。
- 子树拼接间距:将原
node_label_width+1的分隔空格改为单个空格,解决右侧子树过度偏移的问题。 - 中间位置校准:修正节点中间位置的计算逻辑,确保当前节点的中心与标签中心对齐,为上层节点的连线提供准确参考。
修复后的可视化结果
Displaying tree: ---------------- ________4 (four)________ / \ __1 (one)__ __5 (five)__ / \ / \ Empty __2 (two)__ Empty Empty / \ Empty __3 (three)__ / \ Empty Empty ----------------
内容的提问来源于stack exchange,提问作者Tinigam
相关产品推荐
相关产品推荐

