线性表知识总结

本文介绍了线性表的逻辑结构和两种主要的存储方式:顺序存储和链式存储。顺序存储使用数组实现,提供了初始化、插入、删除等操作的实现。链式存储包括单链表和双链表,同样支持线性表的基本操作,并且在插入和删除上更灵活。此外,还提到了循环链表的概念。
摘要由CSDN通过智能技术生成

一、线性表及其逻辑结构

(一)定义

线性表是一个具有相同特性的数据元素的有限序列。

线性表的逻辑表示为

( a1,a2,…,ai,ai+1,…,an )

ai(1≤i≤n)表示第i(i表示逻辑位序)个元素,a1为表头元素,an为表尾元素。

(二)基本运算

初始化线性表InitList(&L):构造一个空的线性表L。

销毁线性表DestroyList(&L):释放线性表L占用的内存空间。

判线性表是否为空表ListEmpty(L):若L为空表,则返回真,否则返回假。

求线性表的长度ListLength(L):返回L中元素个数n。

输出线性表DispList(L):线性表L不为空时,顺序显示L中各结点的值域。

求线性表L中指定位置的某个数据元素GetElem(L,i,&e):用e返回L中第i(1≤i≤n)个元素的值。

定位查找LocateElem(L,e):返回L中第一个值域与e相等的逻辑位序。若这样的元素不存在,则返回值为0。

插入一个数据元素ListInsert(&L,i,e):在L的第i(1≤i≤n)个元素之前插入新的元素e,L的长度增1。

删除数据元素ListDelete(&L,i,&e):删除L的第i(1≤i≤n)个元素,并用e返回其值,L的长度减1。

二、线性表的顺序存储结构

(一)顺序表的存储和声明

  声明线性表的顺序存储类型时,采用结构体类型SqList表示如下

#define MaxSize 50
typedef int ElemType;

typedef struct{
    ElemType data[MaxSize];
    int length;
} SqList;

(二)部分运算实现

1.建立顺序表

void CreateList(SqList *&L,ElemType a[],int n){
    int i=0,k=0;
    L=(SqList *)malloc(sizeof(SqList));    //分配存放线性表的空间
    while(i<n){
        L->data[k]=a[i];
        k++;
        i++;
    }
    L->length=k;
}

2.初始化线性表

void InitList(SqList *&L){
	L=(SqList *)malloc(sizeof(SqList));    //分配存放线性表的空间
	L->length=0;
}

3.插入数据元素

bool ListInsert(SqList *&L,int i,ElemType e){
	int j;
	if(i<1||i>L->length+1)
		return false;
	i--;                            //将逻辑序号转化为物理序号
	for(j=L->length;j>i;j--)        //将data[i]及后面元素后移一个位置
		L->data[j]=L->data[j-1];
	L->data[i]=e;
	L->length++;
	return true;
}

4.删除数据元素

bool ListDelete(SqList *&L,int i,ElemType &e){
	int j;
	if(i<1||i>L->length)
		return false;
	i--;                            //将逻辑序号转化为物理序号
	e=L->data[i];
	for(int j=i;j<L->length-1;j++)  //将data[i]及后面元素前移一个位置
		L->data[j]=L->data[j+1];
	L->length--;
	return true;
}

三、线性表的链式存储结构

(一)单链表

1.单链表的存储和声明

 在单链表中,每个结点类型用LinkNode表示如下

typedef int ElemType;

typedef struct LNode{
    ElemType data;
    struct LNode *next;
} LinkNode;

2.建立单链表

(1)头插法

void CreateListF(LinkNode *&L,ElemType a[],int n){
	LinkNode *s;
	L=(LinkNode*)malloc(sizeof(LinkNode));
	L->next=NULL;
	for(int i=0;i<n;i++){
		s=(LinkNode *)malloc(sizeof(LinkNode));
		s->data=a[i];
		s->next=L->next;
		L->next=s;
	}
}

(2)尾插法

void CreateListR(LinkNode *&L,ElemType a[],int n){
	LinkNode *s,*r;
	L=(LinkNode *)malloc(sizeof(LinkNode));
	r=L;
	for(int i=0;i<n;i++){
		s=(LinkNode *)malloc(sizeof(LinkNode));
		s->data=a[i];
		r->next=s;
		r=s;
	}
	r->next=NULL;
}

3.部分基本运算的实现

(1)初始化线性表

