数据结构【第3章】——线性表
线性表的定义
线性表:零个或多个数据元素的有限序列。
1)线性表是一个序列。即元素之间是有顺序的,若元素存在多个,则第一个元素无前驱,最后一个元素无后继,其他每个元素都有且只有一个前驱和后继。
2)线性表强调是有限的,元素个数也是有限的。事实上,在计算机中处理的对象都是有限的,那么无限的数列,只存在于数学的概念中。
注意:位序是从1开始的。
在较复杂的线性表中一个数据元素可以由若干个数据项组成。
线性表的抽象数据类型
注:
当你传递一个参数给函数的时候,这个参数是否在函数内被改动决定了使用什么参数形式。
1)如果需要被改动,则需要传递指向这个参数的指针。
2)如果不用被改动,可以会直接传递这个参数。
线性表的顺序存储结构
线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素。
线性表的每个数据元素的类型都相同,可以使用C语言的一维数组来实现顺序存储结构。
随着数据的插入,线性表的长度开始变大,不过线性表的当前长度不能超过存储容量,即数组的长度。
定义
#define MAXSIZE 20 /* 存储空间初始分配量 */
typedef int ElemType; /* ElemType类型根据实际情况而定,这里假设为int */
typedef struct
{ElemType data[MAXSIZE]; /* 数组,存储数据元素 */int length; /* 线性表当前长度 */
}SqList;
顺序存储结构需要3个属性:
1:存储空间的起始位置:数组data,它的存储位置就是存储空间的存储位置。
2:线性表的最大存储容量:数组长度MAXSIZE。
3:线性表的当前长度:length。
注1:区别数组长度和线性表长度
线性表的长度是线性表中数据元素的个数,随着线性表插入和删除操作的进行,这个量是变化的。
线性表的长度<=数组的长度。
注2:线性表的第i个元素是要存储在数组下标为i-1的位置上
存储器中的每个存储单元都有自己的编号,这个编号称为地址。
假设占用的是c个存储单元,那么线性表中第i+1个数据元素的存储位置和第i个数据元素的存储位置满足下列关系
(LOC表示获得存储位置的函数)。
通过上述公式,可以随时算出线性表中任意位置的地址,且都是相同的时间,因此它的存取时间性能为O(1),这类存储结构称为随机存取结构。
优缺点
优点:
- 无须为表示表中元素之间的逻辑关系而增加额外的存储空间
- 可以快速地存取表中任一位置的元素
缺点:
- 插入和删除操作需要移动大量元素
- 当线性表长度变化较大时,难以确定存储空间的容量
- 造成存储空间的“碎片”
代码
#include "stdio.h" #include "stdlib.h"
#include "math.h"
#include "time.h"#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0#define MAXSIZE 20 /* 存储空间初始分配量 */
typedef int ElemType; /* ElemType类型根据实际情况而定,这里假设为int */
typedef struct
{ElemType data[MAXSIZE]; /* 数组,存储数据元素 */int length; /* 线性表当前长度 */
}SqList;typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */Status visit(ElemType c)
{printf("%d ",c);return OK;
}/* 初始化顺序线性表 */
Status InitList(SqList *L)
{ L->length=0;return OK;
}/* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
Status ListEmpty(SqList L)
{ if(L.length==0)return TRUE;elsereturn FALSE;
}/* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
Status ClearList(SqList *L)
{ L->length=0;return OK;
}/* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 */
int ListLength(SqList L)
{return L.length;
}/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:用e返回L中第i个数据元素的值,注意i是指位置,第1个位置的数组是从0开始 */
Status GetElem(SqList L,int i,ElemType *e)
{if(L.length==0 || i<1 || i>L.length)return ERROR;*e=L.data[i-1];return OK;
}/* 初始条件:顺序线性表L已存在 */
/* 操作结果:返回L中第1个与e满足关系的数据元素的位序。 */
/* 若这样的数据元素不存在,则返回值为0 */
int LocateElem(SqList L,ElemType e)
{int i;if (L.length==0)return 0;for(i=0;i<L.length;i++){if (L.data[i]==e)break;}if(i>=L.length)return 0;return i+1;
}/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L), */
/* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */
Status ListInsert(SqList *L,int i,ElemType e)
{ int k;if (L->length==MAXSIZE) /* 顺序线性表已经满 */return ERROR;if (i<1 || i>L->length+1)/* 当i比第一位置小或者比最后一位置后一位置还要大时 */return ERROR;if (i<=L->length) /* 若插入数据位置不在表尾 */{for(k=L->length-1;k>=i-1;k--) /* 将要插入位置之后的数据元素向后移动一位 */L->data[k+1]=L->data[k];}L->data[i-1]=e; /* 将新元素插入 */L->length++;return OK;
}/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
Status ListDelete(SqList *L,int i,ElemType *e)
{ int k;if (L->length==0) /* 线性表为空 */return ERROR;if (i<1 || i>L->length) /* 删除位置不正确 */return ERROR;*e=L->data[i-1];if (i<L->length) /* 如果删除不是最后位置 */{for(k=i;k<L->length;k++)/* 将删除位置后继元素前移 */L->data[k-1]=L->data[k];}L->length--;return OK;
}/* 初始条件:顺序线性表L已存在 */
/* 操作结果:依次对L的每个数据元素输出 */
Status ListTraverse(SqList L)
{int i;for(i=0;i<L.length;i++)visit(L.data[i]);printf("\n");return OK;
}/*将所有的在线性表Lb中但不在La中的数据元素插入到La中*/
void unionL(SqList *La,SqList Lb)
{int La_len,Lb_len,i;ElemType e; /*声明与La和Lb相同的数据元素e*/La_len=ListLength(*La); /*求线性表的长度 */Lb_len=ListLength(Lb);for (i=1;i<=Lb_len;i++){GetElem(Lb,i,&e); /*取Lb中第i个数据元素赋给e*/if (!LocateElem(*La,e)) /*La中不存在和e相同数据元素*/ListInsert(La,++La_len,e); /*插入*/}
}int main()
{SqList L;SqList Lb;ElemType e;Status i;int j,k;i=InitList(&L);printf("初始化L后:L.length=%d\n",L.length);for(j=1;j<=5;j++)i=ListInsert(&L,1,j);printf("在L的表头依次插入1~5后:L.data=");ListTraverse(L); printf("L.length=%d \n",L.length);i=ListEmpty(L);printf("L是否空:i=%d(1:是 0:否)\n",i);i=ClearList(&L);printf("清空L后:L.length=%d\n",L.length);i=ListEmpty(L);printf("L是否空:i=%d(1:是 0:否)\n",i);for(j=1;j<=10;j++)ListInsert(&L,j,j);printf("在L的表尾依次插入1~10后:L.data=");ListTraverse(L); printf("L.length=%d \n",L.length);ListInsert(&L,1,0);printf("在L的表头插入0后:L.data=");ListTraverse(L); printf("L.length=%d \n",L.length);GetElem(L,5,&e);printf("第5个元素的值为:%d\n",e);for(j=3;j<=4;j++){k=LocateElem(L,j);if(k)printf("第%d个元素的值为%d\n",k,j);elseprintf("没有值为%d的元素\n",j);}k=ListLength(L); /* k为表长 */for(j=k+1;j>=k;j--){i=ListDelete(&L,j,&e); /* 删除第j个数据 */if(i==ERROR)printf("删除第%d个数据失败\n",j);elseprintf("删除第%d个的元素值为:%d\n",j,e);}printf("依次输出L的元素:");ListTraverse(L); j=5;ListDelete(&L,j,&e); /* 删除第5个数据 */printf("删除第%d个的元素值为:%d\n",j,e);printf("依次输出L的元素:");ListTraverse(L); //构造一个有10个数的Lbi=InitList(&Lb);for(j=6;j<=15;j++)i=ListInsert(&Lb,1,j);unionL(&L,Lb);printf("依次输出合并了Lb的L的元素:");ListTraverse(L); return 0;
}
线性表的链式存储结构
定义
我们把链表中第一个结点的存储位置叫做头指针。
线性链表的最后一个结点指针为“空”(通常用NULL或“^”符号表示)
有时,我们为了更加方便地对链表进行操作,会在单链表的第一个结点前附设一个结点,称为头结点。头结点的数据域可以不存储任何信息,也可以存储如线性表的长度等附加信息,头结点的指针域存储指向第—个结点的指针。
头结点与头指针的区别
代码
typedef struct Node
{ElemType data;struct Node *next;
}Node;
typedef struct Node *LinkList; /* 定义LinkList */
#include "stdio.h"
#include "string.h"
#include "ctype.h"
#include "stdlib.h" #include "math.h"
#include "time.h"#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0#define MAXSIZE 20 /* 存储空间初始分配量 */typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int ElemType;/* ElemType类型根据实际情况而定,这里假设为int */Status visit(ElemType c)
{printf("%d ",c);return OK;
}typedef struct Node
{ElemType data;struct Node *next;
}Node;
typedef struct Node *LinkList; /* 定义LinkList *//* 初始化链式线性表 */
Status InitList(LinkList *L)
{ *L=(LinkList)malloc(sizeof(Node)); /* 产生头结点,并使L指向此头结点 */if(!(*L)) /* 存储分配失败 */return ERROR;(*L)->next=NULL; /* 指针域为空 */return OK;
}/* 初始条件:链式线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
Status ListEmpty(LinkList L)
{ if(L->next)return FALSE;elsereturn TRUE;
}/* 初始条件:链式线性表L已存在。操作结果:将L重置为空表 */
Status ClearList(LinkList *L)
{ LinkList p,q;p=(*L)->next; /* p指向第一个结点 */while(p) /* 没到表尾 */{q=p->next;free(p);p=q;}(*L)->next=NULL; /* 头结点指针域为空 */return OK;
}/* 初始条件:链式线性表L已存在。操作结果:返回L中数据元素个数 */
int ListLength(LinkList L)
{int i=0;LinkList p=L->next; /* p指向第一个结点 */while(p) {i++;p=p->next;}return i;
}/* 初始条件:链式线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:用e返回L中第i个数据元素的值 */
Status GetElem(LinkList L,int i,ElemType *e)
{int j;LinkList p; /* 声明一结点p */p = L->next; /* 让p指向链表L的第一个结点 */j = 1; /* j为计数器 */while (p && j<i) /* p不为空或者计数器j还没有等于i时,循环继续 */{ p = p->next; /* 让p指向下一个结点 */++j;}if ( !p || j>i ) return ERROR; /* 第i个元素不存在 */*e = p->data; /* 取第i个元素的数据 */return OK;
}/* 初始条件:链式线性表L已存在 */
/* 操作结果:返回L中第1个与e满足关系的数据元素的位序。 */
/* 若这样的数据元素不存在,则返回值为0 */
int LocateElem(LinkList L,ElemType e)
{int i=0;LinkList p=L->next;while(p){i++;if(p->data==e) /* 找到这样的数据元素 */return i;p=p->next;}return 0;
}/* 初始条件:链式线性表L已存在,1≤i≤ListLength(L), */
/* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */
Status ListInsert(LinkList *L,int i,ElemType e)
{ int j;LinkList p,s;p = *L; j = 1;while (p && j < i) /* 寻找第i个结点 */{p = p->next;++j;} if (!p || j > i) return ERROR; /* 第i个元素不存在 */s = (LinkList)malloc(sizeof(Node)); /* 生成新结点(C语言标准函数) */s->data = e; s->next = p->next; /* 将p的后继结点赋值给s的后继 */p->next = s; /* 将s赋值给p的后继 */return OK;
}/* 初始条件:链式线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
Status ListDelete(LinkList *L,int i,ElemType *e)
{ int j;LinkList p,q;p = *L;j = 1;while (p->next && j < i) /* 遍历寻找第i个元素 */{p = p->next;++j;}if (!(p->next) || j > i) return ERROR; /* 第i个元素不存在 */q = p->next;p->next = q->next; /* 将q的后继赋值给p的后继 */*e = q->data; /* 将q结点中的数据给e */free(q); /* 让系统回收此结点,释放内存 */return OK;
}/* 初始条件:链式线性表L已存在 */
/* 操作结果:依次对L的每个数据元素输出 */
Status ListTraverse(LinkList L)
{LinkList p=L->next;while(p){visit(p->data);p=p->next;}printf("\n");return OK;
}/* 随机产生n个元素的值,建立带表头结点的单链线性表L(头插法) */
void CreateListHead(LinkList *L, int n)
{LinkList p;int i;srand(time(0)); /* 初始化随机数种子 */*L = (LinkList)malloc(sizeof(Node));(*L)->next = NULL; /* 先建立一个带头结点的单链表 */for (i=0; i<n; i++) {p = (LinkList)malloc(sizeof(Node)); /* 生成新结点 */p->data = rand()%100+1; /* 随机生成100以内的数字 */p->next = (*L)->next; (*L)->next = p; /* 插入到表头 */}
}/* 随机产生n个元素的值,建立带表头结点的单链线性表L(尾插法) */
void CreateListTail(LinkList *L, int n)
{LinkList p,r;int i;srand(time(0)); /* 初始化随机数种子 */*L = (LinkList)malloc(sizeof(Node)); /* L为整个线性表 */r=*L; /* r为指向尾部的结点 */for (i=0; i<n; i++) {p = (Node *)malloc(sizeof(Node)); /* 生成新结点 */p->data = rand()%100+1; /* 随机生成100以内的数字 */r->next=p; /* 将表尾终端结点的指针指向新结点 */r = p; /* 将当前的新结点定义为表尾终端结点 */}r->next = NULL; /* 表示当前链表结束 */
}int main()
{ LinkList L;ElemType e;Status i;int j,k;i=InitList(&L);printf("初始化L后:ListLength(L)=%d\n",ListLength(L));for(j=1;j<=5;j++)i=ListInsert(&L,1,j);printf("在L的表头依次插入1~5后:L.data=");ListTraverse(L); printf("ListLength(L)=%d \n",ListLength(L));i=ListEmpty(L);printf("L是否空:i=%d(1:是 0:否)\n",i);i=ClearList(&L);printf("清空L后:ListLength(L)=%d\n",ListLength(L));i=ListEmpty(L);printf("L是否空:i=%d(1:是 0:否)\n",i);for(j=1;j<=10;j++)ListInsert(&L,j,j);printf("在L的表尾依次插入1~10后:L.data=");ListTraverse(L); printf("ListLength(L)=%d \n",ListLength(L));ListInsert(&L,1,0);printf("在L的表头插入0后:L.data=");ListTraverse(L); printf("ListLength(L)=%d \n",ListLength(L));GetElem(L,5,&e);printf("第5个元素的值为:%d\n",e);for(j=3;j<=4;j++){k=LocateElem(L,j);if(k)printf("第%d个元素的值为%d\n",k,j);elseprintf("没有值为%d的元素\n",j);}k=ListLength(L); /* k为表长 */for(j=k+1;j>=k;j--){i=ListDelete(&L,j,&e); /* 删除第j个数据 */if(i==ERROR)printf("删除第%d个数据失败\n",j);elseprintf("删除第%d个的元素值为:%d\n",j,e);}printf("依次输出L的元素:");ListTraverse(L); j=5;ListDelete(&L,j,&e); /* 删除第5个数据 */printf("删除第%d个的元素值为:%d\n",j,e);printf("依次输出L的元素:");ListTraverse(L); i=ClearList(&L);printf("\n清空L后:ListLength(L)=%d\n",ListLength(L));CreateListHead(&L,20);printf("整体创建L的元素(头插法):");ListTraverse(L); i=ClearList(&L);printf("\n删除L后:ListLength(L)=%d\n",ListLength(L));CreateListTail(&L,20);printf("整体创建L的元素(尾插法):");ListTraverse(L); return 0;
}
注:
1)若线性表需要频繁查找,很少进行插入和删除操作时宣采用顺序存储结构。
2)当线性表中的元素个数变化较大或者根本不知道有多大时,最好用单链表结构。
静态链表
有些低级编程语言没有指针,于是人们用数组来代替指针描述单链表。
我们让数组的元素都是由两个数据域组成,data和cur。也就是说,数组的每个下标都对应一个data和一个cur。数据域data用来存放数据元素,也就是通常我们要处理的数据;而cur相当于单链表中的next指针,存放该元素的后继在数组中的下标,我们把cur叫做游标。
我们把这种用数组描述的链表叫做静态链表。
另外我们对数组第一个和最后—个元素作为特殊元素处理,不存数据。我们通常把未被使用的数组元素称为备用链表。而数组第一个元素,即下标为0的元素的cur就存放备用链表的第一个结点的下标;而数组的最后—个元素的cur则存放第一个有数值的元素的下标,相当于单链表中的头结点作用,当整个链表为空时,则为0。
插入节点
删除节点
优缺点
优点:
在插入和删除操作时,只需要修改游标,不需要移动元素,从而改进了在顺序存储结构中插入和删除操作需要移动大量元素的缺点。
缺点:
没有解决连续存储分配带来的表长难以确定的问题;
总的来说,链式链表其实是为了给没有指针的高级语言设计的一种实现单链表能力的方法。
代码
#include "string.h"
#include "ctype.h" #include "stdio.h"
#include "stdlib.h" #include "math.h"
#include "time.h"#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0#define MAXSIZE 1000 /* 存储空间初始分配量 */typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef char ElemType; /* ElemType类型根据实际情况而定,这里假设为char */Status visit(ElemType c)
{printf("%c ",c);return OK;
}/* 线性表的静态链表存储结构 */
typedef struct
{ElemType data;int cur; /* 游标(Cursor) ,为0时表示无指向 */
} Component,StaticLinkList[MAXSIZE];/* 将一维数组space中各分量链成一个备用链表,space[0].cur为头指针,"0"表示空指针 */
Status InitList(StaticLinkList space)
{int i;for (i=0; i<MAXSIZE-1; i++) space[i].cur = i+1;space[MAXSIZE-1].cur = 0; /* 目前静态链表为空,最后一个元素的cur为0 */return OK;
}/* 若备用空间链表非空,则返回分配的结点下标,否则返回0 */
int Malloc_SSL(StaticLinkList space)
{ int i = space[0].cur; /* 当前数组第一个元素的cur存的值 *//* 就是要返回的第一个备用空闲的下标 */if (space[0]. cur) space[0]. cur = space[i].cur; /* 由于要拿出一个分量来使用了, *//* 所以我们就得把它的下一个 *//* 分量用来做备用 */return i;
}/* 将下标为k的空闲结点回收到备用链表 */
void Free_SSL(StaticLinkList space, int k)
{ space[k].cur = space[0].cur; /* 把第一个元素的cur值赋给要删除的分量cur */space[0].cur = k; /* 把要删除的分量下标赋值给第一个元素的cur */
}/* 初始条件:静态链表L已存在。操作结果:返回L中数据元素个数 */
int ListLength(StaticLinkList L)
{int j=0;int i=L[MAXSIZE-1].cur;while(i){i=L[i].cur;j++;}return j;
}/* 在L中第i个元素之前插入新的数据元素e */
Status ListInsert(StaticLinkList L, int i, ElemType e)
{ int j, k, l; k = MAXSIZE - 1; /* 注意k首先是最后一个元素的下标 */if (i < 1 || i > ListLength(L) + 1) return ERROR; j = Malloc_SSL(L); /* 获得空闲分量的下标 */if (j) { L[j].data = e; /* 将数据赋值给此分量的data */for(l = 1; l <= i - 1; l++) /* 找到第i个元素之前的位置 */k = L[k].cur; L[j].cur = L[k].cur; /* 把第i个元素之前的cur赋值给新元素的cur */L[k].cur = j; /* 把新元素的下标赋值给第i个元素之前元素的ur */return OK; } return ERROR;
}/* 删除在L中第i个数据元素 */
Status ListDelete(StaticLinkList L, int i)
{ int j, k; if (i < 1 || i > ListLength(L)) return ERROR; k = MAXSIZE - 1; for (j = 1; j <= i - 1; j++) k = L[k].cur; j = L[k].cur; L[k].cur = L[j].cur; Free_SSL(L, j); return OK;
} Status ListTraverse(StaticLinkList L)
{int j=0;int i=L[MAXSIZE-1].cur;while(i){visit(L[i].data);i=L[i].cur;j++;}return j;printf("\n");return OK;
}int main()
{StaticLinkList L;Status i;i=InitList(L);printf("初始化L后:L.length=%d\n",ListLength(L));i=ListInsert(L,1,'F');i=ListInsert(L,1,'E');i=ListInsert(L,1,'D');i=ListInsert(L,1,'B');i=ListInsert(L,1,'A');printf("\n在L的表头依次插入FEDBA后:\nL.data=");ListTraverse(L); i=ListInsert(L,3,'C');printf("\n在L的“B”与“D”之间插入“C”后:\nL.data=");ListTraverse(L); i=ListDelete(L,1);printf("\n在L的删除“A”后:\nL.data=");ListTraverse(L); printf("\n");return 0;
}
循环链表
将单链表中终端结点的指针端由空指针改为指向头结点,就使整个单链表形成—个环,这种头尾相接的单链表称为单循环链表,简称循环链表。
为了使空链表与非空链表处理—致,我们通常设—个头结点,当然,这并不是说循环链表—定要头结点,这需要注意。循环链表带有头结点的空链表如下图所示:
双向链表
双向链表是在单链表的每个结点中再设置一个指向其前驱结点的指针域。
双向链表是单链表中扩展出来的结构,所以它的很多操作是和单链表相同的,比如求长度的ListLength,查找元素的GetElem,获得元素位置的LocateElem等,这些操作都只要涉及一个方向的指针即可,另—指针多了也不能提供什么帮助。
双向链表既然是比单链表多了如可以反向遍历查找等数据结构,那么也就需要付出一些小的代价:在插入和删除时,需要更改两个指针变量。
相关文章:

