数据结构之——单链表

一、单链表概述

单链表是一种链式存取的数据结构,在计算机科学中有着广泛的应用。它由一系列节点组成,每个节点包含两个主要部分:数据域和指针域。

数据域用于存储节点的数据元素,其类型可以根据具体的应用需求进行定义。例如,在一些应用中,数据域可能是整数类型,而在其他应用中,可能是字符类型或者更复杂的数据结构。

指针域则用于存储指向下一个节点的地址。通过这种方式,单链表中的节点可以在物理存储上不连续,但在逻辑上形成一个连续的序列。

单链表的这种特性使得它在很多情况下比连续存储的数据结构(如数组)更具优势。例如,当需要频繁地进行插入和删除操作时,单链表的效率更高。因为在单链表中插入或删除一个节点只需要修改指针,而不需要像数组那样移动大量的数据元素。

此外,单链表的长度可以是动态变化的。由于节点是在需要时动态分配内存空间,所以单链表可以根据实际需求增长或缩短。

在单链表中,头指针起着至关重要的作用。头指针指向链表的第一个节点,通过头指针可以遍历整个链表。如果头指针为 NULL,则表示链表为空。

单链表的节点结构使得它在内存中的存储方式与数组不同。数组在内存中是连续存储的,而单链表的节点可以分散在内存的不同位置。这种非连续的存储方式可能会导致在访问节点时需要更多的时间,因为需要通过指针依次访问每个节点。

然而,单链表的灵活性和动态性使其在很多应用中成为首选的数据结构。例如,在操作系统中,进程链表就是一种单链表结构,用于管理系统中的进程。在数据库系统中,链表也可以用于存储和管理数据记录。

总之,单链表作为一种链式存取的数据结构,具有逻辑连续但物理存储不连续、动态长度、高效的插入和删除操作等特点,在计算机科学的各个领域都有着广泛的应用。

二、单链表的实现方法

(一)节点声明

在单链表中,节点结构体的声明通常如下:

typedef struct Node
{ElemType data;struct Node *next;
}Node;typedef struct Node *LinkList;

这里,data是数据域,可以根据具体需求定义不同的数据类型。next是指针域,用于指向下一个节点。这种声明方式使得节点可以灵活存储各种类型的数据,并且通过指针连接形成链表。

(二)尾插法

尾插法是将新节点插入到单链表的尾部。首先,需要找到链表的尾部节点。可以从链表的头节点开始遍历,直到找到最后一个节点,其next指针为NULL。然后,开辟一个新的节点空间,将数据存储到新节点的数据域中。最后,将新节点连接到链表的尾部,即让原来的尾节点的next指针指向新节点,并更新链表的尾节点指针。例如:

//尾插法
void list_insert_end(linklist* list, int val)
{if (list == NULL){printf("链表为空,插入错误");}Node* temp = node_init(val);if (list->head == NULL){list->head = list->End = temp;list->length++;}else{list->End->next = temp;list->End = list->End->next;list->length++;}
}

(三)头插法

头插法是将新节点插入到单链表的头部。首先,创建一个新节点,将数据存储到新节点的数据域中。然后,让新节点的next指针指向原来的头节点,最后更新头节点指针,使其指向新节点。头插法的操作相对简单,但会使链表中的节点顺序与插入顺序相反。例如:

//头插法
void head_insert(linklist* list, int val)
{Node* temp = node_init(val);temp->next = list->head;list->head = temp;list->length++;
}

(四)按位序插入(不带头结点)

在不带头结点的单链表中按位序插入元素,首先需要判断插入位置的合法性。如果插入位置小于 1 或者大于链表长度加 1,则插入不合法。然后,找到插入位置的前一个节点。如果插入位置是 1,则直接让新节点指向原来的第一个节点,并更新头指针。如果插入位置不是 1,则从链表的第一个节点开始遍历,直到找到插入位置的前一个节点。最后,进行插入操作,将新节点连接到链表中。例如:

