第 2 章 线性表 (线性表的单链表存储结构实现)

1. 背景说明

 

2. 示例代码 

1) status.h

/* DataStructure 预定义常量和类型头文件 */#ifndef STATUS_H
#define STATUS_H#define CHECK_NULL(pointer) if (!(pointer)) { \printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_NULL_PTR); \return NULL; \
}#define CHECK_RET(ret) if (ret != RET_OK) { \printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ret); \return ret; \
}#define CHECK_VALUE(value, ERR_CODE) if (value) { \printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_CODE); \return ERR_CODE; \
}#define CHECK_FALSE(value, ERR_CODE) if (!(value)) { \printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_CODE); \return FALSE; \
} /* 函数结果状态码 */
#define TRUE 					1			/* 返回值为真 */
#define FALSE 					0			/* 返回值为假 */
#define RET_OK 					0			/* 返回值正确 */
#define INFEASIABLE    		   	2			/* 返回值未知 */
#define ERR_MEMORY     		   	3			/* 访问内存错 */
#define ERR_NULL_PTR   			4			/* 空指针错误 */
#define ERR_MEMORY_ALLOCATE		5			/* 内存分配错 */
#define ERR_NULL_STACK			6			/* 栈元素为空 */
#define ERR_PARA				7			/* 函数参数错 */
#define ERR_OPEN_FILE			8			/* 打开文件错 */
#define ERR_NULL_QUEUE			9			/* 队列为空错 */
#define ERR_FULL_QUEUE			10			/* 队列为满错 */
#define ERR_NOT_FOUND			11			/* 表项不存在 */
typedef int Status;							/* Status 是函数的类型,其值是函数结果状态代码,如 RET_OK 等 */
typedef int Bollean;						/* Boolean 是布尔类型,其值是 TRUE 或 FALSE */#endif // !STATUS_H

2) singleLinkList.h

/* 线性表的单链表存储结构头文件 */#ifndef SINGLELINKLIST_H
#define SINGLELINKLIST_H#include "status.h"typedef int ElemType;typedef struct LNode {ElemType data;struct LNode *next;
} *LinkList;/* 辅助函数,创建一个新的节点 */
LinkList MakeNewLNode(ElemType e);/* 操作结果:构造一个空的线性表 L */
Status InitList(LinkList *L);/* 初始条件:线性表 L 已存在。操作结果:销毁线性表 L */
Status DestroyList(LinkList *L);/* 初始条件:线性表 L 已存在。操作结果:将 L 重置为空表 */
Status ClearList(LinkList L);/* 初始条件:线性表 L 已存在。操作结果:若 L 为空表,则返回 TRUE,否则返回 FALSE */
Status ListEmpty(LinkList L);/* 初始条件:线性表 L 已存在。操作结果:返回 L 中数据元素个数 */
int ListLength(LinkList L);/* 算法 2.8,L 为带头结点的单链表的头指针。当第 i 个元素存在时, 其值赋给 e 并返回 OK,否则返回 ERROR */
Status GetElem(LinkList L, int i, ElemType *e);/* 初始条件: 线性表 L 已存在, compare() 是数据元素判定函数(满足为 1,否则为 0)操作结果: 返回 L 中第 1 个与 e 满足关系 compare() 的数据元素的位序。若这样的数据元素不存在,则返回值为 0 */
int LocateElem(LinkList L, ElemType e, Bollean(*compare)(ElemType, ElemType));/* 初始条件: 线性表 L 已存在操作结果: 若 cur_e 是 L 的数据元素,且不是第一个,则用 pre_e 返回它的前驱函数返回 OK;否则操作失败, pre_e 无定义, 返回 INFEASIBLE */
Status PriorElem(LinkList L, ElemType cur_e, ElemType *pre_e);/* 初始条件:线性表 L 已存在操作结果:若 cur_e 是 L 的数据元素,且不是最后一个,则用 next_e 返回它的后继函数返回 OK;否则操作失败,next_e无定义,返回 INFEASIBLE */
Status NextElem(LinkList L, ElemType cur_e, ElemType *next_e);/* 算法 2.9,在带头结点的单链线性表 L 中第 i 个位置之前插入元素 e */
Status ListInsert(LinkList L, int i, ElemType e);/* 算法 2.10,在带头结点的单链线性表 L 中,删除第 i 个元素,并由 e 返回其值 */
Status ListDelete(LinkList L, int i, ElemType *e);/* 初始条件:线性表 L 已存在操作结果:依次对 L 的每个数据元素调用函数 vi()。一旦 vi() 失败,则操作失败 */
Status ListTraverse(LinkList L, void(*vi)(ElemType));/* 初始条件:按非降序排列的线性表 L 已存在操作结果:在 L 中按非降序插入新的数据元素 e */
Status InsertAscend(LinkList L, ElemType e);/* 初始条件:按非升序排列的线性表 L 已存在操作结果:在 L 中按非升序插入新的数据元素 e */
Status InsertDescend(LinkList L, ElemType e);/* 初始条件:线性表 L 已存在操作结果:在 L 的头部插入新的数据元素 e, 作为链表的第一个元素 */
Status HeadInsert(LinkList L, ElemType e);/* 初始条件:线性表 L 已存在操作结果:在 L 的尾部插入新的数据元素 e, 作为链表的最后一个元素 */
Status EndInsert(LinkList L, ElemType e);/* 初始条件:线性表 L 已存在,且有不少于 1 个元素操作结果:删除 L 的第一个数据元素,并由 e 返回其值 */
Status DeleteFirst(LinkList L, ElemType *e);/* 初始条件:线性表 L 已存在,且有不少于 1 个元素操作结果:删除 L 的最后一个数据元素,并用 e 返回其值 */
Status DeleteTail(LinkList L, ElemType *e);/* 删除表中值为 e 的元素,并返回 TRUE;如无此元素,则返回 FALSE */
Status DeleteElem(LinkList L, ElemType e);/* 用 e 取代表 L 中第 i 个元素的值 */
Status RePlaceElem(LinkList L, int i, ElemType e);/* 按非降序建立 n 个元素的线性表 */
Status CreateAscend(LinkList *L, int n);/* 按非升序建立 n 个元素的线性表 */
Status CreateDescend(LinkList *L, int n);/* 返回表头元素的值 */
Status GetFirstElem(LinkList L, ElemType *e);#endif

