【C语言数据结构(基础篇)】第二站:顺序表(上)

简介: 【C语言数据结构(基础篇)】第二站:顺序表

一、线性表

首先我们必须要了解的一个概念是线性表

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

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的, 线性表在物理上存储时,通常以数组和链式结构的形式存储。

顺序表就是数组,他的内存是连续的

下面就是一个链表的结构,当然或许你现在并不知道链表是什么,但是没有关系, 我们在后面的文章中将会花费大量的笔墨去详细讲解链表,这里你只需要大概看一眼就可以了,下图什么都看不懂是没有任何关系的。

二、顺序表的实现(概念以及静态顺序表)

对于顺序表的实现,我们采用分文件的形式来展现,在前面我们也已经利用了两个小游戏来让大家熟悉了分文件的写法,这里就不在赘述。如果还有不懂的地方,可以去C语言专栏去找到对应的文章。同样数据结构部分,为了规范我们的写法,我们全部采用大驼峰的命名风格

1.创建三个工程文件

如下图所示,我们创建好三个文件,分别是SeqList.c SeqList.h Test.c

SeqList.c用于顺序表的实现

SeqList.h用于顺序表的声明

Test.c用于测试顺序表

2.顺序表的概念

我们得先了解顺序表的概念,才能继续完成下去

顺序表是一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改

顺序表一般可分为

静态顺序表:使用定长数组进行存储

动态顺序表:使用动态开辟的数组进行存储

3.顺序表的定义

我们先看静态顺序表是如何定义的,如下图所示,我们知道顺序表他也是用来存储数据的,既然是用来存储数据的,那么他必然要有一个数组来存储,然后还要有一个size来确定目前存储了一个数据。将这两个合并到一起就是一个结构体

虽然说这可以当作一个静态顺序表来进行定义,但是要真是这样定义,还是会出现很多问题,比如说哪一天想要存储100个数据了,那么我们上面这个就是写死了,根本没法改。所以我们可以使用define来进行优化,如下图所示

这样的话,确实,解决了一些后续无法增加数据的问题,但是如果突然不想要整型类型了,他想要char类型的话,那这个顺序表又废了,所以我们还得再次进行优化,我们可以使用一个typedef来重定义类型,如下图所示

当然这样其实还不够好,我们如果想要使用这个结构体的话,这个结构体类型太长了,我们写着写着都快烦死了。所以我们也可以对结构体进行typedef

如下图所示,我们让这个结构体类型变成了SL,当然这个有两种写法,一种是使用注释中的写法,另外一种就是在定义结构体的时候就typedef

最终代码如下(SeqList.h这个文件)

#pragma once
#define N 10
typedef int SQDateType;
typedef struct SeqList
{
  SQDateType arr[N];
  int size;
}SL;
//等价于typedef struct SeqList SL;

4.初始化顺序表

我们在说顺序表的概念的时候就提到过,顺序表是要实现增删查改四大功能的,但是在这之前,我们得先初始化顺序表

于是我们在头文件先进行一次初始化函数的声明

在SeqList.c文件中,我们就要实现这个功能了,如下图所示,我们使用一个memset函数,在这里可能有些人还不熟悉或者不太了解这个函数,我们可以现场学习一下 ,如下图所示,他是将传入的一个指针,从他开始的前num个字节都设置为value

所以下面中的意思就是将这个数组的全部元素设置为0,并且将size也就是目前的元素个数也设置为0

而对应这个函数也有他自己的头文件,我们为了方便,可以直接全部放在SeqList.h中

既然如此,那么我们就开始来测试一下这个函数究竟对不对

我们打完断点以后,直接使用F5,跳转至断点处,并打开调试的监视窗口,如下图所示,我们已经将顺序表给初始化完成了

我们开始进入我们的函数,我们发现,这块并没有将这个顺序表给初始化啊。这是为什么呢?

其实这块已经很多人发现了这个问题,因为我们传的其实是形参,形参的改变不会影响实参。我们就不该使用这个传值调用了,我们应该使用传址调用,我们现在将我们的代码都改为指针

而此时就能够完成我们的目标了,实现初始化顺序表

顺序表初始化接口代码为

//顺序表初始化
void SeqListInit(SL* ps)
{
  memset(ps->arr, 0, sizeof(SQDateType) * N);
  ps->size = 0;
}

5.静态顺序表的尾插

在我们将顺序表给初始化以后,我们现在需要的就是试下顺序的表的增删查改,当然我们在讲述顺序表的概念的时候,提到了这两个关键点:

1.连续的物理存储地址------数组

2.数据必须是从头开始,依次存储------不能在数组的第一个元素插入一个,然后第二个又跑到了第三个元素上

那么我们就先来定义一下我们的接口函数,如下图所示,这里我们的命名与c++的标准库一致,让我们的程序更加规范

