C语言数据结构篇——顺序表的理解,创建,插入和删除

简介: C语言数据结构篇——顺序表的理解,创建,插入和删除

作为一名才接触c语言半年的大一学生,在自学数据结构时是非常痛苦的,单是第一章顺序表的创建与操作就令我苦不堪言,在经过两天的钻研后,基本才算理顺了顺序表,所以我就想写下这篇人生中第一篇博客记录我对c语言数据结构中顺序表的理解。(初学者一名,有什么不对的地方大家可以提出来一起讨论,万分感谢)


数据结构主要研究的就是数据在计算机中的存储和处理方法,而线性表就是最简单而且最常用的一种数据结构,线性表的三大特点,有头结点,尾结点,其他的每个结点都有前驱节点和后驱结点,线性表的顺序存储就称为顺序表。


简单的说,顺序表可以看做一个数组,而大多数人习惯用结构体保存顺序表的信息。那怎样创建一个顺序表呢?顺序表是线性表的一种,所以按照线性表的三大特点,首先我们需要建立一个结构体头结点来存放顺序表的信息,因为顺序表创建后需要用来填充数据,但数据并不一定填满所以头结点存放的信息的第一个——你创建的顺序表容量,第二个自然就是你实际使用的顺序表容量。那么问题来了?数据放在哪里?上面讲了,顺序表可以看做一个数组,那我们第三个信息就可以定义一个指向数组首地址的指针,而这个数组就用来保存数据,一个结构体形式的顺序表头结点就建立好了(用来存放顺序表的总容量,顺序表已经使用的容量,一个指向用来存放数据的数组的首地址的指针),代码如下:


顺序表头结点的建立


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct begin_SeqList//定义的头结点结构体用来保存结构体的信息
{
    int capacity;//顺序表长度
    int length;//实际使用的长度
    int *node;//指向数组node[capacity]首地址的指针(存放数据)
}TSeqList;


顺序表的创建


接下来就是按头结点所保存的信息建立顺序表了(就是写一个函数)这个函数的作用就是创建好顺序表(包括头结点和储存数据的数组)并返回顺序表的地址(也就是头结点),创建失败就返回NULL,这样使用顺序表时就可以通过返回的头结点中指向数组首地址的指针存放数据到数组中,具体代码如下:


TSeqList* SeqList_creat(int capacity)//创建指定容量的顺序表返回创建好的顺序表
{
    TSeqList *temp=NULL;
    temp=(TSeqList *)malloc(sizeof(TSeqList));//为头结点分配空间
    if(temp==NULL)//判断申请失败的情况
    {
        printf("SeqList_Creat():error");
        return NULL;//结束创建
    }
    memset(temp,0,sizeof(TSeqList));//使用memset初始化顺序表(库函数,可以查阅)
    temp->capacity=capacity;
    temp->length=0;
    temp->node=(int *)malloc(sizeof(int )*capacity);//分配头结点指定容量的数组分配空间
    if(temp->node==NULL)//申请失败
    {
        printf("SeqList_Creat():error");
        return NULL;
    }
    return temp;//返回分配好的顺序表地址
}


顺序表的使用


如上,一个顺序表就常见完成了,但怎么使用呢?我最开始在网上查阅“顺序表怎么使用”,但搜出来的都是顺序表数据的插入,删除,查找等操作,现在我才认为我这个问题属实有点弱智了,顺序表的使用其实就是对一个创建好的数组的赋值嘛,哈哈,这么一说你们是不是明白多了。下面就随便写一个顺序表的使用,具体代码如下,粗略看一下就行。(主要还是研究插入,删除等操作的)


int main()
{
    int capacity;
    printf("请输入顺序表的容量\n");
    scanf("%d",&capacity);
    TSeqList *p;//用来接收返回的顺序表;
    p=SeqList_creat(capacity);//引用顺序表
    printf("输入顺序表(-1结束输入)\n");
    for(int i=0;i<p->capacity;i++)//给顺序表赋值
    {
       scanf("%d",&p->node[i]);
       while(p->node[i]==-1)
      {
          goto start;(库函数,可查阅)
      }
       p->length++;
    }
    start:
    printf("输出顺序表\n");
    for(int i=0;i<p->length;i++)
    {
        printf("%d ",p->node[i]);
    }
}

封装顺序表插入数据函数


好了,顺序表的基本知识弄清楚了,那就需要了解顺序表的插入,删除,这些操作了(重点),这里都用封装函数的方式写,首先是顺序表中元素的插入,顺序表插入时需要考虑的东西很多,首先,刚才应该判断刚才顺序表是否创建成功(健壮性判断),即创建顺序表的函数返回的是不是空;第二个考虑的就是顺序表的容量是不是已经使用完了,如果顺序表已满,你可以选择再分配内存给新的数据或者提示分配错误(偷个懒,哈哈);


