《数据结构》(应用题)
历年真题(09~24)
2009 最短路径(Dijkstra青春版)
【2009统考真题】带权图(权值非负,表示边连接的两顶点间的距离)的最短路径问题是找出从初始顶点到目标顶点之间的一条最短路径。假设从初始顶点到目标顶点之间存在路径,现有一种解决该问题的方法:
①设最短路径初始时仅包含初始顶点,令当前顶点为初始顶点。
②选择离最近且尚未在最短路径中的一个顶点,加入最短路径,修改当前顶点u=v。
③重复步骤②,直到是目标顶点时为止
请问上述方法能否求得最短路径?若该方法可行,请证明;否则,请举例说明。
分析:咋一看貌似很有道理嘞,还是贪心的思路。那我们回忆一下局部贪心是否能一定得到最优解嘞?显然并不是所有的结果都是最优的对吧。
该方法不一定能够求得最优解(最短路径)。
因此,该方法并不总是能找到最短路径。特别是当存在多个路径且某些路径的间接距离较短时,贪心选择可能导致错误的结果。(不用写这句,应用题看答案是否正确而不是看你哔哩吧啦了多久)
2010 散列表(Hash)
【2010统考真题】将关键字序列(7,8,30,11,18,9,14)散列存储到散列表中。散列表的存储空间是一个下标从0开始的一维数组,散列函数为H(key)=(key×3)mod7,处理冲突采用线性探测再散列法,要求装填(载)因子为0.7。
1)请画出所构造的散列表。
2)分别计算等概率情况下,查找成功和查找不成功的平均查找长度。
注:
- 装载因子是一个很容易被遗忘的知识点。
- ASL成功和ASL不成功是根本不一样的哦,其关键就在于一个是key,而另一个是h(key),一个的次数是指找到(成功)一个的次数是指找不到(失败)。
2011 关键路径(AOE网)
注:时间余量为零(即这个事情拖不了一点)故该为关键事件,由关键事件所组成的路径就被称作关键路径。多大多小尾早头晚减权
l(i)=Vl(i)-weigh
2012 哈夫曼树(Huffman)
【2012统考真题】设有6个有序表A,B,C,D,E,F,分别含有10,35,40,50,60和200个数据元素,各表中的元素按升序排列。要求通过5次两两合并,将6个表最终合并为1个升序表,并使最坏情况下比较的总次数达到最小。请回答下列问题:
1)给出完整的合并过程,并求出最坏情况下比较的总次数。
2)根据你的合并过程,描述n(n≥2)个不等长升序表的合并策略,并说明理由。
分析:我的第一反应比较总次数最小?应该是要用Huffman吧。结果,嘿~还真是。
1)由于合并两个长度分别为m和n的有序表,最坏情况下需要比较m+n-1次,所以最坏情况下比较的总次数计算如下:
- 第1次合并:最多比较次数=10+35-1=44。
- 第2次合并:最多比较次数=40+45-1=84。
- 第3次合并:最多比较次数=50+60-1=109。
- 第4次合并:最多比较次数=85+110-1=194。
- 第5次合并:最多比较次数=195+200-1=394。
- 比较的总次数最多为44+84+109+194+394=825。
2)各表的合并策略是:对多个有序表进行两两合并时,若表长不同,则最坏情况下总的比较次数依赖于表的合并次序。可以借助于哈天曼树的构造思想,依次选择最短的两个表进行合并,此时可以获得最环情况下的最佳合并效率。
2013 折半查找
【2013统考真题】设包含4个数据元素的集合S={'do','for','repeat','while'}各元素的查找概率依次为P=0.35,P=0.15,P=0.15,p=0.35。将S保存在一个长度为4的顺序表中,采用折半查找法,查找成功时的平均查找长度为2.2。
1)若采用顺序存储结构保存S,且要求平均查找长度更短,则元素应如何排列?应使用何种查找方法?查找成功时的平均查找长度是多少?
2)若采用链式存储结构保存S,且要求平均查找长度更短,则元素应如何排列?应使用何种查找方法?查找成功时的平均查找长度是多少?
分析:折半查找会生成折半查找树,故其ASL应该是这样的
那折半查找默认要求应该是元素有序的,故其数据元素应该按照字典序排列(do<for<repeat<while)但是这题的查找概率并不是一样的,所以折半查找未必是最优。那我们用顺序存储结构保存的话如何使其ASL变短呢?其实也很简单就是将概率更大的元素放在前面,这样查找长度会比较短。链式当然也是一样的咯。(答案有更好的做法)
2014 图(邻接表)and 最短路径(Dijkstra)
分析:好家伙这一长串属实是怪吓人的,但是其实我们只关注题干(123)本身的会发现,这纯纯就是一道数据结构的设计题+Dijkstra算法的手算蛤。
这一看就是无向图嘛,那我们直接开始设计,定义一个结构体RXnode,接着定义一个Router ID用于标识路由器,再定义三个小结点Link1、Link2、Net1,最后来设置三个指针域,根据三个小结点的数据指向其相对应的结点。欸到这我才想起来,这不就是邻接表吗,又有顶点表结点,又有边表结点。那我们只需要对其稍加改造不就是第二题的答案了吗?剩下最后一个手算其实就很简单了,瞪眼秒杀法。
1)无向图
2)
typedef struct{int ID, IP;
} LinkNode; // 定义链路结构体,包含ID和IPtypedef struct { int Prefix, Mask;
} NetNOde; // 定义网络结构体,包含Prefix和Masktypedef struct ArcNode{bool Flag; // 判断是Link还是Netunion{LinkNode Lnode; // 联合体用于存储LinkNode或NetNodeNetNode Nnode;} NL;int Merit; // 弧的度量值struct ArcNode *next; // 指向下一个ArcNode的指针
} ArcNode; // 定义弧结构体typedef struct VNode{int RouterID; // 路由器IDArcNode *Link; // 指向相连的第一个弧的指针struct VNode *next; // 指向下一个VNode的指针
} VNode; // 定义表结构体,用于构建顶点链表
3)
- 192.1.1.0:1
- 192.1.5.0:4
- 192.1.6.0:5
- 192.1.7.0:8
2015 邻接矩阵
分析:我们作为后来人显然已经背过该结论了,不过这个A^n邻接矩阵的含义到底是怎么推出来的呢?第一问撒撒水,第二问求A^2也还是很简单,可我们回顾一下求A^2的过程(a[0][0] = a[0][0]*a[0][0] + a[0][1]*a[1][0] + a[0][2]*a[2][0] + a[0][3]*a[3][0] + a[0][4]*a[4][0] = 3)是不是只有当乘积中的任意一方不为0时,才有1的贡献度。那我们再思考下一阶邻接矩阵中元素的含义:
- 对于无向图,邻接矩阵的第i行(或第i列)非零元素(或非无穷元素)的个数正好是顶点i的度。
- A[i][j]不为0是不是表示它们之间是有通路的。
再捋一下a[0][1]*a[1][0]=1是不是说明从1到0,和从0到1是不是都有通路,那这是不是一个来回,且这个通路的长度(2)您猜怎么着?嘿~恰好等于矩阵的次方数。那是不是第三列元素值的含义应该是0~4结点到3这个结点长度为2的路径数量。故第三问的答案就应该为:B^m中,B[i][j]表示的是从i出发走到点j走m步,有多少种走法。非零元素就代表存在长度为m的路径有多少条。
2016 树(性质)
【2016统考真题】若一棵非空k(k≥2)叉树T中的每个非叶结点都有k个孩子,则称T为正则k叉树。请回答下列问题并给出推导过程。
1)若T有m个非叶结点,则T中的叶结点有多少个?
2)若T的高度为h(单结点的树h=1),则T的结点数最多为多少个?最少为多少个?
注:正则的定义要求。
2017 最小生成树(MST)
【2017统考真题】使用Prim算法求带权连通图的最小(代价)生成树(MST)。请回答下列问题:
1)对下列图G,从顶点A开始求G的MST,依次给出按算法选出的边。
2)图G的MST是唯一的吗?
3)对任意的带权连通图,满足什么条件时,其MST是唯一的?
分析:Prim还是简单的吧,从某一个顶点开始构建最小生成树,依次加入当前剩余顶点中代价最小的顶点,直到加入所有顶点。
那MST是否唯一呢?显然是唯一的,因为这四条边的权值最小(AE会被自动排除因为如果有AE的话会造成环路,这是不允许的)所以无论你从哪个结点开始遍历最后的生成树都长这个样子。
从中我们可以得到启发,只要在一张带权连通图中的任意一个环各边的权值都不想等即可满足其生成树必然唯一。
2018 最小生成树(MST)
分析:读完题干我们发现,是不是只要考虑权值之和最少且能连上所有结点就完事了呗,那这是啥?不就是MST嘛。
那我们就有方向了,不就是考我们这俩算法生成的树呗。
用邻接表还是邻接矩阵其实都可以。TTL为5的话,意思应该就是最远传输距离吧,那看图便一目了然了,左边可以,右边不行。
2019 队列(存储结构、循环队列)
1)顺序存储无法满足要求②的队列占用空间随着入队操作而增加。根据要求来分析:要求①容易满足:链式存储方便开辟新空间,要求②容易满足:对于要求③,出队后的结点并不真正释放,用队头指针指向新的队头结点,新元素入队时,有空余结点则无须开辟新空间,赋值到队尾后的第一个空结点即可,然后用队尾指针指向新的队尾结点,这就需要设计成一个首尾相接的循环单链表,类似于循环队列的思想。设置队头、队尾指针后,链式队列的入队操作和出队操作的时间复杂度均为O(1),要求④可以满足。因此,采用链式存储结构(两段式单向循环链表),队头指针为front,队尾指针为rear。
2)该循环链式队列的实现可以参考循环队列,不同之处在于循环链式队列可以方便地增加空间,出队的结点可以循环利用,入队时空间不够也可以动态增加。同样,循环链式队列也要区分队满和队空的情况,这里参考循环队列性一个单元来判断。初始时,创建只有一个空闲结点的循环单链表,头指针front和尾指针rear均指向空闲结点,如下图所示。
- 队空的判定条件:front==rear
- 队满的判定条件:ront==rear->next
3)
4)
2020 哈夫曼树(Huffman)
【2020统考真题】若任意一个字符的编码都不是其他字符编码的前缀,则称这种编码具有前缀特性。现有某字符集(字符个数≥2)的不等长编码,每个字符的编码均为二进制的0、1序列,最长为L位,且具有前缀性。请回答下列问题
1)哪种数据结构适宜保存上述具有前缀特性的不等长编码?
2)基于你所设计的数据结构,简述从0/1串到字符串的译码过程。
3)简述判定某字符集的不等长编码是否具有前缀性的过程。
书本课后答案:
1)使用一棵二叉树保存字符集中各字符的编码,每个编码对应于从根开始到达某叶结点的一条路径,路径长度等于编码位数,路径到达的叶结点中保存该编码对应的字符。
2)从左至右依次扫描0/1串中的各位。从根开始,根据串中当前位沿当前结点的左子指针或右子指针下移,直到移动到叶结点时为止。输出叶结点中保存的字符。然后从根开始重复这个过程,直到扫描到0/1串结束,译码完成。
3)二叉树既可用于保存各字符的编码,又可用于检测编码是否具有前特性。判定编码是否具有前缀性的过程,也是构建二叉树的过程。初始时,二叉树中仅含有根结点,其左子指针和右子指针均为空。
依次读入每个编码C,建立/寻找从根开始对应于该编码的一条路径,过程如下:
对每个编码,从左至右扫描C的各位,根据C的当前位(0或1)沿结点的指针(左子指针或右子指针)向下移动。当遇到空指针时,创建新结点,让空指针指向该新结点并继续移动。沿指针移动的过程中,可能遇到三种情况:
- 若遇到了叶结点(非根),则表明不具有前缀性,返回。
- 若在处理C的所有位的过程中,均没有创建新结点,则表明不具有前缀性,返回。
- 若在处理C的最后一个编码位时创建了新结点,则继续验证下一个编码。
- 若所有编码均通过验证,则编码具有前缀特性。
2021 计数排序
分析:大概遍历一边代码,我们可以发现该函数实现的功能其实就是利用一个指针实现了数组按从小到大的排序。(基于计数排序的思想,count数组第i个元素记录着比该元素小的个数)
1)那自然就是 b[6] = {-10、10、11、19、25、25}
2)比较次数的话,因为每一趟i都是往后全部遍历一遍的,所以应该是n-1 + n-2 + ... + 1 = n(n+1)/2(一定是n-1开始蛤,因为咱自己是不需要和自己比对的)
3)既然它诚心诚意地问了,我便大发慈悲告诉它,并不稳定蛤。
我们可以看到25的相对次序发生了改变,所以是不稳定的,那怎么能够使其出现相同大小的情况,也不会改变相对次序呢?很显然就是调整一下边界的判断条件。
if(a[i]<=a[j]) count[j]++;
else count[i]++;
2022 堆排序
【2022统考真题】现有n(n>100000)个数保存在一维数组M中,需要查找M中最小的10个数。请回答下列问题
1)设计一个完成上述查找任务的算法,要求平均情况下的比较次数尽可能少,简述其算法思想(不需要编程实现)。
2)说明你所设计的算法平均情况下的时间复杂度和空间复杂度。
分析:比较次数较少,那就是要找的比较快咯,而且查找的又不是只有一个数的话,应该可以用小根堆来实现呀,也就是堆排序。那确定算法之后,只要简单说一下其思想过程是什么就好了。
堆的插入:对于大(或小)根堆,要插入的元素放到表尾,然后与父节点对比,若新元素比父节点更大(或小),则将二者互换。新元素就这样一路“上升”,直到无法继续上升为止。
还有一点需要注意的是,我们只需要10个最小数嘛,即咱只需要维护一个10元素大根堆就好啦。那为什么是大根堆嘞,原因很简单,你用小根堆其实不太好比较。大队堆则只需要你先拎出来10个元素塞进去,然后从第11起,你都和其堆顶(当前最大值)比较一次,如果小于的话,就将其插入并删除根顶。如此反复,到最后根中剩下的10个元素一定就是所要寻找的10个最小元素。
1)算法思想。
【方法1】定义含10个元素的数组A,初始时元素值均为该数组类型能表示的最大数MAX。
for M中的每个元素sif(s<A[9)丢弃A[9]并将s按升序插入A;
当数据全部扫描完毕,数组A[O]~A[9]保存的就是最小的10个数。
【方法2】定义含10个元素的大根堆H,元素值均为该堆元素类型能表示的最大数MAX。
for M中的每个元素sif(S<H的堆顶元素)删除堆顶元素并将s插入H;
当数据全部扫描完毕,堆H中保存的就是最小的10个数。
2)算法平均情况下的时间复杂度是O(n),空间复杂度是O(1)。
注:两个方法的思路其实差不多。
2023 外部排序
【2023统考真题】对含有n(n>0)个记录的文件进行外部排序,采用置换-选择排序生成初始归并段时需要使用一个工作区,工作区中能保存m个记录。请回答:
1)若文件中含有19个记录,其关键字依次是51,94,37,92,14,63,15,99,48,56,23,60,31,17,43,8,90,166,100,则当m=4时,可生成几个初始归并段?各是什么?
2)对任意的m(n>>m>0),生成的第一个初始归并段的长度最大值和最小值分别是多少?
分析:本题没什么好分析的,直接开干就完事了。
1)
由上图可知,可以生成3个归并段分别是{37,51,63,92,94,99}、{14,15,23,31,48,56,60,90,166}、{8,17,41,100}(但其实手算的话不需要这么复杂,直接看和抄录最小值即可)
2)那最牛犇的情况就是全部有序嘛,一次就干完了,那就是长度为n呗;那最菜的情况就是拎一个出来之后再也没有比它大(小),那就是长度为1呗。
好,我才是菜的那个,答案里面说,最小值是m。
2024 散列表(Hash)
王道打卡表
数组的应用
压缩存储
- 给自己出题:自己动手创造,画一个5行5列的对称矩阵
- 画图:按“行优先”压缩存储上述矩阵,画出一维数组的样子
- 简答:写出元素 i,j 与 数组下标之间的对应关系
- 画图:按“列优先”压缩存储上述矩阵,画出一维数组的样子
- 简答:写出元素 i,j 与 数组下标之间的对应关系
- 画图:假设你的对称矩阵表示一个无向图,画出无向图的样子
那我们知道由于是对称矩阵,其实没必要把所有的元素都存放在数组中,不然我们按上三角不然我们按下三角存其实都可以。
栈、队列的应用
- 写定义顺序存储的栈(数组实现),数据元素是 int 型。
- 基于上述定义,实现“出栈、入栈、判空、判满”四个基本操作。
- 定义链式存储的栈(单链表实现)。
- 基于上述定义,栈顶在链头,实现“出栈、入栈、判空、判满”四个基本操作。
- 定义链式存储的栈(双向链表实现)。
- 基于上述定义,栈顶在链尾,实现“出栈、入栈、判空、判满”四个基本操作。
typedef struct node{int data[MAX_SIZE]; //用于存放数据 int top; //栈顶指针
} intStack; //定义顺序存储的栈(数组实现) void initStack(intStack *s) { //初始化 s->top = -1;
}int isFull(intStack s) { //判满return s.top == MAX_SIZE - 1;
}int isEmpty(intStack s) { //判空 return s.top == -1;
}void push(intStack *s, int element) { //入栈 if (!isFull(*s)) {s->data[++s->top] = element;}return -1;
}int pop(intStack s){ //出栈 if(!isEmpty(*s)) {return s->data[s->top--];}return -1;
}
// 链表节点结构定义
typedef struct Snode {int data; // 数据域struct Snode *next; // 指向下一个节点的指针
} Snode, *listStack; // listStack 是指向 Snode 的指针类型// 初始化栈
void initStack(listStack &S) {S = (Snode*)malloc(sizeof(Snode)); // 分配内存给头结点S->next = NULL; // 头结点的下一个指针初始化为 NULL
}// 判空函数
bool isEmpty(listStack S) {return S->next == NULL; // 如果头结点的下一个指针为 NULL,则栈为空
}// 入栈操作
bool push(listStack &S, int element) {Snode *p = (Snode*)malloc(sizeof(Snode)); // 创建新节点if (p == NULL) return false; // 检查内存分配是否成功p->data = element; // 设置新节点的数据p->next = S->next; // 新节点指向当前栈顶元素S->next = p; // 更新栈顶为新节点return true; // 返回成功
}// 出栈操作
bool pop(listStack &S, int &x) {if (!isEmpty(S)) { // 检查栈是否为空Snode *p = S->next; // 获取栈顶元素x = p->data; // 返回栈顶元素S->next = p->next; // 更新栈顶为下一个元素free(p); // 释放栈顶元素的内存return true; // 返回成功}return false; // 栈为空,出栈失败
}
// 双向链表节点结构定义
typedef struct Dnode {int data; // 数据域struct Dnode *prior; // 指向前一个节点的指针struct Dnode *next; // 指向下一个节点的指针
} Dnode, *dlistStack; // dlistStack 是指向 Dnode 的指针类型// 初始化栈
void initStack(dlistStack &S) {S = (Dnode*)malloc(sizeof(Dnode)); // 分配内存给头结点S->next = NULL; // 头结点的下一个指针初始化为 NULLS->prior = NULL; // 头结点的前一个指针初始化为 NULL
}// 判空函数
bool isEmpty(dlistStack &S) {return S->next == NULL; // 如果头结点的下一个指针为 NULL,则栈为空
}// 入栈操作
bool push(dlistStack &S, int element) {Dnode *p = (Dnode*)malloc(sizeof(Dnode)); // 创建新节点if (p == NULL) return false; // 检查内存分配是否成功p->data = element; // 设置新节点的数据p->next = NULL; // 新节点的下一个指针初始化为 NULLp->prior = S; // 新节点的前一个指针指向当前栈顶(头结点)if (S->next != NULL) { // 如果栈不空S->next->prior = p; // 更新原栈顶的前指针}S->next = p; // 更新栈顶为新节点return true; // 返回成功
}// 出栈操作
bool pop(dlistStack &S, int &x) {if (!isEmpty(S)) { // 检查栈是否为空Dnode *p = S->next; // 获取栈顶元素x = p->data; // 返回栈顶元素S->next = p->prior; // 更新栈顶为前一个元素if (S->next != NULL) { // 如果新的栈顶不为空S->next->next = NULL; // 断开新的栈顶与旧栈顶的连接}free(p); // 释放栈顶元素的内存return true; // 返回成功}return false; // 栈为空,出栈失败
}
分析:最简单,也最容易想到应该就是,直接设置6个计数器来统计左右括号的出现,然后将其相对应的一一比对,只要出现不相等那就是不配对。当然这个简单背后所对应的就是如果面对表达式中的括号嵌套很深,那么可能出问题。
更好的方法是使用栈(stack)(毕竟本来就是在栈这块章节的问题hhhh)来处理括号匹配,这样可以有效地管理括号的配对关系。
使用栈的方法
- 遇到左括号时,压入栈。
- 遇到右括号时,检查栈顶元素:
- 如果栈为空,说明没有对应的左括号,返回不配对。
- 如果栈顶元素与当前右括号不匹配,返回不配对。
- 如果匹配,弹出栈顶元素。
- 遍历结束后,检查栈是否为空:
- 如果栈为空,说明所有括号都配对成功;
- 否则,说明有未配对的左括号。
bool isBalanced(const std::string& expression) {std::stack<char> s;std::unordered_map<char, char> brackets = {{')', '('},{']', '['},{'}', '{'}};for (char ch : expression) {if (ch == '0') {break; // 遇到结束符}// 如果是左括号,压入栈if (ch == '(' || ch == '[' || ch == '{') {s.push(ch);}// 如果是右括号else if (ch == ')' || ch == ']' || ch == '}') {if (s.empty() || s.top() != brackets[ch]) {return false; // 不配对}s.pop(); // 匹配成功,弹出栈顶元素}}return s.empty(); // 栈空则配对成功
}
树的应用
并查集
function:
- 检测图中是否有环
- 实现Kruskal算法
- 判断无向图的连通性
写代码:定义一个并查集(用长度为n的数组实现) |
基于上述定义,实现并查集的基本操作—— 并 Union |
基于上述定义,实现并查集的基本操作—— 查 Find |
自己设计一个例子,并查集初始有10个元素,进行若干次Union操作,画出每一次Union后的样子 |
自己设计一个例子,基于上一步得到的并查集,进行若干次find操作(每次find会进行“路径压缩”)。画出每次 find (路径压缩)后的样子 |
#define SIZE 13
int UFSets[SIZE]; //用一个数组表示并查集//初始化并查集
void Initial(int S[]){for(int i=0;i<SIZE;i++)S[i]=-1;
}//Find “查”操作,找 x 所属集合(返回 x 所属根结点)
int Find(int S[],int x){while(S[x]>=0) //循环寻找 x 的根x=S[x];return x; //根的 S[]小于 0
}//Union “并”操作,将两个集合合并为一个
void Union(int S[],int Root1,int Root2){//要求 Root1 与 Root2 是不同的集合if(Root1==Root2) return;S[Root2]=Root1; //将根 Root2 连接到另一根 Root1 下面
}
//Union “并”操作,小树合并到大树
void Union(int S[], int Root1, int Root2) {if (Root1 == Root2) return; // 如果两个元素已经在同一个集合中,则不进行操作if (S[Root2] > S[Root1]) { // 假设Root2的树的节点数更少或两棵树节点数相等S[Root1] += S[Root2]; // 将Root2树的节点数累加到Root1上S[Root2] = Root1; // 将Root2的根节点指向Root1,即把Root2的树合并到Root1的树下} else {S[Root2] += S[Root1]; // 将Root1树的节点数累加到Root2上S[Root1] = Root2; // 将Root1的根节点指向Root2,即把Root1的树合并到Root2的树下}
}//Find “查”操作优化,先找到根节点,再进行“压缩路径”
int Find(int S[],int x){int root = x;while(S[root]>=0) root=S[root]; //循环找到根while(x!=root){ //压缩路径int t=S[x]; //t 指向 x 的父节点S[x]=root; //x 直接挂到根节点下x=t;}return root; //返回根节点编号
}
二叉排序树(BST)
二叉平衡树(AVL)
自己设计一个例子,给出不少于10个关键字序列,按顺序插入一棵初始为空的二叉排序树,画出每一次插入后的样子 |
基于你设计的例子,计算二叉排序树在查找成功和查找失败时的 ASL |
基于你设计的例子,依次删除不少于4个元素,画出每一次删除之后的样子(需要包含四种删除情况——删一个叶子结点、删一个只有左子树的结点、删一个只有右子树的结点、删一个既有左子树又有右子树的结点) |
自己设计一个例子,给出不少于10个关键字序列,按顺序插入一棵初始为空的平衡二叉树,画出每一次插入后的样子(你设计的例子要涵盖LL、RR、LR、RL四种调整平衡的情况) |
基于你设计的例子,计算平衡二叉树在查找成功和查找失败时的 ASL |
二叉树
写代码:定义顺序存储的二叉树(数组实现,树的结点从数组下标1开始存储) |
基于上述定义,写一个函数 int findFather ( i ) ,返回结点 i 的父节点编号 |
基于上述定义,写一个函数 int leftChild ( i ) ,返回结点 i 的左孩子编号 |
基于上述定义,写一个函数 int rightChild ( i ) ,返回结点 i 的右孩子编号 |
利用上述三个函数,实现先/中/后序遍历 |
写代码:定义顺序存储的二叉树(数组实现,树的结点从数组下标0开始存储) |
基于上述定义,写一个函数 int findFather ( i ) ,返回结点 i 的父节点编号 |
基于上述定义,写一个函数 int leftChild ( i ) ,返回结点 i 的左孩子编号 |
基于上述定义,写一个函数 int rightChild ( i ) ,返回结点 i 的右孩子编号 |
利用上述三个函数,实现先/中/后序遍历 |
分析:都说了是要数组实现的话,那应该就是说我们得找找二叉树左孩子右孩子与父节点之间得关系才对。(也就是根据不同的数组下标去寻找其对应的父节点or孩子结点)那接下来再考虑下特殊情况,可能会存在空结点的对吧,所以需要再设置一个标志位来判断当前结点是否为空。
那又是二叉树又是从一开始其实很简单的,直接上代码。
typedef struct TreeNode {int data;bool empty;
} TreeNode;void Initialize(TreeNode t[], int length) {for (int i = 1; i <= length; i++)t[i].empty = true; // 初始化所有节点为空
}bool isEmpty(TreeNode t[], int index, int length) {if (index < 1 || index >= length)return true; // 超出范围return t[index].empty;
}int findFather(TreeNode t[], int index, int length) {int tmp = index / 2;return (tmp >= 1 && tmp < length && !isEmpty(t, tmp, length)) ? tmp : -1; // 返回父节点编号
}int findLeftChild(TreeNode t[], int index, int length) {int tmp = index * 2;return (tmp < length && !isEmpty(t, tmp, length)) ? tmp : -1; // 返回左孩子编号
}int findRightChild(TreeNode t[], int index, int length) {int tmp = index * 2 + 1;return (tmp < length && !isEmpty(t, tmp, length)) ? tmp : -1; // 返回右孩子编号
}
可如果是从0开始的话就要重新捋一捋了,首先0有1、2两个孩子,也就是1和2找爸爸都要找到0才行对吧,那1很明显根据C语言的要求 " / " 其实明显是还可以除以2来求的,可2除以2的话结果就不对了。那其实我们就再看看后面还是不是呢(也很简单就能验证,其实奇数端不受影响,而偶数端找爸爸的时候会多1,那就好办啦,将奇偶区分开就行。那再看回如何找孩子,先不看最特殊的0,我们看1的孩子3and4,2的孩子5and6。这个规律还是能够一眼就看出来的对吧,就是直接乘2加1或者加2。看回0,你会发现也是一样的道理对不对~
typedef struct TreeNode {int data;bool empty;
} TreeNode;void Initialize(TreeNode t[], int length) {for (int i = 0; i < length; i++)t[i].empty = true; // 初始化所有节点为空
}bool isEmpty(TreeNode t[], int index, int length) {if (index < 0 || index >= length)return true; // 超出范围return t[index].empty;
}int findFather(TreeNode t[], int index, int length) {if (index == 0) return -1; // 根节点没有父节点int tmp = (index % 2 == 0) ? (index / 2 - 1) : (index / 2);return isEmpty(t, tmp, length) ? -1 : tmp; // 返回父节点编号
}int findLeftChild(TreeNode t[], int index, int length) {int tmp = index * 2 + 1;return isEmpty(t, tmp, length) ? -1 : tmp; // 返回左孩子编号
}int findRightChild(TreeNode t[], int index, int length) {int tmp = index * 2 + 2;return isEmpty(t, tmp, length) ? -1 : tmp; // 返回右孩子编号
}
那又如何来实现前/中/后序遍历呢?我想应该只需要使用深度优先即可。(两题的答案是一样的哦)
void preOrder(TreeNode t[], int root, int length) {if (isEmpty(t, root, length)) {return; // 退出递归条件}cout << t[root].data << " "; // 先访问根节点preOrder(t, findLeftChild(t, root, length), length); // 访问左子树preOrder(t, findRightChild(t, root, length), length); // 访问右子树
}void midOrder(TreeNode t[], int root, int length) {if (isEmpty(t, root, length)) {return; // 退出递归条件}midOrder(t, findLeftChild(t, root, length), length); // 访问左子树cout << t[root].data << " "; // 访问根节点midOrder(t, findRightChild(t, root, length), length); // 访问右子树
}void postOrder(TreeNode t[], int root, int length) {if (isEmpty(t, root, length)) {return; // 退出递归条件}postOrder(t, findLeftChild(t, root, length), length); // 访问左子树postOrder(t, findRightChild(t, root, length), length); // 访问右子树cout << t[root].data << " "; // 访问根节点
}
树
写代码:使用“双亲表示法”,定义顺序存储的树(以及森林) |
写代码:使用“孩子表示法”,定义链式存储的树(以及森林) |
对比:树的孩子表示法存储 v.s. 图的邻接表存储 v.s. 散列表的拉链法 v.s. 基数排序。你发现了什么? |
写代码:使用“孩子兄弟表示法”,定义链式存储的树(以及森林) |
自己动手创造,画一个结点总数不少于10的树,并画出对应的“双亲表示法、孩子表示法、孩子兄弟表示法”三种数据结构的示意图 |
自己动手创造,画一个至少包含3棵树的森林,并画出对应的“双亲表示法、孩子表示法、孩子兄弟表示法”三种数据结构的示意图 |
1、使用“双亲表示法”,定义顺序存储的树(以及森林)
#define MAX_TREE_SIZE 100 //树中最多结点数
typedef struct{ //树的结点定义ElemType data; //数据元素(存放结点本身信息。)int parent; //双亲位置域(指示本结点的双亲结点在数组中的位置。)
}PTNode;typedef struct{ //树的类型定义PTNode nodes[MAX_TREE_SIZE]; //双亲表示int n; //结点数
}PTree;
2、 使用“孩子表示法”,定义链式存储的树(以及森林)
struct CTNode{int child; //孩子结点在数组中的位置struct CTNode *next; // 下一个孩子
};typedef struct{ElemType data;struct CTNode *firstChild; // 第一个孩子
}CTBox;typedef struct{CTBox nodes[MAX_TREE_SIZE];int n, r; // 结点数和根的位置
}CTree;
3、树的孩子表示法存储 v.s. 图的邻接表存储 v.s. 散列表的拉链法 v.s. 基数排序。你发现了什么?
嗯~它们应该图都长一个样子,别的不造。
4、使用“孩子兄弟表示法”,定义链式存储的树(以及森林)
typedef struct CSNode{ElemType data; //数据域struct CSNode *firstchild, *nextsibling; //第一个孩子和右兄弟指针
}CSNode. *CSTree;
5、自己动手创造,画一个结点总数不少于10的树,并画出对应的“双亲表示法、孩子表示法、孩子兄弟表示法”三种数据结构的示意图。
6、自己动手创造,画一个至少包含3棵树的森林,并画出对应的“双亲表示法、孩子表示法、孩子兄弟表示法”三种数据结构的示意图。
图的应用
邻接矩阵和邻接表
写代码:定义一个顺序存储的图(邻接矩阵实现) |
写代码:定义一个链式存储的图(邻接表实现) |
自己设计一个不少于6个结点的带权无向图,并画出其邻接矩阵、邻接表的样子 |
自己设计一个不少于6个结点的带权有向图,并画出其邻接矩阵、邻接表的样子 |
分析: 先考虑下邻接矩阵的长相,其实就是存边对吧,但是需要一个额外的数组用于存储顶点集。还需要几个变量用于存储图的顶点数和边数。
#define MaxVertexNum 100 //项目数目的最大值(自己定)
typedef char VertexType; //顶点对应的数据类型
typedef int EdgeType; //边对应的数据类型
typedef struct{VertexType Vex[MaxVertexNum]; //顶点集EdgeType Edge[MaxVertexNum][MaxVertexNum]; //邻接矩阵,边表(也就是权重)int vexnum,arcnum; //图的当前顶点数和边数
}MGraph;
那邻接表和上头那个还是差蛮大的,是不是又有边表,又有顶点表。然后边表中是不是有个邻接点域(该弧所指向的顶点的位置(弧头))和指针域,而顶点表中存放的讯息则是一个顶点域和一个边表头指针。(个人觉得最重要的是要把图记下来,手搓代码反而是其次的)
#define MaxVertexNum 100 //图中顶点数目的最大值
typedef struct ArcNode{ //边表结点int adjvex; //该弧所指向的顶点的位置struct ArcNode *next; //指向下一条弧的指针//InfoType info; //网的边权值
}ArcNode;typedef struct VNode{ //顶点表结点VertexType data; //顶点信息ArcNode *first; //指向第一条依附该顶点的弧的指针
}VNode,AdjList[MaxVertexNum];typedef struct{AdjList vertices; //邻接表int vexnum,arcnum; //图的顶点数和弧数
}ALGraph; //ALGraph是以邻接表存储的图类型
拓扑排序
自己设计一个不少于6个结点的带权有向无环图,并画出其邻接矩阵的样子 用一维数组将你设计的有向无环图的邻接矩阵进行压缩存储 文字描述:基于你压缩存储的数组,如何判断结点 i、j 之间是否有边? 基于你设计的带权有向无环图,写出所有合法的拓扑排序序列 文字描述:拓扑排序的过程
那不就是上三角矩阵压缩存储与k之间的关系嘛
排序算法的应用
堆排序
自己设计一个长度不小于10的乱序数组,用堆排序,最终要生成升序数组,画出建堆后的状态 画出每一轮堆排序的状态
分析: 由于最终是要生成升序数组,故而我们应该使用大根堆。
基数排序
自己设计一个长度不小于15的乱序链表,每个数据元素取值范围0~99,用基数排序,最终要生成升序链表 |
画出每一轮基数排序的状态 |
相关文章:
《数据结构》(应用题)
历年真题(09~24) 2009 最短路径(Dijkstra青春版) 【2009统考真题】带权图(权值非负,表示边连接的两顶点间的距离)的最短路径问题是找出从初始顶点到目标顶点之间的一条最短路径。假设从初始顶点…...
阿里内部正式开源“Spring Cloud Alibaba (全彩小册)”
年轻的毕业生们满怀希望与忐忑,去寻找、竞争一个工作机会。已经在职的开发同学,也想通过社会招聘或者内推的时机争取到更好的待遇、更大的平台。 然而,面试人群众多,技术市场却相对冷淡,面试的同学们不得不面临着 1 个…...
LeetCode题练习与总结:根据字符出现频率排序--451
一、题目描述 给定一个字符串 s ,根据字符出现的 频率 对其进行 降序排序 。一个字符出现的 频率 是它出现在字符串中的次数。 返回 已排序的字符串 。如果有多个答案,返回其中任何一个。 示例 1: 输入: s "tree" 输出: "eert" …...
Excel VBA学习系列汇总20241205
整理几年工作中,实用VBA代码,绝对干货! 方便自己查询,方便大家学习, 有缘人可复制使用,记得分享给大家免费学习哦! 序历史文章1新学期开始,如何新学期开始,如何按成绩名次…...
给el-table表头添加icon图标,以及鼠标移入icon时显示el-tooltip提示内容
在你的代码中,你已经正确地使用了 el-tooltip 组件来实现鼠标划过加号时显示提示信息。el-tooltip 组件的 content 属性设置了提示信息的内容,placement 属性设置了提示信息的位置。 你需要确保 el-tooltip 组件的 content 属性和 placement 属性设置正…...
基于LLM智能问答系统【阿里云:天池比赛】
流程: 1、分别识别问题及提供的资料文件中的公司名实体,有公司名的走语义检索,无公司名的走结构化召回 2、结构化召回:Qwen根据问题生成sql,执行sql获取结果数值,把结果数值与问题给到Qwen生成最终结果 …...
k8s-Informer概要解析(2)
Client-go 主要用在 k8s 控制器中 什么是 k8s Informer Informer 负责与 kubernetes APIServer 进行 Watch 操作,Watch 的资源,可以是 kubernetes 内置资源对象,也可以 CRD。 Informer 是一个带有本地缓存以及索引机制的核心工具包&#x…...
Leetcode 3376. Minimum Time to Break Locks I
Leetcode 3376. Minimum Time to Break Locks I 1. 解题思路2. 代码实现 题目链接:3376. Minimum Time to Break Locks I 1. 解题思路 这一题我最开始的思路走的是贪婪算法的路子,优先走X的增长,不过很不幸失败了,后面还是暴力…...
介绍8款开源网络安全产品
01 HFish蜜罐 HFish是一款开源的蜜罐系统,用于模拟各种网络服务和应用,以吸引潜在的黑客攻击。它能够记录攻击尝试并收集攻击者的信息,从而帮助网络管理员识别潜在的威胁。HFish支持多种协议和服务,包括HTTP、FTP、SSH等&#…...
vue2面试题|[2024-12-5]
开题答辩终于结束了,又要开始我的前端面试学习啦!!! 1.v-model双向绑定原理 class Vue{constructor(options){this.$options optionsthis.$watchEvent {}if(typeof options.beforeCreate function){options.beforeCreate.bind…...
共筑数字安全防线,2024开源和软件安全沙龙即将启幕
随着数字化转型进程的加快以及开源代码的广泛应用,开源凭借平等、开放、协作、共享的优秀创作模式,逐渐成为推动数字技术创新、加速传统行业转型升级的重要模式。但随着软件供应链日趋复杂多元,使得其安全风险不断加剧,针对软件供…...
目标跟踪领域经典论文解析
亲爱的小伙伴们😘,在求知的漫漫旅途中,若你对深度学习的奥秘、JAVA 、PYTHON与SAP 的奇妙世界,亦或是读研论文的撰写攻略有所探寻🧐,那不妨给我一个小小的关注吧🥰。我会精心筹备,在…...
SQL DQL数据查询语言(后续)
SQL DQL数据查询语言(后续) 1.子查询 在查询语句中的WHERE条件子句中,又嵌套了另外一个查询语句在返回列中嵌套一个查询 where条件中嵌套 要求:查询课程为《高等数学-2》且分数不小于80分的学生的学号和姓名select a.StudentNo,a…...
Gitee配置SSH公钥
采用SSH协议同步Git仓库代码的好处就是高效。在配置好SSH公钥后,不需要每次操作都要输入用户名和密码(主要针对命令行来说)。 以我个人项目为例。 生成 SSH 公钥 1. 通过命令 ssh-keygen 生成 SSH Key: ssh-keygen -t ed25519…...
机器学习——感知机模型
文章目录 前言1.感知机模型介绍1.1基本概念1.2数学表达1.3几何解释1.4优缺点 2.二分类应用2.1应用介绍2.2准备数据集2.2.1环境检查2.2.2数据集介绍2.2.3获取数据2.2.4划分数据集 2.3可视化训练集2.4训练过程2.4.1首轮梯度下降2.4.2多轮梯度下降 2.5可视化分类结果2.6在验证集验…...
如何选择安全、可验证的技术?
澳大利亚信号局的澳大利亚网络安全中心 (ASD 的 ACSC) 发布了一份指导文件,题为《选择安全和可验证的技术》,旨在帮助组织在采购软件(专有或开源)、硬件(例如物联网设备)和云服务(SaaS、MSP 服务…...
STL库中list的使用与迭代器的实现
STL库中list的使用与迭代器的实现 1.使用list中的部分函数assignspliceremoveuniquemeger 2.list的部分功能实现(重点)框架迭代器的实现 1.使用list中的部分函数 assign 功能一:当前链表的节点全部销毁,替换成迭代区间的值 功能二…...
android 常用三方框架
说实话, 我是比较讨厌三方框架的, 比如一个eventbus 底层逻辑就是个观察者模式,当然他的场景涵盖的比较丰富, 单从 单一原则来说, 还是一个简单的观察者模式就能解决问题, 何必要添加那么多文件到我们的项目…...
Browser.js断点续传上传
通过断点续传上传的方式将文件上传到OSS前,您可以指定断点记录点。上传过程中,如果出现网络异常或程序崩溃导致文件上传失败时,将从断点记录处继续上传未上传完成的部分。 attention: 1、 当您使用webpack或browserify等打包工具…...
Java项目实战II基于微信小程序的无中介租房系统(开发文档+数据库+源码)
目录 一、前言 二、技术介绍 三、系统实现 四、核心代码 五、源码获取 全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。 一、前言 随着城市化进程的加速,租房市场日益繁荣&a…...
了解Cocoa Touch框架与主要组件
Cocoa Touch框架详解及其主要组件 一、Cocoa Touch框架概述 Cocoa Touch框架是苹果公司为iOS应用程序开发提供的一套完整的框架,它基于Cocoa框架,并专为触控设备如iPhone、iPad等设计。这套框架不仅包含了构建图形用户界面(GUI)…...
ISO45001职业健康安全管理体系涵盖了丰富的内容
范围与术语 适用范围:明确规定了该标准适用于任何有愿望建立、实施和保持职业健康安全管理体系的组织,旨在使组织能够通过管理体系的有效运行,预防和控制职业健康安全风险,持续改进职业健康安全绩效。术语定义:对职业…...
Spring Boot 整合 Druid 并开启监控
文章目录 1. 引言2. 添加依赖3. 配置数据源4. 开启监控功能5. 自定义 Druid 配置(可选)6. 访问监控页面7. 注意事项8. 总结 Druid 是一个由阿里巴巴开源的高性能数据库连接池,它不仅提供了高效的连接管理功能,还自带了强大的监控和…...
【JAVA高级篇教学】第一篇:Springboot对接通义千问大模型
博主今天打算讲解下Java如何对接阿里云的通义千问大模型,可以自己玩玩ai问答之类的! 目录 一、发展历程 二、API-KEY的获取与配置 三、引用SDK 四、文本模型 1.代码 2.返回数据 3.官方代码案例 五、通义千问VL 1.计量计费 六、查看API-KEY调用额…...
【Windows 同时安装 MySQL5 和 MySQL8 - 详细图文教程】
卸载 MySQL 参考文章: 完美解决Mysql彻底删除并重装_怎么找到mysql并卸载-CSDN博客使用命令卸载mysql_卸载mysql服务命令-CSDN博客 先管理员方式打开 cmd ,切换到 MySQL 安装目录的 bin 文件夹下,执行如下命令,删除 MySQL 服务 my…...
Next.js 系统性教学:深入理解缓存与数据优化策略
更多有关Next.js教程,请查阅: 【目录】Next.js 独立开发系列教程-CSDN博客 目录 前言 1. 缓存的基本概念 1.1 缓存的作用 1.2 Next.js 中的缓存策略 2. Next.js 的缓存机制 2.1 请求记忆化(Request Memoization) 2.1.1 什…...
JAVA数据结构
1.数组 (Array): 固定大小的容器,用于存储相同类型的元素,数组在内存中是连续存储的,支持通过索引快 速访问元素。 int[] numbers = new int[10]; numbers[0] = 1;2.Java Collections Framework (JCF) JCF提供了一组接口和类用于管理和操作集合(如列表,集合,…...
力扣第96题 不同的二叉搜索树
力扣第96题 - 不同的二叉搜索树 题目描述 给定一个整数 n,求以 1 到 n 为节点组成的所有 不同的二叉搜索树(BST) 的个数。 题目分析 二叉搜索树的性质 对于一个二叉搜索树,以 i 为根节点: 左子树的节点值来自 [1, i…...
在Ubuntu上使用IntelliJ IDEA:开启你的Java开发之旅!
你好,年轻的学徒!🧑💻 是时候踏上进入Java开发世界的史诗之旅了,我们的得力助手将是强大的IntelliJ IDEA。准备好了吗?出发吧! 在我们开始之前,我们需要下载这个工具。但是&#…...
【C语言】18. 自定义类型:结构体类型
文章目录 前言:一、结构体类型的声明1、结构体回顾1)结构的声明2)结构体变量的创建和初始化 2、结构的特殊声明3、结构的⾃引⽤ 二、结构体变量的创建和初始化1、对⻬规则2、为什么存在内存对⻬?3、修改默认对⻬数 三、结构成员访问操作符1、…...
智能租赁管理系统助力规范化住房租赁市场提升用户体验
内容概要 在当今的住房租赁市场中,智能租赁管理系统应运而生,为房东和租客带来了前所未有的便利。这套系统就像一位全能助手,将租赁信息、监管机制以及在线签约功能集成在一起,让整个过程变得流畅而高效。换句话说,您…...
ERROR: KeeperErrorCode = NoNode for /hbase/master
原因分析 通过上面的情景模拟,我们可以看到报错的原因在于zookeeper中出现问题,可能是zookeeper中的/hbase/master被删除,或者是在hbase集群启动之后重新安装了zookeeper,导致zookeeper中的/hbase/master节点数据异常。 1. 停止…...
springboot第84集:Java进阶之路, Netty
# kafka-map文件夹 cd /usr/local/kafka-map # 根据需求自行修改配置 vi application.yml # 启动 java -jar kafka-map.jar byte minByte -128; byte maxByte 127; 用于表示一个 8 位(1 字节)有符号整数。它的值范围是 -128(-2^7࿰…...
DevOps持续集成
DevOps流程 第一步安装git 关闭防火墙 systemctl stop firewalld cd /usr/loacl vim docker-compose.yml docker search gitlab 拉取gitlab镜像 2.33GB docker pull gitlab/gitlab-ce:latestvim docker-compose.yml修改docker-compose.yml version: 3.1 services:gitlab:i…...
sql server log文件
确定 SQL Server 实例中具有大量 VDF 的数据库 SELECT [name], COUNT(l.database_id) AS vlf_count FROM sys.databases AS s CROSS APPLY sys.dm_db_log_info(s.database_id) AS l GROUP BY [name] HAVING COUNT(l.database_id) > 100; 在收缩日志文件之前确定事务日志中…...
pip install报错 Missing dependencies for SOCKS support的正确解决办法:离线安装pysocks
今天准备开发python项目的时候,发现在pip install 的时候报错了,提示:Missing dependencies for SOCKS support,查遍csdn所有的回答都统一是只需要执行: unset all_proxy unset ALL_PROXY 然后再执行 pip install p…...
嵌入式学习(15)-stm32通用GPIO模拟串口发送数据
一、概述 在项目开发中可能会遇到串口不够用的情况这时候可以用通过GPIO来模拟串口的通信方式。 二、协议格式 按照1位起始位8位数据位1位停止位的方式去编写发送端的程序。起始位拉低一个波特率的时间;发送8位数据;拉高一个波特率的时间。 三、代码 …...
AKE 安全模型:CK, CK+, eCK
参考文献: [BCK98] Mihir Bellare, Ran Canetti, Hugo Krawczyk. A Modular Approach to the Design and Analysis of Authentication and Key Exchange Protocols (Extended Abstract). STOC 1998: 419-428.[CK01] Ran Canetti, Hugo Krawczyk. Analysis of Key-E…...
【Linux】通过crond服务设置定时执行shell脚本,实际执行时间却延迟了8小时
一、问题描述 通过使用crond服务设置定时任务,在每天凌晨的2:00执行脚本,但检查结果时发现,实际执行时间却在上午10点。 检查shell脚本执行结果发现,实际执行脚本时间在上午10:00,延迟了8小时。 检查系统时间…...
什么是云原生数据库 PolarDB?
云原生数据库 PolarDB 是阿里云推出的一款高性能、兼容性强、弹性灵活的关系型数据库产品。它基于云原生架构设计,结合分布式存储和计算分离的技术优势,为用户提供强大的计算能力、卓越的可靠性以及高性价比的数据库解决方案。PolarDB 适合各种业务场景&…...
(6)JS-Clipper2之ClipperOffset
1. 描述 ClipperOffset类封装了对打开路径和关闭路径进行偏移(膨胀/收缩)的过程。 这个类取代了现在已弃用的OffsetPaths函数,该函数不太灵活。可以使用不同的偏移量(增量)多次调用Execute方法,而不必重新分配路径。现在可以在一次操作中对开放和封闭路…...
基于51单片机64位病床呼叫系统设计( proteus仿真+程序+设计报告+原理图+讲解视频)
基于51单片机病床呼叫系统设计( proteus仿真程序设计报告原理图讲解视频) 仿真图proteus7.8及以上 程序编译器:keil 4/keil 5 编程语言:C语言 设计编号:S0095 1. 主要功能: 基于51单片机的病床呼叫系统proteus仿…...
工业智能网关如何为企业实现智能制造赋能?
在数字化转型的浪潮中,工业智能网关作为连接物理世界与数字世界的桥梁,正逐步成为智能制造领域的核心组件。本文将通过一个实际使用案例,深入剖析工业智能网关如何助力企业实现生产流程的优化、数据的高效采集与分析,以及智能化决…...
【Spring项目】表白墙,留言板项目的实现
阿华代码,不是逆风,就是我疯 你们的点赞收藏是我前进最大的动力!! 希望本文内容能够帮助到你!! 目录 一:项目实现准备 1:需求 2:准备工作 (1)…...
Java-WebSocket
文章目录 WebSocket概念SpringBoot实现一个WebSocket示例STOMP消息订阅和发布后端主动发送消息 跨域 WebSocket概念 应用层协议,底层采用TCP,特点:持续连接,有状态,双向通信 当客户端想要与服务器建立WebSocket连接时…...
C#请求https提示未能为 SSL/TLS 安全通道建立信任关系
System.Net.WebException: 基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系 ,这个错误通常表明你的应用程序在尝试建立一个安全的 SSL/TLS 连接时遇到了问题。这通常是由于证书验证失败引起的。证书验证失败可能有几个原因: 证书不受信任&#…...
pdf转word/markdown等格式——MinerU的部署:2024最新的智能数据提取工具
一、简介 MinerU是开源、高质量的数据提取工具,支持多源数据、深度挖掘、自定义规则、快速提取等。含数据采集、处理、存储模块及用户界面,适用于学术、商业、金融、法律等多领域,提高数据获取效率。一站式、开源、高质量的数据提取工具&…...
人工智能与机器学习:真实案例分析及其在各行业的应用前景
目录 引言 人工智能与机器学习的基础概念 人工智能的历史与演变 机器学习的算法分类 深度学习与传统机器学习的区别 行业应用案例分析 医疗健康 疾病预测与诊断 影像识别的运用 案例:IBM Watson在肿瘤治疗中的应用 金融服务 风险评估与欺诈检测 投资预测…...
再谈多重签名与 MPC
目录 什么是 MPC 钱包以及它们是如何出现的 多重签名和智能合约钱包已经成熟 超越 MPC 钱包 关于小队 多重签名已经成为加密货币领域的一部分,但近年来,随着 MPC(多方计算)钱包的出现,多重签名似乎被掩盖了。MPC 钱包之…...
(长期更新)《零基础入门 ArcGIS(ArcMap) 》实验二----网络分析(超超超详细!!!)
相信实验一大家已经完成了,对Arcgis已进一步熟悉了,现在开启第二个实验 ArcMap实验--网络分析 目录 ArcMap实验--网络分析 1.1 网络分析介绍 1.2 实验内容及目的 1.2.1 实验内容 1.2.2 实验目的 2.2 实验方案 2.3 实验流程 2.3.1 实验准备 2.3.2 空间校正…...