当前位置:网站首页>二叉排序树
二叉排序树
2022-06-11 23:37:00 【跑马去追XX】
二叉排序树
先看一个需求
给你一个数列 (7, 3, 10, 12, 5, 1, 9),要求能够高效的完成对数据的查询和添加
解决方案分析
使用数组
数组未排序,
优点:直接在数组尾添加,速度快。 缺点:查找速度慢. [示意图]
数组排序,优点:可以使用二分查找,查找速度快,缺点:为了保证数组有序,在添加新数据时,找到插入位 置后,后面的数据需整体移动,速度慢。[示意图]
使用链式存储-链表 不管链表是否有序,查找速度都慢,添加数据速度比数组快,不需要数据整体移动。[示意图]
使用二叉排序树
二叉排序树介绍
二叉排序树:BST: (Binary Sort(Search) Tree), 对于二叉排序树的任何一个非叶子节点,要求左子节点的值比当前节点的值小,右子节点的值比当前节点的值大.
特别说明:如果有相同的值,可以将该节点放在左子节点或右子节点,比如针对前面的数据 (7, 3, 10, 12, 5, 1, 9) ,对应的二叉排序树为:
二叉排序树创建和遍历
一个数组创建成对应的二叉排序树,并使用中序遍历二叉排序树,比如: 数组为 Array(7, 3, 10, 12, 5, 1, 9) ,创建成对应的二叉排序树为 :
二叉排序树的删除
二叉排序树的删除情况比较复杂,有下面三种情况需要考虑
- 删除叶子节点 (比如:2, 5, 9, 12)
- 删除只有一颗子树的节点 (比如:1)
- 删除有两颗子树的节点. (比如:7, 3,10 )
- 操作的思路分析

