使用 Python、Tkinter 和 Graphviz 可视化二叉搜索树

在本文中,我希望演示如何在二叉搜索树中插入和遍历节点。我还想解释一下以图形方式可视化二叉搜索树中节点关系的过程。

图像 1

介绍

本文演示了如何使用 Python 和 Tkinter 将节点添加到二叉搜索树、遍历节点以及在 GUI 环境中可视化树。

背景

数据结构是一种非线性数据结构,因为它不按顺序存储数据。它被称为分层结构,因为数据在中以多个级别排列。在中,最顶层的节点称为节点。每个节点都包含一些数据,这些数据可以是其他节点(称为子节点)的任何类型和地址。

以下是一些与树木相关的术语:

  1. :它是树中最顶层的节点。它没有任何父节点。
  2. 节点:是某个节点的后代。
  3. 节点:是具有子节点(子节点)的节点。
  4. 兄弟姐妹:他们是共同(同一)父母的孩子。
  5. 叶节点:它是一个没有子节点的节点。它是最底部的节点。它也称为外部节点。
  6. 内部节点:它是具有至少一个子节点的节点。
  7. 祖先节点:它是从根节点到当前节点路径上的前置节点。
  8. 后代节点:它是任何节点的直接继承者。

二叉搜索树是一种特殊类型的,其中每个节点树最多可以有两个子节点,其限制是左侧子树中每个节点的值必须小于节点的值,右侧子树中每个节点的值必须大于节点的值。

二叉搜索树中的节点包含三个字段:

  1. 数据字段
  2. 左子地址字段
  3. 右子地址字段

节点遍历

二叉搜索树中的节点可以通过三种方式遍历:

(所有遍历函数均为递归函数)

  1. inorder - 左-根-右
    • 遍历左侧子树。
    • 访问根。
    • 遍历右侧子树。
  2. preorder - 根-左-右
    • 访问根。
    • 遍历左侧子树。
    • 遍历右侧子树。
  3. postorder - 左-右-根
    • 遍历左侧子树。
    • 遍历右侧子树。
    • 访问根。

使用代码

该应用程序是一个基于 Tkinter 的 GUI 应用程序,用户可以在其中输入数据并实时可视化。

节点类可用于描述二叉搜索树的节点,如下所示:

<span style="color:#111111"><span style="background-color:#ffffff"><span style="color:#000000"><span style="background-color:#fbedbb"><span style="color:#0000ff">class</span> Node:
    <span style="color:#0000ff">def</span> __init__(self,data):
         self.data = data
         self.left = <span style="color:#0000ff">None</span>
         self.right = <span style="color:#0000ff">None</span></span></span></span></span>

插入和遍历操作在类中定义如下:Tree

