数据结构与算法(C语言版)P9---哈夫曼树

news2024/11/26 12:53:03

1、哈夫曼树的基本概念

(1)路径:从树中一个结点到另一个结点之间的__分支__构成这两个结点间的路径。

(2)__结点的路径长度:__两结点间路径上的分支树。

练习:计算下面二叉树结点之间的路径长度

在这里插入图片描述

从结点A到D结点的路径长度为2,原因:A—>C,C—>D。

从C结点到H结点的路径长度为3.原因:C—>E,E—>G,G—>H。

从A到B,C,D,E,F,G,H,I的路径长度分别为1,1,,2,2,3,3,4,4。

(3)__树的路径长度:__从树根到每个结点的路径长度之和。记作:TL。

练习:计算下列二叉树的树路径长度

在这里插入图片描述

TL(a):0+1+1+2+2+3+3+4+4=20

TL(b):0+1+1+2+2+2+2+3+3=16

结点数目相同的二叉树中,完全二叉树是路径长度最短的二叉树,但路径最短的不一定是完全二叉树。

(4)权(weight):将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。

(5)__结点的带权路径长度:__从__跟__结点到该结点之间的__路径长度__与该结点的权的乘积。

(6)__树的带权路径长度:__树中所有叶子节点的带权路径长度之和。

​ 记作:

在这里插入图片描述

__练习一:__有4个结点a,b,c,d。权值分别为7,5,2,4。构造以此4个结点为叶子节点的二叉树如下,现要求求此树的带权路径长度。

在这里插入图片描述

结算结果:WPL= 7*2 + 5*2 + 2*2 + 4*2 = 14+10+4+8 = 36。

所以此树的带权路径长度为 36。

__练习二:__求下列树的带权路径长度

WPL = 4*2 + 2*1 + 7*3 + 3*5 = 8+2+21+15 = 46。

在这里插入图片描述

2、一句话总结哈夫曼树

哈夫曼树就是__最优树,也就是__带权路径长度(WPL)最短的树。

但是有个地方需要注意一下:

【注】:“带权路径长度最短”是在“度相同”的树中比较而得的结果,因此有最优二叉树、最优三叉树之称等等。

所以:最优二叉树,就是带权路径长度(WPL)最短的二叉树。

因为构造这种树的算法是由哈夫曼教授与1952年提出的,所以被称为__哈夫曼树__,相应的算法称为哈夫曼算法。

参考如下图,可以总结哈夫曼树的几个特点:

在这里插入图片描述

哈夫曼树的特性:

  • 满二叉树不一定是哈夫曼树。
  • 哈夫曼树中权越大的叶子结点离根越近。
  • 具有相同带权结点的哈夫曼树不唯一。

3、哈夫曼树的构造算法

在上面发现,哈夫曼树中权越大的叶子离根越近。

那我们可以先选择权值小的叶子节点,那最后剩下的就是权值的结点了。

这也是__贪心算法__:构造哈夫曼树时首先选择权值小的叶子结点。

【重点如下】:

哈夫曼算法:

  • 首先根据n个特定的权值{w1,w2,w3,…,wn}构成n棵二叉树的森林,F={T1,T2,…,Tn},其中Ti只有一个带权为wi的根节点。(简单来说就是:森林里面由n个树,每个树里面只有一个结点,就是根结点。每个根节点对应的权值,就是我们给的。)

    这一步可以总结为:构造森林全是根。

  • 在F中选取两颗根节点的权值最小的树作为左右子树,构造一棵新的二叉树,且设置新的二叉树的根节点的权值为其左右子树上根节点的权值之和。

    这一步可以总结为:选用两小造新树。

  • 在森林(F)中删除这两棵树,同时将新得到的二叉树加入森林中。

    这一步可以总结为:删除两小添新人。

  • 最后重复第二、三步骤,直到森林中只有一棵树为止,这棵树即为哈夫曼树。

口诀:1、构造森林全是根;2、选用两小造新树。

