前言
我们在上一篇文章中说到,要揭开线性表是什么,怎么构成的,如何实现的,这一章节中,我们就来讲线性表中的顺序表,线性表是具有相同特性的数据结构的集合,其逻辑结构一定连续,但是其物理结构不一定连续。道理很简单,假设我们作为生产绿皮火车的公司之一,我们会给每一个车厢生产编号,No.26
、No.28
等等,但我们会发现绿皮火车的车厢排序并不会因为生产编号的固定而固定,一列绿皮火车的车厢组合是任意的,也就是说,并不在意生产编号是否连号,而注重的是连接后产生的车厢编号。
文章目录
什么是顺序表?
上面的绿皮火车例子,我们发现在实际生活中,我们会忽略物理结构上的存在,但是并不证明我们的物理结构不能相连接。
更可以说,我们要追求的是逻辑上的连续,而不是物理结构上的连续。如果说想起物理结构(即内存空间)的连续,我们会想起C
、C++
中的数组
这一概念,而这一概念正是我们今天想要引入的顺序表的底层。
要知道,数据结构是计算机存储、组织数据的方式。
就像C++
中的STL
一般,顺序表也杂糅了一些方法,所以是基于数组出发,提供了具体的实际应用,后面我也会提及相关的STL
学习,基本上是一脉相承的,都是具有某些功能的封装。
int arr[10]={
0};//一个一维数组,可以存储至多10个数字
int *arr;//用于确定动态内存开辟,确定大小之后再去动态申请
我们又可以根据顺序表的有效数据个数是否为动态的来分为静态顺序表,以及动态顺序表。
我们经常利用struct
结构体来定义线性表,我们不妨用这种方式来构建静态顺序表和动态顺序表。
静态顺序表
struct SeqList{
int arr[100];//数组是定长的
int size;
};
我们注意到利用struct
还要考虑到一些问题,我们对于结构体的具体介绍在此按下不表,可以参考从零开始学C语言:结构体篇。
假设读者已经习得了struct
结构体的一些语法,以及性质,我们就来分析该结构体,可以观察到,Seqlist
是其结构体类型名,我们要采用该结构体的时候还要考虑会不会超容量,由于只能最多容纳100个数据,我们会发现,在后续的运行维护中会随着该结构体数量呈现几何增长,虽然说效果并非很明显,但对于大型项目的管理并不有利,所以我们应该寻找到一个更加灵活的方法,因此我们引入——动态顺序表。
动态顺序表
struct SeqList{
int* arr;//一个指向整型数据的指针,用于存储列表中的元素地址
int size;//目前存储的数量
int capacity;//最大的容量
};
我们会发现,动态顺序表与静态顺序表的不同是,动态顺序表用一个动态的数组去存储数据,比静态顺序表更加灵活,它可以进行动态增容,我们知道,有了动态增容后,我们的运行维护会更加容易,所以动态顺序表是在活的数据处理中优点很明显,可以处理多个数据。
既然知道了顺序表,我们就来引入如何初始化、尾插、头插、尾删、头删。
关于写在这些操作的前面
我们知道,优质的代码是呈现简洁性的,他们并不会有太多的复杂情况,而我们在此之前要把我们写代码的基础逻辑搞好,我们需要一个头文件SeqList.h
,SeqList.cpp
和test.cpp
。
而我们的SeqList.h
中写:
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
在SeqList.cpp
中我们则写:
#include"SeqList.h"
在C和Cpp中,#include""
指的是引用本地文件夹中的某头文件,而#include<>
是指引用C和Cpp自带的文件库。
typedef的用法
C和Cpp中内置了typedef
关键字,我们可以通过typedef
给一个类型取一个新名字,我们可以如下方法来把unsigned int
转换为UI
.
typedef unsigned int UI;
我们要写一个unsigned int
数据类型的变量的时候,可以通过
UI a=0x10000011;
给a赋初值,其应用与unsigned int a=0x100000011;
相同
malloc、calloc、realloc的应用
内存是什么
我们可以认为,程序处理的数据存储在内存(RAM)。现在常用的内存条,包含若干内存颗粒(半导体集成电路)
物理上,通过一些微小的元器件来表示“0”,“1”状态,能存储的比特数取决于集成电路里的元器件数目。
可以想象成一条非常非常长的纸带每个格子可以填写0-255的一个状态(8个0/比特,一个字节),例如16G的内存,一共能填写16x1024x1024x1024个字节。然后这根纸带卷啊卷,卷到了一根内存条这么大。
这就是操作系统所拥有的内存资源,操作系统会将内存分配给正在执行的程序。
malloc
C/Cpp提供了一个动态内存数据开辟的函数;
void* malloc(size_t size);
我们可以知道,malloc
函数是返回值为void
类型,所以我们一般要强制类型转换
typedef TYPE VOID
(VOID)* malloc(size_t size