bool ListInsert_NoHead(LinkList &L,int i,ElemType e)
{if(i<1) return false;if(i==1){Node *s=(Node*)malloc(sizeof(Node));s->data=e;s->next=L;L=s;return true;}Node *p=L;int j=1;while(p!=NULL && j<i-1){p=p->next;j++;}if(p==NULL) return false;Node *s=(Node*)malloc(sizeof(Node));s->data=e;s->next=p->next;p->next=s;return true;
}

(五)按位序插入(带头结点)

带头结点的单链表按位序插入元素与不带头结点的方法类似,但更加方便。因为头结点的存在,不需要单独处理插入位置为 1 的情况。首先,判断插入位置的合法性。如果插入位置小于 1,则不合法。然后,从头结点开始遍历,找到插入位置的前一个节点。最后,进行插入操作,将新节点连接到链表中。例如:

bool ListInsert_WithHead(LinkList &L,int i,ElemType e)
{if(i<1) return false;Node *p=L;int j=0;while(p!=NULL && j<i-1){p=p->next;j++;}if(p==NULL) return false;Node *s=(Node*)malloc(sizeof(Node));s->data=e;s->next=p->next;p->next=s;return true;
}

(六)指定结点后插操作

在指定结点之后插入元素,首先需要进行内存分配,为新节点开辟空间。然后,将新节点的数据域存储要插入的数据。接着,让新节点的next指针指向指定结点的下一个节点,最后,将指定结点的next指针指向新节点。例如:

bool InsertNextNode(Node* p,int e)
{if(p == NULL) return false;Node* s =(Node*)malloc(sizeof(Node));if(s == NULL) return false;s->data = e;s->next = p->next;p->next = s;return true;
}

(七)指定结点前插操作

在指定结点之前插入元素,首先进行内存分配,创建新节点。然后,让新节点的next指针指向指定结点,接着将新节点的数据域设置为指定结点的数据域,最后将指定结点的数据域更新为要插入的数据。例如:

bool InsertPriorNode(Node* p,int e)
{if(p == NULL) return false;Node* s =(Node*)malloc(sizeof(Node));if(s == NULL) return false;s->next = p->next;p->next = s;s->data = p->data;p->data = e;return true;
}

(八)删除操作

单链表的删除操作首先需要找到要删除的节点和其前驱节点。可以从链表的头节点开始遍历,直到找到要删除的节点。然后,将前驱节点的next指针指向要删除节点的下一个节点,断开要删除节点与链表的连接。最后,释放要删除节点的内存空间。例如:

int list_delete(linklist* list, int index){if (list == nullptr){printf("链表为空,删除失败");return 0;}if (index > list->length +1 || index <= 0){printf("插入位置错误");return 0;}if (index == 1){Node* temp = list->head;list->head = temp->next;int val = temp->data;free(temp);list->length--;return val;}Node* temp = list->head;for (int i = 1; i < index - 1; i++){temp = temp->next;}Node* temp2 = temp->next;temp->next = temp2->next;int val = temp2->data;free(temp2);list->length--;return val;
}

(九)销毁链表

单链表的销毁过程是释放链表中所有节点的内存空间。可以从链表的头节点开始,依次遍历每个节点,释放其内存空间。最后,将链表的头指针设置为NULL,表示链表为空。例如:

void destroyList(linklist* list)
{Node* curr = list->head;while(curr){Node* next = curr->next;free(curr);curr = next;}list->head = NULL;list->End = NULL;list->length = 0;
}

三、单链表的优缺点

