二叉搜索树(BST)
二叉搜索树需满足以下四个条件:
1.若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
2.若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
3.任意节点的左、右子树也分别为二叉查找树;
4.没有键值相等的节点。
如下图所示:
这里主要分析下删除操作,(插入操作比较简单,这里暂不分析)
删除操作主要有以下几种情况
1.要删除的节点是一个叶子节点,直接使用她的父节点删除即可。
2.要删除的节点是只有左孩子节点,直接用当前要删除的节点的左孩子替换要删除的节点。
3.要删除的节点是只有右孩子节点,直接用当前要删除的节点的右孩子替换要删除的节点。
4.要删除的节点是既有左孩子,又有右孩子,
首先我们需要找到哪个值来覆盖当前要删除的节点,很明显,就是刚刚把她大的那个数。也就是她的直接中序后继节点,也就是当前节点的右子树中 值最小的节点,并且此中序后继节点一定不含子节点或者只含有一个右孩子
找到该节点以后把值赋给当前要删除的节点即可。并删除该直接中序后继节点 (如果没有子节点的话),如果有子节点 需要把他的右子节点移动到他的位置。
下面是源代码
class Node {
int data;
Node leftChild;
Node rightChild; public Node(int key) {
this.data = key;
}
} public class BST {
Node root; public void insert(int data) {
if (root == null) {
root = new Node(data);
return;
}
Node currentNode = root;
Node parentNode = root;
boolean isLeftChild = true;
while (currentNode != null) {
parentNode = currentNode;
if (data < currentNode.data) {
currentNode = currentNode.leftChild;
isLeftChild = true;
} else {
currentNode = currentNode.rightChild;
isLeftChild = false;
}
}
Node newNode = new Node(data);
if (isLeftChild) {
parentNode.leftChild = newNode;
} else {
parentNode.rightChild = newNode;
}
} public boolean delete(int data) {
// 首先先找到该节点
Node currentParentNode = root;
Node currentNode = root;
boolean isLeftChild = false; // 用来记录当前查找的节点是他父节点的左孩子还是右孩子
while (currentNode != null && currentNode.data != data) {
currentParentNode = currentNode;
if (data < currentNode.data) {
currentNode = currentNode.leftChild;
isLeftChild = true;
} else {
currentNode = currentNode.rightChild;
isLeftChild = false;
} }
if (currentNode == null) {
return false;
}
// System.out.println("p " + currentParentNode.data);
// System.out.println("c " + currentNode.data + "isLeft " + isLeftChild);
// 找到了该节点
if (currentNode.leftChild == null && currentNode.rightChild == null) {
if (isLeftChild) {
currentParentNode.leftChild = null;
} else {
currentParentNode.rightChild = null;
}
} else if (currentNode.leftChild != null && currentNode.rightChild == null) {
if (currentNode == root) {
root = currentNode;
} else if (isLeftChild) {
currentParentNode.leftChild = currentNode.leftChild;
} else {
currentParentNode.rightChild = currentNode.leftChild;
}
} else if (currentNode.leftChild == null && currentNode.rightChild != null) {
if (currentNode == root) {
root = currentNode;
} else if (isLeftChild) {
currentParentNode.leftChild = currentNode.rightChild;
} else {
currentParentNode.rightChild = currentNode.rightChild;
}
} else if (currentNode.leftChild != null && currentNode.rightChild != null) { // 先找到当前节点的直接中序后继节点
Node directPostNode = getDirectPostNode2(currentNode);
currentNode.data = directPostNode.data;
}
return true;
} private Node getDirectPostNode2(Node delNode) {
Node parentNode = delNode;// 用来保存待删除节点的直接后继节点的父亲节点
Node direcrPostNode = delNode;// 用来保存待删除节点的直接后继节点
Node temp = delNode.rightChild;
while (temp != null) {
parentNode = direcrPostNode;
direcrPostNode = temp;
temp = temp.leftChild;
}
// 删除该直接后继节点
if (direcrPostNode != parentNode.rightChild) {
parentNode.leftChild = direcrPostNode.rightChild;
direcrPostNode.rightChild = null;
} else {
parentNode.rightChild = null;
}
return direcrPostNode;
} public void inOrder(Node rootNode) {
if (rootNode != null) {
inOrder(rootNode.leftChild);
System.out.print(" " + rootNode.data);
inOrder(rootNode.rightChild);
}
} public static void main(String[] args) {
BST tree = new BST();
tree.insert(6);// 插入操作,构造图一所示的二叉树
tree.insert(3);
tree.insert(1);
tree.insert(14);
tree.insert(16);
tree.insert(10);
tree.insert(9);
tree.insert(13);
tree.insert(11);
tree.insert(12); tree.inOrder(tree.root);
System.out.println();
tree.delete(10);
tree.inOrder(tree.root);
}
}
总结:
BST效率 : 查找最好时间复杂度O(logN),最坏时间复杂度O(N)(BST退化成单支树结构)。
插入删除操作算法简单,时间复杂度与查找差不多
另外关于avl(平衡查找树)以rbt以及B-,b+tree
红黑树并不追求“完全平衡”——它只要求部分地达到平衡要求,降低了对旋转的要求,从而提高了性能。
红黑树能够以O(log2 n) 的时间复杂度进行搜索、插入、删除操作。此外,由于它的设计,任何不平衡都会在三次旋转之内解决。当然,还有一些更好的,但实现起来更复杂的数据结构,能够做到一步旋转之内达到平衡。但红黑树能够给我们一个比较“便宜”的解决方案。红黑树的算法时间复杂度和AVL相同,但统计性能比AVL树更高。大量数据实践证明,RBT的总体统计性能要好于平衡二叉树。AVL树更平衡一些,适合查找多的应用,红黑树插入删除更快一些
B-,b+tree 树大多用于数据库中,可以有效地降低磁盘读取次数
二叉搜索树(BST)的更多相关文章
- C++版 - 剑指offer 面试题24:二叉搜索树BST的后序遍历序列(的判断) 题解
剑指offer 面试题24:二叉搜索树的后序遍历序列(的判断) 题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则返回true.否则返回false.假设输入的数组的任意两个 ...
- 萌新笔记之二叉搜索树(BST)
前言,以前搞过线段树,二叉树觉得也就那样= =.然后数据结构的课也没怎么听过,然后下周期中考... 本来以为今天英语考完可以好好搞ACM了,然后这个数据结构期中考感觉会丢人,还是好好学习一波. 二叉搜 ...
- 给定一个二叉搜索树(BST),找到树中第 K 小的节点
问题:给定一个二叉搜索树(BST),找到树中第 K 小的节点. 出题人:阿里巴巴出题专家:文景/阿里云 CDN 资深技术专家. 考察点: 1. 基础数据结构的理解和编码能力 2. 递归使用 参考答案 ...
- 在二叉搜索树(BST)中查找第K个大的结点之非递归实现
一个被广泛使用的面试题: 给定一个二叉搜索树,请找出其中的第K个大的结点. PS:我第一次在面试的时候被问到这个问题而且让我直接在白纸上写的时候,直接蒙圈了,因为没有刷题准备,所以就会有伤害.(面完的 ...
- 二叉搜索树 (BST) 的创建以及遍历
二叉搜索树(Binary Search Tree) : 属于二叉树,其中每个节点都含有一个可以比较的键(如需要可以在键上关联值), 且每个节点的键都大于其左子树中的任意节点而小于右子树的任意节点的键. ...
- [LeetCode] Convert BST to Greater Tree 将二叉搜索树BST转为较大树
Given a Binary Search Tree (BST), convert it to a Greater Tree such that every key of the original B ...
- 二叉搜索树(BST)学习笔记
BST调了一天,最后遍历参数错了,没药救了-- 本文所有代码均使用数组+结构体,不使用指针! 前言--BFS是啥 BST 二叉搜索树是基于二叉树的一种树,一种特殊的二叉树. 二叉搜索树要么是一颗空树, ...
- 二叉搜索树(BST)
(第一段日常扯蛋,大家不要看)这几天就要回家了,osgearth暂时也不想弄了,毕竟不是几天就能弄出来的,所以打算过完年回来再弄.这几天闲着也是闲着,就掏出了之前买的算法导论看了看,把二叉搜索树实现了 ...
- hdu 3791:二叉搜索树(数据结构,二叉搜索树 BST)
二叉搜索树 Time Limit : 2000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other) Total Submiss ...
- 数据结构---二叉搜索树BST实现
1. 二叉查找树 二叉查找树(Binary Search Tree),也称为二叉搜索树.有序二叉树(ordered binary tree)或排序二叉树(sorted binary tree),是指一 ...
随机推荐
- cdnbest补充api
1.应用防火墙---防CC 添加|修改 请求地址: {api_dir}/firewall/anticc 请求方式: PUT 请求参数: frcquency string 触发频率 例:low(低) | ...
- python学习day4 数据类型 if语句
1.变量的内存管理 cpython解释器垃圾回收机制 什么是垃圾,当一个值身上没有绑定变量名时,(该值的引用计数=0时)就是一个垃圾 age=18 #18的引用计数=1 x=age #18的引用计数 ...
- 使用solr界面管理工具创建core 不能用的解决方法
可以用命令行进行创建 首先要先进入 solr所属的 用户 solr 中 ./solr create -c solr_sample 然后创建 你的core 显示以下信息 就创建成功了 成功之之后可以 ...
- python--第一天总结
[变量]1.变量定义的规则: 变量名只能是 字母.数字或下划线的任意组合 变量名的第一个字符不能是数字 以下关键字不能声明为变量名 ['and', 'as', 'assert', ' ...
- mysql 5.7.21 主从集群恢复GTID方式(不锁库)
从库损坏后,进行恢复 1.查看主加标记点 show master status\G 记录下POST的值 2.备注主库数据 mysqldump -u root -p -S /data/mysql/mys ...
- 弹出序列(python)
题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压 ...
- docker容器和镜像
这篇文章希望能够帮助读者深入理解Docker的命令,还有容器(container)和镜像(image)之间的区别,并深入探讨容器和运行中的容器之间的区别. 当我对Docker技术还是一知半解的时候,我 ...
- HDU-1257.最少拦截系统(基础DP)
本题大意:给出n和n个整数,让你求出其中不上升子序列的个数. 本题思路:用dp[ i ]保存第i个防御系统攻击的最低的导弹,遍历数组,遇到更低的导弹则更新最小值,否则新加一个系统用来防御,并且更新最小 ...
- 18. 4Sum (通用算法 nSum)
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = tar ...
- Appium+python自动化4-等待函数
4.1 等待函数癈使用 4.1.1 为什么要使用等待函数 我们在做自动化的时候很多时候都不是很顺利,不是因为app的问题,我们的脚本也没问题,但是很多时候都会报错,比如一个页面本来就有id为1的这个元 ...