数据结构:线性表(List)【详解】

数据结构之线性表(List)(一) 线性表是具有相同类型的n(n >= 0)个数据元素的有限序列,其中n为表长,当n=0时,线性表为空表。若用L命名线性表,则一般表示为:L=(a1,a2,...ai,ai+1,...,an)。其中,a1是唯一的“第一个”数据元素,又称为表头元素;an是唯一的“最后一个元素”,又称为表尾元素。除第一个元素外,每个元素有且仅有一个直接前驱;除最后一个元素外,每个元素有且仅有一个直接后继。以上为线性表的逻辑特性。线性表的顺序存储又称顺序表。 阅读详情
AI摘要

本文详细介绍了线性表的两种存储结构——顺序表和链表。顺序表利用数组实现,支持随机访问,但插入和删除操作需要移动元素。链表包括单链表、静态链表和循环链表,插入和删除操作更为灵活,但访问速度相对较慢。文章还对比了两种结构的优缺点,并提供了具体的C语言实现示例。

友情链接:数据结构专栏

线性表

【知识框架】

在这里插入图片描述

一、线性表的定义

线性表(List):零个或多个数据元素的有限序列。

线性表的数据集合为{a1,a2,…,an},假设每个元素的类型均为DataType。其中,除第一个元素a1外,每一个元素有且只有一个直接前驱元素,除了最后一个元素an外,每一个元素有且只有一个直接后继元素。数据元素之间的关系是一对一的关系。
线性表
在较复杂的线性表中,一个数据元素可以由若干个数据项组成。在这种情况下,常把数据元素称为记录,含有大量记录的线性表又称为文件


线性表的顺序存储结构

一、顺序表

1、顺序表的基本概念

概念:用一组地址连续的存储单元依次存储线性表的数据元素,这种存储结构的线性表称为顺序表。

特点:逻辑上相邻的数据元素,物理次序也是相邻的。

只要确定好了存储线性表的起始位置,线性表中任一数据元素都可以随机存取,所以线性表的顺序存储结构是一种随机存取的储存结构,因为高级语言中的数组类型也是有随机存取的特性,所以通常我们都使用数组来描述数据结构中的顺序储存结构,用动态分配的一维数组表示线性表。

2、顺序表存储结构

//头文件
#include<stdio.h>
#include<stdlib.h>

#define MAXSIZE 20  //线性表存储空间的初始分配量
#define OK 1    //成功标识
#define ERROR 0 //失败标识

typedef int Status;	//Status是函数的类型,其值是函数结果状态代码,如OK等
typedef int ElemType;   //ElemType的类型根据实际情况而定,这里假定为int
//顺序表数据结构
typedef struct
{
    ElemType *elem;
    int length;
}SqList;

3、构造一个空的顺序表L

Status InitList(SqList* L){
    //构造一个空的线性表L
    L -> elem = (ElemType *)malloc(MAXSIZE*sizeof(ElemType));
    if(!L -> elem){
        return ERROR;
    }
    L -> length = 0;
    return OK;
}

4、顺序表的插入

/*
插入操作
初始条件:顺序表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->elem[k+1] = L->elem[k];
        }
    }   
    L->elem[i-1] = e;   //将新元素插入
    L->length++;    //长度加1
    return OK;
}

5、顺序表的删除

/*
删除操作
初始条件:顺序表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 -> elem[i-1];
    if(i < L->length){  //如果删除位置不在最后位置
        for(k = i;k < L->length;k++){
            L->elem[k-1] = L->elem[k];
        }
    }
    L->length--;    //长度减1
    return OK;
}

6、获取顺序表某一位置上的元素

/*
获取元素操作
初始条件:顺序表L已存在
操作结果:用e返回L中第i个数据元素的值
*/
Status GetElem(SqList L, int i, ElemType *e){
    if(L.length == 0 || i<1 || i>L.length){
        return ERROR;
    }
    *e = L.elem[i-1];
    return OK;
}

7、读取顺序表所有元素

/*打印线性表中的所有元素*/
void OutPut(SqList L){
    printf("当前顺序表的长度:%d\n", L.length);
    for(int i = 0; i < L.length; i++){
        printf("%d ",L.elem[i]);
    }
    printf("\n");
}

8、运行测试