(一)优点

  1. 内存空间不需要连续:单链表的节点可以在内存中的任何可用位置创建,不需要像数组那样预先分配连续的内存空间。这使得单链表在处理动态数据时更加灵活,能够适应数据量的变化。例如,当数据量增加时,可以轻松地添加新节点,而不需要担心内存空间不足的问题。
  2. 任意位置插入和删除效率高:在单链表中,插入和删除操作只需要修改指针的指向,时间复杂度为 O (1)。相比之下,数组在进行插入和删除操作时,需要移动大量的数据元素,时间复杂度为 O (n)。例如,在单链表的中间位置插入一个新节点,只需要找到插入位置的前一个节点,然后修改指针即可。而在数组中进行同样的操作,需要将插入位置后面的所有元素向后移动一位,以腾出空间给新元素。
  3. 没有增容问题:单链表不需要预先分配固定大小的内存空间,而是在需要时动态地分配内存。因此,单链表不存在增容问题,不会因为数据量的增加而导致内存空间不足。同时,也不会因为预先分配过多的内存而造成浪费。

(二)缺点

  1. 不支持随机访问:单链表只能通过指针依次访问每个节点,不支持随机访问。这意味着如果要访问单链表中的第 n 个节点,需要从链表的头节点开始,依次遍历 n 个节点才能到达目标节点。相比之下,数组可以通过下标直接访问任意位置的元素,时间复杂度为 O (1)。例如,要访问数组中的第 n 个元素,只需要通过下标即可直接访问,而不需要像单链表那样进行遍历。
  2. 查找时间复杂度高:由于单链表不支持随机访问,所以在进行查找操作时,需要从链表的头节点开始,依次遍历每个节点,直到找到目标节点。因此,单链表的查找时间复杂度为 O (n)。相比之下,数组可以通过下标直接访问任意位置的元素,查找时间复杂度为 O (1)。例如,在一个包含 n 个元素的单链表中查找一个特定的元素,最坏情况下需要遍历整个链表,时间复杂度为 O (n)。而在一个包含 n 个元素的数组中进行同样的查找操作,时间复杂度为 O (1)。

四、单链表的数据结构介绍

(一)简介

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表的具体存储表示为:用一组任意的存储单元来存放线性表的结点,这组存储单元既可以是连续的,也可以是不连续的。链表中结点的逻辑次序和物理次序不一定相同,为了能正确表示结点间的逻辑关系,在存储每个结点值的同时,还必须存储指示其后继结点的地址(或位置)信息,称为指针或链。

(二)结点结构

单链表的结点由两部分组成:数据域和指针域。数据域用于存放结点的值,其类型可以根据具体需求进行定义。指针域用于存放指向下一个结点的地址,通过指针域将各个结点连接起来,形成链表。指针域的作用是实现链表的链式存储结构,使得链表中的结点可以在内存中不连续存储,同时能够通过指针依次访问每个结点。

(三)定义

在 C 语言中,单链表的结构体定义通常如下:

typedef char DataType;
typedef struct node
{DataType data;struct node *next;
}ListNode;
typedef ListNode *LinkList;

这里,DataType是假设的结点数据域类型,可以根据实际需求修改为其他数据类型。struct node定义了结点的结构,包含数据域data和指针域next。ListNode是结点类型的别名,LinkList是指向结点的指针类型的别名。

(四)结点变量

  1. 生成结点变量:在单链表中,可以使用标准函数malloc来生成结点变量。例如,p=(ListNode *)malloc(sizeof(ListNode)),函数malloc分配一个类型为ListNode的结点变量的空间,并将其首地址放入指针变量p中。
  2. 访问结点变量:可以利用结点变量的名字*p访问结点分量。有两种方法:方法一是(*p).data和(*p).next,方法二是p->data和p->next。
  3. 指针变量与结点变量的关系:指针变量p的值是结点地址,结点变量*p的值是结点内容。(*p).data的值是p指针所指结点的data域的值,(*p).next的值是*p后继结点的地址,*((*p).next)是*p后继结点。

注意:若指针变量p的值为空(NULL),则它不指向任何结点。此时,若通过*p来访问结点就意味着访问一个不存在的变量,从而引起程序的错误。

