二叉搜索树 , Set 和 Map (JAVA)

news/2024/10/29 5:31:04/

二叉搜索树

二叉搜索树又称二叉排序树,它具有以下性质的二叉树空树:

  1. 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
  2. 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
  3. 它的每颗子树也分别为二叉搜索树

二叉搜索树的插入非常简单:

  1. 从根节点开始比较,如果大于根节点就遍历右子树,小于根节点就遍历左子树
  2. 对所有的子树都进行如上操作
  3. 直到遍历到空节点,将待插入元素插入此空节点
public class BinarySearchTree {public static class TreeNode {public int key;public TreeNode left;public TreeNode right;TreeNode(int key) {this.key = key;}}public TreeNode root;/*** 插入一个元素*/public boolean insert(int key) {TreeNode tmp = new TreeNode(key);if (this.root == null) {this.root = tmp;return true;}TreeNode privat = this.root;TreeNode p1 = this.root;while (p1 != null) {privat = p1;if (p1.key > key) {p1 = p1.left;}else {p1 = p1.right;}}if (privat.key > key) {privat.left = tmp;}else {privat.right = tmp;}return true;}
}

二叉搜索树的查找:

  1. 从根节点开始比较,如果大于根节点就遍历右子树,小于根节点就遍历左子树
  2. 对所有的子树都进行如上操作
    //查找key是否存在public TreeNode search(int key) {if (this.root == null){return null;}TreeNode tmp = this.root;while (tmp != null) {if (tmp.key > key) {tmp = tmp.left;}else if (tmp.key < key) {tmp = tmp.right;}else {return tmp;}}return null;}

二叉搜索树的删除比较复杂因为要保证删除之后的树依旧是一颗二叉搜索树

二叉搜索树的删除:

分两种情况:

  • 左树或者右树为空
  1. 当待删除节点左树为空就令待删除节点的双亲指向其右子树
  2. 当待删除节点右树为空就令待删除节点的双亲指向其左子树

  • 左右子树都不为空
  1. 找到右(左)子树最左(右)端的节点
  2. 交换两个结点的值
  3. 删除该节点

    //删除key的值public boolean remove(int key) {if (this.root == null) {return false;}TreeNode tmp = this.root;TreeNode privat = tmp;while (tmp != null) {if (tmp.key > key) {privat = tmp;tmp = tmp.left;}else if (tmp.key < key) {privat = tmp;tmp = tmp.right;}else {break;}}if (tmp == null) {return false;}//左树或者右树为空if (tmp.left == null || tmp.right == null) {if (tmp.left == null) {if (tmp == this.root) {this.root = tmp.right;}else {if (privat.left == tmp) {privat.left = tmp.right;}else {privat.right = tmp.right;}}}else {if (tmp == this.root) {this.root = tmp.left;}else {if (privat.left == tmp) {privat.left = tmp.left;}else {privat.right = tmp.left;}}}}else {//左右子树都不为空TreeNode a = tmp.right;while(a.left != null) {privat = a;a = a.left;}tmp.key = a.key;if (privat.left == a) {privat.left = a.right;}else {privat.right = a.right;}}return true;}

Set 和 Map

Map和set是一种专门用来进行搜索的容器或者数据结构,其搜索的效率与其具体的实例化子类有关。
一般把搜索的数据称为关键字(Key),和关键字对应的称为(Value),将其称之为Key-value的键值对。


两种模型:

  • 纯 key 模型:

             有一个英文词典,快速查找一个单词是否在词典中快速查找某个名字在不在通讯录中

  • Key-Value 模型:

             统计文件中每个单词出现的次数,统计结果是每个单词都有与其对应的次数:<单词,单词出现的次数>

Map.Entry

Map.Entry<K, V> 是Map内部实现的用来存放<key, value>键值对映射关系的内部类
里面有这几种方法:

方法解释
K getKey()返回 entry 中的 key
V getValue()返回 entry 中的 value
V setValue(V value)将键值对中的value替换为指定value

Map

  • Map是一个接口,不能直接实例化对象,如果要实例化对象只能实例化其实现类TreeMap或者HashMap
  • Map中存放键值对的Key是唯一的,value是可以重复的
  • TreeMap中插入键值对时,key不能为空,否则就会抛NullPointerException异常,value可以为空。但是HashMap的key和value都可以为空
  • Map中的Key可以全部分离出来,存储到Set中来进行访问(因为Key不能重复)。
  • Map中的value可以全部分离出来,存储在Collection的任何一个子集合中(value可能有重复)。
  • Map中键值对的Key不能直接修改value可以修改,如果要修改key,只能先将该key删除掉,然后再来进行重新插入。
     
    public static void main(String[] args) {Map<Integer,Integer> map = new HashMap<>();Map<Integer,Integer> map1 = new TreeMap<>();}
