平衡二叉树总结一:二叉搜索树

原创 2017年01月03日 10:20:38

  这段时间一直再刷leetcode,现在刷了快一半了吧,感觉没什么状态了,再继续刷可能就不太好了,想想不如回头再补补算法吧。总结了自己在基础算法上的一些短板,准备后面这些时间把它们都补上。好了,上正题。

  平衡二叉树算是应用最广泛的树型结构了吧,至少在内存里面是吧。刚开始学数据结构的时候,树的那一章基本没怎么看,大部分精力都放在了排序和图论里,而且感觉树也挺简单的,现在刷题才慢慢发现这种数据结构的威力,虽然c++的算法库已经有了现成的工具,但是学习好这种数据结构的思想还是很有必要的。

  首先,平衡二叉树是一颗二叉搜索树。其结构满足 root->left->val < root-> val < root->right->val 即根节点左儿子值 < 根节点值 < 右儿子值,并且根节点左右儿子也是二叉搜索树。

第一次作图,凑或着看吧

struct searchTree{
  searchTree* left;
  searchTree* right;
  int val;
}
typedef serachTree* tree;
二叉搜索树的结构,c++版。主要是一个左指针、一个右指针、一个值,不难看出left与right其实是“多余”的,然而没有这俩多余的域二叉树的搜索效率就无从谈起,这就是空间
换时间的典型吧。


  1.二叉搜索树的搜索

  二叉搜索树操作都很简单,搜索时,我们只需比较待搜索值与根节点的大小,比根节点大肯定在左子树,这样我们排除了右子树上节点,这就是二叉搜索树能节省时间的原理,当然比根节点小自然就在右边,相等的话该节点就是我们要找的节点了,代码如下:

/*递归的写法,当然也可以改成循环的,不过递归的逻辑更简明。*/
tree search(tree t,int& val){
  if(t==NULL)return NULL;//为空说明没找到该值。
  if(val>t->val) return search(t->right,val);//大于根节点,往右走。
  else if(val<t->val) return search(t->left,val);//小于往左走。
  return t;//等于,返回该节点。
}
2.插入

/*二叉树的插入,与搜索算法类似。比根节点大就往右插,小往左(等于的情形需要特别
处理,这里先不说,之后的也不考虑等于的情形),直到遇到空节点。*/
tree insert(tree t,int& val){
  if(t==NULL){
    t = new searchTree;
    t->val = val;
    t->left = t->right = NULL;
  }
  if(val>t->val)t->right = insert(t->right,val);
  if(val<t->val)t->left = insert(t->left,val);
  return t;
  //其实返回t不是最优的写法,会多一个赋值过程,不过这样程序看起来更简明。
}
3.删除

  相对而言,删除操作是比较复杂的,需要寻找删除节点的左子树的最大值,或右子树最小值来代替该节点,中间会有一些细节需要注意。

代码稍长,主要是最后寻找替代节点比较麻烦。

/*二叉树的删除或多或少会有些复杂,如果要删除的叶节点,直接删除即可。但是倘若
要删除非叶节点则需要找一个节来替代它。一般是选取左子树的最大值或右子树的最小值。*/
tree del(tree t,int& val){
  if(t==NULL)return NULL;
  if(val>t->val)t->right=del(t->right,val);//递归删除左边
  if(val<t->val)t->left = del(t->left,val);//递归删除右边
  if(val==t->val){//找到节点
    tree v,p=t;
    if(t->left){//如果该节点有左子树,找到左子树最大值。
      for(v=t->left;v->right;p=v,v=v->right){}
      t->val = v->val;//最大值替换删除值。
      if(p==t)p->left = v->left;//如果p节点等于t说明左子树最大值正好为t的左儿子。
      //v自然没有了右儿子,所以将v左儿子赋值给p的右儿子。
      else{p->right = v->left;}//此时p改变过一次,需要p的右儿子是v,所以需要改变一下。
      delete v;//删除v。
    }
    else if(t->right){
      for(v=t->right;v->left;p=v,v=v->left){}
      t->val = v->val;
      if(p==t)p->right = v->right;
      else{p->left = v->right;}
      delete v;
    }
    else{
      delete t;
      return NULL;
    }
    return t;
  }
}

