数据结构(六)----串

目录

1.串的定义

2.串的基本操作

3.串的存储结构

(1)串的定义

•顺序存储

•链式存储

(2)求串长

(3)求子串

(4)比较串的大小

(5)定位操作

4.字符串的模式匹配

(1)朴素模式匹配算法

(2)KMP算法

•求模式串中的next数组(重点)

•练习:

(3)KMP算法的进一步优化

•求nextval数组的方法(重点)


1.串的定义

串,即字符串(String)是由零个或多个字符组成的有限序列。一般记为 S='a_{1}a2_{2}.....a_{n}'。其中,S是串名,单引号括起来的字符序列是串的值(有的地方用双引号(如Java,C),有的地方用单引号(如Python));ai可以是字母、数字或其他字符;串中字符的个数n称为串的长度。n=0时的串称为空串(用\phi表示)。

几个专业术语

子串:串中任意个连续的字符组成的子序列(空串也是字符串的子串)。

主串:包含子串的串。

字符在主串中的位置:字符在串中的序号(从1开始)。

子串在主串中的位置:子串的第一个字符在主串中的位置(从1开始)。

空串与空格串:

空串:单引号之间没有任何字符,如下面的M。

空格串:有多个空格字符组成的字符串,每个空格字符占1B,如下面 的N。

是一种特殊的线性表,数据元素之间呈线性关系。线性表中存放的数据对象可以是各种类型的,但是串的数据对象限定为字符集(如中文字符、英文字符、数字字符、标点字符等),串的基本操作,如增删改查等通常以子串(多个数据对象)为操作对象。

2.串的基本操作

StrAssign(&T,chars):赋值操作。把串T赋值为chars。

StrCopy(&T,S):复制操作。由串S复制得到串T。

StrEmpty(S):判空操作。若S为空串,则返回TRUE,否则返回FALSE

StrLength(S):求串长。返回串S的元素个数。

ClearString(&S):清空操作。将S清为空串。

DestroyString(&S):销毁串。将串S销毁(回收存储空间)。

Concat(&T,S1,S2):串联接。用T返回由S1和S2联接而成的新串

SubString(&Sub,S,pos,len):求子串。用Sub返回串S的第pos个字符起长度为len的子串。

Index(S,T):定位操作。若主串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的位置;否则函数值为0。

StrCompare(S,T):比较操作。若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0。

比较规则

计算机只能存储二进制数,需要确定一个编码的规则,使得各个字符与二进制数能够一一对应起来,比较字符就是在比较二进制数的大小,例如'a'的Ascll码是97,对应的二进制就是

0110 0001,'A'的Ascll码是65,对应的二进制为0100 0001。

Ascll码表可以看:ASCII 表 | 菜鸟教程 (runoob.com)

Ascll字符集只是英文字符的集合。但是,除了英文字符外,还有很多其他字符(例如:中文,法语等),Ascll字符集中无法包含所有的字符,因为Ascll字符集中,每个字符占用的空间为1B(8bit的二进制数),只能表示2的8次方,即256个状态。

所以出现了其他字符集,如Unicode字符集,包含了中英文字符的集合。这些字符通过一个编码方案映射为二进制数(一个字符集可以有多个编码方案,例如UTF-8和UTF-16就是两种不同的Unicode编码方案)。

注:采用不同的编码方式,每个字符所占空间不同,考研中只需默认每个字符占1B即可。

1.从第一个字符开始往后依次对比,先出现更大字符的串就更大 。

2.长串的前缀与短串相同时,长串更大。

3.只有两个串完全相同时,才相等。

3.串的存储结构

(1)串的定义
•顺序存储
//定长顺序存储
#define MAXLEN 255    //预定义最大串长为255
typedef struct{char ch[MAXLEN];    //每个分量存储一个字符int length;    //串的实际长度
}SString;//堆分配存储(用malloc函数申请的内存空间属于内存的堆区)
typedef struct{char *ch;    //按串长分配存储区,ch指向串的基地址int length;    //串的长度
}HString;HString S;
S.ch=(char *)malloc(MAXLEN * sizeof(char));
S.length=0;//由malloc申请的内存空间需要手动free回收,而用静态数组申请的空间是由系统自动回收的。

顺序存储的实现:

在方案一中,专门声明一个int型变量length表示字符串的长度。

在方案二中,若用ch[0]来存储字符串的长度,那么字符的位序和数组下标相同。但是一个字符只占8bit,其所能表示的数字范围为0~255。