对删除结点的各种情况的思路分析:
第一种情况: 删除叶子节点 (比如:2, 5, 9, 12)
思路 (1) 需求先去找到要删除的结点 targetNode
(2) 找到 targetNode 的 父结点 parent
(3) 确定 targetNode 是 parent 的左子结点 还是右子结点
(4) 根据前面的情况来对应删除 左子结点 parent.left = null 右子结点 parent.right = null;
第二种情况: 删除只有一颗子树的节点 比如 1
思路 (1) 需求先去找到要删除的结点 targetNode
(2) 找到 targetNode 的 父结点 parent
(3) 确定 targetNode 的子结点是左子结点还是右子结点
(4) targetNode 是 parent 的左子结点还是右子结点
(5) 如果 targetNode 有左子结点
5.1 如果 targetNode 是 parent 的左子结点
parent.left = targetNode.left;
5.2 如果 targetNode 是 parent 的右子结点 parent.right = targetNode.left;
(6) 如果 targetNode 有右子结点
6.1 如果 targetNode 是 parent 的左子结点 parent.left = targetNode.right;
6.2 如果 targetNode 是 parent 的右子结点 parent.right = targetNode.right
情况三 : 删除有两颗子树的节点. (比如:7, 3,10 )
思路 (1) 需求先去找到要删除的结点 targetNode
(2) 找到 targetNode 的 父结点 parent
(3) 从 targetNode 的右子树找到最小的结点
(4) 用一个临时变量,将 最小结点的值保存 temp = 11
(5) 删除该最小结点 (6) targetNode.value = temp
或
从 targetNode 的左子树找到最大的结点,用一个临时变量,将最大结点的值保存 temp = 11,删除该最大结点,targetNode.value = temp
二叉排序树删除结点的代码实现:
package com.iflytek.binarysortTree;
public class BinarySortTreeDemo {
public static void main(String[] args) {
int[] arr = {
7, 3, 10, 12, 5, 1, 9, 2};
BinarySortTree binarySortTree = new BinarySortTree();
//循环的添加结点到二叉排序树
for (int i = 0; i < arr.length; i++) {
binarySortTree.add(new Node(arr[i]));
}
//中序遍历二叉排序树 System.out.println("中序遍历二叉排序树~");
binarySortTree.infixOrder(); // 1, 3, 5, 7, 9, 10, 12
//测试一下删除叶子结点
binarySortTree.delNode(12);
binarySortTree.delNode(5);
binarySortTree.delNode(10);
binarySortTree.delNode(2);
binarySortTree.delNode(3);
binarySortTree.delNode(9);
binarySortTree.delNode(1);
binarySortTree.delNode(7);
System.out.println("root=" + binarySortTree.getRoot());
System.out.println("删除节点后");
binarySortTree.infixOrder();
}
}
//创建二叉排序树
class BinarySortTree {
private Node root;
public Node getRoot() {
return root;
}
//查找要删除的结点
public Node search(int value) {
if (root == null) {
return null;
} else {
return root.search(value);
}
}
//查找父结点
public Node searchParent(int value) {
if (root == null) {
return null;
} else {
return root.searchParent(value);
}
}
//编写方法:
// 1. 返回的 以 node 为根结点的二叉排序树的右子节点的最小结点的值
// 2. 删除 node 为根结点的二叉排序树的最小结点
public int delRightTreeMin(Node node) {
Node target = node;
//循环的查找左子节点,就会找到最小值
while (target.left != null) {
target = target.left;
}
//这时 target 就指向了最小结点
// 删除最小结点
delNode(target.value);
return target.value;
}
public void delNode(int value) {
if (root == null) {
return;
} else {
//1.需求先去找到要删除的结点 targetNode
Node targetNode = search(value);
//如果没有找到要删除的结点
if (targetNode == null) {
return;
}
//如果我们发现当前这颗二叉排序树只有一个结点
if (root.left == null && root.right == null) {
root = null;
return;
}
//去找到 targetNode 的父结点
Node parent = searchParent(value);
//如果要删除的结点是叶子结点
if (targetNode.right == null && targetNode.left == null) {
//判断 targetNode 是父结点的左子结点,还是右子结点
if (parent.left != null && parent.left.value == value) {
//是左子结点
parent.left = null;
} else if (parent.right != null && parent.right.value == value) {
//是右子结点
parent.right = null;
}
} else if (targetNode.left != null && targetNode.right != null) {
//删除有两颗子树的节点
int minVal = delRightTreeMin(targetNode.right);
targetNode.value = minVal;
} else {
// 删除只有一颗子树的结点
//如果要删除的结点有左子结点
if (targetNode.left != null) {
if (parent != null) {
// 只有两个节点时,删除要注意一点
//如果 targetNode 是 parent 的左子结点
if (parent.left.value == value) {
parent.left = targetNode.left;
} else {
// targetNode 是 parent 的右子结点
parent.right = targetNode.left;
}
} else {
root = targetNode.left;
}
} else {
//如果要删除的结点有右子结点
if (parent != null) {
//如果 targetNode 是 parent 的左子结点
if (parent.left.value == value) {
parent.left = targetNode.right;
} else {
//如果 targetNode 是 parent 的右子结点
parent.right = targetNode.right;
}
} else {
root = targetNode.right;
}
}
}
}
}
//添加结点的方法
public void add(Node node) {
if (root == null) {
root = node;//如果 root 为空则直接让 root 指向 node
} else {
root.add(node);
}
}
//中序遍历
public void infixOrder() {
if (root != null) {
root.infixOrder();
} else {
System.out.println("二叉排序树不能为空");
}
}
}
//创建Node 结点
class Node {
int value;
Node left;
Node right;
public Node(int value) {
this.value = value;
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
'}';
}
//查找要删除的结点
/** * @param value 希望要删除的值 * @return 如果找到返回该结点,否则返回 null */
public Node search(int value) {
if (this.value == value) {
return this;
} else if (value < this.value) {
if (this.left == null) {
return null;
}
return this.left.search(value);
} else {
if (this.right == null) {
return null;
}
return this.right.search(value);
}
}
//查找要删除结点的父结点
/** * @param value 要找到的结点的值 * @return 返回的是要删除的结点的父结点,如果没有就返回 null */
public Node searchParent(int value) {
//如果当前结点就是要删除的结点的父结点,就返回
//程序是从左往右执行的,必须先判断子节点不为空,然后才能比较值
if ((this.left != null && this.left.value == value) ||
(this.right != null && this.right.value == value)) {
return this;
} else {
//如果查找的值小于当前结点的值, 并且当前结点的左子结点不为空
if (this.value > value && this.left != null) {
return this.left.searchParent(value);//向左子树递归查找
} else if (this.value <= value && this.right != null) {
return this.right.searchParent(value);//向右子树递归查找
} else {
return null;// 没有找到父结点
}
}
}
//添加结点的方法
// 递归的形式添加结点,注意需要满足二叉排序树的要求
public void add(Node node) {
if (node == null) {
return;
}
//判断传入的结点的值,和当前子树的根结点的值关系
if (node.value < this.value) {
//添加的结点的值小于 当前结点的值
//如果当前结点左子结点为 null
if (this.left == null) {
this.left = node;
} else {
//递归的向左子树添加
this.left.add(node);
}
} else {
//添加的结点的值大于 当前结点的值
if (this.right == null) {
this.right = node;
} else {
//递归的向右子树添加
this.right.add(node);
}
}
}
public void infixOrder() {
if (this.left != null) {
this.left.infixOrder();
}
System.out.println(this);
if (this.right != null) {
this.right.infixOrder();
}
}
}
课后练习:完成老师代码,并使用第二种方式来解决
如果我们从左子树找到最大的结点,然后前面的思路完成.
边栏推荐
- Here we go! Dragon lizard community enters PKU classroom
- VS code 编写汇编代码【微机原理】
- Implementation scheme of iteration and combination pattern for general tree structure
- Beginner JS BOM implementation window centered
- Procédures d'introduction et d'installation de sonarqube
- Postgresql10 process
- 2022 safety officer-b certificate theoretical question bank and simulation test
- QR code
- Lake Shore—SuperTran-VP 连续流低温恒温器系统
- Fonctionnement de la plate - forme d'examen de simulation pour les agents de sécurité - Questions d'examen de certificat a en 2022
猜你喜欢

