数据结构进阶(一)

2023-11-12

更多内容可以访问我的个人博客

1. 二叉查找树

参考:深入学习理解二叉搜索树(附详细讲解与实例分析)

1.1 基本概念

二叉查找树,也称二叉搜索树,或二叉排序树。其要么是一颗空树,要么就是具有如下性质的二叉树:

(1)若任意节点的左子树不空,则左子树上所有结点的值均不大于它的根结点的值;

(2)若任意节点的右子树不空,则右子树上所有结点的值均不小于它的根结点的值;

(3)任意节点的左、右子树也分别为二叉查找树;

在这里插入图片描述

1.2 基本操作

对于一棵二叉搜索树来说,它支持许多动态集合操作,包括**WALK(遍历)、SEARCH(查找)、MINIMUM(最小关键字)、MAXIMUM(最大关键字)、SUCCESSOR(后继)、PREDECESSOR(前驱)、INSERT(插入)、DELETE(删除)**等。下面将依次讲解这些操作。

1.2.1 Walk(遍历)

得益于二叉搜索树的性质,当使用中序遍历来访问一棵二叉搜索树上的所有结点时,最后得到的访问序列恰好是所有结点关键字的升序序列。

    /* 中序遍历 */
    void inOrder_Tree_Walk(BSTNode x)
    {
        if (x != NULL)
        {
            inOrder_Tree_Walk(x.lchild);
            System.out.println(x.getKey())
            inOrder_Tree_Walk(x.rchild);
        }
    }

树的先序遍历和后序遍历也类似。

1.2.2 Search(查找)

在二叉搜索树中查找一个具有给定关键字key的结点,需要输入一个指向树根的指针x和一个关键字k,如果这个结点存在,则TREE-SEARCH返回一个指向关键字为k的结点的指针;否则返回NULL。

具体查找过程为:
① 从树根开始查找,并沿着这棵树中的一条简单路径向下进行;
② 若树为空树,则查找失败,返回NULL;
③ 对于遇到的每个结点x,若关键字k等于结点x的关键字,查找终止,返回指向结点x的指针;
④ 若关键字k小于结点x的关键字,则查找在x的左子树中继续(根据二叉搜索树的性质,k此时不可能在右子树中);
⑤ 对称地,若关键字k大于结点x的关键字,则查找在x的右子树中继续(k此时不可能在左子树中);
⑥ 若查找至叶子结点后仍未匹配到相等的关键字,则关键字为k的结点不存在,返回NULL。

    /**
     * 查找(递归实现)
     * 输入:一个指向根节点的指针x,和待查找的关键字k
     * 输出:指向关键字为k的节点的指针(若存在,否则输出NULL)
     */
    BSTNode tree_Search(BSTNode x, double k)
    {
        if (x == NULL || k == x.getKey())       /* 如果找不着就返回NULL,找到了则返回对应节点的指针 */
            return x;
        if (k < x.getKey())                       /* 关键字小于当前节点的关键字,查找就在左子树中继续 */
            return tree_Search(x.lchild, k);
        else                                   /* 关键字大于当前节点的关键字,查找就在右子树中继续 */
            return tree_Search(x.rchild, k);
    }

或者不使用递归,采用迭代实现

    /**
     * 查找(迭代实现)
     * 输入:一个指向根节点的指针x,和待查找的关键字k
     * 输出:指向关键字为k的节点的指针(若存在,否则输出NIL)
     */
    BSTNode iterative_Tree_Search(BSTNode x, double k)
    {
        while (x != NULL && k != x.getKey())
        {
            if (k < x.getKey())               /* 关键字小于当前节点的关键字,查找就在左子树中继续 */
                x = x.lchild;
            else                           /* 关键字大于当前节点的关键字,查找就在右子树中继续 */
                x = x.rchild;
        }
        return x;                           /* 如果找不着就返回NULL,找到了则返回对应节点的指针 */
    }

二叉搜索树的查找的时间复杂度为O(h),其中h为二叉搜索树的高度。

1.2.3 Minimum(最小关键字)

根据二叉搜索树的性质,对于非叶子结点来说,其左子树的关键字总是不大于该结点的关键字。从一棵子树的树根开始,沿着lchild指针直到遇到一个NULL,我们总能在一棵二叉搜索树中找到一个指针,这个指针指向该子树中的最小元素。

