数据结构理论篇(期末突击)

找往期文章包括但不限于本期文章中不懂的知识点:

个人主页:我要学编程(ಥ_ಥ)-CSDN博客

所属专栏: 学校课程突击

下面均是为了应付学校考试所用,如果有涉及部分知识点下面未说明,可以去我的数据结构专栏看看或者自行在网上查阅资料。 

以下所有知识均是阅读大话数据结构所得。如果有小伙伴对这本书也感兴趣,可以去看看。

通过百度网盘分享的文件:大话数据结构-目录版.rar
链接:https://pan.baidu.com/s/1ge7HSe00tvj1U1S2zWnA8w?pwd=2580 
提取码:2580

目录

树与二叉树章节相关

树与二叉树的转换

森林与二叉树的转换

树与森林的遍历

赫夫曼树(哈夫曼树)

图章节相关 

查找章节相关

数据结构的相关理解(记忆)

算法


树与二叉树章节相关

我们前面学习的树都是特殊的二叉树,且都是采用孩子双亲表示法,而下面要学习的二叉树采用的是 孩子兄弟表示法,第一个节点表示孩子,第二个节点表示当前节点的兄弟节点。

typedef struct Node {
    int val;                // 节点的值
    struct Node *child;     // 指向第一个子节点的指针
    struct Node *brother;   // 指向下一个兄弟节点的指针
} TreeNode;

树与二叉树的转换

一般的树都不是只有两个分叉的,而是存在多个分叉,但我们要想办法将多个分叉的树转换为二叉树就需要用到下面的方法:

1、加线。在同一层的相邻兄弟节点之间加上一根线,将其相连。

2、去线。若某个节点存在多个子节点, 将除第一个子节点之外的所有子节点之间的线全部去掉。

3、调整层次。

上述就是树转换为二叉树的过程。

二叉树转换为树,就是树转换为二叉树的逆过程。 

1、加线。若某个节点存在左子节点,且该子节点的右子节点不为空,则将父节点与该子节点的右子节点相连。

2、去线。将所有与右子节点的相连的线全部去掉。

3、调整层次。

森林与二叉树的转换

森林是由若干棵树组成的,所以完全可以理解为,森林中的每一棵树都是兄弟,可以按照兄弟的处理办法来操作。

1、先将森林中的每棵树都转为二叉树;

2、再以第一棵树作为基准,将后续的树全部使用。

上图转换为二叉树的过程。

二叉树转换为森林也是逆着来。但首先得判断这二叉树是转换成一棵树,还是森林。如果根结点存在右子树,那么这棵二叉树就可以转为森林;反之,则不能转为森林,就是直接转为树了。

1、先将森林分裂成多棵二叉树。将根结点与右子树之间的连线断开,继续从右子树为起点,重复上述步骤,直至右子树为空。

2、将分裂出的每棵子树,全部使用二叉树转换为树的方法去转换每棵树。

树与森林的遍历

树的遍历方式分为两种,一种是先根遍历树,即先访问树的根结点,然后依次先根遍历根的每棵子树。另一种是后根遍历,即先依次后根遍历每棵子树,然后再访问根结点。

树的先根遍历,就是二叉树的先序遍历,而树的后根遍历,就是二叉树的后序遍历。

如果直接看不出来的话,还有一种方法,将树先转为二叉树,然后再对二叉树进行相应的遍历即可。 将图中的树转为二叉树之后,再去遍历结果还是一样的。

森林的遍历也分为两种方式:一种是前序遍历:先访问森林中第一棵树的根结点,然后再依次先根遍历根的每棵子树,再依次用同样方式遍历除去第一棵树的剩余树构成的森林。

后序遍历:是先访问森林中第一棵树,后根遍历的方式遍历每棵子树,然后再访问根结点,再依次同样方式遍历除去第一棵树的剩余树构成的森林。

森林的前序遍历就是对每个树都进行先根遍历,同理后序遍历就是对每棵树都进行后序遍历。

同样如果直接看不出来的话,也可以先将森林转换为二叉树,然后再对二叉树进行先序遍历 与 中序遍历。这样得出的结果是一样的。  注意这里森林的后序遍历不是二叉树的后序遍历,而是中序遍历了。

注意:我们上面所说的树均不是二叉树,而是普通的树。只有当说是二叉树时,才表明这是二叉树。同样森林也不是由二叉树构成,而是由普通的树构成的。