​ 3、删除两小添新人;4、重复2、3剩新书。

下面我们来看个例子:

3.1、示例一:求哈夫曼树

__示例一:__由4个结点a,b,c,d权值分别为7,5,2,4。要求构造哈夫曼树。

(1)构造森林全是根,结果为:

在这里插入图片描述

(2)选用两小造新树,结果为:

将C,D结点作为左右子树,并且此左右子树的根节点是左右子树权值之和。

在这里插入图片描述

(3)删除两小添新人。由于结点C,D已经使用了,所以在现在的森林,是如下图:

在这里插入图片描述

重复第二、三步骤。

首先第二步:由于现在新的根节点权值为6,那再从森林中单独的根结点中选出权值最小的一个,然后和权值为6的根节点作为新的左右子树即可,如下:

在这里插入图片描述

第三步:现在的森林,如下:

在这里插入图片描述

再重复第二步骤。

首先第二步:由于现在新的根节点权值为11,那再从森林中单独的根结点中选出权值最小的一个,然后和权值为11的根节点作为新的左右子树即可,如下:

在这里插入图片描述

最后发现森林中树只有一个根结点了,所以哈夫曼树构造完毕。

可以发现:

  • 哈夫曼树中4个带权值的结点都是叶子结点。

  • 哈夫曼树的结点度数只能为0或2,没有度为1的结点。

  • n个叶子节点的哈夫曼树共有2n-1个结点。

    原因:

    ​ 包含n棵树的森林要经过n-1次合并才能形成哈夫曼树,共产生n-1个新节点。那咋加上原来n个叶子 节点,一共就是2n-1个结点。

    ​ 并且度为0的结点是n个,度为2的结点是n-1个。

3.2、示例二:求哈夫曼树

__示例二:__有5个结点a,b,c,d,e;权值分别为7,5,5,2,4。要求构造哈夫曼树。

(1)构造森林全是根:将每个结点作为单独的树,所以说每个数只有一个结点就是根节点,并且这些由单节点构 成的树组成森林。

在这里插入图片描述

(2)选用两小造新树:在这里插入图片描述

(3)删除两小添新人:

在这里插入图片描述

重复2,3步…

首先是第二步:选用两小造新树

【重点】:我们说第二步要求的是:再森林F中__选取两颗根节点的权值最小的树作为左右子树__

现在那两个结点权值最小呢?就是结点b,c,所以新的左右子树就是b,c结点构成的。这是个要注意的地方,不能把b结点或者c结点和权值为6的结点进行结合成为新的左右子树。

那结果为:

在这里插入图片描述

第三步:删除两小添新人

在这里插入图片描述

再重复2,3步…

第二步:选用两小造新树

现在根节点有3个,分别是权重为6,7,10的结点,那需要权值最小的两个结点结合构成新的左右子树,那就是权值为6,7进行结合。

在这里插入图片描述

第三步:删除两小添新人

在这里插入图片描述

那到最后就只剩下两个根节点了,那就让它们成为新的左右子树:

在这里插入图片描述

3.3、总结

这里再总结一下:

  • 在哈夫曼树中,初始时有n棵二叉树,要经过n-1次合并最终形成哈夫曼树。
  • 经过n-1次合并产生n-1个新节点,且这个n-1个新节点都是具有两个孩子的分支节点,也就是度为2结点。
  • 可见:哈夫曼树中共有n+n-1=2n-1个结点,且其所有的分支节点的度军部为1,要么为0要么为2。

4、哈夫曼树算法实现

首先哈夫曼树可以使用顺序存储结构,也可以使用链式存储结构。

这里采用顺序存储结构————一维数组,相对来说简单一些。

首先来看结构体定义:

typedef struct
{
    int weight;         //权重值
    int parent,lch,rch;          //双亲结点,左右孩子下标
}HTNode,*HuffmanTree;

如下图表格所示:

在这里插入图片描述

4.1、看图分析

例,有n=8(有8个根节点),权值为W={7,19,2,6,32,3,21,10}