查询二叉搜索树的最小关键字的时间复杂度为O(h),其中h为二叉搜索树的高度。

1.2.4 Maximum(最大关键字)

最大关键字的查询过程与最小关键字的十分类似。根据二叉搜索树的性质,对于非叶子结点来说,其右子树的关键字总是不小于该结点的关键字。从一棵子树的树根开始,沿着rchild指针直到遇到一个NULL,我们总能在一棵二叉搜索树中找到一个指针,这个指针指向该子树中的最大元素。

查询二叉搜索树的最大关键字的时间复杂度为O(h),其中h为二叉搜索树的高度。

1.2.5 Successor(后继)

给定一棵二叉搜索树中的一个结点,有时候需要按中序遍历的次序查找它的后继,即中序遍历顺序下的后面一位。一棵二叉搜索树的结构允许我们通过没有任何关键字的比较来确定一个结点的后继。如果后继存在,则返回指向结点x的后继的指针。倘若结点x的关键字是这棵树的最大关键字,则说明它没有后继了,返回NULL。

求后继的过程可以分以下两种情况讨论:

① 如果结点x的右子树非空,那么x的后继恰是x右子树中的最左结点(右子树中的最小关键字);

② 如果结点x的右子树为空,则有以下两种可能:

a. 结点x是其父结点的左孩子,则结点x的后继结点为它的父结点;

b. 结点x是其父结点的右孩子,则结点x的后继结点为x的最底层祖先,同时满足“这个最底层祖先的左孩子也是结点x的祖先”的条件。

举个例子:

在这里插入图片描述

对于情况①,假设我们要求结点5的后继。因为结点5的右子树非空,所以5的后继就是它的右子树中的最小关键字,即为6。

对于情况②a,假设我们要求结点2的后继。因为结点2的右子树为空,且结点2是其父结点3的左孩子,所以2的后继就是它的父结点,即为3。

对于情况②b,假设我们要求结点4的后继。因为结点4的右子树为空,且结点4是其父结点3的右孩子。此时我们要找的后继是4的最底层祖先,而且这个最底层祖先的左孩子也是结点4的祖先之一。我们可以这样看,首先结点4的祖先有3、5;按理说最底层结点应该是3。但是我们需要注意,这个最底层是有前提条件的。前提条件就是这个祖先要有左孩子,并且这个左孩子也是结点4的祖先之一。在祖先3、5中,有左孩子的有3和5,但是结点3左孩子2并不是结点4的祖先之一;结点5的左孩子3正是结点4的另一个祖先。因此,符合前提条件的最底层祖先为5。所以4的后继就是5。

1.2.6 Predecessor(前驱)

给定一棵二叉搜索树中的一个结点查找它的前驱的情况跟求后继的情况是对称的。一棵二叉搜索树的结构也允许我们通过没有任何关键字的比较来确定一个结点的前驱。如果前驱存在,则返回指向结点x的前驱的指针。倘若结点x的关键字是这棵树的最小关键字,则说明它没有前驱了,返回NULL。

求前驱的过程同样可以分以下两种情况讨论:

① 如果结点x的左子树非空,那么x的前驱恰是x左子树中的最右结点(左子树中的最大关键字);

② 如果结点x的左子树为空,则有以下两种可能:

a. 结点x是其父结点的右孩子,则结点x的前驱结点为它的父结点;
b. 结点x是其父结点的左孩子,则结点x的前驱结点为x的最底层祖先,同时满足“这个最底层祖先的右孩子也是结点x的祖先”的条件。

举个例子:

在这里插入图片描述

对于情况①,假设我们要求结点5的前驱。因为结点5的左子树非空,所以5的前驱就是它的左子树中的最大关键字,即为4。

对于情况②a,假设我们要求结点7的前驱。因为结点7的左子树为空,且结点4是其父结点3的右孩子,所以4的前驱就是它的父结点,即为3。

对于情况②b,假设我们要求结点6的前驱。因为结点6的左子树为空,且结点6是其父结点7的左孩子。此时我们要找的前驱是6的最底层祖先,而且这个最底层祖先的右孩子也是结点6的祖先之一。

我们可以这样看,首先结点6的祖先有7、5,;按理说最底层结点应该是7。但是我们需要注意,这个最底层是有前提条件的。前提条件就是这个祖先要有右孩子,并且这个右孩子也是结点17的祖先之一。在祖先7、5中,结点5的右孩子7正是结点6的另一个祖先。因此,符合前提条件的最底层祖先为5。所以6的前驱就是5。

