写在前面

今天学习在排序和查找中都很有用的特殊二叉树,平衡二叉树和搜索二叉树。

相关代码实现已上传至Github:data_structure/Tree/

1.二叉搜索树(Binary Search Tree)

二叉搜索时是一种对排序和查找都很有用的特殊二叉树。其或者是一棵空树;或者是具有以下性质的二叉树:

  • 若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值
  • 若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值
  • 左、右子树也分别为二叉排序树

树中结点类实现:

class Node:def __init__(self, data):self.data = dataself.lchild = Noneself.rchild = None

2.二叉搜索树操作

2.1二叉搜索树的动态查找

当二叉查找树不为空时:

(1)首先将给定值与根结点的关键字比较,若相等,则查找成功
(2)若小于根结点的关键字值,递归查左子树
(3)若大于根结点的关键字值,递归查右子树

(4)若子树为空,查找不成功

如下列出了二叉搜索树查找的递归算法

def search(self, node, parent, data):if node is None:return False, node, parentif node.data == data:return True, node, parentif node.data > data:return self.search(node.lchild, node, data)else:return self.search(node.rchild, node, data)

若要查找树中的最大(最小)元素,分析结构可知:

二叉查找树的最左边的结点即为最小值,要查找最小值。仅仅需遍历左子树的结点直到为空为止。同理,最右边的结点结尾最大值。要查找最大值,仅仅需遍历右子树的结点直到为空为止。

最小元素查找python代码实现如下,最大元素同理:

def findmin(root):if root.left:return findmin(root.left)else:return root

2.2 BST的插入

将元素插入BST中关键是找到元素应该插入的位置。位置的确定可以利用与查找函数search类似的方法,如果在树中找到 说明要插入的元素已经存在,可放弃插入操作。如果没有找到,查找终止的位置就是应该插入的位置。

def insert(self, data):flag, n, p = self.search(self.root, self.root, data)if not flag:new_node = Node(data)if data > p.data:p.rchild = new_nodeelse:p.lchild = new_node

2.3 BST的删除

二叉搜索树的删除比较复杂,要删除结点在树中的位置决定了操作所采取的策略。可分为以下三种情况:

1.要删除的是叶结点。可以直接删除,然后修改其父节点的指针,置空即可。

2.如果要删除的节点只有一个孩子结点,删除之前需要改变其父节点的指针,指向要删除结点的孩子结点。

3.如果要删除的节点有左右两棵子树,究竟用那棵子树的根结点来填充删除结点的位置?

第一种方法是取其右子树中的最小元素;另一种方法是取其左子树的最大元素。

代码实现如下:

   def delete(self, root, data):flag, n, p = self.search(root, root, data)if flag is False:print "无该关键字,删除失败"else:if n.lchild is None:if n == p.lchild:p.lchild = n.rchildelse:p.rchild = n.rchilddel nelif n.rchild is None:if n == p.lchild:p.lchild = n.lchildelse:p.rchild = n.lchilddel nelse:  # 左右子树均不为空pre = n.rchildif pre.lchild is None:n.data = pre.datan.rchild = pre.rchilddel preelse:next = pre.lchildwhile next.lchild is not None:pre = nextnext = next.lchildn.data = next.datapre.lchild = next.rchilddel next

3.平衡二叉树(AVL树)

平衡二叉搜索树又称AVL树,它能保证二叉树高度相对平衡,尽量降低二叉树的高度,提高搜索效率。单纯的二叉搜索树在最坏的情况下插入查找删除等操作时间复杂度会是O(N),AVL树就能避免这种情况,使得增删查改的时间复杂度为O(lgN).

AVL树的特点:

  • 任一结点的左右子树均为AVL树
  • 根结点左右子树高度差的绝对值不超过1
  • 每个节点都有一个平衡因子(balance factor--bf),任一节点的平衡因子是-1,0,1。(每个节点的平衡因子等于右子树的高度减去左子树的高度 ) .

3.1 AVL树的调整