有8个结点,所以最终构成的哈夫曼树共有2*8 - 1= 15个结点。那这里创建一个从016的数组,但是下标为0的数组不用,从下标为1为止开始存储,115。

(1)构造结点全是根:由于每个结点在其所在的树中就是根结点,接没有双亲结点,有没有孩子结点,所以在初 始化中将其值全部初始化为0。

​ 如下表格:

在这里插入图片描述

(2)选用两小造新树,

经过循环找到权重最小的两个结点,下标分别为:3,6。

造新树如下:

在这里插入图片描述

然后我们把权值为5的结点,存储到数组下表为9处。并且,下标为3,6的结点有双亲结点了,所以,需要在下标3,6的parent处填入双亲结点的下标9。并且双亲结点有左右子树了,所以还需要在下表为9处的lch,rch处填入左右子树的下标,如下图:

在这里插入图片描述

下面的就重复以上过程即可…

最终结果如下图:

在这里插入图片描述
在这里插入图片描述

4.2、具体代码实现

初始化部分:

  • 初始化HT[1,2,3,…,2n-1]:lch=rch=parent=0;
  • 输入初始化n个叶子节点:置HT[1…n]的weight值。

进行合并:

  • 进行以下n-1次合并,依次产生n-1个结点HT[i],i=n+1/n+2/n+3/…/2n-1。
    • a)在HT[1…i-1]中选两个__未被选过__(从parent==0的结点中选)的weight最小的两个结点HT[s1]和HT[s2],s1、s2为最小结点下标;
    • b)修改HT[s1]和HT[s2]的parent值:HT[s1].parent = i;HT[s2].parent=i;
    • c)修改新产生的HT[i]:
      • 权值修改:HT[i].weight = HT[s1].weigth+HT[s2].weight;
      • 左右子树修改:HT[i].lch=s1;HT[i].rch=s2;

代码展示:

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>

typedef struct
{
    int weight;         //权重值
    int parent, lch, rch;          //双亲结点,左右孩子下标
}HTNode, *HuffmanTree;

//筛选出最小和次最小权值的结点
void Select(HuffmanTree* HT, int n, int* s1, int* s2)
{
    ;
}

//构建哈夫曼树
void CreateHuffmanTree(HuffmanTree HT, int n)
{
    int m = 2 * n - 1;         //数组一共2n-1个元素

    if (n <= 1)     
    {
        return;
    }
    //一共2n-1个结点,但是下标为0的置空不用,所以需要2n个结点,而m+1=2n;
    HT = (HuffmanTree)malloc(sizeof(HTNode) * m+1);          
    for (int i = 1; i <= m; i++)         //将2n-1个元素的lch,rch,parent置为0
    {
        HT[i].lch = 0;
        HT[i].rch = 0;
        HT[i].parent = 0;
    }
    for (int i = 1; i <= n; i++)
    {
        //输入前n个元素的weight值
        scanf("%d",&HT[i].weight);
    }
    //以上为初始化结束。
    
    //下面开始构造哈夫曼树
    //合并产生n-1个结点
    for (int i = n + 1; i <= m; i++)    //n+1是新产生结点的起始下标,m是新产生结点的结束下标
    {
        int s1 = 0;
        int s2 = 0;
        //在HT[k](1<=k<=i-1)中选择两个其双亲域为0,且权值最小的结点,并返回它们在HT中的序号s1,s2。
        Select(HT, i - 1, &s1, &s2);

        //表示从F中删除s1,s2
        HT[s1].parent = i;
        HT[s2].parent = i;

        //s1,s2分别作为i的左右孩子
        HT[i].lch = s1;
        HT[i].rch = s2;

        //i的权值为左右孩子权值之和
        HT[i].weight = HT[s1].weight + HT[s2].weight;
    }
}

int main()
{
    HuffmanTree HT = NULL;
    CreateHuffmanTree(HT, 3);
	return 0;
}

5、哈夫曼树应用

5.1、哈夫曼编码算法概念