赫夫曼树(哈夫曼树)

从树中一个结点到另一个结点之间的分支构成两个结点之间的路径,路径上的分支数目称做路径长度。树的路径长度就是从树根(根结点)到每一结点(叶子结点)的路径长度之和。针对带权路径来说,树的带权路径长度为树中所有叶子结点的带权路径长度之和。
假设有n个权值{W1,W2,...,Wn},构造一棵有n个叶子结点的二叉树,每个叶子结点带权Wk,每个叶子的路径长度为Ik,我们通常记作,则其中带权路径长度WPL最小的二叉树称做赫夫曼树。也被称为 哈夫曼树 与 最优二叉树。

考试中使用最多的就是去计算一棵树的带权路径长度。

那如何去构造一棵赫夫曼树呢?

1、将结点与权值绑定在一起。

2、找到结点权值最小的两个,连接在一起构造成一个新的结点(权值为两者之和)。

3、重复上述步骤,直至构造成一个完整的二叉树即可。

如下图所示:

注意:

1、将两个结点结合成一个新的结点时,下次再去找权值最小的两个结点就只能从结合的新结点与原来剩下的结点中去寻找。如果使用队列进行预处理的话,就是将队列中的两个权值最小的结点出队,然后再将结合的结点入队。

2、为了更好的处理,我们一般都会先将需要构造赫夫曼树的结点重新排序。上述图示只是为了更好的展示效果,实际的处理过程中,我们是使用优先级队列来处理的。

3、由于结点放置的左右顺序没有要求,因此最终所形成的赫夫曼树也是有不同的形状的,但是带权路径长度一定是最小的。

赫夫曼树构造出来之后,就可以求对应的加权路径长度,以及每个结点字符对应的赫夫曼编码了。

我们先来看赫夫曼树的加权路径长度(WPL)。其计算方法是将每个根结点到叶子结点的长度求出,然后乘上叶子结点的权值,最后将所有的结果相加就得到了WPL。

注意:为了做到不重不漏的计算出正确答案,我们最好是按照叶子结点从左到右的顺序来计算。 

在学习赫夫曼编码之前,我们先来了解一下什么是编码?以及为什么需要编码?

编码是将数据从一种形式转换为另一种形式。例如,二进制编码就可以将不属于二进制的数据转换为属于二进制的数据。编码的作用主要是为了更好的传输与存储。这里的哈夫曼编码就是为了更好的传输。

在现实生活中,数据的传输都是先转换为二进制数据,然后通过光信号或者电信号发生出去,最后接收方再通过同样的方式将接受的光信号或者电信号转换为对应的二进制,最终在转换为相应的原始数据。

在上述情况下,便诞生了赫夫曼编码 与 赫夫曼树。赫夫曼编码既不会产生前缀不唯一的情况,也不会出现冗余。 赫夫曼编码是通过赫夫曼树得到的。这里的权值是每次字符出现的次数。我们还是拿最上面的那个赫夫曼树来举例。

其实现在我们再去看赫夫曼树的构造过程,使用权值最小的结点开始构造这样最终形成的编码也是最长的,但是权值小意味着出现的频率小,也就占用的编码长度短,因此采用赫夫曼树构造出来的树的带权路径长度一定是最短的。 

注意:由于赫夫曼树的构造不止一种,因此对应字符的赫夫曼编码也是唯一的,但是带权路径长度一定是唯一且最短的。

除了上述构造赫夫曼树与对应的赫夫曼编码以及WPL之外,还常考的就是计算存储一段正文所需的二进制字节数(或者说存储这段正文所需的最小内存是多少)。

这种题目的思路是将对应字符出现的次数构造成一棵赫夫曼树,然后将对应字符的编码求出来,最后将编码长度乘以对应字符出现的次数整体求和就可以得到存储这段正文所需的内存,这里得到的是比特位的个数。

图章节相关 

深度优先遍历 与 广度优先遍历的区别:

深度优先遍历的思想体现在"深",当遍历到一个新的顶点时,不会继续往当前路径去遍历,而是直接沿着新顶点的路径去遍历剩下的顶点了。

广度优先遍历的思想体现在"广",当遍历到一个新的顶点时,会将该顶点相邻的所有顶点都尝试去遍历一遍。

普利姆算法 与 克鲁斯卡尔算法的区别:

