文章目录
简介
作为线性表的一种,顺序存储的线性表(以后简称:顺序表)在存储结构上更像是一种数组,与数组不同的是,它在操作上要复杂一些,但是与线性表的操作一致(毕竟数据表是线性表的一种)。本章节将对顺序表的定义和操作进行详细的讲解和实现。
顺序表长度与最大长度之间的关系:
由于顺序表的存储结构是顺序存储,它的元素存储在一片连续的存储空间。因此,顺序表的最大长度从建立是就已经固定,无法动态的增加或减少。顺序表长度是指顺序表内数据元素的个数,会随着数据元素的插入或删除而增加或减少;最大长度是指存储空间内所允许容纳最多的数据元素的个数。如图1所示:顺序表中是数据元素为E类型的数据,存储区间可容许数据元素个数为8,因此最大数据长度为8;顺序表中的共5个数据元素,因此顺序表的长度为5。需要注意的是,顺序表元素的位置是指相对于表中其他元素的位置,而不是相对于存储区间的位置。
数据类型定义:
c
#define LIST_LEN 10 //定义顺序表的最大长度
typedef struct //定义顺表数据类型
{
int data;
}element;
typedef struct //定义线性表数据类型
{
int element[LIST_LEN];
int length;
}List;
定义顺序表首先需要定义其长度(LIST_LEN),用于规定表中最多元素个数;element为元素类型结构体,包含int 类型的数据data,根据实际应用不同,element的类型可以修改;List是顺序表定义类型,它包含了LIST_LEN个element类型的元素和顺序表长度length。
线性表API函数及其具体实现:
创建函数:
c
List* ListCreate()
{
//新建一个List类型的指针,并将分配空间
List *temp = (List *)malloc(sizeof(List));
//将顺序表的长度,设置为0
temp->length = 0;
//返回指针
return temp;
}
创建一个顺序表函数的作用是,在堆区分配一个List大小的内存空间,将顺序表长度设置为0。它的数据元素存储区、顺序表长度和存储区间长度关系如图2所示。函数的最后返回一个List 类型的指针,使用时可以先定义一个List类型的指针,将ListCreate函数的返回值赋值给该指针,即完成了顺序表的创建。
函数应用代码如下:
c
List * MyList = NULL;//建立一个线性表指针
MyList = ListCreate();//建立一个线性表
销毁函数:
销毁函数的作用是将List 类型指针指向的内存空间释放掉,必将它指向NULL(避免野指针)。函数参数为二级指针,因为我们将要一个指针的值,根据值传和地传的概念,我们只能用二级指针才能修改一级指针的值。
c
int ListDestory(List **list)
{
if (*list == NULL)
{
//如果顺序表是否已经销毁,返回-1
return -1;
}
//释放顺序表内存空间
free(*list);
//将顺序表指针指向NULL
*list = NULL;
return 0;
}
函数应用代码如下:
c
ListDestory(&MyList);
清空函数:
清空函数只是将顺序表内的数据元素清空,因此只要将顺序表的长度清0,数据元素便不会再被访问,即实现清空数据元素;后续的插入覆盖原来的元素实现了元素的插入。
c
int ListClear(List *list)
{
if (list == NULL)
{
//如果输入参数为NULL,返回-1
return -1;
}
//将顺序表长度设置为0
list->length = 0;
return 0;
}
函数应用代码如下:
c
ListClear(MyList);
长度获取函数:
长度获取函数的作用是,返回顺序表的长度,便于用户了解此时的顺序表的长度。
c
int ListGetLength(List *list)
{
if (list == NULL)
{
//如果输入参数为NULL,返回-1
return -1;
}
//返回顺序表长度
return list->length;
}
函数应用代码如下:
c
listLen = ListGetLength(MyList);
相应位置元素获取函数:
长度获取函数的作用是将顺序表中相应位置的元素复制一份,通过函数参数将该元素传递出去,如图所示。
c
int ListGet(List *list, int position,element *ele)
{
if (list == NULL || position < 0 || position >= list->length)
{
//如果list为NULL,position小于0或者大于最大长度,返回-1
return -1;
}
*ele = list->member[position];
return 0;
}

