1. 二叉查找树

  二叉查找树(Binary Search Tree)/  有序二叉树(ordered binary tree)/ 排序二叉树(sorted binary tree)

    1). 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;

    2). 若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;

    3). 任意节点的左、右子树也分别为二叉查找树。

    4). 没有键值相等的节点(no duplicate nodes)。

public class BinarySearchTree<AnyType extends Comparable<? super AnyType>>{
private static class BinaryNode<AnyType>{
BinaryNode(AnyType theElement){
this(theElement,null,null);
} BinaryNode(AnyType theElement, BinaryNode<AnyType> lt, BinaryNode<AnyType>){
element=theElement; left=lt; right= rt;
} AnyType element;
BinaryNode<AnyType> left;
BinaryNode<AnyType> right;
} private BinaryNode<AnyType> root; //构造函数
public BinarySearchTree(){
root=null;
} public void makeEmpty(){
root=null;
} public booolean isEmpty(){
return root==null;
} public boolean contains(AnyType x){
return contains(x,root);
} public AnyType findMin()
{
if(isEmpty()) throw new UnderflowException();
return findMin(root).element;
} public AnyType findMax()
{
if(isEmpty()) throw new UnderflowException();
return findMax(root).element;
} public void insert(AnyType x){
root=insert(x,root);
} public void remove(AnyType x){
root=remove(x,root);
} public void printTree(){
if(isEmpty())
System.out.println("Empty tree");
else
printTree(root);
} //二叉树的contains操作
private boolean contains(AnyType x, BinaryNode<AnyType> t){ if(t==null)
return false; //Comparable接口的compareTo方法比较两个值
int compareResult=x.compareTo(t.element);
if(compareResult<0)
return contains(x,t.left);
else if (compareResult>0)
return contains(x,t.right);
else
return true;
} //查找最小值节点
private BinaryNode<AnyType> findMin(BinaryNode<AnyType> t){
if(t==null)
return null;
else if(t.left==null)
return t;
return findMin(t.left);
} //查找最大值节点
private BinaryNode<AnyType> findMax(BinaryNode<AnyType> t){
if(t !=null)
while(t.right!=null)
t=t.right;
return t;
} //insert插入,返回对 新树根的引用
private BinaryNode<AnyType> insert(AnyType x, BinaryNode<AnyType> t){
if(t==null)
return new BinaryNode<AnyType>(x,null,null); int compareResult=x.compareTo(t.element);
if(compareResult<0)
t.left=insert(x,t.left);
else if(compareResult >0)
t.right=insert(x,t.right);
else
;
return t;
} //删除节点
private BinaryNode<AnyType> remove(AnyType x, BinaryNode<AnyType> t){
if(t==null)
return t;
int compareResult=x.compareTo(t.element); if(compareResult<0)
t.left=remove(x,t.left);
else if(compareResult>0)
t.right=remove(x,t.right);
else if(t.left != null && t.right!=null){
//两个孩子的情况,将右子树的最小值填充到该节点;
//在右子树删除最小值节点
t.element=findMin(t.right).element;
t.right=remove(t.element.t.right);
}
else
//只有一个孩子
t=(t.left != null) ? t.left: t.right;
return t;
} private void printTree(BinaryNode<AnyType> t){
if(t!=null)
{
printTree(t.left);
System.out.println(t.element);
printTree(t.right);
}
} }

2. AVL树

  平衡二叉树定义(AVL) /  Balanced Binary Tree 或 Height-Balanced Tree:它或者是一棵空树,或者是具有一下性质的二叉查找树-- 它的结点左子树和右子树的深度之差不超过1,而且该结点的左子树和右子树都是一棵平衡二叉树。      平衡因子:结点左子树的深度-结点右子树的深度。(0、1、-1)。

  四种情况导致二叉树不平衡:

  针对四种种情况可能导致的不平衡,可以通过旋转使之变平衡。有两种基本的旋转:

      1)左旋转:将根节点旋转到(根节点的)右孩子的左孩子位置

      2)右旋转:将根节点旋转到(根节点的)左孩子的右孩子位置

