算法笔记·6-树
  • 非线性数据结构;
  • 包括根,枝,叶三部分;也可以说由节点(node)和边(edge)组成;
  • 层次化,各个子节点之间独立每个叶节点具有唯一性;
  • 树中所有节点的最大曾经称为树的高度根节点所在的层级为0

树的实现

嵌套列表实现

子树结构与树相同,是一种递归数据结构。

atree=['a',['left',[],[]],['right',[],[]]]

插入方法的实现(以插入左树为例)。

  def insertLeft(root,newBranch):
    t = root.pop(1)  
    #提取左子节点
    if len(t) > 1:
    #如果左子节点存在,则需要先插入新节点再将原来的节点作为其左子节点   
      root.insert(1,[newBranch,t,[]])
    else:
      root.insert(1,[newBranch,[],[]])

树的链表实现

  • 节点链表法:链表中每个节点保存节点的数据项以及左右子树的链接。

插入方法:加入中间变量,将插入节点与原先节点相连接。

应用

  • 树表示表达式

树的遍历(Tree Traversals)

遍历(Traversals):对数据集中所有数据进行访问。对于线性数据结构,按顺序访问即可。

树的遍历包括:前序遍历(根--左--右),中序遍历(左--根--右)和后序遍历(左--右--根)。

优先队列与二叉堆

优先队列:先入先出,内部次序由优先级确定

二叉堆(Binary Heap)实现优先队列

入队和出队的复杂度均为O(log n)。如果使操作始终保持再对数量级上,二叉树必须保持平衡。可以通过完全二叉树近似实现平衡。

完全二叉树:叶节点最多只出现在最底层和次底层;最底层的叶节点集中在左边(最多由有一个节点例外)。

性质:若节点下表为p,则其左子节点下标为2p,右子节点下标为2p+1。所以可以使用非嵌套列表表示完全二叉树。

堆次序(Heap Order):父节点的key小于其子节点。

二叉堆

二叉堆的性质:

  • 完全二叉树:可以用非嵌套数组表示
  • 堆:任意路径为有序数列。

二叉堆操作的实现

列表保存堆数据,列表中下标为0项不用。

class BinHeap:
  def __init__():
    self.heapList = [0]
    self.currentsize = 0
  • insert(key)

    为了保证二叉堆中堆的性质,需要将插入key上浮至正确的位置。插入时先添加到末尾并改变二叉树currentsize的值,之后进行上浮操作。

    #上浮(i 二叉树节点数)
    def perUp(self,i):
    while i // 2 > 0:  #到根节点j结束循环
      #与父节点比较
      if self.heapList[i] < self.heapList[i//2]:   
        #与父节点交换位置
        i = i // 2
  • delMin()

    删除堆中最小的key,即根节点。最后一个节点代替根节点并下沉。

    # 下沉
    def percDown(self,i):
    # 是否存在左节点
    while (i * 2) <= self.currentSize:
      mc = self.minChild(i) # 返回子节点的较小值的位置
      if self.heapList[i] > self.heapList[mc]:
        # 交换下沉
        ......
      i = mc
  • buildHeap(lst)

    利用下沉法从无序表生成堆。从最后一个节点的父节点处开始下沉(len(list)//2处),并不断迭代;为保证完全二叉树的性质,需要在无序表前端插入一个空值。

二叉查找树(Binary Search Tree)

二叉查找树比父节点大key的在右子树,比父节点小的key在左子树。

二叉搜索树的实现

二叉查找树的性能受到插入顺序的影响。

平衡二叉树(AVL Tree)

在实现过程中,与 BST差别在于需要对每个节点加入平衡因子。平衡因子是左右子树的高度差,大于0为左重,小于0为右重。平衡树的每个节点的平衡因子在-1到1之间。AVL树的搜索时间复杂度为O(log n)。

在插入方法中需要接入更新平衡因子的函数,自下而上更新每个节点的平衡因子。

重新平衡

将不平衡的子树进行旋转实现,左重右旋,右重左旋,左旋挂右,右旋挂左。在旋转过程中,只有新根节点和就根节点的平衡因子发生了变化。

def rotateLeft(self,rotRoot):
  newRoot = rotRoot.rightChild
  rotRoot.rightChild = newRoot.leftChild
  # 新根左子节点,挂到旧根的右子节点,父与子相连。左旋挂右。
  if newRoot.leftChild != None:
    newRoot.leftChild.parent = rotRoot 
    # 子与父相连
    ... ...
    # 整理节点之间关系
    ... ...
    rotRoot.blanceFactor = rotRoot.balanceFactor + 1 - min(newRoot.balanceFactor,0)
    newRoot.blanceFactor = newRoot.balanceFactor + 1 + max(newRoot.balanceFactor,0)

在左旋要检查右子节点的因子,若右子节点左重则应先右旋在左旋。同样,右旋也需要进行类似操作。

引用

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