3.数据结构-串、数组和广义表

news2025/7/14 9:11:37

串、数组和广义表

  • 3.1串
    • 3.1.1串的类型定义、存储结构及其运算
      • 串的顺序存储
      • 串的堆式顺序存储结构
      • 串的链式存储
    • 3.1.2 串的模式匹配算法
      • BF算法
      • *KMP算法(待更新)
  • 3.2数组
    • 3.2.1数组的顺序存储
    • 3.2.2特殊矩阵的压缩存储
      • 对称矩阵
      • 三角矩阵
      • 对角矩阵
  • 3.3广义表
      • *案例病毒感染检测

3.1串

串是由零个或多个字符组成的有限序列,一般记为 s = " a 1 a 2 . . . a n " ( n ≥ 0 ) s="a_1 a_2 ...a_n "(n \ge0) s="a1a2...an"(n0),其中s是串的名,用双引号括起来的字符序列是串的值; a i ( 1 ≤ i ≤ n ) a_i(1\le i \le n) ai(1in)可以是字母、数字或其他字符;串中字符的数目n称为串的长度。零个字符的串称为空串,其长度为0。

串中任意个连续的字符组成的子序列称为该串的子串。包含子串的串相应地称为主串。通常称字符在序列中的序号为该字符在串中的位置。

称两个串是相等的,当且仅当这两个串的值相等,也就是说,只有当这两个串的长度相等并且各个对应位置的字符都相等时才相等。而由一个或多个空格组成的串“ ”称为空格串

3.1.1串的类型定义、存储结构及其运算

串的顺序存储

类似于线性表的顺序存储结构,用一组地址连续的存储单元存储串值的字符序列。按照预定义的大小,为每个定义的串变量分配一个固定长度的存储区,可以用定长数组描述:

typedef struct{
    char ch[MAXLEN+1];
    int length; //字符串当前长度
}SString;

完整操作

#include<iostream>

#define MAXLEN 255
#define QElemType int
#define Status int

using namespace std;

typedef struct{
    char ch[MAXLEN+1];
    int length;
}SString;

void StrAssign(SString &T, string chars){
    //将chars的值赋给T
    int len = T.length < MAXLEN ? T.length : MAXLEN;
    for(int i = 0; i < len; i ++){
        T.ch[i] = chars[i];
    }
    T.length = len;
    T.ch[len] = '\0';  // 确保以空字符结尾
}

void StrCopy(SString &T, SString &S){
    //由串S复制得串T
    int len = S.length < MAXLEN ? S.length : MAXLEN;
    
    for(int i = 0; i < len; i ++){
        T.ch[i] = S.ch[i];
    }
    T.length = S.length;
    T.ch[len] = '\0';  // 确保以空字符结尾
}

bool StrEmpty(SString T){
    return T.length > 0;
}

Status StrCompare(SString &T, SString &S){
    //若S>T返回值>0,S=T返回0,S<T返回<0
    int minLength = (T.length < S.length) ? T.length : S.length;

    // 逐字符比较
    for (int i = 0; i < minLength; i++) {
        if (T.ch[i] != S.ch[i]) {
            return T.ch[i] - S.ch[i];  // 返回 ASCII 差值
        }
    }

    // 若前面字符都相等,则比较长度
    return T.length - S.length;
}


int main()
{
	SString T, S;
	string chars;
	getline(cin, chars);
	
	StrAssign(S, chars);
	cout << S.ch << endl;
	
	StrCopy(T, S);
	cout << T.ch << endl;
	
	cout << StrEmpty(T) << endl;
	
	cout << StrCompare(S, T) << endl;
	
	return 0;
	
} 

这种存储方式是静态的存储的大小是固定了的,而在实际过程中我们需要动态的分配和释放字符数组空间。

串的堆式顺序存储结构

在C语言中,存在一个称之为**“堆(Heap)”**的自由存储区,可以为每个新产生的串动态分配一块实际串长所需要的存储空间,若分配成功,则返回一个指向起始地址的指针,作为串的基址。