int main()
{
    SqList L;
    printf("------构造一个空的线性表L------\n");
    InitList(&L);
    OutPut(L);  //打印结果
    printf("------测试插入10个数------\n");
    for(int i = 1;i <= 10; i++){
        ListInsert(&L,i,i);
    }
    OutPut(L);  //打印结果
    printf("------在第三位之前插入0------\n");
    ListInsert(&L,3,0);
    OutPut(L);  //打印结果
    printf("------删除第6位的数据------\n");
    ElemType e;
    ListDelete(&L,6,&e);
    printf("删除的数据为:%d\n", e);
    OutPut(L);  //打印结果
    printf("------获取元素操作------\n");
    GetElem(L,5,&e);
    printf("得到第5个元素:%d", e);
}

运行结果
在这里插入图片描述

小结

1、顺序表时间复杂度

从以上代码可以很明显的看出,线性表的顺序存储结果在读、存数据是的时间复杂度是O(1),插入、删除操作的时间复杂度是O(n)。

2、顺序表的优缺点

优点:无须为表中元素之间的逻辑关系而增加额外的存储空间;可以快速的存取表中任一位置的元素。
缺点:插入和删除操作需要移动大量元素;当线性表长度较大时,难以确定存储空间的容量;造成存储空间的“碎片”。


线性表的链式存储结构

一、单链表

1、单链表的基本概念

在链式结构中,除了要存储数据元素的信息外,还要存储它的后继元素的存储地址。因此,为了表示每个数据元素ai与其直接后继元素ai+1之间的逻辑关系,对数据ai来说,除了存储其本身的信息之外,还需要存储一个指示其直接后继的信息(即直接后继的存储位置)。我们吧把存储数据元素信息的域称为数据域,把存储直接后继位置的域称为指针域。指针域中存储的信息称做指针或链。这两部分信息组成数据元素ai的存储映像,称为结点(Node)。
n个结点(ai的存储映像)链结成一个链表,即为线性表(a1, a2, …, an)的链式存储结构,因为此链表的每个结点中只包含一个指针域,所以叫做单链表。
在这里插入图片描述

把链表中第一个结点的存储位置叫做头指针。

在这里插入图片描述

有时为了方便对链表进行操作,会在单链表的第一个结点前附设一个节点,称为头结点,此时头指针指向的结点就是头结点。

在这里插入图片描述

空链表,头结点的直接后继为空。

在这里插入图片描述
假设p是指向线性表第i个数据元素的指针,p->data表示第i个位置的数据域,p->next表示第i+1个位置的指针域,则第p+i个数据元素可表示为:
在这里插入图片描述

2、单链表的存储结构

#define OK 1    //正确标识
#define ERROR 0 //失败标识

typedef int Status; //Status是函数的类型,其值是函数结果状态代码,如OK等

typedef int ElemType;   //ElemType的类型根据实际情况而定,这里假定为int

/*线性表的单链表存储结构*/
//构造结点
typedef struct Node
{
    ElemType data;
    struct Node *next;
} Node;

//构造LinkList
typedef struct {
    int lenght;
    Node *next;
}*LinkList;

3、构造单链表

/*构造一个带头结点的单链表*/
Status InitList(LinkList *L){
    //生成一个空的LinkList和一个新结点
    LinkList p = (LinkList)malloc(sizeof(LinkList));
    Node *q = (Node *)malloc(sizeof(Node)); //头结点
    q->next = NULL; //头结点的后继指向null
    p->next = q;    //头指针指向头结点
    p->lenght = 0;  //初始长度为0
    (*L) = p;
    return OK;
}

4、单链表的插入

若将将节点s插入到节点p和几点p->next之间,如下图所示,其核心操作是:

s->next=p->next;
p->next=s;

在这里插入图片描述
具体代码如下:

/**
 * 单链表插入操作
 * 初始条件:线性表L已存在
 * 操作结果:在L中第pos个位置之前插入新的数据元素e,L的长度增加1
*/
Status ListInsert(LinkList *L, ElemType elem, int pos){
    if(pos<1 || pos > (*L)->lenght+1){
        return ERROR;
    }
    //寻找第pos个结点
    Node *p = (*L)->next; //头结点
    for(int i=1; i<pos; i++){
        p = p->next;
    }
    //生成一个新结点
    Node *q = (Node *) malloc(sizeof(Node));
    q->data = elem;
    q->next = p->next;  //将p的后继赋值给q的后继
    p->next = q;    //将q赋值给p的后继
    (*L)->lenght += 1;  //链表长度加1
    return OK;
}

