数据结构-线性表-顺序表
一. 了解顺序表
顺序表定义:
顺序表(也称为线性数组)是一种线性数据结构,它将数据元素按顺序存储在一块连续的内存空间中。顺序表的基本特征包括:
-
元素的顺序性:顺序表中的元素具有线性关系,每个元素都有一个唯一的位置(索引),可以通过索引直接访问。
-
存储方式:顺序表的元素在内存中是连续存储的,这使得可以通过简单的下标访问实现快速的随机访问,时间复杂度为 O(1)。
-
固定大小:在创建顺序表时,通常需要指定其最大容量,虽然可以通过动态数组等形式实现扩展,但扩展过程可能涉及到大量的数据复制。
-
插入与删除操作:在顺序表中进行插入和删除操作时,可能需要移动大量元素以保持顺序,这使得这些操作的时间复杂度为 O(n)。
-
适用场景:顺序表适合存储固定数量的数据,尤其是当数据量较小且访问频繁时,能够提供高效的性能。
顺序表优缺点:
优点包括快速随机访问,能够通过索引直接访问元素,时间复杂度为O(1)。实现相对简单,结构清晰,易于理解,适合初学者。此外,数据在内存中连续存储,能够提高缓存利用率和访问速度。对于小规模数据,内存开销较小。
缺点方面,顺序表的大小是固定的,必须预先定义容量,超出时需要重新分配内存,增加复杂性。插入和删除操作效率较低,因为需要移动大量元素,时间复杂度为 O(n)。如果预设容量过大,可能导致内存浪费。对于需要频繁插入和删除的场景,顺序表的性能表现不佳。
总的来说,顺序表适合随机访问和数据量相对固定的情况,但在动态数据管理和频繁修改方面存在不足。选择时需根据具体需求进行权衡。
二、顺序表的基本操作(C语言)
1. 静态分配与动态分配
-
静态分配
// 静态分配
#define MaxSize 50 // 定义线性表最大长度
typedef struct {// ElemType data[MaxSize]; // 顺序表的元素 ElemType泛指你想设置的类型int data[MaxSize]; // 顺序表的元素 这里以int作为参考 int length; // 顺序表当前长度(有效内容)
}SqList;
-
动态分配
// 动态分配
#define InitSize 100 // 表长度的初始化定义
typedef struct {// ElemType *data; // 指示动态分配数组的指针int *data; // int Maxsize, length; // 指示2最大的容量和当前个数
}SeqList;// 初始化动态分配语句(C语言)
// #include <stdlib.h>
// L.data = (ElemType*)malloc(sizeof(ElemType) * InitSize);
// free(L.data);//释放
2. 顺序表的初始化
-
静态初始化
// SqList L; // 假设创建了一个顺序表
// 初始化静态分配的顺序表
void InitList_Static(SqList* L) {L->length = 0;
}
-
动态初始化
// 动态
void InitList_Dynamic(SeqList* L) {L->data = (int*)malloc(sizeof(int) * InitSize); // 分配存储空间L->length= 0; // 顺序表初始化长度为0L->Maxsize = InitSize; // 初始存储容量
}
3. 插入操作
注意:bool报错可能是版本问题加入 // #include < stdbool.h >
-
静态插入
// 静态插入
bool ListInsert_Static(SqList* L, int i, int e) {if (i < 1 || i > L->length + 1) { // 检查i是否在有效范围内(从用户角度来看) return false;}if (L->length >= MaxSize) {return false; // 检查存储空间是否已满 }// 从当前列表的末尾开始,将元素向后移动,为新元素腾出空间 for (int j = L->length; j >= i; j--) {L->data[j] = L->data[j - 1]; // 注意这里j是从length开始的,所以j-1是安全的 }// 在用户指定的位置(从1开始)插入新元素 L->data[i - 1] = e; // 注意这里要减去1来访问数组的实际位置 L->length++; // 线性表长度加1 return true;
}
最好情况
在最好情况下,即当 i 等于 L->length + 1 时,新元素将被添加到列表的末尾,而不需要移动任何现有元素。因此,最好情况下的时间复杂度是 O(1),因为只执行了常数次数的操作(主要是更新 L->data[i - 1] 和 L->length)。
最坏情况
在最坏情况下,即当 i 等于 1 时,新元素将被插入到列表的开头。这要求将列表中的所有现有元素都向后移动一个位置,以为新元素腾出空间。因此,最坏情况下的时间复杂度是 O(n),其中 n 是列表的当前长度(L->length),因为需要执行与列表长度成正比的移动操作。
平均情况
平均情况的时间复杂度也取决于 i 的值。然而,由于 i 可以是 1 到 L->length + 1 之间的任何值,并且每个值被选择的概率(在不知道具体应用场景的情况下)可以假设是相等的,因此平均情况下需要移动的元素数量大约是列表长度的一半。但这并不直接转化为一个简单的时间复杂度表达式,因为“平均”的概念在这里涉及到的是一个分布,而不是一个固定的值。
然而,从渐进复杂度的角度来看,平均情况下的时间复杂度仍然是 O(n),因为即使在最平均的情况下,也需要执行与列表长度成线性关系的操作(尽管可能不是完整的列表长度)。
总结
- 最好情况:O(1)
- 最坏情况:O(n)
- 平均情况:虽然具体分布可能复杂,但从渐进复杂度的角度来看,也是 O(n)
这里的关键是理解,无论 i 的值如何,都可能需要移动一定数量的元素(在最坏情况下是全部,在最好情况下是零),而平均情况下这个数量与列表长度成正比。
-
动态插入
#define AddNewSize 10
bool InitInsert_Dynamic(SeqList* L, int i, int e) { if (i < 1 || i > L->length + 1) return false; // 如果需要扩容 if (L->length >= L->Maxsize) { int new_MaxSize = L->Maxsize + AddNewSize; // 计算新的最大容量 int* new_data = (int*)malloc(sizeof(int) * new_MaxSize); // 分配新的内存块 if (new_data == NULL) return false; // 内存分配失败 // 复制旧数据到新内存块 for (int j = 0; j < L->length; j++) { new_data[j] = L->data[j]; } // 释放旧内存块 free(L->data); // 更新SeqList的指针和大小信息 L->data = new_data; L->Maxsize = new_MaxSize; } // 在指定位置插入新元素 for (int j = L->length; j >= i; j--) { L->data[j] = L->data[j - 1]; // 将第i位及之后的元素后移 } L->data[i - 1] = e; // 插入新元素 L->length++; // 线性表长度加1 return true;
}
分析 InitInsert_Dynamic 函数的时间复杂度,我们需要考虑两个主要部分:扩容(如果需要)和元素插入。
扩容部分
-
时间复杂度:如果扩容发生,时间复杂度主要由内存分配和旧数据复制决定。内存分配通常被认为是常数时间操作(尽管实际复杂度可能依赖于系统和分配器的实现),但这里我们将其视为
O(1)。旧数据复制需要遍历整个现有列表,因此其时间复杂度是O(n),其中n是当前列表的长度(L->length)。 -
发生概率:扩容只在列表已满(即
L->length >= L->Maxsize)时发生。如果L->Maxsize足够大或插入操作不频繁,这个操作可能很少发生。
元素插入部分
-
时间复杂度:无论是否需要扩容,插入操作都需要将从
i位置开始的元素向后移动一个位置。在最坏情况下(即i = 1),需要移动所有元素,时间复杂度为O(n)。在最好情况下(即i = L->length + 1),不需要移动任何元素,时间复杂度为O(1)。 -
平均情况:由于
i可以是1到L->length + 1之间的任何值,且假设每个值被选择的概率相等,平均情况下需要移动的元素数量大约是列表长度的一半。然而,从渐进复杂度的角度来看,平均情况仍然被认为是O(n),因为存在一个与n成正比的项(即使这个项是n的一半)。
总结
-
最好情况:如果不需要扩容且
i = L->length + 1(即在列表末尾插入),则时间复杂度为O(1)。 -
最坏情况:如果需要扩容且
i = 1(即在列表开头插入),则时间复杂度主要由扩容操作(O(n))和元素插入操作(O(n))决定,总体为O(n)。但由于扩容通常不经常发生,更关注单次插入操作的最坏情况,也是O(n)。 -
平均情况:尽管平均情况下移动的元素数量可能较少,但从渐进复杂度的角度来看,时间复杂度仍然是
O(n),因为存在一个与n成正比的项。 -
InitInsert_Dynamic函数的时间复杂度在最好情况下为O(1),在最坏和平均情况下为O(n)。注意,这里的n是指插入操作执行时列表的当前长度。
3. 删除操作
-
静态删除
// 静态
bool ListDelete_Static(SqList* L, int i, int *e){if (i<1 || i > L->length) return false;*e = L->data[i - 1];for (int j = i; j < L->length; j++) {L->data[j-1] = L->data[j];}L->length --;return true;
}
-
动态删除
// 动态
bool ListDelete_Dynamic(SeqList* L, int i, int* e) {if (i<1 || i > L->length) return false;*e = L->data[i - 1];for (int j = i; j < L->length; j++) {L->data[j - 1] = L->data[j];}L->length--;return true;
}
-
时间复杂度
这两个函数 ListDelete_Static 和 ListDelete_Dynamic 的时间复杂度分析是相似的,因为它们都执行了几乎相同的操作:检查索引的有效性、移动元素、减少长度,并返回结果。它们的主要区别在于它们操作的数据结构(SqList 和 SeqList)的潜在性质,但这些性质在上下文中并不直接影响时间复杂度。
- 最好情况 发生在索引
i正好是要删除的最后一个元素(即i == L->length的前一个位置,因为索引从 1 开始)。在这种情况下,你不需要移动任何元素(除了更新长度),因此时间复杂度是 O(1)。然而,由于i > L->length的检查会立即返回false,严格来说最好情况不会执行到元素移动的代码。但如果我们考虑的是一旦检查通过就立即开始的操作,那么可以认为最好情况的时间复杂度是 O(1)(尽管这种情况在函数内部逻辑上并不实际发生)。 - 最坏情况 发生在索引
i指向列表的第一个元素(即i == 1)。在这种情况下,你需要将除第一个元素之外的所有元素都向前移动一个位置,这涉及L->length - 1次赋值操作。因此,时间复杂度是 O(n),其中 n 是列表的长度(L->length)。 - 平均情况 很难精确计算,因为它取决于索引
i的分布。但是,由于最坏情况(需要移动几乎所有元素)和最好情况(不需要移动元素)之间的显著差异,我们可以合理地假设平均情况接近于最坏情况,即 O(n)。这是因为无论索引i的值如何,只要它位于有效范围内,你都需要至少移动一定数量的元素(在最坏情况下是n-1个,在最好情况下是 0 个)。
注意
- 请注意,虽然这两个函数在逻辑上相似,但它们的命名和上下文(即它们操作的数据结构)不同。
SqList和SeqList分别具有类似的属性(如data指针和length字段),但它们的实现细节(如内存分配和释放策略)不同。 -
SeqList是一个动态分配的数据结构,并且data指针指向的内存是动态分配的,还需要考虑内存管理的复杂性,但这与函数本身的时间复杂度分析不直接相关。 - 请注意,如果
i的值在调用函数之前没有得到有效的验证,那么可能会导致数组越界访问,这是一个严重的运行时错误。
4. 按值查找
-
静态查找
// 静态
int LocateElem_Static(SqList* L, int e) {int i = 0;for (i = 0; i < L->length; i++) {if (L->data[i] == e)return i + 1;}return 0; //
}
-
动态查找
int LocateElem_Dynamic(SeqList* L, int e) {int i = 0;for (i = 0; i < L->length; i++) {if (L->data[i] == e)return i + 1;}return 0; //
}
-
时间复杂度
对于 LocateElem_Static 和 LocateElem_Dynamic 这两个函数,它们的时间复杂度分析是相同的,因为它们的内部逻辑是完全一致的。这两个函数都是在顺序表中查找一个特定的元素 e,并返回该元素的逻辑索引(如果找到的话;否则返回0)。
- 最好情况 发生在顺序表的第一个元素就是要查找的元素
e。在这种情况下,函数只需要进行一次比较就可以找到元素,因此时间复杂度是 O(1)。然而,这种情况非常罕见,因为它要求目标元素恰好位于列表的开头。 - 最坏情况 发生在目标元素
e不在顺序表中,或者它位于顺序表的最后一个位置。在这种情况下,函数需要遍历整个顺序表,比较L->length次(因为索引是从0开始的,所以要比较到L->length - 1),因此时间复杂度是 O(n),其中 n 是顺序表的长度(L->length)。 - 平均情况 的时间复杂度很难精确计算,因为它取决于目标元素
e在顺序表中出现的概率和位置。然而,由于最好情况和最坏情况之间的差异很大(O(1) vs O(n)),我们可以合理地假设平均情况的时间复杂度接近于最坏情况,即 O(n)。这是因为,在不知道e是否存在于顺序表中以及它位于何处的情况下,我们需要做好遍历整个顺序表的准备。
总结:
- 无论是
LocateElem_Static还是LocateElem_Dynamic,它们的时间复杂度在最好情况下是 O(1),在最坏情况下是 O(n),平均情况下也接近于 O(n)。 - 函数名的“Static”和“Dynamic”主要反映了它们操作的数据结构类型(尽管在这个上下文中,这种差异对于查找操作的时间复杂度分析来说并不重要),而不是函数本身的静态或动态特性。
- 查找操作的时间复杂度主要取决于顺序表的长度和元素在顺序表中的分布,而不是查找函数的具体实现细节。
三、简单线性表操作(C语言)
1. 求表长
// 求表长
int Length_Static(SqList *L) {return L->length;
}int Length_Dynamic(SeqList* L) {return L->length;
}
2. 按位查找
// 按位查找
int GetElem_Static(SqList* L,int i) {return L->data[i - 1];
}int GetElem_Dynamic(SeqList* L, int i) {return L->data[i - 1];
}
3. 输出操作
// 输出操作
void PrintList_Static(SqList* L) {if (L == NULL || L->data == NULL) {printf("顺序表为空或未初始化!\n");return;}int i = 0;for (i = 0; i < L->length; i++)printf(" %d ", L->data[i]);
}void PrintList_Dynamic(SeqList* L) {if (L == NULL || L->data == NULL) {printf("顺序表为空或未初始化!\n");return;}int i = 0;for (i = 0; i < L->length; i++)printf(" %d ", L->data[i]);
}
4. 判空操作
// 判空操作(针对SqList)
bool Empty_Static(SqList * L) {// 如果L是NULL,我们可以认为这是一个未初始化的顺序表,但在许多情况下, // 我们可能期望在这种情况下调用函数是一个错误,或者已经由其他逻辑确保了L不是NULL。 // 这里我们只检查顺序表的长度是否为0。 if (L == NULL) {// 可选:打印一个错误消息或处理异常情况 printf("警告:传入的顺序表指针为NULL!\n");return true; // 或者可以抛出异常或退出函数,取决于您的错误处理策略 }return L->length == 0;
}// 判空操作(针对SeqList,SqList类似)
bool Empty_Dynamic(SeqList* L) {if (L == NULL) {// 同样的警告 printf("警告:传入的顺序表指针为NULL!\n");return true; // 或者处理错误 }return L->length == 0;
}
5. 销毁操作
// 销毁操作
void DestroyList_Static(SqList *L) {L->length = 0;
}void DestroyList_Dynamic(SeqList* L) {if (L != NULL && L->data != NULL) {free(L->data);L->data = NULL; // 避免悬空指针 L->length = 0;}// 如果需要,也可以将L设置为NULL,但这取决于L是如何被管理的
}
四、总代码(C语言)
#include <stdio.h>
#include <stdlib.h>
#include < stdbool.h >
// 仔细说明,争取小白也能看懂// 静态分配
#define MaxSize 50 // 定义线性表最大长度
typedef struct {// ElemType data[MaxSize]; // 顺序表的元素 ElemType泛指你想设置的类型int data[MaxSize ]; // 顺序表的元素 这里以int作为参考int length; // 顺序表当前长度(有效内容)
}SqList;// 动态分配
#define InitSize 100 // 表长度的初始化定义
typedef struct {// ElemType *data; // 指示动态分配数组的指针int *data; // int Maxsize, length; // 指示2最大的容量和当前个数
}SeqList;// 初始化动态分配语句(C语言)
// #include <stdlib.h>
// L.data = (ElemType*)malloc(sizeof(ElemType) * InitSize);
// free(L.data);//释放// 顺序表的初始化
// 静态
// SqList L; // 假设创建了一个顺序表
// 初始化静态分配的顺序表
void InitList_Static(SqList* L) {L->length = 0; // 顺序表初始化长度为0
}// 动态
void InitList_Dynamic(SeqList* L) {L->data = (int*)malloc(sizeof(int) * InitSize); // 分配存储空间L->length = 0; // 顺序表初始化长度为0L->Maxsize = InitSize; // 初始存储容量
}// 插入操作
// 静态插入
bool ListInsert_Static(SqList* L, int i, int e) {if (i < 1 || i > L->length + 1) { // 检查i是否在有效范围内(从用户角度来看) return false;}if (L->length >= MaxSize) {return false; // 检查存储空间是否已满 }// 从当前列表的末尾开始,将元素向后移动,为新元素腾出空间 for (int j = L->length; j >= i; j--) {L->data[j] = L->data[j - 1]; // 注意这里j是从length开始的,所以j-1是安全的 }// 在用户指定的位置(从1开始)插入新元素 L->data[i - 1] = e; // 注意这里要减去1来访问数组的实际位置 L->length++; // 线性表长度加1 return true;
}// 动态插入
#define AddNewSize 10
bool InitInsert_Dynamic(SeqList* L, int i, int e) {if (i < 1 || i > L->length + 1) return false;// 如果需要扩容 if (L->length >= L->Maxsize) {int new_MaxSize = L->Maxsize + AddNewSize; // 计算新的最大容量 int* new_data = (int*)malloc(sizeof(int) * new_MaxSize); // 分配新的内存块 if (new_data == NULL) return false; // 内存分配失败 // 复制旧数据到新内存块 for (int j = 0; j < L->length; j++) {new_data[j] = L->data[j];}// 释放旧内存块 free(L->data);// 更新SeqList的指针和大小信息 L->data = new_data;L->Maxsize = new_MaxSize;}// 在指定位置插入新元素 for (int j = L->length; j >= i; j--) {L->data[j] = L->data[j - 1]; // 将第i位及之后的元素后移 }L->data[i - 1] = e; // 插入新元素 L->length++; // 线性表长度加1 return true;
}// 删除操作
// 静态
bool ListDelete_Static(SqList* L, int i, int *e){if (i<1 || i > L->length) return false;*e = L->data[i - 1];for (int j = i; j < L->length; j++) {L->data[j-1] = L->data[j];}L->length --;return true;
}// 动态
bool ListDelete_Dynamic(SeqList* L, int i, int* e) {if (i<1 || i > L->length) return false;*e = L->data[i - 1];for (int j = i; j < L->length; j++) {L->data[j - 1] = L->data[j];}L->length--;return true;
}// 顺序表的查找
// 静态
int LocateElem_Static(SqList* L, int e) {int i = 0;for (i = 0; i < L->length; i++) {if (L->data[i] == e)return i + 1;}return 0; //
}// 动态
int LocateElem_Dynamic(SeqList* L, int e) {int i = 0;for (i = 0; i < L->length; i++) {if (L->data[i] == e)return i + 1;}return 0; //
}// 求表长
int Length_Static(SqList *L) {return L->length;
}int Length_Dynamic(SeqList* L) {return L->length;
}// 按位查找
int GetElem_Static(SqList* L,int i) {return L->data[i - 1];
}int GetElem_Dynamic(SeqList* L, int i) {return L->data[i - 1];
}// 输出操作
void PrintList_Static(SqList* L) {if (L == NULL || L->data == NULL) {printf("顺序表为空或未初始化!\n");return;}int i = 0;for (i = 0; i < L->length; i++)printf(" %d ", L->data[i]);
}void PrintList_Dynamic(SeqList* L) {if (L == NULL || L->data == NULL) {printf("顺序表为空或未初始化!\n");return;}int i = 0;for (i = 0; i < L->length; i++)printf(" %d ", L->data[i]);
}/
// 判空操作(针对SqList)
bool Empty_Static(SqList * L) {// 如果L是NULL,我们可以认为这是一个未初始化的顺序表,但在许多情况下, // 我们可能期望在这种情况下调用函数是一个错误,或者已经由其他逻辑确保了L不是NULL。 // 这里我们只检查顺序表的长度是否为0。 if (L == NULL) {// 可选:打印一个错误消息或处理异常情况 printf("警告:传入的顺序表指针为NULL!\n");return true; // 或者可以抛出异常或退出函数,取决于您的错误处理策略 }return L->length == 0;
}// 判空操作(针对SeqList,假设与SqList类似)
bool Empty_Dynamic(SeqList* L) {if (L == NULL) {// 同样的警告 printf("警告:传入的顺序表指针为NULL!\n");return true; // 或者处理错误 }return L->length == 0;
}// 销毁操作
void DestroyList_Static(SqList *L) {L->length = 0;
}void DestroyList_Dynamic(SeqList* L) {if (L != NULL && L->data != NULL) {free(L->data);L->data = NULL; // 避免悬空指针 L->length = 0;}// 如果需要,也可以将L设置为NULL,但这取决于L是如何被管理的
}int main() {return 0;
}
五、总结
顺序表是一种简单而高效的数据结构,适合于需要快速随机访问的场景。然而,由于其固定大小和插入、删除操作的低效性,在需要频繁修改数据的情况下,可能需要考虑其他数据结构(如链表、动态数组等)。在实际应用中,选择合适的数据结构需要根据具体需求进行权衡。
相关文章:
数据结构-线性表-顺序表
一. 了解顺序表 顺序表定义: 顺序表(也称为线性数组)是一种线性数据结构,它将数据元素按顺序存储在一块连续的内存空间中。顺序表的基本特征包括: 元素的顺序性:顺序表中的元素具有线性关系,每…...
AI绘画大模型-StableDiffusion最强模型sd3(本地安装方法)
前言/introduction Stable Diffusion 3(简称SD3)是Stability AI最新推出的文本到图像生成模型。相比前代模型,SD3在生成质量、细节表现以及运行效率上有了显著提升,尤其在细腻的图像渲染和复杂的场景构建方面表现出色。SD3模型…...
SpringBoot调用外部接口的几种方式
SpringBoot调用外部接口的几种方式 使用FeignClient调用1、在使用方引入依赖2、服务接口调用方2.1、在启动类上加上EnableFeigncliens注解2.2、编写Feign接口调用服务controller层2.3、服务接口调用service层 3、服务接口提供者4、说明 使用RestTemplate调用1、引入依赖2、Rest…...
MySQL:information_schema查找某个表的主键是否在数据的其他位置出现之二
上一篇: MySQL:information_schema查找某个表的主键是否在数据的其他位置出现之一-CSDN博客 摘要 遍历数据库每一张表的每一个字段,是否存在字符串search_term 正文 源码 import pymysql from datetime import datetime# 测试函数 if __n…...
Linux进程和计划任务管理
目录 一、进程基本概念 1.进程 2.程序和进程的关系 二、查看进程信息 1.ps命令 1.1 ps aux命令 1.2 ps -elf 命令 2. top 命令 3.pgrep 命令 4.jobs 命令 三、查看进程树 四、进程的启动方式 1.手动启动 2.调度启动 五、终止进程的运行 1.CtrlC组合键 2.kill、kil…...
【Angular18】封装自定义组件
1. 准备组件 2. 创建打包文件夹及部分配置文件 创建 文件夹app-legalentities-root拷贝组件源文件到新的文件夹app-legalentities中创建文件 .npmrc registry发布地址always-authtrue创建文件 ng-package.json {"$schema": "./node_modules/ng-packagr/ng-pac…...
【流媒体】RTMPDump—RTMP_ConnectStream(创建流连接)
目录 1. RTMP_ConnectStream函数1.1 读取packet(RTMP_ReadPacket)1.2 解析packet(RTMP_ClientPacket)1.2.1 设置Chunk Size(HandleChangeChunkSize)1.2.2 用户控制信息(HandleCtrl)1…...
MySQL学习3之锁机制
一、什么是锁粒度? 锁粒度(Lock Granularity)是指在数据库中锁定数据资源的最小单位。锁粒度决定了锁定操作的范围,即锁定的是整个数据库、整个表、表中的某个分区、表中的某一页还是表中的某一行。 在MySQL中常见的锁粒度有&am…...
2004-2023年上市公司过度负债数据(含原始数据+计算结果)
2004-2023年上市公司过度负债数据(含原始数据计算结果) 1、时间:2004-2023年 2、来源:上市公司年报 3、指标:证券代码、证券简称、统计截止日期、是否剔除ST或*ST股、是否剔除当年新上市、已经退市或被暂停退市的公…...
[机器学习]--KNN算法(K邻近算法)
KNN (K-Nearest Neihbor,KNN)K近邻是机器学习算法中理论最简单,最好理解的算法,是一个 非常适合入门的算法,拥有如下特性: 思想极度简单,应用数学知识少(近乎为零),对于很多不擅长数学的小伙伴十分友好虽然算法简单,但效果也不错 KNN算法原理 上图是每一个点都是一个肿瘤病例…...
跨平台控制神器Escrcpy,您的智能生活助手
Escrcpy 是一款基于 Scrcpy 开发的图形化安卓手机投屏控制软件,它允许用户将 Android 手机屏幕实时镜像到电脑上,并使用电脑的鼠标和键盘直接操作手机,实现了无线且高效的操控。这款软件是免费开源的,支持跨平台使用,包…...
AR 眼镜之-开关机定制-实现方案
目录 📂 前言 AR 眼镜系统版本 开关机定制 1. 🔱 技术方案 1.1 技术方案概述 1.2 实现方案 1)开机 Logo 2)开机音效 3)开机动画 4)关机动画 5)关机弹窗 2. 💠 开机 Logo…...
论文阅读-Transformer Layers as Painters
1. 摘要 尽管大语言模型现在已经被广泛的应用于各种任务,但是目前对其并没有一个很好的认知。为了弄清楚删除和重组预训练模型不同层的影响,本文设计了一系列的实验。通过实验表明,预训练语言模型中的lower和final layers与中间层分布不一致…...
【STL】vector模拟实现
vector引入 vector的实现主要依靠三个成员变量:start,finish和end_of_storage 其中: [start]指向容器中的起始位置 [finish]指向容器中最后一个有效数据的下一个位置 [end_of_storage]指向容器中现有容量的位置 通过这三个指针,就使得vector的size…...
静态成员static关键字
定义: 静态成员在C类中是一个重要的概念,它包括静态成员变量和静态成员函数。 静态成员变量 1定义:静态成员变量是类的所有对象共享的变量。与普通成员变量相比,无论创建了多少个类的实 例,静态成员变量只有一份拷贝…...
本地项目git同步到线上
将本地创建的项目同步到你的 GitHub 账号线上仓库,可以按照以下步骤进行操作: 1. 在 GitHub 上创建一个新仓库 登录你的 GitHub 账号。点击右上角的加号(),然后选择 New repository。填写仓库的名称、描述等信息。选…...
Allegro如何导入DXF结构文件并生成板框(1)?
在用Allegro进行PCB设计时,需要导入DXF结构文件,由此来生成PCB的板框。 本节先讲Allegro如何导入DXF结构文件?下节讲如何利用导入的DXF结构文件生成OUTLINE板框。 Allegro如何导入DXF结构文件并生成板框(2)?-CSDN博客 详细操作方法如下: 1、选择菜单栏File 选择Import…...
Word密码忘记怎么办?三个密码找回工具帮你轻松找回密码
在工作当中,为了保护文档内容的安全,我们时常会设置密码。但有时会因为长时间未打开而忘记了密码,导致word文档无法打开。面对这种情况,我们该怎么办呢?下面小编就将给大家带来3个实用的密码找回工具,帮助大…...
使用 ABP 框架 (ASP.NET Boilerplate Project) 创建一个带有迁移功能的示例
使用 ABP 框架 (ASP.NET Boilerplate Project) 创建一个带有迁移功能的示例项目是一个很好的方式来学习如何结合高级框架进行开发。ABP 框架提供了强大的模块化和分层架构,适合构建复杂的企业级应用程序。 以下是一个使用 ABP 框架的完整示例项目,它展示了如何创建一个包含 …...
WPF图表控件库
LiveCharts: LiveCharts2预览版、内存管理不是很好,长时间持续更新的情况下,内存溢出,慎用 数据加载量不能太大(1000点左右 开始卡) 第一步:下载LiveChart NuGet包 第二步:引用&a…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