1.2.7 Insert(插入)

插入操作会引起由二叉搜索树表示的动态集合的变化。我们需要修改数据结构来反映这个变化,但要保证修改后二叉搜索树的性质不被破坏。
插入的过程首先从树根开始遍历,沿树向下移动。指针x记录了一条向下的简单路径,并查找要替换的输入项z的NIL。同时,保持遍历指针y指向x的双亲。两个指针沿树向下移动时,通过比较当前结点x的关键字与待插入结点z的关键字大小,来决定向左或向右移动。直到x指向NIL时,这个NIL占据的位置就是输入项z要放置的位置。前面我们提到在x移动过程中还需要保持y指向x的父结点,原因是当我们找到可插入的NIL位置时,我们需要知道z属于哪个结点。

1.2.8 Delete(删除)

相对于插入操作,删除操作会更加复杂一些。从一棵二叉搜索树中删除某个特定结点z可以分为以下三种情况,其中前两种情况较为简单,最后一种情况则复杂一点。

如果z没有孩子结点,那么只是简单地将它删除,并修改它的父结点,用NIL作为孩子来替换z;

如果z只有一个孩子,那么将这个孩子提升到树中z的位置上,并修改z的父结点,用z的孩子来替换z;

如果z有两个孩子,那么找z的后继y,并让y占据树中z的位置。z的原来右子树部分成为y的新的右子树,z的原来左子树部分成为y新的左子树。这里要注意,z的后继y一定在z的右子树中,并且没有左孩子(详情见上文2.7前的证明)。利用z的后继y替换z,又细分为以下两种情况:

a. 如果y是z的右孩子,那么直接用y替换z,并保留y的右子树(y没有左子树);

在这里插入图片描述

b. 如果y不是z的右孩子,那么先用y的右孩子替换y(y没有左孩子),然后再用y替换z。

在这里插入图片描述


2. AVL树(二叉平衡树)

2.1 AVL树概述

参考:AVL树(一)之 图文解析 和 C语言的实现

AVL树是根据它的发明者G.M.Adelson-Velsky和E.M.Landis命名的。

上面介绍的二叉查找树在不断插入的情况下,有可能出现一侧不断生长,最后退化成线性结构的情形,查找插入等操作的效率就会退化为线性查找的效率。

而AVL树是最先发明的自平衡二叉查找树,也被称为高度平衡树。相比于"二叉查找树",它的特点是:AVL树中任何节点的两个子树的高度最大差别为1。

AVL树的查找、插入和删除在平均和最坏情况下都是O(logn)。

如果在AVL树中插入或删除节点后,使得高度之差大于1。此时,AVL树的平衡状态就被破坏,它就不再是一棵二叉树;为了让它重新维持在一个平衡状态,就需要对其进行旋转处理。学AVL树,重点的地方也就是它的旋转算法。

树的高度为最大层次。即空的二叉树的高度是0,非空树的高度等于它的最大层次(根的层次为1,根的子节点为第2层,依次类推)

2.2 AVL树失去平衡的四种情况

如果在AVL树中进行插入或删除节点后,可能导致AVL树失去平衡。这种失去平衡的可以概括为4种姿态:LL(左左),LR(左右),RR(右右)和RL(右左)

在这里插入图片描述

在这里插入图片描述

① LL:LeftLeft,也称为"左左"。插入或删除一个节点后,根节点的左子树的左子树还有非空子节点,导致"根的左子树的高度"比"根的右子树的高度"大2,导致AVL树失去了平衡。

例如,在上面LL情况中,由于"根节点(8)的左子树(4)的左子树(2)还有非空子节点",而"根节点(8)的右子树(12)没有子节点";导致"根节点(8)的左子树(4)高度"比"根节点(8)的右子树(12)"高2。

② LR:LeftRight,也称为"左右"。插入或删除一个节点后,根节点的左子树的右子树还有非空子节点,导致"根的左子树的高度"比"根的右子树的高度"大2,导致AVL树失去了平衡。

例如,在上面LR情况中,由于"根节点(8)的左子树(4)的左子树(6)还有非空子节点",而"根节点(8)的右子树(12)没有子节点";导致"根节点(8)的左子树(4)高度"比"根节点(8)的右子树(12)"高2。