void InitList(LinkNode *&L){
    L=(LinkNode *)malloc(sizeof(LinkNode));
    L->next=NULL;
}

(2)销毁线性表:需要逐一释放全部结点的空间

void DestroyList(ListNode *&L){
    LinkNode *pre=L,*p=L->next;    //pre指向p的前驱结点
    while(p!=NULL){
        free(pre);
        pre=p;
        p=pre->next;               //pre、p同步后移一个结点
    }
    free(pre);
}

(3)插入数据元素

bool ListInsert(LinkNode *&L,int i,ElemType e){
	int j=0;
	LinkNode *p=L,*s;
	if(i<=0)
		return false;
	while(j<i-1&&p!=NULL){
		j++;
		p=p->next;
	}
	if(p==NULL)
		return false;
	else{
		s=(LinkNode *)malloc(sizeof(LinkNode));
		s->data=e;
		s->next=p->next;
		p->next=s;
		return true;
	}
}

(4)删除数据元素

bool ListDelete(LinkNode *&L,int i,ElemType &e){
	int j=0;
	LinkNode *p=L,*q;
	if(i<=0)
		return false;
	while(j<i-1&&p!=NULL){
		j++;
		p=p->next;
	}
	if(p==NULL)
		return false;
	else{
		q=p->next;
		if(q==NULL)
			return false;
		e=q->data;
		p->next=q->next;
		free(q);
		return true;
	}
}

(二)双链表

1.双链表的存储和声明

对于双链表,其结点类型DLinkNode的声明如下:

typedef struct DNode{
    ElemType data;
    struct DNode *prior;
    struct DNode *next;
} DLinkNode;

2.建立双链表

(1)头插法

void CreateListF(DLinkNode *&L,ElemType a[],int n){
	DLinkNode *s;
	L=(DLinkNode *)malloc(sizeof(DLinkNode));
	L->prior=L->next=NULL;
	for(int i=0;i<n;i++){
		s=(DLinkNode *)malloc(sizeof(DLinkNode));
		s->data=a[i];
		s->next=L->next;
		if(L->next!=NULL)
			L->next->prior=s;
		L->next=s;
		s->prior=L;
	}
}

(2)尾插法

void CreateListR(DLinkNode *&L,ElemType a[],int n){
	DLinkNode *s,*r;
	L=(DLinkNode *)malloc(sizeof(DLinkNode));
	r=L;
	for(int i=0;i<n;i++){
		s=(DLinkNode *)malloc(sizeof(DLinkNode));
		s->data=a[i];
		r->next=s;
		s->prior=r;
		r=s;
	}
	r->next=NULL;
}

3.部分基本运算的实现

(1)插入数据元素

bool ListInsert(DLinkNode *&L,int i,ElemType e){
	int j=0;
	DLinkNode *p=L,*s;
	if(i<=0)
		return false;
	while(j<i-1&&p!=NULL){
		j++;
		p=p->next;
	}
	if(p==NULL)
		return false;
	else{
		s=(DLinkNode *)malloc(sizeof(DLinkNode));
		s->data=e;
		s->next=p->next;
		if(p->next!=NULL)
			p->next->prior=s;
		s->prior=p;
		p->next=s;
		return true;
	}
}

(2)删除数据元素

bool ListDelete(DLinkNode *&L,int i,ElemType &e){
	int j=0;
	DLinkNode *p=L,*q;
	if(i<=0)
		return false;
	while(j<i-1&&p!=NULL){
		j++;
		p=p->next;
	}
	if(p==NULL)
		return false;
	else{
		q=p->next;
		if(q==NULL)
			return false;
		e=q->data;
		p->next=q->next;
		if(p->next!=NULL)
			p->next->prior=p;
		free(q);
		return true;
	}
}

(三)循环链表

循环单链表:将表中尾结点的指针域改为指向表头结点,整个链表形成一个环。由此从表中任一结点出发均可找到链表中其他结点。 

循环双链表:将尾结点的next指针域由原来为空指向头节点,将它的头结点的prior指针域改为指向尾结点,整个双链表形成两个环。

四、线性表相关应用

26.删除有序数组中的重复项【双指针】

给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:

  • 更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
  • 返回 k 。

4.寻找两个正序数组的中位数【二分查找】

给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。

算法的时间复杂度应该为 O(log (m+n)) 。

92.反转链表 II

给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。

25.K 个一组翻转链表

给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。

k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

23.合并K个升序链表

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

STRANGEX-03

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值