【线性表】

本文详细介绍了线性表的两种存储结构——顺序表和链表。顺序表使用连续的存储单元存储元素,适合静态存储,支持快速访问;链表则通过指针链接元素,适合动态存储,但在访问上较慢。文中还具体阐述了顺序表的插入、删除和查找操作,以及链表的头插法和尾插法建立,同时讨论了双链表的插入和删除操作。顺序表与链表各有优劣,适用于不同的应用场景。
摘要由CSDN通过智能技术生成

一、顺序表的定义

线性表的顺序存储又称顺序表。它是用一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻

假定线性表的元素类型为ElemType,则线性表的顺序存储类型描述为:

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

二、顺序表上基本操作的实现

1.插入操作
在顺序表L的第i(1<=i<=L.length+1)个位置插入新元素e。若i的输入不合法,则返回false,表示插入失败;否则,将顺序表的第i个元素及其后的所有元素右移一个位置,腾出一个空位置插入新元素e,顺序表长度增加1,插入成功,返回true。

bool ListInsert(SqList &L,int i,ElemType e){
   if(i<1||i>L.length+1)          //判断i的范围是否有效
       return  false;
   if(L.length>=MaxSize)          //当前存储空间已满,不能插入
       return  false;
   for(int j=L.length;j>=i;j--)    //将第i个元素及之后的元素后移
       L.data[j]=L.data[j-1];
   L.data[i-1]=e;                 //在位置i处放入e
   L.length++;                   //线性表长度加1
   return  true;

2.删除操作
删除顺序表L中第i(1<=i<=L.length)个位置的元素,若成功返回true,并将被删除的元素用引用变量e返回,否则返回false。

bool ListDelete(SqList &L,int i,Elemtype &e){
   if(i<1||i>L,length)              //判断i的范围是否有效
       return  false;
    e=L.data[i-1];                  //将被删除的元素赋值给e
   for(int j=i;j<L.length;j++)      //将第i个位置后的元素前移
      L.data[j-1]=L.data[j];
   L.length--;                      //线性表长度减1
   return  true;
   }

3.按值查找(顺序查找)
在顺序表L中查找第一个元素值等于e的元素,并返回其位序。

int LocateElem(SqList L,ElemType e){
int i;
for(i=0;i<L.length;i++)
   if(L.data[i]==e)
      return  i+1;      //下标为i的元素值等于e,返回其位序i+1
   return  0;           //退出循环,说明查找失败
 }

一、链表的定义

线性表的链式存储又称单链表,它是通过一组任意的存储单元来存储线性表中的数据元素。为了建立数据元素之间的线性关系,对每个链表结点,除存放元素自身的信息外,还需要存放一个指向其后继的指针。
data为数据域,存放数据元素;next为指针域,存放其后继结点的地址。

单链表结点结构:
在这里插入图片描述

单链表中结点类型的描述:

typedef struct LNode{             //定义单链表结点类型
    ElemType data;                //数据域
    struct LNode *next;           //指针域
}LNode, *LinkList;

利用单链表可以解决顺序表需要大量连续存储单元的缺点,但单链表附加指针域,也存在浪费存储空间的缺点。由于单链表的元素离散地分布在存储空间中,所以单链表是非随机存取的存储结构,即不能直接找到表中某个特定的结点。查找某个特定的结点时,需要从表头开始遍历,依次查找。
在这里插入图片描述

二、单链表上基本操作的实现

1.采用头插法建立单链表

该方法是从一个空表开始,生成新结点,并将读取到的数据存放到新结点的数据域中,然后将新结点插入到当前链表的表头,即头结点之后。
在这里插入图片描述

头插法建立单链表
头插法建立单链表的算法如下:

LinkList List_HeadInsert(LinkList &L){ //逆向建立单链表
    LNode *s; int x;
    L=(LinkList)malloc(sizeof(LNode)); //创建头结点
    L—>next=NULL;                      //初始为空链表
    scanf("%d",&x);                    //输入结点的值
    while(x!=9999){                    //输入9999表示结束
        s=(LNode*)malloc(sizeof(LNode));//创建新结点
        s->data=x;
        s->next=L->next;
        L->next=s;                     //将新结点插入表中,L为头指针
        scanf("%d",&x);
    }
    return L;
} 

采用头插法建立单链表时,读入数据的顺序与生成的链表中的元素的顺序是相反的。每个结点插入的时间为O(1),设单链表长为n,则总时间复杂度为O(n)。

2.采用尾插法建立单链表
头插法建立单链表的算法虽然简单,但生成的链表中结点的次序和输入数据的顺序不一致。希望两者次序一致,则可采用尾插法。该方法将新结点插入到当前链表的表尾,为此必须增加一个尾指针r,使其始终指向当前链表的尾结点。
在这里插入图片描述

尾插法建立单链表的算法:
在这里插入图片描述
在这里插入图片描述

3.按序号查找结点值
在这里插入图片描述

4.按值查找表结点
在这里插入图片描述

5.插入结点操作
在这里插入图片描述

6.删除结点操作
在这里插入图片描述

7.求表长操作
在这里插入图片描述

三、双链表

1、双链表的插入操作

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

s->next=p->next; //将结点s插入到结点p之后
p->next->prior=s;
s->prior=p;
p->next=s;

2.双链表的删除操作

删除双链表中结点p的后继结点q,其指针的变化过程:
在这里插入图片描述

删除操作的代码片段:

p->next=q->next; //图2.11中的步骤①
p->next->prior=p; //图2.11中的步骤②
free(q); //释放结点空间
在这里插入图片描述

3.顺序表和链表的比较

在这里插入图片描述

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值