结构体线性表一——顺序表

目录

顺序表

一.全部代码

二.预备工作

a.SeqList.h

b.SeqList.c

c.test.c

三.写码工作(SeqList.h暂且忽略)

1.顺序表的定义

2.顺序表的初始化

a.SeqList.c

b.test.c

c.调试看看是否正确

3.顺序表的销毁

4.顺序表的插入

a.头插

头插代码

检查容量是否够

代码

b.尾插

c.指定插入

5.删除

6.查找


顺序表

前言:要想实现顺序表一定要清楚顺序表的底层逻辑就是数组。在顺序表的实现功能中只要我们会插入其他简直太简单了。

我们今天要分享的主要内容是顺序表的实现。大致内容请看图

一.全部代码

//头文件

#include<stdio.h>
//开辟空间需要用到calloc或malloc或realloc
#include<stdlib.h>
#include<assert.h>
typedef int SLDateType;
typedef struct SeqList
{
    SLDateType* arr;
    
    //描述数组arr里存储数据的个数
    int size;
    //描述数组arr的内存大小
    int capicty;
}SL;

//函数实现
//顺序表初始化
void SLInit(SL* object)
{
    object->arr = 0;
    object->size = 0;
    object->capicty = 0;
}
//顺序表的打印
void Print(SL object)
{
    printf("\n");
    
    for (int i = 0; i < object.size; i++)
    {
        printf("%d ", object.arr[i]);//
    }
}
//销毁
void Destory(SL* object)
{
    if (object->arr)
    {
        object->arr = NULL;
    }
    object->size = 0;
    object->capicty = 0;
}
//检查内存
void CheckCapicty(SL* object)
{
    //扩容条件
    if (object->size == object->capicty) {
        int NewCapicty = object->capicty == 0 ? 4 : 2 * object->capicty;
        SLDateType* Re = (SLDateType*)realloc(object->arr, sizeof(SLDateType) * NewCapicty);
        if (Re == 0)
        {
            printf("内存开辟失败");
            exit(1);
        }
        object->arr = Re;
        object->capicty = NewCapicty;
    }
}
//头插
void pophead(SL* object, SLDateType H1)
{
    assert(object);
    //检查arr容量是否够
    CheckCapicty(object);
    for (int i = object->size; i > 0; i--)
    {
        object->arr[i] = object->arr[i - 1];
    }
    object->arr[0] = H1;
    object->size++;
}
//尾插
void popblack(SL* object, SLDateType B1)
{
    assert(object);
    CheckCapicty(object);
    object->arr[object->size] = B1;
    object->size++;
}
//指定插入
void popChoice(SL* object, int number1, SLDateType C1)
{
    assert(object);
    //检查number1的值是否合理
    assert(number1 >= 0 && number1 < object->size);
    for (int i = object->size; i > number1; i--)
    {
        object->arr[i] = object->arr[i - 1];
    }
    object->arr[number1] = C1;
    object->size++;
}
//头删
void Delethead(SL* object)
{
    assert(object);
    for (int i = 1; i < object->size; i++)
    {
        object->arr[i - 1] = object->arr[i];
    }
    object->size--;
}
//尾删
void Deletblack(SL* object)
{
    assert(object);
    object->size--;
}
//指定删除
void DeletChoice(SL* object, int number2)
{
    assert(object);
    assert(number2 >= 0 && number2 < object->size);
    for (int i = number2; i < object->size-1; i++)
    {
        object->arr[i] = object->arr[i+1];
    }
    object->size--;
}
//查找
int Find(SL* object, SLDateType F)
{
    assert(object);
    for (int i = 0; i < object->size; i++)
    {
        if (object->arr[i] == F)
        {
            return i;
        }
    }
    return -1;
}
//测试是否写的正确

void test()
{
    SL brr;
    SLInit(&brr);
    pophead(&brr, 1);
    pophead(&brr, 11);
    pophead(&brr, 19);
    pophead(&brr, 13);
    
    Print(brr);
    popblack(&brr, 2);
    popblack(&brr, 103);
    popblack(&brr, 101);
    popblack(&brr, 109);
    Print(brr);
    popChoice(&brr, 1, 10);
    Print(brr);
    Delethead(&brr);
    Print(brr);
    Deletblack(&brr);
    Print(brr);
    DeletChoice(&brr, 1);
    Print(brr);
    int find = Find(&brr, 11);
    if (find > 0)
    {
        printf("找到了下标是%i", find);
    }
    else
    {
        printf("nothing");
    }
    Destory(&brr);
}
int main()
{
    test();
    return 0;
}

