数据结构之线性表

1 线性表的定义和基本操作

1.1 定义

线性表是具有相同数据类型的n个数据元素的有限序列,其中n为表长,当n=0时线性表是一个空表。

线性表的特点:

  • 表中元素个数有限
  • 表中元素具有逻辑上的顺序性,有先后次序
  • 表中元素的数据类型都相同,具有抽象性

2 线性表的顺序表示

2.1 顺序表的定义

顺序表的特点是表中元素的逻辑顺序与其存储的物理顺序相同。
注意 :线性表中元素的位序是从1开始的,而数组中的元素的下标是从0开始的。

静态顺序表

c 复制代码
#define MaxSize 50 //定义线性表的最大长度
typedef struct{
  ElemType data[MaxSize];  //顺序表的元素
  int length;       //顺序表的当前长度
}SqList;    //顺序表的类型定义

顺序表的基本操作:增,删,改,插。

顺序表的优点:①可随机访问;②存储密度高。缺点:①元素的插入和删除需要移动大量元素;②顺序存储分配需要一段连续的存储空间,不够灵活。

2.2顺序表的插入

在顺序表插入元素,需要做到如下两步工作:

  1. 将要插入的位置元素及其后续元素整体向后移动一位
  2. 将元素放到腾出来的位置上

代码:

c 复制代码
bool ListInsert( SqList &L,int i,ElemType e)
{
  if(i<1||i>L.length+1)
    return false; 
  if(L.length>=MaxSize)
    return false;
  for(int j=L.length;j>=i;j++)
  {
    L.data[j]=L.data[j-1];
  }
  L.data[i-1]=e;
  L.length++;
  return true;
}

插入算法的平均时间复杂度为O(n)。

2.3 顺序表的删除

在顺序表中删除元素,就是找到改元素的位置,将其后续元素整体向前移动一个位置。

代码:

c 复制代码
bool ListDelete( SqList &L,int i,ElemType e)
{
  if(i<1||i>L.length+1)
    return false; 
  e=L.data(i-1);
  for(int j=i;j<L.length;j++)
  {
    L.data[j-1]=L.data[j];
  }
  L.length--;
  return true;
}

删除算法的时间复杂度为O(n)。

2.4 顺序表按值查找

在顺序表中查找第一个元素值为e的元素,并返回位序:

c 复制代码
int Locate(SqList L,ElemType e)
{
  int i;
  for(i=0;i<L.length;i++)
  {
    if(L.data[i]==e)
    {
     return i+1;
    }
  }
  return 0;
}

按值查找的平均时间复杂度为O(n)。

3 线性表的链式表达

链式存储就是用指针将相互的结点连接起来,链式存储根据链表的构造不同,可分成:单向链表,单向循环链表,双向链表,双向循环链表。

3.1 单链表的定义

线性表的链式存储也称单链表,它是指通过一组任意的存储单元来存储线性表中的数据元素。

数据域 指针域
data next

数据域:存放数据元素的区域

指针域:存储直接后继位置的区域

单链表:

c 复制代码
typedef struct LNode{
  ElemType data;
  struct LNode *next;
}LNode,*LinkList;

3.1.1 初始化

带头结点的初始化:

c 复制代码
bool InitList(LinkList &L)
{
  L=(LNode*)malloc(sizeof(LNode));
  L->next=NULL;
  return true;
}

3.1.2 求表长

c 复制代码
int Length(LinkList L)
{
  int len=0;
  LNode *p=L;
  while(p->next!=NULL)
  {
   p=p->next;
   len++;
  }
  return len;
}

3.1.3 插入结点操作

插入结点操作将值为x的新结点插入到单链表的第i个位置。

首先查找第i-1个结点,假设第i-1个结点为p,然后令新节点 s 的指针域指向p的后继,再令结点p的指针域指向新插入的结点*s。

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

必须先执行 s->next=p->next,后执行 p->next=s,否则先执行 p->next=s后,指向原后继的指针就不存在了。

时间复杂度是O(n)

3.1.4 删除结点操作

删除结点操作是将单链表的第i个结点删除。

假设结点p为被删除结点的前驱,只需修改 p的指针域,将p的指针域指向q的下一个结点,然后释放*q的存储空间。

c 复制代码
bool ListDelete(LinkList &L,int i,ElemType &e)
{
	 LNode *p=L;
	 int j=0;
	 while(p->next==NULL&&j<i-1)
	 (
	  p=p->next;
	  j++;
	 )
	 if(p->next==NULL||j>i-1)
	 { 
	   return false;
	 }
	 LNode *q=p->next;
	 e=q->data;
	 p->next=q->next;
	 free(q);
	 return true;;
  
}

时间复杂度为O(n)

3.1.5 采用头插法建立单链表

该方法从一个空表开始,生成新的结点,并将读取到的数据放到新结点的数据中,然后将新结点插入到当前链表的表头,即头结点之后。

如图所示:

c 复制代码
Linklist List_HeadInsert(LinkList &L)
{
  LNode *s;int x;
  L=(LNode*)malloc(sizeof(LNode));
  L->next=NULL;
  scanf("%d",&x);
  while(x!=9999)
  {
   s=(LNode*)malloc(sizeof(LNode));
   s->data=x;
   s->next=L->next;
   L->next=s;
   scanf("%d",&x);
  }
  return L;
}

3.1.6 采用尾插法建立单链表

该方法将新结点插入到当前链表的表尾,为必须增加一个尾指针 r,使其始终指向当前链表的尾结点。

如图所示:

c 复制代码
Linklist List_TailInsert(LinkList &L)
{
  int x;
  L=(LNode*)malloc(sizeof(LNode));
  LNode *s,*r=L;
  scanf("%d",&x);
  while(x!=9999)
  {
   s=(LNode*)malloc(sizeof(LNode));
   s->data=x;
   r->next=s;
   r=s;
   scanf("%d",&x);
  }
  r->next=NULL;
  return L;
}

3.2 头指针和头结点

链表中,第一个结点存储的位置叫头指针 ,如果链表由头结点,那么头指针就是指向头结点的指针。

头指针所指的不存在数据元素的第一个结点就叫做头结点 (而头结点又指向首元结点),头结点一般不存放数据,存放第一个数据元素的结点叫做第一个数据元素节点,也叫做首元结点。

相关推荐
小超超爱学习993716 小时前
大数乘法,超级简单模板
开发语言·c++·算法
Ricardo-Yang16 小时前
SCNP语义分割边缘logits策略
数据结构·人工智能·python·深度学习·算法
凌波粒16 小时前
LeetCode--344.反转字符串(字符串/双指针法)
算法·leetcode·职场和发展
啊哦呃咦唔鱼16 小时前
LeetCode hot100-543 二叉树的直径
算法·leetcode·职场和发展
soragui17 小时前
【Python】第 4 章:Python 数据结构实现
数据结构·windows·python
sinat_2869451917 小时前
harness engineering
人工智能·算法·chatgpt
少许极端17 小时前
算法奇妙屋(四十三)-贪心算法学习之路10
学习·算法·贪心算法
samroom17 小时前
【鸿蒙应用开发 Dev ECO Studio 5.0版本】从0到1!从无到有!最全!计算器------按钮动画、滑动退格、中缀表达式转后缀表达式、UI设计
数据结构·ui·华为·typescript·harmonyos·鸿蒙
算法鑫探18 小时前
10个数下标排序:最大值、最小值与平均值(下)
c语言·数据结构·算法·排序算法·新人首发
样例过了就是过了18 小时前
LeetCode热题100 爬楼梯
c++·算法·leetcode·动态规划