(1)LL:插入一个新节点到根节点的左子树(Left)的左子树(Left),导致根节点的平衡因子由1变为2

  第一列中,在2节点左子树插入D,为了平衡,应该将{2,D}上移一层,A下移一层,以3为根即可,而原来树中B介于3和5之间,因此将B作为5的左子树;

  第二列中,在2节点的右子树插入D,同理

         

(2)RR:插入一个新节点到根节点的右子树(Right)的右子树(Right),导致根节点的平衡因子由-1变为-2

(3)LR:插入一个新节点到根节点的左子树(Left)的右子树(Right),导致根节点的平衡因子由1变为2

 

(4)RL:插入一个新节点到根节点的右子树(Right)的左子树(Left),导致根节点的平衡因子由-1变为-2

package com.kiritor;
/**
*二叉平衡树简单实现
*/
public class AvlTree< T extends Comparable< ? super T>>
{
private static class AvlNode< T>{//avl树节点 AvlNode( T theElement )
{
this( theElement, null, null );
}
AvlNode( T theElement, AvlNode< T> lt, AvlNode< T> rt )
{
element = theElement;
left = lt;
right = rt;
height = 0;
}
T element; // 节点中的数据
AvlNode< T> left; // 左儿子
AvlNode< T> right; // 右儿子
int height; // 节点的高度
} private AvlNode< T> root;//avl树根 public AvlTree( )
{
root = null;
}
//在avl树中插入数据,重复数据复略
public void insert( T x )
{
root = insert( x, root );
} //在avl中删除数据,这里并未实现
public void remove( T x )
{
System.out.println( "Sorry, remove unimplemented" );
} //在avl树中找最小的数据
public T findMin( )
{
if( isEmpty( ) )
System.out.println("树空");;
return findMin( root ).element;
}
//在avl树中找最大的数据
public T findMax( )
{
if( isEmpty( ) )
System.out.println("树空");
return findMax( root ).element;
}
//搜索
public boolean contains( T x )
{
return contains( x, root );
} public void makeEmpty( )
{
root = null;
} public boolean isEmpty( )
{
return root == null;
}
//排序输出avl树
public void printTree( )
{
if( isEmpty( ) )
System.out.println( "Empty tree" );
else
printTree( root );
} private AvlNode< T> insert( T x, AvlNode< T> t )
{
if( t == null )
return new AvlNode< T>( x, null, null ); int compareResult = x.compareTo( t.element ); if( compareResult < 0 )
{
t.left = insert( x, t.left );//将x插入左子树中
if( height( t.left ) - height( t.right ) == 2 )//打破平衡
if( x.compareTo( t.left.element ) < 0 )//LL型(左左型)
t = rotateWithLeftChild( t );
else //LR型(左右型)
t = doubleWithLeftChild( t );
}
else if( compareResult > 0 )
{
t.right = insert( x, t.right );//将x插入右子树中
if( height( t.right ) - height( t.left ) == 2 )//打破平衡
if( x.compareTo( t.right.element ) > 0 )//RR型(右右型)
t = rotateWithRightChild( t );
else //RL型
t = doubleWithRightChild( t );
}
else
; // 重复数据,什么也不做
t.height = Math.max( height( t.left ), height( t.right ) ) + 1;//更新高度
return t;
} //找最小
private AvlNode< T> findMin( AvlNode< T> t )
{
if( t == null )
return t;
while( t.left != null )
t = t.left;
return t;
}
//找最大
private AvlNode< T> findMax( AvlNode< T> t )
{
if( t == null )
return t;
while( t.right != null )
t = t.right;
return t;
}
//搜索(查找)
private boolean contains( T x, AvlNode t )
{
while( t != null )
{
int compareResult = x.compareTo( (T) t.element ); if( compareResult < 0 )
t = t.left;
else if( compareResult > 0 )
t = t.right;
else
return true; // Match
}
return false; // No match
}
//中序遍历avl树
private void printTree( AvlNode< T> t )
{
if( t != null )
{
printTree( t.left );
System.out.println( t.element );
printTree( t.right );
}
}
//求高度
private int height( AvlNode< T> t )
{
return t == null ? -1 : t.height;
}
//带左子树旋转,适用于LL型
private AvlNode< T> rotateWithLeftChild( AvlNode< T> k2 )
{
AvlNode< T> k1 = k2.left;
k2.left = k1.right;
k1.right = k2;
k2.height = Math.max( height( k2.left ), height( k2.right ) ) + 1;
k1.height = Math.max( height( k1.left ), k2.height ) + 1;
return k1;
}
//带右子树旋转,适用于RR型
private AvlNode< T> rotateWithRightChild( AvlNode< T> k1 )
{
AvlNode< T> k2 = k1.right;
k1.right = k2.left;
k2.left = k1;
k1.height = Math.max( height( k1.left ), height( k1.right ) ) + 1;
k2.height = Math.max( height( k2.right ), k1.height ) + 1;
return k2;
}
//双旋转,适用于LR型
private AvlNode< T> doubleWithLeftChild( AvlNode< T> k3 )
{
k3.left = rotateWithRightChild( k3.left );
return rotateWithLeftChild( k3 );
}
//双旋转,适用于RL型
private AvlNode< T> doubleWithRightChild( AvlNode< T> k1 )
{
k1.right = rotateWithLeftChild( k1.right );
return rotateWithRightChild( k1 );
}
// Test program
public static void main( String [ ] args )
{
AvlTree< Integer> t = new AvlTree< Integer>( );
final int NUMS = 200;
final int GAP = 17;
System.out.println( "Checking... (no more output means success)" );
for( int i = GAP; i != 0; i = ( i + GAP ) % NUMS )
t.insert( i );
t.printTree( );
System.out.println(t.height(t.root)); }
}