Map底层结构TreeMapHashMap
底层结构红黑树哈希桶
插入/删除/查找时间
复杂度
O(\log_{2}N)O(1)
是否有序关于Key有序无序
线程安全不安全不安全
插入/删除/查找区别需要进行元素比较通过哈希函数计算哈希地址
比较与覆写key必须能够比较,否则会抛出
ClassCastException异常
自定义类型需要覆写equals和
hashCode方法
应用场景需要Key有序场景下Key是否有序不关心,需要更高的
时间性能

方法解释
V get(Object key)返回 key 对应的 value
V getOrDefault(Object key, V defaultValue)返回 key 对应的 value,key 不存在,返回默认值
V put(K key, V value)设置 key 对应的 value
V remove(Object key)删除 key 对应的映射关系
Set<K> keySet()返回所有 key 的不重复集合
Collection<V> values()返回所有 value 的可重复集合
Set<Map.Entry<K, V>> entrySet()返回所有的 key-value 映射关系
boolean containsKey(Object key)判断是否包含 key
boolean containsValue(Object value)判断是否包含 value

Set

  • Set是继承自Collection的一个接口类
  • Set中只存储了key,并且要求key一定要唯一
  • TreeSet的底层是使用Map来实现的,其使用key与Object的一个默认对象作为键值对插入到Map中的
  • Set最大的功能就是对集合中的元素进行去重
  • 实现Set接口的常用类有TreeSet和HashSet,还有一个LinkedHashSet,LinkedHashSet是在HashSet的基础上维护了一个双向链表来记录元素的插入次序。
  • Set中的Key不能修改,如果要修改,先将原来的删除掉,然后再重新插入
  • TreeSet中不能插入null的key,HashSet可以
Set底层结构TreeSetHashSet
底层结构红黑树哈希桶
插入/删除/查找时间
复杂度
O(\log_{2}N)O(1)
是否有序Key有序不一定有序
线程安全不安全不安全
插入/删除/查找区别按照红黑树的特性来进行插入和删除

1. 先计算key哈希地址

2. 然后进行插入和删除

比较与覆写key必须能够比较,否则会抛出
ClassCastException异常
自定义类型需要覆写equals和
hashCode方法
应用场景需要Key有序场景下Key是否有序不关心,需要更高的
时间性能

http://www.ppmy.cn/news/1134480.html

相关文章

腾讯云南京服务器性能如何?南京服务器测速IP地址

腾讯云服务器南京地域怎么样&#xff1f;南京地域很不错&#xff0c;正好处于中间的位置&#xff0c;南方北方用户均可以选择&#xff0c;网络延迟更低速度更快&#xff0c;并且目前南京地域有活动&#xff0c;南京地域可用区可选南京一区、南京二区和南京三区&#xff0c;腾讯…

【力扣】买卖股票(121,122,123)

121. 买卖股票的最佳时机 题意 只能买卖股票各一次求最大收益 解法 动态规划 要求最值&#xff0c;肯定要穷举。而穷举主要有两种方法&#xff1a;动态规划 和 回溯。 这道题显然可以使用动态规划的算法来解决&#xff0c;因为这里有一个很明显的子问题&#xff1a;前 i …

C++ 实现运算符重载

代码&#xff1a; #include <iostream> #include <cstring>using namespace std;class myString { private:char *str; //记录c风格的字符串int size; //记录字符串的实际长度 public://无参构造myString():size(10){str new char[size]; …

记录使用vue-test-utils + jest 在uniapp中进行单元测试

目录 前情安装依赖package.json配置jest配置测试文件目录编写setup.js编写第一个测试文件jest.fn()和jest.spyOn()jest 解析scss失败测试vuex$refs定时器测试函数调用n次手动调用生命周期处理其他模块导入的函数测试插槽 前情 uniapp推荐了测试方案dcloudio/uni-automator&…

tcp拥塞控制原理

18.3 拥塞控制 我们在向对端发送数据时&#xff0c;并不是一股脑子任意发送&#xff0c;因为TCP建立连接后&#xff0c;就是建立了一根管道&#xff0c;这跟管道上&#xff0c;实际上有很多的工作设备&#xff0c;比如路由器和交换机等等&#xff0c;他们都会对接收到的TCP包进…

文件管理:极速复制粘贴,畅享无限次文件管理!

亲爱的用户&#xff0c;您是否经常需要将文件夹里的所有文件进行无限次复制粘贴&#xff0c;但又觉得这个过程繁琐而耗时&#xff1f;现在&#xff0c;我们为您推出一款极速文件管理工具&#xff0c;让您可以轻松实现无限次的文件复制粘贴&#xff0c;让文件管理更加高效畅快&a…

Ajax异步请求(不等待,继续执行)

案例&#xff1a; 1、问题&#xff1a; 以下代码中&#xff0c;if 和 else里面都有以下两句话&#xff0c;能不能把这两句话放在else之后执行&#xff1f; //关闭对话框 this.dialogFormVisible false; //刷新数据 this.list(); save() {//修改和新增显示的是同一个表单,点…