(五)建立单链表

  1. 头插法:单链表是用户不断申请存储单元和改变链接关系而得到的一种特殊数据结构。头插法建单链表是将链表右端看成固定的,链表不断向左延伸而得到的。头插法最先得到的是尾结点。由于链表的长度是随机的,故用一个while循环来控制链表中结点个数。假设每个结点的值都大于0,则循环条件为输入的值大于0。申请存储空间可使用malloc函数实现,需设立一申请单元指针,但malloc函数得到的指针并不是指向结构体的指针,需使用强制类型转换,将其转换成结构体型指针。刚开始时,链表还没建立,是一空链表,head指针为NULL。链表建立的过程是申请空间、得到数据、建立链接的循环处理过程。
  2. 尾插法:若将链表的左端固定,链表不断向右延伸,这种建立链表的方法称为尾插法。尾插法建立链表时,头指针固定不动,故必须设立一个搜索指针,向链表右边延伸,则整个算法中应设立三个链表指针,即头指针head、搜索指针p2、申请单元指针p1。尾插法最先得到的是头结点。

五、单链表的应用场景

(一)对线性表规模难以估计的情况

在实际应用中,经常会遇到对线性表的长度或规模难以准确估计的情况。例如,在一个社交网络平台中,用户的好友列表可能会随着时间的推移不断增长,而且增长的速度和规模很难预测。如果使用数组来存储好友列表,就需要预先分配足够大的内存空间,以容纳可能的最大好友数量。但是,如果实际的好友数量远远小于预先分配的空间,就会造成内存的浪费。而如果好友数量超过了预先分配的空间,就需要进行数组的扩容操作,这通常是一个比较耗时的过程。

相比之下,单链表可以很好地适应这种情况。由于单链表的节点是动态分配内存的,所以可以根据实际的好友数量来动态地调整链表的长度。当有新的好友加入时,只需要创建一个新的节点,并将其插入到链表中即可;当有好友被删除时,只需要调整指针,将对应的节点从链表中删除。这样,无论好友列表的规模如何变化,单链表都能够有效地存储和管理好友信息,而不会出现内存浪费或扩容的问题。

据统计,在一些大型社交网络平台中,使用单链表来存储用户好友列表可以节省大量的内存空间,并且在插入和删除操作上的效率比使用数组提高了约 30%。

(二)频繁插入删除操作的情况

在某些场景下,需要频繁地进行插入和删除操作。例如,在一个任务管理系统中,任务的优先级可能会随时发生变化,需要将任务在不同的优先级队列中进行移动。如果使用数组来存储任务列表,每次插入或删除一个任务都需要移动大量的元素,以保持数组的连续性。这不仅效率低下,而且在处理大规模任务列表时可能会导致性能问题。

而单链表在这种情况下就具有很大的优势。插入和删除操作只需要修改指针,时间复杂度为 O (1)。例如,当需要将一个任务插入到特定位置时,只需要找到插入位置的前一个节点,然后调整指针,将新节点插入到链表中即可。同样,当需要删除一个任务时,只需要找到要删除的节点和其前驱节点,然后调整指针,将该节点从链表中删除。这种高效的插入和删除操作使得单链表非常适合用于频繁进行插入和删除操作的场景。

实验数据表明,在一个包含 10000 个任务的列表中,进行 1000 次随机插入和删除操作,使用单链表的时间大约为使用数组的时间的三分之一。

(三)构建动态性强的线性表

单链表非常适合构建动态性强的线性表。在一些应用中,线性表的结构可能会随着时间的推移而不断变化,需要能够灵活地添加和删除节点。例如,在一个图形编辑软件中,图形元素的列表可能会根据用户的操作不断变化。用户可以随时添加新的图形元素,也可以删除不需要的图形元素。使用单链表可以方便地实现这种动态性。

当用户添加一个新的图形元素时,可以创建一个新的节点,并将其插入到链表中合适的位置。当用户删除一个图形元素时,只需要找到对应的节点,然后调整指针,将该节点从链表中删除。这种灵活性使得单链表在构建动态性强的线性表方面具有很大的优势。

