Python数据结构应用——树

1. 什么是树

在计算机科学中,树是一种数据结构,由节点构成,节点之间存在一定的关系,形成了一个类似于树形结构的图形。树是一种非线性的数据结构,其中每个节点都可以有多个子节点,但每个节点只有一个父节点。

树形结构中,包括以下几个术语:

根节点:整个树最顶部的节点,没有父节点

叶节点:没有子节点的节点,也被称为终端节点。

父节点:自己有子节点的节点。

子节点:直接依附于父节点的节点。

深度:从根节点到该节点所经过的边的数量,根节点深度为0

高度:从该节点到叶节点所经过的边的数量。

树可以用来表示各种问题,并且可以通过各种算法进行优化。

2. 二叉树

2.1 什么是二叉树

二叉树是一种特殊的树结构,每个节点都最多只有两个子节点,左子节点和右子节点。因为它们的特点,在实际中也比较常见,例如文件系统、家谱图等都可以使用二叉树来表示。

二叉树的实现可以采用链表或数组,这里可以看到使用链表来实现二叉树的代码:

class Node:

def __init__(self, val=None):

self.left = None

self.right = None

self.val = val

class BinaryTree:

def __init__(self):

self.root = None

def add(self, val):

if not self.root:

self.root = Node(val)

else:

self._add(val, self.root)

def _add(self, val, node):

if val < node.val:

if node.left:

self._add(val, node.left)

else:

node.left = Node(val)

else:

if node.right:

self._add(val, node.right)

else:

node.right = Node(val)

以上代码使用了递归来实现添加节点的操作。

2.2 二叉树的遍历

在使用二叉树时,我们需要对其进行遍历。遍历就是按照一定顺序访问每个节点,遍历可以分为三种类型:

先序遍历:先访问父节点,再访问左子节点,最后访问右子节点。

中序遍历:先访问左子节点,再访问父节点,最后访问右子节点。

后序遍历: 先访问左子节点,再访问右子节点,最后访问父节点。

遍历二叉树的代码可以使用递归,这里给出一段中序遍历的代码:

def inorderTraversal(self, root):

"""

:type root: TreeNode

:rtype: List[int]

"""

res = []

if not root:

return res

res.extend(self.inorderTraversal(root.left))

res.append(root.val)

res.extend(self.inorderTraversal(root.right))

return res

以上代码使用了递归,实现了中序遍历的操作。

3. 平衡树

3.1 什么是平衡树

平衡树是一种特殊的树结构,其可以保证每个节点的左右子树高度差在一定范围内,这样可以避免二叉树退化成链表,从而提高了查询效率。

常见的平衡树包括:

AVL树

红黑树

B树

这里以AVL树为例进行介绍。

3.2 AVL树原理解析

AVL树是由两位前苏联的计算机科学家 Adelson-Velsky 和 Landis 提出的,它是一种自平衡的二叉搜索树,在AVL树中,任何节点的两个子树的高度差小于等于1,如果有高度差大于1的情况出现,就需要通过旋转操作来使树重新平衡。

旋转有两种操作:左旋转和右旋转,左旋转是将节点的右子树移到它的左边,右旋转是将节点的左子树移到它的右边。

AVL树的实现可以采用链表或数组,以下为采用链表的实现:

class TreeNode:

def __init__(self, val):

self.val = val

self.left = None

self.right = None

self.height = 1

class AVLTree:

def getHeight(self, root):

if not root:

return 0

return root.height

def getBalance(self, root):

if not root:

return 0

return self.getHeight(root.left) - self.getHeight(root.right)

def leftRotate(self, z):

y = z.right

T2 = y.left

y.left = z

z.right = T2

z.height = 1 + max(self.getHeight(z.left), self.getHeight(z.right))

y.height = 1 + max(self.getHeight(y.left), self.getHeight(y.right))

return y

def rightRotate(self, z):

y = z.left

T3 = y.right

y.right = z

z.left = T3

z.height = 1 + max(self.getHeight(z.left), self.getHeight(z.right))

y.height = 1 + max(self.getHeight(y.left), self.getHeight(y.right))

return y

def insert(self, root, val):

if not root:

return TreeNode(val)

if val < root.val:

root.left = self.insert(root.left, val)

else:

root.right = self.insert(root.right, val)

root.height = 1 + max(self.getHeight(root.left), self.getHeight(root.right))

balance = self.getBalance(root)

if balance > 1 and val < root.left.val:

return self.rightRotate(root)

if balance < -1 and val > root.right.val:

return self.leftRotate(root)

if balance > 1 and val > root.left.val:

root.left = self.leftRotate(root.left)

return self.rightRotate(root)

if balance < -1 and val < root.right.val:

root.right = self.rightRotate(root.right)

return self.leftRotate(root)

return root

以上代码实现了AVL树的插入操作,并在插入时自动进行了平衡操作。

4. 总结

树是一种非常重要的数据结构,其可以有效地解决各种问题。而在实际中,二叉树和平衡树更是应用广泛,本文进行了详细介绍并提供了相应代码。

需要注意的是,平衡树相对于二叉树来说,代码实现更加复杂,需要考虑节点的高度差等问题,因此在实际中应使用时慎重,但在某些情况下,其可以有效地提高查询效率和数据分布均匀性。

后端开发标签