普利姆算法是需要确定一个顶点,从该顶点出发,寻找局部权值最小的边(与已知顶点相连的边),直至构成最小生成树。

克鲁斯卡尔算法是在图中所有的边中,选取一个权值最小的边,因此并不需要确定顶点出发。

顶点的度:

在有向图中,顶点的度包括了出度与入度,而在无向图中顶点的图只需要看出度或者入度即可。

关键路径:

概念:在项目网络图中,关键路径是从项目开始到结束的最长序列(边权值和最大)。这个路径上的任务总持续时间最长。

求关键路径一般就是求其的序列,而求关键路径长度时,才会去求具体的边权和。

关键活动是指关键路径上的顶点。

若一个有向无环图的关键路径有几条时,当要求加快进度缩短工期时,应如何才能做到?必须同时提高几条关键路径上的活动。 

关键活动速度的提高在什么情况下才有效?在不改变关键路径路径的情况下才有效。

注意:关键路径只存在于有向无环图中。对于无向图或者有向成环图不存在这样的概念。

拓扑排序:

每次选入度为0的点,然后删除这个点和它的出边。接着继续在图中选择一个入度为0的点,并删除其出边,直至图中不存在点。

注意:拓扑排序只针对有向无环图才能生效,如果图中存在环,就不能使用拓扑排序或者说拓扑排序的结果不存在。

对上图进行拓扑排序:

1、选择入度为0的点: a;

2、删除a 与 其的出边(这里也可以认为是全部的边,因为其不存在入边);

3、从 b 与 c 中选择一个点即可,继续重复上述步骤。

最终拓扑排序的结果为(其中一种):a b c e d。

我们也可以看一下对于存在环的图是啥样的:

对上图进行拓扑排序:

1、选择入度为0的点: a;

2、删除a 与 其的出边(这里也可以认为是全部的边,因为其不存在入边);

3、c d e 都不满足入度为0的点,这个要求,因此没法继续拓扑排序了。

拓扑排序也常用来判断图中是否存在环。

查找章节相关

二叉搜索树: 

1、求在等概率情况下的查找成功的平均查找长度:

查找成功的情况只能出现在树中有节点存在的情况才行,而查找本质上就是遍历整棵树。对于第一层的结点来说,查找一次即可,对于第二层的结点来说查找两次即可,依次类推,对于第n层的结点查找成功的次数是n。对于查找成功的平均查找长度就是将这棵树的结点全部查找所需的次数,然后除以节点的个数,就是最终的结果。

上面这棵树查找成功的平均查找长度:ASL = (1*1 + 2*2 + 3*4 + 4*2 + 5*1) / 10 = 3

2、求在等概率情况下的查找不成功的平均查找长度:

查找不成功就是指不是树中存在,那怎么知道不在树中存在呢?当查找到空节点时,就证明查找失败了。查找不成功的平均长度就是空节点的查找次数之和除以空节点的个数。注意的是,对于处于第n层的空节点来说,查找的次数是 n-1,而不是n。ASL = (6*3 + 3*4 + 2*5) / 11 = 3.64(约为)

二分查找:

对于有序表(12 ,18 , 24 , 35 , 47, 50, 62, 83, 90 ,115,134),在等概率的情况下:

1)请画出折半查找树(判定树);

2)求采用折半查找法时成功和不成功的平均查找长度。

3)当用折半查找法查找90时需要进行多少次查找可以确定成功?

4)查找100时需要进行多少次查找才能确定不成功?

1、对于 折半查找树画法,是根据二分查找(折半查找)的顺序来的。将二分查找取的数,作为当前子树的根结点。左区间就作为左子树,右区间就作为右子树。

2、查找成功与不成功的平均查找长度和前面的二叉搜索树是一样的做法,都是计算树中节点的查找的次数之和 除以 节点的个数。

ASL不成功 =(4*3 + 8*4)/ 12 = 3.67          ASL成功 =(1*1 + 2*2 + 4*3 + 4*4)/ 11 = 3

3、4:当我们画出折半查找树之后,就可以直接对照树来进行判断了。

90 是属于第二层,那么查找的次数就是2次。

100 是属于 第四层的空节点,查找的次数为3次。 

哈希表:

设哈希(Hash)表的地址范围为0~17,哈希函数为:H(K)=K  MOD  16。K为关键字,用线性探测法再散列法处理冲突,输入关键字序列:(10,24,32,17,31,30,46,47,40,63,49)造出Hash表,试回答下列问题:

  1. 画出哈希表的示意图;
  2. 若查找关键字63,需要依次与哪些关键字进行比较?
  3. 若查找关键字60,需要依次与哪些关键字比较?
  4. 假定每个关键字的查找概率相等,求查找成功时的平均查找长度。

1、画出哈希表:根据映射函数 + 线性探测法,将哈希表的图给画出来即可:

2、查找63,就是先通过哈希映射函数将对应的下标求出来,key = 15,先查找到31,不对;继续往后找:46 47 32 17 63,一共找了6次。 

3、查找60,同样是通过哈希映射函数计算出下标,key = 12,查找到12的位置为空,就说明不存在这个元素,只需要比较一次。

4、计算平均查找长度就是将所有元素查找成功的次数之和 除以 元素的个数。哈希表中没有冲突的元素只需要查找一次,冲突的元素加上线性探测的次数即为最终的查找次数。

ASL= (6×1+2+3+3+3+6=6+2+3+3+3+6)/ 11 = 23 / 11 ≈ 2.09

数据结构的相关理解(记忆)

1、简述线性结构与非线性结构的不同点

答:线性结构反映结点间的逻辑关系是 一对一的,非线性结构反映结点间的逻辑关系是多对多的。

2、数据结构中讲述的结构主要有哪四种?这四种又分别属于哪二个大类?请分别给出这二类结构中你学了哪些结构?

答:

1)数据结构中的结构主要有以下四种:集合、线性表、树与图。

2)这四种又分别属于线性与非线二个大类,其中线性表属于线性结构,树与图属于非线性结构。

3)线性结构学了:线性表、栈、队列、串、数组

      非线性结构学了:树、图

3、一般来说,一个问题往往有多种不同的算法,我们如何评价这些算法的好坏并能从中得到较好的算法呢?

答:评价一个算法的好坏主要从二个方面进行:一个方面是时间,这个主要用时间复杂度来度量;另一个方面是空间,这个主要用空间复杂度不度量;考虑一个算法的优劣主要是从时间复杂度方面来考虑。

4、数据结构中的存储结构主要有哪二种?它们分别通过什么来实现?他们各有什么特点与优缺点?

答:

1)数据结构中的存储结构主要有静态结构动态结构

2)静态结构主要通过数组来实现,动态结构主要通过链表来实现;

3)静态结构的特点:逻辑上相邻的元素在存储上一定相邻;动态结构的特点:逻辑上相邻的元素在存储上不一定相邻

4)静态结构的优点:能随机访问,缺点是:插入删除要移动大量的元素;动态结构的优点:插入删除不需要移动元素,缺点是:不能随机访问元素

算法

// 一、使用C语言对链表进行排序
// 1、结构体的定义
typedef struct ListNode {
	int data;
	struct ListNode *next;
} ListNode, *List;

// 2、排序的主逻辑
void sort(List L) {
    // 如果链表为空,或者只有一个结点则无需排序
    if (L == NULL || L->next == NULL) {
        return;
    }

    ListNode *p, *q;
    // 外层循环
    for (p = L->next; p != NULL; p = p->next) {
        // 内层循环
        for (q = p->next; q != NULL; q = q->next) {
            // 如果数据较大,交换数据
            if (p->data > q->data) {
                int tmp = p->data;
                p->data = q->data;
                q->data = tmp;
            }
        }
    }
}

// 2、将两个集合合并
typedef struct list {
	ElemType *elem; // 集合元素
    int length; // 有效元素个数
    int listsize; // 集合的大小
}sqList

// 将 la 和 lb 线性表归并到 la
void mergelist_sq(sqlist &la, sqlist lb) {
    ElemType *pa, *pb, *pc, *pa_last, *pb_last;
    
    pa = la.elem;
    pb = lb.elem;
    
    pa_last = la.elem + la.length - 1;
    pb_last = lb.elem + lb.length - 1;
    
    // 合并后的表从 la 的末尾开始插入
    pc = pa_last + 1;

    // 归并 lb 到 la
    while (pb <= pb_last) {
        pa = la.elem;
        
        // 在 la 中查找是否有与 pb 相等的元素
        while (pa <= pa_last) {
            if (*pa == *pb) {
                break;
            }
            pa++;
        }
        
        // 如果 la 中没有相等的元素,则将 pb 插入 la
        if (pa > pa_last) {
            *pc++ = *pb;
            la.length++;
        }
        
        pb++;
    }
}