On the knowledge points of cookie attributes and the differences between webstorage and cookies?

2022 operation of simulation examination platform for safety officer C certificate

2022年起重机司机(限桥式起重机)考试题模拟考试题库及模拟考试

2022安全员-C证判断题模拟考试平台操作

Pad printing process flow and application precautions
![[day3 literature intensive reading] Oriental time and space interaction in tau and kappa effects](/img/90/4470dca9b19dbcd0f99655f7d9d23e.png)
[day3 literature intensive reading] Oriental time and space interaction in tau and kappa effects
![[day4 literature intensive reading] space – time interdependence: evidence against Asymmetric mapping between time and space](/img/ce/f3817690a024cfebcf58a5ccc3cfdc.png)
[day4 literature intensive reading] space – time interdependence: evidence against Asymmetric mapping between time and space

Beginner JS BOM implementation window centered

解决IDEA下载插件慢的问题

Zigbee3.0 wireless packet capturing installation method based on e18-2g4u04b
随机推荐
2022年安全员-A证考题模拟考试平台操作
(linear DP) acwing 898 Number triangle
[Day9 literature extensive reading] on the (a) symmetry between the perception of time and space in large-scale environments
2022年安全员-A证考题模拟考试平台操作
Single page pull-down refresh and double page pull-down refresh of MUI
[day3 literature intensive reading] Oriental time and space interaction in tau and kappa effects
MySQL 8.0 解压版安装教程
[day4 literature intensive reading] space – time interdependence: evidence against Asymmetric mapping between time and space
Introduction and installation steps of sonarqube
Lake Shore - supervaritemp low temperature thermostat
CD process
One to one correspondence of multiple schematic diagrams and PCB diagrams under Altium designer project
Queue (C language)
2022 high place installation, maintenance and removal of simulated examination platform for operation certificate examination question bank
Figure overview of neural network
Les produits antigéniques entrent dans la famille et les entreprises chinoises de dispositifs médicaux accueillent un nouvel océan bleu
机器学习之数据处理与可视化【鸢尾花数据分类|特征属性比较】
MySQL 8.0 decompressed version installation tutorial
I2C read / write process
Unity3d C#开发微信小游戏音频/音效播放问题解决过程分享