5、单链表的删除

在这里插入图片描述

/**
 * 单链表删除操作
 * 初始条件:线性表L已存在
 * 操作结果:删除L的第pos个数据元素,并用e返回其值,L的长度减1
*/
Status ListDelete(LinkList *L, ElemType *elem, int pos){
    if(pos < 1 || pos>(*L)->lenght){
        return ERROR;
    }
    //寻找到第pos个结点
    Node *p = (*L)->next, *q;
    for(int i=1; i<pos; i++){
        p=p->next;
    }
    q = p->next;    //要删除的结点
    p->next = q->next;
    free(q);
    (*L) -> lenght -= 1;
    return OK;
}

6、清空单链表

/**
 * 清空单链表
*/
Status Clear(LinkList *L){
    Node *p = (*L)->next->next, *q;
    while(p != NULL){
        q = p;
        p = p->next;
        free(q);
    }
    (*L)->next->next = NULL;
    (*L)->lenght = 0;
    return OK;
}

7、销毁单链表

/**
 * 销毁单链表
*/
Status Destory(LinkList *L){
    Node *p = (*L)->next, *q;
    while(p != NULL){
        q = p;
        p = p->next;
        free(q);
    }
    free((*L));
    (*L) = NULL;
    return OK;
}

8、遍历打印单链表

/*打印单链表表中的所有元素*/
void OutPut(LinkList L){
    
    Node *p=L->next->next ;
	for(int i=0;i<L->lenght;i++)
	{
		printf("%d ",p->data );
		p=p->next ;
	} 
    printf("\n");
}

9、测试运行

int main()
{
    LinkList L;
    //构造单链表
    InitList(&L);
    printf("------测试插入10个数------\n");
    for(int i = 1; i<=10;i++){
        ListInsert(&L,i,i);
    }
    OutPut(L);
    printf("------删除第5位的数据------\n");
    ElemType elem;
    ListDelete(&L, &elem, 5);
    OutPut(L);
    printf("------清空单链表------\n");
    Clear(&L);
    OutPut(L);
}

运行结果:
在这里插入图片描述


二、静态链表

1、静态链表的基本概念

静态链表,使用数组连描述指针,首先我们让数组的元素都是由两个数据域组成,data和cur。数据域data,用来存放数据元素;游标cur相当于单链表的next指针,存放该元素的后继在数组中的下标。

为了方便插入数据,我们通常会把数组建立得大一些,以便有一些空闲空间可以便于插入时不至于溢出。

#define MAXSIZE 1000    //假设链表的最大长度是1000
typedef struct{
    ElemType data;
    int cur;    //游标(Cursor),为0时表示无指向
} Component,StaticLinkList[MAXSIZE];

另外我们对数组的第一个和最后一个元素作为特殊元素处理,不存数据。通产把未被使用的数组元素称为备用链表。而数组第一个元素,即下标为0的元素的cur存放备用链表的第一个结点的下标;而数组的最后一个元素的cur则存放第一个有数值的元素的下标,相当于单链表中的头结点的作用,当整个链表为空时,则为0。
在这里插入图片描述
此时图示相当于初始化的数组状态,见下面代码:

/**
 * 将一维数组space中各分量链成一备用链表
 * space[0].cur为头指针。“0”表示空指针
*/
Status InitList(Component *space){
    int i;
    for(i=0; i<MAXSIZE; i++){
        space[i].cur = i+1;
    }
    space[MAXSIZE-1].cur = 0; //目前静态链表为空,最后一个元素的cur为0
    return OK;
}

在前面的动态链表中,节点的申请和释放分别借用malloc()和free()两个函数来实现。在静态链表中,我们需要自己实现这两个函数。
为了辨明数组中哪些分量未被使用,解决的办法是将所有未被使用过的及已被删除的分量用游标链成一个备用的链表,每当进行插入时,便可以从备用链表上取得第一个结点作为待插入的新节点。

