关于数据结构(c语言)中,线性表中顺序存储结构的大部分操作的代码实现

        数据结构是计算机专业必学的一门课程,如果说算法是一个程序的操作动作,那么数据结构就是一个程序的灵魂,它让一段程序在运行过程中,拥有足够强大的“内力”进行代码的实现。

        数据结构的三要素分为逻辑结构,存储结构和运算。而本篇文章将要介绍的线性表,是数据结构入门内容,也正因为是一个入门内容,它的重要性也不言而喻。将数据结构中的线性表学习透彻,将在数据结构之后的学习中打好坚实的基础。

        本篇文章将要介绍的,是线性表(逻辑结构)中的顺序结构(存储结构),是限线性表的基础之一,而在下列程序中,将要通过对顺序表进行初始化、判断空满、输出、追加、插入、删除、逆序、升序排序(冒泡排序)的分段过程,对整段代码进行分析解剖。

         第一部分:创建一个结构体,使该结构体中有顺序表的首地址、长度和有效元素的个数。顺序表的首地址是一个指针,类似于数组中的第一个元素的地址,作为整个顺序表中的“导航”;分别定义长度和有效元素个数的目的,在于之后判断顺序表满或空的情况,便于灵活操作。

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

struct SqList
{
    int * pBase; //顺序表的首地址
    int length; //顺序表的长度
    int cnt; //有效元素个数
};

第二部分:提前对所需操作的函数进行函数声明,对顺序表进行初始化、判断空满、输出、追加、插入、删除、逆序、升序排序(冒泡排序)的操作,也便于为具体代码的书写时理清思路。

void init_sl(struct SqList * pSl,int len); //初始化顺序表
bool is_empty(struct SqList * pSl); //判断是顺序表是否为空
bool is_full(struct SqList * pSl); //判断顺序表是否为满
void show_sl(struct SqList * pSl); //输出顺序表的元素
bool appand(struct SqList * pSl, int val); //在顺序表中追加元素
bool insert_sl(struct SqList * pSl, int pos, int val); //在顺序表中插入一个元素
bool delete_sl(struct SqList * pSl, int pos, int * pVal); //在顺序表中删除一个元素,并将删除元素存储下来
void inverse_sl(struct SqList * pSl); //将顺序表中的元素逆序
void sort_sl(struct SqList * pSl); //对顺序表中的元素进行排序

第三部分:将结构体变量实例化为sl,并进行各类操作。要注意的是,在形参列表中对顺序表的取地址操作符是必要的,原因是sl本身是一个顺序表,取地址类似于数组中取下标地址的操作。

int main(void)
{
    struct SqList sl;
    int val;
init_sl(&sl,7);
appand(&sl,1);
appand(&sl,3);
appand(&sl,2);
appand(&sl,5);
appand(&sl,4);
appand(&sl,7);
appand(&sl,6);
printf("初始顺序表为:\n");
show_sl(&sl);
if(delete_sl(&sl,4,&val))
{
    printf("删除成功,删除的元素为:%d\n",val);
}
    else
    {
        printf("删除失败!\n");
    }
    printf("删除元素后的顺序表为:\n");
show_sl(&sl);
insert_sl(&sl, 6, 100);
printf("插入一个元素后的顺序表为:\n");
show_sl(&sl);
sort_sl(&sl);
printf("升序排序后的顺序表为:\n");
show_sl(&sl);
inverse_sl(&sl);
printf("逆序后的顺序表为:\n");
show_sl(&sl);

    return 0;
}

第四部分:各类操作的具体代码实现。

1.顺序表的初始化 void init_sl(struct SqList * pSl, int len);

首先对顺序表的首地址进行动态内存的分配,这时要使用c语言内置的malloc函数,其调用格式是(元素数据类型*)malloc(sizeof(元素数据类型)*定义的顺序表长度)。分配操作结束后,对分配情况进行判断,若顺序表首地址为空,则动态内存分配失败;若不为空,则对顺序表进行初始化,使其初始长度为定义长度,有效元素个数为0。

2.顺序表的空满判断 bool is_empty(struct SqList * pSl) ;  bool is_full(struct SqList * pSl);

空判断:判断顺序表的有效元素个数是否为0,若为0则返回true,否则返回false。

满判断:判断顺序表中的有效元素个数是否与顺序表的长度相等,若相等则返回true,否则返回false。

3.输出  void show_sl(struct SqList * pSl);

首先判断顺序表是否为空,若为空则无法进行输出操作,否则,输出(类似于数组的输出操作)。

4.追加 bool appand_sl(struct SqList * pSl, int val);

函数的形参列表中需要多传入一个val,成为追加在顺序表中的元素。追加操作中,首先判断顺序表是否已满,若已满则无法进行后续操作,返回false,否则,使将要追加的元素赋值给,以有效元素为下标的顺序表元素,最后使有效元素个数加一,返回true。