RL:RightLeft,称为"右左"。插入或删除一个节点后,根节点的右子树的左子树还有非空子节点,导致"根的右子树的高度"比"根的左子树的高度"大2,导致AVL树失去了平衡。

例如,在上面RL情况中,由于"根节点(8)的右子树(12)的左子树(10)还有非空子节点",而"根节点(8)的左子树(4)没有子节点";导致"根节点(8)的右子树(12)高度"比"根节点(8)的左子树(4)"高2。

(4)RR:RightRight,称为"右右"。插入或删除一个节点后,根节点的右子树的右子树还有非空子节点,导致"根的右子树的高度"比"根的左子树的高度"大2,导致AVL树失去了平衡。

例如,在上面RR情况中,由于"根节点(8)的右子树(12)的右子树(14)还有非空子节点",而"根节点(8)的左子树(4)没有子节点";导致"根节点(8)的右子树(12)高度"比"根节点(8)的左子树(4)"高2。

2.3 AVL树的旋转
2.3.1 LL的旋转

在这里插入图片描述

图中左边是旋转之前的树,右边是旋转之后的树。从中可以发现,旋转之后的树又变成了AVL树,而且该旋转只需要一次即可完成。

k2结点不一定是整棵AVL树的根结点,而是开始失去平衡的那个根结点,至于k1则是高度过高的那棵子树的根结点。将k1变成根节点,k2变成k1的右子树,“k1的右子树"变成"k2的左子树”。

2.3.2 RR的旋转

在这里插入图片描述

图中左边是旋转之前的树,右边是旋转之后的树。RR旋转也只需要一次即可完成。

RR旋转操作即LL旋转的镜像操作。

2.3.3 LR的旋转

在这里插入图片描述

LR失去平衡的情况,需要经过两次旋转才能让AVL树恢复平衡。第一次旋转是围绕"k1"进行的"RR旋转",第二次是围绕"k3"进行的"LL旋转"。

2.3.4 RL的旋转

在这里插入图片描述

RL是LR的镜像操作。第一次旋转是围绕"k3"进行的"LL旋转",第二次是围绕"k1"进行的"RR旋转"。


3. B树、B+树和B*树

3.1 B树
3.1.1 概述

在现代计算机中通常采用分级存储系统,以最简单的二级分级存储策略为例,就是由内存储器与外存储器(磁盘)组成二级存储系统.这一策略的思想是:将最常用的数据副本存放于内存中,而大量的数据存放于外存中,借助有效的算法可以将外存的大存储量与内存高速度的优点结合起来

一般的,在分级存储系统中,各级存储器的速度有着巨大的差异,仍然以磁盘和内存为 例,前者的平均访问速度为 10ms左右,而内存储器的平均访问时间为ns级,通常在 10~100ns 左右,二者之间差异大约为 10的6次方.因此,为了节省一次外存储器的访问,我们宁愿多访问内存储器一百次,一千次甚至一万次. 当问题规模太大时,以至于内存储器无法容纳时,即使是前面介绍的 AVL 树,在时间上也会大打折扣。

B树是对二叉查找树的改进。它的设计思想是,将相关数据尽量集中在一起,以便一次读取多个数据,减少硬盘操作次数。B树为系统最优化大块数据的读和写操作。B树算法减少定位记录时所经历的中间过程,从而加快存取速度。普遍运用在数据库和文件系统。

假定一个节点可以容纳100个值,那么3层的B树可以容纳100万个数据,如果换成二叉查找树,则需要20层!假定操作系统一次读取一个节点,并且根节点保留在内存中,那么B树在100万个数据中查找目标值,只需要读取两次硬盘,相对于平衡二叉树,查询比较的次数可能没有减少,但是磁盘IO次数会大大减少。

3.1.2 B树的结构

所谓 m 阶B-树或为空树,或为满足下列特性的 m叉树:

① 树中每个结点至多有 m 棵子树;

② 若根结点不是叶子结点,则至少有两棵子树;

③ 除根结点之外的所有非终端结点至少有 ⎡m/2⎤ 棵子树;

④ 所有的非终端结点的结构为:(n , A0 , K1 , A1 , K2 , … , Kn , An) 其中: Ki(i=1,2,…,n)为关键字,且Ki<Ki+1,Ai为指向子树根结点的指针(i=0,1,…,n), 且指针A(i-1)所指子树中所有结点的关键字均小于Ki (i=1,2,…,n),An所指子树中所有结点的关键字均大于Kn,n为关键码的个数,⎡m/2⎤ −1≤ n ≤ m −1