当向一颗AVL树中插入新的节点时,该节点的平衡因子很可能不在上述集合范围内,破坏树的平衡。这时候就需要做调整。

1. 单旋调整

  • RR旋转

  • LL旋转

2.双旋调整

  • LR旋转

  • RL旋转

python代码实现如下:

class ALVTreeNode():  def __init__(self, data, height, freq, left, right):  self.data = data;  self.height = height;  self.freq = freq;  self.left = left;  self.right = right;  #小于<法则
def less(x1, x2):  return x1 < x2;  class ALVTree():  def __init__(self):  self.root = None;  self.left = None;  self.right = None;  def setValue(self, root, left, right):  self.root = root;  self.left = left;  self.right = right;  def getValue(self):  return [self.root, self.left, self.right];  def info(self, node):  if (node == None):  info = 'None';  else:  if (node.left == None):  sL = 'None';  else:  sL = node.left.data;  if (node.right == None):  sR = 'None';  else:  sR = node.right.data;  info = [node.data, node.height, node.freq, sL, sR];  print(info);  def genNode(self, data, height, freq, left, right):  return ALVTreeNode(data, height, freq, left, right);  def height(self, node):  if (node == None):  return 0;  else:  lh = self.height(node.left);  rh = self.height(node.right);  node.height = max(lh, rh)+1;  return node.height;  #左左情况下的旋转  #输入的是高度最高的节点,也就是待处理的root  def rotateLL(self, k2):  k1 = k2.left;  k2.left = k1.right;  k1.right = k2;  k2.height = max(self.height(k2.left), self.height(k2.right))+1;  k1.height = max(self.height(k1.left), k2.height)+1;  return k1;  #右右情况下的旋转  #输入的是高度最高的节点,也就是待处理的root  def rotateRR(self, k2):  k1 = k2.right;  k2.right = k1.left;  k1.left = k2;  k2.height = max(self.height(k2.left), self.height(k2.right))+1;  k1.height = max(self.height(k1.right), k2.height)+1;  return k1;  #左右情况的旋转  #输入的是高度最高的节点,也就是待处理的root  def rotateLR(self, k3):  k1 = self.rotateRR(k3.left);  k3.left = k1;  k2 = self.rotateLL(k3);  return k2;  #右左情况的旋转  #输入的是高度最高的节点,也就是待处理的root  def rotateRL(self, k3):  k1 = self.rotateLL(k3.right);  k3.right = k1;  k2 = self.rotateRR(k3);  return k2;  #平衡值  def balanceFlag(self, node):  return self.height(node.left)-self.height(node.right);  #左平衡  def LBalance(self, root):  p = root;  c = p.left;  rc = c.right;  cbf = self.balanceFlag(c);  if (cbf == 1):  root = self.rotateLL(root);  elif (cbf == -1):  root = self.rotateLR(root);  return root;  #右平衡  def RBalance(self, root):  p = root;  c = p.right;  lc = c.left;  cbf = self.balanceFlag(c);  if (cbf == -1):  root = self.rotateRR(root);  elif (cbf == 1):  root = self.rotateRL(root);  return root;  

以上,欢迎交流指正~

2018.04.28

