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

数据结构-线性表-具有独立头节点的双向循环链表

完整代码:

#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:6013)#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<time.h>// 一个具有独立头节点的双向循环链表,
// 区别在于将头节点和数据区域分开;
// 而且有独立头节点的链表为空的条件是:L->next等于L->prior等于NULL;
// 没有独立头节点的链表未空的条件是:L->next等于L->prior等于L;
// 还有一点要注意的是如何让p=L,指针转一圈之后不会回到L;typedef int ElemType;
typedef int Status;typedef struct Node {ElemType data;struct Node* next;	//直接后继指针struct Node* prior;	//直接前驱指针
}Node;
typedef Node* DuLinkList;// 函数声明
Status ListCreate(DuLinkList* L);
Status LinkEmpty(DuLinkList L);
Status ClearList(DuLinkList L);
Status GetElem(DuLinkList L, int i, ElemType* e);
Status LocateElem(DuLinkList L, ElemType e);
Status ListInsert(DuLinkList L, int i, ElemType e);
Status ListDelete(DuLinkList L, int i, ElemType* e);
void printAll(DuLinkList L);
void randList(DuLinkList L, int i);
Status insertHead(DuLinkList L, ElemType e);
Status insertEnd(DuLinkList L, ElemType e);
Status deleteEnd(DuLinkList L);
void ListReverse(DuLinkList L);
void test(DuLinkList L);/// <summary>
/// 创建一个空的链表,并创建头节点
/// </summary>
Status ListCreate(DuLinkList* L) {	//传递的是指针,要用指针接收*L = (DuLinkList)malloc(sizeof(Node));if (!L) {printf("创建失败!\n");return 0;}(*L)->data = 0;(*L)->next = NULL;(*L)->prior = NULL;printf("创建成功!\n");return 1;
}/// <summary>
/// 判断链表是否为空
/// </summary>
Status LinkEmpty(DuLinkList L) {int flag;flag = (L->next == NULL) ? 0 : 1;return flag;
}/// <summary>
/// 将链表清空。
/// </summary>
Status ClearList(DuLinkList L) {DuLinkList p;p = L->next;int j = 1;while (1) {if (p == L->prior) {free(p);break;}p = p->next;free(p->prior);}L->next = NULL;L->prior = NULL;L->data = 0;return 1;
}/// <summary>
/// 将链表L中的第i个位置元素值返回给e。
/// </summary>
Status GetElem(DuLinkList L, int i, ElemType* e) {DuLinkList p;p = L->next;int j = 1;while (j < i) {if (p == L->prior && j != 1 || p == NULL) { return 0; } //指针转了一圈,没找到第i个元素;p = p->next;j++;}if (j > i || p == NULL) { return 0; }*e = p->data;return 1;
}/// <summary>
/// 在链表L中查找与给定值e相等的元素,
/// 如果查找成功,返回该元素在表中序号表示成功;
/// 否则,返回0表示失败。
/// </summary>
Status LocateElem(DuLinkList L, ElemType e) {DuLinkList p;p = L->next;int i;i = 1;while (p) {if (p->data == e) { return i; }if (p == L->prior) { break; }p = p->next;i++;}return 0;
}/// <summary>
/// 在链表L中的第i个位置插入新元素e。
/// </summary>
Status ListInsert(DuLinkList L, int i, ElemType e) {DuLinkList p, s;p = L->next;s = NULL;int j = 1;if (i < 1) {printf("第%d个元素不存在。\n", i);return 0;}while (j < i) {if (p == L->next && j != 1) {printf("第%d个元素不存在。\n", i);return 0;}p = p->next;j++;}s = (DuLinkList)malloc(sizeof(Node));if (!s) {printf("内存申请失败!\n");}s->data = e;// 考虑极端情况if (L->next == NULL) {	//链表中没有数据元素;s->next = s;s->prior = s;L->next = s;L->prior = s;}else {	// 链表中有数据元素;s->next = p;s->prior = p->prior;p->prior->next = s;p->prior = s;if (i == 1) { //插入的位置是首元结点;L->next = s;}else if (i == L->data + 1) { //插入的位置是尾节点;L->prior = s;}}L->data++;return 1;
}/// <summary>
/// 删除链表L中第i个位置元素,并用e返回其值。
/// </summary>
Status ListDelete(DuLinkList L, int i, ElemType* e) {DuLinkList p;p = L->next;int j = 1;if (i < 1 || i>L->data) {printf("第%d个元素不存在。\n", i);return 0;}while (j < i) {p = p->next;j++;}*e = p->data;if (L->next == L->prior) {	// 链表中只有一个元素L->next = NULL;L->prior = NULL;}else if (L->next == p) {	// 删除第一个元素L->next = p->next;}else if (L->prior == p) {	// 删除最后一个元素L->prior = p->prior;}// 正常情况p->next->prior = p->prior;p->prior->next = p->next;free(p);L->data--;return 1;
}/// <summary>
/// 输出链表中所有元素。
/// </summary>
void printAll(DuLinkList L) {DuLinkList p;p = L->next;int i = 0;while (p) {printf("%d\t", p->data);if (p == L->prior)break;p = p->next;}printf("\n");
}/// <summary>
/// 向链表中添加i个随机元素。
/// </summary>
void randList(DuLinkList L, int i) {int min = 0;int max = 1000;int range = max - min + 1;for (int j = 0; j < i; j++) {ElemType e = min + rand() % range;insertEnd(L, e);}printf("\n");
}
/// <summary>
/// 在链表头部插入一个元素(头插法)
/// </summary>
Status insertHead(DuLinkList L, ElemType e) {DuLinkList p, s;p = L->next;s = (DuLinkList)malloc(sizeof(Node));if (s == NULL) {return 0;}s->data = e;L->next = s;if (!p) {    //链表中没有一个元素L->prior = s;s->next = s;s->prior = s;}else {    //链表中又元素s->next = p;s->prior = L->prior;L->prior->next = s;p->prior = s;}L->data++;return 1;
}/// <summary>
/// 在链表末尾插入一个元素(尾插法)
/// </summary>
Status insertEnd(DuLinkList L, ElemType e) {DuLinkList p, s;p = L->prior;s = (DuLinkList)malloc(sizeof(Node));if (!s) {return 0;}s->data = e;L->prior = s;if (!p) {    //链表中没有一个元素L->next = s;s->next = s;s->prior = s;}else {    //链表中有元素s->prior = p;s->next = L->next;L->next->prior = s;p->next = s;}L->data++;return 1;
}/// <summary>
/// 在链表末尾删除一个元素
/// </summary>
Status deleteEnd(DuLinkList L) {DuLinkList p;p = L->prior;if (!p) {    //链表中没有一个元素return 0;}if (L->prior == L->next) {   //链表中的元素只有一个L->prior = NULL;L->next = NULL;}else {                   //链表中的元素大于一个L->prior = p->prior;L->prior->next = L->next;L->next->prior = L->prior;}L->data--;free(p);return 1;
}/// <summary>
/// 将所有元素反转(交换每一个结点的next和prior指针)\
/// (还有一种实现方法是:创建一个新的头结点,将原链表的的结点根据一定顺序插进去)
/// </summary>
void ListReverse(DuLinkList L) {DuLinkList p, agent;p = L->next;agent = NULL;while (p) {agent = p->next;p->next = p->prior;p->prior = agent;if (p == L->prior) {break;}p = agent;}agent = L->next;L->next = L->prior;L->prior = agent;
}// 另一种实现方式
void Reverse(DuLinkList L) {DuLinkList p, s;p = L->next;s = NULL;ListCreate(&s);if (!s) {return;}while (p) {insertHead(s, p->data);if (p == L->prior) {break;}p = p->next;}//printf("%p\n", &L);//printf("%p\n", L);ClearList(L);*L = *s;//printf("%p\n", L);//test(L);//printf("---------\n");//test(s);free(s);
}/// <summary>
/// 获得链表长度(同ListEmpty)
/// </summary>
int ListLight(DuLinkList L) {return L->data;
}void menu() {printf("=============================菜单-双向循环链表===================================\n");printf("(1) 显示菜单\t\t\t\t(2) 判空\t\t\t\t|\n");printf("(3) 清空链表\t\t\t\t(4) 按位删除\t\t\t\t|\n");printf("(5) 按位查找\t\t\t\t(6) 按值查找\t\t\t\t|\n");printf("(7) 按位插入\t\t\t\t(8) 元素个数\t\t\t\t|\n");printf("(9) 输出链表\t\t\t\t(10) 随机生成\t\t\t\t|\n");printf("(11) 头插入\t\t\t\t(12) 尾插入\t\t\t\t|\n");printf("(13) 尾删除\t\t\t\t(14) 反转链表\t\t\t\t|\n");printf("(0) 结束程序\t\t\t\t\t\t\t\t\t|\n");printf("=================================================================================\n");
}void test(DuLinkList L) {int i = 1;printf("[0] data: %d\tself: %p   next: %p    prior: %p\n", L->data, L, L->next, L->prior);DuLinkList p;p = L->next;while (p) {printf("[%d] data: %d\tself: %p   next: %p    prior: %p\n", i++, p->data, p, p->next, p->prior);if (p == L->prior) { break; }p = p->next;}
}// 简化后的main函数
int main() {DuLinkList L = NULL;ListCreate(&L);int choice;ElemType e, * p_e = (ElemType*)malloc(sizeof(ElemType));int i;menu();while (1) {printf("请输入菜单序号:");scanf("%d", &choice);switch (choice) {case 999:test(L);break;case 0:free(L);printf("链表已经销毁。\n");return 0;case 1:menu();break;case 2:if (LinkEmpty(L)) {printf("非空。\n");}else {printf("空\n");}break;case 3:ClearList(L);printf("Ok\n");break;case 4:printf("要删除的位置是:");scanf("%d", &i);if (ListDelete(L, i, p_e)) {printf("Success:删除第%d个位置上的元素 %d\n", i, *p_e);}else {printf("Error:检查输入是否正确。\n");}break;case 5:printf("要查找的位置为:(下标从1开始)");scanf("%d", &i);if (GetElem(L, i, p_e)) {printf("Success:第%d个元素为:%d\n", i, *p_e);}else {printf("Error:无法找到第%d个元素,检查输入是否正确。\n", i);}break;case 6:printf("要查找的值为:");scanf("%d", &e);i = LocateElem(L, e);if (i) {printf("Success:第%d个位置\n", i);}else {printf("没有发现这个值。\n");}break;case 7:printf("输入插入的位置(下标从1开始)以及插入的数值,用空格隔开:\n");scanf("%d %d", &i, &e);if (ListInsert(L, i, e)) {printf("Success\n");}else {printf("Error:插入失败!\n");}break;case 8:printf("表中元素个数为:%d\n", ListLight(L));break;case 9:printAll(L);break;case 10:printf("随机生成几个数?");scanf("%d", &i);randList(L, i);break;case 11:printf("输入要插入的数:");scanf("%d", &e);if (insertHead(L, e)) {printf("Success:插入成功。\n");}else {printf("Error:插入失败!\n");}break;case 12:printf("输入要插入的数:");scanf("%d", &e);if (insertEnd(L, e)) {printf("Success:插入成功。\n");}else {printf("Error:插入失败!\n");}break;case 13:if (deleteEnd(L)) {printf("Success:删除成功。\n");}else {printf("Error:删除失败\n");}break;case 14:/*	printf("%p\n", &L);printf("%p\n", L);*/Reverse(L);break;default:printf("Error:错误输入。\n");break;}}free(p_e);return 0;
}

一、双向循环链表简介

双向循环链表是一种在链表基础上拓展而来的数据结构。与普通链表不同的是,它的每个节点都有两个指针,一个指向前驱节点(prior),一个指向后继节点(next)。而且,它是循环的,即链表的尾节点的后继指针指向头节点,头节点的前驱指针指向尾节点,形成一个闭合的环。

我们这里讨论的双向循环链表还有一个独立的头节点。这个独立头节点不存储数据,主要用于方便对链表的操作和维护。这种链表为空的条件是头节点的nextprior指针都指向NULL

二、代码结构和数据类型定义

(一)数据类型定义

在代码中,首先定义了链表节点的数据类型。通过以下结构体来表示一个节点:

typedef struct Node {ElemType data;struct Node* next;struct Node* prior;
} Node;
typedef Node* DuLinkList;

这里,ElemType被定义为int类型,用于存储节点的数据。Node结构体包含了数据域data以及nextprior这两个指针,分别用于构建链表的双向连接。DuLinkList则是指向Node类型的指针,它代表了整个链表(实际上是从独立头节点开始)。

(二)函数声明

代码中声明了一系列操作双向循环链表的函数,包括创建链表、判断链表是否为空、清空链表、按位获取元素、按值查找元素、插入元素(按位插入、头插法、尾插法)、删除元素(按位删除、尾删除)以及链表的反转等功能。这些函数为我们全面操作链表提供了丰富的接口。

三、主要函数实现分析

(一)创建链表 - ListCreate函数

Status ListCreate(DuLinkList* L) {*L = (DuLinkList)malloc(sizeof(Node));if (!L) {printf("创建失败!\n");return 0;}(*L)->data = 0;(*L)->next = NULL;(*L)->prior = NULL;printf("创建成功!\n");return 1;
}

这个函数用于创建一个空的链表。它通过malloc函数为链表的头节点分配内存空间。如果分配成功,将头节点的data初始化为0nextprior指针都设为NULL,并返回1表示创建成功;如果malloc失败,则返回0

(二)判断链表是否为空 - LinkEmpty函数

Status LinkEmpty(DuLinkList L) {int flag;flag = (L->next == NULL)? 0 : 1;return flag;
}

通过检查链表头节点的next指针是否为NULL来判断链表是否为空。如果nextNULL,说明链表没有数据节点,返回0;否则返回1

(三)清空链表 - ClearList函数

Status ClearList(DuLinkList L) {DuLinkList p;p = L->next;int j = 1;while (1) {if (p == L->prior) {free(p);break;}p = p->next;free(p->prior);}L->next = NULL;L->prior = NULL;L->data = 0;return 1;
}

这个函数用于清空链表。它从链表的第一个数据节点开始,依次释放每个节点的内存。在遍历过程中,通过free(p->prior)释放当前节点的前驱节点,直到到达尾节点。最后,将头节点的nextprior指针设为NULLdata设为0

(四)按位获取元素 - GetElem函数

Status GetElem(DuLinkList L, int i, ElemType* e) {DuLinkList p;p = L->next;int j = 1;while (j < i) {if (p == L->prior && j!= 1 || p == NULL) { return 0; } p = p->next;j++;}if (j > i || p == NULL) { return 0; }*e = p->data;return 1;
}

该函数用于获取链表中指定位置i的元素值。通过遍历链表,从头节点的下一个节点开始,逐个移动指针p,直到找到第i个节点。如果找到了,将该节点的数据存储到e所指向的变量中,并返回1;如果在遍历过程中出现指针转了一圈还没找到或者pNULL等情况,则返回0

(五)按值查找元素 - LocateElem函数

Status LocateElem(DuLinkList L, ElemType e) {DuLinkList p;p = L->next;int i;i = 1;while (p) {if (p->data == e) { return i; }if (p == L->prior) { break; }p = p->next;i++;}return 0;
}

在链表中查找值为e的元素。从链表的第一个数据节点开始,逐个比较节点的数据值与e是否相等。如果找到相等的值,返回该元素在链表中的序号;如果遍历完整个链表都没找到,则返回0

(六)按位插入元素 - ListInsert函数

Status ListInsert(DuLinkList L, int i, ElemType e) {DuLinkList p, s;p = L->next;s = NULL;int j = 1;if (i < 1) {printf("第%d个元素不存在。\n", i);return 0;}while (j < i) {if (p == L->next && j!= 1) {printf("第%d个元素不存在。\n", i);return 0;}p = p->next;j++;}s = (DuLinkList)malloc(sizeof(Node));if (!s) {printf("内存申请失败!\n");}s->data = e;if (L->next == NULL) {s->next = s;s->prior = s;L->next = s;L->prior = s;}else {s->next = p;s->prior = p->prior;p->prior->next = s;p->prior = s;if (i == 1) { L->next = s;}else if (i == L->data + 1) { L->prior = s;}}L->data++;return 1;
}

这个函数实现在链表的指定位置i插入新元素e。首先,通过遍历找到要插入位置的前一个节点p。然后创建一个新节点s,并根据链表是否为空以及插入位置是否为首元节点或尾节点等情况,调整节点之间的指针关系,最后增加链表长度计数器L->data的值。

(七)按位删除元素 - ListDelete函数

Status ListDelete(DuLinkList L, int i, ElemType* e) {DuLinkList p;p = L->next;int j = 1;if (i < 1 || i>L->data) {printf("第%d个元素不存在。\n", i);return 0;}while (j < i) {p = p->next;j++;}*e = p->data;if (L->next == L->prior) {L->next = NULL;L->prior = NULL;}else if (L->next == p) {L->next = p->next;}else if (L->prior == p) {L->prior = p->prior;}p->next->prior = p->prior;p->prior->next = p->next;free(p);L->data--;return 1;
}

用于删除链表中指定位置i的元素,并将删除元素的值存储到e所指向的变量中。先找到要删除的节点p,然后根据链表中节点的数量情况(如只有一个元素、删除第一个元素、删除最后一个元素等)调整指针关系,最后释放被删除节点的内存,并减少链表长度计数器的值。

(八)头插法 - insertHead函数

Status insertHead(DuLinkList L, ElemType e) {DuLinkList p, s;p = L->next;s = (DuLinkList)malloc(sizeof(Node));if (s == NULL) {return 0;}s->data = e;L->next = s;if (!p) {L->prior = s;s->next = s;s->prior = s;}else {s->next = p;s->prior = L->prior;L->prior->next = s;p->prior = s;}L->data++;return 1;
}

实现将一个元素插入到链表头部。创建一个新节点s,将其数据域设为e,然后调整头节点与新节点以及原第一个节点(如果存在)之间的指针关系,最后增加链表长度。

(九)尾插法 - insertEnd函数

Status insertEnd(DuLinkList L, ElemType e) {DuLinkList p, s;p = L->prior;s = (DuLinkList)malloc(sizeof(Node));if (!s) {return 0;}s->data = e;L->prior = s;if (!p) {L->next = s;s->next = s;s->prior = s;}else {s->prior = p;s->next = L->next;L->next->prior = s;p->next = s;}L->data++;return 1;
}

将元素插入到链表的末尾。创建新节点s,设置其数据值为e,然后根据链表是否为空来调整新节点与链表尾节点(如果存在)以及头节点之间的指针关系,最后更新链表长度。

(十)尾删除 - deleteEnd函数

Status deleteEnd(DuLinkList L) {DuLinkList p;p = L->prior;if (!p) {return 0;}if (L->prior == L->next) {L->prior = NULL;L->next = NULL;}else {L->prior = p->prior;L->prior->next = L->next;L->next->prior = L->prior;}L->data--;free(p);return 1;
}

用于删除链表的尾节点。首先判断链表是否为空,如果不为空,根据链表中节点数量情况(只有一个节点或多个节点)调整指针关系,释放尾节点内存并减少链表长度。

(十一)链表反转 - ListReverse函数

void ListReverse(DuLinkList L) {DuLinkList p, agent;p = L->next;agent = NULL;while (p) {agent = p->next;p->next = p->prior;p->prior = agent;if (p == L->prior) {break;}p = agent;}agent = L->next;L->next = L->prior;L->prior = agent;
}

这个函数通过交换每个节点的nextprior指针来实现链表的反转。使用一个临时指针agent来辅助交换过程,遍历链表,逐个交换节点的指针,最后调整头节点的nextprior指针,完成链表的反转。

(十二)另一种链表反转 - Reverse函数

void Reverse(DuLinkList L) {DuLinkList p, s;p = L->next;s = NULL;ListCreate(&s);if (!s) {return;}while (p) {insertHead(s, p->data);if (p == L->prior) {break;}p = p->next;}ClearList(L);*L = *s;free(s);
}

这是另一种实现链表反转的方法。它先创建一个新的链表s,然后通过遍历原链表L,将原链表的元素以头插法插入到新链表s中。接着清空原链表L,再将新链表s的内容复制到原链表L中(通过*L = *s),最后释放新链表s的头节点内存。

相关文章:

数据结构-线性表-具有独立头节点的双向循环链表

完整代码&#xff1a; #define _CRT_SECURE_NO_WARNINGS #pragma warning(disable:6013)#include<stdio.h> #include<malloc.h> #include<stdlib.h> #include<time.h>// 一个具有独立头节点的双向循环链表&#xff0c; // 区别在于将头节点和数据区域…...

CSS 响应式设计之媒体查询技术

CSS 媒体查询&#xff08;Media Queries&#xff09;是一种根据不同设备的特性&#xff08;如屏幕宽度、分辨率、方向等&#xff09;来应用不同的 CSS 样式的技术。它通常用于响应式设计&#xff0c;帮助网页在不同设备和屏幕尺寸下良好地展示。 基本语法 media (条件) {/* 样…...

HARCT 2025 分论坛4:智能系统传感、传感器开发和数据融合中的智能数据分析

机电液一体化与先进机器人控制技术国际会议&#xff08;HARCT 2025&#xff09;将于2025年1月3日-6日在中国广西桂林召开。本届会议围绕“机电液一体化”“机器人”“控制技术”等最新研究成果&#xff0c;邀请海内外在这一领域贡献卓著的专家学者做精彩致辞和报告。 会议期间…...

云计算研究实训室建设方案

一、引言 随着云计算技术的迅速发展和广泛应用&#xff0c;职业院校面临着培养云计算领域专业人才的迫切需求。本方案旨在构建一个先进的云计算研究实训室&#xff0c;为学生提供一个集理论学习、实践操作、技术研发与创新于一体的综合性学习平台&#xff0c;以促进云计算技术…...

VRT: 关于视频修复的模型

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;编程探索专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年11月15日14点34分 神秘男子影, 秘而不宣藏。 泣意深不见, 男子自持重, 子夜独自沉。 论文链接 点击开启你的论文编程之旅…...

实习冲刺Day22

算法题 路径总和 112. 路径总和 - 力扣&#xff08;LeetCode&#xff09; class Solution { public:bool hasPathSum(TreeNode* root, int targetSum) {if(!root)return 0;//节点为空返回0int sumroot->val;//记录当前节点的值int ntargetSum-sum;//距离目标值还差多少if…...

datawhale2411组队学习之模型压缩技术1:模型剪枝

文章目录 一、环境配置二、模型压缩2.1 模型压缩简介2.2 模型压缩评价指标 三、 模型剪枝3.1 模型剪枝简介3.2 何为剪枝&#xff08;What is Pruning?&#xff09;3.3 剪枝标准&#xff08;How to prune?&#xff09;3.4 剪枝频率&#xff08;How often?&#xff09;3.5 剪枝…...

高防服务器的费用受到哪些原因影响?

在如今的互联网社会中&#xff0c;越来越多的企业都开始了线上网络业务的发展&#xff0c;网络安全也日益受到了重视&#xff0c;高防服务器成为了众多企业的首要选择&#xff0c;不仅可以帮助企业有效抵御各种网络攻击&#xff0c;保证网站和应用的稳定性。 但是高防服务器与其…...

中断和异常处理,嵌入式行业的门槛?

Linux内核中&#xff0c;中断和异常是重要的机制&#xff0c;用于响应硬件事件和处理异常情况。它们直接关系到系统的稳定性和性能。本文将通过清晰的结构、逻辑图、表格&#xff0c;深入解析中断和异常处理的种类、流程以及它们与系统调用和用户空间的联系。 1. 中断和异常概述…...

latex中英文环境中双引号怎么输入

latex中英文环境中双引号怎么输入 1. **英文环境中的双引号**2. **中文环境中的双引号**3. **嵌套引号**4. **一致性处理**小结&#xff1a; 在 LaTeX 中&#xff0c;输入双引号的方法取决于文档的语言环境。以下是针对英文和中文环境的双引号输入方法&#xff1a; 1. 英文环境…...

用 Python 从零开始创建神经网络(三):添加层级(Adding Layers)

添加层级&#xff08;Adding Layers&#xff09; 引言1. Training Data2. Dense Layer Class 引言 我们构建的神经网络变得越来越受人尊敬&#xff0c;但目前我们只有一层。当神经网络具有两层或更多隐藏层时&#xff0c;它们变成了“深度”网络。目前我们只有一层&#xff0c…...

前端知识点---构造函数(javascript)

文章目录 前端知识点---构造函数(Javascript)1. 定义构造函数2. 使用构造函数创建对象3. 工作原理4. 构造函数与原型5. 类的语法糖6. 注意事项 前端知识点—构造函数(Javascript) 在我的文章 “对象” 里我提到了构造函数 , 前端知识点—Javascript的对象(Javascript) 因为day…...

Nginx 上安装 SSL 证书并启用 HTTPS 访问

本文将介绍如何在 Nginx 上为你的域名安装 SSL 证书&#xff0c;并配置 Nginx 使用 HTTPS 安全访问。我们将使用 Let’s Encrypt 免费的 SSL 证书&#xff0c;通过 Certbot 生成并管理证书&#xff0c;然后配置 Nginx 实现 HTTPS 加密访问。同时&#xff0c;我们将解决因 SSL 证…...

谷歌Gemini发布iOS版App,live语音聊天免费用!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;专注于分享AI全维度知识&#xff0c;包括但不限于AI科普&#xff0c;AI工…...

docker运行ActiveMQ-Artemis

前言 artemis跟以前的ActiveMQ不是一个产品&#xff0c;原ActiveMQ改为ActiveMQ Classic, 现在的artemis是新开发的&#xff0c;和原来不兼容&#xff0c;全称&#xff1a;ActiveMQ Artemis 本位仅介绍单机简单部署使用&#xff0c;仅用于学习和本地测试使用 官网&#xff1a;…...

90.选择排序(理论分析)

一.选择排序 冒泡排序每相邻的俩个元素之间都会比较交换一次&#xff0c;效率比较慢。这对这个问题所改进的算法叫做选择排序。 二&#xff0e;选择排序的实现思路 首先在一组未排序的数据中假定一个最大或者最小元素&#xff0c;一般是第0个元素。然后在从剩余未排序的元素中…...

GitLab 如何跨版本升级?

本分分享 GitLab 跨版本升级的一些注意事项。 众所周知&#xff0c;GitLab 的升级必须要严格遵循升级路径&#xff0c;否则就会出现问题&#xff0c;导致升级失败。因此&#xff0c;在 GitLab 升级之前需要做好两件事情&#xff1a; 当前版本的确认升级路径的确认 极狐GitLa…...

【Fermat】费马小定理

定理 若存在整数 a &#xff0c; p 且g c d ( a &#xff0c; p ) 1 gcd(a&#xff0c;p)1gcd(a&#xff0c;p)1&#xff0c;即二者互为质数&#xff0c;则有 a ( p − 1 ) ≡ 1 ( m o d p ) a^{(p-1)}≡ 1(mod p) a (p−1) ≡1(modp) 目录 定理 引理 引理一 引理二 证…...

NVMe(Non-Volatile Memory Express)非易失性存储器访问和传输协议

目录 NVMe(Non-Volatile Memory Express)非易失性存储器访问和传输协议 一、NVMe的定义 二、NVMe的特点 三、NVMe的应用场景 四、举例说明 NVMe(Non-Volatile Memory Express)非易失性存储器访问和传输协议 是一种非易失性存储器访问和传输协议,专为固态硬盘(SSD)…...

C++初阶——queue

一、什么是queue 是一个容器适配器&#xff0c;专门设计用于在先进先出&#xff08;FIFO&#xff0c;First In First Out&#xff09;的上下文中操作。它是一个容器适配器&#xff0c;这意味着它不是一个完整的容器类&#xff0c;而是封装了一个特定的容器类&#xff08;如list…...

达梦数据库迁移j脚本

国产环境使用达梦数据库的越来越多&#xff0c;除了使用管理工具&#xff0c;还是可以使用脚本。 下面简单记录下&#xff0c;我在迁移中遇到的问题&#xff1a; 备份脚本 使用此脚本可以一次备份一个数据 backup_one_db.sh #!/bin/bashexport DB$1 export PASS<your_p…...

【Linux】内核调用栈打印函数dump_stack使用效果

init/main.c的start_kernel示例&#xff0c;这个调用栈不太深&#xff1a; /var/log/dmesg日志&#xff1a; [ 0.000000] kernel: [init/main.c start_kernel 911] start_kernel(void) [ 0.000000] kernel: [kernel/panic.c print_tainted 519 LOG_TIMES: 1 ] [ 0.…...

Uniapp踩坑input自动获取焦点ref动态获取实例不可用

前言 大家好我是没钱的君子下流坯&#xff0c;用自己的话解释自己的知识。很久很更新了&#xff0c;这几个月一直在加班&#xff0c;今天记录一个uniapp关于input中focus()方法自动获取焦点的坑。 案例 为了实现一个手机验证码的页面&#xff0c;验证码是五个输入框&#xf…...

数据分析-47-时间序列变点检测之离线历史数据的CPD

文章目录 1 时间序列结构1.1 变化点的定义1.2 结构变化的类型1.2.1 水平变化1.2.2 方差变化1.3 变点检测1.3.1 离线数据检测方法1.3.2 实时数据检测方法2 模拟数据2.1 模拟恒定方差数据2.2 模拟变化方差数据3 离线数据变点检测3.1 Ruptures模块3.2 恒定方差CPD3.3 变化方差CPD4…...

加入GitHub Spark需要申请

目录 加入GitHub Spark需要申请 GitHub Spark 一、产品定位与特点 二、核心组件与功能 三、支持的AI模型 四、应用场景与示例 五、未来展望 六、申请体验 加入GitHub Spark需要申请 GitHub Spark 是微软旗下GitHub在2024年10月30日的GitHub Universe大会上推出的一款革…...

生成式GPT商品推荐:精准满足用户需求

生成式GPT商品推荐&#xff1a;精准满足用户需求 随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;电商平台正在逐步迎来一场前所未有的变革。尤其是生成式GPT&#xff08;Generative Pre-trained Transformer&#xff09;技术的应用&#xff0c;正在重新定…...

async 和 await的使用

一、需求 点击按钮处理重复提交&#xff0c;想要通过disabled的方式实现。 但是点击按钮调用的方法里有ajax、跳转、弹窗等一系列逻辑操作&#xff0c;需要等方法里流程都走完&#xff0c;再把disabled设为false&#xff0c;这样下次点击按钮时就可以继续走方法里的ajax等操作…...

Spring Cloud Vault快速入门Demo

1.什么是Spring Cloud Vault&#xff1f; Spring Cloud Vault 是 Spring Cloud 生态系统中的一个项目&#xff0c;旨在简化 Spring 应用程序与 HashiCorp Vault 的集成。它提供了一种方便的方式来管理和访问应用程序的敏感配置数据&#xff0c;如数据库凭证、API 密钥和其他机…...

道陟科技EMB产品开发进展与标准设计的建议|2024电动汽车智能底盘大会

11月12日&#xff0c;2024电动汽车智能底盘大会在重庆开幕。会议由中国汽车工程学会主办&#xff0c;电动汽车产业技术创新战略联盟、中国汽车工程学会智能底盘分会、智能绿色车辆与交通全国重点实验室承办。本届大会围绕电动汽车智能底盘相关技术发展与融合&#xff0c;满足高…...

GitHub Org

运营一个GitHub Org&#xff08;组织&#xff09;是一个复杂但充满价值的过程&#xff0c;它涉及多个方面&#xff0c;包括项目管理、团队协作、代码审查、文档维护、社区建设等。以下是一篇关于如何运营GitHub Org的详细指南&#xff0c;旨在帮助组织者更好地管理和维护其GitH…...