5.插入 bool insert_sl(struct SqList *pSl, int pos, int val);

函数的形参列表中需要多传入插入元素的位置(需要插入的指定元素的位置之前)和插入的元素的值。判断顺序表是否为满,若为满则无法进行插入操作,返回false;判断插入的位置是否符合逻辑,即插入的位置不能在第0个元素之前(pos<1),也不能在最后一个有效元素的下一个位置之后(pos>pSl->cnt+1),返回false;否则,将插入元素之后的元素,从最后一个元素开始依此往后移动一个位置,使得将要插入的位置空出后,把待插入的元素插入移动出的空位中,返回true。

6.删除 bool delete_sl(struct SqList *pSl, int pos, int * pVal);

函数的形参列表中引入一个可以存储被删除元素的值的变量,便于在最终操作中查看所删除的值(该形参 int * pVal 可有可无,据需求而定)。与插入操作判断类似,要判断顺序表是否为空,若为空则返回false;判断删除元素的位置是否符合逻辑,无法删除“第零个元素”(pos<1),也无法删除有效元素之后的“元素”(pos>pSl->cnt),返回false;将待删除的元素存放在*pVal中,所谓的删除操作,实则使将待删除的元素的位置之后的元素,由近到远地依此向前移动一个位置,将待删除的元素覆盖,即为所谓删除,删除后有效元素个数减一,返回true。

7.逆序 void inverse_sl(struct SqList * pSl);

通过得到整个顺序表首部和尾部下标,展开逆序操作。首先通过while循环,当首部作为的下标一直小于尾部作为的下标时,进入循环,进行首尾元素交换的操作,并通过首部作为的下标加一,尾部作为的下标减一,达到代码健壮性的目的。

8.升序排序(冒泡排序) void sort_sl(struct SqList * pSl);

比较简单的算法内容,在此不作赘述分析。

void init_sl(struct SqList * pSl, int len)
{
    pSl->pBase=(int *)malloc(sizeof(int)*len);
    if(NULL==pSl->pBase)
    {
        printf("动态内存分配失败,程序终止!\n");
        exit(-1);
    }
    pSl->length=len;
    pSl->cnt=0;
    return;
}

bool is_empty(struct SqList * pSl)
{
    if(0==pSl->cnt)
    {
        return true;
    }
    else
    {
        return false;
    }
}

bool is_full(struct SqList * pSl)
{
    if(pSl->cnt==pSl->length)
    {
        return true;
    }
    else
    {
        return false;
    }
}

void show_sl(struct SqList * pSl)
{
    if(is_empty(pSl))
    {
        printf("顺序表为空!\n");
    }
    for(int i=0;i<pSl->cnt;++i)
    {
        printf("%d",pSl->pBase[i]);
        printf("\n");
    }
}

bool appand(struct SqList * pSl, int val)
{
    if(is_full(pSl))
    {
        return false;
    }
    pSl->pBase[pSl->cnt]=val;
    pSl->cnt++;
    return true;
}

bool insert_sl(struct SqList * pSl, int pos, int val)
{
    if(is_full(pSl))
    {
        return false;
    }
    if(pos<1||pos>pSl->cnt+1)
    {
        return false;
    }
    for(int i=pSl->cnt-1;i>=pos-1;--i)
    {
        pSl->pBase[i+1]=pSl->pBase[i];
    }
    pSl->pBase[pos-1]=val;
    pSl->cnt++;
    return true;
}

bool delete_sl(struct SqList * pSl, int pos, int * pVal)
{
    if(pos<1||pos>pSl->cnt)
    {
        return false;
    }
    if(is_empty(pSl))
    {
        return false;
    }
    * pVal=pSl->pBase[pos-1];
    for(int i=pos;i<pSl->cnt;++i)
    {
        pSl->pBase[i-1]=pSl->pBase[i];
    }
    pSl->cnt--;
    return true;
}

void inverse_sl(struct SqList * pSl)
{
    int start=0;
    int end=pSl->cnt-1;
    if(is_empty(pSl))
    {
        printf("顺序表为空!\n");
    }
    while(start<end)
    {
        int t=pSl->pBase[start];
        pSl->pBase[start]=pSl->pBase[end];
        pSl->pBase[end]=t;
        start++;
        end--;
    }
}

void sort_sl(struct SqList * pSl)
{
    if(is_empty(pSl))
    {
        printf("顺序表为空!\n");
    }
    for(int i=0;i<pSl->cnt-1;i++)
    {
        for(int j=0;j<pSl->cnt-i-1;j++)
        {
            if(pSl->pBase[j]>pSl->pBase[j+1])
            {
                int t=pSl->pBase[j];
                pSl->pBase[j]=pSl->pBase[j+1];
                pSl->pBase[j+1]=t;
            }
        }
    }
    return;
}

        以上所有的操作细节和代码具体实现的思想以叙述完毕,希望对各位读者有所帮助。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

grx_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值