5.1.1、哈夫曼编码思想

在远程通讯中,要将待传字符换成由二进制的字符串

设要传送的字符为:ABACCDA

若编码为:

​ A——00

​ B——01

​ C——10

​ D——11

所以传输字符ABACCDA就转换为传输为00010010101100,当对方接收到数据后,再根据相应的规则进行解码就行了。

这种叫做__定长编码方式。__

但是这种编码方式有个缺陷,就是,比较浪费空间。

但是若将编码设计为长度不等的二进制编码,即让代转字符串中__出现次数较多的字符采用尽可能短的编码__,则转码的二进制字符串便可能减少。

这种叫做__长度不等编码方式。__

就比如上面举的例子,要传输字符:ABACCDA。可以看到A,C是出现较多的字符,所以现将编码这样规定:

​ A——0

​ B——00

​ C——1

​ D——01

那ABACCDA就转换为000011010。

那我们来对比下:00010010101100(定长编码)和000011010(长度不等编码方式)的长度可以发现,确实后者可以减少空间浪费。

但是__长度不等编码方式__也有个缺陷,就是会造成重码的现象。

什么是重码呢?来解释下,就比如刚才我们使用长度不等编码方式将ABACCDA转为了000011010。我们来看000011010的前四位为是0,那前四个0组成的字符就会有多种情况:

在这里插入图片描述

那到底代表那种字符呢?不知道,所以说这样就会造成错误。

为什么会造成重码呢?是因为一个字符是另一个字符的编码的前缀。比如:A代表0,B代表00,A就是B的编码的前缀。所以造成了重码!

那我们要如何设计长度不等编码呢?

可以这样:要设计长度不等的编码,则必须使任一字符的编码都不是另一个字符的编码的前缀。

这种编码称做:前缀编码。

那前缀编码怎么设计呢?就可以用哈夫曼编码进行设计。

所以当有问题:什么样的前缀编码能使得电文总长最短?答:哈夫曼编码。

5.1.2、如何实现哈夫曼编码

1、统计字符集中每个字符在电文中出现的平均概率(出现字符概率越大,要求编码越短)。

2、利用哈夫曼树的特点:权越大的叶子离根越近;__将每个字符的概率值作为权值,构造哈夫曼树。__则概率越大的结点,路径越短。

3、在哈夫曼树的每个分支上标上0或1:

​ 结点的__左分支标为0,右分支标1;__

​ 把从根到每个叶子的路径上的标号连接起来,作为该叶子代表的__字符的编码。__

看概念苦涩难懂,我们来看个案例:

要传输的字符集D={C,A,S,T,;}

字符出现频率	W={2,4,2,3,3}       //这里的频率就是哈夫曼树的权值

根据字符频率(权值)我们可以写出此哈夫曼树,并且所有的左子树标为1,右子树变为0。如下图:

在这里插入图片描述

那我们从根节点出发到每一个叶子节点路过的所有分支的数字构成的数字符,我们就做为这个字符的字符编码。

如下字符集D的编码:

  • T——00
  • ;——01
  • A——10
  • C——110
  • S——111

如上各字符的编码就叫做哈夫曼编码。

那好,既然学会了哈夫曼编码,那看个示例,写出此电文的哈夫曼编码{CAS;CAT;SAT;AT}。

那根据上面各字符的哈夫曼编码,我们可以写出此电文的哈夫曼编码:11010111011101000011111000011000

反之,若编码是“1101000”,则其译文是:CAT。

5.1.3、哈夫曼编码的两个问题及两个性质

1、为什么哈夫曼编码能够保证是前缀编码?

答:

因为没有一片树叶是另一片树叶的祖先,所以每个叶节点的编码就不可能是其它叶节点编码的前缀。

如下图:

在这里插入图片描述

2、为什么哈夫曼编码能够保证字符编码总长最短?

答:

因为哈夫曼树的树带权路径长度最短,故字符编码的总长最短。

性质一:哈夫曼编码是前缀码。