不过既然有尾插,那么与之对应的就有头插,尾删,以及头删,不妨我们也直接定义好他们的接口吧,如下图所示

那么我们先来实现尾插,如何实现尾插呢?我们可以试着画图理解一下,如下图所示,我们假设数组已经存储了5个元素了,此时他的size就是5,那么这个5刚好就是下一个数据的下标,所以我们就想到了,有了下标了,那不就是直接插入数据了吗。插入完之后再让size++就行了吗,确实是这样的。

我们来实现一下我们的想法,如下图所示

但是这样存在一个问题,如果顺序表满了呢?我们可以实验一下

我们进行调试,如下图所示,顺序表已经初始化完成

我们使用F10不进入函数内部进行调试,我们可以发现现在即将越界

此时已经越界了,我们发现arr[10]他与size进行同步变化,size直接变成了12,而不是变成了11,这个问题,在我们之前讲解调试的时候已经提到过了,这就是数组越界所带来的风险。size的数据已经被破坏了。所以这个顺序表已经废了

那么我们该怎么办呢?我们可以在顺序表满的时候提示一句顺序表满了,然后就直接返回,直接拦截这个错误的信息,不让他插入进去,所以实现如下

这个时候我们再次调试一下,此时我们发现,拦截成功了。

其实到这块我们也发现一个问题,那就是静态顺序表不太好,要么消耗的空间太大,要么空间不够。总之很麻烦。而我们一般下也不会去使用静态的顺序表,我们都是使用动态的顺序表,可以进行扩容的顺序表。

所以我们在这里就不在继续进行实现静态的顺序表的,我们转而实现动态的顺序表

相关文章
|
2月前
|
算法 数据处理 C语言
C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合
本文深入解析了C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合,旨在帮助读者掌握这一高效的数据处理方法。
58 1
|
2月前
|
存储 算法 搜索推荐
【趣学C语言和数据结构100例】91-95
本文涵盖多个经典算法问题的C语言实现,包括堆排序、归并排序、从长整型变量中提取偶数位数、工人信息排序及无向图是否为树的判断。通过这些问题,读者可以深入了解排序算法、数据处理方法和图论基础知识,提升编程能力和算法理解。
57 4
|
2月前
|
存储 机器学习/深度学习 搜索推荐
【趣学C语言和数据结构100例】86-90
本文介绍并用C语言实现了五种经典排序算法:直接插入排序、折半插入排序、冒泡排序、快速排序和简单选择排序。每种算法都有其特点和适用场景,如直接插入排序适合小规模或基本有序的数据,快速排序则适用于大规模数据集,具有较高的效率。通过学习这些算法,读者可以加深对数据结构和算法设计的理解,提升解决实际问题的能力。
50 4
|
2月前
|
存储 算法 数据处理
【趣学C语言和数据结构100例】81-85
本文介绍了五个经典算法问题及其C语言实现,涵盖图论与树结构的基础知识。包括使用BFS求解单源最短路径、统计有向图中入度或出度为0的点数、统计无向无权图各顶点的度、折半查找及二叉排序树的查找。这些算法不仅理论意义重大,且在实际应用中极为广泛,有助于提升编程能力和数据结构理解。
54 4
|
2月前
|
算法 数据可视化 数据建模
【趣学C语言和数据结构100例】76-80
本文介绍了五种图论算法的C语言实现,涵盖二叉树的层次遍历及广度优先搜索(BFS)和深度优先搜索(DFS)的邻接表与邻接矩阵实现。层次遍历使用队列按层访问二叉树节点;BFS利用队列从源节点逐层遍历图节点,适用于最短路径等问题;DFS通过递归或栈深入图的分支,适合拓扑排序等场景。这些算法是数据结构和算法学习的基础,对提升编程能力和解决实际问题至关重要。
55 4
|
13天前
|
数据库
数据结构中二叉树,哈希表,顺序表,链表的比较补充
二叉搜索树,哈希表,顺序表,链表的特点的比较
数据结构中二叉树,哈希表,顺序表,链表的比较补充
|
2月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
74 5
|
2月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
68 1
|
存储 缓存 C语言
数据结构——双链表(C语言)
数据结构——双链表(C语言)
|
2月前
|
存储 C语言
【数据结构】手把手教你单链表(c语言)(附源码)
本文介绍了单链表的基本概念、结构定义及其实现方法。单链表是一种内存地址不连续但逻辑顺序连续的数据结构,每个节点包含数据域和指针域。文章详细讲解了单链表的常见操作,如头插、尾插、头删、尾删、查找、指定位置插入和删除等,并提供了完整的C语言代码示例。通过学习单链表,可以更好地理解数据结构的底层逻辑,提高编程能力。
122 4