/**
 * 申请下一个分量的资源,返回下标
*/
int Malloc_SLL(StaticLinkList space){
    int i = space[0].cur;   //当前数组第一个元素的cur存的值,就是要返回的第一个备用空间的下标
    if(space[0].cur){
        space[0].cur = space[i].cur;    //把下一个分量用来做备用
    }
    return i;
}
/**
 * 将下标为k的空闲节点收回到备用链表
*/
void Free_SSL(Component *space, int k){
    space[k].cur = space[0].cur;    //把第一个元素cur值赋值给要删除的分量cur
    space[0].cur = k;   //把要删除的分量下标赋值给第一个元素的cur
}

2、静态链表的插入操作

例如如果我们需要在“乙”和“丁”之间,插入一个“丙”,操作如图所示:
在这里插入图片描述
用代码实现如下:

/**
 * 得到静态列表的长度
 * 初始条件:静态列表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(Component *L, int i, ElemType e){
    int j,k,l;
    k = MAXSIZE - 1;    //注意k首先是最后一个元素的下标
    if(i<1 || i>ListLength(L) + 1){
        return ERROR;
    }
    j = Malloc_SLL(L);
    if(j){
        L[j].data = e;  //将数据赋值给此分量的data
        for(l=1; l<= i-1; l++){ 
            k = L[k].cur;   //找到第i个元素之前的位置
        }
        L[j].cur = L[k].cur;    //把第i个元素之前的cur赋值给新元素的cur
        L[k].cur = j;   //把新元素的下标赋值给第i个元素之前元素的cur
        return OK;
    }
    return ERROR;
}

3、静态链表的删除操作

例如如果要删除“甲”元素,如图所示:
在这里插入图片描述
用代码实现如下:

/**
 * 删除在L中第i个数据元素e
*/
Status ListDelete(Component *L, int i){
    int j,k;
    if(i<1 || i>ListLength(L)+1){
        return ERROR;
    }
    k = MAXSIZE - 1;
    for(j=1; j<=i-1; j++){
        k = L[k].cur;   //找到第i个元素之前的位置
    }
    j = L[k].cur;
    L[k].cur = L[j].cur;
    OUTPUT(L);
    Free_SSL(&L, j);
    return OK;
}

三、循环链表

1、循环链表的基本概念

将单链表中终端节点的指针端由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相接的单链表称为单循环链表,简称循环链表。
循环链表带有头结点的空链表如下图所示:
在这里插入图片描述
对于非空的循环链表则如下图所示:
在这里插入图片描述

2、仅设尾指针的循环链表

上述仅设头指针的循环链表有一个弊端,我们可以用O(1)的时间访问第一个节点,但对于最后一个节点,却需要O(n)的时间,于是就有了仅设尾指针的循环链表。

如下图所示:
在这里插入图片描述
从上图可以看到,终端节点用尾指针rear指示,则查找终端节点是O(1),而开始节点,其实就是rear->next->next,其时间复杂度也是O(1)。

举个程序的例子,要将两个循环链表合成一个表时,有了尾指针就非常简单了。比如下面的这两个循环链表,它们的尾指针分别是rearA和rearB。
在这里插入图片描述
要想把它们合并,只需要如下操作即可:
在这里插入图片描述

//第一步:保存A的头结点
p = rearA->next;	
//第二步:将本是指向B表的第一个节点(不是头结点)赋值给rearA->next
rearA->next = rearB->next->next;
//第三步:将原A表的头结点赋值给rearB->next
rearB->next=p;
//释放p
free(p);

四、双向链表

1、双向链表的基本概念

双向链表(double linked list)是在单链表的每个结点中,再设置一个指向其前驱结点的指针域。所以在双向链表中的结点都有两个指针域,一个指向直接后继,另一个指向直接前驱。

/*双向链表存储结构*/
typedef struct DulNodse{
	ElemType data;
	struct DulNode *prior;	//直接前驱指针
	struct DulNode *next;	//直接后继指针
} DulNode, *DuLinkList;

双链表示意图如下所示:
在这里插入图片描述
双向链表中,对于链表中的某一个结点p,它的后继的前驱以及它的前驱的后继都是它自己,即:

p->next-prior = p = p->prior-next

2、双向链表的插入操作