【数据结构与算法基础】二叉搜索树和平衡二叉树相关推荐

  1. 《数据结构与算法之二叉搜索树(Java实现)》

    说在前头:本人为大二在读学生,书写文章的目的是为了对自己掌握的知识和技术进行一定的记录,同时乐于与大家一起分享,因本人资历尚浅,能力有限,文章难免存在一些错漏之处,还请阅读此文章的大牛们见谅与斧正.若 ...

  2. 数据结构与算法之二叉搜索树

    与链表不同,树是一种非线性的数据结构.树中最常用的是二叉树,二叉树限制了子树的数量,也就是每个结点的子树至多2个,并且这两个子树是有顺序的.而二叉搜索树(二叉查找树,二叉排序树)是指根节点的关键字大于 ...

  3. 数据结构与算法-平衡二叉搜索树

    平衡二叉搜索树 1.自平衡的二叉搜索树 2.平衡 (1)空树平衡 (2)非空树平衡 左右子树平衡 左右子树高度差绝对值 <= 1 3.平衡因子 左右子树的高度差的衡量值 -1 0 1 (一)平衡 ...

  4. 【数据结构与算法】二叉搜索树V2.0的Java实现

    更新说明 在二叉搜索树V1.0的编程实现中,我们实现了BST的查找.插入,左右儿子删除的功能,但写的确实很一般,这里就Update一下. 功能介绍 void insert(x) → Insert x ...

  5. 《数据结构与算法之二叉平衡树(AVL)》

    说在前头:本人为大二在读学生,书写文章的目的是为了对自己掌握的知识和技术进行一定的记录,同时乐于与大家一起分享,因本人资历尚浅,发布的文章难免存在一些错漏之处,还请阅读此文章的大牛们见谅与斧正.若在阅 ...

  6. 看动画学算法之:二叉搜索树BST

    文章目录 简介 BST的基本性质 BST的构建 BST的搜索 BST的插入 BST的删除 看动画学算法之:二叉搜索树BST 简介 树是类似于链表的数据结构,和链表的线性结构不同的是,树是具有层次结构的 ...

  7. b+树时间复杂度_满二叉树、完全二叉树、二叉搜索树、平衡二叉树

    "存在即合理"为什么需要每种树,本文不再冗余的总结每种树太多性质,就说重点. 二叉树(Binary Tree)主要包括:满二叉树.完全二叉树.二叉搜索树.平衡二叉树 性质太多,定义 ...

  8. 【数据结构与算法】二叉堆与二叉搜索树的区别

    问题描述 记得刚学习数据结构的时候,就容易混淆二叉堆和二叉搜索树,其实虽说堆也是一种完全二叉树,但二者差别还是挺大的,本文试做分析. 逻辑结构 二叉堆和二叉搜索树都是结点带权重,并在父子结点间满足某种 ...

  9. 基础数据结构——是否同一棵二叉搜索树

    给定一个插入序列就可以唯一确定一棵二叉搜索树.然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到.例如分别按照序列{2, 1, 3}和{2, 3, 1}插入初始为空的二叉搜索树,都得到一样的结果 ...

最新文章

  1. 李开复谏言学生转学Android软件开发
  2. SAP 电商云 Spartacus UI 修改代码后,重新构建基于 SSR 版本的程序报错
  3. .net mvc web api上传图片/文件并重命名
  4. Vue项目中如何设置动态的TDK
  5. HALCON示例程序gray_features.hdev提取灰度图的不同特征(area_center_gray 、elliptic_axis_gray)
  6. PL/SQL NOCOPY限制模式
  7. Spring从入门到入土——Bean的作用域与生命周期
  8. 随笔 - Andriod
  9. java 方法注释_Java注释,java方法注释详解
  10. Git 基础知识 - 查看提交历史记录
  11. 解决Android部分手机图片剪切返回崩溃问题
  12. golang chan
  13. 北大人工智能前沿讲座--第二讲 嵌入式人工智能
  14. 2019 ICPC 南京 F题 Paper Grading
  15. CentOS7安装PHP开发环境1-源码安装Nginx
  16. 嵌入式 linux yum命令详解
  17. 怎么用xshell等ssh连接方式连接自己的本地虚拟机
  18. Matic Network的应用场景大揭秘!
  19. 骚年,来填坑了!!!
  20. Line实现一号一群,关键在于注册

热门文章

  1. SQL HQL JPQL CQL的对比
  2. pandas 操作 excel
  3. [JS]关于表单的自动运算(已解决)
  4. Processing中PDF格式输出
  5. 解决securecrt rz 上传rar,gif文件不正确问题【转】
  6. 常用数据挖掘算法举例(上)
  7. typescript的基本类型
  8. HDU1754 —— I Hate It 线段树 单点修改及区间最大值
  9. 17-8-26-WebApp总结
  10. System.setOut 重定向 memcached 的输出