顺序表和链表,时间和空间复杂度--数据结构初阶(1)(C/C++)
文章目录
- 前言
- 时间复杂度和空间复杂度
- 理论部分
- 习题部分
- 顺序表和链表
- 理论部分
- 作业部分
前言
这期的话会给大家讲解复杂度,顺序表和链表的一些知识和习题部分(重点是习题部分,因为这几个理念都比较简单)
时间复杂度和空间复杂度
理论部分
时间复杂度和空间复杂度的计算一般都是遵循大O表示法,然后的话时间复杂度的计算都是按照最坏的情况计算的
大O表示法的相关概念:
1.用常数1取代运行时间中的所有加法常数。
2、在修改后的运行次数函数中,只保留最高阶项。
3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶
习题部分
这道题要注意的地方是在代码上这里的循环虽然让人感觉是n次,但是实际上没有执行到n次,应该选择D选项
题目:力扣 移除元素(移除特定元素的好办法)
原地移除,并且要不变的元素移到前面,方法:
遇到不等于val的元素(第k个)时,就把该元素移到第k个位置即可
此题不了解的知识:a[0] = a[0]是不会报错的
代码展示:
class Solution {
public:int removeElement(vector<int>& nums, int val) {int k = 0;int n = nums.size();for(int i = 0;i<=n-1;i++){if(nums[i]!= val)nums[k++] = nums[i];}return k;}
};
顺序表和链表
理论部分
链表能做的事,顺序表都可以完成,只是操作方法不同,效率不同
顺序表比链表唯一好的地方就是找下标为多少的位置好,其他都是链表好些
顺序表跟数组非常的相似,几乎可以说是一模一样
链表的话有用数组模拟的,还有用结构体去模拟的,一般来说,在竞赛方面,一般都是用数组去模拟(但是感觉竞赛没必要用链表),在工程方面的话,一般是动态去用结构体去模拟
顺序表的动态模拟:
typedef int SLDataType;
typedef struct SeqList
{SLDataType* a;int size; // 有效数据个数int capacity; // 空间容量
}SL;// 增删查改
void SLInit(SL* ps);
void SLDestroy(SL* ps);
void SLPrint(SL* ps);
void SLCheckCapacity(SL* ps);
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);
int SLFind(SL* ps, SLDataType x);void SLInit(SL* ps)
{assert(ps);ps->a = (SLDataType*)malloc(sizeof(SLDataType)* INIT_CAPACITY);if (ps->a == NULL){perror("malloc fail");return;}ps->size = 0;ps->capacity = INIT_CAPACITY;
}void SLDestroy(SL* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->capacity = ps->size = 0;
}void SLPrint(SL* ps)
{assert(ps);for (int i = 0; i < ps->size; ++i){printf("%d ", ps->a[i]);}printf("\n");
}void SLCheckCapacity(SL* ps)
{assert(ps);if (ps->size == ps->capacity){SLDataType* tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * ps->capacity * 2);if (tmp == NULL){perror("realloc fail");return;}ps->a = tmp;ps->capacity *= 2;}
}void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);SLCheckCapacity(ps);int end = ps->size - 1;while (end >= pos){ps->a[end + 1] = ps->a[end];--end;}ps->a[pos] = x;ps->size++;
}void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);int begin = pos + 1;while (begin < ps->size){ps->a[begin - 1] = ps->a[begin];++begin;}ps->size--;
}int SLFind(SL* ps, SLDataType x)
{assert(ps);for(int i = 0; i < ps->size; ++i){if (ps->a[i] == x){return i;}}return -1;
}在书写的时候需要注意的几个点:
1.ps.a[ps.size++]这里面的ps.size可以不打括号,因为是类似名字
2.扩容一般喜欢扩为原来的二倍(因为以后C++的STL中的一般都是这样搞的,比如vector)
3.开辟空间一定要检查开辟成功没有
说到开辟成功与否,还有个要注意的点是数组那个叫做越界 指针那个叫做空指针或者野指针,不要叫错了
链表的动态模拟:
typedef int SLTDataType;typedef struct SListNode
{SLTDataType data;struct SListNode* next;
}SLTNode;
// 单链表查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x);
// pos之前插入
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
// pos位置删除
void SLTErase(SLTNode** pphead, SLTNode* pos);// pos后面插入
void SLTInsertAfter(SLTNode* pos, SLTDataType x);
// pos位置后面删除
void SLTEraseAfter(SLTNode* pos);SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{SLTNode* cur = phead;while (cur){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}// pos之前插入
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pos);assert(pphead);if (pos == *pphead){SLTPushFront(pphead, x);}else{// 找到pos的前一个位置SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}SLTNode* newnode = BuySLTNode(x);prev->next = newnode;newnode->next = pos;}
}// pos位置删除
void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead);assert(pos);//assert(*pphead);if (*pphead == pos){SLTPopFront(pphead);}else{// 找到pos的前一个位置SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}prev->next = pos->next;free(pos);//pos = NULL;}
}// pos后面插入
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{assert(pos);SLTNode* newnode = BuySLTNode(x);newnode->next = pos->next;pos->next = newnode;
}// pos位置后面删除
void SLTEraseAfter(SLTNode* pos)
{assert(pos);assert(pos->next);SLTNode* del = pos->next;pos->next = del->next;free(del);del = NULL;
}注意事项:
不难发现,其中有些函数的形参是*有些是**,这个的话要看是要改什么
一般来说,可以总结为一句话,传想改的东西的地址过去,比如:你想改指针本身,那就要把指针的地址传过去
还有就是,链表的头节点要赋值给其他再拿去了,不然就会"一去不复返"
作业部分
在这里先总结一手:
链表这里最好单用头插或者尾插 而不用中间插入删除这些(除非没有更好的思路了,不然麻烦)
取巧的办法:把链表里面的值放到数组中去搞(面试会卡空间复杂度让你不能用这个)
单链表的话一般不动头结点,而是再搞一个尾节点去动尾节点,不然后面要用头就不行了
单链表可能空的话建议加个哨兵位,不然要分很多类讨论
注意:创建结构体变量跟开辟空间的区别:
创建结构体变量就相当于开辟了空间
创建的是结构体指针的话,要自己为结构体开辟空间(自己一般这么搞的)
代码展示:
struct Nodenew = (struct Node)malloc(sizeof(struct Node));
力扣 合并两个有序数组
这个题从前面开始比较的话会需要把后面的往后推
从后面开始比较就不用,所以采用从后面开始比较的方法
代码展示:
class Solution {
public:void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {while(n>0&&m>0){if(nums1[m-1]>nums2[n-1]){nums1[m+n-1] = nums1[m-1];m--;}else{nums1[m+n-1] = nums2[n-1];n--;}}while(n>0){nums1[n-1] = nums2[n-1];n--;}}
};
力扣 删除链表中等于给定值 val 的所有结点
1.传统做法:
当前指针cur cur前面的那个指针prev,然后用cur去遍历看
2.不是val的值就尾插到新链表中(我选的是这一种)
代码展示:
/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/
struct ListNode* removeElements(struct ListNode* head, int val) {struct ListNode*tail = NULL;struct ListNode*old = head;int num = 0;while(old){if(old->val!=val){if(tail == NULL){head = tail = old;num++;}else{tail->next = old;tail = tail->next;num++;}}old = old->next;}if(tail){tail->next = NULL;}if(!num){head = NULL;}return head;
}
力扣 链表的中间结点
做法:快慢指针
慢指针一次走一个next 快指针一次走两个next
/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/
struct ListNode* middleNode(struct ListNode* head) {struct ListNode *slow = head;struct ListNode *fast = head;while(fast&&fast->next){slow = slow->next;fast = fast->next->next;}return slow;
}
例题:牛客网 返回倒数第k个节点的值
做法:快指针比慢指针多走k个节点
力扣 反转链表
做法:
取旧节点头插到新链表里
另外,这题让返回链表,其实就是返回头节点
代码展示:
/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/
struct ListNode* reverseList(struct ListNode* head) {struct ListNode* newhead = NULL ;struct ListNode*a = head;struct ListNode*next ;while(a){next = a->next;a->next = newhead;newhead = a;a = next;}
return newhead;
}
例题:力扣 合并两个有序链表
做法:依次比较 取小的尾插
注意:头节点在第一次插的时候要记得给第一个插的节点的地址,而不是还是eg:NULL
代码展示:
/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {if(list1 == 0)return list2;if(list2 == 0)return list1;struct ListNode*cur1 = list1,*cur2 = list2;struct ListNode*list3 = NULL;struct ListNode*tail = NULL;while(cur1&&cur2){if(cur1->val>cur2->val){if(list3 == NULL){list3 = tail = cur2;cur2 = cur2->next;}else{tail->next = cur2;cur2 = cur2->next;tail = tail->next;}}else{if(list3 == NULL){list3 = tail = cur1;cur1 = cur1->next;}else{tail->next = cur1;cur1 = cur1->next;tail = tail->next;}}}if(cur1!= NULL) tail->next = cur1;else tail->next = cur2;return list3;
}
例题:牛客网 链表分割
做法:小于x的尾插到一个链表
大于x的尾插到另一个链表 然后把这两个链接起来
(后面那个哨兵位的头结点不要)
这里说不能改变原来数据的顺序–代码中间改没问题,只要最后跟原来一样就行
代码展示:
/*
struct ListNode {int val;struct ListNode *next;ListNode(int x) : val(x), next(NULL) {}
};*/
class Partition {
public:ListNode* partition(ListNode* pHead, int x) {// write code hereListNode*ghead = NULL,*gtail = NULL,*lhead = NULL,*ltail = NULL;while(pHead){if(pHead->val<x){if(lhead ==NULL){lhead = ltail = pHead;}else{ltail->next = pHead;ltail = ltail->next;}//!!!}else{if(ghead ==NULL){ghead = gtail = pHead;}else{gtail->next = pHead;gtail = gtail->next;}}pHead = pHead->next;}if (gtail) gtail->next = NULL; if (ltail) ltail->next = ghead; return lhead?lhead:ghead;}
};
例题:牛客网 链表的回文结构
做法:1.找到中间节点 2.从中间节点开始,对后半段逆置 3.前半段和后半段比较就行
代码展示:
/*
struct ListNode {int val;struct ListNode *next;ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:bool chkPalindrome(ListNode* A) {// write code hereListNode*slow = A,*fast = A;while(fast&&fast->next)//!!!!!!!!{slow = slow->next;fast = fast->next->next;}ListNode*cur = slow;ListNode*prev = nullptr;ListNode*tmp = nullptr;while(cur){tmp = cur->next;cur->next = prev;prev = cur;cur = tmp;}ListNode*head = prev;while(head){if(head->val!=A->val)return false;head = head->next;A = A->next;}return true;}
};
例题:力扣 相交链表
做法:1.分别求两个链表的长度 2.长的链表先走差距步 3.再同时走,第一个地址相同的就是交点
代码展示:
/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {int lenA = 0;int lenB = 0;struct ListNode* cur1 = headA;struct ListNode* cur2 = headB;while(cur1){cur1 = cur1->next;lenA++;}while(cur2){cur2 = cur2->next;lenB++;}int gap = abs(lenA-lenB);struct ListNode*longlist = headA; struct ListNode*shortlist = headB;if(lenA<lenB){shortlist = headA;longlist = headB;}while(gap--)longlist = longlist->next;while(longlist){if(longlist == shortlist)return longlist;longlist = longlist->next;shortlist = shortlist->next;}return NULL;
}
例题: 力扣 环形链表
做法:快慢指针(这里选择fast一次两步,slow一次一步)
while(fast&&fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
延伸的常考问题:(这个是企业面试时的常考点)
1.为什么slow走1步,fast走2步,他们会相遇?会不会错过?请证明
slow进环以后,fast开始追击slow,slow每走一步,fast走两步,他们之间的距离缩小1
当距离为0的时候就追上了
2.为什么slow走1步,fast走n步(n>=3),他们会相遇?会不会错过?请证明
如果之间的距离N是n-1的倍数的话才能相遇,否则余数不为0是追不上的
3.求环的长度:
让slow再走到跟fast的相遇点的步数就是
4.求入环的第一个结点(也就是入口点)
例题:力扣 环形链表II
这里有个结论(带一个环的链表):
一个指针从相遇点走,一个指针从起始点走,会在入口点相遇
(怎么推出来的要知道)
做法:1.用那个结论
2.让相遇点跟相遇点的下一个节点之间的链接断开
然后将找入口点问题转换成找链表的交点
代码展示:
/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/
bool hasCycle(struct ListNode *head) {struct ListNode*fast = head,*slow = head;while(fast&&fast->next){slow = slow->next;fast = fast->next->next;if(slow == fast)return true;}return false;
}
例题;力扣 复制带随机指针的链表
做法:1.先复制旧节点然后连在每个旧节点后面(NULL不复制)
2.把新节点的random搞一下(新节点->random = 旧节点->random->next)
3.把新节点从旧节点的链表上断下来成为新链表
代码展示:
/*** Definition for a Node.* struct Node {* int val;* struct Node *next;* struct Node *random;* };*/struct Node* copyRandomList(struct Node* head) {struct Node*newhead = NULL;struct Node*new = NULL;struct Node*old = head;struct Node*tail = NULL;while(old){new = (struct Node*)malloc(sizeof(struct Node));new->val = old->val;new->next = old->next;tail = old->next;old->next = new;old = tail;}old = head;while(old){new = old->next;if(old->random)new->random = old->random->next;//!!!else{new->random = NULL;}if(old->next)old = old->next->next;else{break;}}//新节点脱落old = head;while(old){if(old == head)new = newhead = old->next;
if(old->next)old = old->next->next;if(new->next){new->next = new->next->next;new = new->next;//!!!}}return newhead;
}
相关文章:
顺序表和链表,时间和空间复杂度--数据结构初阶(1)(C/C++)
文章目录 前言时间复杂度和空间复杂度理论部分习题部分 顺序表和链表理论部分作业部分 前言 这期的话会给大家讲解复杂度,顺序表和链表的一些知识和习题部分(重点是习题部分,因为这几个理念都比较简单) 时间复杂度和空间复杂度 理论部分 时间复杂度和…...
【C++面向对象】封装(下):探索C++运算符重载设计精髓
🔥个人主页 🔥 😈所属专栏😈 每文一诗 💪🏼 年年岁岁花相似,岁岁年年人不同 —— 唐/刘希夷《代悲白头翁》 译文:年年岁岁繁花依旧,岁岁年年看花之人却不相同 目录 C运…...
分布式存储数据恢复—hbase和hive数据库文件被删除如何恢复数据?
分布式存储数据恢复环境: 16台某品牌R730xd服务器节点,每台服务器节点上有数台虚拟机。 虚拟机上部署Hbase和Hive数据库。 分布式存储故障: 数据库底层文件被误删除,数据库不能使用。要求恢复hbase和hive数据库。 北亚企安数据恢复…...
【并行分布计算】Hadoop伪分布搭建
Hadoop伪分布搭建 1. 修改core-site.xml fs.defaultFS设置的是HDFS的地址,设置运行在本地的9000端口上 hadoop.tmp.dir设置的是临时目录,如果没有设置的话默认在/tmp/hadoop-${user.name}中,系统重启后会导致数据丢失,因此修改这…...
Redis面试——常用命令
一、String (1)设置值相关命令 1.1.1 SET 功能:设置一个键值对,如果键已存在则覆盖旧值语法: SET key value [EX seconds] [PX milliseconds] [NX|XX]EX seconds:设置键的过期时间为 seconds 秒 PX milli…...
告别定时任务!用Dagster监听器实现秒级数据响应自动化
在数据管道开发中,我们经常面临需要根据外部事件触发计算任务的场景。传统基于时间的调度方式存在资源浪费和时效性不足的问题。本文将通过Dagster的**传感器(Sensor)**功能,演示如何构建事件驱动的数据处理流程。 场景模拟&…...
测试用例的生命周期:从诞生到退役的全过程管理
测试用例不是一成不变的标本 在敏捷开发时代,测试用例就像有机生命体一样会经历完整的生命周期。据Microsoft Research调查,良好管理的测试用例可使缺陷发现率提升40%,而缺乏管理的用例库在6个月后失效比例高达65%,本文将深入解析…...
【并行分布计算】Hadoop单机分布搭建
Hadoop单机分布搭建 环境:VMware Workstation虚拟机centos7镜像MobaXterm远程连接工具 为了使机器都处于同一个局域网中,先要修改机器的ip地址分配方式为固定ip,并为其固定分配一个ip地址。 [rootlocalhost ~]# vi /etc/sysconfig/network-…...
Android studio前沿开发--利用socket服务器连接AI实现前后端交互(全站首发思路)
我们在前几期学习了利用socket进行前后端的交互,但那只是基础性知识,这次,通过参考讯飞星火的java参考文档,再结合之前所学的socket服务,成功实现了通过后端将AI的调用实现在了自己的APP中。 本次的学习内容 1.真机的…...
Redis的下载安装和使用(超详细)
目录 一、所需的安装包资源小编放下述网盘了,提取码:wshf 二、双击打开文件redis.desktop.manager.exe 三、点击next后,再点击i agree 四、点击箭头指向,选择安装路径,然后点击Install进行安装 五、安装完后依次点…...
手机状态:UML 状态图(State Diagram)的解析与绘画
目录 一、UML 状态图(State Diagram)是什么 二、题目原型 三、手机状态图的解析 状态转换的触发条件 四、状态图的构建与解读 图的解读 五、状态图的实际应用 六、总结与展望 一、UML 状态图(State Diagram)是什么 UML …...
MyBatisPlus-QueryWrapper的exists方法拼接SQL中的EXISTS子句
在 MyBatis-Plus 中,QueryWrapper 的 exists 方法用于拼接 SQL 中的 EXISTS 子句,通常用于构 建子查询条件。以下是具体用法和示例: 1. 基本语法 // 判断是否存在符合条件的记录 queryWrapper.exists(String existsSql); queryWrapper.notExists(String existsSq…...
HarmonyOS-ArkUI: 自定义组件冻结功能@ComonentV2 freezeWhenInactive属性
引 @ComponentV2 装饰器是可以接收参数的,叫freezeWhenInactive, 顾名思义,就是当组件变成Inactive的时候,冻结。其默认值是false。所以如果您没有传参数时,默认不冻结。 冻结到底是一种什么状态呢?说简单点就是状态变量不响应更新。@Monitor修饰的那些状态变量更新检测…...
【问题】一招解决vscode输出和终端不一致的困扰
背景(闲话Trae) Trae是挺好,用了几天,发现它时不时检查文件,一检测就转悠半天,为此我把当前环境清空,就留一个正在调的程序,结果还照样检测,虽然没影响什么,…...
【CODESYS学习笔记001】MODBUS-TCP 与 标准TCP通信的优缺点对比
1. MODBUS-TCP 优点: 1. 标准化协议 - 基于工业标准(RFC标准),兼容性强,几乎所有PLC和工业设备都支持。 - 固定功能码(如0x03读寄存器、0x10写寄存器),开发简单。 2. 数据格…...
⭐ Unity 使用Odin Inspector增强编辑器的功能:UIManager脚本实例
先看一下测试效果: 在Unity开发中,Odin Inspector已经成为了一个非常受欢迎的工具,它通过增强编辑器的功能,使得开发者在工作中更加高效,尤其是在处理复杂数据和自定义编辑器方面。今天,我们将通过一个简…...
Linux网络协议栈深度解析:从数据封装到子网划分的底层架构
知识点5 1、封装和解封装的流程 封装数据报文:发送数据 解封装数据报文:接收报文 以后我们的网络编程过程中,只需要告知IP与端口号,链路层的MAC地址 有协议栈帮我们提供。 2、链路层报文格式(mac报文) …...
Java与MySQL数据库连接的JDBC驱动配置教程
系列文章目录 Java JDBC编程 文章目录 系列文章目录前言一、JDBC简介:二、mysql-connector-java驱动详解: 驱动版本特性介绍: 三、JDBC驱动安装与配置: 1.IDE项目设置:2.命令行安装:3.使用Maven或Gradle :…...
光伏产品研发项目如何降本增效?8Manage 项目管理软件在复合材料制造的应用
在复合材料制造领域,特别是光伏PECVD石墨舟和燃料电池石墨双极板等高精尖产品的研发过程中,高效的项目管理直接决定了产品开发周期、质量和市场竞争力。然而,许多企业在项目立项、进度跟踪、资源分配和质量控制等环节面临挑战。 针对这些痛点…...
矫平机:工业制造中的“板材整形师“
在机械制造车间此起彼伏的轰鸣声中,一卷卷冷轧钢卷正经历着神奇的蜕变。经过开卷、矫平、剪切等工序,原本蜷曲的金属板材变得平整如镜,这些改变都源于生产线上一个关键设备——矫平机。这台被称作"板材整形师"的精密机械࿰…...
数据江湖:Node.js 与 SQLite3 的轻量之道
前言 在这个“万码奔腾”的时代,想在江湖中闯出一片天地,不光要有剑(JavaScript),还得有招式(数据库)!本篇秘籍便是教你如何用 Node.js + SQLite3 打造一座小而美的“数据藏经阁”。初学者可轻松上手,高手可在细节中悟出更深的“数据库心法”。 简介 SQLite 在前端…...
4.15BUUCTF Ez_bypass,HardSQL,AreUSerialz,BabyUpload,CheckIn
[MRCTF2020]Ez_bypass 打开环境,看源码 include flag.php; $flagMRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}; if(isset($_GET[gg])&&isset($_GET[id])) {$id$_GET[id];$gg$_GET[gg];if (md5($id) md5($gg) && $id ! $gg) {echo You got the first step;i…...
【HarmonyOS NEXT+AI】问答 03:找不到 DevEco Studio Cangjie Plugin 下载链接?
【HarmonyOS NEXTAI】问答 03:找不到 DevEco Studio Cangjie Plugin 下载链接? 在 "HarmonyOS NEXTAI 大模型打造智能助手 APP (仓颉版)" 课程里面,有学员提到了这样一个问题:我在华为开发者社区官网找不到 DevEco Stu…...
使用 reverse-sourcemap 工具反编译 Vue 项目
要使用 reverse-sourcemap 工具反编译 Vue 项目,可以按照以下步骤操作: 步骤一:安装 reverse-sourcemap 首先,需要全局安装 reverse-sourcemap 工具。在命令行中执行以下命令: npm install --global reverse-sourcem…...
通信安全员历年考试重难点有哪些?
通信安全员考试的重难点紧密围绕行业特性和法规更新展开,需结合最新政策与实践案例综合掌握。以下是基于历年考试趋势及 2025 年新规的深度解析: 一、核心法规与标准体系(占比 30%-40%) 1. 安全生产法与行业规定 《安全生产法》…...
C++(OpenCV)实现MATLAB的edge(I, “sobel“)边缘检测
文章目录 方案分析具体代码实现关键步骤说明注意事项 为了实现类似于MATLAB的edge(I, "sobel")函数的C代码,我们需要复现其完整的边缘检测流程,包括梯度计算、非极大值抑制和阈值处理。以下是具体的方案及代码实现: 方案分析 图像…...
uniapp通过uni.addInterceptor实现路由拦截
注:此拦截不能首次拦截路由跳转的方法(switchTab, navigateTo, reLaunch, redirectTo),拦截request请求api可以 1. app.vue 代码 import { onLaunch} from dcloudio/uni-appimport permission from ./utils/permissiononLaunch(…...
vue2.x Echart label根据数据长度选择不同的间隔显示
折线图需要在各个点上方展示数据,但是数据数字的位数可能达到5~8位,需要根据密度进行间隔展示。例如,如果数据长度小于7,则每一项都展示,如果在7~10之间,2位展示一项,如果大于10,那么…...
Wifi密码查看软件V1.0
⭐本软件用于查看电脑连接过所有WiFi密码,不具备破解功能。 可在忘记WiFi密码或他人输入密码自己不知道的情况下使用。 ⭐⭐为便于快速分享,加入双击【密码】列可将WIFI密码复制在粘贴板。 ⭐⭐⭐双击【名称】列可生成用于手机连接的二维码进行显示&…...
Hyperf (Swoole)的多进程 + 单线程协程、Gin (Go)Go的单进程 + 多 goroutine 解说
1. 核心概念解析 (1) Hyperf (Swoole): 多进程 单线程协程 Swoole 并发模型详解 Swoole 的并发模型基于多进程架构,每个进程是单线程的,线程内运行多个协程。以下是其结构的关键点: 多进程:Swoole 应用程序启动时,…...
国内网络设备厂商名单(List of Domestic Network Equipment Manufacturers)
国内网络设备厂商名单 运维工程师必须广泛熟悉国内外各大厂商的设备,深入掌握其应用场景、功能特点及优势。这不仅有助于在故障排查时迅速定位问题,还能在系统设计、优化与升级中做出更合理的决策。对设备特性的精准把握,能够显著提升运维效…...
基础元器件-电感(2025.4.17)
1.电感是电磁感应器件,它是储能元器件。 2.电感表示形式(直标法和色标法) 3.电感读取基准是mH,3R3指的是3.3mH,R代表小数点。 4.电感特性:通直流阻交流 5.电感的分类 注:用电容或者电感滤波是…...
高通手机抓取sniffer log的方法
方法如下: adb root adb remount adb shell echo 4 >/sys/module/wlan/parameters/con_mode //不同的高通基线这块目录存在差异性 ifconfig wlan0 up iwpriv wlan0 setMonChan 149 2 //设置信道和bandwitdh tcpdump -i wlan0 -v -w /data/chan149.pcap 生成…...
React 设计艺术:如何精确拆分组件接口,实现接口隔离原则
接口隔离原则 接口隔离原则(Interface Segregation Principle,简称 ISP)也是面向对象设计中的重要原则之一。它的核心思想是,一个类不应该依赖它不需要的接口。在 React 开发中,遵循接口隔离原则可以提高代码的可维护性…...
BFS DFS ----习题
题目1 答案1 #include <bits/stdc.h>using namespace std;const int N 210; int n,k; int arr[N]; int res 0;void dfs(int x,int start,int nowsum) {if (nowsum > n) return ;if(x>k){if(nowsum n) res;return ;}for(int i start;nowsumi*(k-x1)<n;i){a…...
第十七届“华中杯”大学生数学建模挑战赛题目A题 晶硅片产销策略优化 完整成品 代码 模型 思路 分享
近年来,高纯度晶硅片需求的增长引发了更激烈的市场竞争。晶硅片企业需要在成本控制、利润优化和供需管理之间取得平衡,以提高经营效率和市场竞争力。晶硅片的生产是一个高能耗、高成本的过程,企业效益会受到原材料价格波动、市场需求变化以及…...
java 设计模式之单例模式
简介 单例模式:一个类有且仅有一个实例,该类负责创建自己的对象,同时确保只有一个对象被创建。 特点:类构造器私有、持有自己实例、对外提供获取实例的静态方法。 单例模式的实现方式 饿汉式 类被加载时,就会实例…...
新能源汽车能量流测试的传感器融合技术应用指南
第一部分:核心原理模块化拆解 模块1:多源传感器物理层融合 关键技术: 高精度同步采集架构 采用PXIe-8840控制器同步定时模块(NI PXIe-6674T),实现CAN/LIN/模拟量信号的μs级同步光纤电压传感器࿰…...
高级java每日一道面试题-2025年4月11日-微服务篇[Nacos篇]-Nacos使用的数据库及其数据同步机制是什么?
如果有遗漏,评论区告诉我进行补充 面试官: Nacos使用的数据库及其数据同步机制是什么? 我回答: Nacos 使用的数据库及其数据同步机制详解 在微服务架构中,Nacos 作为服务注册与配置管理的核心组件,其数据存储和同步机制对系统的高可用性和…...
音视频相关协议和技术内容
视频编解码: H264(AVC,MPEG-4 Part 10) 高压缩率,支持多种分辨率和帧率,用于在线流媒体、会议、数字电视 编码过程: 分块处理,将视频帧划分为宏块(16x16)使用帧预测和…...
SpringBoot整合Rabbitmq(包括docker配置Rabbitmq的详细过程)
一、什么是mq MQ(message queue),从字面意思上看就个 FIFO 先入先出的队列,只不过队列中存放的内容是 message 而已,它是一种具有接收数据、存储数据、发送数据等功能的技术服务。 在互联网架构中,MQ 是一种非常常见的上下游“逻…...
20个常用的初级Java笔试题及其参考答案
### 1. Java基本数据类型有哪些? - **答案**:Java中的基本数据类型有: - `byte`:8位 - `short`:16位 - `int`:32位 - `long`:64位 - `float`:32位 - `double`:64位 - `char`:16位(Unicode字符) - `boolean`:表示真或假(没有固定大小) ### 2. Java中的字符串是可…...
矫平机:工业制造的精密“雕刻师”
在金属加工的浩瀚图景中,矫平机犹如一位沉默的雕塑大师,用机械的精准与科学的智慧,将扭曲变形的板材重塑为工业艺术的杰作。从新能源电池极片到空间站耐压舱体,矫平工艺贯穿现代制造的每一处精度巅峰。 一、核心技术:从…...
游戏数据分析,力扣(游戏玩法分析 I~V)mysql+pandas
力扣的游戏玩法分析 I~V, ps:虽然表结构不变但是力扣输入示例数据有些许变化,所以你使用上一题的数据跑下一题的代码可能产生的结果和示例中的不一样,建议点击连接到力扣中直接运行! 目录 1. 游戏玩法分析 I mysql …...
C++之哈希
目录 一、unordered_set 1.1、unordered_set的介绍 1.2、unordered_set和set的使用差异 二、unordered_map 2.1、unordered_map和map的差异 2.2、unordered_multimap/unordered_multiset 三、哈希表 3.1、哈希概念 3.1.1、直接定地址法 3.1.2、哈希冲突 3.1.3、负载…...
DSP、MCU、FPGA 的详细总结
一、核心定义与特点 类型定义核心特点DSP(数字信号处理器)专为高速数字信号处理设计的处理器- 哈佛架构,单周期乘加(MAC) - 实时性强,低延迟处理流式数据 - 专用指令集优化算法(如FFT、滤波&am…...
linux学习 3.用户的操作
用户 建议在系统操作的时候不要一直使用root用户,因为root用户具有最高权限,你可能因为某些操作影响了你的系统,采用子用户则可以避免这一点 这里的学习不用太深入,掌握如何创建删除切换即可(除非你要做详细的用户管理࿰…...
闭坑-- `a-auto-complete` 组件中的 `options` 数据存在重复
当 ant-design 的 a-auto-complete 组件中的 options 数据存在重复时,可能会导致以下问题: 1. 交互问题 键盘导航失效: 使用键盘上下键选择时,可能会在重复项之间跳转,无法正常移动到下一个选项。选择结果不准确&…...
【Rust基础】使用Rocket构建基于SSE的流式回复
背景 我们正在使用Rust开发基于RAG的知识库系统,其中对于模型的回复使用了常用的SSE,Web框架使用Rocket,Rocket提供了一个简单的方式支持SSE,但没有会话保持、会话恢复等功能,因此我们自己简单实现这两个功能。 使用R…...
一种改进的CFAR算法用于目标检测(解决多目标掩蔽)
摘要 恒虚警率(CFAR)技术在雷达自动检测过程中起着关键作用。单元平均(CA)CFAR算法在几乎所有的多目标情况下都会受到掩蔽效应的影响。最小单元平均(SOCA)CFAR算法仅当干扰目标位于参考窗口的前后方时才具有…...