int SeqList_insert(TSeqList *list,int x,int pos)//顺序表,要插入的元素,在哪里插入
{
    TSeqList *temp=NULL;
    if(list==NULL)//顺序表创建失败
    {
        return -1;
    }
    temp=list;//重点
    if(temp->length==temp->capacity)//顺序表已满(这个和创建失败也可以用||连接)
    {
        return -1;
    }
    if(pos>temp->length)//尾插(可以改变pos在实际长度后面,即中间有空余的情况)
    {
        pos=temp->length;
    }
    for(int i=temp->length;i>pos;i--)//实际的length比现在大1,所以不会越界
    {
        temp->node[i]=temp->node[i-1];
    }
    temp->node[pos]=x;
    temp->length++;
    return 0;
}


顺序表插入函数的完整使用  


所以插入数据的函数就封装完了,我们来使用一下,注意这里插入的位置pos相当于数组的下标,例如1235,需要在第4个位置插入一个4,而第四个位置下标是3,所以此时的pos应该代3;


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct begin_SeqList//定义的头结点结构体用来保存结构体的信息
{
    int capacity;//最大长度
    int length;//当前长度
    int *node;//定义指针数组node[capacity](存放数据)
}TSeqList;
TSeqList* SeqList_creat(int capacity)//创建指定容量的顺序表返回创建好的顺序表
{
    TSeqList *temp=NULL;
    temp=(TSeqList *)malloc(sizeof(TSeqList));//为头结点分配空间
    if(temp==NULL)//判断申请失败的情况
    {
        printf("SeqList_Creat():error");
        return NULL;//结束创建
    }
    memset(temp,0,sizeof(TSeqList));//使用memset初始化顺序表(库函数,可以查阅)
    temp->capacity=capacity;
    temp->length=0;
    temp->node=(int *)malloc(sizeof(int )*capacity);//分配头结点指定容量的数组分配空间
    if(temp->node==NULL)//申请失败
    {
        printf("SeqList_Creat():error");
        return NULL;
    }
    return temp;//返回分配好的顺序表地址
}
int SeqList_insert(TSeqList *list,int x,int pos)//顺序表,要插入的元素,在哪里插入
{
    TSeqList *temp=NULL;
    if(list==NULL)//顺序表创建失败
    {
        return -1;
    }
    temp=list;//重点
    if(temp->length==temp->capacity)//顺序表已满(这个和创建失败也可以用||连接)
    {
        return -1;
    }
    if(pos>temp->length)//尾插(可以改变pos在实际长度后面,即中间有空余的情况)
    {
        pos=temp->length;
    }
    for(int i=temp->length;i>pos;i--)//实际的length比现在大1,所以不会越界
    {
        temp->node[i]=temp->node[i-1];
    }
    temp->node[pos]=x;
    temp->length++;
    return 0;
}
int main()
{
    int capacity;
    printf("请输入顺序表的容量\n");
    scanf("%d",&capacity);
    TSeqList *p;
    p=SeqList_creat(capacity);//引用顺序表
    printf("输入顺序表(-1结束输入)\n");
    for(int i=0;i<p->capacity;i++)
    {
       scanf("%d",&p->node[i]);
       while(p->node[i]==-1)
      {
          goto start;
      }
       p->length++;
    }
    start:
    printf("输出顺序表\n");
    for(int i=0;i<p->length;i++)
    {
        printf("%d ",p->node[i]);
    }
    printf("\n");
    int x;
    int Node;
    printf("输入插入的元素和位置\n");
    scanf("%d %d",&x,&Node);
    int m=SeqList_insert(p,x,Node);
    if(m!=0)
    {
        printf("SeqList_insert():error %d\n",m);
    }
    printf("插入后的顺序表\n");
    for(int i=0;i<p->length;i++)
    {
        printf("%d ",p->node[i]);
    }
}


运行一下就是下面这个效果


请输入顺序表的容量

10

输入顺序表(-1结束输入)

1 2 3 4 5 7 -1

输出顺序表

1 2 3 4 5 7

输入插入的元素和位置

6 5

插入后的顺序表

1 2 3 4 5 6 7


顺序表数据的删除


相比于插入,删除要考虑的就比较少,只需要考虑顺序表创建失败的情况或者删除的位置有问题的情况,但因为要移动元素,所以效率还是比较低,代码如下:


int SeqList_delete(TSeqList *list,int pos)//删除数据(顺序表,删除位置)
{
    TSeqList *temp=NULL;
    if(list==NULL||pos<0||pos>list->length)
    {
        return -1;
    }
    temp=list;
    for(int i=pos+1;i<temp->length;i++)
    {
        temp->node[i-1]=temp->node[i];
    }
    temp->length--;
    return 0;
}


顺序表删除函数的完整使用  