3) singleLinkList.c

/* 线性表的单链表存储结构源文件实现 */#include "singleLinkList.h"
#include <stdlib.h>
#include <stdio.h>/* 辅助函数,创建一个新的节点 */
LinkList MakeNewLNode(ElemType e)
{LinkList newLNode = (LinkList)malloc(sizeof(struct LNode));CHECK_NULL(newLNode)newLNode->data = e;newLNode->next = NULL;return newLNode;
}/* 操作结果:构造一个空的线性表 L */
Status InitList(LinkList *L)
{*L = (LinkList)malloc(sizeof(struct LNode));CHECK_VALUE(!(*L), ERR_MEMORY_ALLOCATE)(*L)->next = NULL;return RET_OK;
}/* 初始条件:线性表 L 已存在。操作结果:销毁线性表 L */
Status DestroyList(LinkList *L)
{LinkList q;while (*L) {q = (*L)->next;free(*L);*L = q;}return RET_OK;
}/* 初始条件:线性表 L 已存在。操作结果:将 L 重置为空表 */
Status ClearList(LinkList L)
{LinkList p, q;p = L->next;while (p) {q = p->next;free(p);p = q;}L->next = NULL;return RET_OK;
}/* 初始条件:线性表 L 已存在。操作结果:若 L 为空表,则返回 TRUE,否则返回 FALSE */
Status ListEmpty(LinkList L)
{return (L->next == NULL) ? TRUE : FALSE;
}/* 初始条件:线性表 L 已存在。操作结果:返回 L 中数据元素个数 */
int ListLength(LinkList L)
{int count = 0;LinkList p = L->next;while (p) {++count;p = p->next;}return count;
}/* 算法 2.8,L 为带头结点的单链表的头指针。当第 i 个元素存在时, 其值赋给 e 并返回 RET_OK,否则返回 ERROR */
Status GetElem(LinkList L, int i, ElemType *e)
{int j = 1;LinkList p = L->next;while (p && j < i) {p = p->next;++j;}CHECK_VALUE((!p || j > i), ERR_PARA)		/* j > i 适用于 i < 1 时,如 i = 0 */*e = p->data;return RET_OK;
}/* 初始条件: 线性表 L 已存在, compare() 是数据元素判定函数(满足为 1,否则为 0)操作结果: 返回 L 中第 1 个与 e 满足关系 compare() 的数据元素的位序。若这样的数据元素不存在,则返回值为 0 */
int LocateElem(LinkList L, ElemType e, Bollean(*compare)(ElemType, ElemType))
{int i = 0;LinkList p = L->next;while (p) {++i;if (compare(p->data, e)) {return i;}p = p->next;}return 0;
}/* 初始条件: 线性表 L 已存在操作结果: 若 cur_e 是 L 的数据元素,且不是第一个,则用 pre_e 返回它的前驱函数返回 RET_OK;否则操作失败, pre_e 无定义, 返回 INFEASIBLE */
Status PriorElem(LinkList L, ElemType cur_e, ElemType *pre_e)
{LinkList q, p = L->next;while (p->next) {q = p->next;if (q->data == cur_e) {*pre_e = p->data;return RET_OK;}p = q;}return INFEASIABLE;
}/* 初始条件:线性表 L 已存在操作结果:若 cur_e 是 L 的数据元素,且不是最后一个,则用 next_e 返回它的后继函数返回 RET_OK;否则操作失败,next_e无定义,返回 INFEASIBLE */
Status NextElem(LinkList L, ElemType cur_e, ElemType *next_e)
{LinkList p = L->next;while (p->next) {if (p->data == cur_e) {*next_e = p->next->data;return RET_OK;}p = p->next;}return INFEASIABLE;
}/* 算法 2.9,在带头结点的单链线性表 L 中第 i 个位置之前插入元素 e */
Status ListInsert(LinkList L, int i, ElemType e)
{int j = 0;LinkList p = L;while (p && j < i - 1) {++j;p = p->next;}CHECK_VALUE((!p || j > i - 1), ERR_PARA)LinkList newLNode = MakeNewLNode(e);CHECK_VALUE(!newLNode, ERR_MEMORY_ALLOCATE)newLNode->next = p->next;p->next = newLNode;return RET_OK;
}/* 算法 2.10,在带头结点的单链线性表 L 中,删除第 i 个元素,并由 e 返回其值 */
Status ListDelete(LinkList L, int i, ElemType *e)
{int j = 0;LinkList p = L;while (p->next && j < i - 1) {++j;p = p->next;}CHECK_VALUE((!p || j > i - 1), ERR_PARA)LinkList q = p->next;p->next = q->next;*e = q->data;free(q);return RET_OK;
}/* 初始条件:线性表 L 已存在操作结果:依次对 L 的每个数据元素调用函数 vi()。一旦 vi() 失败,则操作失败 */
Status ListTraverse(LinkList L, void(*vi)(ElemType))
{LinkList p = L->next;while (p) {vi(p->data);p = p->next;}return RET_OK;
}/* 初始条件:按非降序排列的线性表 L 已存在操作结果:在 L 中按非降序插入新的数据元素 e */
Status InsertAscend(LinkList L, ElemType e)
{LinkList q = L, p = L->next;while ((p) && (e > p->data)) {q = p;p = p->next;}LinkList s = MakeNewLNode(e);q->next = s;s->next = p;return RET_OK;
}/* 初始条件:按非升序排列的线性表 L 已存在操作结果:在 L 中按非升序插入新的数据元素 e */
Status InsertDescend(LinkList L, ElemType e)
{LinkList q = L, p = L->next;while ((p) && (e < p->data)) {q = p;p = p->next;}LinkList s = MakeNewLNode(e);q->next = s;s->next = p;return RET_OK;
}/* 初始条件:线性表 L 已存在操作结果:在 L 的头部插入新的数据元素 e, 作为链表的第一个元素 */
Status HeadInsert(LinkList L, ElemType e)
{LinkList newLNode = MakeNewLNode(e);newLNode->next = L->next;L->next = newLNode;return RET_OK;
}/* 初始条件:线性表 L 已存在操作结果:在 L 的尾部插入新的数据元素 e, 作为链表的最后一个元素 */
Status EndInsert(LinkList L, ElemType e)
{LinkList p = L;while (p->next) {p = p->next;}LinkList newLNode = MakeNewLNode(e);p->next = newLNode;return RET_OK;
}/* 初始条件:线性表 L 已存在,且有不少于 1 个元素操作结果:删除 L 的第一个数据元素,并由 e 返回其值 */
Status DeleteFirst(LinkList L, ElemType *e)
{LinkList p = L->next;CHECK_VALUE(!p, ERR_NOT_FOUND)*e = p->data;L->next = p->next;free(p);return RET_OK;
}/* 初始条件:线性表 L 已存在,且有不少于 1 个元素操作结果:删除 L 的最后一个数据元素,并用 e 返回其值 */
Status DeleteTail(LinkList L, ElemType *e)
{LinkList p = L;CHECK_VALUE(!(p->next), ERR_NOT_FOUND)LinkList q = NULL;while (p->next) {q = p;p = p->next;}q->next = NULL;*e = p->data;free(p);return RET_OK;
}/* 删除表中值为 e 的元素,并返回 TRUE;如无此元素,则返回 FALSE */
Status DeleteElem(LinkList L, ElemType e)
{LinkList p = L, q;while (p) {q = p->next;if ((q) && (q->data == e)) {p->next = q->next;free(q);return TRUE;}p = q;}return FALSE;
}/* 用 e 取代表 L 中第 i 个元素的值 */
Status RePlaceElem(LinkList L, int i, ElemType e)
{LinkList p = L;int j = 0;while ((p->next) && (j < i)) {++j;p = p->next;}CHECK_VALUE(j != i, ERR_NOT_FOUND)p->data = e;return RET_OK;
}/* 按非降序建立 n 个元素的线性表 */
Status CreateAscend(LinkList *L, int n)
{CHECK_VALUE(n < 1, ERR_PARA)CHECK_VALUE(!L, ERR_NULL_PTR)InitList(L);printf("Please input %d elements: ", n);ElemType e;scanf_s("%d", &e);LinkList newLNode = MakeNewLNode(e);(*L)->next = newLNode;for (int i = 0; i < n - 1; ++i) {scanf_s("%d", &e);LinkList newLNode = MakeNewLNode(e);LinkList q = *L;LinkList p = (*L)->next;while ((p) && (p->data < e)) {q = p;p = p->next;}newLNode->next = q->next;q->next = newLNode;}return RET_OK;
}/* 按非升序建立 n 个元素的线性表 */
Status CreateDescend(LinkList *L, int n)
{CHECK_VALUE(n < 1, ERR_PARA)CHECK_VALUE(!L, ERR_NULL_PTR)InitList(L);printf("Please input %d elements: ", n);ElemType e;scanf_s("%d", &e);LinkList newLNode = MakeNewLNode(e);(*L)->next = newLNode;for (int i = 0; i < n - 1; ++i) {scanf_s("%d", &e);LinkList newLNode = MakeNewLNode(e);LinkList q = *L;LinkList p = (*L)->next;while ((p) && (p->data > e)) {q = p;p = p->next;}newLNode->next = q->next;q->next = newLNode;}return RET_OK;
}/* 返回表头元素的值 */
Status GetFirstElem(LinkList L, ElemType *e)
{LinkList p = L->next;CHECK_VALUE(!p, ERR_NOT_FOUND)*e = p->data;return RET_OK;
}

