002+limou+顺序表

0、前要:线性表的概念

(1)线性表(linear list)是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构,常见的线性表有 :顺序表、链表、栈、队列、字符串等

(2)线性表在逻辑上是线性结构,也就说是连续的一条直线。

(3)线性表在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储

简单来说就是其数据存储后看起来就是一条线

1、顺序表(sequence list)的概念

  • 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
  • 顺序表一般可以分为:
    • 静态顺序表:使用定长数组存储
    • 动态顺序表:使用动态开辟的数组存储

2、顺序表的实现

一般情况下我们使用动态顺序表,而不使用静态顺序表

(1)顺序表结构体

typedef int SLDataType;
typedef struct SeqList
{
	SLDataType* array;//存储数据
	size_t size;//当前已存储的数量
	size_t capicity;//当前最大容量
}SeqList;

(2)顺序表初始化

void SeqListInit(SeqList* psl)
{
    assert(psl);//避免空指针
    SLDataType* cache = (SLDataType*)malloc(sizeof(SLDataType) * INITIAL_NUMBER);//初始化就给INITIAL_NUMBER个数据空间
    if (!cache)
    {
        perror("malloc fail");
        return;
    }
    psl->array = cache;//申请成功就将这块可用空间给顺序表
    psl->size = 0;
    psl->capicity = INITIAL_NUMBER;
}

(3)顺序表销毁

void SeqListDestory(SeqList* psl)
{
    assert(psl);
    free(psl->array);
    psl->array = NULL;
    psl->capicity = psl->size = 0;
}

(4)顺序表打印

void SeqListPrint(SeqList* psl)
{
    assert(psl);
    if (psl->size == 0)
    {
        printf("空顺序表\n");
        return;
    }
    for (int i = 0; i < psl->size; i++)
    {
        printf("%d ", psl->array[i]);
    }
    printf("\n");
}

(5)检查空间,如果满了,进行增容

void CheckCapacity(SeqList* psl)
{
    assert(psl);
    if (psl->capicity == psl->size)
    {
        SLDataType* cache = (SLDataType*)realloc(psl->array, sizeof(SLDataType) * psl->capicity * 2);
        if (!cache)
        {
            perror("malloc fail");
            return;
        }

        psl->array = cache;
        psl->capicity *= 2;//容量倍增
    }
}

(6)顺序表尾插

void SeqListPushBack(SeqList* psl, SLDataType x)
{
    assert(psl);
    CheckCapacity(psl);//检查是否已满,满则增容
    psl->array[psl->size++] = x;
    //psl->size++;
}

(7)顺序表尾删

void SeqListPopBack(SeqList* psl)
{
    //直接操控size就可以
    assert(psl);
    assert(psl->size > 0);//直接使用较为暴力的检查,这样就会直接报错
    //if (psl->size > 0)
    //{
        psl->size--;
    //}
    //else
    //{
    //    printf("删除失败\n");//比较柔和的检查
    //}
}

(8)顺序表头插

void SeqListPushFront(SeqList* psl, SLDataType x)
{
    assert(psl);
    CheckCapacity(psl);
    //if (psl->size > 0)//这个判断没有必要
    //{
        for (int i = psl->size - 1; i >= 0; i--)
        {
            psl->array[i + 1] = psl->array[i];
        }
    //}
    psl->array[0] = x;
    psl->size++;
    //实际上还有另外一种简单的方式就是使用mommove库函数
}

(9)顺序表头删

void SeqListPopFront(SeqList* psl)
{
    assert(psl);
    assert(psl->size > 0);//暴力检查
    //if (psl->size > 0)
    //{
        for (int i = 0; i < psl->size - 1; i++)
        {
            psl->array[i] = psl->array[i + 1];
        }
        psl->size--;
    //}
    //else
    //{
    //    printf("删除失败\n");
    //}
}

(10)顺序表查找

int SeqListFind(SeqList* psl, SLDataType x)
{
    assert(psl);
    for (int i = 0; i < psl->size; i++)
    {
        if (psl->array[i] == x)
        {
            return i;//返回x的下标
        }
    }
    return -1;//下标不可能是负数
}

(11)顺序表在pos位置的值前插入x

void SeqListInsert(SeqList* psl, int pos, SLDataType x)
{
    assert(psl);//避免解引用空指针
    CheckCapacity(psl);//避免容量不够

    //if (pos == 0 && psl->size == 0)//这一串代码是多余的,后面的代码足以完成头插和尾插
    //{
    //    psl->array[0] = x;
    //    psl->size++;
    //    return;
    //}

    assert(pos <= psl->size && pos >= 0);//检查pos的合法性,等号代表头插和尾插
    for (int i = psl->size - 1; i >= pos; i--)//如果是头插和尾插就不会进入循环
    {
        psl->array[i + 1] = psl->array[i];
    }
    psl->array[pos] = x;
    psl->size++;
}

(12)顺序表在pos位置的值删除

void SeqListErase(SeqList* psl, int pos)
{
    assert(psl);
    assert(pos < psl->size && pos >= 0);//检查pos的合法性,注意有了这个语句就不需要加上assert(psl->size > 0);这条语句,因为被这条语句间接检查了
    for (int i = pos; i < psl->size - 1; i++)
    {
        psl->array[i] = psl->array[i + 1];
    }
    psl->size--;
}

(13)顺序表在pos位置的值被修改

void SeqListAmend(SeqList* psl, int pos, SLDataType x)
{
    assert(psl);
    assert(pos < psl->size && pos >= 0);//检查pos的合法性
    psl->array[pos] = x;
}