在双链表中p所指的结点之后插入结点*s,其指针的变化过程如下图所示:
在这里插入图片描述

插入操作的代码片段如下:

//第一步:把p赋值给s的前驱
s->prior = p;
//第二步:把p->next赋值给s的后继
p->next = p->next
//第三步:把s赋值给p->next的前驱
p->next->prior = s;
//第四步:把s赋值给p的后继
p->next = s;

3、双向链表的删除操作

如果要删除q结点,只需下面两步:
在这里插入图片描述

代码片段如下:

//第一步
p->next = q->next;
//第二步
q->next->prior = p;
free(q);

总结

一、顺序表和链表的比较

1、存取(读写)方式

顺序表可以顺序存取,也可以随机存取,链表只能从表头顺序存取元素。例如在第i个位置上执行存或取的操作,顺序表仅需一次访问,而链表则需从表头开始依次访问i次。

2、逻辑结构与物理结构

采用顺序存储时,逻辑上相邻的元素,对应的物理存储位置也相邻。而采用链式存储时,逻辑上相邻的元素,物理存储位置则不一定相邻,对应的逻辑关系是通过指针链接来表示的。

3、查找、插入和删除操作

对于按值查找,顺序表无序时,两者的时间复杂度均为O(n);顺序表有序时,可采用折半查找,此时的时间复杂度为O(log2n)。
对于按序号查找,顺序表支持随机访问,时间复杂度仅为O(1),而链表的平均时间复杂度为O(n)。顺序表的插入、删除操作,平均需要移动半个表长的元素。链表的插入、删除操作,只需修改相关结点的指针域即可。由于链表的每个结点都带有指针域,故而存储密度不够大。

4、空间分配

顺序存储在静态存储分配情形下,一旦存储空间装满就不能扩充,若再加入新元素,则会出现内存溢出,因此需要预先分配足够大的存储空间。预先分配过大,可能会导致顺序表后部大量闲置;预先分配过小,又会造成溢出。动态存储分配虽然存储空间可以扩充,但需要移动大量元素,导致操作效率降低,而且若内存中没有更大块的连续存储空间,则会导致分配失败。链式存储的结点空间只在需要时申请分配,只要内存有空间就可以分配,操作灵活、高效。

二、在实际中应该怎样选取存储结构呢?

1、基于存储的考虑

难以估计线性表的长度或存储规模时,不宜采用顺序表;链表不用事先估计存储规模,但链表的存储密度较低,显然链式存储结构的存储密度是小于1的。

2、基于运算的考虑

在顺序表中按序号访问a1的时间复杂度为O(1),而链表中按序号访问的时间复杂度为O(n)因此若经常做的运算是按序号访问数据元素,则显然顺序表优于链表。
在顺序表中进行插入、删除操作时,平均移动表中一半的元素,当数据元素的信息量较大且表较长时,这一点是不应忽视的;在链表中进行插入、删除操作时,虽然也要找插入位置,但操作主要是比较操作,从这个角度考虑显然后者优于前者。

3、基于环境的考虑

顺序表容易实现,任何高级语言中都有数组类型;链表的作是基于指针的,相对来讲,前者实现较为简单,这也是用户考虑的一个因素。
总之,两种存储结构各有长短,选择哪一种由实际问题的主要因素决定。通常较稳定的线性表选择顺序存储,而频繁进行插入、删除操作的线性表(即动态性较强)宜选择链式存储。
注意:只有熟练掌握顺序存储和链式存储,才能深刻理解它们各自的优缺点。


附录

上文链接

数据结构:基本概念

下文链接

数据结构:栈和队列

专栏

数据结构专栏

参考资料

1、严蔚敏、吴伟民:《数据结构(C语言版)》
2、程杰:《大话数据结构》
3、王道论坛:《数据结构考研复习指导》
4、托马斯·科尔曼等人:《算法导论》

