数据结构|线性表

是指

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

可以含有相同值的元素

长度

所含元素的个数

元素

成线性关系

作用

在这里插入图片描述

一般表示

(a1,a2,a3…)

特性

有穷性
一致性
序列性:

  • 所有元素的相对位置是线性的,存在唯一的开始元素、终端元素
  • 每个元素有唯一的前驱元素、后继元素
  • 各元素在线性表中的位置只取决于序号
  • 线性表中可以存在两个值相同的元素

基本运算

ListLength(L)=5

顺序存储结构

按逻辑顺序,依次存储到存储器中一片连续存储空间中

顺序表类型定义

typedef struct {//用数组实现顺序存储结构
	ElemType data[MaxSize];//elemtype为抽象类型
							//data成员存放元素
	int length;
}SqList;

注意:逻辑位序和物理位序相差1

算法参数说明

1、顺序表指针?
在这里插入图片描述
传递的不是顺序表本身,而是顺序表指针

*2、顺序表指针引用SqList &L?

void CreateList(SqList *&L,ElemType a[],int n)

为什么要加&:
将执行结果回传给实惨
输出型参数均使用&,不论参数值是否改变

顺序表基本运算

//建立顺序表
void InitList(SqList*& L) {
	L = (SqList*)malloc(sizeof(SqList));//为顺序指针L分配线性表的空间
	L->length = 0;
}

//销毁线性表
void DestroyList(SqList*& L) {
	free(L);
}

//判断是否为空表
bool ListEmpty(SqList* L) {
	return (L->length == 0);//是双==,不是=
}

//求线性表长度
int ListLength(SqList* L) {
	return(L->length);
}

//输出线性表
void DispList(SqList* L) {
	for (int i = 0; i < L->length; i++)//挨个元素输出
	{
		printf("%d", L->data[i]);
	}
	printf("\n");
}

//求某个元素值
bool GetElem(SqList* L, ElemType& e,int i) {//bool型函数,返回t或f,但是函数中进行了值传递
	if (i<1||i>L->length)//检测合法性
	{
		return false;
	}
	e = L->data[i - 1];//引用传参,将该元素传出放在e中
		return true;
}

//按元素值查找
int LocateElem(SqList* L, ElemType e) {
	int i = 0;
	while (i < L->length&&L->data[i]!=e)//合法性和元素值一起检查
	{
		i++;
	}
	if (i >= L->length)
		return 0;
	else
	{
		return i + 1;//因为数组从0开始,顺序表从1开始
	}
}

//插入数据元素,bool型
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--)
	{
		L->data[j] = L->data[j - 1];//将i-1往后移动
	}
	L->data[i] = e;//插入元素
	L->length++;//长度增加
	return true;
}

//删除数据元素,bool型
bool ListDelete(SqList*& L, int i, ElemType& e) {
	int j;
	if (i<1 || i>L->length)
		return false;
	i--;//将逻辑序号转化为物理序号
	e = L->data[i];
	for (j = i; j < L->length; j++)//实际是移动i下标,前移
		L->data[j] = L->data[j + 1];
	L->length--;
}

bool型:判断空表/插入/删除
引用&传参:建表/销毁/插入/删除

此算法在移动元素上耗时最多
在这里插入图片描述
i=n+1时,移动次数为0
i=1时,移动次数为n
插入算法的平均时间复杂度是O(n)

在这里插入图片描述
i=n时,移动次数为0
i=1时,移动次数为n-1
删除算法的平均时间复杂度是O(n)

在这里插入图片描述

实际问题1

在这里插入图片描述

方法一:用原表,删一些元素(根据下标直接换人)

**思想:**删除=保存剩下的
在这里插入图片描述
k的作用:

  • 记录元素个数,随时更新
  • 成为新的元素下标,便于直接用原有表

方法二:用原表,前移元素(踢走不要的)

例题2

在这里插入图片描述

  • 此题不要求有大小排序
  • 所以直接交换即可

方法一:双向查找,交换位置

在这里插入图片描述

方法二:前后依次查找,换到空位上

在这里插入图片描述
时间复杂度都是O(n)

关于交换元素:
当需要连续交换多个元素时:
在这里插入图片描述
==》效率低
而:

tmp=a;
a=b;
b=c;
c=tmp;

==》效率高

单链表

在这里插入图片描述

单链表的优点

  • 对于每个结点无需特殊处理
  • 对于空/非空无需特殊处理

存储密度:
在这里插入图片描述
数据本身/总空间大小

顺序表存储密度=1,链表存储密度<1

单链表中节点类型的定义

在这里插入图片描述
单链表特点:
访问过一个节点后,只能接着访问后继节点,不能访问前趋节点
==》引入双链表

基本运算

删除:

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

插入:

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

建立单链表:
1、头插法
在这里插入图片描述
链表元素顺序和数组本身顺序相反
(节点顺序与逻辑次序相反)

//1、头插法
void CreatListF(LinkList*& L, ElemType a[], int n) {
	LinkList* s;//单链表的节点指针s,s是指针!!!
	int i;
	L = (LinkList*)malloc(sizeof(LinkList));//为表分配空间
	L->next = NULL;//创建头节点,next指向空
	for (i = 0; i < n; i++)
	{
		s = (LinkList*)malloc(sizeof(LinkList));//为节点分配空间
		s->data = a[i];//s是节点指针,有data和next两个域,其中next是指针
		s->next = L->next;//即插入的原操作
		L->next = s;//将s指针插到表头指针后面
	}
}

头插法特点:插入到头结点之后,原来的头前面

2、尾插法
在这里插入图片描述

L是头结点,s是数据节点

//2、尾插法
void CreateListF2(LinkList*& L, ElemType a[], int n) {
	LinkList*s,*r;//*r是一个新的指针
	int i;
	L = (LinkList*)malloc(sizeof(LinkList));//创建头结点
	r = L;//先指向头结点
	for ( i = 0; i < n; i++)
	{
		s = (LinkList*)malloc(sizeof(LinkList));
		s->data = a[i];
		r->next = s;//将*s插入*r之后
		r = s;//
	}
	r->next = NULL;
}

销毁线性表:
在这里插入图片描述
需要逐一释放全部节点

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值