线性表之顺序表的基本操作

线性表的定义

线性表是具有相同数据类型的 n ( n > = 0 ) n(n>= 0) n(n>=0)个数据元素的有限序列,其中 n n n为表长,当 n = 0 n=0 n=0时线性表是一个空表。若用 L L L命名线性表,则其一般表示为 L = ( a 1 , a 2 , . . . , a i , a i + 1 , . . . , a n ) L=(a_1,a_2,...,a_i,a_{i+1}, ..., a_n) L=(a1,a2,...,ai,ai+1,...,an)式中, a 1 a_1 a1是唯一的"第一个"数据元素,又称表尾元素。除第一个元素外,每个元素有且仅有一个直接前驱。除最后一个元素外,每个元素有且仅有一个直接后续。
所以,线性表的特点如下:

  1. 表中元素的个数有限
  2. 表中元素具有逻辑上的顺序性,表中元素有其先后次序
  3. 表中元素都是数据元素,每个元素都是单个元素
  4. 表中元素的数据类型都相同,这意味着每个元素占有相同大小的存储空间
  5. 表中元素元素具有抽象性,即仅讨论元素间的逻辑关系,而不是考虑元素究竟表示什么内容
    注意:线性表是一种逻辑结构,表示元素之间一对一的相邻关系。顺序表和链表是指存储结构两者属于不同层面的概念,因此不要将其混淆。

顺序表的定义

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

顺序表的基本操作的实现

前期准备
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 50
typedef struct{
    int data[MaxSize];
    int length;
}SqList;

void InitList(SqList* L)
{
    L->length = 0;
};

void Input(SqList* L)
{
    int i;
    printf("输入-1作为结束\n");
    while (1 && L->length < MaxSize){
        scanf("%d", &i);
        if (i == -1)
            break;
        L->data[L->length++] = i;
    }
};

void PrintList(SqList L)
{
    if (L.length == 0)
        printf("这是一个空列表\n");
    else
    {
        printf("展示结果\n");
        for(int i=0; i < L.length;i++)
            printf("%d ", L.data[i]);
        printf("\n");
    }
};
(1) 插入操作

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

/**************************************
顺序表的插入操作
L 表示原顺序表
i 表示插入的第i个位置
e 表示插入的值
return 如果可以插入返回1,否则返回0
**************************************/

int ListInster(SqList* L, int i, int e){
    if(i < 1 || i > L->length + 1)
        return 0;
    if (L->length >= MaxSize)
        return 0;
    for(int j = L->length; j >= i;  j--)
        L->data[j] = L->data[j - 1];
    L->data[i - 1] = e;
    L->length ++;
    return 1;
};

最好情况:在表尾插入(即 i = n + 1 i=n+1 i=n+1),时间复杂度为 O ( 1 ) O(1) O(1)
最坏情况:在表头插入(即 i = 1 i=1 i=1),时间复杂度为 O ( n ) O(n) O(n)
平均情况:假设 p i ( p i = 1 ( n + 1 ) ) p_i(p_i=\frac{1}{(n+1)}) pi(pi=(n+1)1)是在第 i i i个位置上插入一个结点的概率,则在长度为 n n n的线性表中插入一个结点时,所需要移动结点的平均次数为 ∑ i = 1 n + 1 p i ( n − i + 1 ) = ∑ i = 1 n + 1 1 n + 1 ( n − i + 1 ) = 1 1 + n ∑ i = 1 n + 1 ( n − i + 1 ) = 1 1 + n n ( n + 1 ) 2 = n 2 \sum^{n+1}_{i=1}{p_i(n-i+1)}=\sum^{n+1}_{i=1}{\frac{1}{n+1}(n-i+1)}=\frac{1}{1+n}\sum^{n+1}_{i=1}(n-i+1)=\frac{1}{1+n}\frac{n(n+1)}{2}=\frac{n}{2} i=1n+1pi(ni+1)=i=1n+1n+11(ni+1)=1+n1i=1n+1(ni+1)=1+n12n(n+1)=2n
因此,线性表插入算法的平均时间复杂度为 O ( n ) O(n) O(n)

(2)删除操作

删除顺序表 L L L中第 i ( 1 < = i < = L . l e n g t h ) i(1<=i<=L.length) i(1<=i<=L.length)个位置的元素,若成功则返回1,并将被删除的元素用引用变量 e m em em返回,否则返回0