3. 伸展树

伸展树(Splay Tree),也叫分裂树,是一种二叉排序树,它由Daniel Sleator和Robert Tarjan创造,后者对其进行了改进。

假设想要对一个二叉查找树执行一系列的查找操作。为了使整个查找时间更小,被查频率高的那些条目就应当经常处于靠近树根的位置。于是想到设计一个简单方法,在每次查找之后对树进行重构,把被查找的条目搬移到离树根近一些的地方。splaytree应运而生。splaytree是一种自调整形式的二叉查找树,它会沿着从某个节点到树根之间的路径,通过一系列的旋转把这个节点搬移到树根去。

伸展树能在O(logn)内完成插入、查找和删除作。它的优势在于不需要记录用于平衡树的冗余信息。在伸展树上的一般操作都基于“伸展”操作。当查找到一个结点后,需要进行“伸展”操作,把这个结点移动到树根。至于伸展操作有两种方式:自底向上和自顶向下。

1)自底向上 

  所谓的自底向上就是像AVL树那样的“左旋”、“右旋”,多次操作之后把此结点旋转到树根,但这种方式,需要保存查找路径上的各个结点的指针以供旋转之用。

2)自顶向下

  当我们沿着树向下搜索某个节点X的时候,我们将搜索路径上的节点及其子树移走。我们构建两棵临时的树──左树和右树。

  没有被移走的节点构成的树称作中树。在伸展操作的过程中:

    1、当前节点X是中树的根。

    2、左树L保存小于X的节点。

    3、右树R保存大于X的节点。

  开始时候,X是树T的根,左右树L和R都是空的。我们以一个查找2结点的实例,来图解SplayTree的伸展过程。

4.

 

