数据结构---顺序表

文章目录


定义

顺序表是线性表的顺序存储结构 ,其核心特征是:用一组地址连续的 存储单元依次 存储线性表中的元素,使得逻辑上相邻的元素在物理内存中也相邻。

如何理解这里的物理与逻辑 ?

①物理存储连续:所有元素存放在一片连续的内存空间中(类似数组).

复制代码
    例如:存储元素 [1,2,3] 的顺序表,在内存中可能占用地址 0x100 ~ 0x111(假设每个 int 占 4 字节),每个元素的地址依次递增 4 字节。

②逻辑与物理顺序一致:线性表中元素的逻辑顺序(即 "第 1 个、第 2 个...... 第 n 个")与它们在内存中的物理存储顺序完全相同。

复制代码
    例如:逻辑上的 "第 2 个元素",在物理内存中一定存储在 "第 1 个元素" 的后面、"第 3 个元素" 的前面.

代码实现

要实现顺序表的代码,不仅要实现顺序表的定义 ,还要完成一系列的增删改查的操作

定义
c 复制代码
#define MAX_SIZE 100
//定义能够存储任意数据类型的数组  结构体
typedef struct SeqList
{
    void* data[MAX_SIZE];//指针数组,里面全是指针数据元素
    int size;
}SeqList;

之所以指针数组,是因为数组里面全部放的void*的指针,指针的大小是由操作系统决定的,这就意味着指针数组中的每个元素都是占8字节(X64电脑),但是指针具体指向的内容,可以是任意类型,这也是这个设计的美妙之处.这里不需要capacity,因为结构体的定义,已经写了指针数组的大小,相当于capacity了

知识点:

1.void* 是 通用指针类型(泛型指针)

2.它可以指向任意类型的数据

2.所有类型的指针都可以被隐式转换为 void*

附:

另一种定义方式,非指针数组:

c 复制代码
typedef int SLdataType;
typedef struct Seqlist
{
	SLdataType* a;
	SLdataType size;
	SLdataType capacity;
} SL;  //声明这个结构体
创建
c 复制代码
//创建顺序表
SeqList* create()
{
    SeqList * SL = (SeqList*)calloc(1,sizeof(SeqList));
    if (SL == NULL)
    {
        printf("create fail");
        exit(0);
    }
    else
    {
        SL->size = 0;
        return SL;
    }
}
增加
c 复制代码
void add(SeqList* SL,void* element)
{
    if(! is_full)
    {
        SL->data[SL->size] = element;
        SL->size++;
    }else
    {
        printf("Seqlist is already full,you can not add element\n");
    }
}

element就是要添加的指针,就像上面说的,这个指针可以是任意类型的指针,反正都只占8字节

查找
c 复制代码
void* find_element(SeqList* SL,int index)
{
    if(! is_empty(SL))
    {
        if (index < 0 || index >= SL->size )
        {
            printf("invalid index");
            return NULL;
        }else
        {
            void* temp = SL->data[index];
            return temp;
        }
    }
}

根据下标去进行查找对应的元素,找到返回对应的指针

删除
c 复制代码
//删除数据
int delete(SeqList* SL,int index)
{
    if(is_empty(SL))
    {
        printf("There is no element\n");
        return 0; 
    }
    else if (index < 0 || index >= SL->size )
    {
        printf("invalid index");
        return 0;
    }else
    {
        for (size_t i = index; i < SL->size - 1; i++)
        {
            SL->data[i] = SL->data[i+1];
        }
        SL->size--;
        return SL->size;
    }
}

接受值是int,返回0代表删除失败,返回非0才代表删除成功

修改
c 复制代码
int modify(SeqList *SL,int index,void* element){
    //空数组无法修改
    if (is_empty(SL))
    {
        printf("数组为空,修改失败!\n");
        return 0;
    }
    //index必须有效
    if (index<0 || index>=SL->size)
    {   
        printf("无效index,请查证!\n");
        return 0;//修改失败
    }
    //修改
    SL->data[index]=element;
    return 1;//修改成功
}