4) algorithm.h

/* 算法定义头文件 */
#ifndef ALGORITHM_H
#define ALGORITHM_H#include "singleLinkList.h"/* 算法 2.11,逆位序(插在表头)输入 n 个元素的值,建立带表头结构的单链线性表 L */
void CreateList(LinkList *L, int n);/* 正位序(插在表尾)输入 n 个元素的值,建立带表头结构的单链线性表 */
void CreateList2(LinkList *L, int n);/* 算法 2.12,已知单链线性表 La 和 Lb 的元素按值非递减排列归并 La 和 Lb 得到新的单链线性表 Lc,Lc 的元素也按值非递减排列此处需要释放 Lb 头节点故需要传入 Lb 指针变量 */
void MergeList(LinkList La, LinkList *Lb, LinkList *Lc);/* 算法 2.1 其他实现,将所有在线性表 Lb 中但不在 La 中的数据元素插入到 La 中 */
void Union(LinkList La, LinkList Lb);/* 算法 2.2 其他实现,已知线性表 La 和 Lb 中的数据元素按值非递减排列归并 La 和 Lb 得到新的线性表 Lc,Lc 的数据元素也按值非递减排列 */
Status MergeList2(LinkList La, LinkList Lb, LinkList *Lc);#endif // !ALGORITHM_H