4.总结

  二叉搜索树的搜索与插入效率理想的情形下(左右子树都填满)自然是log2(n)的,但是实际操作中往往达不到这个要求,比如插入的序列是递增的,此时该树退化成

链表,效率变为o(n)。所以为了防止该情况的出现,人们开发出了二叉平衡树,也就是对于根节点而言其左右子树尽量相等的二叉搜索树,平衡条件不同,树的搜索与插入

效率不同。不过一般平衡条件越严格,搜索效率越高,但是插入就变得困难了。

  二叉平衡树有很多,如最早的avl树以及其变种红黑树,无需额外空间的splay树,编程简单的treap树,SBT树,替罪羊树等,待我一一总结起来。

 

二叉搜索树与平衡二叉树

二叉树也是一种树,适用与以上的全部操作,但二叉搜索树能 够实现数据的快速查找 性质: 非空左子树的所有键值小于其根节点的键值 非空右子树的所有键值大于其根节点的键值 左右子树都是二叉搜...
  • Gouhailiang
  • Gouhailiang
  • 2016年11月08日 21:57
  • 1583

看了谷歌的视频演示秒懂平衡二叉搜索树--迷之旋转

最近要找工作复习了一下数据结构,看到平衡二叉树,想起当年刚入学的时候,那节课给我懵比的呀!!!没错,就是那迷之旋转。。。        网上有好多讲解这个过程的博客,但是基本都是和教科书上一个性质,...
  • u011089927
  • u011089927
  • 2016年12月14日 21:55
  • 1257

二叉搜索树(BST)与平衡二叉树(AVL树)专题

1 二叉搜索树(BST)一颗二叉搜索树 (BST)是以一颗二叉树来组织的,可以使用一个链表数据结构来表示,其中,每个结点就是一个对象,包含数据内容key以及left、right和p分别指向结点的左孩子...
  • DaveBobo
  • DaveBobo
  • 2017年08月26日 17:10
  • 613

平衡二叉查找树[AVL]

平衡二叉树的定义 (AVL—— 发明者为Adel'son-Vel'skii 和 Landis)   平衡二叉查找树,又称 AVL树。 它除了具备二叉查找树的基本特征之外,还具有一个非常重要...
  • sagadean
  • sagadean
  • 2011年12月18日 15:03
  • 9155

合并两个二叉搜索树

如何合并两个二叉搜索树? How would you merge two binary search tree's ? 假设二叉搜索树分别有m和n个元素。通过单独遍历每个BST,能得到两个已排序的...
  • f81892461
  • f81892461
  • 2013年05月16日 19:44
  • 1857

算法之 有序链表和平衡二叉树 有序数组与平衡二叉树

题目描述: Given a singly linked list where elements are sorted in ascending order, convert it to a heigh...
  • C12345SDN
  • C12345SDN
  • 2014年08月23日 21:57
  • 1200

二叉搜索树及判断一棵树是否平衡

二叉搜索树的特点: 1. 每个节点都有一个作为搜索依据的关键码(key),所有节点的关键码互不相同。 2. 左子树上所有节点的关键码(key)都小于根节点的关键码(key)。 ...
  • yangrujing
  • yangrujing
  • 2016年07月08日 20:34
  • 993

什么是平衡二叉树和平衡二叉树的高度达到O(log2n)最少需要结点数为n

  • chy89224
  • chy89224
  • 2017年02月13日 20:54
  • 536

平衡二叉树实现的实例

之前谈过平衡二叉树的实现原理,详见http://blog.csdn.net/wxbmelisky/article/details/47755753,下述实例的实现过程依此为据。 现在通过实例来分析平...
  • wxbmelisky
  • wxbmelisky
  • 2015年08月19日 21:11
  • 2743

平衡二叉树删除某个节点的方法

确认违规节点的位置              首先我们找到待删除的节点Z,如果节点Z的两个孩子均为空,那么将其父节点中对应指向Z的指针置为空,然后删除节点Z。如果节点Z仅有一个孩子,那么将Z节点的父...
  • u011583439
  • u011583439
  • 2013年09月18日 10:29
  • 1206
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:平衡二叉树总结一:二叉搜索树
举报原因:
原因补充:

(最多只允许输入30个字)