数据结构 —— 顺序表(超详细图解 & 接口函数实现)

系列文章目录

数据结构 —— 顺序表
数据结构 —— 单链表
数据结构 —— 双向链表
数据结构 —— 队列
数据结构 —— 栈
数据结构 —— 堆
数据结构 —— 二叉树
数据结构 —— 八大排序



前言

数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。数据结构是一种十分优秀的解决实际问题的模板,是先进思想的结晶。博主将会用代码结合大量图解,对数据结构进行深度剖析,以便大家更好的学习数据结构的思想。


一、示例问题:酒店住宿

1.住宿需求

某公司需要一串连续的房间让员工住宿,但不清楚有多少员工将会入住

2.住宿管理

公司:首先安排了 3 个员工入住酒店

酒店:安排了 3 个连续房间 1 - 3 号房间

在这里插入图片描述

公司:又安排了 2 个员工入住

酒店:

  1. 后面的 4 号房间空闲,但 5 号房有其他人入住,无法直接向后开辟房间
  2. 重现寻找连续的 5 个房间

在这里插入图片描述

公司:又安排了 2 个员工入住

酒店:后面的 6 号和 7 号房间均空闲,直接向后面开辟两个房间

在这里插入图片描述
到此酒店成功满足了该公司的需求,通过这个示例问题引出了我们下面将要讲的顺序表,它们可以完美的描述并解决上述问题。

二、顺序表的概念

1.定义

顺序表:用一段地址连续的存储单元依此存储线性表的数据元素

顺序表就像是军训时,同学们站成一排,从左往右报数,每个人对应一个序号,这些序号是一个接着一个的有序排列。数组就是顺序表的一种,每个位置站着一名同学,他的序号就是数组的下标,通过序号就能找到那个同学。
请添加图片描述

2.结构

顺序表的结构类型

//重定义类型
typedef int SeqDateType;	//便于更改存储类型

//顺序表类型
typedef struct SeqList {
    SeqDateType *array;  	//顺序表
    int size;        		//有效数据的个数
    int capacity;    		//总容量
}SeqList;

在这里插入图片描述

3.存储

存储:用动态开辟的一维数组来实现顺序表的存储结构

在这里插入图片描述

三、顺序表的接口函数

1.初始化

对顺序表的内容进行初始设置

//初始化
void SeqListInit(SeqList *pq) {
    assert(pq);
    pq->array = NULL;				//指针置空
    pq->capacity = pq->size = 0;	//大小和容量赋值为0
}

2.容量检查

判断是否达到最大容量

  • 达到最大容量 —— 扩容
  • 没有达到最大容量 —— 不扩容
//判断是否存满
void SeqCheckCapacity(SeqList *pq) {
    assert(pq);
    if (pq->size == pq->capacity) {
        int newcapacity = (pq->capacity == 0) ? 4 : (pq->capacity * 2);  //判断是否开辟空间 若没有自动开辟
        SeqDateType *newA = (SeqDateType *) realloc(pq->array, sizeof(SeqDateType) * newcapacity);
        if (newA == NULL) {
            perror("realloc fail:");
            exit(-1);
        }
        pq->array = newA;
        pq->capacity = newcapacity;
    }
}

达到最大容量 —— 扩容

在这里插入图片描述

在这里插入图片描述

3.指定位置插入

指定位置 pos 插入数据

//指定位置插入
void SeqListInsert(SeqList *pq, int pos, SeqDateType x) {
    assert(pq);
    assert(pos >= 0 && pos <= pq->size);
    //判断扩容
    SeqCheckCapacity(pq);
    //向后推移
    int end = pq->size;
    while (end > pos) {
        pq->array[end] = pq->array[end - 1];
        end--;
    }
    pq->array[pos] = x;
    pq->size++;
}

在这里插入图片描述

在这里插入图片描述

4.指定位置删除

删除指定位置 pos 的数据

//指定位置删除
void SeqListErase(SeqList *pq, int pos) {
    assert(pq);
    assert(pos < pq->size);
    //向前推移
    for (int i = pos + 1; i < pq->size; i++) {
        pq->array[i - 1] = pq->array[i];
    }
    pq->size--;
}

在这里插入图片描述

在这里插入图片描述

5.指定位置修改

