当前位置: 首页 > news >正文

初阶数据结构(三)链表

💓博主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线性表链式存储结构定义

在解释这个思路之前,我们先来谈另一个话题。前几年,有一本书风靡了全世界,它叫《达·芬奇密码》,成为世界上最畅销的小说之一,书的内容集合了侦探、惊使和阴谋论等多种风格,很好看。这本书和绝大部分负小说一样,都是同一种处理办法。那就是,作者不会让你事先知道整个过程的全部,而是在一步一步地到这某个环节,才根据现场的信息,获得或推断出下一步是什么,也就是说,每一步除了对你侦破的信息进一步确认外(之前信息也不一定都是对的,有时是证明某个信息不正确),还有就是对下一步如何操作或行动的指引。

不过,这个例子也不完全与线性表相符合,因为案件侦破的线案可能是错综复杂的,有点像我们之后要讲到的树和图的数据结构。今天,我们要讲的是单线索,无分支的情况。即线性表的链式存储结构。

线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的。这就意 味着,这些数据元素可以存在内存未被占用的任意位置
(如下图所示)。
图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();
}

相关文章:

初阶数据结构(三)链表

&#x1f493;博主csdn个人主页&#xff1a;小小unicorn&#x1f493; ⏩专栏分类&#xff1a;c &#x1f69a;代码仓库&#xff1a;小小unicorn的学习足迹&#x1f69a; &#x1f339;&#x1f339;&#x1f339;关注我带你学习编程知识 前面我们讲的线性表的顺序存储结构。它…...

Python小知识 - 八大排序算法

八大排序算法 排序算法是计算机科学中非常重要的一个研究领域。排序算法可以分为内部排序和外部排序&#xff0c;内部排序是数据记录在计算机内部&#xff0c;而外部排序是数据记录在计算机外部&#xff0c;这里我们主要讨论内部排序。 内部排序中的算法大致可以归纳为四类&…...

安卓动态申请权限

我们在使用一些官方app时&#xff0c;刚下载进去之后经常会弹出各种各样的权限获取请求&#xff0c;今天简单学习了下&#xff0c;希望不会误人子弟哈哈哈哈。 一、将需要用到的权限添加到Manifest清单里 <uses-permission android:name"android.permission.WRITE_EXT…...

关于亚马逊云科技云技能孵化营学习心得

1、活动介绍 本活动主要是面向想要全面了解亚马逊云科技 (Amazon Web Services) 云的个人&#xff0c;而不受特定技术角色的限制。内容包括亚马逊云科技云概念、亚马逊云科技服务、安全性、架构、定价和支持等等&#xff0c;此外还可以参加亚马逊的认证考试。 2、学习过程 该…...

计算机安全学习笔记(III):强制访问控制 - MAC

基本概念 强制访问控制是一种高级访问控制机制&#xff0c;旨在通过强制执行事先定义的安全策略&#xff0c;实现资源和信息的严格保护。与自主访问控制&#xff08;Discretionary Access Control&#xff0c;DAC&#xff09;不同&#xff0c;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…...

如何通过人工智能和自动化提高供应链弹性?

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

【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

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

LLMs NLP模型评估Model evaluation ROUGE and BLEU SCORE

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

BlazorServer中C#与JavaScript的相互调用

BlazorServer中C#与JavaScript的相互调用 前言&#xff1a; ​ 虽然BlazorServer中推荐使用C#在razor页面中的替代JavaScript来完成逻辑的编写&#xff0c;但当需要使用第三方的javascript文件/组件里的内容时&#xff0c;则难免要在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目录下&#xff0c;新建router/index.ts&#xff0c;具体配置如下 import {RouteRecordRaw,createRouter,createWebHashHistory} from vue-router const r…...

Qt应用开发(基础篇)——日历 QCalendarWidget

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

Python学习笔记:正则表达式、逻辑运算符、lamda、二叉树遍历规则、类的判断

1.正则表达式如何写&#xff1f; 序号实例说明1.匹配任何字符(除换行符以外)2\d等效于[0-9]&#xff0c;匹配数字3\D等效于[^0-9]&#xff0c;匹配非数字4\s等效于[\t\r\n\f]&#xff0c;匹配空格字符5\S等效于[^\t\r\n\f]&#xff0c;匹配非空格字符6\w等效于[A-Za-z0-9]&…...

【滑动窗口】leetcode1004:最大连续1的个数

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

力扣:73. 矩阵置零(Python3)

题目&#xff1a; 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚…...

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…...

Github 博客搭建

Github 博客搭建 准备工作 准备一个 github 账号&#xff1b;建立 github 仓库&#xff0c;仓库名为 username.github.io&#xff0c;同时设置仓库为 public&#xff1b;clone 仓库&#xff0c;写入一个 index.html 文件&#xff0c;推送到仓库&#xff08;许多网上的教程会有…...

模型预测笔记(三):通过交叉验证网格搜索机器学习的最优参数

文章目录 网络搜索介绍步骤参数代码实现 网络搜索 介绍 网格搜索&#xff08;Grid Search&#xff09;是一种超参数优化方法&#xff0c;用于选择最佳的模型超参数组合。在机器学习中&#xff0c;超参数是在训练模型之前设置的参数&#xff0c;无法通过模型学习得到。网格搜索…...

创建型模式-建造者模式