typedef struct{
    char *ch; //若为非空串,则按串长分配存储区,否则ch为NULL
    int length; //串的当前长度
}HString;

完整操作

#include<iostream>
#include<cstring>

#define MAXLEN 255
#define QElemType int
#define Status int

using namespace std;

typedef struct{
    char *ch; //若为非空串,则按串长分配存储区,否则ch为NULL
    int length; //串的当前长度
}HString;

void StrAssign(HString &T, string chars) {
    // 释放 T 原有的内存,避免内存泄漏
    if (T.ch != NULL) {
        delete[] T.ch;
        T.ch = NULL;
    }

    // 获取 chars 长度
    T.length = chars.length();

    // 若 chars 为空,则 T.ch 设为 NULL
    if (T.length == 0) {
        T.ch = NULL;
        return;
    }

    // 动态分配空间存储 chars,并复制字符串
    T.ch = new char[T.length + 1];  // +1 预留 '\0' 结尾符
    strcpy(T.ch, chars.c_str());    // 拷贝字符串
}

// 复制串 S 到 T
void StrCopy(HString &T, HString &S) {
    // 先释放 T 原有的内存,避免内存泄漏
    if (T.ch != NULL) {
        delete[] T.ch;
        T.ch = NULL;
    }

    // 复制长度
    T.length = S.length;

    // 若 S 为空串,则 T 也设为空串
    if (S.length == 0 || S.ch == NULL) {
        T.ch = NULL;
        return;
    }

    // 分配新空间并复制内容
    T.ch = new char[T.length + 1]; // 额外 +1 以存放 '\0'
    strcpy(T.ch, S.ch);  // 拷贝字符串
}

Status StrCompare(HString &T, HString &S) {
    int minLength = (T.length < S.length) ? T.length : S.length;  // 找到最短的长度

    // 逐字符比较
    for (int i = 0; i < minLength; i++) {
        if (T.ch[i] != S.ch[i]) {
            return T.ch[i] - S.ch[i];  // 返回字符 ASCII 差值
        }
    }

    // 如果前面所有字符都相等,则比较字符串的长度
    return T.length - S.length;  // 长度更长的字符串较大
}



int main()
{
	HString T, S;
	T.ch = NULL, S.ch = NULL;
	T.length = 0, S.length = 0;
	
	string chars;
	getline(cin, chars);
	
	StrAssign(S, chars);
	cout << S.ch << endl;
	
	StrCopy(T, S);
	cout << T.ch << endl;
	
	return 0;
	
} 

串的链式存储

顺序串的插入和删除操作都不方便,需要移动大量的字符。因此,可采用单链表方式存储,每一个结点可以存放一个字符,也可以放多个字符。当结点大小大于1时,由于串长不一定是结点大小的整数倍,则链表中的最后一个结点不一定全倍串值占满,此时通常补上**“#”**或其他的非串值字符。
为了便于进行串的操作,当以链表存储串值时,除头指针外,还可以附设一个尾指针指示链表中的最后一个结点,并给出当前串的长度。

typedef struct Chunk{
    char ch[MAXLEN];
    struct Chunk *next;
};

typedef struct{
    Chunk *head, *tail;
    int length; //串的当前长度
}LString;

完整操作

#include<iostream>
#include<cstring>

#define MAXLEN 255
#define QElemType int
#define Status int

using namespace std;

typedef struct Chunk{
    char ch[MAXLEN];
    struct Chunk *next;
};

typedef struct{
    Chunk *head, *tail;
    int length; //串的当前长度
}LString;

