线性表的顺序表示是指用一组地址连续的存储单元依次存储线性表的数据元素。
假设每个元素占用l长度的存储空间,并以所占的第一个单元的存储地址作为数据元素的存储位置。则数据元素的第i个元素的存储位置LOC(ai)和第i+1个数据元素的存储位置LOC(a(i+1))之间满足下列关系:
LOC(a(i+1)) = LOC(ai)+ l
一般来说线性表第i个元素的存储位置为:LOC(ai) = LOC(a1)+ (i-1)x l
线性表的这种机内表示称作线性表的顺序存储结构或顺序映像。每两个相邻的元素之间相差一个存储单位l的长度。由此,只要确定了存储线性表的起始位置,线性表中的任一数据元素都可随机存取,所以线性表的顺序存储结构是一种随机存取的存储结构。
由于高级程序设计语言中的数组类型也有随机存取的特性,因此,通常都用数组来描述数据结构中的顺序存储结构。
在此,由于线性表的长度可变,且所需最大存储空间随问题不同而不同,则在C语言中可用动态分配的一维数组。
//--------------------------线性表的动态分配顺序存储结构-----------------------------------------------------------------
#define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量;
#define LISTINCREMENT 10 //线性表存储空间的分配增量;
typedef struct{
ElemType * elem; //存储空间基址;
int length; //当前长度;
int listsize; //当前分配的存储容量(以sizeof(ElemType)为单位);
}SqList;
顺序表的初始化操作就是为顺序表分配一个预定义大小的数组空间,并将线性表的当前长度设为“0”。参见算法2.3如下:
Status InitList_Sq(SqList &L){
//构造一个空的线性表L。
L.elem = (ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType));
if(!L.elem)exit(OVERFLOW); //存储空间分配失败;
L.length = 0; //空表长度为0;
L.listsize = LIST_INIT_SIZE; //初始存储容量;
return OK;
}
在这种存储结构中,容易实现线性表的某些操作,如随机存取某个元素。
下面着重讨论线性表的插入和删除两种操作在顺序存储表示时的实现方法。
插入:
一般情况下,在第i(1<= i <= n)个元素之前插入一个元素时,需要将第i至最后一个元素向后移动一个位置,如算法2.4,如下所示:
Status ListInsert_Sq(SqList &L,int i,ElemType e)
{
//在线性表L中的第i个位置插入新的元素e;
if(i <1 || i >L.length + 1)return ERROR;
if(L.length >= L.listsize)
{ //当前存储空间已满,增加分配;
newbase = (ElemType *)realloc(L.elem,(L.lsitsize + LISTINCREMENT)*sizeof(ElemType));
if(!newbase)exit(OVERFLOW);
L.elem = newbase; //新基址;
L.listsize += LISTINCREMENT; //增加存储容量;
}
q = &(L.elem[i-1]); //q为插入e值的位置;
for(p = &(L.elem[L.length - 1]);p >= q;- -p) //先找到最后一个元素的位置,然后后移一位,然后向前类推直到位置p处所有的元素后移一位;
{
*(p+1) = *p; //p位置的值放到(p+1)位置;即是后移的意思;
}
*q = e; //插入e到q位置;
++L.length; //线性表长度加1;
return OK;
}
删除:
一般情况下,删除第i(1<= i <= n)个元素时,删除后需要将第i+1至最后一个元素向前移动一个位置,如算法2.5,如下所示:
Status ListDelete_Sq(SqList &L,int i,ElemType &e)
{
if(i <1 || i >L.length + 1)return ERROR;
p = &(L.elem[i-1]); //p为删除元素的位置;
e = *p;
q = L.elem + L.length -1; //表尾元素的位置;
for(++p;p <= q;++p)
{
*p = *(p + 1)
}
- -L.length;
return OK;
}