数据结构之线性表,这一篇就够了,吐血总结,建议收藏~~ 线性表及其顺序存储结构 痛定思痛,决定吐血总结一下线性表相关的知识,篇幅较多,字数较长,建议收藏学习! 另外,请大家多多指教! 又到了幼儿园放学的时间,今天天气很不错,光明顶幼儿园门口很多家长来接自己家的小宝贝,只见老师带着小朋友们,一个拉着另一个的衣服,依次从教室出来。而且我发现很有规律的是,每次他们的次序都是一样。比如宋远桥的儿子排在第5个,据说每次他都是在第5个,前面同样是那个小女孩,后面一直是那个小男孩。这点让我很奇怪,为什么一定要这样? 后来从老师那里得知,为了保障小朋友的安全,避免漏掉小朋友,所 阅读详情

相关推荐

线性表详解

一篇博文带你了解线性表,

qq_59293418的博客 1856

【数据结构】List介绍

List中提供了好的方法,具体如下:虽然方法比较多,但是常用方法如下方法解释尾插 e将 e 插入到 index 位置尾插 c 中的元素删除 index 位置元素删除遇到的第一个 o获取下标 index 位置元素将下标 index 位置元素设置为 element清空判断 o 是否在线性表中返回第一个 o 所在下标返回最后一个 o 的下标截取部分 list。

小黑屋的黑小子的博客 981

数据结构——线性表及Set,Map详解

线性表:由n(n>0)个数据元素(数字,字符等)所构成的有限序列,逻辑连续(一条直线),物理上不一定连续,分为顺序表和链表1.顺序表:1.能存储的数据有限(一次开辟,永久使用),但是易于操作、编写代码 2.空间利用率相对高 3.若查改元素,其时间复杂度低O(1),可根据数组下标直接访问; 若增删移其时间复杂度高,至少 O(n),会牵涉到大量元素的整体移动2.链表: 1.能存储的数据取决于堆的内存

weixin_63056061的博客 2764

数据结构基础系列(2):线性表

数据结构课程是计算机类专业的专业基础课程,在IT人才培养中,起着重要的作用。课程按照大学计算机类专业课程大纲的要求,安排教学内容,满足需要系统学习数据结构的人。系列课程包含11个部分,本课为第2部分,线性表的逻辑结构,线性表的顺序表和链表两种存储结构,以及在各种存储结构中基本运算的实现,还通过相关的应用案例介绍了相关知识的应用方法。

数据结构与算法——线性表(List)

1、定义:由n(n>=0)个数据元素a1,a2,……an组成的有序序列。2、特性:同一线性表中的元素必定具有相同的特性,数据元素之间的关系是线性关系。

m0_57086839的博客 1815

数据结构线性表的构建

数据结构线性表的构建 创建名为线性表的空项目,在创建的线性表中创建线性表cpp文件,之际按c文件的格式写代码即可。 首先要在开头添加两个头文件: #include <conio.h> (不然,getch()没有定义) #include <windows.h> 然后,因为clrscr()在vs中没有提供,所以我们采用以下代码来说明,需要与#include <wi...

weixin_43928264的博客 2666

线性表的详解

线性表是算法题命题的重点。这类算法题实现起来比较容易且代码量较少,但是要求具有最优的性能(时间复杂度、空间复杂度),才能获得满分。因此,应牢固掌握线性表的各种基本操作(基于两种存储结构),在平时的学习中多注重培养动手能力。另外,需要提醒的是,算法最重要的是思想!考场上的时间紧迫,在试卷上不一定要求代码具有实际的可执行性,因此应尽力表达出算法的思想和步骤,而不必过于拘泥每个细节。注意算法题只能用C/C++语言实现。

gongjunbox的博客 1万+

MATLAB配置MinGW编译器的完整指南

本文提供了在Windows系统上为MATLAB配置MinGW编译器的完整指南。详细介绍了通过MATLAB附加功能管理器在线安装和手动离线安装两种核心方法,并重点说明了如何解决常见的“未找到支持的编译器”等错误。指南包含从版本检查、环境变量配置到最终使用mex命令验证的每一步,帮助用户顺利完成MATLAB与MinGW的集成,以支持C/C++代码编译。

weixin_29031057的博客 265

数据结构学习之——线性表

定义:线性表的顺序存储又称顺序表。它是用一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻。位序:第1个元素存储在线性表的起始位置,第i个元素的存储位置后面紧接着存储的是第i+1个元素,称i为元素aia_{i}ai​在线性表中的位序。因此,顺序表的特点是表中元素的逻辑顺序与其物理顺序相同。

会飞的鱼的博客 5449