顺序表的数据删除函数就封装好了,使用具体代码如下:


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct begin_SeqList//定义的头结点结构体用来保存结构体的信息
{
    int capacity;//最大长度
    int length;//当前长度
    int *node;//定义指针数组node[capacity](存放数据)
}TSeqList;
TSeqList* SeqList_creat(int capacity)//创建指定容量的顺序表返回创建好的顺序表
{
    TSeqList *temp=NULL;
    temp=(TSeqList *)malloc(sizeof(TSeqList));//为头结点分配空间
    if(temp==NULL)//判断申请失败的情况
    {
        printf("SeqList_Creat():error");
        return NULL;//结束创建
    }
    memset(temp,0,sizeof(TSeqList));//使用memset初始化顺序表
    temp->capacity=capacity;
    temp->length=0;
    temp->node=(int *)malloc(sizeof(int )*capacity);//分配指定容量的数组
    if(temp->node==NULL)//申请失败
    {
        printf("SeqList_Creat():error");
        return NULL;
    }
    return temp;//返回分配好的顺序表地址
}
int SeqList_delete(TSeqList *list,int pos)//删除数据(顺序表,删除位置)
{
    TSeqList *temp=NULL;
    if(list==NULL||pos<0||pos>list->length)
    {
        return -1;
    }
    temp=list;
    for(int i=pos+1;i<temp->length;i++)
    {
        temp->node[i-1]=temp->node[i];
    }
    temp->length--;
    return 0;
}
int main()
{
    int capacity;
    printf("请输入顺序表的容量\n");
    scanf("%d",&capacity);
    TSeqList *p;
    p=SeqList_creat(capacity);//引用顺序表
    printf("输入顺序表(-1结束输入)\n");
    for(int i=0;i<p->capacity;i++)
    {
       scanf("%d",&p->node[i]);
       while(p->node[i]==-1)
      {
          goto start;
      }
       p->length++;
    }
    start:
    printf("输出顺序表\n");
    for(int i=0;i<p->length;i++)
    {
        printf("%d ",p->node[i]);
    }
    printf("\n");
    printf("请输入要删除的元素位置\n");
    int x,m;
    scanf("%d",&x);
    m=SeqList_delete(p,x);
    if(m!=0)
    {
         printf("SeqList_delete(): error\n");
    }
    printf("输出删除后的顺序表\n");
    for(int i=0;i<p->length;i++)
    {
        printf("%d ",p->node[i]);
    }
}

请输入顺序表的容量

10

输入顺序表(-1结束输入)

1 2 3 4 5 -1

输出顺序表

1 2 3 4 5

请输入要删除的元素位置

2

输出删除后的顺序表

1 2 4 5


运行下来就是这个效果啦,顺序表的操作还有查找,清空(内容全部置为0),销毁(释放分配的内存)等 ,都是差不多的思路,理解了上面两个之后就很好写了,由于这是我第一次写博客,感觉语言有些繁琐,再加上刚学c语言没多久,可能代码优化也不够完善,如果有什么错误希望大家见谅,万分感谢。

相关文章
|
3天前
|
存储 算法 C语言
通义灵码在考研C语言和数据结构中的应用实践 1-5
通义灵码在考研C语言和数据结构中的应用实践,体验通义灵码的强大思路。《趣学C语言和数据结构100例》精选了五个经典问题及其解决方案,包括求最大公约数和最小公倍数、统计字符类型、求特殊数列和、计算阶乘和双阶乘、以及求斐波那契数列的前20项和。通过这些实例,帮助读者掌握C语言的基本语法和常用算法,提升编程能力。
|
11天前
|
存储 编译器 C语言
数据结构-顺序表详解(看这篇就足够了,哈哈哈)
数据结构-顺序表详解(看这篇就足够了,哈哈哈)
44 2
|
3天前
|
存储 算法 C语言
【趣学C语言和数据结构100例】
《趣学C语言和数据结构100例》精选5个编程问题,涵盖求最大公约数与最小公倍数、字符统计、特殊序列求和及阶乘计算等,通过实例讲解C语言基础与算法思维,适合初学者实践学习。
|
13天前
|
存储 Java
数据结构第二篇【关于java线性表(顺序表)的基本操作】
数据结构第二篇【关于java线性表(顺序表)的基本操作】
24 6
|
13天前
|
存储 安全 Java
【用Java学习数据结构系列】探索顺序表和链表的无尽秘密(附带练习唔)pro
【用Java学习数据结构系列】探索顺序表和链表的无尽秘密(附带练习唔)pro
18 3
|
13天前
|
存储 C语言
探索C语言数据结构:利用顺序表完成通讯录的实现
本文介绍了如何使用C语言中的顺序表数据结构实现一个简单的通讯录,包括初始化、添加、删除、查找和保存联系人信息的操作,以及自定义结构体用于存储联系人详细信息。
17 2
|
13天前
|
C语言
链式顺序表实现(C语言描述)
本文介绍了如何在C语言中实现链式顺序表,包括数据结构的定义、节点的创建、数据的插入和删除以及链表的打印和销毁。
33 2
|
13天前
|
C语言
顺序表数组法构建(C语言描述)
如何使用C语言通过数组方法构建有序顺序表,包括顺序表的创建、插入、删除和打印等。
14 2
|
16天前
|
存储 算法 索引
【数据结构】——顺序表
【数据结构】——顺序表
|
16天前
|
存储
【数据结构】线性表和顺序表
【数据结构】线性表和顺序表
18 1