[数据结构] Data Structure(2) 之线性表(顺序存储结构)

线性表的顺序存储结构,指的是用一段连续的存储单元存储线性表的数据元素。

线性表特性

· 是一个序列,元素直接是有序的。
· 表中元素个数叫表长,元素个数可以有多个,也可以为0。
· 某个元素的上一个元素叫直接前驱元素,下一个元素叫直接后继元素。

顺序存储结构特点

使用数组对元素进行存储。
优点:
· 可以快速存储表中任意位置的元素的值。
· 无需为表中的逻辑关系增加额外的存储空间。
缺点:
· 插入和删除元素需移动大量的元素。
· 容易生成存储空间“碎片”。

时间复杂度

· 读取时的时间复杂度为O(1)。
· 插入、删除时的时间复杂度为O(n)。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

算法实现

#include <stdio.h>
#include <stdlib.h>

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

#define MAXSIZE 20

typedef int Status;
typedef int ElemType;

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

//初始化线性表
Status InitList(SqList *L)
{
    L->length = 0;
    return OK;
}

//判空
Status ListEmpty(SqList L)
{
    if(L.length == 0)
    {
        return TRUE;
    } else {
        return FALSE;
    }
}

//清空线性表
Status ClearList(SqList *L)
{
    L->length = 0;
    return OK;
}

//获取线性表长度
int ListLength(SqList L)
{
    return L.length;
}

/**
 * 获取线性表中指定位置的元素值
 * @param i 获取元素位置下标
 * @param e 获取元素值
 */
Status GetElem(SqList L, int i, ElemType *e)
{
    if (L.length == 0 || i < 1 || i > L.length)
    {
        return ERROR;
    }
    *e = L.data[i - 1];
    return OK;
}

//定位元素e在线性表中的位置
int LocateElem(SqList L, ElemType e)
{
    int i;
    if(L.length == 0)
    {
        return 0;
    }

    if (i >= L.length)
    {
        return 0;
    }

    for (i = 0; i < L.length; i++)
    {
        if(L.data[i] == e)
        {
            break;
        }
    }

    return i + 1;
}

//在线性表中指定位置插入新元素
Status ListInsert(SqList *L, int i, ElemType e)
{
    int k;  //用于遍历元素的下标

    if(L->length == MAXSIZE)
    {
        return ERROR;
    }
    if(i < 1 || i > L->length + 1)
    {
        return ERROR;
    }

    //插入的位置在线性表范围内
    if(i <= L->length)
    {
        //从倒数第二个元素开始到插入位置的元素,全都向后移动一个位置
        for(k = L->length - 1; k >= i - 1; k--)
        {
            L->data[k + 1] = L->data[k];
        }
    }
    L->data[i - 1] = e;
    L->length++;
    return OK;
}

Status ListDelete(SqList *L, int i, ElemType *e)
{
    int k;

    if (L->length == 0)
    {
        return ERROR;
    }

    if (i < 1 || i > L->length)
    {
        return ERROR;
    }

    *e = L->data[i - 1];

    if (i < L->length)
    {
        for (k = i; k < L->length; k++)
        {
                L->data[k - 1] = L->data[k];
        }
    }
    L->length--;
    return OK;
}

//打印单个元素
Status visit(ElemType e)
{
    printf("%d ", e);
    return OK;
}


//遍历输出线性表中所有元素
Status ListTravel(SqList L)
{
    int i;  //用于遍历元素的下标
    printf("[ ");
    for (i = 0; i < L.length; i++)
    {
        visit(L.data[i]);
    }
    printf("]\n");
    return OK;
}

void unionL(SqList *La, SqList Lb)
{
    int i;
    int La_len, Lb_len;
    ElemType e;

    La_len = ListLength(*La);
    Lb_len = ListLength(Lb);

    for (i = 1; i <= Lb_len; i++)
    {
        GetElem(Lb, i, &e);
        if(!LocateElem(*La, e))
        {
            ListInsert(La, ++La_len, e);
        }
    }
}

int main()
{
    SqList L;
    SqList Lb;
    Status status;
    ElemType e;
    int result;
    int j, k;

    InitList(&L);
    printf("初始化线性表L后,L的长度为:%d\n", L.length);

    result = ListEmpty(L);
    printf("L是否为空:%s\n", result == TRUE ? "是" : "否");

    for(j = 1; j <= 5; j++)
    {
        status = ListInsert(&L, 1, j);
    }
    printf("在L表头依次插入1-5后,L中的值为:");
    ListTravel(L);

    printf("插入5个元素后,L的长度为:%d\n", L.length);

    result = ListEmpty(L);
    printf("L是否为空:%s\n", result == TRUE ? "是" : "否");

    status = ClearList(&L);
    printf("清空线性表L后,L的长度为:%d\n", L.length);

    result = ListEmpty(L);
    printf("L是否为空:%s\n", result == TRUE ? "是" : "否");

    //给L的表尾插入10个元素
    for (j = 1; j <= 10; j++)
    {
        ListInsert(&L, j, j);   //向线性表表尾插入值
    }

    printf("插入10个元素后,L中的值为:");
    ListTravel(L);

    printf("插入10个元素后,L的长度为:%d\n", L.length);

    ListInsert(&L, 1, 33);

    printf("在L表头插入元素33后,L中的值为:");
    ListTravel(L);

    printf("插入元素33后,L的长度为:%d\n", L.length);

    GetElem(L, 5, &e);
    printf("L中第5个元素的值为:%d\n", e);

    for (j = 3; j <= 4; j++)
    {
        k = LocateElem(L, j);
        if(k)
        {
            printf("第%d个元素的值为:%d\n", k, j);
        } else {
            printf("没有值为%d的元素\n", j);
        }
    }

    k = ListLength(L);
    for (j = k + 1; j >= k; j--)
    {
        status = ListDelete(&L, j, &e);
        if (status == ERROR)
        {
            printf("删除第%d个元素失败\n", j);
        }else{
            printf("删除的第%d个元素为%d\n", j, e);
        }
    }

    printf("删除表中元素后,L中的值为:");
    ListTravel(L);

    j = 5;
    ListDelete(&L, j, &e);
    printf("删除第%d个元素的值为:%d\n", j, e);

    printf("删除第%d个元素后,L中的值为:", j);
    ListTravel(L);

    status = InitList(&Lb);
    for (j = 6; j <= 15; j++)
    {
        status = ListInsert(&Lb, 1, j);
    }
    printf("插入10个元素后,Lb中的值为:");
    ListTravel(L);

    unionL(&L, Lb);

    printf("合并L到Lb后,L中的值为:");
    ListTravel(L);

    system("pause\n");
    return 0;
}

运行结果
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值