二叉树需要实现的功能及思路

  1. 找到最小值

    没什么好说的就是二叉树最左下的顶点

  2. 找到最大值

    没什么好说的就是二叉树最右下的顶点

  3. 插入

    分情况,如果二叉树为空那么直接直接设置成根节点就好了。否则就逐层向下,比当前小的往左边方向,否则往右边方向

  4. 删除

    为了要实现删除的功能,我们先定义一个方法,它返回的是被删除的节点和它的父节点,返回形式为tuple,即(parent,node)

    这个就比较复杂了,分三种情况:

    1. 被删除的节点没有子节点

      再分为两种:

      • 有父节点:看是父节点的左节点还是右节点,将对应的赋为None
      • 无父节点:很明显这就是根节点本身了,直接赋为None就好了
    2. 被删除的节点有1个子节点

      将返回的父节点直接链接到被删除节点的子节点,用一张图说明就是:

      具体去代码中感受就好

    3. 被删除的节点有2个子节点

      这种情况要么找左子树的最右边节点或者右子树的最左节点(由二叉树的定义可知)

  5. 查找某个节点

    就是从根节点开始,根据大小关系逐层往下找就好了

  6. 先序/中序/后序遍历

    代码不同的一行在于输出当前节点的语句的位置,具体看代码

  7. 宽度优先遍历

    也就是逐层遍历,通过队列实现,将根节点入队,然后扫描左右节点,分别入队,这样出队的时候一定是左边的节点先出来,子节点在入队。入队-出队持续到队列为空为止。

代码

from collections import deque

class Node:
def __init__(self, data=None):
self.data = data
self.left_child = None
self.right_child = None class Tree:
def __init__(self):
self.root_node = None def find_min(self):
current = self.root_node
while current.left_child:
current = current.left_child
return current def find_max(self):
current = self.root_node
while current.right_child:
current = current.right_child return current def insert(self, data):
node = Node(data)
if self.root_node is None:
self.root_node = node
else:
current = self.root_node
parent = None
while True:
parent = current
if node.data < current.data:
current = current.left_child
if current is None:
parent.left_child = node
return
else:
current = current.right_child
if current is None:
parent.right_child = node
return def get_node_with_parent(self, data):
current = self.root_node
parent = None
if current is None:
return (parent,None)
while True:
if current.data == data:
return (parent,current)
elif current.data > data:
parent = current
current = current.left_child
else:
parent = current
current = current.right_child return (parent,current) def remove(self, data):
parent, node = self.get_node_with_parent(data) if parent is None and node is None:
return False children_count = 0 if node.left_child and node.right_child:
children_count = 2
elif (node.left_child is None) and (node.right_child is None):
children_count = 0
else:
children_count = 1 if children_count == 0:
if parent:
if parent.right_child is node:
parent.right_child = None
else:
parent.left_child = None
else: #只有根节点
self.root_node = None
elif children_count == 1:
'''要删除的节点有一个子节点'''
next_node = None
if node.left_child:
next_node = node.left_child
else:
next_node = node.right_child #确定子节点是在左边还是在右边 if parent:
if parent.left_child is node:
parent.left_child = next_node
else:
parent.right_child = next_node
else:
self.root_node = next_node
else:
'''要么找左子树的最右边节点或者右子树的最左节点'''
parent_of_leftmost_node = node
leftmost_node = node.right_child #右边的顶点才会比要被删除的节点大
while leftmost_node.left_child:
parent_of_leftmost_node = leftmost_node
leftmost_node = leftmost_node.left_child #找到最左下的顶点,保持平衡性,这个是右子树的最小节点 node.data = leftmost_node.data
if parent_of_leftmost_node.left_child == leftmost_node:
parent_of_leftmost_node.left_child = leftmost_node.right_child
else:
parent_of_leftmost_node.right_child = leftmost_node.right_child def search(self, data):
current = self.root_node
while True:
if current is None:
return None
elif current.data == data:
return data
elif current.data > data:
current = current.left_child
else:
current = current.right_child def inorder(self, root_node):
current = root_node
if current is None:
return
self.inorder(current.left_child)
print(current.data)
self.inorder(current.right_child) def preorder(self, root_node):
current = root_node
if current is None:
return
print(current.data)
self.preorder(current.left_child)
self.preorder(current.right_child) def postorder(self, root_node):
current = root_node
if current is None:
return
self.postorder(current.left_child)
self.postorder(current.right_child)
print(current.data) def breadth_first_traversal(self):
list_of_nodes = []
traversal_queue = deque([self.root_node])
while len(traversal_queue) > 0:
node = traversal_queue.popleft()
list_of_nodes.append(node.data) if node.left_child:
traversal_queue.append(node.left_child) if node.right_child:
traversal_queue.append(node.right_child)
return list_of_nodes