5) algorithm.c

/* 算法实现源文件 */
#include "algorithm.h"
#include "auxiliary.h"
#include <stdlib.h>
#include <stdio.h>/* 算法 2.11,逆位序(插在表头)输入 n 个元素的值,建立带表头结构的单链线性表 L */
void CreateList(LinkList *L, int n)
{(void)InitList(L);printf("Please input %d integers: ", n);int num;LinkList p;for (int i = 0; i < n; ++i) {scanf_s("%d", &num);p = MakeNewLNode(num);p->next = (*L)->next;(*L)->next = p;}
}/* 正位序(插在表尾)输入 n 个元素的值,建立带表头结构的单链线性表 */
void CreateList2(LinkList *L, int n)
{(void)InitList(L);LinkList q = *L, p;int num;printf("Please input %d integers: ", n);for (int i = 0; i < n; ++i) {scanf_s("%d", &num);p = MakeNewLNode(num);q->next = p;q = p;}
}/* 算法 2.12,已知单链线性表 La 和 Lb 的元素按值非递减排列归并 La 和 Lb 得到新的单链线性表 Lc,Lc 的元素也按值非递减排列 此处需要释放 Lb 头节点故需要传入 Lb 指针变量 */
void MergeList(LinkList La, LinkList *Lb, LinkList *Lc)
{LinkList pa = La->next, pb = (*Lb)->next, pc = NULL;*Lc = pc = La;while (pa && pb) {if (pa->data <= pb->data) {pc->next = pa;pc = pa;pa = pa->next;}else {pc->next = pb;pc = pb;pb = pb->next;}}pc->next = pa ? pa : pb;free(*Lb);
}/* 算法 2.1 其他实现,将所有在线性表 Lb 中但不在 La 中的数据元素插入到 La 中 */
void Union(LinkList La, LinkList Lb)
{int lengthLa = ListLength(La);int lengthLb = ListLength(Lb);ElemType e;for (int i = 0; i < lengthLb; ++i) {GetElem(Lb, i + 1, &e);if (!LocateElem(La, e, Equal)) {ListInsert(La, ++lengthLa, e);}}
}/* 算法 2.2 其他实现,已知线性表 La 和 Lb 中的数据元素按值非递减排列归并 La 和 Lb 得到新的线性表 Lc,Lc 的数据元素也按值非递减排列 */
Status MergeList2(LinkList La, LinkList Lb, LinkList *Lc)
{CHECK_VALUE(!Lc, ERR_NULL_PTR)InitList(Lc);int lengthLa = ListLength(La);int lengthLb = ListLength(Lb);ElemType ai, bj;int i = 1, j = 1, k = 0;while ((i <= lengthLa) && (j <= lengthLb)) {GetElem(La, i, &ai);GetElem(Lb, j, &bj);if (ai <= bj) {ListInsert(*Lc, ++k, ai);++i;} else {ListInsert(*Lc, ++k, bj);++j;}}while (i <= lengthLa) {GetElem(La, i++, &ai);ListInsert(*Lc, ++k, ai);}while (j <= lengthLb) {GetElem(Lb, j++, &bj);ListInsert(*Lc, ++k, bj);}return RET_OK;
}