/**********************************************
顺序表的删除操作
L 表示原顺序表
i 表示删除第i个位置
em 表示用指针返回被删除位置的值
return 如果可以删除返回1,否则返回0
**********************************************/

int ListDelete(SqList *L, int i, int *em)
{
    if (i < 1 || i > L->length)
        return 0;
    *em = L->data[i-1];
    for (int j = i; j<L->length; j++)
    {
        L->data[j - 1] = L->data[j];
    }
    L->length --;
    return 1;
}

最好情况:在表尾删除(即 i = n i=n i=n),时间复杂度为 O ( 1 ) O(1) O(1)
最坏情况:在表头删除(即 i = 1 i=1 i=1),时间复杂度为 O ( n ) O(n) O(n)
平均情况:假设 p i ( p i = 1 n ) p_i(p_i=\frac{1}{n}) pi(pi=n1)是删除第 i i i个位置上结点的概率,则在长度为 n n n的线性表中删除一个结点时,所需要移动结点的平均次数为 ∑ i = 1 n p i ( n − i ) = ∑ i = 1 n 1 n ( n − i ) = 1 n ∑ i = 1 n ( n − i ) = 1 n n ( n − 1 ) 2 = n − 1 2 \sum^{n}_{i=1}{p_i(n-i)}=\sum^{n}_{i=1}{\frac{1}{n}(n-i)}=\frac{1}{n}\sum^{n}_{i=1}(n-i)=\frac{1}{n}\frac{n(n-1)}{2}=\frac{n-1}{2} i=1npi(ni)=i=1nn1(ni)=n1i=1n(ni)=n12n(n1)=2n1
因此,线性表删除算法的平均时间复杂度为 O ( n ) O(n) O(n)

(3)按值查找(顺序查找)

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

/*************************************************
顺序表按值查找操作
L 表示原顺序表
e 表示在顺序表中找到的第一个元素值等于e的元素
return 如果可以找到返回其位序,否则返回0
**************************************************/

int LocateElem(SqList L, int e)
{
    int i;
    for (i=0; i < L.length; i ++)
        if (L.data[i] == e)
        return i+1;
    return 0;
}

最好情况:查找的元素就在表头,时间复杂度为 O ( 1 ) O(1) O(1)
最坏情况:查找的元素就在表尾,时间复杂度为 O ( n ) O(n) O(n)
平均情况:假设 p i ( p i = 1 n ) p_i(p_i=\frac{1}{n}) pi(pi=n1)是查找的元素在第 i ( 1 < = i < = L . l e n g t h ) i(1<=i<=L.length) i(1<=i<=L.length)个位置上的概率,则在长度为 n n n的线性表中查找值为 e e e时所需要比较的平均次数为 ∑ i = 1 n p i ∗ i = ∑ i = 1 n 1 n ∗ i = 1 n n ( n + 1 ) 2 = n + 1 2 \sum^{n}_{i=1}{p_i*i}=\sum^{n}_{i=1}{\frac{1}{n}*i}=\frac{1}{n}\frac{n(n+1)}{2}=\frac{n+1}{2} i=1npii=i=1nn1i=n12n(n+1)=2n+1
因此,线性表按值查找算法的平均时间复杂度为 O ( n ) O(n) O(n)

主函数代码
int main()
{
    SqList* L;
    int em;
    L = (SqList *)malloc(sizeof(SqList));
    int i=3, e=4, ii = 2;
    int res;
    InitList(L);
    Input(L);
    PrintList(*L);
    # 插入
    res = ListInster(L, i, e);
    if (res==1)
        printf("可以在第%d的位置上插入%d\n", i, e);
    else
        printf("无法插入\n");
    PrintList(*L);
    # 删除
    res = ListDelete(L, ii, &em);
    if (res==1)
        printf("已经删除了第%d的位置上的%d\n", ii, em);
    else
        printf("无法删除\n");
    PrintList(*L);
    # 按值查找
    res = LocateElem(*L, 4);
    if (res==0)
        printf("未找到该元素\n");
    else
        printf("4在列表的第%d个位置上\n", res);
    return 0;
};

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

是强筱华哇!

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

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

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

打赏作者

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

抵扣说明:

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

余额充值