注意:使用 Hoare法、 挖坑法 对同一组序列进行快速排序时,最终排序的结果是一样的,但是中间排序的结果可能会不一样。

若一组记录的排序码为(46, 79, 56, 38, 40, 84),则利用快速排序的方法,以第一个记录为基准得到的一次划分结果为:() 

A、 38, 40, 46, 56, 79, 84

B、 40, 38, 46, 79, 56, 84

C、 40, 38, 46, 56, 79, 84

D、 40, 38, 46, 84, 56, 79

1、Hoare法版:

2、挖坑法版:

上图题目的答案是C,采取的挖坑法。

好啦!本期 数据结构理论篇(期末突击) 的学习之旅 就到此结束啦!我们下一期再一起学习吧!

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

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

相关文章

Kafka的rebalance机制

1、什么是 rebalance 机制 重平衡&#xff08;rebalance&#xff09;机制规定了如何让消费者组下的所有消费者来分配 topic 中的每一个分区。 2、rebalance 机制的触发条件是什么 &#xff08;1&#xff09;消费者组内成员变更 成员增加&#xff1a;当有新的消费者加入到消费…

人工智能之基于阿里云图像人脸融合部署

人工智能之基于阿里云图像人脸融合部署 需求描述 基于阿里云搭建图像人脸融合模型&#xff0c;模型名称&#xff1a;iic/cv_unet-image-face-fusion_damo使用上述模型输出人脸融合照片 模型路径&#xff1a;人脸融合 业务实现 阿里云配置 阿里云配置如下&#xff1a; SD…

如何利用无线路由器实现水泵房远程监测管理

水泵站广泛部署应用在工农业用水、防洪、排涝和抗旱减灾等方面&#xff0c;如果水泵站发生异常&#xff0c;往往会对生产生活造成诸多损失&#xff0c;甚至引发安全事故。因此&#xff0c;建立一套高效、可靠的泵站远程监测管理系统至关重要。 方案背景 目前&#xff0c;我国大…

Unity Canvas中显示粒子特效

首先在场景中新建一个粒子特效 修改一下参数 1.改变粒子特效的渲染层级,层级修改为UI层,由UI相机渲染 使用粒子特效的Sorting Layer ID和Order In Layer,Sorting Layer ID设置为UI(如果没有UI层则新建就好了),对UI进行排序 对于要显示在前的UI组件添加Canvas组件,设置O…

Spring Cloud Security集成JWT 快速入门Demo

一、介绍 JWT (JSON Web Token) 是一种带有绑实和信息的简单标准化机制&#xff0c;在信息通信中用于验证和信息传递。尤其在应用中使用Spring Cloud实现分布式构建时&#xff0c;JWT可以作为一种无状态验证原理的证明。 本文将进一步描述如何在Spring Cloud Security中集成JW…

逻辑数据模型设计过程包含哪些任务?

逻辑数据模型设计是数据库开发周期中的一个关键环节&#xff0c;它位于需求分析之后、物理数据模型设计之前。这一步骤的主要目标是构建一个准确反映业务需求、结构清晰且易于理解的数据模型。本文将深入探讨逻辑数据模型设计过程所包含的各项任务&#xff0c;结合理论与实践&a…

CAT3D: Create Anything in 3D with Multi-View Diffusion Models 论文解读

24年5月的论文&#xff0c;上一版就是ReconFusion 目录 一、概述 二、相关工作 1、2D先验 2、相机条件下的2D先验 3、多视角先验 4、视频先验 5、前馈方法 三、Method 1、多视角扩散模型 2、新视角生成 3、3D重建 一、概述 该论文提出一种CAT3D方法&#xff0c;实现…

GitHub 及 GitHub Desktop 详细使用教程(通俗易懂)

目录 Δ前言 一、Github教程 1.什么是Github&#xff1f; 2.仓库和对仓库的操作&#xff1a; 2.1 Repository&#xff08;仓库&#xff09; 2.2 Fork&#xff08;派生&#xff09; 2.3 Star&#xff08;收藏&#xff09; 2.4 Watch&#xff08;追番&#xff09; 2.5 Issue&am…

Shell-概述、脚本、变量、数值运算

