二叉查找树(Binary Search Tree)

来源:互联网 发布:婚礼发布网站源码java 编辑:程序博客网 时间:2024/05/21 09:36

本帖部分文字和图片来自于
https://zh.wikipedia.org/wiki/%E4%BA%8C%E5%85%83%E6%90%9C%E5%B0%8B%E6%A8%B9
http://www.cnblogs.com/huangxincheng/archive/2012/07/21/2602375.html

但所有代码均为原创

二叉查找树(英语:Binary Search Tree),也称二叉搜索树、有序二叉树(英语:ordered binary tree),排序二叉树(英语:sorted binary tree),是指一棵空树或者具有下列性质的二叉树:

  • 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
  • 若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
  • 任意节点的左、右子树也分别为二叉查找树;
  • 没有键值相等的节点。

这里写图片描述

二叉查找树相比于其他数据结构的优势在于查找、插入的时间复杂度较低,为O(log n)。二叉查找树是基础性数据结构,用于构建更为抽象的数据结构,如集合、multiset、关联数组等。

如何添加元素到二叉查询树中呢?

  • 若b是空树,则将s所指结点作为根节点插入,否则:
  • 若s->data等于b的根节点的数据域之值,则返回,否则:
  • 若s->data小于b的根节点的数据域之值,则把s所指节点插入到左子树中,否则:
  • 把s所指节点插入到右子树中。(新插入节点总是叶子节点)

这里写图片描述

首先定义二叉查找树类

public class BinarySearchTreeNode {    public int value = 0;    public BinarySearchTreeNode parent = null;    public BinarySearchTreeNode left = null;    public BinarySearchTreeNode right = null;    public BinarySearchTreeNode(int value){        this.value = value;    }}

然后定义add方法

public BinarySearchTreeNode add(int value, BinarySearchTreeNode node){    if(node == null) {        node = new BinarySearchTreeNode(value);    }else {        if (value< node.value) {            node.left = add(value, node.left);        } else {            node.right = add(value, node.right);        }    }

打印整个二叉查找树:

public void printBST(BinarySearchTreeNode node){    System.out.print("node = " + node.value);    System.out.print(", node.parent = " + (node.parent==null?"null":node.parent.value));    System.out.print(", left=" + (node.left==null?"null":node.left.value));    System.out.print(", right=" + (node.right==null?"null":node.right.value));    System.out.println("");    if(node.left != null){        printBST(node.left);    }    if(node.right != null){        printBST(node.right);    }}

最后我们运行下面的代码进行测试:

int[] values = {20,15,25,10,18,30,12};BinarySearchTreeNode root = null;for(int i=0; i<values.length; i++) {    root = add(values[i], root);}printBST(root);

以下是输出内容:

node = 20, node.parent = null, left=15, right=25
node = 15, node.parent = 20, left=10, right=18
node = 10, node.parent = 15, left=null, right=12
node = 12, node.parent = 10, left=null, right=null
node = 18, node.parent = 15, left=null, right=null
node = 25, node.parent = 20, left=null, right=30
node = 30, node.parent = 25, left=null, right=null

生成二叉查找树的问题解决了,那么如何查找呢
- 若b是空树,则搜索失败,否则:
- 若x等于b的根节点的数据域之值,则查找成功;否则:
- 若x小于b的根节点的数据域之值,则搜索左子树;否则:
- 查找右子树。

public BinarySearchTreeNode search(BinarySearchTreeNode node, int value){    if(node != null) {        if(value == node.value){            return node;        }else if (value < node.value) {            return search(node.left, value);        } else {            return search(node.right, value);        }    }else{        return null;    }}

>

System.out.println(“search 18 = ” + (search(root, 18)==null?”failure”:”success”));
System.out.println(“search 22 = ” + (search(root, 22)==null?”failure”:”success”));
输出结果:
search 18 = success
search 22 = failure

删除是最复杂的,主要考虑两种情况

单孩子的情况
这个比较简单,如果删除的节点有左孩子那就把左孩子顶上去,如果有右孩子就把右孩子顶上去,结束。
这里写图片描述

左右都有孩子的情况
首先可以这么想象,如果我们要删除一个数组的元素,那么我们在删除后会将其后面的一个元素顶到被删除的位置,如图
这里写图片描述

那么二叉树操作同样也是一样,我们根据”中序遍历“找到要删除结点的后一个结点,然后顶上去就行了,原理跟”数组”一样一样的。

这里写图片描述

代码如下:

public BinarySearchTreeNode delete(BinarySearchTreeNode node){    if(node != null){        if (node.left == null && node.right == null) {            if(node.parent == null){                node = null;                return node;            } else if (node.parent.left != null && node.parent.left.value == node.value) {                node.parent.left = null;            } else if (node.parent.right != null && node.parent.right.value == node.value) {                node.parent.right = null;            }            return node.parent;        } else if (node.left != null && node.right != null) {            node.value = node.right.value;            node = delete(node.right);        } else {            BinarySearchTreeNode parent = node.parent;            BinarySearchTreeNode n = node.left == null ? node.right : node.left;            n.parent = parent;            if (node.parent.left != null && node.parent.left.value == node.value) {                node.parent.left = n;            } else if (node.parent.right != null && node.parent.right.value == node.value) {                node.parent.right = n;            }            node = n;        }    }    return node;}

以下是测试代码:

System.out.println("it will delete 15");BinarySearchTreeNode deleteNode15 = search(root, 15);if(deleteNode15 != null && deleteNode15.parent != null) {    System.out.println("delete 15 = " + (delete(deleteNode15) == null ? "failure" : "success"));}else{    deleteNode15 = null;    System.out.println("There is no any node.");}printBST(root);

it will delete 15
delete 15 = success
node = 20, node.parent = null, left=18, right=25
node = 18, node.parent = 20, left=10, right=null
node = 10, node.parent = 18, left=null, right=12
node = 12, node.parent = 10, left=null, right=null
node = 25, node.parent = 20, left=null, right=30
node = 30, node.parent = 25, left=null, right=null

阅读全文
0 0
原创粉丝点击