顺序存储:依次存储
特性:没数据还占座
结构代码#define MAXSIZE 20
typedef int ElemType; //整型的
typedef struct
{
ElemType data[MAXSIZE];
int length;
}SqList;
封装的三个属性:
1. 存储空间的起始位置,数组data (座位)
2.最大存储容量:数组的长度MaxSize (一般初始化不变,若变,需动态扩容,可能降低性能)
3.length:当前线性表的长度 (时刻可变,只看元素个数)
地址计算方法(线性表是从1开始的)
ElemType 占用c个存储单元(字节),存储位置关系:LOC(i+1)=LOC(i)+ c;
元素 1 2 3 4 5 n
数组 0 1 2 3 4 n-1
第n个元素的位置=第1个元素的位置 + (n-1)*c
可通过公式 一次 计算出存储地址,存储时间性能为 O(1)
顺序存储结构的优缺点:
在存、读数据时(GetElem操作),任何位置时间复杂度都是O(1)。插入或删除时(只考虑平均情况),时间复杂度为O(n)。
说明,顺序结构适合元素个数比较稳定的存取应用,不经常插入和删除元素。
优点:
1.不需要为元素之间的逻辑关系增加额外的存储空间;
2.可以快速存取表中任意位置的元素。
缺点:
1.插入和删除需要移动大量元素;
2.若线性表长度变化较大,难以确定存储空间的容量。
3.易生成存储空间的碎片(由于顺序存储申请空间是连续的)
--------------------------------------------------------------------------------------------------------------------------------
有待增加
problem1.为什么插入、删除需要移动大量数据?
由于相邻元素的存储位置具有邻居关系,在内存中的位置也是相邻的,中间没有缝隙,导致只能整体移动,无法快速插入和产出
------------------------------------------------------------------------------------------------------------------------------------------------------------
将线性表中第i个位置元素值返回->将数组第i-1下标 值返回;
具体见 getelem.cpp
getelem.cpp
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status;
// Status 函数类型,值为函数结果状态,eg ok;
Status GetElem(SqList L, int i, ElemType *e)
{
if(L.length == 0 || i>L.length)
{
return ERROR;
}
*e = L.data[i-1];
return OK;
}
ListInsert操作
思路:
1.插入位置不合理,抛出异常
2.线性表长度大于等于数组长度--》没有插入的位置,抛出异常,或动态增加数组容量
3.从最后一个 位置向前遍历到第i个位置,分别将它们都向后移动一个位置
4.将插入元素放到i处
5.线性表长度+1
具体见cpp
ListInsert.cpp
//初始条件:顺序线性表L存在,1<i<ListLengh(L)
//操作结果:在L中第i个位置之前插入新的数据元素e L长度+1
Status ListInsert(SqList *L,int i,ElemType e)
{
int k;
if(L->lengh == MAXSIZE) //线性表已满
{
return ERROR;
}
if(i<1 || i>L->length+1) // 当i不在范围之内
{
return ERROR;
}
if (i<= L->length )
{
for(k= L->length-1; k>= i-1;k--) //将最后一位到要插入位置 元素全部向后移一位
{
L->data[k+1]=L->data[k];
}
}
L->data[i-1]=e;
L->length++;
return OK;
}
1.如果删除位置不合理,抛出异常
2.取出删除元素
3.从删除元素位置开始遍历到最后一个元素位置,分别将他们向前移动一个位置
4.表长减一
delete.cpp
/*初始条件:顺序线性表L已存在,1<=i<=ListLength(L)*/
/*操作条件:删除L的第i个元素,并用e返回其值,L的长度-1*/
Status ListDelete(SqList *L,int i,ElemType *e)
{
int k;
if (L->length==0) //空表
return ERROR;
if (i<1 || i < L->length) //删除元素的位置不对
{
return ERROR;
}
*e = L->data[i-1];
if (i < L->length)
{
for(k=i; k < L->length ; k++)
{
L->data[k-1]=L->data[k]; //每个元素从i开始,依次向前移动一位
}
}
L->length--; //表长减一
return OK;
}
插入和删除时间复杂度
1.最好的情况:插入和删除元素刚好在最后一位,不需要移动任何元素,时间复杂度为O(1);
2.最坏的情况:插入和删除元素在第一位,则整个线性表中的元素都要移动,时间复杂度为O(n);
3.平均情况:时间复杂度为最好、最坏的中间值,O((n-1)/2),简化后还是O(n)。