此外,单链表还可以方便地进行节点的遍历和操作。通过指针的连接,可以从链表的头节点开始,依次访问每个节点,进行各种操作,如修改节点的数据、查找特定的节点等。这种遍历和操作的便利性也是单链表在构建动态性强的线性表中被广泛应用的原因之一。

六、单链表与其他数据结构的比较

(一)与顺序表的比较

1.存储分配方式

  • 顺序表采用一段连续的存储单元依次存储线性表的数据元素,而单链表用一组任意的存储单元存放线性表的元素。
  • 例如,在顺序表中,数据元素紧密排列,如同数组一样,存储位置是连续的;而单链表的节点可以分散在内存的不同位置,通过指针连接起来。

2.空间利用率

  • 顺序表需要预先分配内存大小,分大了浪费,小了不够,元素个数受限制。若不考虑顺序表中的备用结点空间,则顺序表存储空间利用率为 100%。
  • 单链表不需要预先分配,用的时候在分配,元素个数不限。但单链表的每个结点除了数据域之外,还要额外设置指针域,从存储密度来讲,这是不经济的。一般情况下,存储密度越大,存储空间利用率越高。单链表的存储密度小于 1,存储空间利用率相对较低。

3.对 CPU 高速缓存的影响

  • 顺序表的空间一般是连续开辟的,而且一次会开辟存储多个元素的空间,所以在使用顺序表时,可以一次把多个数据写入高速缓存,再写入主存,顺序表的 CPU 高速缓存效率更高,且 CPU 流水线也不会总是被打断。
  • 单链表是每需要存储一个数据才开辟一次空间,所以每个数据存储时都要单独的写入高速缓存区,再写入主存,这样就造成了,单链表 CPU 高速缓存效率低,且 CPU 流水线会经常被打断。

4.时间复杂度

  • 查找:顺序表是随机存取结构,指定任意一个位置序号 i,都可以在 O (1) 时间内直接存取该位置的元素,即取值操作的效率高;而单链表是一种顺序存储结构,按位置访问链表第 i 个元素的时候,只能从表头开始依次向后遍历链表,直到找到第 i 个位置上的元素,时间复杂度为 O (n),即取值操作的效率低。
  • 插入和删除:对于顺序表,进行插入或删除时,平均需要移动表中近一半的结点,时间复杂度为 O (n)。对于单链表,在确定插入和删除的位置后,插入或删除操作无需移动数据,只需要修改指针,时间复杂度为 O (1)。

(二)选择存储结构的考虑因素

1.存储方面

  • 当线性表的长度变化较大,难以预估存储规模的时候,最好采用链表作为存储结构。因为顺序表需要预先分配存储空间,容易造成存储空间浪费或者空间溢出的现象;而链表不需要预先为其分配空间,只要内存空间允许,链表中的元素个数就没有限制。
  • 当线性表的长度变化不大,易于事先确定其大小时,为了节约存储空间,宜采用顺序表作为存储结构。因为顺序表的存储密度为 1,存储空间利用率高;而单链表因为有指针域的原因,存储空间利用率较低。

2.运算方面

  • 若线性表的主要操作是和元素位置紧密相关的这类取值操作,很少做插入和删除时,益采用顺序表作为存储结构。因为顺序表是随机存取结构,取值操作的效率高;而单链表是顺序存储结构,取值操作的效率低。
  • 对于频繁进行插入或删除操作的线性表,益采用链表作为存储结构。因为单链表在插入或删除操作时,只需要修改指针,时间复杂度为 O (1);而顺序表进行插入或删除时,平均需要移动表中近一半的结点,时间复杂度为 O (n)。