顺序表修改数据元素,找到index 直接覆盖

释放
c 复制代码
//释放
void free_SL(SeqList *SL){
    //不能释放NULL
    if (SL)
    {
        free(SL);
    }
}

一些功能函数

c 复制代码
//2.判断顺序表是否为空
int is_empty(SeqList* SL){
    return SL->size==0;
}

//3.判断顺序表是否已满
int is_full(SeqList* SL){
    return SL->size>=MAX_SIZE;
}

主函数使用

c 复制代码
```c
int main(int argc, char const *argv[])
{
    //1.创建数组
    array *SL=create();
    //2.添加数据
    int a=9527;
    double b=7.77;
    char c='U';
    printf("&a=%p,&b=%p,&c=%p\n",&a,&b,&c);
    add(SL,&a);
    add(SL,&b);
    add(SL,&c);

    //2.通过index查询数据,返回数据的指针
    int *ip=(int*)get_element(SL,0); 
    double *dp=(double*)get_element(SL,1); 
    char *cp=(char*)get_element(SL,2); 

    printf("ip=%p,dp=%p,cp=%p,*ip=%d,*dp=%lf,*cp=%c\n",ip,dp,cp,*ip,*dp,*cp);
    //4.指定index删除元素
    int res=delete(SL,2);
    if (res)
    {
        int* ip2=(int*)get_element(SL,0); 
        ip=(int*)get_element(SL,1);
        dp=(double*)get_element(SL,2); 
        cp=(char*)get_element(SL,3); 
        int* ip4=(int*)get_element(SL,4); 
        printf("ip2=%p,ip=%p,dp=%p,cp=%p,ip4=%p,*ip2=%d,*ip=%d,*dp=%lf,*cp=%c,*ip4=%d\n",ip2,ip,dp,cp,ip4,*ip2,*ip,*dp,*cp,*ip4);
    }

    //5.指定index修改元素
    double h=9.99;
    res=modify(SL,1,&h);
    if (res)
    {
        ip2=(int*)get_element(SL,0); 
        double *dp2=(double*)get_element(SL,1);
        dp=(double*)get_element(SL,2); 
        cp=(char*)get_element(SL,3); 
        ip4=(int*)get_element(SL,4); 
        printf("ip2=%p,dp2=%p,dp=%p,cp=%p,ip4=%p,*ip2=%d,*dp2=%lf,*dp=%lf,*cp=%c,*ip4=%d\n",ip2,dp2,dp,cp,ip4,*ip2,*dp2,*dp,*cp,*ip4);
    }
    //last.释放数组
    free_SL(SL);
    return 0;
}

我们写的delete(),modify()函数都使用int作为返回值,main()函数中也给出了如何合理运用这个整型返回值,那就是if (res)来查看是否删除或修改成功

相关推荐
好奇龙猫2 小时前
【大学院-筆記試験練習:线性代数和数据结构(12)】
数据结构·线性代数
sin_hielo2 小时前
leetcode 1292(二维前缀和)
数据结构·算法·leetcode
炽烈小老头2 小时前
【 每天学习一点算法 2026/01/19】位1的个数
学习·算法
孩子 你要相信光2 小时前
解决:React 中 map 处理异步数据不渲染的问题
开发语言·前端·javascript
jllllyuz2 小时前
ANPC三电平逆变器损耗计算的MATLAB实现
开发语言·matlab·php
Watermelo6172 小时前
面向大模型开发:在项目中使用 TOON 的实践与流式处理
javascript·数据结构·人工智能·语言模型·自然语言处理·数据挖掘·json
aini_lovee2 小时前
基于MATLAB Simulink的定轴齿轮与行星齿轮仿真模型
开发语言·matlab
软件开发技术深度爱好者2 小时前
JavaScript的p5.js库使用详解(下)
开发语言·前端·javascript
一叶之秋14122 小时前
深入剖析List的底层实现原理
c++·list