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

java 数据结构 二叉查找树的简单实现

2018-01-16 17:50 666 查看

什么是二叉查找树

二叉查找树是一种树结构。首先是二叉树。它表示每个节点最多有两个子节点,而二叉查找树,它还要求左子节点必须比右子节点小。



对于这个结构,我们以下几个操作的实现:

树中的元素必须能比较

这里的比较,我们不用equals和==,我们要判断它与节点中元素的大小关系,所以这里我们有2种实现方案:

1. 元素实现Comparable接口,重写它的compareTo方法

2. 在二叉树的构造方法中传入特定的Comparator比较器进行比较

/**
* 比较器
*/
private Comparator<T> comparator;

public BinarySearchTree() {
root = null;
comparator = null;
}

/**
* 带有指定比较器的构造方法
* @param comparator
*/
public BinarySearchTree(Comparator<T> comparator) {
root = null;
this.comparator = comparator;
}

/**
* 自己实现一个compare方法
* 如果在构造时传入了相应的比较器,则用传入比较器的compare方法
* 若没有传,则强转成comparable进行比较
*
* @param t1
* @param t2
* @return
*/
private int compare(T t1, T t2) {
/**
* 如果比较器不为null
*/
if (comparator != null) {
return comparator.compare(t1, t2);
}
return ((Comparable) t1).compareTo(t2);
}


insert操作

当执行插入操作时,思路就是比较插入元素和节点元素的大小,若插入元素大,则往节点右边走,相反则往节点左边走,最后当节点的左边或右边为null的时候,就把元素插入进去了.若碰到插入元素重复的情况则不管

public void insert(T t) {
root = insert(t, root);
}

private BinaryNode<T> insert(T t, BinaryNode binaryNode) {
if (binaryNode == null) {
BinaryNode node = new BinaryNode(t, null, null);
return node;
}
Object element = binaryNode.element;

int compare = compare(t, (T) element);

if (compare == -1) {
// 说明t 比 element 小
binaryNode.left = insert(t, binaryNode.left);
} else if (compare == 1) {
// 说明t 比 element 大
binaryNode.right = insert(t, binaryNode.right);
} else ;
/**
* 若t和element一样大则不做任何事情
*/

/**
* 把根返回
*/
return binaryNode;
}


contains操作

和insert操作基本一个思路,就是比较元素和节点元素大小来判断往左走还是往右走,若碰到元素和节点元素相等的情况则返回true,否则返回false

public boolean contains(T t) {
return contains(t, root);
}

private boolean contains(T t, BinaryNode binaryNode) {
if (binaryNode == null) {
return false;
}
Object element = binaryNode.element;

int compare = compare(t, (T) element);

if (compare == 1) {
return contains(t, binaryNode.right);
} else if (compare == -1) {
return contains(t, binaryNode.left);
} else {
return true;
}
}


findMin和findMax操作

很简单,findMin就是一直往左走,知道节点的左节点为null时,则该节点的元素最小,findMax则相反,这里我们findMax用递归实现,findMin用循环实现

public T findMin() {
BinaryNode min = findMin(root);
if (min != null) {
return (T) min.element;
}
return null;
}

public T findMax() {
BinaryNode max = findMax(root);
if (max != null) {
return (T) max.element;
}
return null;
}

private BinaryNode findMin(BinaryNode binaryNode) {
if (binaryNode != null) {
while (binaryNode.left != null) {
binaryNode = binaryNode.left;
}
}
return binaryNode;
}

private BinaryNode findMax(BinaryNode binaryNode) {
if (binaryNode == null) {
return null;
}
if(binaryNode.right != null) {
return findMax(binaryNode.right);
}
return binaryNode;
}


remove操作

这个比较麻烦,因为有几种情况:

删除的节点没有子节点。。。。这个比较简单,直接删除即可

删除的节点有一个子节点。。。。我们通过把要删除节点的父节点的链绕过该节点,在删除

删除的节点有两个子节点。。。这种情况就比较麻烦了,我们先拿到这个节点的右子节点,然后一直往左拿到最小的那个节点,用这个最小节点的数据代替我们要删除的节点,然后把这个最小的节点删除即可

public boolean remove(T t) {
BinaryNode remove = remove(t, root);
if (remove != null) {
return true;
}
return false;
}

private BinaryNode remove(T t, BinaryNode binaryNode) {
if (binaryNode == null) {
return binaryNode;
}
int compare = compare(t, (T) binaryNode.element);

if (compare == -1) {
binaryNode.left = remove(t, binaryNode.left);
} else if (compare == 1) {
binaryNode.right = remove(t, binaryNode.right);
} else if (binaryNode.left != null && binaryNode.right != null) {
/**
*这儿注释的三局代码,findMin会搜索一遍,remove又会搜索一遍,所以我们写一个特殊的removeMin方法来避免这个操作
*/
//            BinaryNode min = findMin(binaryNode.right);
//            binaryNode.element = min.element;
//            binaryNode.right = remove((T) min.element, binaryNode.right);
removeMin(binaryNode);
} else {
binaryNode = binaryNode.left == null ? binaryNode.right : binaryNode.left;
}
return binaryNode;
}