性质二:哈夫曼编码是最优前缀码。

练习,设组成电文的字符集D及其概率分布W为:

D={A,B,C,D,E,F,G}

W={0.40,0.30,0.15,0.05,0.04,0.03,0.03}

请设计其哈夫曼编码。

这里直接写结果了:

  • 首先得到哈夫曼树

    在这里插入图片描述

  • 并且此哈夫曼树抽象出来的逻辑关系,如下图:

    在这里插入图片描述

  • 将左分支标记为0,右分支标记为1,从而得到哈夫曼编码:

    在这里插入图片描述

将从根节点到叶子结点路径上的数字符串联起来,就得到哈夫曼编码:

  • A——0
  • B——11
  • C——101
  • D——10011
  • E——10010
  • F——10001
  • G——10000

5.2、哈夫曼编码算法实现

5.2.1、过程分析

要想实现哈夫曼编码算法,前提必须先实现哈夫曼树算法。

哈夫曼算法抽象出来就是如下表格(使用上面一题的哈夫曼树表格):

在这里插入图片描述

在这里插入图片描述

要想找到每个结点的哈夫曼编码,最主要的就是把从根节点到每个结点分支给标记出来:左分支标记为0,右分支标记为1。

想要实现如此算法,从__哈夫曼树尾部__开始是比较简单的。

下面我们就要找到:

  • G结点到根节点之间每个分支的数字字符(0|1),然后再将此数字字符串联起来即可。
  • F结点到根节点之间每个分支的数字字符(0|1),然后再将此数字字符串联起来即可。
  • E结点到根节点之间每个分支的数字字符(0|1),然后再将此数字字符串联起来即可。
  • D结点到根节点之间每个分支的数字字符(0|1),然后再将此数字字符串联起来即可。

这里演示一下——G结点到根节点之间每个分支是如何标记的。

过程如下:

(1)找到G结点,找到G结点中parent域值,这就相当于找到了G结点的双亲结点,然后再根据此双亲结点中的lch或者rch域,来匹配G结点的下标,如果lch匹配到了,说明G结点就是此双亲结点的左子树,那就将此左子树标记为0;如果rch匹配到了,说明G结点是此双亲结点的右子树,那就将此右子树标记为1。

接下来继续寻找

(2)现在只知道G结点和G结点的双亲结点的存储位置,而且G结点所在的分支已经标记过了,那现在就要标记G结点的双亲结点的分支(0.06这个结点),还是一样的步骤,先找0.06这个结点的partent域值,这就相当于找到了0.06结点的双亲结点,然后再根据此双亲结点中的lch或者rch域,来匹配0.06结点的下标,发现是左子树,所以做分支标记为0。

就这样一直查找、标记;查找、标记…

直到查找到根节点A,就会得到G结点的哈夫曼编码为:00001

【注意】:这里我们找到G结点的哈夫曼编码是00001它和正确的哈夫曼编码正好相反。正确G结点的哈夫曼编码应该为:10000。为什么呢?起始原因很简单:因为我们是倒着从尾部的叶子节点G开始查找的。所以哈夫曼编码正好和正确的相反。

那这样就找倒了G结点的哈夫曼编码。

然后再依次找F,E,D,…结点的哈夫曼编码,最后别忘记再将此哈夫曼编码倒过来。

那我们可以发现,需要找几次哈夫曼编码呢?

答案:有几个结点就找几次哈夫曼编码。

所以这个for循环即可。

但是如果要是问某个结点需要找几次双亲才能找出此结点的哈夫曼编码,这个是不确定的,因为每个结点到根节点的路径长度不一样。所以使用while(f!=0)即可,使用f表示parent的值,如果f!=0就执行,否则就找到了根节点。

那如何存储每个结点的哈夫曼编码呢?

我们可以使用二维数组,实现一个字符串数组,数组中有n个元素(n个元素对应每个结点)每个元素中是字符串,此字符串就是某个结点的哈夫曼编码。

在这里插入图片描述

