特征
- 除首尾元素外每个数据元素只有一个前驱,一个后继
- 线性表长度为0时,为空表
- 支持插入,删除,取值等基本运算
具体实现
顺序存储
线性表中第i个元素的存储位置满足
L
o
c
(
a
i
)
=
L
o
c
(
a
0
)
+
l
×
i
Loc(a_i) = Loc(a_0) + l\times i
Loc(ai)=Loc(a0)+l×i
具体操作
- 初始化:动态分配内存
#define MAX_TERMS 100 // 最大项数
typedef struct{
int* num;
int length;
}SqList;
void init(SqList* l){ //传指针
l->num = (int*)malloc(MAX_TERMS*sizeof(int));
l->length = 0;
}
- 取值:需要判断索引值是否有效
int GetElem(SqList l,int i){
if(i > 0 && i< l.length)
return l.num[i-1];
else
return -1;
}
- 查找:遍历
int LocateElem(SqList l,int e){
for(int i = 0;i < l.length;i++){
if(e == l.num[i])
return i+1;
}
return -1;
}
定义平均查找长度为ASL,
P
i
P_i
Pi 为查找到第i个元素概率,
C
i
C_i
Ci 为元素在表中位置
A
S
L
=
∑
i
=
1
n
p
i
C
i
ASL = \sum_{i=1}^np_iC_i
ASL=i=1∑npiCi
若每个元素查找概率相等,均为
1
n
\frac{1}{n}
n1,则ASL可进一步简化为
n
+
1
2
\frac{n+1}{2}
2n+1
故该查找算法平均时间复杂度为
O
(
n
)
O(n)
O(n)
- 插入
第1至length+1个位置均为合法插入位置(位置与线性表实际下标不同)
在第i个元素位置插入,即原线性表第i个元素前
将第1至length位置处元素依次向后移一个位置,空出第i个位置
void ListInsert(SqList* l,int i,int e){
if(i < 1||i > l->length+1) //invalid index
return;
if(l->length == MAX_TERMS) //overflow
return;
for(int j = l->length-1;j >= i-1;j--){
l->num[j+1] = l->num[j];
}
l->num[i-1] = e;
l->length++;
}
顺序表插入元素的时间复杂度也为 O ( n ) O(n) O(n)
- 删除
void ListDelete(SqList* l,int i){
if(i < 1 && i > l->length)
return;
for(int j = i-1;j < l->length-1;j++){
l->num[j] = l->num[j+1];
}
l->length--;
}
顺序表删除元素的时间复杂度也为 O ( n ) O(n) O(n)
- 两线性表合并
void merge(SqList* a,SqList* b){
int temp;
for(int i = 0;i < b->length;i++){
temp = b->num[i];
if(LocateElem(*a,temp) == 0)
ListInsert(a,a->length+1,temp);
}
}
下面补充show函数并依次进行检验
void show(SqList l){
for(int i = 0;i < l.length;i++){
printf("%d%c",l.num[i],(i==l.length-1?'\n':'\t'));
}
}
int main(){
SqList SL;
init(&SL);
for(int i = 0;i < 5;i++){
ListInsert(&SL,i+1,i);
}
printf("第一次插入:\n");
show(SL);
printf("第二次插入:\n");
ListInsert(&SL,2,100);
show(SL);
printf("删除:\n");
ListDelete(&SL,2);
show(SL);
printf("取值:\n");
int e = GetElem(SL,2);
printf("%d\n",e);
printf("合并:\n");
SqList TMP;
init(&TMP);
for(int i = 5;i < 10;i++){
ListInsert(&TMP,i-4,i);
}
merge(&SL,&TMP);
show(SL);
return 0;
}
输出依次为
第一次插入:
0 1 2 3 4
第二次插入:
0 100 1 2 3 4
删除:
0 1 2 3 4
取值:
1
合并:
0 1 2 3 4 5 6 7 8 9
顺序表弊端
- 存储空间预先分配,元素扩充受限制,且易造成溢出
- 可能造成空间浪费
- 插入,删除操作需移动大量元素
因此,当线性表长度变化小,且可事先确定长度时,使用顺序表