6) auxiliary.h

/* 辅助函数定义头文件 */#ifndef AUXILIARY_H
#define AUXILIARY_H
#include "singleLinkList.h"void Visit(ElemType e);
Bollean Equal(ElemType e1, ElemType e2);
void ShowList(char str[], LinkList L);#endif // !AUXILIARY_H

7) auxiliary.c

/* 辅助函数实现源文件 */#include "auxiliary.h"
#include <stdio.h>void Visit(ElemType e)
{printf("%d ", e);
}Bollean Equal(ElemType e1, ElemType e2)
{return (e1 == e2) ? TRUE : FALSE;
}void ShowList(char str[], LinkList L)
{printf("%s", str);ListTraverse(L, Visit);putchar('\n');
}

8) main.c

/* 主函数入口源文件 */
#include "singleLinkList.h"
#include "algorithm.h"
#include "auxiliary.h"
#include <stdio.h>int main(void)
{int n = 5;LinkList La;CreateList(&La, n);ShowList("La is: ", La);LinkList Lb;CreateList2(&Lb, n);ShowList("Lb is: ", Lb);LinkList Lc;MergeList(La, &Lb, &Lc);ShowList("Lc is: ", Lc);int ret = DestroyList(&Lc);CHECK_RET(ret);/* free() 的作用:仅仅是释放堆内存,不将指针置空 */printf("After Destroy list Lc, the address of Lc is %p\n", Lc);/* 算法 2.1 其他实现测试 */LinkList LA, LB;CreateList2(&LA, 5);CreateList2(&LB, 5);ShowList("LA is: ", LA);ShowList("LB is: ", LB);Union(LA, LB);ShowList("LA is: ", LA);ShowList("LB is: ", LB);DestroyList(&LA);DestroyList(&LB);/* 算法 2.2 其他实现测试 */LinkList Lm, Ln;CreateList2(&Lm, 5);CreateList2(&Ln, 5);ShowList("Lm is: ", Lm);ShowList("Ln is: ", Ln);LinkList Lu;MergeList2(Lm, Ln, &Lu);ShowList("Lu is: ", Lu);DestroyList(&Lm);DestroyList(&Ln);DestroyList(&Lu);/* 测试其他 */LinkList L;printf("Please input the element num of L for create ascend: ");int num;scanf_s("%d", &num);CreateAscend(&L, num);ShowList("L is: ", L);InsertAscend(L, 10);printf("After insert 10 for ascend, ");ShowList("L is: ", L);HeadInsert(L, 12);EndInsert(L, 9);printf("After insert 12 in the head of L, insert 9 in the tail of L, ");ShowList("L is: ", L);ElemType e;printf("Please input the element to be delete: ");scanf_s("%d", &e);printf("delete %d %s\n", e, (DeleteElem(L, e) == TRUE) ? "success" : "failed");ShowList("L is: ", L);printf("Please input the order of the element to be replace and the new value: ");scanf_s("%d%d", &num, &e);RePlaceElem(L, num, e);ShowList("L is: ", L);DestroyList(&L);printf("Create L for descend, please input the num of L: ");scanf_s("%d", &num);CreateDescend(&L, num);ShowList("L is: ", L);InsertDescend(L, 10);printf("After insert 10 in L for descend, ");ShowList("L is: ", L);printf("Please input the element to be delete: ");scanf_s("%d", &e);printf("delete %d %s\n", e, (DeleteElem(L, e) == TRUE) ? "success" : "failed");ShowList("L is: ", L);ElemType e2;DeleteFirst(L, &e);DeleteTail(L, &e2);printf("After delete head element %d and tail element %d, ", e, e2);ShowList("L is: ", L);DestroyList(&L);return 0;
}

