您的位置:首页 > 理论基础 > 数据结构算法

数据结构-Java实现-树

2015-12-23 09:40 351 查看
二叉查找树

AVL树

树的遍历

…(待续)

1、二叉查找树

使二叉树成为二叉查找树的性质是,对于树中的每个节点X,它的左子树中所有项的值小于X的值,而它的右子树中所有项的值大于X的值。

//二叉查找树
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> rt)
{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 boolean isEmpty()
{ return root==null;}
//contains方法(递归实现)
private boolean contains(AnyType x,BinaryNode<AnyType> t)
{
//节点为空,则该节点为叶子节点,走到头了没找到返回false
if(t==null)
return false;

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;  //不大不小,是它就是它!
}

//findMin方法(递归实现)
private BinaryNode<AnyType> findMin(BinaryNode<AnyType> t)
{
if(t==null)
return null;
eles if(t.left==null)
return t;
return findMin(t.left);
}

//findMax方法(非递归实现,类似指针)
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);
//插入操作,关键在于t.left和t.right的重置就相当于重新连接
if(compareResult<0)
t.left=insert(x,t.left);
else if(compareResult>0)
t.right=insert(x,t.right);
else
;  //重复元素不管它
return t;  //t在插入后被改变
}
//remove方法
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(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;
}
}


2、AVL树

一颗AVL树是其每个节点的左子树和右子树的高度最多差1的二叉查找树(空树高度定义为-1)。

//AVL树
//节点类
private static class AvlNode<AnyType>
{
AvlNode(AnyType theElement)
{this(theElement,null,null);}

AvlNode(AnyType theElement, AvlNode<AnyType> lt,AvlNode<AnyType> rt)
{element=theElement;left=lt;right=rt;}

AnyType element;
AvlNode<AnyType> left;
AvlNode<AnyType> right;
int height;  //节点高度
}
//计算节点高度的方法
private int height(AvlNode<AnyType> t)
{
return t==null?-1:t.height;
}

private AvlNode<AnyType> insert(AnyType x, AvlNode<AnyType> t)
{
if(t==null)
return new AvlNode<AnyType>(x, null, null);

int compareResult=compare(x,t.element);  //compare方法可以在主类中通过创建Comparator对象定义

if(compareResult<0)  //当被插入值小于节点值
{
t.left=insert(x,t.left);  //则递归地在该节点的左子树中执行插入操作
if(height(t.left)-height(r.right)==2)  //==2表示不平衡了
if(compare(x,t.left.element)<0)  //x比节点左子节点值小,说明是左左,执行单旋转
t=rotateWhithLeftChild(t);
else  //否则就是左右,执行双旋转
t=doubleWithLeftChild(t);
}
else if(compareResult>0)  //当被插入值大于节点值
{
t.right=insert(x,t.right);  //则递归地在该节点的右子树中执行插入操作
if(height(t.right)-height(t.left)==2)  //==2表示不平衡
if(compare(x,t.right.element)>0)  //x比节点右子节点值大,说明是右右,执行单旋转
t=rotateWhithRightChild(t);
else
t=doubleWithRightChild(t);
}
else
;  //重复值不予处理
t.height=Math.max(height(t.left),height(t.right))+1;  //递归地计算节点的高度
return t;
}
//左左单旋转
private AvlNode<AnyType> rotateWhithLeftChild(AvlNode<AnyType> k2)
{
AvlNode<AnyType> k1=k2.left;  //k2左子节点
k2.left=k1.right;  //由于k2成为k1的右子节点,k1的原本的右子节点断开成为k2的左子节点
k1.right=k2;  //k1上提,k2成为k1的右子节点
k2.height=Math.max(height(k2.left),height(k2,right))+1;
k1.height=Math.max(height(k1.left),k2.height)+1;
return k1;
}
//左右双旋转
private AvlNode<AnyType> doubleWithLeftChild(AvlNode<AnyType> k3)
{
k3.left=rotateWhithRightChild(k3.left); //先将第二个节点右右
return rotateWhithLeftChild(k3);  //再将第一个节点左左
}
//右右单旋转和右左双旋转对称


3、树的遍历

//中序遍历
//重载和递归
public printTree()
{
if(isEmpty())
System.out.println("Empty tree");
else
printTree(root);
}

private void printTree(BinaryNode<AnyType> t)
{
if(t!=null)
{
printTree(t.left);
System.out.println(t.element);
printTree(t.right);
}
}
//后续遍历
//可计算树的高度
private int height(Binary<AnyType> t)
{
if(t==null)
return -1;
else
return 1+Math.max(height(t.left),height(t.right));
}
//先序遍历
//用深度标记每一个节点的时候可以使用
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: