从本节开始讨论线性表,这次先讨论线性表的顺序实现。
一提到线性表,我们脑子很可能会出现数组、链表这样的概念。没错,数组和链表都是线性表,但它们只是线性表的两种实现,强调的是线性表的物理结构。我们研究一个数据结构时,一般先从它的逻辑结构入手,等研究清楚了逻辑结构再考虑具体的物理实现。在写程序时,思路也是一样的,先要分清哪些问题是逻辑的,哪些问题是物理的,先逻辑后物理是计算机解题的一般步骤。如果开始不想清楚逻辑,而一头扎到物理细节中,就容易理不清思路或者作出有缺陷的设计。当然这不是绝对的,很多情况下物理结构也会影响逻辑结构的设计。
简单来说,一个线性表是n个相同特性的数据元素的有限序列。这里“n个相同特性的数据元素”指的是数据对象,“序列”指的是数据关系,每个数据元素都有一个确定的位置。从数据对象和数据关系入手,就很容易看清一个数据结构的本质。就线性表来说,只要某些数据存在次序关系,并且各个元素特性相同,就可以认为是一个线性表。
下面我们来考虑线性表的顺序实现。在很多人包括我自己的眼里,线性表的顺序实现已经和数组画上了等号。虽然用数组实现线性表的顺序存储结构天经地义,但不应该把顺序实现局限在数组上。如果有一天你必须用汇编语言实现一个顺序存储的线性表,没有了数组你岂不是哭了。如作者所说,线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素。用C语言实现时,由于线性表的长度可变,且所需最大存储空间随问题不同而不同,所以通常用动态分配的一维数组来实现。
#define LIST_INIT_SIZE 100 // 初始长度
#define LISTINCREMENT 10 // 分配增量
typedef struct {
ElemType *elem; // 存储基址
int length; // 当前长度
int listsize; // 存储容量
} SqList;
用上述结构在分配存储空间时,初始分配可以用malloc,空间不够再分配时可以用realloc,这个函数保证在原分配基础上扩大容量时不影响其内容。