修改指定位置 pos 的数据

//修改数据
void SeqListModify(SeqList *pq, int pos, SeqDateType x) {
    assert(pq);
    assert(pos >= 0 && pos < pq->size);
    pq->array[pos] = x;
}

在这里插入图片描述

在这里插入图片描述

6.查找数据

查找指定数据

  • 存在 —— 返回第一次查找到的位置
  • 不存在 —— 返回 NULL
//查找数据
int SeqListFind(SeqList *pq, SeqDateType x) {
    assert(pq);
    //查找数据
    for (int i = 0; i < pq->size; i++) {
        if (pq->array[i] == x) {         //如果找到了返回位置
            return i;
        }
    }
    return -1;                         //如果没找到返回-1
}

在这里插入图片描述

7.头部插入

利用指定位置插入实现头插

//头部插入
void SeqListPushFront(SeqList *pq, SeqDateType x) {
    SeqListInsert(pq, 0, x);
}

在这里插入图片描述
在这里插入图片描述

8.头部删除

利用指定位置删除实现头删

//头部删除
void SeqListPopFront(SeqList *pq) {
    SeqListErase(pq, 0);
}

在这里插入图片描述
在这里插入图片描述

9.尾部插入

利用指定位置插入实现尾插

//尾部插入
void SeqListPushBack(SeqList *pq, SeqDateType x) {
    SeqListInsert(pq, pq->size, x);
}

在这里插入图片描述
在这里插入图片描述

10.尾部删除

利用指定位置删除实现尾删

//尾部删除
void SeqListPopBack(SeqList *pq) {
    SeqListErase(pq, pq->size - 1);
}

在这里插入图片描述

在这里插入图片描述


四、总结

顺序表是解决实际问题时极其常用的一种数据结构,是非常重要的解决问题的方式。顺序表的各种接口的复现,有利于更好的学习数据结构的思想,有利于开阔视野,学习前辈的智慧结晶。对我们后续解决实际问题也会有很大帮助。

  • 29
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 25
    评论
以下是使用C语言实现顺序表判定子集的代码: ```c #include <stdio.h> #define MAXSIZE 100 typedef struct { int data[MAXSIZE]; int length; } SqList; // 初始化顺序表 void init(SqList *L) { L->length = 0; } // 向顺序表中插入元素 void insert(SqList *L, int x) { if (L->length == MAXSIZE) { printf("顺序表已满,无法插入。\n"); return; } L->data[L->length++] = x; } // 判断顺序表B是否是顺序表A的子集 int isSubset(SqList *A, SqList *B) { int i, j; for (i = 0; i < B->length; i++) { for (j = 0; j < A->length; j++) { if (B->data[i] == A->data[j]) { break; } } if (j == A->length) { return 0; } } return 1; } int main() { SqList A, B; init(&A); init(&B); // 向顺序表A中插入元素 insert(&A, 1); insert(&A, 2); insert(&A, 3); insert(&A, 4); insert(&A, 5); // 向顺序表B中插入元素 insert(&B, 2); insert(&B, 4); insert(&B, 6); // 判断顺序表B是否是顺序表A的子集 if (isSubset(&A, &B)) { printf("B是A的子集。\n"); } else { printf("B不是A的子集。\n"); } return 0; } ``` 在该代码中,我们定义了一个`SqList`结构体来表示顺序表,其中`data`数组用于存储顺序表中的元素,`length`表示顺序表的长度。我们通过`init`函数来初始化顺序表,通过`insert`函数来向顺序表中插入元素。 在`isSubset`函数中,我们使用两个循环来遍历顺序表B和顺序表A中的元素,如果在顺序表A中找到了顺序表B中的元素,则继续循环查找顺序表B中的下一个元素。如果在顺序表A中找不到顺序表B中的元素,则直接返回0表示顺序表B不是顺序表A的子集。如果顺序表B中的所有元素都在顺序表A中找到了,则返回1表示顺序表B是顺序表A的子集。 最后,在`main`函数中,我们初始化了两个顺序表A和B,并向它们中插入了一些元素。然后,我们调用`isSubset`函数来判断顺序表B是否是顺序表A的子集,并输出结果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

十里坡小白

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

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

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

打赏作者

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

抵扣说明:

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

余额充值