void StrAssign(LString &T, string chars) {
    // 初始化链表, 
    T.head = T.tail = nullptr;
    T.length = 0;

    int charsLeft = chars.length();
    int currentIndex = 0;

    // 分段将字符串 chars 存入链表
    while (charsLeft > 0) {
        // 计算当前块存储的字符数量(最多 MAXLEN)
        int chunkLength = (charsLeft > MAXLEN) ? MAXLEN : charsLeft;
        
        // 创建新的 Chunk
        Chunk *newChunk = new Chunk;
        
        for (int i = 0; i < chunkLength; ++i) {
            newChunk->ch[i] = chars[currentIndex + i]; // 填充字符
        }
        newChunk->ch[chunkLength] = '\0'; // 确保以 '\0' 结尾
        newChunk->next = nullptr; // 最后一个块的 next 指向 nullptr
        
        // 将 newChunk 加入链表
        if (T.tail == nullptr) {
            T.head = T.tail = newChunk; // 链表为空时,head 和 tail 都指向 newChunk
        } else {
            T.tail->next = newChunk;  // 将 newChunk 添加到尾部
            T.tail = newChunk;         // 更新尾指针
        }

        // 更新剩余字符数, chars可能会大于MAXLEN,但是每个字节最多存储MAXLEN,所以要分段
        currentIndex += chunkLength;
        charsLeft -= chunkLength;
        T.length += chunkLength; // 更新链表的总长度
    }
}


void PrintLString(LString &T) {
    Chunk *current = T.head;
    while (current != nullptr) {
        cout << current->ch; // 打印当前 Chunk 存储的字符
        current = current->next; // 移动到下一个 Chunk
    }
    cout << endl;
}

void StrInsert(LString &S, int pos, LString T) {
    if (pos < 0 || pos > S.length) {
        cout << "插入位置无效!" << endl;
        return;
    }

    // 如果要插入的位置是0,直接将 T 插入到 S 的开头
    if (pos == 0) {
        T.tail->next = S.head;
        S.head = T.head;
        if (S.tail == nullptr) { // 如果 S 本来是空链表,更新尾指针
            S.tail = T.tail;
        }
        S.length += T.length;
        return;
    }

    // 定位到插入位置前的节点
    Chunk *current = S.head;
    int currentPos = 0;
    
    while (current != nullptr && currentPos < pos - 1) {
        current = current->next;
        currentPos++;
    }

    // 插入操作
    if (current != nullptr) {
        // 将 S 的第 pos 位置分成两部分
        Chunk *nextChunk = current->next;

        // 插入 T 到当前节点后面
        current->next = T.head;
        T.tail->next = nextChunk;

        // 如果插入的位置是链表末尾,更新 S 的尾指针
        if (nextChunk == nullptr) {
            S.tail = T.tail;
        }

        S.length += T.length;
    }
}

void StrDelete(LString &S, int pos, int len) {
    // 检查删除位置是否合法
    if (pos < 0 || pos >= S.length || pos + len > S.length) {
        cout << "删除位置无效!" << endl;
        return;
    }

    Chunk *current = S.head;
    Chunk *prev = nullptr;
    int currentPos = 0;

    // 遍历到要删除的起始位置
    while (current != nullptr && currentPos < pos) {
        prev = current;
        current = current->next;
        currentPos++;
    }

    // `prev` 现在是待删除部分前一个节点,`current` 是待删除部分的第一个节点
    Chunk *deleteStart = current;

    // 遍历到删除的结束位置
    while (current != nullptr && currentPos < pos + len) {
        Chunk *temp = current;
        current = current->next;
        delete temp;  // 释放当前节点的内存
        currentPos++;
    }

    // 连接删除后的部分
    if (prev != nullptr) {
        prev->next = current;  // 如果删除的不是从头开始,更新前一个节点的指针
    } else {
        S.head = current;  // 如果删除的是从头开始,更新头指针
    }

    // 如果删除的部分在尾部,需要更新尾指针
    if (current == nullptr) {
        S.tail = prev;
    }

    // 更新链表的长度
    S.length -= len;
}




int main()
{
    LString S, T;
	
	string chars;
	getline(cin, chars);
	
	StrAssign(S, chars);
	PrintLString(S);
	
// 	StrInsert(T, 1, S);
// 	PrintLString(T);
	
	StrDelete(S, 1, 3);
	PrintLString(S);
	
	return 0;
	
} 

