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

原创 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树,替罪羊树等,待我一一总结起来。

 

版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

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

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

二叉搜索树--进阶篇之平衡二叉搜索树

第四步:旋转   对于一个平衡的节点,由于任意节点最多有两个儿子,因此高度不平衡时,此节点的两颗子树的高度差2.容易看出,这种不平衡出现在下面四种情况:   1、6节点的左子树3节...

精选:深入理解 Docker 内部原理及网络配置

网络绝对是任何系统的核心,对于容器而言也是如此。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker的网络一直以来都比较薄弱,所以我们有必要深入了解Docker的网络知识,以满足更高的网络需求。

二叉平衡搜索树——AVL树

AVL树:保持二叉树的高度平衡,尽量降低二叉树的高度,减少树的平均搜索长度。 AVL树的性质:(1)左子树和右子树的高度之差的绝对值不超过1              &...

平衡二叉搜索树(AVL树)

#pragma once #ifndef _AVLTREE_H_ #define _AVLTREE_H_ #include #include struct Student { long key...

平衡二叉树、完全二叉树、满二叉树、二叉搜索(查找 / 排序)树、平衡二叉搜索树、二叉堆

查了一些博客、百科整理出以下关于树的定义以及易混点: 平衡二叉树:一棵空树或左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是平衡二叉树。(注意:实际应用中很少有不是二叉搜索树的平衡二叉树...

二叉搜索树、二叉平衡树、B-树

之前在Linux内核开发大会上听到B+树,当时不明白B+树是个什么东西,百科了一下更是看的一头雾水,翻起数据结构的书一点点看吧(数据结构要学好啊!!!)。 本文只讲求了解、明白二叉搜索树等之的概念,...

平衡二叉树总结二:avl树

avl树是第一个创造出来的平衡二叉树,之后很多的平衡树都是基于AVL树的基本操作——旋转来实现的。 avl树结构如下: struct avl{ avl* left; avl* right; ...

二叉搜索树与平衡二叉树

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

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

二叉搜索树的特点: 1. 每个节点都有一个作为搜索依据的关键码(key),所有节点的关键码互不相同。 2. 左子树上所有节点的关键码(key)都小于根节点的关键码(key)。 ...

PHP二叉树(一):二叉搜索树

关于二叉搜索树的原理网上的资源就挺多的,而且情况有点小复杂,所以在这里我就不再陈述了,直接上代码吧:#bst.php 文件<?php /** * author:zhongjin * time:20...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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