目录
介绍
本文演示了如何使用Python和Tkinter将节点添加到二叉搜索树、遍历节点以及在GUI环境中可视化树。
背景
树数据结构是一种非线性数据结构,因为它不按顺序存储数据。它被称为分层结构,因为数据在树中以多个级别排列。在树中,最顶层的节点称为根节点。每个节点都包含一些数据,这些数据可以是其他节点(称为子节点)的任何类型和地址。
以下是一些与树木相关的术语:
- 根节点:它是树中最顶层的节点。它没有任何父节点。
- 子节点:是某个节点的后代。
- 父节点:是具有子节点(子节点)的节点。
- 兄弟节点:他们是共同(同一)父母的孩子。
- 叶节点:它是一个没有子节点的节点。它是最底部的节点。它也称为外部节点。
- 内部节点:它是具有至少一个子节点的节点。
- 祖先节点:它是从根节点到当前节点路径上的前置节点。
- 后代节点:它是任何节点的直接继承者。
二叉搜索树是一种特殊类型的树,其中每个节点树最多可以有两个子节点,其限制是左侧子树中每个节点的值必须小于根节点的值,右侧子树中每个节点的值必须大于根节点的值。
二叉搜索树中的节点包含三个字段:
- 数据字段
- 左子地址字段
- 右子地址字段
节点遍历
二叉搜索树中的节点可以通过三种方式遍历:
(所有遍历函数均为递归函数)
- Inorder——左-根-右
- 遍历左侧子树。
- 访问根节点。
- 遍历右侧子树。
- Preorder——根-左-右
- 访问根节点。
- 遍历左侧子树。
- 遍历右侧子树。
- Postorder——左-右-根
- 遍历左侧子树。
- 遍历右侧子树。
- 访问根节点。
使用代码
该应用程序是一个基于Tkinter的GUI应用程序,用户可以在其中输入数据并实时可视化。
节点类可用于描述二叉搜索树的节点,如下所示:
class Node:
def __init__(self,data):
self.data = data
self.left = None
self.right = None
插入和遍历操作在Tree类中定义如下:
class Tree:
def __init__(self):
self.root = None
self.nodes = ""
def addnode(self,data):
currnode = Node(data)
if self.root is None:
self.root = currnode
else:
parent = None
ptr = self.root
while ptr is not None:
parent = ptr
if int(currnode.data) < int(ptr.data):
ptr = ptr.left
else:
ptr = ptr.right
if int(currnode.data) < int(parent.data):
parent.left = currnode
else:
parent.right = currnode
def inorder(self,root):
if root != None:
self.inorder(root.left)
self.nodes += root.data + " "
self.inorder(root.right)
def preorder(self,root):
if root != None:
self.nodes += root.data + " "
self.preorder(root.left)
self.preorder(root.right)
def postorder(self,root):
if root != None:
self.postorder(root.left)
self.postorder(root.right)
self.nodes += root.data + " "
def visualizetree(self,root):
dot = graphviz.Digraph()
dot.node(str(root.data))
self.addedge(root,dot)
dot.render("tree",format="png")
def addedge(self,node,dot):
if node.left:
dot.node(str(node.left.data))
dot.edge(str(node.data),str(node.left.data))
self.addedge(node.left,dot)
if node.right:
dot.node(str(node.right.data))
dot.edge(str(node.data),str(node.right.data))
self.addedge(node.right,dot)
在上面的代码中,该addnode()函数根据其值将节点添加到树的适当位置。inorder()、preorder()和postorder()递归函数执行各自的遍历,并将遍历的节点值存储在nodes变量中。该visualizetree()方法使用graphviz执行可视化。该addedge()函数以递归方式将边从节点绘制到其子节点。该树将呈现并存储为当前文件夹中的“png”图像。
以下代码为应用程序提供GUI环境:
def add():
tree.addnode(txtvalue.get())
tree.visualizetree(tree.root)
img = ImageTk.PhotoImage(Image.open("tree.png"))
lblimage.configure(image=img)
lblimage.image = img
def inorder():
tree.inorder(tree.root)
messagebox.showinfo("Inorder",tree.nodes)
tree.nodes = ""
def preorder():
tree.preorder(tree.root)
messagebox.showinfo("Preorder",tree.nodes)
tree.nodes = ""
def postorder():
tree.postorder(tree.root)
messagebox.showinfo("Postorder",tree.nodes)
tree.nodes = ""
def showimage(event):
os.system("tree.png") if os.path.exists("tree.png") else None
if __name__ == "__main__":
tree = Tree()
root = Tk()
root.title("Binary Search Tree")
root.geometry("500x300")
lblvalue = Label(root,text="Enter data: ")
lblvalue.place(x=50,y=50,width=100)
txtvalue = Entry(root)
txtvalue.place(x=150,y=50,width=100)
btnadd = Button(root,text="Add",command=add)
btnadd.place(x=50,y=100,width=100)
btninorder = Button(root,text="Inorder",command=inorder)
btninorder.place(x=150,y=100,width=100)
btnpreorder = Button(root,text="Preorder",command=preorder)
btnpreorder.place(x=50,y=150,width=100)
btnpostorder = Button(root,text="Postorder",command=postorder)
btnpostorder.place(x=150,y=150,width=100)
lblimage = Label(root)
lblimage.bind("<Button-1>",showimage)
lblimage.place(x=300,y=50,width=150,height=150)
root.mainloop()
if os.path.exists("tree.png"):
os.remove("tree.png")
os.remove("tree")
上面的代码可用于添加节点并以交互方式可视化树。渲染的树将显示在标签中,单击该标签将在默认图像查看器应用程序中打开树图像。
兴趣点
我希望读者觉得这篇文章及其概念有用。
https://www.codeproject.com/Articles/5377926/Visualize-Binary-Search-Tree-using-Python-Tkinter