3.1.2 串的模式匹配算法

子串的定位运算通常称为串的模式匹配串匹配
串的模式匹配设有两个字符串S和T,设S为主串,也称正文串;设T为子串,也称为模式。在主串S中查找与模式T相匹配的子串,如果匹配成功,确定相匹配的子串中的第一个字符在主串S中出现的位置。

BF算法

模式匹配不一定是从主串的第一个位置开始,可以指定主串中查找的起始位置pos。如果采用字符串顺序存储结构,可以写出不依赖于其他串操作的匹配算法。
【算法步骤】
1.分别利用计数指针i和j指示主串S和模式T中当前正待比较的字符位置,i初值为pos,j的初值为;
2.如果两个串均未比较到串尾,即i和j均分别小于等于S和T的长度时,则循环执行一下操作:

  • S[i].ch和T[j].ch比较,若相等,则i和j分别指示串中下个位置,继续比较后续字符
  • 若不等,指针后退重新开始匹配,从主串的下一个字符 ( i = i − j + 2 ) (i=i-j+2) (i=ij+2)起再重新和模式的第一个字符 ( j = 1 ) (j=1) (j=1)比较。(为什么是 ( i = i − j + 2 ) (i=i-j+2) (i=ij+2),因为从i开始长度为j的这段子串与模式T是不匹配的,直接从这个子串的下一个字符开始比较)

3.如果j>T.length,说明模式T中的每个字符依次和主串S中的一个连续的字符序列相等,则匹配成功,返回和模式T中第一个字符相等的字符在主串S中的序号 ( i − T . l e n g t h ) (i-T.length) (iT.length);否则匹配不成功。

#include<iostream>

#define MAXLEN 255
#define QElemType int
#define Status int

using namespace std;

typedef struct{
    char ch[MAXLEN+1];
    int length;
}SString;

void StrAssign(SString &T, string chars){
    //将chars的值赋给T
    int len = chars.length();
    for(int i = 0; i < len; i ++){
        T.ch[i] = chars[i];
    }
    T.length = len;
    T.ch[len] = '\0';  // 确保以空字符结尾
}

int Index_BF(SString S, SString T, int pos){
    int i = pos, j = 0;
    while(i < S.length && j < T.length){
        if(S.ch[i] == T.ch[j]){++i, ++j;}
        else{
            i = i - j + 1;
            j = 0;
        }
    }
    if(j >= T.length) return i-T.length;
    else return -1;
}

int main()
{
	SString T, S;
	string chars;
	getline(cin, chars);
	StrAssign(S, chars);
	
	getline(cin, chars);
	StrAssign(T, chars);

	int indexx = 0;
	for(int i = 0; i < S.length; i ++){
	    indexx = Index_BF(S, T, i);
	    if(indexx+1 > 0){
	        cout << indexx+1 << endl;
	        break;
	    }
	}
	 
	return 0;
	
} 

代码与上述描述不一样的 i − j + 2 i-j+2 ij+2是因为描述时默认下标为1开始,实际是从0开始的。
BF算法最快的情况下就是 O ( n + m ) O(n+m) O(n+m),最坏的情况下的平均时间复杂度则是 O ( n ∗ m ) O(n*m) O(nm),可以看出时间复杂度还是较高,接下来介绍另一种改进的模式匹配算法。

*KMP算法(待更新)

此算法可以在 O ( n + m ) O(n+m) O(n+m)的时间数量级完成串的模式匹配操作。其改进在于:每当一趟匹配过程中出现字符比较不等时,不需要回溯 i i i指针,而是利用已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远的一段距离,继续进行比较。

博主也看了很久才逐渐明白,起始本质就是求最长前后公共缀。看完书后然后找了一个博客很有参照性链接: 如果没懂强烈推荐去看

