数据结构-树-二叉搜索树

1. 概念

二叉查找树(Binary Search Tree)也称有序二叉树(Ordered Binary Tree)、排序二叉树(Sorted Binary Tree)。

二叉查找树是java的 TreeSetTreeMap 类实现的基础。

二叉查找树相比于其他数据结构的优势在于查找、插入的时间复杂度较低。为O(log n)。

2. 特点

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

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

  • 任意结点的左、右子树也分别为二叉查找树。

  • 没有键值相等的结点(no duplicate nodes)。

3. 实现

由于二叉查找树要求所有的节点都可以进行排序.所以编写时代码时需要一个 Comparable 泛型接口。

由于树的递归定义,二叉查找树的代码实现也基本上都是使用递归的函数,

3.1 继承关系


public class BinarySearchTree<T extends Comparable<T>> 

3.2 定义节点

private static class TreeNode<T> {

    T data;

    TreeNode<T> left;

    TreeNode<T> right;

    public TreeNode(T data) {
        this.data = data;
    }
}

3.3 属性

//根节点
private TreeNode<T> root;

3.5 插入 void insert(T data)

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

private TreeNode<T> insert(T data, TreeNode<T> node) {
    if (node == null) {
        return new TreeNode<T>(data);
    }
    int result = node.data.compareTo(data);
    if (result == 0) {
        throw new IllegalArgumentException("has the same data :" + data.toString());
    }
    if (result > 0) {
        node.left = insert(data, node.left);
    } else if (result < 0) {
        node.right = insert(data, node.right);
    }
    return node;
}

3.6 查找最小值 T min()

public T min() {
    TreeNode<T> node = min(root);
    return node == null ? null : node.data;
}

private TreeNode<T> min(TreeNode<T> node) {
    if (node == null) {
        return null;
    }
    if (node.left == null) {
        return node;
    }
    return min(node.left);
}

3.7 查找最大值 T max()

public T max() {
    TreeNode<T> node = max(root);
    return node == null ? null : node.data;
}

private TreeNode<T> max(TreeNode<T> node) {
    if (node == null) {
        return null;
    }
    if (node.right == null) {
        return node;
    }
    return max(node.right);
}

3.8 是否包含元素 boolean contains(T data)

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

public boolean contains(T data, TreeNode<T> node) {
    if (node == null) {
        return false;
    }
    int result = node.data.compareTo(data);
    if (result > 0) {
        return contains(data, node.left);
    } else if (result < 0) {
        return contains(data, node.right);
    }
    return true;
}

3.9 删除元素 void remove(T data)

在二叉查找树种,删除是最复杂的实现。涉及三种情况:

  • 被删除节点是树叶节点(没有子树):最简单,直接删除,将该节点置为null即可

  • 被删除节点有一个子节点(左子树或右子树):是该节点的父节点指向该节点的子节点(左或右). 见图1

  • 被删除节点有两个子节点:用其右子树中的最小值代替该节点上的值,删除其右子树上的最小值. 见图2

public void remove(T data) {
    remove(data, root);
}

public TreeNode<T> remove(T data, TreeNode<T> node) {
    if (data == null) {
        return null;
    }
    int result = node.data.compareTo(data);
    if (result > 0) {
        node.left = remove(data, node.left);
    } else if (result < 0) {
        node.right = remove(data, node.right);
    } else {
        //如果被删除节点有两个儿子
        if (node.left != null && node.right != null) { 
            TreeNode<T> minRight = find(node.right, true);
            node.data = minRight.data; // 当前节点值被其右子树的最小值代替
            node.right = remove(minRight.data, node.right); // 将右子树的最小值删除
        } else if (node.left == null && node.right == null) {
            node = null; // 如果被删除的节点只是一个叶子
        } else if (node.left == null || node.right == null) { // 如果被删除节点只有一个儿子
            node = (node.left != null) ? node.left : node.right;
        }
    }
    return node;
}



作者:faris_shi
链接:https://www.jianshu.com/p/74f13e1a5aed
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

猜你喜欢

转载自blog.csdn.net/u013767488/article/details/88733631
今日推荐