C语言如何实现顺序表(数据结构)

 更新时间:2023年08月18日 09:40:11   作者:桜キャンドル淵  
这篇文章主要介绍了C语言如何实现顺序表(数据结构)问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

以下是我们需要实现的顺序表的功能。 

以下是写在SeqList.h中的内容,我们将全部需要声明的内容放在此处

pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef int SLDateType;
typedef struct SeqList
{
    SLDateType* a;
    size_t size;// 当前存储的数据个数
    size_t capacity; //允许的最大容量
}SeqList;
// 对数据的管理:增删查改
void SeqListInit(SeqList* ps);//初始化顺序表
void SeqListDestory(SeqList* ps);//摧毁顺序表
void SLCheckCapacity(SeqList * ps);//检查空间是否充足
void SeqListPrint(SeqList* ps);//打印列表中的所有元素的值
void SeqListPushBack(SeqList* ps, SLDateType x);//在表尾插入数据
void SeqListPushFront(SeqList* ps, SLDateType x);//在表头位置插入数组
void SeqListPopFront(SeqList* ps);//弹出列表的首个元素
void SeqListPopBack(SeqList* ps);//弹出列表的尾元素
// 顺序表查找
int SeqListFind(SeqList* ps, SLDateType x);
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* ps, size_t pos, SLDateType x);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, size_t pos);

接下来我们来实现函数具体的功能

以下代码是写在SeqList.c中的内容

一、初始化顺序表

这里我们用assert判断ps是否为NULL,也就是我们的顺序表是否创建成功。

如果创建成功,我们就将顺序表中的数组,当前的元素个数,顺序表的大小初始化。

并且打印初始化成功来提示我们完成了初始化。

#include"SeqList.h"
void SeqListInit(SeqList* ps)
{
    assert(ps);
    ps->a=NULL;
    ps->capacity=0;
    ps->size=0;
    printf("初始化列表成功\n");
}

二、从表尾插入元素

在用assert实现断言之后,我们用(四)中的函数功能检查ps当前的空间是否充足,在空间充足之后,我们在顺序表的表尾添加我们的新元素。

void SeqListPushBack(SeqList* ps, SLDateType x)
{
    assert(ps);
    SLCheckCapacity(ps);
    ps->a[ps->size]=x;
    ps->size++;
    printf("已成功添加至表尾\n");
}

三、打印顺序表

在断言之后,我们按照顺序挨个打印顺序表中的元素。

void SeqListPrint(SeqList* ps)
{
    assert(ps);
    for(int i=0;i<ps->capacity;i++)
    {
        printf("%d\t",ps->a[i]);
    }
    printf("\n");
    printf("成功打印\n");
}

四、检查顺序表的空间是否充足

当我们判断当前的已经含有的元素个数和总的存储空间大小相同的时候,先判断当前元素大小是不是0,如果是0,我们就将新的元素个数赋值为4,如果不是0,也就是不是初始化之后,我们将我们的元素个数×2。

当然,我们的realloc函数存在开辟空间失败的问题,我们需要进行一定的判断。

void SLCheckCapacity(SeqList * ps)
{
    if (ps->size == ps->capacity)
    {
        int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
        SLDateType* tmp = (SLDateType*)realloc(ps->a, newCapacity*sizeof(SLDateType));
        if (tmp == NULL)
        {
            printf("realloc fail\n");
            //exit(-1);
            return;
        }
        ps->a = tmp;
        ps->capacity = newCapacity;
    }
}

五、在顺序表表首插入元素

我们需要先将顺序表中的每个元素后移一位,然后在表首的位置插入我们需要插入的元素。

void SeqListPushFront(SeqList* ps, SLDateType x)
{
    assert(ps);
    SLCheckCapacity(ps);
    for(int end=ps->size;end>=0;end--)
    {
        ps->a[end+1]=ps->a[end];
    }
    ps->a[0]=x;
    printf("在表首元素插入成功\n");
}

六、摧毁数据表

摧毁数据表我们需要将数据表的数组指针置空,将其中的元素个数和大小全部赋零。

void SeqListDestory(SeqList* ps)
{
    assert(ps);
    ps->a=NULL;
    ps->capacity=0;
    ps->size=0;
    printf("摧毁列表成功\n");
}

七、弹出顺序表的首元素

将首元素弹出并且打印之后,我们将首元素之后的元素每一个元素往前移动。