void get_next(string T, int next[])
{
	int i = 1;
	next[1] = 0;
	int j = 0;
	while (i < T.length())
	{
		if (j == 0 || T[i] == T[j])
		{
			++i;
			++j;
			next[i] = j;
		}
		else
			j = next[j];
	}
}

void get_nextval(string T, int nextval[])
{
	int i = 1;
	nextval[1] = 0;
	int j = 0;
	while (i < T.length())
	{
		if (j == 0 || T[i] == T[j])
		{
			i++;
			j++;
			if (T[i] != T[j])
				nextval[i] = j;
			else
				nextval[i] = nextval[j];
		}
		else
			j = nextval[j];
	}
}

int Index_KMP(string S, string T, int pos)
{
	//利用模式串T的next函数求T在主串S中第pos个字符之后的位置
	//其中T非空,1<=pos<=S.length
	int i = pos; 
	int j = 1;
	while (i <= S.length() && j <= T.length())
	{
		if (j == 0 || S[i] == T[j])//匹配成功,继续比较后续字符
		{
			++i;
			++j;
		}
		else
			j = next[j];//模式串右移
	}
	if (j > T.length())
		return i - T.length();//匹配成功
	else
		return 0;//匹配失败
}

3.2数组

数组是由类型相同的数据元素构成的有序集合,每个元素称为数组元素,每个元素受n个线性关系的约束。数组可以看成是线性表的推广,其特点是结构中的元素本身可以具有某种结构的数据,但属于同一数据类型。
例如:一维数组可以看成是一个线性表,二维数组可以看成数据元素是线性表的线性表。

3.2.1数组的顺序存储

由于数组一般不做插入或删除操作,也就是说,一旦简历数组,则结构中的数据元素个数和元素之间的关系就不再发生变动。因此采用顺序存储结构表示数组比较合适。在C语言中用的都是行序为主序的存储结构。

3.2.2特殊矩阵的压缩存储

矩阵用二维数组来表示是最自然的方法。但是,在数值分析中经常出现一些阶数很高的矩阵,同时矩阵中有很多值相同的元素或者是零元素。有时为了节省存储空间,可以对这类矩阵进行压缩存储。所谓压缩存储,是指多个值相同的元只分配一个存储空间,对零元不分配空间。

对称矩阵

若n阶矩阵A中的元满足 a i j = a j i , 1 ≤ i , j ≤ j a_{ij}=a_{ji},1 \le i ,j \le j aij=aji,1i,jjw,则称为n阶对称矩阵。