概述 一、什么是shell 在 Linux 内核与用户之间的解释器程序 通常指 /bin/bash负责向内核翻译及传达用户/程序指令相当于操作系统的“外壳” 二、shell的使用方式 交互式 —— 命令行 ---人工干预、智能化程度高 ---逐条解释执行、效率低 非交互式 —— 脚本 ---需要提前…

刷机TP TP-Link-WDR5660【持续更新】

上文中简单介绍了&#xff1a;路由器刷机TP-Link tp-link-WDR5660 路由器升级宽带速度-CSDN博客 步骤如下&#xff1a; 第一步&#xff1a;安装Linux系统 本文使用virtualBox 安装Ubuntu的debian系统&#xff0c;本文不在讲述章 请自行参考&#xff1a;Kali 安装之腾讯云经…

信息科技伦理与道德1:研究方法

1 问题描述 1.1 讨论&#xff1f; 请挑一项信息技术&#xff0c;谈一谈为什么认为他是道德的/不道德的&#xff0c;或者根据使用场景才能判断是否道德。判断的依据是什么&#xff08;自身的道德准则&#xff09;&#xff1f;为什么你觉得你的道德准则是合理的&#xff0c;其他…

如何不修改模型参数来强化大语言模型 (LLM) 能力?

前言 如果你对这篇文章感兴趣&#xff0c;可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」&#xff0c;查看完整博客分类与对应链接。 大语言模型 (Large Language Model, LLM, e.g. ChatGPT) 的参数量少则几十亿&#xff0c;多则上千亿&#xff0c;对其的训…

css实现垂直文本

效果 知识 writing-mode: <value>; 可选值 horizontal-tb: 默认值。文本从左到右&#xff08;或从右到左&#xff09;排列&#xff0c;然后从上到下。vertical-rl: 文本从上到下排列&#xff0c;然后从右到左。适用于垂直书写的方向&#xff0c;如日语和中文。vertica…

【C++/控制台】扫雷

源代码&#xff1a; #include <windows.h> #include <conio.h> #include <stdio.h> int S, W 9, H 9, B 10, s, p 0, c 1, i, *m, *M, (*f)(int, int), *O; int edge(int x, int y) { return x < 0 || W < x || y < 0 || H < y; } void tm…

spring-boot启动源码分析(二)之SpringApplicationRunListener

在上一篇《spring-boot启动源码分析&#xff08;一&#xff09;之SpringApplication实例构造》后&#xff0c;继续看了一个月的Spring boot启动源码&#xff0c;初步把流程看完了&#xff0c;接下来会不断输出总结&#xff0c;以巩固这段时间的学习。同时也希望能帮到同样感兴趣…

计算机网络 (20)高速以太网

一、发展背景 随着计算机技术和网络应用的不断发展&#xff0c;传统的以太网速率已逐渐无法满足日益增长的带宽需求。因此&#xff0c;高速以太网应运而生&#xff0c;它以提高数据传输速率为主要目标&#xff0c;不断推动着以太网技术的发展。 二、技术特点 高速传输&#xff…

svn分支相关操作(小乌龟操作版)

在开发工作中进行分支开发&#xff0c;涉及新建分支&#xff0c;分支切换&#xff0c;合并分支等 新建远程分支 右键选择branch/tagert按钮 命名分支的路径名称 点击确定后远程分支就会生成一个当时命名的文件夹&#xff08;开发分支&#xff09; 分支切换 一般在开发阶段&a…

非关系型数据库和关系型数据库的区别

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

redux react-redux @reduxjs/toolkit

redux团队先后推出了redux、react-redux、reduxjs/toolkit&#xff0c;这三个库的api各有不同。本篇文章就来梳理一下当我们需要在项目中集成redux&#xff0c;从直接使用redux&#xff0c;到使用react-redux&#xff0c;再到react-redux和reduxjs/toolkit配合使用&#xff0c;…

【论文+源码】一个基于SSM(Spring + Spring MVC + MyBatis)的公寓电能计量系统

为了实现一个基于SSM&#xff08;Spring Spring MVC MyBatis&#xff09;的公寓电能计量系统&#xff0c;我们需要创建一个简单的Web应用程序来记录和显示每个公寓的电能使用情况。以下是一个基本的实现示例。 我们将包括以下几个部分&#xff1a; 数据库表设计实体类DAO层…