数据结构【第3章】——线性表
线性表的定义 线性表:零个或多个数据元素的有限序列。 1)线性表是一个序列。即元素之间是有顺序的,若元素存在多个,则第一个元素无前驱,最后一个元素无后继,其他每个元素都有且只有一个前驱和后继。 2&a…...

MySql之分库分表
数据库瓶颈 不管是IO瓶颈还是CPU瓶颈,最终都会导致数据库的活跃连接数增加,进而逼近甚至达到数据库可承载的活跃连接数的阈值。在业务service来看, 就是可用数据库连接少甚至无连接可用,接下来就可以想象了(并发量、吞…...

数据结构—图的遍历
6.3图的遍历 遍历定义: 从已给的连通图中某一顶点出发,沿着一些边访问遍历图中所有的顶点,且使每个顶点仅被访问一次,就叫作图的遍历,它是图的基本运算。 遍历实质:找每个顶点的邻接点的过程。 图的…...
MySQL主从复制基于二进制日志的高可用架构指南
前言 在现代数据库架构中,MySQL主从复制技术扮演着重要角色。它不仅可以提升数据库性能和可扩展性,还赋予系统卓越的高可用性和灾难恢复能力。本文将深入剖析MySQL主从复制的内部机制,同时通过一个实际案例,展示其在实际场景中的…...
RestTemplate HTTPS请求忽略SSL证书
问题描述 使用RestTemplate发送HTTPS请求的时候,出现了这样的一个问题: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification …...

Jenkins触发器时间、次数设定
触发器触发条件介绍 触发器触发条件公式:由5颗星组成 * * * * * 分别代表:分钟(0-59) 小时(0-23) 日期(1-31) 月份(1-12) 星期(0-6) 企业项目中常用场景介绍 场景1:接口脚本部分测试通过,部分还在进行,回归测试脚本执行…...

kafka partition的数据文件(offffset,MessageSize,data)
partition中的每条Message包含了以下三个属性: offset,MessageSize,data,其中offset表示Message在这个partition中的偏移量,offset不是该Message在partition数据文件中的实际存储位置,而是逻辑上一个值&…...
htnl根据轮播图图片切换背景色
htnl根据轮播图图片切换背景色 <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>轮播图示例</title><link rel"stylesheet" href"https://cdn.jsdelivr.net/npm/swiper10/swiper-bundle.min.css&q…...

gpu-manager安装及测试
提示:GPU-manager安装为主部分内容做了升级开箱即用,有用请点收藏❤抱拳 文章目录 前言一、约束条件二、使用步骤1.下载镜像1.1 查看当前虚拟机的驱动类型: 2.部署gpu-manager3.部署gpu-admission4.修改kube-scheduler.yaml
Zookeeper特性与节点数据类型详解
CAP&Base理论 CAP理论 cap理论是指对于一个分布式计算系统来说,不可能满足以下三点: 一致性 : 在分布式环境中,一致性是指数据在多个副本之间是否能够保持一致的 特性,等同于所有节点访问同一份最新的数据副本。在一致性的需…...

函数的递归
1、什么是递归? 程序调用自身的编程技巧称为递归。 递归作为一种算法在程序设计语言中广泛应用。一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解&#x…...

Android T 窗口层级其二 —— 层级结构树的构建(更新中)
如何通过dump中的内容找到对应的代码? 我们dump窗口层级发现会有很多信息,adb shell dumpsys activity containers 这里我们以其中的DefaultTaskDisplayArea为例 在源码的framework目录下查找该字符串,找到对应的代码就可以通过打印堆栈或者…...

ASIC芯片设计全流程项目实战课重磅上线 ,支持 65nm制程流片 !
全流程项目实战课学什么? 此次推出【 ASIC芯片设计全流程项目实战课】,基于IPA图像处理加速器,以企业级真实ASIC项目为案例,学员可参与全流程项目实践,以及65nm真实流片! 众所周知,放眼整个IC硕…...
背上沉重的书包准备run之react篇
沉重,太沉重了。。。没理好捏,等我脑子歇歇再好好补充一下 react特性? React 是一个用于构建用户界面的 JavaScript 库,它具有以下特性: 组件化开发:React 基于组件化思想,将 UI 拆分为独立、…...
LAMP及论坛搭建
一、概述 LAMP架构是目前成熟的企业网站应用模式之一,指的是协同工作的一整套系统和相关软件,能够提供动态Web站点服务及其应用开发环境。LAMP是一个缩写词,具体包括Linux操作系统、Apache网站服务器、MySQL数据库服务器、PHP(或…...

php-cgi.exe - FastCGI 进程超过了配置的请求超时时限
解决方案一: 处理(php-cgi.exe - FastCGI 进程超过了配置的请求超时时限)的问题 内容转载: 处理(php-cgi.exe - FastCGI 进程超过了配置的请求超时时限)的问题_php技巧_脚本之家 【详细错误】: HTTP 错误 500.0 - Internal Server Error C:…...

linux系统虚拟主机开启支持SourceGuardian(sg11)加密组件
注意:sg11我司只支持linux系统虚拟主机自主安装。支持php5.3及以上版本。 1、登陆主机控制面板,找到【远程文件下载】这个功能。 2、远程下载文件填写http://download.myhostadmin.net/vps/sg11_for_linux.zip 下载保存的路径填写/others/ 3、点击控制…...

让我们一起探讨汽车充电桩控制主板的应用
你是否想过,你的汽车充电桩可以更智能?可以支持更多类型的电池,更多操作系统,更多协议和更多电源?让我们一起探讨汽车充电桩控制主板的应用。 控制主板是充电桩的大脑,它可以应用于各种充电桩,包括智能充电桩、电动汽…...

Gartner发布《2023年全球RPA魔力象限》:90%RPA厂商,将提供生成式AI自动化
8月3日,全球著名咨询调查机构Gartner发布了《2023年全球RPA魔力象限》,通过产品能力、技术创新、市场影响力等维度,对全球16家卓越RPA厂商进行了深度评估。 弘玑Cyclone(Cyclone Robotics)、来也(Laiye&am…...

C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...

04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...