在方案三中没有Length变量,以字符’\0'表示结尾(对应ASCIl码的 0),采用这种方式,若想知道字符串的长度,需要从头到尾扫描,扫描到‘\0’才能得到字符串的长度。若经常访问字符串的长度,那么这种方案就是不太可取的。

方案四中采用了方案1与方案2的结合,即舍弃ch[0]不用,并且专门声明一个int型的变量length表示字符串的长度。下面顺序存储的代码编写都是以方案四为存储结构的。

•链式存储
typedef struct StringNode{char ch;    //每个结点存1个字符struct StringNode * next;
}StringNode,* String;

一个char的大小为1B,但是在32位计算机中,指针大小为4B,这就表示我们在存储一个字符时,只用了1B存储实际需要存储的信息,用了4B存储了辅助信息。这样存储密度就太低了。

如何解决?

typedef struct StringNode{char ch[4];    //每个结点存多个字符struct StringNode * next;
}StringNode,* String;

:若最后一个结点的字符存不满,那么可以用一些特殊的字符填充进去,如'#'或'\0'。

(2)求串长
int StringLength(SString S){return S.length;
}
(3)求子串

SubString(&Sub,S,pos,len):求子串。用Sub返回串S的第pos个字符起长度为len的子串。

bool SubString(String &Sub,SString S,int pos,int len){if(pos+len-1>S.length)return false;    //子串范围越界for(int i=pos;i<pos+len;i++)Sub.ch[i-pos+1]=S.ch[i];Sub.length=len;return true;}

(4)比较串的大小

StrCompare(S,T):比较操作。若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0。

int StrCompare(SString S,SString T){for(int i=1;i<=S.length && i<T.length;i++){if(S.ch[i]!=T.ch[i])return S.ch[i]-T.ch[i]; }//扫描过的所有字符都相同,则长度长的串更大return S.length-T.length;
}

(5)定位操作

Index(S,T):定位操作。若主串S中存在与串T值相同的子串,则返回它在主串s中第一次出现的
位置;否则函数值为0。

int StringLength(SString S){return S.length;
}bool SubString(String &Sub,SString S,int pos,int len){if(pos+len-1>S.length)return false;    //子串范围越界for(int i=pos;i<pos+len;i++)Sub.ch[i-pos+1]=S.ch[i];Sub.length=len;return true;
}int StrCompare(SString S,SString T){for(int i=1;i<=S.length && i<T.length;i++){if(S.ch[i]!=T.ch[i])return S.ch[i]-T.ch[i]; }//扫描过的所有字符都相同,则长度长的串更大return S.length-T.length;
}int Index(SString S,SString T){int i=1,n=StrLength(S),m=StrLength(T);SString sub;    //用于暂存子串while(i<=n-m+1){SubString(sub,S,i,m);if(StrCompare(sub,T)!=0)    ++i;else return i;    //返回子串在主串中的位置}return 0;    //S中不存在与T相等的子串 
}

4.字符串的模式匹配

字符串模式匹配就是在主串(被查找串)中找到与模式串(想要查找的字符串)相同的子串,并返回其所在位置。

子串:主串的一部分,一定存在

模式串:不一定在主串中找到

(1)朴素模式匹配算法

若主串长度为n,模式串长度为 m,将主串中所有长度为m的子串依次与模式串对比,直到找到一个完全匹配的子串或所有的子串都不匹配为止。

长度为n的主串中,最多有n-m+1个子串

上面说的定位操作,即Index(S,T),就是一种朴素模式匹配算法:

int Index(SString S,SString T){int i=1,n=StrLength(S),m=StrLength(T);SString sub;    //用于暂存子串while(i<=n-m+1){SubString(sub,S,i,m);if(StrCompare(sub,T)!=0)    ++i;else return i;    //返回子串在主串中的位置}return 0;    //S中不存在与T相等的子串 
}

也可以直接通过数组下标实现朴素模式匹配算法

设置两个扫描指针i,j,将两个指针指向的字符依次对比,若指针指向的字符相同,就将指针一起后移。

若匹配失败,如上图所示,则主串指针 i 指向下一个子串的第一个位置,模式串指针 j 回到模式串的第一个位置。

 

只需要改变i,j指针的指向,就可以完成以上操作。

i=i-j+2;    //i-(j-1)相当于i回到开始的位置,再加1就是下一个字符串
j=1;    //j-(j-1)就相当于回到了1

在下一个串中匹配失败,i-j+2 指向下一个串,j继续重新指回1

若j>T.length(j指向的位置超出了模式串的长度),则当前子串匹配成功,返回当前子串第一个字符的位置 ---- i-T.length

int Index(SString S,SString T){int i=1,j=1;while(i<=S.length && j<=T.length){if(S.ch[i]==T.ch[i]){++i;++j;    //继续比较后继字符}else{i=i-j+2;j=1;    //指针回退重新开始匹配}}if(j>T.length)return i-T.length;elsereturn 0;
}

设主串长度为n,模式串长度为m,那么最坏时间复杂度=O(nm)

若主串和模式串如下图所示, 最坏的情况,每个子串都要对比 m 个字符,共 n-m+1 个子串,复杂度=O((n-m+1)m) = O(nm-m^2+m) = O(nm),通常情况下n>>m

(2)KMP算法

在朴素模式匹配算法中,若主串与模式串不匹配,那么i就要回退到2,j回退到1。换个角度也可以理解为,将模式串往右移动了一步。

匹配失败,模式串继续右移。朴素模式匹配算法的缺点就是,当某些子串与模式串能部分匹配时,主串的扫描指针 i 经常回溯,导致时间开销增加。

所以KMP算法针对这一点进行了改进,即主串指针不回溯,只有模式串指针回溯。

若扫描到不匹配的字符,那么就将这个字符与模式串的第一个字符进行比较,即 i 指向的位置不变,j指回1。也可以理解为模式串往后移动了5步,相比于朴素匹配算法中模式串一步一步右移,这个算法的效率提高了很多。

1.若这个字符也为g,那么就让i++,j++,也就是继续匹配后一个字符。

2.若这个字符不为j,那么就 i++,j依然保持1

3.若扫描到 j =5,才发现匹配失败,也就是 i指向的字符不是“l”。

也就是以“g”开头的字符串与模式串是不匹配的,同理,因为之前扫描过的“o”“o”,都匹配上了(不匹配的字符之前,主串的字符一定是和模式串一致的),那么以“o”开头的字符串肯定也匹配不上。

但是以g开头的子串是可能与模式串进行匹配的,但是在代码中只是判断了i指向的字符与“l”是不匹配的,所以我们可以间接判断,i指向的字符是不是“o”,因为“g”后面是“o”。

所以若j=5 时发生不匹配,则应让 j 回到 2。

4.若 j=4 时发生不匹配,则应让 j 回到1。但是其实这里 i 指向字符一定不是 “g” 了

那么让j回到1,继续重新匹配,就会在开头进行一次没有必要的对比

但是相比于朴素匹配算法而言,他已经少对比了2次了。改进方法在KMP算法的改进中会讲。

5.若 j=3 时发生不匹配,则应让j回到1

相比于朴素算法而言,少进行了一次对比

6.若j=2时发生不匹配,则应让 j 回到1

总结:

当j=k且发现字符不匹配时,令j=next[k]。例如,当j=5发现不匹配时,那么就让j=next[5],即2。

注:当j=1,即第1个字符匹配失败时,先令j=0,再进行i++,j++,就可以使i往后扫描字符,而j保持1。看代码应该能更好理解。

所以KMP算法的关键根据模式串的内容设计出合适的数组next。next数组只和模式串有关,和主串没有关系,也就是说只要模式串不变,不管主串是什么,next数组都是一样的。

代码如下:

int Index_KMP(SString S,SString T,int next[]){int i=1,j=1;while(i<=S.length && j<=T.length){if(j==0 || S.ch[i]==T.ch[j])    
//刚开始j=1,若j=1时,两个字符不匹配,那么跳转到else
//else中,j=next[j],j=next[1]=0,若j=0,那么++i,让i指针向后扫描,并且让j指针保持1{++i;++j;    //继续比较后继字符}elsej=next[j];    //模式串向右移动}if(j>T.length)return i-T.length;    //匹配成功elsereturn 0;}

相比于朴素模式匹配,KMP算法修改了两个部分,当主串和模式串不匹配时,不需要主串指针i回溯,只需要修改模式串中指针 j 即可。

•求模式串中的next数组(重点)

当模式串的第 j 个字符匹配失败时,令模式串跳到 next[j] 再继续匹配。

如下图所示,若j=6时不匹配,应该让next[6]=3,即让 j 指向3,或者说模式串向右移动3位。对比主串中i指向的字符和c是否能匹配。

同理,当j=7时,匹配失败,将模式串往右移动2位,让j=5,看i指向的字符能否与"a"匹配(next[7]=5)。

若刚开始i指向的字符“a”与“c”不匹配,并且将模式串直接向右移动了4位,即next[7]=3,如下图所示:

那么继续往后检查,当i指向字符“c”时,发现a,c并不匹配。

但是按照刚开始的方案,即符号串往右移动2位,那么字符应该是匹配的。

所以只要模式串中有更长的部分能匹配,那么就只考虑更长的情况:

特殊的情况上面已经说过了,即j=1时匹配失败,那么只能紧接着匹配下一个子串,先令j=0,然后让i++,j++,i向后继续扫描,而j=1。所以对任何一个字符串而言,next[1]都为0。

我们将以下红框部分称为串的前缀包含第一个字符,且不包含最后一个字符的子串。

串的后缀包含最后一个字符,且不包含第一个字符的子串。

得出结论:当第 j 个字符匹配失败,由前1~j-1个字符组成的串记为S,则:next[j]= S的最长相等前后缀长度+1。并且next[1]是固定为0的。

例如上图,最长相等前后缀=4,那么next[j]=4+1=5。

练习

模式串:‘ababaa’

1.next[1]=0

2.next[2]表示当匹配到第2个字符时匹配失败,在第2个字符之前组成的串'a'。'a'不存在前缀和后缀,所以其最长前后缀长度=0,所以也可以总结next[2]一定是1

3.next[3]表示当匹配到第3个字符时匹配失败,第3个字符之前组成的串是'ab',其最长相等前后缀长度也为0,所以next[3]=1

4.同理第4个字符前面的字符串“aba",其最长相等前后缀长度为1,所以next[4]=1+1=2

5.第5个字符前面的字符串“abab”,所以next[5]=2+1=3

6.第6个字符前面的字符串为“ababa”,所以next[6]=3+1=4

所以模式串“ababaa”的next数组如下:

代码实现如下:

//求模式串T的next数组
void get_next(SString T,int next[]){    T为模式串int i=1,j=0;next[1]=0;while(i< T.length){   if(j==0 || T.ch[i]=T.ch[j]){    ++i; ++j; //若pi=pj,则next[j+1]=next[j]+1  next[i]=j;}else//否则令j=next[j],循环继续j=next[j];}
}
//while循环中i<T.length,也就是i的范围是1~m,所以可以认为这个函数的时间复杂度为O(m)//KMP算法
int Index_KMP(SString S,SString T){int i=1,j=1;int next[T.length+1];get_next(T,next);    //求模式串的next数组while(i<=S.length && j<=T.length){if(j==0 || S.ch[i]==T.ch[j])    {++i;++j;    //继续比较后继字符}elsej=next[j];    //模式串向右移动}if(j>T.length)return i-T.length;    //匹配成功elsereturn 0;
}
//在KMP算法中,i由1~n,再加上调用的get_next函数,所以KMP算法的时间复杂度为O(n+m)

朴素模式匹配算法中,当某些子串与模式串能部分匹配时,主串的扫描指针 i 经常回溯,导致时间开销增加。最坏时间复杂度O(nm)。而KMP算法中,根据模式串T求出next数组,当子串和模式串不匹配时,利用next数组进行匹配,主串指针 i 不回溯,模式串指针 j=next[j] 。算法最坏时间复杂度:O(n+m),其中,求 next 数组时间复杂度O(m),模式匹配过程最坏时间复杂度 O(n)

如果不会经常出现子串与模式串部分匹配问题,那么KMP算法就显先不出很大的优势。

(3)KMP算法的进一步优化

KMP算法是通过next数组进行匹配的。下面例子中,j指向的字符是a,那么说明主串中的第3个字符一定不是a。

当j=3的字符与主串不匹配时,让j指针指向1,那么j指向的字符a与主串中第3个字符肯定是不匹配的。

所以当j=1的字符与匹配失败的字符相等时,直接让next[3]=0,跳过中间next[3]--->next[1]--->0这一步。

同理:

当j=5时,模式串与主串的值不匹配,即主串的第5个字符不是"b",那么让next[5]=2。

但是由于第2个字符与匹配失败的这一字符相等,所以让 j 指向第2个位置后,接下来的匹配一定是不成功的。这次匹配失败后,next[2]=1,让j=1。

所以可以直接跳过注定匹配失败的那一步,直接让next[5]=1,这样就能少做一次对比。

所以总结下来,如果next数组所指的字符与原本失配的字符相等的话,就可以对next数组优化,如果不等的话,则next数组的值是不变的。

在KMP算法的优化中,我们只优化了next数组,所以在进行KMP算法中,将nextval[]数组替换next[]数组即可。

•求nextval数组的方法(重点)

若模式串ababaa的next数组如下图所示:

nextval[1]=0;        //nextval[1]的值直接写0

如果next[j]所指的字符,与j所指的字符不相同,就让nextval[j]=next[j],例如下图,当前j所指的字符是b,而其next[2]所指的字符是a,两者不同,那么nextval[2]=1 不变。

如果j指向的字符与next[j]所指的字符相同,例如下图,j=3时,j所指的字符是a,其next[3]所指的字符也是a,那么就让nextval的值优化为next[1]的值0。

nextval[j]=nextval[next[j]];        //nextval[3]=nextval[next[3]]

以此类推:

j=5时指向的是a,next[5]也是a,那么其nextval[5]等于0,不再等于1了,根据已经优化的数组来。

最后得到:

代码如下:

nextval[i]=0;
for (int j=2;i<=T.length;j++){if(T.ch[next[j]]==T.ch[j])nextval[j]=nextval[next[j]];elsenextval[j]=next[j];
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++】二维数组传参方式

最近刚开始刷剑指offer&#xff0c;刚做到第三题的时候&#xff0c;发现C二维数组的传参方式和C语言略有些不同&#xff0c;所以在这篇博客中&#xff0c;会列出C/C常见的二维数组传参方式。&#xff08;本方式和代码都是基于vs环境所编写&#xff09; 一.C语言二维数组传参方式…

如何将Oracle 中的部分不兼容对象迁移到 OceanBase

本文总结分析了 Oracle 迁移至 OceanBase 时&#xff0c;在出现三种不兼容对象的情况时的处理策略以及迁移前的预检方式&#xff0c;通过提前发现并处理这些问题&#xff0c;可以有效规避迁移过程中的报错风险。 作者&#xff1a;余振兴&#xff0c;爱可生 DBA 团队成员&#x…

React【Day2】

React表单控制 受控绑定 概念&#xff1a;使用React组件的状态&#xff08;useState&#xff09;控制表单的状态 双向绑定 MVVM 报错记录&#xff1a; 错误代码&#xff1a; import { useState } from "react";const App () > {const [value, setValue] useS…

OpenCV从入门到精通实战(八)——基于dlib的人脸关键点定位

本文使用Python库dlib和OpenCV来实现面部特征点的检测和标注。 下面是代码的主要步骤和相关的代码片段&#xff1a; 步骤一&#xff1a;导入必要的库和设置参数 首先&#xff0c;代码导入了必要的Python库&#xff0c;并通过argparse设置了输入图像和面部标记预测器的参数。…

从OWASP API Security TOP 10谈API安全

1.前言 应用程序编程接口&#xff08;API&#xff09;是当今应用驱动世界创新的一个基本元素。从银行、零售、运输到物联网、 自动驾驶汽车、智慧城市&#xff0c;API 是现代移动、SaaS 和 web 应用程序的重要组成部分&#xff0c;可以在面向客 户、面向合作伙伴和内部的应用程…

从零实现诗词GPT大模型:数据集介绍和预处理

专栏规划: https://qibin.blog.csdn.net/article/details/137728228 本章将介绍该系列文章中使用的数据集&#xff0c;并且编写预处理代码&#xff0c;处理成咱们需要的格式。 一、数据集介绍 咱们使用的数据集名称是chinese-poetry&#xff0c;是一个在github上开源的中文诗…

Android开发:Camera2+MediaRecorder录制视频后上传到阿里云VOD

文章目录 版权声明前言1.Camera1和Camera2的区别2.为什么选择Camera2&#xff1f; 一、应用Camera2MediaPlayer实现拍摄功能引入所需权限构建UI界面的XMLActivity中的代码部分 二、在上述界面录制结束后点击跳转新的界面进行视频播放构建播放界面部分的XMLActivity的代码上述代…

一个基于单片机内存管理-开源模块

概述 此模块是一位大佬写的应用于单片机内存管理模块mem_malloc,这个mem_malloc的使用不会产生内存碎片,可以高效利用单片机ram空间。 源码仓库:GitHub - chenqy2018/mem_malloc mem_malloc介绍 一般单片机的内存都比较小,而且没有MMU,malloc 与free的使用容易造成内存碎…

Linux 添加启动服务--Service

1&#xff0c;服务配置service文件 Service 服务的实际作用是开启后自动启动服务&#xff0c;运行一些不须要登录的程序&#xff0c;任务。 实例1、上电自动连接WIFI热点 1.1 新建.service文件 /etc/systemd/system/wificonnect.service [Unit] DescriptionService [wifico…

react 项目路由配置(react-router-dom 版本 v6.3、v6.4)

根据 react-router-dom 的版本&#xff0c;有不同的方式 一、react-router-dom v6.3 用到的主要 api: BrowserRouteruseRoutesOutlet 下面是详细步骤&#xff1a; 1、index.js BrowserRouter 用来实现 单页的客户端路由使用 BrowserRouter 包裹 App放在 顶级 位置&#x…

【IoTDB 线上小课 02】开源增益的大厂研发岗面经

还有友友不知道我们的【IoTDB 视频小课】系列吗&#xff1f; 关于 IoTDB&#xff0c;关于物联网&#xff0c;关于时序数据库&#xff0c;关于开源...给我们 5 分钟&#xff0c;持续学习&#xff0c;干货满满~ 5分钟学会 大厂研发岗面试 之前的第一期小课&#xff0c;我们听了 I…

【leetcode面试经典150题】58. 两数相加(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…

MySQL高级(性能分析-查看执行频次、慢查询日志)

目录 1、SQL性能分析 1.1、SQL执行频率 1.2、慢查询日志 1、SQL性能分析 1.1、SQL执行频率 MySQL 客户端连接成功后&#xff0c;通过 show [ session | global ] status 命令可以提供服务器状态信息。通过如下指令&#xff0c;可以查看当前数据库的 insert、update、delete、…

绿色自适应网址发布页源码

源码介绍 绿色自适应网址发布页源码&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c;重定向这个界面 效果截图 源码下载 绿色自适应网址…

Linux--进程间的通信-命名管道

前文&#xff1a; Linux–进程间的通信-匿名管道 Linux–进程间的通信–进程池 命名管道的概念 命名管道是一种进程间通信&#xff08;IPC&#xff09;机制&#xff0c;运行不同进程之间进行可靠的、单向或双向的数据通信。 特点和作用&#xff1a; 跨平台性&#xff1a;在W…

CST电磁仿真物体表面的Sheet结构和生成3D Model【基础教程】

由Sheet结构生成3D Model 使用Shell Solid and Thicken Sheet&#xff01; Modeling > Tools > Shape Tools > Shell Solid or Thicken Sheet Shell Solidor ThickenSheet会根据不同类型的模型提供两种完全不同的功能。 如033.由3D Model生成Cavity 所述&#xff…

数据结构(七)——B树和B+树

7.4.1_1 B树 5叉查找树 //5叉排序树的结点定义 struct Node {ElemType keys[4]; //最多4个关键字struct Node &child[5]; //最多5个孩子int num; //结点中有几个关键字 }; 如何保证查找效率&#xff1f; eg:对于5叉排序树&#xff0c;规定…

反射

目录 01、Java反射机制概述1.1、使用反射&#xff0c;实现同上的操作、调用私有属性 02、理解Class类并获取Class实例2.1、Class类的理解2.2、获取Class实例的4种方式2.3、Class实例对应的结构的说明 03、ClassLoader的理解3.1、ClassLoader的理解3.2、使用ClassLoader加载配置…

LabVIEW光学探测器板级检测系统

LabVIEW光学探测器板级检测系统 特种车辆乘员舱的灭火抑爆系统广泛采用光学探测技术来探测火情。光学探测器作为系统的关键部件&#xff0c;其探测灵敏度、响应速度和准确性直接关系到整个系统的运行效率和安全性。然而&#xff0c;光学探测器在长期使用过程中可能会因为灰尘污…

Android --- Activity

官方文档-activity Activity 提供窗口&#xff0c;供应在其中多个界面。此窗口通常会填满屏幕&#xff0c;但也可能小于屏幕并浮动在其他窗口之上。 大多数应用包含多个屏幕&#xff0c;这意味着它们包含多个 Activity。通常&#xff0c;应用中的一个 Activity 会被指定主 Ac…