Python的二叉树实现的更多相关文章

  1. 【DataStructure In Python】Python模拟二叉树

    使用Python模拟二叉树的基本操作,感觉写起来很别扭.最近做编译的优化,觉得拓扑排序这种东西比较强多.近期刷ACM,发现STL不会用实在太伤了.决定花点儿时间学习一下STL.Boost其实也很强大. ...

  2. Python实现二叉树的四种遍历

    对于一个没学过数据结构这门课程的编程菜鸟来说,自己能理解数据结构中的相关概念,但是自己动手通过Python,C++来实现它们却总感觉有些吃力.递归,指针,类这些知识点感觉自己应用的不够灵活,这是自己以 ...

  3. Python实现二叉树的左中右序遍历

    #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/3/18 12:31 # @Author : baoshan # @Site ...

  4. python实现二叉树

    初学python,需要实现一个决策树,首先实践一下利用python实现一个二叉树数据结构.建树的时候做了处理,保证建立的二叉树是平衡二叉树. # -*- coding: utf-8 -*- from ...

  5. Python实现二叉树及其4种遍历

    Python & BinaryTree 1. BinaryTree (二叉树) 二叉树是有限个元素的集合,该集合或者为空.或者有一个称为根节点(root)的元素及两个互不相交的.分别被称为左子 ...

  6. Python实现二叉树的前序、中序、后序、层次遍历

      有关树的理论部分描述:<数据结构与算法>-4-树与二叉树:   下面代码均基于python实现,包含: 二叉树的前序.中序.后序遍历的递归算法和非递归算法: 层次遍历: 由前序序列.中 ...

  7. python实现二叉树遍历算法

    说起二叉树的遍历,大学里讲的是递归算法,大多数人首先想到也是递归算法.但作为一个有理想有追求的程序员.也应该学学非递归算法实现二叉树遍历.二叉树的非递归算法需要用到辅助栈,算法着实巧妙,令人脑洞大开. ...

  8. Python数据结构——二叉树的实现

    1. 二叉树 二叉树(binary tree)中的每个节点都不能有多于两个的儿子. 1.1 二叉树列表实现 如上图的二叉树可用列表表示: tree=['A', #root ['B', #左子树 ['D ...

  9. Python实现二叉树的前序遍历、中序遍历

    计算根节点到叶子节点的所组成的数字(1247, 125, 1367)以及叶子节点到根节点组成的数字(7421, 521, 8631),其二叉树树型结构如下 计算从根节点到叶子节点组成的数字,本质上来说 ...

  10. python实现二叉树和它的七种遍历

    介绍: 树是数据结构中很重要的一种,基本的用途是用来提高查找效率,对于要反复查找的情况效果更佳,如二叉排序树.FP-树. 另外能够用来提高编码效率,如哈弗曼树. 代码: 用python实现树的构造和几 ...

随机推荐

  1. linux配置iptables(3)

    简单通用 web 服务器iptables 配置 *filter :INPUT DROP [0:0]:FORWARD DROP [0:0]:OUTPUT ACCEPT [0:0] #超出 链规则 的数据 ...

  2. [转]zookeeper-端口说明

    一.zookeeper有三个端口(可以修改) 1.2181 2.3888 3.2888 二.3个端口的作用 1.2181:对cline端提供服务 2.3888:选举leader使用 3.2888:集群 ...

  3. Scala学习(四)---映射和元组

    映射和元组 摘要: 一个经典的程序员名言是:"如果只能有一种数据结构,那就用哈希表吧".哈希表或者更笼统地说映射,是最灵活多变的数据结构之一.映射是键/值对偶的集合.Scala有一个通用的叫法:元组, ...

  4. LVM : 简介

    在对磁盘分区的大小进行规划时,往往不能确定这个分区要使用的空间的大小.而使用 fdisk.gdisk 等工具对磁盘分区后,每个分区的大小就固定了.如果分区设置的过大,就白白浪费了磁盘空间:如果分区设置 ...

  5. OpenStack构架知识梳理

    OpenStack既是一个社区,也是一个项目和一个开源软件,提供开放源码软件,建立公共和私有云,它提供了一个部署云的操作平台或工具集,其宗旨在于:帮助组织运行为虚拟计算或存储服务的云,为公有云.私有云 ...

  6. 1013 C. Photo of The Sky

    传送门 [http://codeforces.com/contest/1013/problem/C] 题意 输入一个n代表n颗星星,输入2n个数,其中任意两个数代表一颗行星的坐标,问你把n个星星围起来 ...

  7. wordcount程序中的应用与拓展

    设计思路: 关键是思路,首先知道 单词, 行,字符, 他们有什么特点: 1.单词,标准的是遇到空格后,单词数,自动加一. 2.行是以\n结束的, 也就是说, 遇到\n行数加一,当然也视你的操作系统而言 ...

  8. 个人作业——final

    一 . 对M1M2的一个总结 我特别感谢我们组的PM.以前我觉得女生学计算机这个专业,跟男生比差太远了.总觉得我们女生就是上上课写写作业考考试还行,但是一到开发什么项目啊,实战之类的,总觉得自己的能力 ...

  9. QT 窗口置顶功能

    Qt中,保持窗口置顶的设置为: Qt::WindowFlags m_flags = windowFlags(); setWindowFlags(m_flags | Qt::WindowStaysOnT ...

  10. 在web.xml中配置监听器来控制ioc容器生命周期

    5.整合关键-在web.xml中配置监听器来控制ioc容器生命周期 原因: 1.配置的组件太多,需保障单实例 2.项目停止后,ioc容器也需要关掉,降低对内存资源的占用. 项目启动创建容器,项目停止销 ...