初阶数据结构(三)链表
💓博主csdn个人主页:小小unicorn💓
⏩专栏分类:c++
🚚代码仓库:小小unicorn的学习足迹🚚
🌹🌹🌹关注我带你学习编程知识
前面我们讲的线性表的顺序存储结构。它是有缺点的,最大的缺点就是插入和删除时需要移动大量元素,这显然就需要耗费时间,那能不能想办法解决呢?
要解决这个问题,我们就得考虑一下导致这个问题的大致原因:
为什么当插入和制除时,就要移动大量元素?仔细分析后,发现原因就在于自元素的存储位置也具有邻居关系。它们编号是1,2,3,…,n,它们在内存中的位最的是按着的,中间没有空源,当然就无法快速插入,而删除后,当中就会留出空像,自然需要弥补。问题就出在这里。
A同学思路:让当中每个元素之间都留有一个空位置,这样要插入时,就不至于动,可一个空位置如何解决多个相同位置插入数据的问题呢?所以这个想法显然不行。
B同学思路:那就让当中每个元素之间都留足够多的位置,根据实际情况制定空像大小,比如10个,这样插入时,就不需要移动了。万一10个空位用完了,再考虑移动使得每个位置之间都有10个空位置。如果删除,就直接删掉,把位置留空即可。这样似乎蓄时解决了插入和删除的移动数据问题。可这对于超过10个同位置数据的插入,效率上还是存在问题。对于数据的遍历,也会因为空位置太多而造成判断时间上的浪费。而且显然这里空间复杂度还增加了,因为每个元素之间都有若干个空位置。
C同学思路:我们反正也是要让相邻元素间留有足够余地,那干脆所有的元素都不要考虑相邻位置了,哪有空位就到哪里,而只是让每个元素知道它下一个元素的位置在哪里,这样,我们可以在第一个元素时,就知道第二个元素的位置(内存地址),而找到它:在第二个元素时,再找到第三个元素的位置(内存地址)。这样所有的元素我们就都可以通过遍历而找到。
好!大棒了,这个想法非常好!
C同学,可惜生晚了几十年,不然,c同学的想法对于数据结构来讲就是划时代的意义。我们要的就是这个思路。
链表
- 1.线性表的联试存储结构
- 1.1线性表链式存储结构定义
- 1.2头指针与头结点的异同
- 1.3线性表链式存储结构代码描述
- 2.单链表的具体实现:
- 2.1开辟节点
- 2.2遍历链表以及开辟新节点
- 3.接口函数的实现(增删查改)
- 3.1尾插
- 3.2头插
- 3.3尾删
- 3.4头删
- 3.5查找
- 3.6在pos位置之前插入x
- 3.7在pos位置以后插入x
- 3.8删除pos位置
- 3.9删除pos的后一个位置
- 4.单链表结构与顺序存储结构的优缺点
- 5.链表完整代码:
- 5.1 SList.h
- 5.2 SList.c
- 5.3 Test.c
1.线性表的联试存储结构
1.1线性表链式存储结构定义
在解释这个思路之前,我们先来谈另一个话题。前几年,有一本书风靡了全世界,它叫《达·芬奇密码》,成为世界上最畅销的小说之一,书的内容集合了侦探、惊使和阴谋论等多种风格,很好看。这本书和绝大部分负小说一样,都是同一种处理办法。那就是,作者不会让你事先知道整个过程的全部,而是在一步一步地到这某个环节,才根据现场的信息,获得或推断出下一步是什么,也就是说,每一步除了对你侦破的信息进一步确认外(之前信息也不一定都是对的,有时是证明某个信息不正确),还有就是对下一步如何操作或行动的指引。
不过,这个例子也不完全与线性表相符合,因为案件侦破的线案可能是错综复杂的,有点像我们之后要讲到的树和图的数据结构。今天,我们要讲的是单线索,无分支的情况。即线性表的链式存储结构。
线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的。这就意 味着,这些数据元素可以存在内存未被占用的任意位置
(如下图所示)。
以前在顺序结构中,每个数据元素只需要存储数据 元素信息就可以了。现在链式结构中,除了要存储数据 元素信息外,还要存储它的后继元素的存储地址。
因此,为了表示每个数据元素ai与其直接后继数据 元素ai+1(i是下标)之间的逻辑关系,对数据元素ai来说,除了存储 其本身的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储位置)。我们把存储数据元素信息的域称为数据域,把存储直接后继位置的域称为指针域。指针域中存储的信息称作指针或链。这两部分信息组成数据元素ai的存储映像,称为结点(Node)。
n个结点(a的存储映像)链结成一个链表,即为线性表(a,ay·,a)的链式存储结构,因为此链表的每个结点中只包含一个指针域,所以叫做单链表。单链表正是通过每个结点的指针域将线性表的数据元素按其逻辑次序链接在一起。
对于线性表来说,总得有个头有个尾,链表也不例外。我们把链表中第一个结点的存储位置叫做头指针,那么整个链表的存取就必须是从头指针开始进行了。之后的每一个结点,其实就是上一个的后继指针指向的位置。想象一下,最后一个结点,它的指针指向哪里?
最后一个,当然就意味着直接后继不存在了,所以我们规定,线性链表的最后一个结点指针为“空”(通常用NULL或“^”符号表示,如下图所示)。
有时,我们为了更加方便地对链表进行操作,会在单链表的第一个结点前附设一个结点,称为头结点。头结点的数据域可以不存储任何信息,谁叫它是第一个呢,有这个特权。也可以存储如线性表的长度等附加信息,头结点的指针域存储指向第一个结点的指针,如下图所示。
1.2头指针与头结点的异同
头指针与头结点的异同点,如下图所示:
1.3线性表链式存储结构代码描述
若线性表为空,则头结点的指针域为“空”,如下图所示:
这里我们大概用图示表达了内存中单链表的存储状态。看着满图的省略号“…”,就知道是有多么不方便。而我们真正关心的它在内存中的实际位置吗?不是的。这只是它所表示的线性表中的数据元素及数据元素之间色逻辑关系。所以我们改用更方便的存储示意图来表示单链表,如下图所示:
若带有头结点的单链表,则如下图所示:
空链表如下图所示:
单链表中,我们在c语言中可用结构指针来描述:
//线性表的单链表的存储结构:
typedef struct Node
{ElemType data;struct Node*next;
}Node;
typedef struct Node*LinkList;//定义linkList
从这个结构定义中,我们也就知道,结点由存放数据元素的数据域和存放后继结点地址的指针域组成。假设p是指向线性表第i个元素的指针,则该结点ai 的数据域我们可以用p->data来表示,p->data的值是一个数据元素,结点ai的指针域可以用p->next来表示,p->next的值是一个指针。p->next指向谁呢?当然是指向第i+1个元素,即指向ai+l的指针。也就是说,如果p->data等于a,那么p>next->data等于ai+1(如下图所示)。
2.单链表的具体实现:
2.1开辟节点
首先创建一个新项目,分为三个模块:SList.c用来实现接口函数;SList.h用来结构体创建与函数声明;test.c则用来进行测试我们的接口函数。
创建节点如下:
2.2遍历链表以及开辟新节点
咱们首先用一个cur来存放头结点的地址;
那后面节点的数据怎么访问呢?咱们可以让cur->next赋给cur;
依次内推;当cur为空时;说明已经访问结束。 最后打印即可。
为方便测试我们可以先写一个交互性的链表测试:
写交互性测试的时候,会涉及到开辟新节点,这里我们可以抽离一个函数来专门进行开辟新节点。
测试结果如下:
3.接口函数的实现(增删查改)
3.1尾插
那么如何实现尾插呢?尾插我们首先得先找到尾。
那么如何找呢?
先看下面这个代码。
如果要是这样找尾的话,就会出现一个问题。我们画图分析一下。
这个代码是不是首先有三个指针变量 plist tail newnode;
随着代码运行,最后taill的地址为空,假设新节点的地址为0x0012ff00,那节点newnode存放的地址也就是0x0012ff00,最后呢,又把newnode的地址给了taill,看起来没问题,但有没有想过,这三个指针变量出了作用域呢?
出了作用域,这三个指针变量是不是都销毁了,这不仅造成了内存泄漏还没有吧链表链接起来。基于这个问题,我们在回过来思考这个问题,如何找尾?
所以我们的尾用taii找的时候,条件不是null结束,而是存放null前一个的地址。
继续思考一下,我们写完了吗?那如果本身就是个空链表呢?也就是说空链表传过来的时候。第一次尾插怎么插呢?看下面这个代码。
这个代码就会有一个明显的错误,插入不进去。为什么会这样呢?
看phead=newnode这一步,这一步是把0x0012ffcc给了phead,出了作用域,phead,newnode****销毁,那么显然我们的plist的地址并没有发生任何变化,所以插入不进去。
这就是典型的形参与实参之间的区别,形参只是实参的一份临时拷贝。那么怎们样才能改变呢,那就需要传地址了。
经过以上的不断修改,最终尾插的接口函数完整代码如下:
测试结果如下:
总结一下:
3.2头插
有了尾插的思想,头插就简单了。
实质也就是修改plist,所以还是传值还是用二级指针。
完整代码如下:
测试结果如下:
3.3尾删
如果是空链表,我们可以直接使用断言。
一个节点直接释放掉plist.两个节点以上就首先需要找尾,先看下面这个代码。(**pphead就是plist)
上面这个代码找到尾后,直接把taill置空,肯定不行
free(taill)的本质是把tail指向的节点给free了,再把taill置空。出了作用域,taill销毁,那他前一个还是空。所以还需要找到taill的前一个。
以下两种解决办法都可以。
最终完整代码如下:
测试结果如下:
删除6个。
3.4头删
同理,头删与尾删大同小异,头删实现更简单。
测试结果如下:
3.5查找
查找实质还是遍历链表:
3.6在pos位置之前插入x
pos是任意一个节点,防止为空呢,我们先检查一下:
那他还有什么特殊情况呢,头插,尾插就是其中两种,其次处理pos在中间位置。
完整代码如下:
测试结果如下:在给定数字前面插它的十倍
3.7在pos位置以后插入x
要是后插就会便捷很多。因为他不可能实现头插,所以就会很简单。
如果是第一个代码:测试结果如下:
进入了死循环。
修改后完整代码如下:
测试结果如下:
3.8删除pos位置
删除部分就简单了。分情况,头删首先需要单独处理,其次尾删是不需要单独处理的,因为正常删就已经包含尾删情况了。
完整代码如下:
测试结果如下:
3.9删除pos的后一个位置
删后一个考虑的就是要找到前一个,处理好这个就简单了。其次有个坑,它删不了头。
完整代码:
4.单链表结构与顺序存储结构的优缺点
简单地对单链表结构和顺序存储结构做对比:
通过上面的对比,我们可以得出一些经验性的结论:
1.若线性表需要频繁查找,很少进行插入和删除操作时,宜采用顺序存储结构。若需要频繁插入和删除时,宜采用单链表结构。比如说游戏开发中,对于用户注册的个人信息,除了注册时插入数据外,绝大多数情况都是读取,所以应该考虑用顺序存储结构。而游戏中的玩家的武器或者装备列表,随着玩家的游戏过程中,可能会随时增加或删除,此时再用顺序存储就不太合适了,单链表结构就可以大展拳脚。当然,这只是简单的类比,现实中的软件开发,要考虑的问题会复杂得多。
2.当线性表中的元素个数变化较大或者根本不知道有多大时,最好用单链表给构。这样可以不需要考虑存储空间的大小问题。而如果事先知道线性表的大致长度,比如一年12个月,一周就是星期一至星期日共七天,这种用顺序存储结构效率会高很多。
总之,线性表的顺序存储结构和单链表结构各有其优缺点,不能简单地说哪个好,哪个不好,需要根据实际情况,来综合平衡采用哪种数据结构更能满足和达到需求和性能。
5.链表完整代码:
5.1 SList.h
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int SLTDataType;typedef struct SListNode
{SLTDataType data;struct SListNode* next;
}SLTNode;void SLTPrint(SLTNode* phead);
SLTNode* BuySListNode(SLTDataType x);//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x);
//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x);
//尾删
void SLTPopBack(SLTNode** pphead);
//头删
void SLTPopFront(SLTNode** pphead);
//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x);
//在pos位置之前插入x
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
//在pos位置以后插入x
void SLTInsertAfter(SLTNode* pos, SLTDataType x);
//删除pos位置
void SLTErase(SLTNode** pphead, SLTNode* pos);
//删除pos的后一个位置
void SLTEraseAfter(SLTNode* pos);
5.2 SList.c
#define _CRT_SECURE_NO_WARNINGS
#include"SList.h"//打印函数
void SLTPrint(SLTNode* phead)
{SLTNode* cur = phead;//while (cur != NULL)while (cur){printf("%d->", cur->data);cur = cur->next;}printf("NULL\n");
}//开辟新节点
SLTNode* BuySListNode(SLTDataType x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){perror("malloc fail");exit(-1);}newnode->data = x;newnode->next = NULL;return newnode;
}//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{SLTNode* newnode = BuySListNode(x);if (*pphead == NULL){//改变的结构体的指针*pphead = newnode;}else{SLTNode* tail = *pphead;while (tail->next != NULL){tail = tail->next;}//改变的结构体tail->next = newnode;}
}//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{SLTNode* newnode = BuySListNode(x);newnode->next = *pphead;*pphead = newnode;
}//尾删
void SLTPopBack(SLTNode** pphead)
{//空assert(*pphead);//一个节点//一个以上节点if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}else{SLTNode* tail = *pphead;while (tail->next->next){tail = tail->next;}free(tail->next);tail->next = NULL;/*SLTNode* tailprev = NULL;SLTNode* tail = *pphead;while (tail->next){tailprev = tail;tail = tail->next;}free(tail);tail = NULL;tailprev->next = NULL;*/}
}//头删
void SLTPopFront(SLTNode** pphead)
{//空assert(*pphead);//非空SLTNode* newnode = (*pphead)->next;free(*pphead);*pphead = newnode;
}//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{SLTNode* cur = phead;while (cur){if (cur->data == x){return cur;}cur = cur->next;}return NULL;}//在pos位置之前插入x
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pphead);assert(pos);if (pos == *pphead){SLTPushFront(pphead, x);}else{SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}SLTNode* newnode = BuySListNode(x);prev->next = newnode;newnode->next = pos;}
}//在pos位置以后插入x
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{assert(pos);SLTNode* newnode = BuySListNode(x);/*pos->next = newnode;*/newnode->next = pos->next;pos->next = newnode;
}//删除pos位置
void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead);assert(pos);if (pos == *pphead){SLTPopFront(pphead);}else{SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}prev->next = pos->next;free(pos);//pos = NULL;}
}//删除pos的后一个位置
void SLTEraseAfter(SLTNode* pos)
{assert(pos);//检查Pos是否为尾节点assert(pos->next);SLTNode* posNext = pos->next;pos->next = posNext = posNext->next;free(posNext);posNext = NULL;
}
5.3 Test.c
#define _CRT_SECURE_NO_WARNINGS
#include"SList.h"//交互链表测试
void TestSList1()
{int n;printf("请输入链表的长度:\n");scanf("%d", &n);printf("请依次输入每个节点的值:\n");SLTNode* plist = NULL;for (size_t i = 0; i < n; i++){int val;scanf("%d", &val);SLTNode* newnode = BuySListNode(val);//头插newnode->next = plist;plist = newnode;}SLTPrint(plist);}//测试尾插头插
void TestSList2()
{SLTNode* plist = NULL;SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPushBack(&plist, 5);SLTPrint(plist);SLTPushFront(&plist, 10);SLTPushFront(&plist, 20);SLTPushFront(&plist, 30);SLTPushFront(&plist, 40);SLTPrint(plist);}//测试尾删
void TestSList3()
{SLTNode* plist = NULL;SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPushBack(&plist, 5);SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);/*SLTPopBack(&plist);SLTPrint(plist);*/}//测试头删
void TestSList4()
{SLTNode* plist = NULL;SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPushBack(&plist, 5);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);/*SLTPopFromt(&plist);SLTPrint(plist);*/
}void TestSList5()
{SLTNode* plist = NULL;SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPushBack(&plist, 5);SLTPrint(plist);SLTNode* pos = SLTFind(plist, 40);if (pos){pos->data *= 10;}SLTPrint(plist);int x;scanf("%d", &x);pos = SLTFind(plist, x);if (pos){SLTInsert(&plist, pos, x * 10);}SLTPrint(plist);}void TestSList6()
{SLTNode* plist = NULL;SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPushBack(&plist, 5);SLTPrint(plist);int x;scanf("%d", &x);SLTNode* pos = SLTFind(plist, x);if (pos){SLTErase(&plist, pos);}SLTPrint(plist);
}void TestSList7()
{SLTNode* plist = NULL;SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPushBack(&plist, 5);SLTPrint(plist);int x;scanf("%d", &x);SLTNode* pos = SLTFind(plist, x);if (pos){SLTEraseAfter(pos);pos = NULL;}SLTPrint(plist);//SLTPopFront(&plist);//SLTPrint(plist);//SLTPopFront(&plist);//SLTPrint(plist);//SLTPopFront(&plist);//SLTPrint(plist);//SLTPopFront(&plist);//SLTPrint(plist);}int main()
{TestSList7();
}
相关文章:

初阶数据结构(三)链表
💓博主csdn个人主页:小小unicorn💓 ⏩专栏分类:c 🚚代码仓库:小小unicorn的学习足迹🚚 🌹🌹🌹关注我带你学习编程知识 前面我们讲的线性表的顺序存储结构。它…...

Python小知识 - 八大排序算法
八大排序算法 排序算法是计算机科学中非常重要的一个研究领域。排序算法可以分为内部排序和外部排序,内部排序是数据记录在计算机内部,而外部排序是数据记录在计算机外部,这里我们主要讨论内部排序。 内部排序中的算法大致可以归纳为四类&…...
安卓动态申请权限
我们在使用一些官方app时,刚下载进去之后经常会弹出各种各样的权限获取请求,今天简单学习了下,希望不会误人子弟哈哈哈哈。 一、将需要用到的权限添加到Manifest清单里 <uses-permission android:name"android.permission.WRITE_EXT…...

关于亚马逊云科技云技能孵化营学习心得
1、活动介绍 本活动主要是面向想要全面了解亚马逊云科技 (Amazon Web Services) 云的个人,而不受特定技术角色的限制。内容包括亚马逊云科技云概念、亚马逊云科技服务、安全性、架构、定价和支持等等,此外还可以参加亚马逊的认证考试。 2、学习过程 该…...
计算机安全学习笔记(III):强制访问控制 - MAC
基本概念 强制访问控制是一种高级访问控制机制,旨在通过强制执行事先定义的安全策略,实现资源和信息的严格保护。与自主访问控制(Discretionary Access Control,DAC)不同,MAC 的控制权不由用户自身决定&am…...
java判断ip是否为指定网段
具体网络知识原理请看这个博文 /**** param address servletRequest.getRemoteAddr();* param host servletRequest.getRemoteHost();* return* Description 检验IP是否符合安全限定*/private boolean ipIsInNet(String address, String host){Set<String> iPset allow…...

如何通过人工智能和自动化提高供应链弹性?
全球供应链中的数字化转型已经引起了广泛关注,尽管在过去的十年中,这一话题被广泛讨论,但许多公司仍然对如何实现这一不明确的目标感到困惑。人们普遍认识到这种转变的重要性,而新冠疫情及其带来的巨大影响也为行业向数字化转型方…...

【Apollo学习笔记】——规划模块TASK之PATH_REUSE_DECIDER
文章目录 前言PATH_REUSE_DECIDER功能简介PATH_REUSE_DECIDER相关配置PATH_REUSE_DECIDER总体流程PATH_REUSE_DECIDER相关子函数IsCollisionFreeTrimHistoryPathIsIgnoredBlockingObstacle和GetBlockingObstacleS Else参考 前言 在Apollo星火计划学习笔记——Apollo路径规划算…...

框架分析(6)-Ruby on Rails
框架分析(6)-Ruby on Rails 专栏介绍Ruby on Rails核心概念以及组件讲解MVC架构模式约定优于配置强大的ORM支持自动化测试丰富的插件生态系统RESTful路由安全性总结 优缺点优点快速开发简单易学MVC架构强大的ORM支持大量的插件和Gem支持 缺点性能问题学习…...

LLMs NLP模型评估Model evaluation ROUGE and BLEU SCORE
在整个课程中,你看到过类似模型在这个任务上表现良好,或者这个微调模型在性能上相对于基础模型有显著提升等陈述。 这些陈述是什么意思?如何形式化你的微调模型在你起初的预训练模型上的性能改进?让我们探讨一些由大型语言模型开…...

BlazorServer中C#与JavaScript的相互调用
BlazorServer中C#与JavaScript的相互调用 前言: 虽然BlazorServer中推荐使用C#在razor页面中的替代JavaScript来完成逻辑的编写,但当需要使用第三方的javascript文件/组件里的内容时,则难免要在C#中调用其方法或对象。反之当你的(用到第…...
深入理解 MD5 消息摘要算法和在密码存储中的应用及安全隐患
MD5 算法相信很多开发人员都听说过, 一个最常见的使用到它的地方就是密码的存储. 当然, 很多人会说, 这个算法已经不太安全了, 确实如果你想更安全的保存密码, 则应该考虑其它更安全的算法, 不过这不属于此次讨论的主题. 什么是 MD5 MD5 是一种算法, MD5 中的 MD 代表 Message…...

python网络爬虫指南二:多线程网络爬虫、动态内容爬取(待续)
文章目录 一、多线程网络爬虫1.1 线程的基础内容、GIL1.2 创建线程的两种方式1.3 threading.Thread类1.4 线程常用方法和锁机制1.5 生产者-消费者模式1.5.1 生产者-消费者模式简介1.5.2 Condition 类协调线程 1.6 线程中的安全队列1.6 多线程爬取王者荣耀壁纸1.6.1 网页分析1.6…...
华为AirEgine9700S AC配置示例
Vlan97为管理Vlan <AirEgine9700S>dis cu Software Version V200R021C00SPC100 #sysname AirEgine9700S #http timeout 60http secure-server ssl-policy default_policyhttp secure-server server-source -i allhttp server enable #set np rss hash-mode 5-tuple # md…...
VUE3基础
一、vue-router v4.x 介绍 | Vue Router 1、安装 yarn add vue-routernext next代表最新的版本 2、路由配置 在src目录下,新建router/index.ts,具体配置如下 import {RouteRecordRaw,createRouter,createWebHashHistory} from vue-router const r…...

Qt应用开发(基础篇)——日历 QCalendarWidget
一、前言 QCalendarWidget类继承于QWidget,是Qt设计用来让用户更直观的选择日期的窗口部件。 时间微调输入框 QCalendarWidget根据年份和月份初始化,程序员也通过提供公共函数去改变他们,默认日期为当前的系统时间,用户通过鼠标和…...

Python学习笔记:正则表达式、逻辑运算符、lamda、二叉树遍历规则、类的判断
1.正则表达式如何写? 序号实例说明1.匹配任何字符(除换行符以外)2\d等效于[0-9],匹配数字3\D等效于[^0-9],匹配非数字4\s等效于[\t\r\n\f],匹配空格字符5\S等效于[^\t\r\n\f],匹配非空格字符6\w等效于[A-Za-z0-9]&…...

【滑动窗口】leetcode1004:最大连续1的个数
一.题目描述 最大连续1的个数 这道题要我们找最大连续1的个数,看到“连续”二字,我们要想到滑动窗口的方法。滑动窗口的研究对象是一个连续的区间,这个区间需要满足某个条件。那么本题要找的是怎样的区间呢?是一个通过翻转0后得到…...

力扣:73. 矩阵置零(Python3)
题目: 给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 来源:力扣(LeetCode) 链接:力扣(LeetCode)官网 - 全球极客挚…...
VB|基础语法 变量定义 函数定义 循环语句 IF判断语句等
文章目录 变量定义函数定义控制台输入输出switch case语句IF语句FOR循环语句不等于逻辑运算符 变量定义 int Dim 变量名 As Int32 0 string Dim 变量名 As String "" bool Dim 变量名 As Boolean False 枚举 Dim 变量名 As 枚举名 数组 Dim array(256) As String…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
在汽车智能化的汹涌浪潮中,车辆不再仅仅是传统的交通工具,而是逐步演变为高度智能的移动终端。这一转变的核心支撑,来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒(T-Box)方案:NXP S32K146 与…...

力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...

论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving
地址:LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂,正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
二维FDTD算法仿真
二维FDTD算法仿真,并带完全匹配层,输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...