private void removeMin(BinaryNode binaryNode) {
if (binaryNode == null) {
return ;
}
BinaryNode node = binaryNode.right;
BinaryNode parentNode = null;

while (true) {
if(node.left != null) {
parentNode = node;
node = node.left;
} else {
Object element = node.element;
binaryNode.element = element;
parentNode.left = node.right;
break;
}
}
}


代码

package collection;

import java.util.Comparator;

/**
* Created by sunhan on 2018/1/14.
*/
public class BinarySearchTree<T> {

private static class BinaryNode<T> {

private BinaryNode<T> left;

private BinaryNode<T> right;

private T element;

public BinaryNode(T t) {
this(t, null, null);
}

public BinaryNode(T t, BinaryNode left, BinaryNode right) {
this.element = t;
this.left = left;
this.right = right;
}
}

/**
* 先序遍历
*/

public void suffix(){
midIterator(root);
}

private void suffixIterator(BinaryNode node){
System.out.println(node.element.toString());
if(node.left != null){
suffixIterator(node.left);
}
if(node.right != null){
suffixIterator(node.right);
}
}

/**
* 中序遍历
*/

public void mid(){
midIterator(root);
}

private void midIterator(BinaryNode node){
if(node.left != null){
midIterator(node.left);
}
System.out.println(node.element.toString());
if(node.right != null){
midIterator(node.right);
}
}

/**
* 后序遍历
*/

public void back(){
backIterator(root);
}

private void backIterator(BinaryNode node){
if(node.left != null){
backIterator(node.left);
}
if(node.right != null){
backIterator(node.right);
}
System.out.println(node.element.toString());
}

/**
* 根
*/
private BinaryNode<T> root;

/**
* 比较器
*/
private Comparator<T> comparator;

public BinarySearchTree() {
root = null;
comparator = null;
}

/**
* 带有指定比较器的构造方法
* @param comparator
*/
public BinarySearchTree(Comparator<T> comparator) {
root = null;
this.comparator = comparator;
}

/**
* 自己实现一个compare方法
* 如果在构造时传入了相应的比较器,则用传入比较器的compare方法
* 若没有传,则强转成comparable进行比较
*
* @param t1
* @param t2
* @return
*/
private int compare(T t1, T t2) {
/**
* 如果比较器不为null
*/
if (comparator != null) {
return comparator.compare(t1, t2);
}
return ((Comparable) t1).compareTo(t2);
}

public void insert(T t) {
root = insert(t, root);
}

private BinaryNode<T> insert(T t, BinaryNode binaryNode) {
if (binaryNode == null) {
BinaryNode node = new BinaryNode(t, null, null);
return node;
}
Object element = binaryNode.element;

int compare = compare(t, (T) element);

if (compare == -1) {
// 说明t 比 element 小
binaryNode.left = insert(t, binaryNode.left);
} else if (compare == 1) {
// 说明t 比 element 大
binaryNode.right = insert(t, binaryNode.right);
} else ;
/**
* 若t和element一样大则不做任何事情
*/

/**
* 把根返回
*/
return binaryNode;
}

public T findMin() {
BinaryNode min = findMin(root);
if (min != null) {
return (T) min.element;
}
return null;
}

public T findMax() {
BinaryNode max = findMax(root);
if (max != null) {
return (T) max.element;
}
return null;
}

private BinaryNode findMin(BinaryNode binaryNode) {
if (binaryNode != null) {
while (binaryNode.left != null) {
binaryNode = binaryNode.left;
}
}
return binaryNode;
}

private BinaryNode findMax(BinaryNode binaryNode) {
if (binaryNode == null) {
return null;
}
if(binaryNode.right != null) {
return findMax(binaryNode.right);
}
return binaryNode;
}

public boolean contains(T t) {
return contains(t, root);
}

private boolean contains(T t, BinaryNode binaryNode) {
if (binaryNode == null) {
return false;
}
Object element = binaryNode.element;

int compare = compare(t, (T) element);

if (compare == 1) {
return contains(t, binaryNode.right);
} else if (compare == -1) {
return contains(t, binaryNode.left);
} else {
return true;
}
}

public boolean remove(T t) {
BinaryNode remove = remove(t, root);
if (remove != null) {
return true;
}
return false;
}

private BinaryNode remove(T t, BinaryNode binaryNode) {
if (binaryNode == null) {
return binaryNode;
}
int compare = compare(t, (T) binaryNode.element);

if (compare == -1) {
binaryNode.left = remove(t, binaryNode.left);
} else if (compare == 1) {
binaryNode.right = remove(t, binaryNode.right);
} else if (binaryNode.left != null && binaryNode.right != null) {
//            BinaryNode min = findMin(binaryNode.right);
//            binaryNode.element = min.element;
//            binaryNode.right = remove((T) min.element, binaryNode.right);
removeMin(binaryNode);
} else {
binaryNode = binaryNode.left == null ? binaryNode.right : binaryNode.left;
}
return binaryNode;
}

private void removeMin(BinaryNode binaryNode) {
if (binaryNode == null) {
return ;
}
BinaryNode node = binaryNode.right;
BinaryNode parentNode = null;

while (true) {
if(node.left != null) {
parentNode = node;
node = node.left;
} else {
Object element = node.element;
binaryNode.element = element;
parentNode.left = node.right;
break;
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息