⑤ 所有的叶子结点都出现在同一层次上,并且不带信息(可以看作是外部结点或查找 失败的结点,实际上这些结点不存在,指向这些结点的指针为空);

在这里插入图片描述

3.1.3 B树的查找操作

B-树的查找类似二叉排序树的查找,所不同的是B-树每个结点上是多关键码的有序表, 在到达某个结点时,先在有序表中查找,若找到,则查找成功;否则,到按照对应的指针信 息指向的子树中去查找,当到达叶子结点时,则说明树中没有对应的关键码,查找失败.即在 B-树上的查找过程是一个顺指针查找结点和在结点中查找关键码交叉进行的过程.

正如前面所指出的,B-树的查找适合于大规模的数据.实际的做法是**将大量数据组织为一棵 B-树,并存于外存储器,B-树的根结点常驻内存.**一旦需要查找,则按照上述过程, 首先将根结点作为当前结点,在当前结点中顺序查找;如果当前结点不存在需要查找的关键 字,则根据相应的引用,找到外存中的某一个下层结点,将其读入内存,作为新的当前结点继续查找.如此进行下去,直到找到相应关键字或查找失败.

由此可见,**在B-树中进行查找所需的时间,无外乎两类操作的时间消耗:一种是在 B-树上找结点,即将外存中的结点读入内存;另一种是,在结点中找关键字.**在前面曾经提 到,内外存储器的平均访问时间存在巨大的差异,所以在这两部分时间中,前者必然是主要部分,后一部分时间则可以忽略.因此,B-树的查找效率取决于外存的访问次数.

由推导可知,对于具有N个关键字的m阶B-树的每次查找操作,都可以在Ο(logm N)时间内完成.

3.1.4 B树的插入操作

为了在 m 阶B-树中插入一个新关键字 key,首先要找到该关键字应该插入的位置,该过程实际是在B-树中查找关键字的过程.倘若查找成功,则不再插入重复的关键字,若查找不成功,则在此查找过程中遇到的最后一个非叶子结点p,即为关键字 key 的插入位置.然后,在结点 p 中,按照关键字有序的顺序将 key 插入.若插入后结点 p 上关键字个数不超过 m−1个,则可直接插入到该结点上;否则,要进行调整,即结点的“分裂”.

分裂操作按如下规则进行:

① 假设结点 p 中已有 m-1 个关键字,当插入一个关键字之后,结点中包含的信息为:(m , A0 , K1 , A1 , K2 , … , Km , Am)

② 此时,可以将结点 p 分裂为两个结点 u和v,其中结点 u 包含的信息为 (⎡m/2⎤ −1 , A0 , K1 , A1 , … , K⎡m/2⎤ −1 , A⎡m/2⎤ −1)结点 v 中包含的信息为(m− ⎡m/2⎤ , A⎡m/2⎤ , K⎡m/2⎤+1 , A⎡m/2⎤+1 , … , Km , Am)

③ 而关键字K⎡m/2⎤则插入到p的父结点中去.如果p的父结点不存在(已经到根结点),则新建一个只包含关键字 K⎡m/2⎤的结点

④ 如果p的父结点关键字个数由于关键字K⎡m/2⎤的插入而超过m−1,则分裂过程继续下去,直到p的某个祖先结点g,在插入关键字后g的关键字个数不超过m−1.

◆ 举例如下所示5阶B-树:

① 插入7

在这里插入图片描述

② 插入 3

在这里插入图片描述

③ 插入 38

在这里插入图片描述

3.1.5 B树的删除操作

与插入关键字相反,若在 B-树上删除一个关键字,则首先应该找到该关键字所在的结点u,并从中删除。B-树的删除操作可以分为以下三种情况:

一、若待删关键字所在结点并非最下层的非终端结点

假设待删关键字为Ki,此时,可以用Ai所指子树中的最小关键字X替代,然后问题转换成了删除关键字X,若关键字X仍不是最下层的非终端结点,则继续向下,直到问题转换为删除最下层结点。

二、 若该结点 u 为最下层的非终端结点,且其中关键字的数目不少于 ⎡m/2⎤

直接删除即可。