对于对称矩阵,可以为每一对对称元分配一个存储空间,则可将 n 2 n^2 n2个元压缩到 n ( n + 1 ) / 2 n(n+1)/2 n(n+1)/2个元的空间中,可以行序为主序存储其下三角(包括对角线)中的元。
假设一维数组sa[ n ( n + 1 ) / 2 n(n+1)/2 n(n+1)/2 ]作为n阶对称矩阵A的存储结构,则sa[k]和矩阵元 a i j a_{ij} aij之间存在着一一对应的关系
k = { i ( i − 1 ) 2 + j − 1    i ≥ j j ( j − 1 ) 2 + i − 1    i < j k=\left\{\begin{matrix} \frac{i(i-1)}{2}+j-1 \ \ i\ge j \\ \frac{j(j-1)}{2}+i-1 \ \ i<j \end{matrix}\right. k={2i(i1)+j1  ij2j(j1)+i1  i<j
在这里插入图片描述

三角矩阵

以主对角线划分,三角矩阵有上三角和下三角矩阵两种。**上三角矩阵是指矩阵下三角(不包含对角线)**中的元均为常数c或领的n阶矩阵,下三角矩阵与之相反。对三角矩阵进行压缩存储时,除了和对称矩阵一样,只存储上下三家中的元素之外,再加一个存储常数c的存储空间即可。
上三角矩阵
sa[k]和矩阵元 a i j a_{ij} aij之间的对应关系:
k = { ( 2 n − i + 2 ) ( i − 1 ) 2 + j − i    i ≤ j n ( n + 1 ) 2    i > j k=\left\{\begin{matrix} \frac{(2n-i+2)(i-1)}{2}+j-i \ \ i\le j \\ \frac{n(n+1)}{2} \ \ i>j \end{matrix}\right. k={2(2ni+2)(i1)+ji  ij2n(n+1)  i>j
下三角矩阵
sa[k]和矩阵元 a i j a_{ij} aij之间的对应关系:
k = { i ( i − 1 ) 2 + j − 1    i ≥ j n ( n + 1 ) 2    i < j k=\left\{\begin{matrix} \frac{i(i-1)}{2}+j-1 \ \ i\ge j \\ \frac{n(n+1)}{2} \ \ i<j \end{matrix}\right. k={2i(i1)+j1  ij2n(n+1)  i<j

对角矩阵

对角矩阵所有的非零元素都集中在主对角线为中心的带状区域,即主对角线上和直接在对角线上、下方若干条对角线上的元之外,所有其他的元皆为零。这种矩阵,也可以按某个原则(以行为主,或以对角线的顺序)将其压缩存储到一维数组上。
在这里插入图片描述

3.3广义表

广义表是线性表的推广,也称为列表。广泛运用于人工智能等领域的表处理语言LISP语言,把广义表作为基本的数据结构。
广义表一般记作:
L S = ( a 1 , a 2 , . . . , a n ) LS = (a_1,a_2,...,a_n) LS=(a1,a2,...,an)
n为其长度。在线性表中, a i a_i ai只限于是单个元素。而在广义表的定义中, a i a_i ai可以是单个元素,也可以是广义表,分别称为广义表LS的原表和子表。习惯上,大写字母表示广义表名称,小写字母表示原子。
广义表的图形表示
图中源泉表示广义表,方块表示原子,值得提醒的是广义表()和(())不同。前者为空表,长度n=0;后者长度n=1,可分解得到其表头、表尾均为空表()。

*案例病毒感染检测

#include<iostream>
#include<fstream>
#include<cstring>

#define MAXLEN 255
#define QElemType int
#define Status int

using namespace std; 

typedef struct{
    char ch[MAXLEN+1];
    int length; //字符串当前长度
}SString;

int Index_BF(SString S, SString T, int pos){
    int i = pos, j = 1;
    while(i <= S.length && j <= T.length){
        if(S.ch[i] == T.ch[j]){++i, ++j;}
        else{
            i = i - j + 2;
            j = 1;
        }
    }
    if(j > T.length) return i-T.length;
    else return 0;
}

int main()
{
	SString Virus, Person, temp; 
	ifstream inFile("bug.txt");
	ofstream outFile("result.txt");
	int num;
	inFile >> num;
	while(num--){
		inFile >> Virus.ch + 1;
		inFile >> Person.ch + 1;
		Person.length = strlen(Person.ch + 1);
		Virus.length = strlen(Virus.ch + 1);
		
		string Vir(Virus.ch + 1, Virus.length);
		bool flag = false;
		int m = Virus.length;
		for(int i = m+1, j = 1; j <= m; j ++){
			Virus.ch[i++] = Virus.ch[j]; //将病毒字符串扩长度大两遍 
		}
		
		Virus.ch[2*m+1] = '\0';
		
		for(int i = 0; i < m; i ++){
			for(int j = 1; j <= m; j ++) temp.ch[j] = Virus.ch[i+j];
			temp.ch[m+1] = '\0';
			temp.length = m;
			
			flag = Index_BF(Person, temp, 1);
		
			if(flag) break;
		}
		if(flag) outFile << Vir << "        " << Person.ch+1 << "        " << "YES" << endl;
		else outFile << Vir << "        " << Person.ch+1 << "        " << "NO" << endl;
		
	}
	return 0;
} 

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

输出:
在这里插入图片描述

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

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

相关文章

苹果电脑杀毒软件CleanMyMac

杀毒软件在苹果家族中是一个小众软件&#xff0c;百度搜索苹果电脑杀毒软件&#xff0c;可能各种杀软良莠不齐&#xff0c;因为在这个市场非常小&#xff0c;绝大多数都是冲着“清理”去的&#xff0c;而不是杀毒。最近测试了一款Mac电脑杀毒软件&#xff0c;杀毒效果也是一般般…

Day16:二叉搜索树和双向链表

将一个 二叉搜索树 就地转化为一个 已排序的双向循环链表 。 对于双向循环列表&#xff0c;你可以将左右孩子指针作为双向循环链表的前驱和后继指针&#xff0c;第一个节点的前驱是最后一个节点&#xff0c;最后一个节点的后继是第一个节点。 特别地&#xff0c;我们希望可以…

Qt QML实现弹球消砖块小游戏

前言 弹球消砖块游戏想必大家都玩过&#xff0c;很简单的小游戏&#xff0c;通过移动挡板反弹下落的小球&#xff0c;然后撞击砖块将其消除。本文使用QML来简单实现这个小游戏。 效果图&#xff1a; 正文 代码目录结构如下&#xff1a; 首先是小球部分&#xff0c;逻辑比较麻…

如何在实际应用中测量和调整直线导轨的预紧力?

在实际应用中&#xff0c;准确测量和调整直线导轨的预紧力对于保证设备的性能和精度至关重要&#xff0c;但测量和调整直线导轨的预紧力需要根据具体的导轨型号和结构来选择合适的方法。以下是一些常见的测量和调整方法&#xff1a; 1、使用压力传感器&#xff1a;在一些先进的…

YOLO11 使用入门

YOLO12 使用入门 1. 源码下载2. 权重下载3. 环境配置4. 例程测试4.1. 目标检测4.1.1. 源文件 model4.1.2. 结果Results4.1.3. 边界框 Boxes 2.2. 图像分割4.2.1. 推理 model.predict4.2.2. 掩码 Masks 1. 源码下载 之前介绍了《目标检测 YOLOv5 使用入门》 现在是 2024.12.2…

汽车感性负载-智能高边钳位能量计算

随着汽车电子技术的发展&#xff0c;新的电子电气架构下&#xff0c;越来越多的执行部件在车身出现&#xff0c;比如电磁阀、风机、水泵、油泵、雨刮继电器等常用的执行器&#xff0c; 它们一般都表现为感性特点。驱动这些负载的最简单和最常见的方法是将它们连接到高边侧开关(…

基于Python+Flask+MySQL+HTML的爬取豆瓣电影top-250数据并进行可视化的数据可视化平台

FlaskMySQLHTML 项目采用前后端分离技术&#xff0c;包含完整的前端&#xff0c;以flask作为后端 Pyecharts、jieba进行前端图表展示 通过MySQL收集格列数据 通过Pyecharts制作数据图表 这是博主b站发布的详细讲解&#xff0c;感兴趣的可以去观看&#xff1a;【Python爬虫可…

七大常用智能家居协议对比

如果您不知道在项目中使用哪种智能家居通信协议&#xff0c;那么进入智能家居行业可能会很困难。如果没有合适的协议将其集成到智能家居生态系统中&#xff0c;智能家居设备将无法正常工作。否则&#xff0c;您将面临硬件和软件无法满足最终用户期望的风险。协议选择不当可能会…

996引擎-问题处理:缺失特效分割文件 ModelAtlasSplitConfigs

通常我们买的资源都是带会 ModelAtlasSplitConfigs.txt 或 sceneAtlasSplitConfigs.txt 的 但有时确实找不到的话&#xff0c;是可以用996工具生成的&#xff1a;

异步加载错误如何解决

首先是 提供两张图 如果数据过多的情况下我在所内和住家形式频繁的来回切换 导致数据展示的不一样 大家是不是有这样的问题 这个是导致了数据展示有问题的情况 住家的情况本来是没有几层的 下面我帮大家解决一下 // 防止异步延迟 const Noop () > { } const lhl (resDa…

R语言零基础系列教程-01-R语言初识与学习路线

代码、讲义、软件回复【R语言01】获取。 R语言初识 R是一个开放的统计编程环境&#xff0c;是一门用于统计计算和作图的语言。“一切皆是对象”&#xff0c;数据、函数、运算符、环境等等都是对象。易学&#xff0c;代码像伪代码一样简洁&#xff0c;可读性高强大的统计和可视…

自动化测试-网页聊天室

项目介绍&#xff1a; 针对基于WebSocket协议的网页端即时通讯系统&#xff0c;主导设计并实施全流程自动化测试方案。通过构建模块化测试框架&#xff0c;完成对核心业务场景&#xff08;用户登录鉴权、消息同步、实时聊天等&#xff09;的自动化验证&#xff0c;最终达成测试…

创新实践分享:基于边缘智能+扣子的智能取物机器人解决方案

在 2024 年全国大学生物联网设计竞赛中&#xff0c;火山引擎作为支持企业&#xff0c;不仅参与了赛道的命题设计&#xff0c;还为参赛队伍提供了相关的硬件和软件支持。以边缘智能和扣子的联合应用为核心&#xff0c;参赛者们在这场竞赛中展现出了卓越的创新性和实用性&#xf…

【蓝桥杯】省赛:神奇闹钟

思路 python做这题很简单&#xff0c;灵活用datetime库即可 code import os import sys# 请在此输入您的代码 import datetimestart datetime.datetime(1970,1,1,0,0,0) for _ in range(int(input())):ls input().split()end datetime.datetime.strptime(ls[0]ls[1],&quo…

使用kubeadm方式以及使用第三方工具sealos搭建K8S集群

目录 kubeadm方式: 一、安装要求 二、环境准备 二、安装Docker、kubeadm、kubelet 1、安装Docker &#xff08;1&#xff09;首先配置一下Docker的阿里yum源 &#xff08;2&#xff09;然后用yum 方式安装docker &#xff08;3&#xff09;配置Docker镜像加速器 &#…

2025 linux系统资源使用率统计docker容器使用率统计docker监控软件Weave Scope安装weavescope

1.Weave Scope介绍 Weave Scope 是一款用于监控和可视化 Docker 容器、Kubernetes 集群以及分布式应用的强大工具。它的设计目标是帮助开发者和运维人员更好地理解和管理复杂的微服务架构。以下是 Weave Scope 的主要优点&#xff1a; 1. 实时可视化 Weave Scope 提供了一个直…

通过特征值和特征向量实现的图像压缩和特征提取

前文&#xff0c;我们在学习人工智能的线性代数基础的时候&#xff0c;就了解到&#xff0c;矩阵在人工智能中被广泛使用&#xff0c;接下来我们就从大家非常常见的图像开始&#xff0c;深度理解矩阵在人工智能中的应用。有关线性代数基础的文章可以看的我CSDN:人工智能中的线性…

【eNSP基础使用教程-1】

座右铭: 纵有疾风起&#xff0c;人生不言弃。 文章目录 前言一、更改设备名称指令1、双击路由器进入2、 进入系统视图3、更改设备名称为R14、使用同样的办法修改路由器R2、R3 二、配置路由物理接口的IP 地址1、查看R1路由器当前接口IP 地址配置与路由表2、查看路由器上的路由表…

机器学习常见激活函数

激活函数的作用 引入非线性因素 若神经网络仅由线性层构成&#xff0c;那么无论网络的层数有多少&#xff0c;其整体的输出依然是输入的线性组合。这样的网络只能拟合线性函数&#xff0c;在处理复杂的非线性问题&#xff08;如语音识别、图像分类&#xff09;时能力十分有限。…

netcore publish报错 error CS1056: Unexpected character

问题&#xff1a;jenkins netcore publish报错 检查文件编码&#xff0c;发现是:GB2312。转换为&#xff1a;UTF-8-BOM。 问题解决 。