3. 运行示例

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

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

相关文章

Zebec 生态 AMA 回顾:Nautilus 以及 $ZBC 的未来

在 9 月 7 日&#xff0c;Zebec 创始人 Sam 做客社区&#xff0c;并进行了“Nautilus Chain 以及 $ZBC 的未来”主题的 AMA 访谈。Sam 在本次访谈中对 Nautilus Chain 生态的价值捕获、Zebec 生态布局规划、可能会推出的 Nautilus Chain 治理通证 NAUT 进行了解读。本文将对本次…

GCP之Google Cloud Infrastructure

Google Cloud 的物理网络是如何连接的&#xff1f; Google Cloud 分为 regions&#xff0c;regions 又分为 zones。 region 是一个地理区域&#xff0c;其中一个 VM 到另一个 VM 的往返时间 &#xff08;RTT&#xff09; 通常小于 1毫秒&#xff1b;zone 是 region 中的部署区…

mac+alfred中的Workflow实现快速格式化nginx配置

在好多编辑软件中我发现很少有关于格式化nginx配置的功能&#xff0c;然而&#xff0c;Nginx配置文件通常很复杂&#xff0c;手动格式化它们可能会变得繁琐和耗时。在本文中&#xff0c;我们将介绍如何使用Alfred Workflow在macOS上快速格式化Nginx配置文件&#xff0c;提高配置…