三、 若该结点 u 为最下层的非终端结点,且其中关键字的数目少于 ⎡m/2⎤(即关键字数目为⎡m/2⎤-1)

在u中删除关键字后需要进行“合并”结点的操作。

“合并”操作可以分成以下三种情况分别进行处理:

① 结点 u 的左兄弟 v 包含至少 ⎡m/2⎤ 个关键字

如下图所示,可以从结点v中取出最大的关键字kmax,将u的父结点p中介于v 和u之间的关键字kmid替换为kmax,然后将kmid插至u的最左侧.(即从结点u中删除一个关键字之后,从左兄弟取出最右关键字放入父节点,将父节点关键字放入结点u)

在这里插入图片描述

② 结点 u 的右兄弟 v 包含至少 ⎡m/2⎤ 个关键字

与第一种情况类似,如下图所示,可以从结点v中取出最小的关键字kmin,将u的父结点p中介于v 和u之间的关键字kmid替换为kmin,然后将kmid插至u的最右侧.

在这里插入图片描述

③ 结点 u 没有一个兄弟包含至少 ⎡m/2⎤ 个关键字

此时,结点u和其相邻的兄弟结点中的关键字数目均等于 ⎡m/2⎤ −1,但是结点u至少会有一个兄弟结点.如下图所示,设u有右兄弟v,这时可以取出父结点p中介于u,v之间 的关键字kmid,然后将kmid与u,v中关键字合并为一个结点.

在这里插入图片描述

综合以上三种情况,在“合并”结点之后,结点 u 的父结点中关键字有可能会减少,若“合并”操作之后,父结点关键字数目小于 ⎡m/2⎤ −1,则需要对父结点进行修复(即对父节点进行以上的合并操作),该过程一直进行下去,直到 u 的某个祖先结点 g,g 的关键字数目不少于 ⎡m/2⎤ −1,或直到根结点为止.


3.2 B+树

B+树是B-树的变体,也是一种多路搜索树,其定义基本与B树相同,除了:

① 非叶子结点的子树指针与关键字个数相同;

非叶子结点的子树指针P[i],指向关键字值属于(K[i], K[i+1])的子树(B-树是开区间);

③ 为所有叶子结点增加一个链指针;

所有关键字都在叶子结点出现;

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据结构进阶(一) 的相关文章