FastGPT 引申:借鉴 FastGPT 基于MySQL + ES 实现知识库(含表结构以及核心代码)

FastGPT 引申:借鉴 FastGPT 基于MySQL + ES 实现知识库(含表结构以及核心代码)

蜗牛的专栏 3435

麒麟V10等保三级配置实战:从auditd规则到PAM锁定的可信基线构建

Linux安全基线是信息系统可信运行的基础能力,其核心在于身份鉴别、访问控制与安全审计三大机制的协同落地。在国产化信创环境中,麒麟V10作为深度适配飞腾/鲲鹏平台的操作系统,其等保三级合规并非简单套用CentOS加固脚本,而是需围绕内核审计(auditd)、可插拔认证模块(PAM)及国产安全增强机制(如kysec)进行精细化编排。技术价值体现在将抽象条款(如GB/T 22239-2019中6.1.2、6.3.3条)转化为可验证的命令行操作,确保登录失败可锁定、关键行为可追溯、时间偏差不致日志失效。典型应用场

weixin_29969209的博客 597

数据结构详解:线性表(Linear List)

线性表(Linear List)是由n(n ≥ 0)个具有相同类型的数据元素组成的有限序列。简单来说,线性表就是一组按顺序排列的数据元素,每个元素最多有一个前驱和一个后继。特性顺序表(数组)链表存储方式连续存储空间非连续,通过指针连接访问方式支持随机访问(O(1))只能顺序访问(O(n))插入/删除通常需要移动元素(O(n))修改指针即可(O(1),若已定位)空间开销仅存储数据每个结点需额外存储指针扩展性扩容成本高(尤其是静态数组)动态扩展更加灵活适用场景查找多、插入删除较少。

2501_93515492的博客 1405

IEEE Transaction期刊模板使用注意事项

本文将总结使用IEEE Transactions系列期刊的投稿模板时的一些注意事项,包括模板本身的使用规范、参考文献的正确格式等其他内容。

weixin_39529207的博客 2万+

【数据结构】线性表(List)

数据结构中的顺序表、单链表、双链表、循环链表的基础知识,且还包含部分408真题(附有解析)。此外,含有关于链表的全部具体实现代码

2201_75475240的博客 2086

InfiniteTalk (Wan2.1) 数字人 A800 落地实战:从依赖地狱到完美运行的保姆级指南

摘要:本文详细记录了在A800(80GB)服务器上部署InfiniteTalk开源数字人项目的完整流程。该项目基于阿里Wan2.1视频生成模型,支持无限时长流式生成,但环境配置极其复杂。作者总结了18个关键问题点,包括Python版本冲突、CUDA算子缺失等,并提供了黄金配置方案:使用Python3.10+PyTorch2.5.1环境,精准控制FlashAttention等核心库版本,以及针对A800的显存优化策略。最终实现480P视频30秒/步的生成速度,相比默认配置提升3.7倍性能。

软件工程师文艺 2043

国社科基金申报书“选题与说明依据”用AI怎么写?借助Gemini 3 Pro一次理清研究演进逻辑

研究进展部分要明确指出已有研究的不足与局限,比如方法不足、数据或材料受限、研究视角单一等等局限,之后要找准研究切入点,自然引申出自己的研究问题。为提升课题申报书的质量,学术史梳理要遵循述评结合、中外结合、新老结合的原则,不仅“述”,更要“评”,兼顾国内研究与国际学术动态,统筹经典研究与最新成果。它是对选题的整体概述,需阐明研究的具体问题、视角以及核心概念。2)存在问题或争议:结合已有研究或实践现状,指出该领域在理论建构、测量工具、实践应用或研究结论方面仍存在的不足、空白或争议,明确研究的必要性;

智能AI让学术科研更容易 942

【数据结构】线性表( List)和 顺序表(ArrayList)

关于数据结构中线性表和顺序表的学习~

qq_56251766的博客 1625

UNet + Shuffle Attention:一种轻量高效的医学图像分割注意力机制

本文提出了一种轻量高效的医学图像分割方法,将Shuffle Attention模块嵌入UNet的上采样路径中。Shuffle Attention通过通道分组注意力机制增强关键特征,同时保持计算轻量化。该方法在上采样后应用注意力模块,有效融合高层语义与低层细节,计算开销小且易于部署。实验表明,该模型在保持UNet原有优势的基础上,通过注意力机制提升了特征聚焦能力,适用于多种图像分割任务。未来可进一步结合空间注意力或Transformer模块以增强模型性能。