<span style="color:#111111"><span style="background-color:#ffffff"><span style="color:#000000"><span style="background-color:#fbedbb"><span style="color:#0000ff">class</span> Tree:
    <span style="color:#0000ff">def</span> __init__(self):
        self.root = <span style="color:#0000ff">None</span>
        self.nodes = <span style="color:#800080">"</span><span style="color:#800080">"</span>
    <span style="color:#0000ff">def</span> addnode(self,data):
        currnode = Node(data)
        <span style="color:#0000ff">if</span> self.root <span style="color:#0000ff">is</span> None:
            self.root = currnode
        <span style="color:#0000ff">else:</span>
            parent = <span style="color:#0000ff">None</span>
            ptr = self.root
            <span style="color:#0000ff">while</span> ptr <span style="color:#0000ff">is</span> <span style="color:#0000ff">not</span> None:
                parent = ptr
                <span style="color:#0000ff">if</span> <span style="color:#339999">int</span>(currnode.data) < <span style="color:#339999">int</span>(ptr.data):
                    ptr = ptr.left
                <span style="color:#0000ff">else:</span>
                    ptr = ptr.right
            <span style="color:#0000ff">if</span> <span style="color:#339999">int</span>(currnode.data) < <span style="color:#339999">int</span>(parent.data):
                parent.left = currnode
            <span style="color:#0000ff">else:</span>
                parent.right = currnode
    <span style="color:#0000ff">def</span> inorder(self,root):
            <span style="color:#0000ff">if</span> root != None:
                self.inorder(root.left)
                self.nodes += root.data + <span style="color:#800080">"</span><span style="color:#800080"> "</span>
                self.inorder(root.right)
    <span style="color:#0000ff">def</span> preorder(self,root):
            <span style="color:#0000ff">if</span> root != None:
                self.nodes += root.data + <span style="color:#800080">"</span><span style="color:#800080"> "</span>
                self.preorder(root.left)
                self.preorder(root.right)
    <span style="color:#0000ff">def</span> postorder(self,root):
            <span style="color:#0000ff">if</span> root != None:
                self.postorder(root.left)
                self.postorder(root.right)
                self.nodes += root.data + <span style="color:#800080">"</span><span style="color:#800080"> "</span>
    <span style="color:#0000ff">def</span> visualizetree(self,root):
        dot = graphviz.Digraph()
        dot.node(<span style="color:#339999">str</span>(root.data))
        self.addedge(root,dot)
        dot.render(<span style="color:#800080">"</span><span style="color:#800080">tree"</span>,format=<span style="color:#800080">"</span><span style="color:#800080">png"</span>)
    <span style="color:#0000ff">def</span> addedge(self,node,dot):
        <span style="color:#0000ff">if</span> node.left:
            dot.node(<span style="color:#339999">str</span>(node.left.data))
            dot.edge(<span style="color:#339999">str</span>(node.data),<span style="color:#339999">str</span>(node.left.data))
            self.addedge(node.left,dot)
        <span style="color:#0000ff">if</span> node.right:
            dot.node(<span style="color:#339999">str</span>(node.right.data))
            dot.edge(<span style="color:#339999">str</span>(node.data),<span style="color:#339999">str</span>(node.right.data))
            self.addedge(node.right,dot)</span></span></span></span>

在上面的代码中,该函数根据其值将节点添加到树的适当位置。、 和递归函数执行各自的遍历,并将遍历的节点值存储在 nodes 变量中。该方法使用 执行可视化。该函数以递归方式将边从节点绘制到其子节点。该树将呈现并存储为当前文件夹中的“”图像。addnode()inorder()preorder()postorder()visualizetree()graphvizaddedge()png

以下代码为应用程序提供 GUI 环境:

<span style="color:#111111"><span style="background-color:#ffffff"><span style="color:#000000"><span style="background-color:#fbedbb"><span style="color:#0000ff">def</span> add():
    tree.addnode(txtvalue.get())
    tree.visualizetree(tree.root)
    img = ImageTk.PhotoImage(Image.<span style="color:#339999">open</span>(<span style="color:#800080">"</span><span style="color:#800080">tree.png"</span>))
    lblimage.configure(image=img)
    lblimage.image = img

<span style="color:#0000ff">def</span> inorder():
    tree.inorder(tree.root)
    messagebox.showinfo(<span style="color:#800080">"</span><span style="color:#800080">Inorder"</span>,tree.nodes)
    tree.nodes = <span style="color:#800080">"</span><span style="color:#800080">"</span>

<span style="color:#0000ff">def</span> preorder():
    tree.preorder(tree.root)
    messagebox.showinfo(<span style="color:#800080">"</span><span style="color:#800080">Preorder"</span>,tree.nodes)
    tree.nodes = <span style="color:#800080">"</span><span style="color:#800080">"</span>

<span style="color:#0000ff">def</span> postorder():
    tree.postorder(tree.root)
    messagebox.showinfo(<span style="color:#800080">"</span><span style="color:#800080">Postorder"</span>,tree.nodes)
    tree.nodes = <span style="color:#800080">"</span><span style="color:#800080">"</span>

<span style="color:#0000ff">def</span> showimage(event):
    os.system(<span style="color:#800080">"</span><span style="color:#800080">tree.png"</span>) <span style="color:#0000ff">if</span> os.path.exists(<span style="color:#800080">"</span><span style="color:#800080">tree.png"</span>) <span style="color:#0000ff">else</span> <span style="color:#0000ff">None</span>

<span style="color:#0000ff">if</span> __name__ == <span style="color:#800080">"</span><span style="color:#800080">__main__"</span>:

    tree = Tree()
    root = Tk()
    root.title(<span style="color:#800080">"</span><span style="color:#800080">Binary Search Tree"</span>)
    root.geometry(<span style="color:#800080">"</span><span style="color:#800080">500x300"</span>)

    lblvalue = Label(root,text=<span style="color:#800080">"</span><span style="color:#800080">Enter data: "</span>)
    lblvalue.place(x=50,y=50,width=100)

    txtvalue = Entry(root)
    txtvalue.place(x=150,y=50,width=100)

    btnadd = Button(root,text=<span style="color:#800080">"</span><span style="color:#800080">Add"</span>,command=add)
    btnadd.place(x=50,y=100,width=100)

    btninorder = Button(root,text=<span style="color:#800080">"</span><span style="color:#800080">Inorder"</span>,command=inorder)
    btninorder.place(x=150,y=100,width=100)

    btnpreorder = Button(root,text=<span style="color:#800080">"</span><span style="color:#800080">Preorder"</span>,command=preorder)
    btnpreorder.place(x=50,y=150,width=100)

    btnpostorder = Button(root,text=<span style="color:#800080">"</span><span style="color:#800080">Postorder"</span>,command=postorder)
    btnpostorder.place(x=150,y=150,width=100)

    lblimage = Label(root)
    lblimage.bind(<span style="color:#800080">"</span><span style="color:#800080"><Button-1>"</span>,showimage)
    lblimage.place(x=300,y=50,width=150,height=150)
    root.mainloop()

    <span style="color:#0000ff">if</span> os.path.exists(<span style="color:#800080">"</span><span style="color:#800080">tree.png"</span>):
       os.remove(<span style="color:#800080">"</span><span style="color:#800080">tree.png"</span>)
       os.remove(<span style="color:#800080">"</span><span style="color:#800080">tree"</span>)</span></span></span></span>

上面的代码可用于添加节点并以交互方式可视化。渲染的树将显示在标签中,单击该标签将在默认图像查看器应用程序中打开树图像。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值