void SeqListPopFront(SeqList* ps)
{
    assert(ps);
    if(ps->a[0]!=NULL)
    {
        int temp=ps->a[0];
        printf("数组的首元素是%d,已成功从列表中弹出\n",temp);
        for(int i=0;i<ps->capacity-1;i++)
        {
            ps->a[i]=ps->a[i+1];
        }
        ps->capacity-=1;
    }
    else
    {
        printf("当前列表为空,无法弹出首元素\n");
    }
}

八、弹出顺序表的表尾元素

将表尾的元素打印,并且将总的元素个数-1

void SeqListPopBack(SeqList* ps)
{
    assert(ps);
    printf("数组的尾元素是%d,已成功从列表中弹出\n",ps->a[ps->capacity-1]);
    ps->capacity-=1;
}

九、查找顺序表中的元素,并返回第一次出现的位置

我们采用for循环的形式查找顺序表中指定元素的位置,然后返回其下标。

int SeqListFind(SeqList* ps, SLDateType x)
{
    assert(ps);
    for(int i=0;i<ps->capacity;i++)
    {
        if(ps->a[i]==x)
        {
            printf("在顺序表的%d位置(此处为真实位置-1)查找到了%d元素\n",i,x);
            return i;
        }
    }
    printf("查找不到该元素\n");
    return -1;
}

十、在指定位置插入元素

在指定位置插入元素,我们需要将指定位置之后的元素后移一位,为我们的指定位置的元素腾出空间,然后将我们的元素插入。

void SeqListInsert(SeqList* ps, size_t pos, SLDateType x)
{
    assert(ps);
    assert(pos >= 0 && pos <= ps->size);
    //检查空间
    ps->capacity++;
    SLCheckCapacity(ps);
    for(int end=ps->size;end>=pos;end--)
    {
        ps->a[end]=ps->a[end-1];
    }
    ps->a[pos-1]=x;
    printf("已经在列表的%d位置成功插入%d元素\n",pos,x);
}

十一、删除指定位置的元素

我们将指定位置之后的元素挨个往前移动,就能够删除指定位置的元素。

void SeqListErase(SeqList* ps, size_t pos)
{
    assert(ps);
    assert(pos >= 0 && pos <= ps->size);
    for(int i=pos;i<ps->capacity-1;i++)
    {
        ps->a[i-1]=ps->a[i];
    }
    ps->capacity--;
    printf("已经成功删除列表%d位置处的元素\n",pos);
}

接下来就是我们的测试代码

以下代码写在test.c文件中

#include "SeqList.h"
int main() {
    SeqList sl;
    SeqListInit(&sl);
    SeqListPushBack(&sl,10);
    SeqListPushBack(&sl,1);
    SeqListPushBack(&sl,20);
    SeqListPushBack(&sl,30);
    SeqListPushFront(&sl, 8);
    SeqListPrint(&sl);
    SeqListPopFront(&sl);
    SeqListPrint(&sl);
    printf("%d",sl.capacity);
    SeqListPopBack(&sl);
    SeqListPrint(&sl);
    SeqListFind(&sl,0);
    SeqListInsert(&sl,4, 10);
    SeqListPrint(&sl);
    SeqListErase(&sl,3);
    SeqListPrint(&sl);
    SeqListDestory(&sl);
    printf("程序已完成执行");
    return 0;
}

以下是SeqList.c中代码的合集 