比ChatGPT更厉害的AutoGPT,GitHub 星标 149K,一个自主人工智能横空出世

比ChatGPT更厉害的AutoGPT&#xff0c;GitHub 星标 83.6K&#xff0c;一个自主人工智能横空出世。 最近 AI 界貌似出现了一种新的趋势&#xff1a;自主人工智能。 这不是空穴来风&#xff0c;最近一个名为 AutoGPT 的研究开始走进大众视野。特斯拉前 AI 总监、刚刚回归 Open…

【Redis专题】大厂生产级Redis高并发分布式锁实战

目录 前言课程内容一、一个案例引发的思考二、Redis分布式锁的演进2.1 单纯使用Redis的setnx实现分布式锁2.2 setnx 过期时间3.3 Redisson实现分布式锁&#xff1a;setnx 过期时间 锁续命 三、Redisson客户端实现的分布式锁源码分析4.1 RedissonLock#lock()&#xff1a;加锁…

AI系统论文阅读:SmartMoE

提出稀疏架构是为了打破具有密集架构的DNN模型中模型大小和计算成本之间的连贯关系的——最著名的MoE。 MoE模型将传统训练模型中的layer换成了多个expert sub-networks&#xff0c;对每个输入&#xff0c;都有一层special gating network 来将其分配到最适合它的expert中&…

EOCR-3DM2、FDM2电动机保护器的报警方式选择

施耐德EOCR-3DM2/FDM2电动机保护器具有预报警功能&#xff0c;可在电动机电流将要达到过载值时给出开关信号&#xff0c;及时的提醒运行人员注意电机状态。该功能具备多种的输出状态&#xff0c;具体如下: 报警方式&#xff1a; 设置方法 首先设置报警负荷率&#xff0c;在正…

数据通信网络之IPv6以太网多层交换

文章及资源归档至【AIShareLab】&#xff0c;回复 通信系统与网络 可获取。 文章目录 一、目的二、环境及网络拓扑三、需求四、步骤 一、目的 掌握 VLAN 的基础配置。掌握 Trunk 的基础配置。掌握 VLANIF 的基础配置&#xff0c;并理解通过三层交换机实现 VLAN 之间通信的方案…

java基础-基础知识点

文章目录 jdk目录结构函数式接口wait、notify、notifyAll 并发编程Threadsleep、yield、joindaemon &#xff08;守护线程&#xff09; 锁[synchronized ](https://blog.csdn.net/EnjoyFight/article/details/127457876)线程池 jdk目录结构 jdk1.8 jdk20 函数式接口 http…

2023 年前端编程 NodeJs 包管理工具 npm 安装和使用详细介绍

npm 基本概述 npm is the world’s largest software registry. Open source developers from every continent use npm to share and borrow packages, and many organizations use npm to manage private development as well. npm 官方网站&#xff1a;https://www.npmjs.…

HBase 记录

HBase 管理命令 hbase hbck -details TABLE_NAME hbase hbck -repair TABLE_NAMEHBase概览 Master、RegionServer作用 RegionServer与Region关系 数据定位原理 https://blogs.apache.org/hbase/entry/hbase_who_needs_a_master RegionServer HBase Essentials.pdf (P25)…

第二证券:举牌和收购有什么区别?

在股市中&#xff0c;举牌和收买是两种常见的出资策略。虽然这两种策略都是用来取得股权控制权&#xff0c;但举牌和收买仍是有着一些差异&#xff0c;下面从多个角度进行剖析。 一、定义和方法 从定义上来看&#xff0c;举牌是指出资者购买公司股票的数量已到达公司股份总量的…