二.预备工作

1.我们可以把顺序表分为三个内容:SeqList.h(头文件),SeqList.c(实现文件),test.c(测试文件)

a.SeqList.h

把要申明的东西写在一起

b.SeqList.c

我们要对顺序表SL进行初始化,插入,删除,查找,这些功能可以写成函数,放在SeqList.c

c.test.c:测试我们写的函数是否正确,简而言之就是写函数。

比如

c.test.c

测试函数是否写的正确

三.写码工作(SeqList.h暂且忽略)

1.顺序表的定义

顺序表的底层逻辑是数组,基于这个原理我们编写出如下代码

//我们不知道我们的数组类型会不会变,所以给它一个名字

typedef int SLDateType;
typedef struct Seqlist{
    SLDateType* arr;
//描述数组arr里存储数据的个数
    int size;
    //描述数组arr的内存大小
    int capicty;
}SL;

2.顺序表的初始化

a.SeqList.c

//SeqList.c

#include"SeqList.h"
void SLInit(SL* object)
{
    object->arr = 0;
    object->size = 0;
    object->capicty = 0;
}

b.test.c

#include"SeqList.h"
void test()
{
    SL brr;
    SLInit(&brr);
}
int main()
{
    test();
    return 0;
}

c.调试看看是否正确

3.顺序表的销毁

为什么要销毁呢,因为当我们使用malloc/calloc/realloc为其开辟空间结束时要把空间还给操作系统

void Destory(SL* object)
{
    if (object->arr)
    {
        object->arr = NULL;
    }
    object->size = 0;
    object->capicty = 0;
}

4.顺序表的插入

a.头插

画画图我们就知道啦

头插代码

void pophead(SL* object, SLDateType H1)
{
    assert(object);
    //检查arr容量是否够
    CheckCapicty(object);
    for (int i = object->size; i > 0; i--)
    {
        object->arr[i] = object->arr[i - 1];
    }
    object->arr[0] = H1;
    object->size++;
}

注意增加减少都要改变size的值

检查容量是否够

代码

void CheckCapicty(SL* object)
{
    //是否扩容条件
    if (object->size == object->capicty) {

//扩大容量,运用三目操作符
        int NewCapicty = object->capicty == 0 ? 4 : 2 * object->capicty;

//防止扩容失败,之前的数据被影响
        SLDateType* Re = (SLDateType*)realloc(object->arr, sizeof(SLDateType) * NewCapicty);
        if (Re == 0)
        {
            printf("内存开辟失败");
            exit(1);
        }
        object->arr = Re;
        object->capicty = NewCapicty;
    }
}

b.尾插

思想:检查是否扩容然后尾部直接插入

void popblack(SL* object, SLDateType B1)
{
    assert(object);
    CheckCapicty(object);
    object->arr[object->size] = B1;
    object->size++;
}

c.指定插入

//指定插入
void popChoice(SL* object, int number1, SLDateType C1)
{
    assert(object);
    //检查number1的值是否合理
    assert(number1 >= 0 && number1 < object->size);
    for (int i = object->size; i > number1; i--)
    {
        object->arr[i] = object->arr[i - 1];
    }
    object->arr[number1] = C1;
    object->size++;
}

5.删除

如果我们学会了头插尾插指定插,这个肯定不在话下

//头删
void Delethead(SL* object)
{
    assert(object);
    for (int i = 1; i < object->size; i++)
    {
        object->arr[i - 1] = object->arr[i];
    }
    object->size--;

}

//尾删
void Deletblack(SL* object)
{
    assert(object);
    object->size--;
}
//指定删除
void DeletChoice(SL* object, int number2, SLDateType C2)
{
    assert(object);
    assert(number2 >= 0 && number2 < object->size);
    for (int i = number2; i < object->size-1; i++)
    {
        object->arr[i] = object->arr[i+1];
    }
    object->size--;
}

//简直爽歪歪

6.查找

思想:一个个访问,如果是则返回下标,和数组查找相同数一样

int Find(SL* object, SLDateType F)
{
    assert(object);
    for (int i = 0; i < object->size; i++)
    {
        if (object->arr[i] == F)
        {
            return i;
        }
    }
    return -1;
}

OK到这里基本就差不多了,只要学会了插入,剩下的不要太轻松了!此顺序表是动态顺序表,静态顺序表的空间是一定的,不需要开辟空间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值