函数应用代码如下:
c
ListGet(MyList,i,&temp);
插入元素函数:
c
int ListAdd(List *list, int position, element e)
{
int i;
//判断输入参数是否有误
if (list == NULL || position < 0 || position >LIST_LEN)
{
//如果list为NULL,position小于0或者大于最大长度,返回-1
return -1;
}
if (list->length == LIST_LEN)
{
//如果顺序表已满,返回-2
return -2;
}
if (position == list->length)
{
//如果插入位置在末尾,在末尾加入元素
list->member[position] = e;
//顺序表长度加1
list->length++;
return 0;
}
//将从position开始位置的元素向后移动一个位置
for (i = list->length; i > position; i--)
{
list->member[i] = list->member[i-1];
}
//在插入位置插入元素(此时i==position)
list->member[i] = e;
//顺序表长度加1
list->length++;
return 0;
}

在元素进行插入时,首先要进行输入参数的检测,主要是检测指针是否为空,插入位置是否符合要求;然后判断顺序表是否已满,若已满,返回-2,否则继续插入元素。此时元素的插入有两种情况:
第一种:在顺序表末尾插入元素,如图4左侧图所示。因为我们元素下标从0开始,因此,当插入位置position大于或等于顺序表长度时(大于时可插入是为了提高使用方便性,但是严谨性降低,实际使用可以进行调整),表示在表尾部插入,此时将表中相应位置元素赋值即可。在图4左侧图中,顺序表长度为5,我们在下标5处插入新的元素,即实现了顺序表元素的尾部插入,插入成功后,顺序表长度加1,函数返回。
第二种:在顺序表中间位置插入元素,如图4右侧所示。在顺序表中间位置插入元素时,需要先将插入位置及其后面的元素,向后移动一位,然后将插入位置元素赋值为新元素。在图4右侧中,我们要在位置1处插入新的元素,因此需要将E1-E5向后移动一位,移动时从后面的元素开始(从前开始,元素会覆盖丢失),移动到插入位置。移动完成后,在位置1处插入元素,顺序表长度加1,函数返回。
应用代码如下:
c
ListAdd(MyList,0,data0);
ListAdd(MyList,0,data1);
ListAdd(MyList,0,data2);
删除元素函数:
c
int ListDelete(List *list, int position,element *e)
{
int i;
//判断输入参数是否有误
if (list == NULL || position < 0 || position >= list->length)
{
//如果list为NULL,position小于0或者大于最大长度,返回-1
return -1;
}
if (list->length == 0)
{
//如果顺序表已空,返回-2
return -2;
}
//保存要删除位置的元素
if (e != NULL)
{
*e = list->member[position];
}
//如果要删除元素在末尾
if (position == list->length -1)
{
//顺序表长度减1
list->length--;
return 0;
}
//position位置之后,所有的元素向前移动
for (i = position; i < list->length -1; i++)
{
list->member[i] = list->member[i + 1];
}
//顺序表长度减1
list->length--;
return 0;
}

元素的删除与元素的插入有类似之处,首先进行输入参数的检测,判断顺序表指针是否为空,判断要删除的元素的位置是正确。如果此时,表中无元素,表长度为0,此时返回错误;否则进行元素删除。元素的删除也分为两种情况,不过在删除前,可以选择将元素取出或者不取出(删除前进行)。
第一种:要删除的元素在顺序表的尾部,如图5左侧图所示。删除前,顺序表长度为5,要删除的元素位置为4。删除元素时,只需要将顺序表长度减1,以后就无法对该位置的元素读取,即实现了元素的删除。
第二种:要删除的元素在顺序表中间位置,只需要将要删除位置元素后面的元素以此前移一位,然后将顺序表长度减1,即实现了元素的删除。
应用代码如下:
c
ListDelete(MyList,0,NULL);
小结
顺序表结构及其功能函数较为简单,它们的主要功能都是对元素存储位置来实现的。在在顺序表学习中,要理解好存储区间长度和顺序表长度的区别,元素存储位置的变换(特别是在元素插入和删除的时候)。因此,想学好顺序表,首先要对C语言中的数据有较深刻的理解,理解和熟练掌握了数组,顺序表就很简单了!