数据结构与算法分析java——树2(二叉树类型)的更多相关文章

  1. 数据结构与算法分析java——树1

    1. 基本术语 度(degree):一个节点的子树个数称为该节点的度: 树中结点度的最大值称为该树的度. 层数(level):从根结点开始算,根节点为1 高度(height)/深度(depth):节点 ...

  2. 《数据结构与算法分析-Java语言描述》 分享下载

    书籍信息 书名:<数据结构与算法分析-Java语言描述> 原作名:Data Structures and Algorithm Analysis in Java 作者: 韦斯 (Mark A ...

  3. Android版数据结构与算法(六):树与二叉树

    版权声明:本文出自汪磊的博客,未经作者允许禁止转载. 之前的篇章主要讲解了数据结构中的线性结构,所谓线性结构就是数据与数据之间是一对一的关系,接下来我们就要进入非线性结构的世界了,主要是树与图,好了接 ...

  4. [数据结构与算法分析(Mark Allen Weiss)]二叉树的插入与删除 @ Python

    二叉树的插入与删除,来自Mark Allen Weiss的<数据结构与算法分析>. # Definition for a binary tree node class TreeNode: ...

  5. 数据结构(三) 树和二叉树,以及Huffman树

    三.树和二叉树 1.树 2.二叉树 3.遍历二叉树和线索二叉树 4.赫夫曼树及应用 树和二叉树 树状结构是一种常用的非线性结构,元素之间有分支和层次关系,除了树根元素无前驱外,其它元素都有唯一前驱. ...

  6. 读书笔记:《数据结构与算法分析Java语言描述》

    目录 第 3 章 表.栈和队列 3.2 表 ADT 3.2.1 表的简单数组实现 3.2.2 简单链表 3.3 Java Collections API 中的表 3.3.1 Collection 接口 ...

  7. 数据结构与算法分析java——线性表1

    说到线性结构的话,我们可以根据其实现方式分为三类: 1)顺序结构的线性表 2)链式结构的线性表 3)栈和队列的线性表   应用程序后在那个的数据大致有四种基本的逻辑结构: 集合:数据元素之间只有&qu ...

  8. 数据结构与算法分析-AVL树

    1.AVL树是带有平衡条件的二叉查找树. 2.AVL树的每个节点高度最多相差1. 3.AVL树实现的难点在于插入或删除操作.由于插入和删除都有可能破坏AVL树高度最多相差1的特性,所以当特性被破坏时需 ...

  9. 数据结构与算法分析java——散列

    1. 散列的概念 散列方法的主要思想是根据结点的关键码值来确定其存储地址:以关键码值K为自变量,通过一定的函数关系h(K)(称为散列函数),计算出对应的函数值来,把这个值解释为结点的存储地址,将结点存 ...

随机推荐

  1. [转] 使用 Java8 Optional 的正确姿势

    [From] https://unmi.cc/proper-ways-of-using-java8-optional/ 我们知道 Java 8 增加了一些很有用的 API, 其中一个就是 Option ...

  2. casper爬虫操作记录

    phantom.outputEncoding = "gbk"; var fs=require("fs") //var data = fs.read(" ...

  3. 转: centos系统home下的中文目录改为英文目录

    转自h t t p : / /xugang-1017-126-com.iteye.com/blog/2081845 如果安装了中文版的Cent OS之后,root目录和home目录下会出现中文的路径名 ...

  4. Spring整合AspectJ的AOP

    学而时习之,不亦说乎!                              --<论语> 看这一篇之前最好先看前面关于AOP的两篇. http://www.cnblogs.com/z ...

  5. Linux批量杀掉挂掉的进程

    $ `ps aux | grep test | grep -v grep | awk '{print $2}'` 杀掉含有test且不含有grep的进程,后面的 awk '{print $2}' 是进 ...

  6. 谈谈UI设计的6个实用小技巧

    从事UI设计的朋友们,肯定知道我们在做UI设计时,其实是可以通过一些小技巧来帮我们设计的界面更加的漂亮.实用.交互性强,用户体验更好.今天的话,上海艾艺在互联网上面搜寻了几个小技巧.在这里跟大家一起来 ...

  7. Bloom filter和Counting bloom filter

    Bloom filter原理: https://en.wikipedia.org/wiki/Bloom_filter 推导过程结合博客: https://blog.csdn.net/jiaomeng/ ...

  8. Maths Intro - Probability

    设事件A,B,C两辆独立,且满足ABC=空集,及P(A)=P(B)=P(C)=x,求max(x) x最大值为1/2分析: x值要保证所有的由A.B.C交或并得到的集合的概率测度在0到1之间. 先考虑A ...

  9. Nginx 配置跨域权限

    今天设置静态资源服务器时发现 Font from origin 'http://start.fbzl.org' has been blocked from loading by Cross-Origi ...

  10. word 快捷键

    Ctrl+shift+F9  清除word文档中的超链接