顺序表
数据类型定义
typedef struct{
ElemType *elem; //存储空间基地址
int length; //顺序表当前长度
int listsize; //当前分配的存储容量(以sizeof(ElemType)为单位)
}SqList;
附加定义
#define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量
#define LISTINCREMENT 100 //线性表存储空间的分配增量
基本操作
初始化操作
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;
}//InitList_Sq
时间复杂度: O(1)
取值操作
status GetELem(SqList L,int i,ElemType e){
//若i的值小于1或者大于表长,则返回ERROR;否则用e返回第i个元素的值,并返回OK
if(i < 1 || i > L.length)
return ERROR; //查找失败,返回ERROR
e = L.elem[i - 1]; //查找成功,返回元素的值
return OK;
}//GetELem
时间复杂度: O(1)
查找操作
int LocateElem_Sq(SqList L,ElemType e){
//在顺序表L中查找第一个值与e相等的元素的位序,若找到则返回其在L中的位序,否则返回0
for(i = 0;i < L.length;i++)
if(e == L.elem[i])
return i + 1;
return 0;
}//LocateElem_Sq
时间复杂度: O(n)
插入操作
status ListInsert_Sq(SqList &L,int i,ElemType e){
//在顺序表L的第i个位置之前插入新的元素e,其中1 <= i <= ListLength(L)+1
if(i < 1 || i > L.length+1)
return ERROR;
if(L.length >= L.listsize){ //当前存储空间已满,追加分配
newbase = (ElemType *)realloc(L.elem,(L.listsize + LISTINCREMENT)*sizeof(ElemType));
if(!newbase)
exit(OVERFLOW); //分配失败
L.elem = newbase; //新地址
L.listsize += LISTINCREMENT; //增加存储容量
}
p = &L.elem[i - 1]; //p为插入位置
for(q = &L.elem[L.length - 1];q >= p;q--)
*(q + 1) = *q; //将插入位置及其后的元素后移一个位置
*p = e; //插入元素e
L.length ++; //表长加一
return OK;
}//ListInsert_Sq
时间复杂度: O(n)
删除操作
statues ListDelete_Sq(Sqlist &L,int i,ElemType &e){
//在顺序表L中删除第i个元素,并用e返回其值
//i的合法值为 1 ≤ i ≤ ListLength_Sq(L)
if(i < 1 || i > L.length)
return ERROR; //i的值不合法
p = L.elem + i - 1; //p为删除元素的位置
e = *p; //用e返回被删除元素的值
q = L.elem + L.length - 1; //q为最后一个元素的位置
for(p++;p <= q;p++)
*(p - 1) = *p; //被删元素其后的元素向前移动一个位置
--L.length; //表长减一
return OK;
}//ListDelete_Sq
时间复杂度: O(n)
删除操作(下标实现法)
statues ListDelete_Sq(Sqlist &L,int i,ElemType &e){
//在顺序表L中删除第i个元素,并用e返回其值
//i的合法值为 1 ≤ i ≤ ListLength_Sq(L)
if(i < 1 || i > L.length)
return ERROR; //i的值不合法
e = L.elem[i - 1]; //用e返回被删除元素的值
for(j = 1;j < L.length - 1;j++)
L.elem[j - 1] = L.elem[j]; //被删元素其后的元素向前移动一个位置
--L.length; //表长减一
return OK;
}//ListDelete_Sq
时间复杂度: O(n)
合并操作
void MergeList_Sq(Sqlist La,SqList Lb,SqList &Lc){
//已知顺序线性表La和Lb中的数据元素按值非递减顺序排列,归并La和Lb所得到新的顺序表Lc,Lc的元素也按非递减排列
pa = La.elem;
pb = Lb.elem;
Lc.listsize = Lc.length = La.length + Lb.length;
pc = Lc.elem = (ElemType *)malloc(Lc.listsize * sizeof(ElemType));
if(!Lc.elem)
exit(OVERFLOW); //空间分配失败
pa_last = La.elem + La.length + 1; //La中最后一个元素的位置
pb_last = Lb.elem + Lb.length + 1; //Lb中最后一个元素的位置
while(pa <= pa_last && pb <= pb_last)
{
if(*pa <= *pb)
*pc++ = *pa++; //将La中的元素插入Lc
else
*pc++ = *pb++; //将Lb中的元素插入Lc
}
while(pa <= pa_last)
*pc++ = *pa++; //将La中的剩余元素插入Lc
while(pb <= pb_last)
*pc++ = *pb++; //将Lb中的剩余元素插入Lc
}//MergeList_Sq
时间复杂度: O(La.length + Lb.length)
顺序表存储实现总结
- 用一组地址连续的存储单元,需要预分配空间,会导致空间的闲置或溢出
- 按逻辑次序依次存储元素,逻辑上相邻的元素物理上也相邻,即物理次序和逻辑次序一致
- 元素之间的关系不占存储单元,用元素物理位置相邻表示,存储密度等于1,空间利用率高
- 支持随机访问,又称直接访问
- 插入元素需要移动大量元素
- 适合表长变化不大,经常按位存取元素的场合