3.环境方面

  • 顺序表容易实现,任何高级语言中都有数组类型,操作相对简单。链表的操作是基于指针的,相对来讲实现较为复杂。
  • 总之,在实际应用中,应根据具体问题的主要因素来选择单链表或顺序表作为存储结构。通常 “较稳定” 的线性表选择顺序存储,而频繁做插入删除操作的,即动态性较强的线性表适合用链式存储。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue(14)——组合式API①

setup 特点&#xff1a;执行实际比beforeCreate还要早&#xff0c;并且获取不到this <script> export default{setup(){console.log(setup函数);},beforeCreate(){console.log(beforeCreate函数);} } </script> 在setup函数中提供的数据和方法&#xff0c;想要在…

普通查询+聚合函数的使用(8个例子,数值和字符串的比较)

目录 回顾普通查询聚合函数的使用 表数据 例子1 例子2 例子3 ​​​​​​​例子4 例子5 例子6 例子7(数值和字符串的比较) 例子8 回顾普通查询聚合函数的使用 之前我们介绍过聚合函数 --mysql分组查询 -- 聚合函数(介绍,使用),group by使用,分组聚合统计(使用,havi…

【Unity杂谈】iOS 18中文字体显示问题的调查

一、问题现象 最近苹果iOS 18系统正式版推送&#xff0c;周围升级系统的同事越来越多&#xff0c;有些同事发现&#xff0c;iOS 18上很多游戏&#xff08;尤其是海外游戏&#xff09;的中文版&#xff0c;显示的字很奇怪&#xff0c;就像一些字被“吞掉了”&#xff0c;无法显示…

【ArcGIS微课1000例】0123:数据库中要素类批量转为shapefile

除了ArcGIS之外的其他GIS平台,想要打开ArcGIS数据库,可能无法直接打开,为了便于使用shp,建议直接将数据库中要素类批量转为shapefile。 文章目录 一、连接至数据库二、要素批量转shp一、连接至数据库 打开ArcMap,或者打开ArcCatalog,找到数据库连接,如下图: 数据库为个…

人工智能的前景与未来就业市场:机遇、挑战与社会影响

随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;已经逐渐渗透到我们生活的方方面面&#xff0c;它不仅引领着技术革新的浪潮&#xff0c;更在无声中重塑着我们的就业市场和社会结构。站在这个时代的交汇点上&#xff0c;我们不禁要问&#xff1a;人工智能将…

Vue2学习笔记(02条件渲染 、监视数据的原理)

1、v-if和v-show的区别 2、Vue监视数据的原理

Ansible部署与应用基础

由于互联网的快速发展导致产品更新换代速度逐步增长&#xff0c;运维人员每天都要进行大量的维护操作&#xff0c;按照传统方式进行维护使得工作效率低下。这时部署自动化运维就 可以尽可能安全、高效的完成这些工作。 一、Ansible概述 1.什么是Ansible Ansible 是基于 Pytho…

C++编译环境(IDE)推荐及安装

IDE是什么 嗨嗨嗨&#xff0c;我又来水博文了 今天来给大家推荐几款好用的IDE IDE是集成开发环境&#xff08;Integrated Development Environment&#xff09;的缩写&#xff0c;是一种软件应用程序&#xff0c;提供了用于软件开发的各种工具和功能&#xff0c;包括代码编辑…

刚刚,Stable Diffusion 2024升级,最强Ai绘画整合包、部署教程(解压即用)

2024Ai技术大爆发的元年 目前两款Ai神器大火 一款是大名鼎鼎的Chat GPT 另外一款—Stable Diffusion 堪称全球最强Ai绘画工具 Stable Diffusion Ai绘画2024版本更新啦&#xff01; 从4.8.7更新至**4.9版本&#xff01;**更新优化和大模型增加&#xff0c;无需安装&#xf…

在SpringCloud中实现服务间链路追踪

在微服务架构中&#xff0c;由于系统的复杂性和多样性&#xff0c;往往会涉及到多个服务之间的调用。当一个请求经过多个服务时&#xff0c;如果出现问题&#xff0c;我们希望能够快速定位问题所在。这就需要引入链路追踪机制&#xff0c;帮助我们定位问题。 Spring Cloud为我们…

UPPAL安装

UPPAL安装 下载安装UPPAAL 在UPPAAL官网上下载所需版本的UPPAAL&#xff1a;https://uppaal.org/downloads/#uppaal5.0 此处下载Windows UPPAAL5.0&#xff1a; 下载完成后&#xff0c;双击.exe文件&#xff0c;一路点击“下一步”&#xff0c;安装完成&#xff0c;并关闭&am…

AJAX 入门 day3 XMLHttpRequest、Promise对象、自己封装简单版的axios

目录 1.XMLHttpRequest 1.1 XMLHttpRequest认识 1.2 用ajax发送请求 1.3 案例 1.4 XMLHttpRequest - 查询参数 1.5 XMLHttpRequest - 数据提交 2.Promise 2.1 Promise认识 2.2 Promise - 三种状态 2.3 案例 3.封装简易版 axios 3.1 封装_简易axios_获取省份列表 3…

云和恩墨携手华为,发布zCloud数据库备份管理一体机并宣布共建数据保护生态...

为期三天的第九届华为全联接大会&#xff08;HUAWEI CONNECT 2024&#xff09;于9月19日在上海世博中心&展览馆盛大召开。20日下午&#xff0c;一场围绕“全场景数据保护&#xff0c;护航数智化时代”的专题论坛举办&#xff0c;云和恩墨受邀参加&#xff0c;并期待与华为合…

Apache APISIX学习(1):介绍、docker启动

一、介绍 Apache APISIX 是一个动态、实时、高性能的 API 网关&#xff0c; 提供负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。你可以把 Apache APISIX 当做流量入口&#xff0c;来处理所有的业务数据&#xff0c;包括动态路由、动态上游…

两台虚拟机之分布式部署

Apache2 和 PHP 安装 在虚拟机1上执行以下步骤: 更新系统包列表: sudo apt update安装 Apache2: sudo apt install apache2 -y安装 PHP 及其扩展: sudo apt install php libapache2-mod-php php-mysql配置Apache和PHP sudo nano /etc/apache2/mods-enabled/dir.conf#…

使用 Internet 共享 (ICS) 方式分配ip

设备A使用dhcp的情况下&#xff0c;通过设备B分配ip并共享网络的方法。 启用网络共享&#xff08;ICS&#xff09;并配置 NAT Windows 自带的 Internet Connection Sharing (ICS) 功能可以简化 NAT 设置&#xff0c;允许共享一个网络连接给其他设备。 打开网络设置&#xff1…

ComfyUI - 使用 ComfyUI 部署与测试 FLUX.1 图像生成模型 教程

前言 FLUX.1 是由 Black Forest Labs 推出的文本到图像生成模型&#xff0c;已成为 AI 绘画领域的高品质模型。该模型由 Stability AI 的前核心成员开发&#xff0c;具备强大的生成能力和高质量的图像输出。目前&#xff0c;Flux 的相关模型&#xff1a; Flux & AE 模型&…

【图虫创意-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…

详解Vite创建Vue3项目router-less-scss-pinia-持久化

前言 Vite 和 Webpack 都是现代化的前端构建工具&#xff0c;它们可以帮助开发者优化前端项目的构建和性能。虽然它们的目标是相似的&#xff0c;但它们在设计和实现方面有许多不同之处。webpack可以看我的上一篇文章 一、准备工作安装工具 这里我们简单介绍一下文章中使用到…

2024年双十一有什么好物值得买呢?双十一必买好物清单

双十一买什么犒劳自己既不会浪费钱又可以增添生活的幸福感&#xff1f;以下就整理了五款更适合与秋冬独自生活相伴的好物&#xff0c;精致增加生活氛围感&#xff0c;热爱生活的同时更好的爱自己&#xff01;努力工作和生活当然也要更好的享受生活&#xff0c;给生活创造更多美…