Henry的博客 240

数据结构之线性表List

数据结构之线性表List 与线性表相关的最重要的概念是“位置”,应该把线性表看成是数学序列的表现。线性表中常见的术语如下。 术语 含义 长度length 线性表当前存储的元素数目 表头head 线性表的开始节点 表尾tail 线性表的结尾节点 抽象数据类型ADT的创建 首先使用C++中的抽象类表示法正式定义线性表的ADT,抽象类指成员函数都被声明为“纯虚的”(pure virtual)的类。这里定义抽象类List,使得继承List的任何线性表实现都必须支持这些函数,并使用函数所规

Viviennebla的博客 405

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

数据结构:线性表

线性表是最基本、最简单、也是最常用的一种数据结构。线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意,这句话只适用大部分线性表,而不是全部。比如,循环链表逻辑层次上也是一种线性表(存储层次上属于链式存储,但是把最后一个数据元素的尾指针指向了首位结点)。

梁辰兴的博客 2661

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

【数据结构】List 详解

本文介绍了List数据结构的概念、实现方式及在Java中的应用。List作为一种有序、可重复的线性结构,主要有两种实现:基于动态数组的ArrayList(查询快O(1),增删慢O(n))和基于链表的LinkedList(增删快O(1),查询慢O(n))。文章详细对比了两者的特性、时间复杂度及适用场景:ArrayList适合频繁随机访问,LinkedList适合频繁插入删除。此外还介绍了常见算法如列表反转、排序的实现,并建议在大多数情况下优先选择ArrayList,仅在特定场景使用LinkedList。理解这

2301_79816047的博客 2114

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

【数据结构】线性表--list(详解建议收藏)

零个或多个数据元素的有限序列。线性表的数据集合为{a1,a2,…,an},假设每个元素的类型均为DataType。其中,除第一个元素a1外,每一个元素有且只有一个直接前驱元素,除了最后一个元素an外,每一个元素有且只有一个直接后继元素。数据元素之间的关系是一对一的关系。在较复杂的线性表中,一个数据元素可以由若干个数据项组成。在这种情况下,常把数据元素称为记录,含有大量记录的线性表又称为文件顺序表可以顺序存取,也可以随机存取,链表只能从表头顺序存取元素。

DreamSun的博客 2312

C语言数据结构--线性表(List)

1.0 线性表 线性表头文件: #pragma once #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 #define INVALID_INDEX -1 // 存储空间初始分配量 #define LIST_INIT_SIZE 20 // 元素类型,假定是 int 类型。 typedef int elemType; typedef struct ListNode { // 容量 int capacity; /.

SurpriseKuang的博客 2339

线性表(Linear List)

线性表(Linear List) 1. 线性表的概念 线性表是最基本、最简单、也是最常用的一种数据结构。 线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意,这句话只适用大部分线性表,而不是全部。比如,循环链表逻辑层次上也是一种线性表(存储层次上属于链式存储),但是把最后一个数据元素的尾指针指向了哨位结点)。 在数据结构逻辑层次上细分,线性表可分为一般线

Catherine的笔记 5781

ADT线性表List的定义和顺序表示及实现

线性表是最常用且最简单的一种数据结构。简言之,一个线性表是n个数据元素的有限序列。至于每个数据元素的具体含义,在不同的情况下各不相同,它可以是一个数字或者一个符号,也可以是一列数字的集合(例如二维数组),亦或是一串字符(例如字符串数组),甚至其他更复杂的信息。例如,26个英文字母的字母表:(A,B,C,···,Z)是一个线性表,表中的数据元素是单个字母字符。又如:(6, 17, 28, 50, 92, 188)表中的数据元素是整数。在稍微复杂的线性表中,一个数据元素可以又若干个数据项。

m0_53360850的博客 2745
上一篇: windows上使用telnet测试端口号通不通
下一篇: Visual Studio Code安装以及C/C++运行环境搭建
UniqueUnit
博客等级 码龄9年 4万+粉丝 15原创
评论 50
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值