使用多个简单的对象一步一步构建成一个复杂的对象 主要解决&#xff1a;主要解决在软件系统中&#xff0c;有时候面临着"一个复杂对象"的创建工作&#xff0c;其通常由各个部分的子对象用一定的算法构成&#xff1b;由于需求的变化&#xff0c;这个复杂对象的各个部…...

Rust常用加密算法

哈希运算(以Sha256为例) main.rs: use crypto::digest::Digest;use crypto::sha2::Sha256;fn main() { let input "dashen"; let mut sha Sha256::new(); sha.input_str(input); println!("{}", sha.result_str());} Cargo.toml: [package]n…...

[管理与领导-55]:IT基层管理者 - 扩展技能 - 1 - 时间管理 -2- 自律与自身作则,管理者管好自己时间的五步法

前言&#xff1a; 管理好自己的时间&#xff0c;不仅仅是理念&#xff0c;也是方法和流程。 步骤1&#xff1a;理清各种待办事项 当提到工作事项时&#xff0c;这通常指的是要完成或处理的工作任务或事务。这些事项可以包括以下内容&#xff1a; 任务分配&#xff1a;根据工作…...

电子商务员考试题库及答案(中级)--判断题

电子商务员题库 一、判断题 1&#xff0e;EDI就是按照商定的协议&#xff0c;将商业文件分类&#xff0c;并通过计算机网络&#xff0c;在贸易伙伴的计算机网络系统之间进行数据交换和自动处理。〔〕 2.相互通信的EDI的用户必须使用相同类型的计算机。〔 〕 3.EDI采用共同…...

(WAF)Web应用程序防火墙介绍

&#xff08;WAF&#xff09;Web应用程序防火墙介绍 1. WAF概述 ​ Web应用程序防火墙&#xff08;WAF&#xff09;是一种关键的网络安全解决方案&#xff0c;用于保护Web应用程序免受各种网络攻击和威胁。随着互联网的不断发展&#xff0c;Web应用程序变得越来越复杂&#x…...

SpringMVC拦截器常见应用场景

在Spring MVC中&#xff0c;拦截器是通过实现HandlerInterceptor接口来定义的。该接口包含了三个方法&#xff1a; preHandle&#xff1a;在请求到达处理器之前执行&#xff0c;可以进行一些预处理操作。如果返回false&#xff0c;则请求将被拦截&#xff0c;不再继续执行后续的…...

爬虫:绕过5秒盾Cloudflare和DDoS-GUARD

本文章仅供技术研究参考&#xff0c;勿做它用&#xff01; 5秒盾的特点 <title>Just a moment...</title> 返回的页面中不是目标数据&#xff0c;而是包含上面的代码&#xff1a;Just a moment... 或者第一次打开网页的时候&#xff1a; 这几个特征就是被Cloud…...

数据仓库环境下的超市进销存系统结构

传统的进销存系统建立的以单一数据库为中心的数据组织模式&#xff0c;已经无 法满足决策分析对数据库系统的要求&#xff0c;而数据仓库技术的出现和发展&#xff0c;为上述问题 的解决提供了强有力的工具和手段。数据仓库是一种对多个分布式的、异构的数据 库提供统一查询…...

重庆博达建设集团股份有限公司网站/磁力棒

cmd中输入 netstat -ano 回车.可以查看本机开放的全部端口. 协议&#xff1a;分为TCP和UDP本地地址&#xff08;Local Address&#xff09;&#xff1a;代表本机IP地址和打开的端口号外部地址&#xff08;Foreign Address&#xff09;&#xff1a;远程计算机IP地址和端口号状态…...

防邪办网站建设方案文档/windows优化大师好不好

转自&#xff1a;http://www.dearda.com/index.php/archives/380 之前我发布的《SharePoint备份与还原》一文初步探讨了使用SharePoint管理中心备份与还原站点的方法。但是在我实际部署的过程中发现用管理中心做还原并不可靠&#xff01;&#xff08;PS&#xff1a;微软的备份与…...

轴承外贸网站怎么做/打开百度网站

在login屏幕一直不能登录进去&#xff0c;输入admin密码admin后还会是停止在登录屏幕&#xff0c;要求输入用户和密码.百思不得其解&#xff0c;后面在cacti的官方论坛上找答案&#xff0c;发现有人有同样的问题&#xff0c;他有发apache的日志。突然一想&#xff0c;我也可以看…...

小企业网站建设哪里做得好/100个成功营销案例

http简介 HTTP协议是Hyper Text Transfer Protocol&#xff08;超文本传输协议&#xff09;的缩写,是用于从万维网&#xff08;WWW:World Wide Web &#xff09;服务器传输超文本到本地浏览器的传送协议。。HTTP是一个基于TCP/IP通信协议来传递数据&#xff08;HTML 文件, 图片…...

网站建设 图片/如何制作链接推广

题目&#xff1a;部分遮挡区域的超像素正则化精确光场深度估计 Abstract 深度估计是光场摄影应用的基本问题。近年来的方法是&#xff1a; 制定成本项以进行更稳健的匹配分析嵌入在极线平面图像中的场景结构的几何形状 但是&#xff0c;当前最先进的方法在处理复杂的遮挡结构…...

专门做调查问卷的网站/seo销售是做什么的

mysql workbench 导出建表结构 导出数据&#xff0c;直接上图&#xff0c;gif简示图&#xff1b;...