但是还需要考虑个问题,就是我们需要将得到的哈夫曼编码给倒过来才行,那这就要求先将每个分支的数字字符给存起来,然后再遍历正确存储倒上面二维数组中取。

这里再使用一个字符数组来存储:
在这里插入图片描述

那这个数组的长度是多少呢?n个结点最高也就n-1层,所以数组的长度为n-1

5.2.2、代码实现

6、文件的编码和解码

1、编码:

  • 输入各字符及其权值。
  • 构造哈夫曼树——HT[i]。
  • 进行哈夫曼编码——HC[i]。
  • 查找HC[i],得到各字符的哈夫曼编码。

2、解码:

  • 构造哈夫曼树。
  • 依次读入二进制码。
  • 读入0,则走向左孩子;读入1,则走向右孩子。
  • 一旦到达某__叶子结点__,即可译出字符。
  • 然后再从根出发继续译码,直到结束。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

1.7.C++项目:仿muduo库实现并发服务器之Poller模块的设计

项目完整在&#xff1a; 文章目录 一、Poller模块&#xff1a;描述符IO事件监控模块二、提供的功能三、实现思想&#xff08;一&#xff09;功能&#xff08;二&#xff09;意义&#xff08;三&#xff09;功能设计 四、封装思想五、代码&#xff08;一&#xff09;框架&#…

基于微信小程序的懒人美食帮外卖订餐设计与实现(亮点:多角色的订餐系统、最贴近现实的小程序)

文章目录 前言系统主要功能&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…

CH347读取MPU6050传感器数据和显示

MPU6050 是一款集成了六轴加速度计和陀螺仪的微电子机械系统&#xff08;MEMS&#xff09;传感器。它由 InvenSense&#xff08;现为 TDK&#xff09; 公司开发&#xff0c;是一种广泛应用于姿态估计、运动追踪和稳定控制等领域的常用传感器。 MPU6050 具有以下主要特点和技术…

1、【开始】【简介】Qlib:量化平台

【简介】1、Qlib:量化平台 简介框架简介 Qlib是一个面向AI的量化投资平台,旨在实现AI技术在量化投资中的潜力,赋能研究,并创造价值。 通过Qlib,用户可以轻松利用他们的想法来创建更好的量化投资策略。 框架 在模块层,Qlib 是由上述组件组成的平台。这些组件被设计为低耦…

ssm+vue的图书管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的图书管理系统(有报告)。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring Spr…

正点原子嵌入式linux驱动开发——TF-A移植

经过了之前的学习&#xff0c;除了TF-A的详细启动流程仍待更新&#xff0c;TF-A的使用和其对应的大致启动流程已经进行过了学习。但是当我们实际做产品时&#xff0c;硬件平台肯定会和ST官方的有区别&#xff0c;比如DDR容量会改变&#xff0c;自己的硬件没有使用到官方EVK开发…

1.HTML-标题排版

1.Vscode快速生成基本代码结构 !enter <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" conte…

Acwing 908. 最大不相交区间数量

Acwing 908. 最大不相交区间数量 知识点题目描述思路讲解代码展示 知识点 贪心 题目描述 思路讲解 代码展示 #include <iostream> #include <algorithm>using namespace std;const int N 100010;int n;struct Range {int l, r;bool operator<(const Range …

【爬虫】用wget命令爬虫的简易教程

文章目录 1. 获取登录的请求2. 用postman模拟登录请求3. 用wget模拟登录请求并保存cookie4. 开始爬取网站5. 查看爬取结果6. 网站爬虫简易教程 爬取需要登录的网站的资源 背景&#xff1a;对于一些网站需要使用用户名和密码登录并且使用了https&#xff0c;我们如果不通过凭证将…

Arcgis提取玉米种植地分布,并以此为掩膜提取遥感影像

Arcgis提取玉米种植地分布上&#xff0c;并以此为掩膜提取遥感影像 一、问题描述 因为之前反演是整个研究区&#xff0c;然而土地利用类型有很多类&#xff0c;只在农田或者植被上进行反演&#xff0c;需要去除水体、建筑等其他类型&#xff0c;如何处理得到下图中只有耕地类…

