目录
引言
本文详细介绍了顺序表的相关知识,并基于此实现了可无限扩容,可实现数据增,删,查,改,功能的通讯录。
顺序表知识回顾
线性表
顺序表是线性表的一种,而线性表是一种实际中被广泛使用的数据结构,常见的线性表有:顺序表,栈,链表,队列,字符串........。线性表在逻辑上是线性结构,但在物理上不一定是线性的,比如链表,线性表在物理存储上,通常是数组和链式结构的形式,而本文要讨论的顺序表在逻辑上和物理上都是线性的。因为顺序表的底层就是数组,数组在内存上是连续存放的。
顺序表的分类与缺陷
顺序表分为动态顺序表和静态顺序表两种,静态顺序表,即能储存的空间大小是固定的顺序表,动态顺序表,即可以根据实际需要,动态的在内存中申请空间,以满足需要的一种数据结构。动态顺序表,虽然较静态顺序表功能更强,但是仍有以下几点缺陷:
1,动态申请的空间即扩容时有可能会出现浪费。
2,在头插或者指定位置插入数据时,需要成段的移动数据时间复杂度为O(N)
3,增容时,需要申请新空间,拷贝旧数据,释放旧空间,这会有不少的消耗。
动态顺序表的代码实现
为了代码的规范性,我们需要分别建立SeqList.c与SeqList.h两个文件如图所示
Seq即Sequence
顺序表的定义
动态顺序表分为储存数据的数组,有效数据个数,总空间大小三个部分,这里为了之后方便更改储存的数据类型,使用typedef进行重定义int,并将结构体类型简写为SL。
顺序表的思考
前面说过,顺序表的底层就是数组,在顺序表的定义中就很好的体现了这一点。当我们定义一个普通的数组时,我们会确定其首元素的地址,这里就是SLDatatype,我们会确定其最大容量,这里就是capacity。如果定义的同时,我们初始化数组中一部分数据,就会出现有效元素个数,这里就是size。所以顺序表的就是将数组的各项构成元素拆开,并使数组的容量可根据需要自动扩容,同时提供增删查改等方法的一种数据结构。
顺序表的方法
涉及的方法由头文件可清晰的看到:
-
初始化与销毁
顺序表有三个参数一个指针,两个整型变量用于记录顺序表的有效值与目前申请的总内存空间。所以需要让指针指向NULL,避免野指针。而capacity与size的初始化对后续代码的影响巨大。
第一种方法:将两值全置为0,这种做法较简单,但会给顺序表的扩容带来而外的工作量。因为扩容使用的函数realloc的第二个参数是新空间的字节数,转换成代码就是 sizeof(SLDatatype) * 2 * ps->capacity,这里需要乘以capacity,如果是第一次扩容并且初始化使用的是第一种方法,capacity的值为零,程序是跑不起来的,所以需要而外处理,如下:
第二种方法:就是将size的值初始化为2,相应的capacity的值初始化使用malloc申请两个空间,这样在后续扩容是会方便一些,如下:
销毁方法如下: