(C语言)循环单链表(数据结构)(指针)(循环列表教程)
目录
源代码:
代码详解:
1. 头文件和宏定义
2. 类型定义
3. 初始化链表
4. 判断链表是否为空
5. 求链表的长度
6. 清空链表
7. 销毁链表
8. 链表的插入(头插法)
9. 链表的插入(尾插法)
10. 查看链表
11. 单链表插入(在第 i 个结点之前插入)
12. 删除第 i 个结点
13. 查看第 i 个元素
14. 主函数
知识原理:
1. 基础结构定义
2. 初始化链表
3. 头插法创建链表(动图演示)
4. 尾插法创建链表
5. 遍历链表(带图解)
6. 插入结点(步骤分解)
7. 删除结点(安全版)
8. 内存管理要点
运行结果:
单链表教程:
源代码:
#include <stdio.h>
#include <stdlib.h>//函数结果状态代码
#define OK 1
#define ERROR 0typedef int Status;//函数返回状态,ok,error
typedef int Elemtype;//链表元素为整形
typedef struct Lnode//定义结构体
{Elemtype data;//数据域struct Lnode* next;//指针域
}Lnode,*LinkList;//单个结点,整个链表(指向结点的指针)//初始化链表(建立一个头结点)
Status InitLinkList(LinkList* L){*L=(LinkList)malloc(sizeof(Lnode));//分配头结点内存if(*L==NULL){return ERROR;//判断是否分配成功}(*L)->next=*L;//头结点的指针域指向他自己(循环链表)return OK;
}//判断链表是否为空
Status IsEmptyLinkList(const LinkList* L){if((*L)->next==(*L)){//看看是否指向他自己printf("该链表为空!\n");return ERROR;}else{printf("该链表不为空!\n");return OK;}
}//求链表的长度
Status LenLinkList(const LinkList* L){IsEmptyLinkList(L);//判断链表是否为空int i=0;//计数Lnode* p;//定义一个临时的结点p=(*L)->next;while (p!=*L)//仍然是看看是否指向自己(回到头结点){i++;//每循环一次计数加一p=p->next;}printf("该链表的长度为:%d\n",i);return OK;
}//清空链表
Status ClearLinkList(LinkList* L){Lnode* p;Lnode* q;p=(*L)->next;while (p!=*L)//回到头结点时结束{q=p;p=p->next;free(q);}(*L)->next=*L;printf("该链表已清空!\n");return OK;
}//销毁链表
Status DestoryLinkList(LinkList* L){LinkList p;//定义一个临时的指向结点的指针LinkList q=(*L)->next;while (q!=*L){p=*L;//储存原来的指针(结点)*L=(*L)->next;//往后移动结点free(p);//释放原来的指针}printf("该链表已销毁!\n");return OK;
}//链表的插入,头插法
Status CreateLinkList_h(LinkList* L,int n){//n是插入几条数据InitLinkList(L);//创建头结点for(int i=0;i<n;i++){LinkList newlnode;//创建一个新结点newlnode=(Lnode*)malloc(sizeof(Lnode));//为新节点分配内存if(newlnode==NULL){return ERROR;//判断是否分配成功}printf("请输入数据:\n");scanf("%d",&newlnode->data);newlnode->next=(*L)->next;//使新结点指向原指针(*L)->next=newlnode;//使头指针指向新结点}return OK;
}//链表的插入,尾插入
Status CreateLinkList_r(LinkList* L,int n){InitLinkList(L);//创建头结点LinkList p=*L;//定义临时尾结点for(int i=0;i<n;i++){LinkList newlnode;newlnode=(Lnode*)malloc(sizeof(Lnode));//给新结点分配内存if(newlnode==NULL){return ERROR;//判断是否分配成功}printf("请输入数据:\n");scanf("%d",&newlnode->data);newlnode->next=*L;//使新结点指向头结点p->next=newlnode;//使原结点指向新结点p=p->next;//后移一次,定义新的尾结点}return OK;
}//查看链表
Status ShowLinkList(const LinkList* L){IsEmptyLinkList(L);Lnode* p=(*L)->next;//定义个临时结点int i=1;printf("该链表的数据为:\n");while (p!=*L)//指向头结点{printf("%d : %d\n", i, p->data); // 打印序号和数据i++; // 序号递增p = p->next; // p 移动到下一个结点}return OK;
}//单链表插入,在第i个结点之前插入一个结点
Status InsertLinkList(LinkList *L, int i, Elemtype value)
{Lnode* p;//定义临时结点p = (*L)->next;//初始化为第一个结点int j = 1;while (p && j < i - 1) //找到第i-1个结点(就是i的前面){j++;p = p->next;}if (!p || j > i - 1) //i大于表长+1,或者小于1,插入位置非法return ERROR;Lnode* newlnode;//定义新结点newlnode = (Lnode*)malloc(sizeof(Lnode));newlnode->data = value;//插入的数据newlnode->next = p->next;p->next = newlnode;return OK;
}//删除第i个结点
Status DelLinkList(LinkList* L,int i){int j=i;i=1;Lnode* p=(*L);Lnode* q;while (j!=i)//找到第i个结点{i++;p=p->next;}if (p->next == *L || j > i) return ERROR;//检查是否越界q=p->next;p->next=q->next;free(q);return OK;
}//查看第i个元素
Status LocatElem(const LinkList* L,int i){int j=i;//赋值给ji=1;//初始化iLinkList p=(*L)->next;//创建临时结点表示第一个结点IsEmptyLinkList(L);//检查是否为空//逐步后移,直到i和j相等while (i!=j){i++;p=p->next;}if (p->next == *L || j > i) return ERROR;//检查是否越界printf("第%d个 : %d\n", j, p->data); // 打印第i个序号,和数据return OK;
}//主函数
int main(){LinkList mylist;mylist=NULL;//CreateLinkList_h(&mylist,4);//头插CreateLinkList_r(&mylist,4);//尾插ShowLinkList(&mylist);InsertLinkList(&mylist, 3, 9);ShowLinkList(&mylist);LenLinkList(&mylist);DelLinkList(&mylist,3);ShowLinkList(&mylist);LocatElem(&mylist,2);IsEmptyLinkList(&mylist);ClearLinkList(&mylist);DestoryLinkList(&mylist);
}
代码详解:
1. 头文件和宏定义
#include <stdio.h> #include <stdlib.h>//函数结果状态代码 #define OK 1 #define ERROR 0
#include <stdio.h>
:引入标准输入输出库,这样就能使用printf
和scanf
等函数了。#include <stdlib.h>
:引入标准库,可使用malloc
和free
等内存管理函数。#define OK 1
和#define ERROR 0
:定义宏,用于表示函数执行的状态,OK
代表操作成功,ERROR
代表操作失败。2. 类型定义
typedef int Status;//函数返回状态,ok,error typedef int Elemtype;//链表元素为整形 typedef struct Lnode//定义结构体 {Elemtype data;//数据域struct Lnode* next;//指针域 }Lnode, * LinkList;//单个结点,整个链表(指向结点的指针)
typedef int Status
:将int
类型重命名为Status
,用来表示函数的返回状态。typedef int Elemtype
:把int
类型重命名为Elemtype
,意味着链表中存储的元素类型为整数。typedef struct Lnode
:定义一个结构体Lnode
,它包含两个成员:
Elemtype data
:数据域,用于存储结点的数据。struct Lnode* next
:指针域,指向链表中的下一个结点。Lnode, * LinkList
:Lnode
表示单个结点的类型,LinkList
表示指向结点的指针类型,也就是整个链表。3. 初始化链表
//初始化链表(建立一个头结点) Status InitLinkList(LinkList* L) {*L = (LinkList)malloc(sizeof(Lnode));//分配头结点内存if (*L == NULL) {return ERROR;//判断是否分配成功}(*L)->next = *L;//头结点的指针域指向他自己(循环链表)return OK; }
LinkList* L
:传入的是指向链表指针的指针,这样就能修改调用者的链表指针了。*L = (LinkList)malloc(sizeof(Lnode))
:为头结点分配内存。if (*L == NULL)
:检查内存分配是否成功,若失败则返回ERROR
。(*L)->next = *L
:让头结点的next
指针指向自身,形成循环链表。return OK
:若初始化成功,返回OK
。图解:
+--------+| 头结点 |+--------+| ^| |+----+
4. 判断链表是否为空
//判断链表是否为空 Status IsEmptyLinkList(const LinkList* L) {if ((*L)->next == (*L)) {//看看是否指向他自己printf("该链表为空!\n");return ERROR;}else {printf("该链表不为空!\n");return OK;} }
const LinkList* L
:传入指向链表指针的常量指针,不修改链表指针。if ((*L)->next == (*L))
:检查头结点的next
指针是否指向自身,若是则链表为空,输出提示信息并返回ERROR
。- 反之,输出链表不为空的提示信息并返回
OK
。5. 求链表的长度
//求链表的长度 Status LenLinkList(const LinkList* L) {IsEmptyLinkList(L);//判断链表是否为空int i = 0;//计数Lnode* p;//定义一个临时的结点p = (*L)->next;while (p != *L)//仍然是看看是否指向自己(回到头结点){i++;//每循环一次计数加一p = p->next;}printf("该链表的长度为:%d\n", i);return OK; }
IsEmptyLinkList(L)
:先判断链表是否为空。int i = 0
:初始化计数器。Lnode* p
:定义一个临时结点指针。p = (*L)->next
:让p
指向头结点的下一个结点。while (p != *L)
:当p
不等于头结点时,继续循环。
i++
:计数器加一。p = p->next
:p
指向下一个结点。- 最后输出链表的长度并返回
OK
。6. 清空链表
//清空链表 Status ClearLinkList(LinkList* L) {Lnode* p;Lnode* q;p = (*L)->next;while (p != *L)//回到头结点时结束{q = p;p = p->next;free(q);}(*L)->next = *L;printf("该链表已清空!\n");return OK; }
Lnode* p
和Lnode* q
:定义两个临时结点指针。p = (*L)->next
:p
指向头结点的下一个结点。while (p != *L)
:当p
不等于头结点时,继续循环。
q = p
:用q
保存当前结点。p = p->next
:p
指向下一个结点。free(q)
:释放q
指向的结点。(*L)->next = *L
:让头结点的next
指针指向自身,恢复为空链表状态。- 输出清空提示信息并返回
OK
。7. 销毁链表
//销毁链表 Status DestoryLinkList(LinkList* L) {LinkList p;LinkList q = (*L)->next;while (q != *L) {p = q;q = q->next;free(p);}free(*L);printf("该链表已销毁!\n");return OK; }
LinkList p
和LinkList q
:定义两个链表指针。q = (*L)->next
:q
指向头结点的下一个结点。while (q != *L)
:当q
不等于头结点时,继续循环。
p = q
:用p
保存当前结点。q = q->next
:q
指向下一个结点。free(p)
:释放p
指向的结点。free(*L)
:释放头结点。- 输出销毁提示信息并返回
OK
。8. 链表的插入(头插法)
//链表的插入,头插法 Status CreateLinkList_h(LinkList* L, int n) {//n是插入几条数据InitLinkList(L);//创建头结点for (int i = 0; i < n; i++) {LinkList newlnode;//创建一个新结点newlnode = (Lnode*)malloc(sizeof(Lnode));//为新节点分配内存if (newlnode == NULL) {return ERROR;//判断是否分配成功}printf("请输入数据:\n");scanf("%d", &newlnode->data);newlnode->next = (*L)->next;//使新结点指向原指针(*L)->next = newlnode;//使头指针指向新结点}return OK; }
InitLinkList(L)
:初始化链表,创建头结点。for (int i = 0; i < n; i++)
:循环n
次,插入n
个结点。
LinkList newlnode
:定义一个新结点指针。newlnode = (Lnode*)malloc(sizeof(Lnode))
:为新结点分配内存。if (newlnode == NULL)
:检查内存分配是否成功,若失败则返回ERROR
。scanf("%d", &newlnode->data)
:从用户输入读取数据存入新结点的数据域。newlnode->next = (*L)->next
:让新结点的next
指针指向头结点原来指向的结点。(*L)->next = newlnode
:让头结点的next
指针指向新结点。- 最后返回
OK
。图解:
插入前:+--------+ +--------+| 头结点 | -> | 结点1 |+--------+ +--------+
插入后:
+--------+ +--------+ +--------+| 头结点 | -> | 新结点 | -> | 结点1 |+--------+ +--------+ +--------+
9. 链表的插入(尾插法)
//链表的插入,尾插入 Status CreateLinkList_r(LinkList* L, int n) {InitLinkList(L);//创建头结点LinkList p = *L;//定义临时尾结点for (int i = 0; i < n; i++) {LinkList newlnode;newlnode = (Lnode*)malloc(sizeof(Lnode));//给新结点分配内存if (newlnode == NULL) {return ERROR;//判断是否分配成功}printf("请输入数据:\n");scanf("%d", &newlnode->data);newlnode->next = *L;//使新结点指向头结点p->next = newlnode;//使原结点指向新结点p = p->next;//后移一次,定义新的尾结点}return OK; }
InitLinkList(L)
:初始化链表,创建头结点。LinkList p = *L
:定义一个临时尾结点指针,初始指向头结点。for (int i = 0; i < n; i++)
:循环n
次,插入n
个结点。
LinkList newlnode
:定义一个新结点指针。newlnode = (Lnode*)malloc(sizeof(Lnode))
:为新结点分配内存。if (newlnode == NULL)
:检查内存分配是否成功,若失败则返回ERROR
。scanf("%d", &newlnode->data)
:从用户输入读取数据存入新结点的数据域。newlnode->next = *L
:让新结点的next
指针指向头结点。p->next = newlnode
:让原尾结点的next
指针指向新结点。p = p->next
:更新尾结点指针,使其指向新结点。- 最后返回
OK
。10. 查看链表
//查看链表 Status ShowLinkList(const LinkList* L) {IsEmptyLinkList(L);Lnode* p = (*L)->next;//定义个临时结点int i = 1;printf("该链表的数据为:\n");while (p != *L)//指向头结点{printf("%d : %d\n", i, p->data); // 打印序号和数据i++; // 序号递增p = p->next; // p 移动到下一个结点}return OK; }
IsEmptyLinkList(L)
:先判断链表是否为空。Lnode* p = (*L)->next
:定义一个临时结点指针,指向头结点的下一个结点。int i = 1
:初始化序号。while (p != *L)
:当p
不等于头结点时,继续循环。
printf("%d : %d\n", i, p->data)
:打印序号和结点的数据。i++
:序号加一。p = p->next
:p
指向下一个结点。- 最后返回
OK
。11. 单链表插入(在第
i
个结点之前插入)//单链表插入,在第i个结点之前插入一个结点 Status InsertLinkList(LinkList* L, int i, Elemtype value) {Lnode* p;//定义临时结点p = (*L);int j = 0;while (p && j < i - 1) //找到第i-1个结点(就是i的前面){j++;p = p->next;}if (!p || j > i - 1) //i大于表长+1,或者小于1,插入位置非法return ERROR;Lnode* newlnode;//定义新结点newlnode = (Lnode*)malloc(sizeof(Lnode));newlnode->data = value;//插入的数据newlnode->next = p->next;p->next = newlnode;return OK; }
Lnode* p
:定义一个临时结点指针,初始指向头结点。int j = 0
:初始化计数器。while (p && j < i - 1)
:循环找到第i - 1
个结点。
j++
:计数器加一。p = p->next
:p
指向下一个结点。if (!p || j > i - 1)
:检查插入位置是否合法,若不合法则返回ERROR
。Lnode* newlnode
:定义一个新结点指针。newlnode = (Lnode*)malloc(sizeof(Lnode))
:为新结点分配内存。newlnode->data = value
:将插入的值存入新结点的数据域。newlnode->next = p->next
:让新结点的next
指针指向第i
个结点。p->next = newlnode
:让第i - 1
个结点的next
指针指向新结点。- 最后返回
OK
。12. 删除第
i
个结点//删除第i个结点 Status DelLinkList(LinkList* L, int i) {if (i < 1) return ERROR;int j = 1;Lnode* p = *L;Lnode* q;while (p->next != *L && j < i) {j++;p = p->next;}if (p->next == *L || j > i) return ERROR;q = p->next;p->next = q->next;free(q);return OK; }
if (i < 1)
:检查i
是否小于 1,若小于 1 则返回ERROR
。int j = 1
:初始化计数器。Lnode* p = *L
:定义一个临时结点指针,初始指向头结点。while (p->next != *L && j < i)
:循环找到第i - 1
个结点。
j++
:计数器加一。p = p->next
:p
指向下一个结点。if (p->next == *L || j > i)
:检查i
是否超出链表长度,若超出则返回ERROR
。q = p->next
:用q
保存第i
个结点。p->next = q->next
:让第i - 1
个结点的next
指针指向第i + 1
个结点。free(q)
:释放第i
个结点的内存。- 最后返回
OK
。13. 查看第
i
个元素//查看第i个元素 Status LocatElem(const LinkList* L, int i) {if (i < 1) return ERROR;int j = 1;LinkList p = (*L)->next;IsEmptyLinkList(L);//检查是否为空while (p != *L && j < i) {j++;p = p->next;}if (p == *L) {printf("位置超出链表长度!\n");return ERROR;}printf("第%d个 : %d\n", i, p->data); // 打印第i个序号,和数据return OK; }
if (i < 1)
:检查i
是否小于 1,若小于 1 则返回ERROR
。int j = 1
:初始化计数器。LinkList p = (*L)->next
:定义一个临时结点指针,指向头结点的下一个结点。IsEmptyLinkList(L)
:检查链表是否为空。while (p != *L && j < i)
:循环找到第i
个结点。
j++
:计数器加一。p = p->next
:p
指向下一个结点。if (p == *L)
:检查i
是否超出链表长度,若超出则输出提示信息并返回ERROR
。printf("第%d个 : %d\n", i, p->data)
:打印第i
个结点的数据。- 最后返回
OK
。14. 主函数
//主函数 int main() {LinkList mylist;mylist = NULL;//CreateLinkList_h(&mylist,4);//头插CreateLinkList_r(&mylist, 4);//尾插ShowLinkList(&mylist);InsertLinkList(&mylist, 3, 9);ShowLinkList(&mylist);LenLinkList(&mylist);DelLinkList(&mylist, 3);ShowLinkList(&mylist);LocatElem(&mylist, 2);IsEmptyLinkList(&mylist);ClearLinkList(&mylist);DestoryLinkList(&mylist); }
LinkList mylist
:定义一个链表指针。mylist = NULL
:初始化链表指针为NULL
。CreateLinkList_r(&mylist, 4)
:使用尾插法插入 4 个结点。ShowLinkList(&mylist)
:显示链表内容。InsertLinkList(&mylist, 3, 9)
:在第 3 个结点之前插入值为 9 的结点。ShowLinkList(&mylist)
:再次显示链表内容。LenLinkList(&mylist)
:计算并输出链表长度。DelLinkList(&mylist, 3)
:删除第 3 个结点。ShowLinkList(&mylist)
:再次显示链表内容。LocatElem(&mylist, 2)
:查看第 2 个结点的数据。IsEmptyLinkList(&mylist)
:判断链表是否为空。ClearLinkList(&mylist)
:清空链表。DestoryLinkList(&mylist)
:销毁链表。
知识原理:
1. 基础结构定义
typedef struct Lnode {int data; // 数据域(存储整型数据)struct Lnode* next; // 指针域(指向下一个结点) } Lnode, *LinkList; // Lnode是结点类型,LinkList是指向结点的指针类型图示:
[data|next] → [data|next] → ... → [头结点]
2. 初始化链表
Status InitLinkList(LinkList* L) {*L = (LinkList)malloc(sizeof(Lnode)); // 创建头结点(*L)->next = *L; // 头结点指向自己,形成空环return OK; }原理:
分配头结点内存
让头结点的
next
指向自己,表示空链表内存状态:
头结点↓ [NULL|] ←┐↑_____┘
3. 头插法创建链表(动图演示)
newNode->next = (*L)->next; // ① 新结点指向原首结点 (*L)->next = newNode; // ② 头结点指向新结点插入过程:
初始:头结点 → [A] 步骤1:newNode → [A] 步骤2:头结点 → newNode → [A]
4. 尾插法创建链表
newNode->next = *L; // 新结点指向头结点 p->next = newNode; // 尾结点指向新结点 p = newNode; // 更新尾指针特点:
需要维护尾指针
p
插入顺序与数据顺序一致
5. 遍历链表(带图解)
while (p != *L) { // 回到头结点时停止printf("%d ", p->data);p = p->next; }遍历路径:
头结点 → [10] → [20] → [30] → 头结点↑_________________________|
6. 插入结点(步骤分解)
// 在位置i前插入 newNode->next = p->next; // ① 新结点指向原i位置结点 p->next = newNode; // ② i-1结点指向新结点示例(在第2个位置插入9):
插入前:头结点 → [10] → [20] → [30] 插入后:头结点 → [10] → [9] → [20] → [30]
7. 删除结点(安全版)
q = p->next; // ① 保存待删除结点 p->next = q->next; // ② 绕过待删除结点 free(q); // ③ 释放内存边界检查:
if (p->next == *L) return ERROR; // 防止删除不存在的结点
8. 内存管理要点
操作 关键步骤 注意事项 创建结点 malloc
分配内存检查是否分配成功 删除结点 free
释放内存必须先保存 next
再释放清空链表 循环释放所有结点 最后重置头结点指针 销毁链表 先清空再释放头结点 将头指针设为NULL
运行结果:
请输入数据:
12
请输入数据:
23
请输入数据:
34
请输入数据:
45
该链表不为空!
该链表的数据为:
1 : 12
2 : 23
3 : 34
4 : 45
该链表不为空!
该链表的数据为:
1 : 12
2 : 23
3 : 9
4 : 34
5 : 45
该链表不为空!
该链表的长度为:5
该链表不为空!
该链表的数据为:
1 : 12
2 : 23
3 : 34
4 : 45
该链表不为空!
第2个 : 23
该链表不为空!
该链表已清空!
该链表已销毁!请按任意键继续. . .
单链表教程:
(C语言)单链表(2.0)数据结构(指针,单链表教程)-CSDN博客
注:该代码是本人自己所写,可能不够好,不够简便,欢迎大家指出我的不足之处。如果遇见看不懂的地方,可以在评论区打出来,进行讨论,或者联系我。上述内容全是我自己理解的,如果你有别的想法,或者认为我的理解不对,欢迎指出!!!如果可以,可以点一个免费的赞支持一下吗?谢谢各位彦祖亦菲!!!!!
相关文章:
(C语言)循环单链表(数据结构)(指针)(循环列表教程)
目录 源代码: 代码详解: 1. 头文件和宏定义 2. 类型定义 3. 初始化链表 4. 判断链表是否为空 5. 求链表的长度 6. 清空链表 7. 销毁链表 8. 链表的插入(头插法) 9. 链表的插入(尾插法) 10. 查看…...
Debian 12 服务器搭建Beego环境
一、Debian 12系统准备 1.更新系统 #apt update && apt upgrade -y 2.安装基础工具 #apt install -y git curl wget make gcc 二、安装Go环境 Go语言的镜像官网:https://golang.google.cn/ 1.下载go最新版 #cd /usr/local/src #wget -o https://golang.go…...
淘宝商品评论API接口概述及JSON数据参考(测试)
前言 一、淘宝商品评论API接口概述 淘宝商品评论API接口是淘宝开放平台提供的一项服务,允许开发者通过HTTP请求获取指定商品的评论数据。这些数据包括评论内容、评论者信息、评分、评论时间等,为开发者提供了丰富的商品评价信息,有助于分析…...
AI:决策树、决策森林与随机森林
决策树与随机森林:从原理到实战的全面解析(2025最新版) 引言 在机器学习的世界里,决策树和森林模型(包括随机森林)常常是数据科学家们常用的工具之一。无论是初学者还是资深从业者,理解这些模型的原理和应用,都能帮助你在数据分析和预测任务中获得更好的结果。本文将…...
图形化编程语言:低代码赛道的技术革命与范式突破
在 2024 年 Gartner 低代码平台魔力象限报告中,传统低代码厂商市场份额增速放缓至 12%,而图形化编程语言赛道融资额同比激增 370%。本文深度剖析低代码平台的技术瓶颈,系统阐释图形化编程语言的核心优势,揭示其如何重构软件开发范…...
EdgeInfinite: 用3B模型处理无限长的上下文
论文标题 EdgeInfinite: A Memory-Efficient Infinite-Context Transformer for Edge Devices 论文地址 https://arxiv.org/pdf/2503.22196 作者背景 vivo,浙江大学 代码 The code will be released after the official audit. 动机 self-attention的二次时…...
大模型论文:Improving Language Understanding by Generative Pre-Training
大模型论文:Improving Language Understanding by Generative Pre-Training OpenAI2018 文章地址:https://www.mikecaptain.com/resources/pdf/GPT-1.pdf 摘要 自然语言理解包括各种各样的任务,如文本蕴涵、问题回答、语义相似性评估和文…...
springboot 项目怎样开启https服务
要在Spring Boot项目中启用HTTPS服务,请按照以下步骤操作: 1. 生成SSL证书密钥库 使用keytool生成自签名证书 在终端或命令行工具中运行以下命令,生成一个PKCS12格式的密钥库文件: keytool -genkeypair -alias myapp -keyalg …...
R语言之mlr依赖包缺失警告之分析
因为本地没有网络,所有相关的依赖包都是手动下载,再使用脚本一键安装的。 在使用mlr包时,执行下面的代码时,总是报各种依赖缺失,也不知道咋看FAIL信息。 # 建模与调参 # 查阅线性回归、随机森林、xgboost和KNN四种模…...
如何记录日常笔记
关于用Obsidian记日常笔记这事儿,我的经验是别想得太复杂。刚开始用的时候总想着要搞个完美的分类系统,后来发现简单粗暴反而最实用。 文件夹分两类就够了——比如「工作记录」扔一个文件夹,「读书笔记」扔另一个,别分太细&#…...
Completablefuture的底层原理是什么
参考面试回答: 个人理解 CompletableFuture 是 Java 8 引入的一个类、它可以让我们在多线程环境中更加容易地处理异步任务。CompletableFuture 的底层原理是基于一个名为 FutureTask 的机制、结合了 监听器模式 和 等待-通知机制 来处理异步计算。 1.首先就是Com…...
Linux学习笔记(1) 目录结构与路径描述:对比 Windows 系统差异(期末,期中复习笔记全)
前言 一、Linux 的目录结构 二、Linux 路径的描述方式 三、总结 前言 在计算机操作系统的领域中,Linux 和 Windows 是两大主流系统。它们在目录结构和路径描述方式上存在显著不同,理解这些差异对于熟练掌握 Linux 系统至关重要。 一、Linux 的目录结构…...
《算法笔记》10.3小节——图算法专题->图的遍历 问题 A: 第一题
题目描述 该题的目的是要你统计图的连通分支数。 输入 每个输入文件包含若干行,每行两个整数i,j,表示节点i和j之间存在一条边。 输出 输出每个图的联通分支数。 样例输入 1 4 4 3 5 5样例输出 2 分析: 由于题目没给出范围࿰…...
【docker】
1.构建jar包 2.构建自定义的镜像dockerfile vim Dockerfile # 使用 OpenJDK 17 作为基础镜像,该镜像包含 JDK 17 环境 # 该镜像适用于需要编译或运行基于 JDK 17 的 Java 应用程序FROM openjdk:8-jdk-alpine# 设置容器中的工作目录为 /app # 所有后续操作…...
深度学习总结(1)
初识神经网络(helloworld) 要解决的问题是,将手写数字的灰度图像(28像素28像素)划分到10个类别中(从0到9)。我们将使用MNIST数据集。 在机器学习中,分类问题中的某个类别叫作类(class),数据点叫作样本(sample),与某个样本对应的类叫作标签(label)。…...
Java面试38-Dubbo是如何动态感知服务下线的?
首先,Dubbo默认采用Zookeeper实现服务注册与服务发现,就是多个Dubbo服务之间的通信地址,是使用Zookeeper来维护的。在Zookeeper上,会采用树形结构的方式来维护Dubbo服务提供端的协议地址,Dubbo服务消费端会从Zookeeper…...
企业数据分析何时该放弃Excel?
在企业数据分析中,Excel 的适用数据量范围取决于 数据复杂度、计算需求 和 硬件性能: 一、Excel 适合处理的数据量范围 数据规模适用场景限制与风险≤10万行- 日常报表 - 简单数据透视表 - 基础公式计算(如SUMIFS、VLOOKUP)处理流畅,无明显性能问题10万~50万行- 较复杂分析…...
单片机实现触摸按钮执行自定义任务组件
触摸按钮执行自定义任务组件 项目简介 本项目基于RT8H8K001开发板 RT6809CNN01开发板 TFT显示屏(1024x600) GT911触摸屏实现了一个多功能触摸按钮组件。系统具备按钮控制后执行任务的功能,可用于各类触摸屏人机交互场景。 硬件平台 MCU: STC8H8K64U࿰…...
深度学习与神经网络 | 邱锡鹏 | 第四章学习笔记 神经网络
四、神经网络 文章目录 四、神经网络4.1 神经元4.2 神经网络4.3 前馈神经网络4.4 反向传播算法4.5 计算图与自动微分4.6 优化问题 4.1 神经元 w表示每一维(其他神经元)的权重,b可以用来调控阈值,z 经过激活函数得到最后的值a来判…...
去产能、去库存、去杠杆、降成本、补短板的智慧工业开源了。
智慧工业视觉监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒,省去繁琐重复的适配流程,实现芯片、算法、应用的全流程组合,从而大大减少企业级应用约95%的开发成本。用户只需在界面上…...
【嵌入式系统设计师】知识点:第4章 嵌入式系统软件基础知识
提示:“软考通关秘籍” 专栏围绕软考展开,全面涵盖了如嵌入式系统设计师、数据库系统工程师、信息系统管理工程师等多个软考方向的知识点。从计算机体系结构、存储系统等基础知识,到程序语言概述、算法、数据库技术(包括关系数据库、非关系型数据库、SQL 语言、数据仓库等)…...
Scala基础知识
数组 不可变数组 第一种方式定义数组 定义:val arr1 new Array[Int](10) (1)new 是关键字 (2)[Int]是指定可以存放的数据类型,如果希望存放任意数据类型,则指定Any (3&#x…...
scala课后总结(7)
不可变数组与可变数组的转换 arr1.toBuffer :将不可变数组 arr1 转换为可变数组,原 arr1 不变,返回新的可变数组 。 arr2.toArray :把可变数组 arr2 转为不可变数组, arr2 本身不变,返回新的不可…...
【T2I】MIGC: Multi-Instance Generation Controller for Text-to-Image Synthesis
code:CVPR 2024 MIGC: Multi-Instance Generation Controller for Text-to-Image Synthesis [CVPR 2024] MIGC: Multi-Instance Generation Controller for Text-to-Image Synthesis - 知乎 Abstract 我们提出了一个多实例生成(Multi-Instance Generation, MIG)任务…...
MyBatis的第三天笔记
4. MyBatis核心配置文件详解 4.1 配置文件结构 MyBatis核心配置文件采用XML格式,主要用于配置数据库连接、事务管理、映射文件等信息。以下是一个基本的配置文件示例: <?xml version"1.0" encoding"UTF-8" ?> <!DOCTY…...
03_docker 部署 nginx 配置 HTTPS 并转发请求到后端服务
03_Docker 部署 Nginx 配置 HTTPS 并转发请求到后端服务 一、在 Docker 内部署 Nginx 拉取 Nginx 镜像 docker pull nginx:1.19.4 //如果能直接拉取使用这个命令 docker pull docker.xuanyuan.me/nginx:1.19.4 //不能直接拉取需要在前面加上镜像地址拉取成功后,创建…...
位运算题目:N 天后的牢房
文章目录 题目标题和出处难度题目描述要求示例数据范围 解法思路和算法代码复杂度分析 题目 标题和出处 标题:N 天后的牢房 出处:957. N 天后的牢房 难度 5 级 题目描述 要求 8 \texttt{8} 8 间牢房排成一排,每间牢房的状态是被占用或…...
OceanBase V4.3.5 上线全文索引功能,让数据检索更高效
近日,OceanBase 4.3.5 BP1 版本正式推出了企业级全文索引功能。该版本在中文分词、查询效率及混合检索能力上进行了全面提升。经过自然语言模式和布尔模式在不同场景下的对比测试,OceanBase 的全文索引性能明显优于 MySQL。 点击下载 OceanBase 社区版…...
【MySQL 数据库】数据表的操作
🔥博客主页🔥:【 坊钰_CSDN博客 】 欢迎各位点赞👍评论✍收藏⭐ 目录 1. 表的查看 1.1 语法 2. 表的创建 2.1 语法 2.2 练习 3. 查看表结构 3.1 语法 3.2 示例 4. 表的修改 4.1 语法 4.2 示例操作 4.2.1 向表中添加字段…...
(三十七)Dart 中使用 Pub 包管理系统与 HTTP 请求教程
Dart 中使用 Pub 包管理系统与 HTTP 请求教程 Pub 包管理系统简介 Pub 是 Dart 和 Flutter 的包管理系统,用于管理项目的依赖。通过 Pub,开发者可以轻松地添加、更新和管理第三方库。 使用 Pub 包管理系统 1. 找到需要的库 访问以下网址,…...
几款开源网盘的比较
开源网盘 1. Nextcloud2. Seafile3. ownCloud4. Syncthing5. FileBrowser6. Z-File7. kiftd总结对比推荐选择 1. Nextcloud 开发语言:PHP (后端) JavaScript (前端) 官网:https://nextcloud.com/ 特点: 功能全面(文件同步、共享…...
python中的in关键字查找的时间复杂度
列表(List) 对于列表来说, in 运算符的复杂度是 O(n),其中n是列表的长度。这意味着如果列表中有n个元素,那么执行 in 运算符需要遍历整个列表来查找目标元素。 以下是一个示例,演示了在列表中使用 in 运算…...
Windows注册鼠标钩子,获取用户选中的文本
注册鼠标钩子 // 注册鼠标钩子 HHOOK hMouseHook; hMouseHook SetWindowsHookEx(WH_MOUSE_LL, MouseProc, GetModuleHandle(NULL), 0);// 取消鼠标钩子 UnhookWindowsHookEx(hMouseHook); hMouseHook nullptr; 上述代码中MouseProc方法用于处理系统的鼠标消息 处理鼠标消息…...
UE5 蓝图里的反射
蓝图支持使用名字调用函数 使用SetTimerByFunctionName节点即可,该节点是指延后多少时间调用函数,注意时间不能是0也不能是负数,否者不会执行...
私有化视频会议系统,业务沟通协作安全不断线
BeeWorks Meet视频会议平台具备丰富而强大的功能,能够满足企业多样化的业务场景需求。其会议管理功能,让企业能够轻松安排和管理各类会议。 从创建会议、设置会议时间、邀请参会人员到会议提醒,一应俱全,确保会议的顺利进行。多人…...
大数据学习(100)-kafka详解
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言📝支持一…...
unittest测试模块:Python 标准库中的单元测试利器
在当今的软件开发中,测试的必要性不言而喻。为了确保代码的质量和稳定性,开发者需要一种高效的方式去编写和运行单元测试。Python 提供了一个强大的工具——unittest。这是一个标准库模块,专为编写和运行测试而设计,帮助开发者减少…...
java后端对时间进行格式处理
时间格式处理 通过java后端,使用jackson库的注解JsonFormat(pattern "yyyy-MM-dd HH:mm:ss")进行格式化 package com.weiyu.pojo;import com.fasterxml.jackson.annotation.JsonFormat; import lombok.AllArgsConstructor; import lombok.Data; import …...
Spring的简单介绍
Spring的简单介绍 Spring 是一个开源的 Java 企业级应用开发框架,旨在简化企业应用的开发过程。它通过提供全面的基础设施支持,帮助开发人员构建可靠的、高效的、可扩展的企业级应用程序。Spring 提供了多种功能模块,支持开发不同类型的应用…...
Python基础知识点(函数2)
#需求 打印stu_info def show_info(name,age): print(f"姓名:{name},年龄:{age}") #1.必要参数 在调用函数的时候必须传值 show_info("tom",3) #注意!对于形参,除了个数要匹配,顺序也要匹配 …...
MySQL的左连接、右连接、内连接、外连接
一、前言 MySQL中的左连接、右连接、内连接和全外连接是用于多表关联查询的核心操作。 二、内连接(INNER JOIN) 定义:返回两个表中完全匹配的行,即只保留两个表连接字段值相等的行。示例场景:查询所有有选课记录的学…...
Springboot JPA ShardingSphere 根据年分表
Spring Boot集成JPA与ShardingSphere实现按年分表,需重点关注分片算法选择、时间字段映射及动态表管理。以下是实现方案: 一、依赖配置 1. 核心依赖引入 <!-- ShardingSphere JDBC --> <dependency><groupId>org.apache.shardi…...
巧记英语四级单词 Unit1-3【晓艳老师版】
light 光,轻的、 grant v.准予,承认 gr官人,ant蚂蚁,外面下着大雨,官人让蚂蚁进来了grind v.摩擦,磨碎 官人在里面的 磨刀,准备找法海给白娘子报仇slight v.稍微的,有点的 light 光…...
Flink 任务调度机制
一、Task 任务调度执行流程 一、Graph 的概念 Flink 中的执行图可以分为四层:StreamGraph -> JobGraph -> ExecutionGraph -> 物理执行图。 StreamGraph:执行用户代码中的 env.execute() 方法后,根据用户通过 Stream API 编写的代码生成的最初的图。用来表示程序的…...
设计模式之享元模式
1. 概念 享元模式(Flyweight Pattern), 运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。 在享元模式中可以共享的相同内容称为内部状态(Intrinsic State)&…...
设计模式 - 策略模式Strategy
设计思想: 策略模式的就是定义一系列算法,将他们一个个封装起来,并且使它们可以相互替换,通常我们的代码中出现大量的if...else...或者switch语句时,我们都可以使用策略模式来优化代码 典型场景: 支付系…...
23种设计模式-行为型模式-策略
文章目录 简介场景解决代码关键实现细节 总结 简介 策略是一种行为设计模式,它能让你定义一系列算法,并将每种算法分别放入独立的类中,以使算法对象能够被替换。 场景 你在开发一款导航应用,类似高德。你要实现自动路线规划的功…...
Ubuntu16.04配置远程连接
配置静态IP Ubuntu16.04 修改超管账户默认密码 # 修改root账户默认密码 sudo passwd Ubuntu16.04安装SSH # 安装ssh服务: sudo apt-get install ssh# 启动SSH服务: sudo /etc/init.d/ssh start # 开机自启 sudo systemctl enable ssh# 如无法连接&…...
window部署虚拟机VirtualBox来部署flink
window通过Cygwin部署flink-1.15.0失败 按理来说Cygwin可以在window模拟unix环境来部署运行flink, 但是在flink 不知从哪个版本开始,flink启动时会在window时创建临时文件夹,传递的文件夹名称参数中有冒号,导致文件夹创建失败&a…...
mac 卸载流氓软件安全助手
之前个人电脑在公司使用过一段时间,为了使用网线联网安装了公司指定的 联软上网助手,谁知安装容易卸载难,后来找运维来卸载,输入管理员密码后,也无反应,最后不了了之了,这个毒瘤软件长期在后台驻…...