世界前沿技术发展报告2023《世界信息技术发展报告》(六)网络与通信技术

&#xff08;六&#xff09;网络与通信技术 1. 概述2. 5G与光通讯2.1 美国研究人员利用电磁拓扑绝缘体使5G频谱带宽翻倍2.2 日本东京工业大学推出可接入5G网络的高频收发器2.3 美国得克萨斯农工大学通过波束管理改进5G毫米波通信2.4 联发科完成全球首次5G NTN卫星手机连线测试2…

springmvc-国际化中英文切换文件上传下载

1. 国际化 1.1 介绍 国际化(internationalization)&#xff0c; 简称国际化。一个产品支持国际化是指产品在无需做大的改变就能够适应不同的语言和地区的能力。i18n是指是一种让软件在开发阶段就支持多种语言的技术。 1.2 java.util.Locale 该类对象表示了特定的地理&#…

【算法学习】-【双指针】-【复写零】

LeetCode原题链接&#xff1a;1089. 复写零 下面是题目描述&#xff1a; 给你一个长度固定的整数数组 arr &#xff0c;请你将该数组中出现的每个零都复写一遍&#xff0c;并将其余的元素向右平移。 注意&#xff1a;请不要在超过该数组长度的位置写入元素。请对输入的数组 …

【word】从正文开始设置页码

在写报告的时候&#xff0c;会要求有封面和目录&#xff0c;各占一页。正文从第3页开始&#xff0c;页码从正文开始设置 word是新建的 分出三节&#xff08;封面、目录、正文&#xff09; 布局--->分割符--->分节符--->下一页 这样就能将word分为3节&#xff0c;分…

『RSSHub』搭建部署指南

前言 相信各位对推荐算法已经很熟悉了&#xff0c;平台基于推荐算法不断推送我们感兴趣的信息&#xff0c;但是身处推荐算法中心&#xff0c;有时我们可能感觉视野越来越闭塞&#xff0c;原来节约我们时间的推荐系统&#xff0c;这时却成了困住我们的信息茧房 那么也许 RSS&a…

想做网络安全但是没有任何证书可以吗

大家好&#xff0c;我是网络工程师成长日记实验室的郑老师&#xff0c;您现在正在查看的是网络工程师成长日记专栏&#xff0c;记录网络工程师日常生活的点点滴滴 有个同学说他打算做网络安全工程师。他问我说如果考这个软考的网络工程师或者信息安全这个工程师&#xff0c;到时…

基于SSM的公司项目管理系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

世界前沿技术发展报告2023《世界信息技术发展报告》(七)网络与信息安全技术

&#xff08;七&#xff09;网络与信息安全技术 1. 概述2. 网络安全关键技术2.1 美国特种作战司令部举办网络挑战赛以寻找边缘安全技术2.2 英国卡迪夫大学开发出在1秒内阻止网络攻击的方法2.3 国研究人员开发出检测恶意网页的新方法2.4 韩国仁川大学研发出一种基于5G的人工智能…

SpringBoot的全局异常拦截

在 Spring Boot 中&#xff0c;可以通过使用 ControllerAdvice 注解和 ExceptionHandler 注解来实现全局异常拦截。 RestControllerAdvice RestControllerAdvice 是 Spring Framework 提供的注解&#xff0c;用于定义全局异常处理类&#xff0c;并且结合 ExceptionHandler 注…

Python——ASCII编码与Unicode(UTF-8,UTF-16 和 UTF-32)编码

Python3 Python——ASCII编码与Unicode&#xff08;UTF-8&#xff0c;UTF-16 和 UTF-32&#xff09;编码 文章目录 Python3一、编码与编码格式二、ASCII编码与UTF-8编码&#xff08;UTF-16 和 UTF-32编码&#xff09;三、ASCII 字符串和 Unicode 字符串 最近看Python程序的文件…