随机推荐

  • linux shell 数字等于怎么判断

    在 Linux shell 中可以使用等号 来判断一个变量是否等于某个数字 举个例子 如果要判断变量 x 是否等于 5 可以使用以下代码 if x eq 5 then echo x is equal to 5 else echo x is
  • 数据挖掘-可挖掘的数据类型

    可挖掘的数据类型 1 数据库数据 数据库系统 也成数据库管理系统 DBMS 由一组内部相关的数据 称作数据库 和一组管理和存取数据的软件程序组成 关系数据库是表的汇集 每个表都被赋予一个唯一的名字 每个表都包含一组属性 列或字段 并且通常存
  • 【Linux】用户和权限

    文章目录 前言 什么是 root 用户 su 命令和 exit 命令 sudo 命令 为普通用户配置 sudo 认证 用户 用户组管理 什么是Linux 用户和用户组 用户组管理 用户管理 创建用户 删除用户 查看用户所属组 将指定用户添加
  • SOCK_RAW PF_PACKET IPv6带物理地址发送报文

    通过link layer发送IPv4 IPv6 例子如下 http www pdbuchan com rawsock rawsock html 发送ipv4 http www pdbuchan com rawsock tcp4 ll c 发
  • onedrive的多电脑同步妙用

    序言 很多时候 一些问题与想法 必须要有多个设备的背景 概述 通过两台电脑的日常使用思考 展现OneDrive这一同步利器 以及OneDrive的理念与意义 正文 背景 三月份由于一些原因 入手了一个主机 原来的笔记本一下子变成了键盘托 想
  • svn在idea中的使用

    idea在使用svn之前需要对svn进行一下设置 svn默认是需要你去指定客户机自己安装的svn客户端 但这要求我们当初安装时需要将安装svn的 exe那个程序选上 一般大家安装时都不会安装 idea默认集成的也有svn 我们只要简单设置一
  • 6.带你入门matlab 协方差和相关系数( matlab程序)

    1 简述 协方差 V cov X V cov X flag 同上 X为矩阵 相关系数 R corr X X为矩阵 协方差和相关系数函数的使用如下 代码及运行结果 协方差 clear all X1 rand 1 5 c1 cov X1 方差
  • 常用的文件操作命令-重定向-管道符-笔记

    文件操作命令 mkdir 文件名 创建目录 mkdir 文件名 文件名 连续创建目录 mkdir p 文件名 文件名 递归创建目录 touch 文件 创建文件 rm rf 强制且不提醒删除文件 rmdir 删除目录 mv 文件名 新文件名
  • 解决Debian 11系统缺少无线网卡固件rtl8192cfw.bin

    解决Debian 11系统缺少无线网卡固件rtl8192cfw bin 一 先简单介绍解决办法 rtlwifi rtl8192cfw bin 是无线网卡的固件 其实缺少它网卡也是可以用的 只是不知道是不是这个原因导致丢包频繁 在CSDN找到
  • java 前缀树的实现,敏感词的匹配和标记

    目录 一 前缀树的介绍和定义 1 前缀树的定义 2 前缀树的结构 二 前缀树的实现 1 向前缀树中增加词语 2 向前缀树中删除词语 3 对于使用前缀树进行词语标识 4 前缀树的实现代码 三 前缀树使用及测试 1 向前缀树上增加词语 2 根据
  • 【计算机视觉

    文章目录 一 检测相关 13篇 1 1 Polygon Intersection over Union Loss for Viewpoint Agnostic Monocular 3D Vehicle Detection 1 2 Radar
  • c++ 和cuda混合编程 VS2015 C++ 调用 cuda

    1 新建一个C 项目 2 右键添加一个cuda C C file 3 添加下面 lib 库 右键项目 gt 属性 gt 链接器 gt 输入 gt 附加依赖项目 cudart static lib kernel32 lib user32 li
  • S3C2440之PWM

    include uart h include stdlib h MS延时 void delay unsigned int time unsigned int i j for i 0 i
  • python通过ssl加密连接mysql

    目录 1 django程序的配置 2 pymysql连接数据库 3 DBUtils数据库连接池连接配置 我们在连接某些数据库时 需要提供ssl证书 如果是IT的数据库 那么可能会提供下载 如果是自己想做 可参考如下步骤 https dev
  • 基于Docker搭建Redis7.0主从哨兵集群高可用模式

    Docker搭建Redis主从哨兵模式 本文基于docker compose Redis7 0版本搭建Redis1主2从3哨兵高可用集群 不同版本redis配置文件略有差异 请参考官方文档Github地址与Redis官网地址 如下图可以看出
  • 微信怎么发匿名消息 微信发匿名消息方法【详解】

    很多小伙伴加了微信好友后 有些话难以说出口 想给对方发送一些匿名消息 掩盖自己的身份 保护个人隐私 这要怎么做呢 小编今天就为大家支个招 轻松搞定匿名消息设置方法 赶紧来看看吧 微信怎么发匿名消息 1 打开微信 搜索 匿名的信 点击进入匿名
  • 评测:对接GPT-4的NewBing使用体验变化

    GPT 4是OpenAI发布的最新一代语言模型 于2023年3月14日正式发布 并通过API和ChatGPT Plus平台向用户开放 微软也证实 在GPT 4正式发布之前 就已经在部分版本的Bing中使用GPT 4技术 本文旨在对使用GPT
  • 华为OD机试真题 Java 实现【寻找符合要求的最长子串】【2023Q1 200分】

    一 题目描述 给定一个字符串 s 找出这样一个子串 该子串中的任意一个字符最多出现2次 该子串不包含指定某个字符 请你找出满足该条件的最长子串的长度 二 输入描述 第一行为要求不包含的指定字符 为单个字符 取值范围 0 9a zA Z 第二
  • 在ubuntu上安装qt

    1 登录VM 上网下载Qt 保存路径一般在下载文件夹 可以下载后放到自定义文件夹 2 下载完成后 cd到保存文件的文件夹 并执行命令 sudo chmod a x qt opensource linux x64 5 9 run 将文件改变成
  • 数据结构进阶(一)

    更多内容可以访问我的个人博客 1 二叉查找树 参考 深入学习理解二叉搜索树 附详细讲解与实例分析 1 1 基本概念 二叉查找树 也称二叉搜索树 或二叉排序树 其要么是一颗空树 要么就是具有如下性质的二叉树 1 若任意节点的左子树不空 则左子