(14)顺序表的测试用例

void test_1()
{
    SeqList a;
    SeqListInit(&a);//初始化
    CheckCapacity(&a);//检查空间
    SeqListPushBack(&a, 1);//尾插
    SeqListPushBack(&a, 2);//尾插
    SeqListPushBack(&a, 3);//尾插
    SeqListPushBack(&a, 4);//尾插
    SeqListPushBack(&a, 5);//尾插
    SeqListPrint(&a);

    SeqListPopBack(&a);//尾删
    SeqListPopBack(&a);//尾删
    SeqListPopBack(&a);//尾删
    SeqListPopBack(&a);//尾删
    SeqListPrint(&a);
    SeqListPopBack(&a);//尾删
    SeqListPrint(&a);
    //SeqListPopBack(&a);//尾删
    //SeqListPopBack(&a);//尾删

    SeqListPushBack(&a, 1);//尾插
    SeqListPushFront(&a, -1);//头插
    SeqListPushFront(&a, -2);//头插
    SeqListPushFront(&a, -3);//头插
    SeqListPushFront(&a, -4);//头插
    SeqListPrint(&a);

    SeqListPopFront(&a);//头删
    SeqListPopFront(&a);//头删
    SeqListPopFront(&a);//头删
    SeqListPopFront(&a);//头删
    SeqListPrint(&a);
    SeqListPopFront(&a);//头删
    //SeqListPopFront(&a);//头删
    //SeqListPopFront(&a);//头删
    SeqListPrint(&a);

    SeqListInsert(&a, 0, 1000);//任意插入
    SeqListPrint(&a);
    SeqListInsert(&a, 0, 1000);//任意插入
    SeqListInsert(&a, 1, -1000);//任意插入
    SeqListInsert(&a, 2, -800);//任意插入
    SeqListInsert(&a, 0, 8000);//任意插入
    SeqListPrint(&a);

    SeqListErase(&a, 0);//任意删除
    SeqListErase(&a, 0);//任意删除
    SeqListPrint(&a);
    SeqListErase(&a, 2);//任意删除
    SeqListPrint(&a);
    SeqListErase(&a, 0);//任意删除
    SeqListPrint(&a);
    SeqListErase(&a, 0);//任意删除
    SeqListPrint(&a);

    SeqListInsert(&a, 0, 8000);//任意插入
    SeqListPrint(&a);
    SeqListInsert(&a, 0, 100);//任意插入
    SeqListPrint(&a);
    SeqListInsert(&a, 1, -100);//任意插入
    SeqListPrint(&a);
    SeqListAmend(&a, 1, 2);//修改
    SeqListPrint(&a);
    SeqListAmend(&a, 0, 1);//修改
    SeqListPrint(&a);
    SeqListAmend(&a, 2, 3);//修改
    SeqListPrint(&a);

    printf("%d\n", SeqListFind(&a, 3));//查找
    printf("%d\n", SeqListFind(&a, 4));//查找

    SeqListDestory(&a);//销毁
}
void test_2()
{
    SeqList sl;//创建顺序表变量
    SeqListInit(&sl);//初始化顺序表
    SeqListPushBack(&sl, 1);//尾插
    SeqListPushBack(&sl, 2);//尾插
    SeqListPushBack(&sl, 3);//尾插
    SeqListPushFront(&sl, 0);//头插
    SeqListPrint(&sl);//打印
    SeqListPopFront(&sl);//头删
    SeqListPopBack(&sl);//尾删
    SeqListPrint(&sl);//打印
    SeqListDestory(&sl);//销毁顺序表
}
void test_3()
{
    SeqList sl;//创建顺序表变量
    SeqListInit(&sl);//初始化顺序表
    SeqListPushBack(&sl, 1);//尾插
    SeqListPushBack(&sl, 2);//尾插
    SeqListPushBack(&sl, 3);//尾插
    SeqListInsert(&sl, 0, 0);//任意插入
    SeqListInsert(&sl, 2, 10);//任意插入
    SeqListErase(&sl, 4);//任意删除
    SeqListAmend(&sl, 1, 20);//任意修改
    SeqListPrint(&sl);//打印
    SeqListDestory(&sl);//销毁
}
void test_4()
{
    SeqList sl;
    SeqListInit(&sl);//初始化
    for (int i = 0; i < 10; i++) 
    {
        SeqListPushBack(&sl, i);//循环尾插
    }
    SeqListPrint(&sl);//打印
    SeqListPushBack(&sl, 10);//尾插
    SeqListPrint(&sl);//打印
    SeqListDestory(&sl);//销毁
}
void test_5()
{
    SeqList sl;
    SeqListInit(&sl);//初始化
    for (int i = 0; i < 10; i++) 
    {
        SeqListPushFront(&sl, i);//循环尾插
    }
    SeqListPrint(&sl);//打印
    SeqListPushFront(&sl, 10);//头插
    SeqListPrint(&sl);//打印
    SeqListDestory(&sl);//销毁
}
void test_6()
{
    SeqList sl;
    SeqListInit(&sl);//初始化
    SeqListPushBack(&sl, 1);//尾插
    SeqListPushBack(&sl, 2);//尾插
    SeqListPushBack(&sl, 3);//尾插
    printf("%d\n", SeqListFind(&sl, 2));//查找成功
    printf("%d\n", SeqListFind(&sl, 4));//查找失败
    SeqListDestory(&sl);
}
  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

limou3434

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

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

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

打赏作者

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

抵扣说明:

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

余额充值