一文彻底掌握二叉查找树,非史上最全总结(多图,附代码)

一文彻底掌握二叉查找树,非史上最全总结(多图,附代码)树在数据结构中是重中之重,尤其以各类二叉树为学习的难点。现在希望通过写一个关于二叉树的专题系列。在学习与总结的同时更加深入的了解掌握二叉树,让我

欢迎大家来到IT世界,在知识的湖畔探索吧!

树在数据结构中是重中之重,尤其以各类二叉树为学习的难点。现在希望通过写一个关于二叉树的专题系列。在学习与总结的同时更加深入的了解掌握二叉树,让我们开始吧!!!

定义

二叉查找树(Binary Search Tree),又称二叉排序树(Binary Sort Tree),亦称二叉搜索树。多种叫法,反正都是一个意思,这些叫法的由来主要是由它的性质决定的。

二叉树具有以下性质:

1. 一棵空树,或者是具有下列性质的二叉树

2. 若左子树不空,则左子树上所有结点的值均小于它的根结点的值

3. 若右子树不空,则右子树上所有结点的值均大于它的根结点的值

4.左、右子树也分别为二叉排序树

5. 没有键值相等的结点

二叉树的概念非常好理解,如下图所示就是一棵二叉查找树:

一文彻底掌握二叉查找树,非史上最全总结(多图,附代码)

二叉查找树的操作

查找节点

1. 若比较关键字与根节点的大小,相等则成功返回

2. 若小于根节点,递归左子树

3. 若大于根节点,递归右子树

4. 若子树为空,查找不成功。

插入节点

1. 比较关键字与根节点的大小,相等则表示已存在,成功返回

2. 若小于根节点,递归左子树

3. 若大于根节点,递归右子树

4. 若子树为空,作为节点的子节点,返回

删除节点

二叉排序树删去一个结点,分三种情况讨论,先贴张图方便理解:

一文彻底掌握二叉查找树,非史上最全总结(多图,附代码)

1. 删除的节点为叶子节点,直接删除,不会对树的结构有影响,如上图删除1,5,10,12,14

2. 删除的节点只有左子树或右子树,将节点的左子树或右子树作为父节点的左子树或右子树,删掉节点。如上图的删除节点7,将节点3作为8的左子树。删除节点9,则将10作为11的左子树

3. 删除的节点有左子树和右子树。找到右子树的最小节点,替换要删除的节点的位置。

第1,2种情况比较好理解,就不再赘述了,但第3种情况怎么理解呢?为方便讲解,把图标下颜色

一文彻底掌握二叉查找树,非史上最全总结(多图,附代码)

假设要删除一个节点11,其左右子树为DL(绿色部分)、DR(黄色部分)。

即从树上把节点11摘除,同时将DL、DR两棵子树融合成一棵树DLR,挂到D原来的父节点上。

我们知道,二叉树的任意节点的左子树上的所有节点均小于其右子树上的所有节点。那么我们只要找到右子树上的最小的节点(该例子中为节点12),那么该节点必然小于右子树DR上所有其它节点,同时大于左子树DL上的所有节点,假设这个节点是M。

把左子树作为M的左子树,把右子树除去M然后作为M的右子树,这时产生的新的树必然满足二叉搜索树的定义。再把M替换原来D的位置,删除完成,结果如下图。

一文彻底掌握二叉查找树,非史上最全总结(多图,附代码)

最后附上相关代码:

public class Tree {
	private Node root;

	public void insert(int value) {

		root = insert(root, value);
	}

	private Node insert(Node x, int value) {
		if (x == null) {// 首次插入
			return new Node(value);
		}
		int xVal = x.value;

		if (value < xVal) {
			x.left = insert(x.left, value);
		} else if (value > xVal) {
			x.right = insert(x.right, value);
		} else {
			// do nothing
		}

		return x;

	}

	private class Node {

		private int value;
		private Node left, right;

		public Node(int value) {
			this.value = value;
			left = right = null;
		}
	}

	public Node select(int value) {
		return select(root, value);// work when BST is empty
	}

	private Node select(Node x, int value) {

		if (x == null)
			return null;

		int xVal = x.value;

		if (value < xVal)
			return select(x.left, value);
		else if (value > xVal)
			return select(x.right, value);
		else
			return x;

	}

	public void delete(int value) {

		root = delete(root, value);

	}

	private Node delete(Node x, int value) {

		if (x == null)
			return null;

		int xVal = x.value;

		if (value < xVal)
			x.left = delete(x.left, value);// 左子树
		else if (value > xVal)
			x.right = delete(x.right, value);// 右子树
		else {
			if (x.right == null)
				return x.left;
			if (x.left == null)
				return x.right;

			Node temp = x;// 要被删除的节点
			x = min(temp.right);// 右子树的最小节点
			x.right = deleteMin(temp.right);// 删除最小节点,同时返回右子树
			x.left = temp.left;// 原来的左子树
		}

		return x;
	}

	private Node min(Node x) {
		if (x.left == null)
			return x;
		return min(x.left);
	}

	private Node deleteMin(Node x) {

		if (x.left == null)
			return x.right;

		x.left = deleteMin(x.left);

		return x;
	}
}

欢迎大家来到IT世界,在知识的湖畔探索吧!

效率

对该二叉树的节点进行查找发现深度为1的节点的查找次数为1,深度为2的查找次数为2,深度为n的节点的查找次数为n,因此其平均查找次数为 (1+2+2+3+3+3) / 6 = 2.3次

二叉查找树可以任意地构造,同样是1,2,3,4,5,6这六个数字,也可以按照下图的方式来构造:

一文彻底掌握二叉查找树,非史上最全总结(多图,附代码)

但是这棵二叉树的查询效率就低了,它实际是一个链表。所以二叉树的查询效率最好时为O(logN),而最差则是O(N),这是非常的低效的。

因此若想二叉树的查询效率尽可能高,需要这棵二叉树是平衡的,从而引出新的定义——平衡二叉树,或称AVL树。

我将在下一篇博文为大家详细讲解平衡二叉树的知识,尽请关注,如果你觉得这篇文章帮助到你了,还请帮忙转发,让更多人看到吧。想看更多精彩的文章,就关注我吧。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/34571.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们YX

mu99908888

在线咨询: 微信交谈

邮件:itzsgw@126.com

工作时间:时刻准备着!

关注微信