//
// Created by 杨凯亮 on 2022/4/22.
//
#include"SeqList.h"
void SeqListInit(SeqList* ps)
{
    assert(ps);
    ps->a=NULL;
    ps->capacity=0;
    ps->size=0;
    printf("初始化列表成功\n");
}
void SeqListPushBack(SeqList* ps, SLDateType x)
{
    assert(ps);
    SLCheckCapacity(ps);
    ps->a[ps->size]=x;
    ps->size++;
    printf("已成功添加至表尾\n");
}
void SeqListPrint(SeqList* ps)
{
    assert(ps);
    for(int i=0;i<ps->capacity;i++)
    {
        printf("%d\t",ps->a[i]);
    }
    printf("\n");
    printf("成功打印\n");
}
void SLCheckCapacity(SeqList * ps)
{
    if (ps->size == ps->capacity)
    {
        int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
        SLDateType* tmp = (SLDateType*)realloc(ps->a, newCapacity*sizeof(SLDateType));
        if (tmp == NULL)
        {
            printf("realloc fail\n");
            //exit(-1);
            return;
        }
        ps->a = tmp;
        ps->capacity = newCapacity;
    }
}
void SeqListPushFront(SeqList* ps, SLDateType x)
{
    assert(ps);
    SLCheckCapacity(ps);
    for(int end=ps->size;end>=0;end--)
    {
        ps->a[end+1]=ps->a[end];
    }
    ps->a[0]=x;
    printf("在表首元素插入成功\n");
}
void SeqListDestory(SeqList* ps)
{
    assert(ps);
    ps->a=NULL;
    ps->capacity=0;
    ps->size=0;
    printf("摧毁列表成功\n");
}
void SeqListPopFront(SeqList* ps)
{
    assert(ps);
    if(ps->a[0]!=NULL)
    {
        int temp=ps->a[0];
        printf("数组的首元素是%d,已成功从列表中弹出\n",temp);
        for(int i=0;i<ps->capacity-1;i++)
        {
            ps->a[i]=ps->a[i+1];
        }
        ps->capacity-=1;
    }
    else
    {
        printf("当前列表为空,无法弹出首元素\n");
    }
}
void SeqListPopBack(SeqList* ps)
{
    assert(ps);
    printf("数组的尾元素是%d,已成功从列表中弹出\n",ps->a[ps->capacity-1]);
    ps->capacity-=1;
}
int SeqListFind(SeqList* ps, SLDateType x)
{
    assert(ps);
    for(int i=0;i<ps->capacity;i++)
    {
        if(ps->a[i]==x)
        {
            printf("在顺序表的%d位置(此处为真实位置-1)查找到了%d元素\n",i,x);
            return i;
        }
    }
    printf("查找不到该元素\n");
    return -1;
}
void SeqListInsert(SeqList* ps, size_t pos, SLDateType x)
{
    assert(ps);
    assert(pos >= 0 && pos <= ps->size);
    //检查空间
    ps->capacity++;
    SLCheckCapacity(ps);
    for(int end=ps->size;end>=pos;end--)
    {
        ps->a[end]=ps->a[end-1];
    }
    ps->a[pos-1]=x;
    printf("已经在列表的%d位置成功插入%d元素\n",pos,x);
}
void SeqListErase(SeqList* ps, size_t pos)
{
    assert(ps);
    assert(pos >= 0 && pos <= ps->size);
    for(int i=pos;i<ps->capacity-1;i++)
    {
        ps->a[i-1]=ps->a[i];
    }
    ps->capacity--;
    printf("已经成功删除列表%d位置处的元素\n",pos);
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Qt使用QChart实现动态显示温度变化曲线

    Qt使用QChart实现动态显示温度变化曲线

    Qt的QChart是一个用于绘制图表和可视化数据的类,提供了一个灵活的、可扩展的、跨平台的图表绘制解决方案,所以本文就将使用QChart实现动态显示3个设备的温度变化曲线,感兴趣的可以了解一下
    2023-06-06
  • C语言实现扫雷算法简易版

    C语言实现扫雷算法简易版

    这篇文章主要为大家详细介绍了C语言实现扫雷算法简易版,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • C语言计算Robots机器人行走路线

    C语言计算Robots机器人行走路线

    这篇文章介绍了C语言计算Robots机器人行走路线,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-12-12
  • Qt实现绘制一个简单多边形的示例代码

    Qt实现绘制一个简单多边形的示例代码

    QT提供了图形绘制接口QPainter,通过该接口可以绘制多种图形,包括多边形。本文就来利用它实现绘制一个简单的多边形,感兴趣的可以尝试一下
    2022-11-11
  • C++11/14的新特性(更简洁)

    C++11/14的新特性(更简洁)

    这篇文章主要介绍了C++11/14的新特性(更简洁),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • c++11中std::move函数的使用

    c++11中std::move函数的使用

    本文主要介绍了c++11中std::move函数的使用,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • C语言数据结构之顺序表和单链表

    C语言数据结构之顺序表和单链表

    在数据结构中,线性表是入门级数据结构,线性表又分为顺序表和链表,这篇文章主要给大家介绍了关于C语言数据结构之顺序表和单链表的相关资料,需要的朋友可以参考下
    2021-06-06
  • C语言链表案例学习之通讯录的实现

    C语言链表案例学习之通讯录的实现

    为了将所学到的链表的知识进行巩固学习,做到学以致用,本文将利用链表制作一个简单的通讯录。文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2022-10-10
  • C++入门到精通之循环语句的使用教程

    C++入门到精通之循环语句的使用教程

    这篇文章主要给大家介绍了关于C++中循环语句的用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05
  • C++名称空间特性

    C++名称空间特性

    这篇文章主要介绍了C++名称空间特性,文章围绕C++名称空间特性的相关资料展开详细内容,需要的小伙伴可以参考一下下文具体内容,希望对你的学习有所帮助
    2022-01-01

最新评论