线性表的存储结构:顺序存储结构和链式存储结构
顺序存储结构:指的是用一段地址连续的存储单元依次存储线性表的数据元素
顺序结构封装需要三个属性:
——存储空间的起始位置,数据data,它的存储位置就是线性表存储空间的存储位置、
——线性表的最大存储容量:数组的长度MaxSize
——线性表的当前长度:length
(数组的长度与线性表的当前长度需要区分:数组长度是存放线性表的存储空间的总长度,一般初始化后不变,而线性表的当前长度是线性表中的元素的个数,是会变化的)
插入操作思路:
——如果插入数据不合理,抛出异常
——如果线性长度大于等于数组长度,则抛出异常或动态增加数组容量
——从最后一个元素开始向前遍历到第i个,分别将他们都向后移动一个位置
——将要插入的元素填入位置i处
——线性表长度+1
status listInsert(sqList *L, int i, ElemType e)
{
int k;
if (L->length == MAXSIZE) {
return ERROR;
}
if (i<1 || i>L->length+1) {
return ERROR;
}
*e = L->data[i-1];
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;
}
删除操作思路:
——如该删除位置不合理,抛出异常
——取出删除元素
——从删除元素位置开始遍历到最后一个元素位置,分别将它们都向前移动一个位置
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]
}
}
L->length--;
return ok;
}
插入和删除的时间复杂度:
最好情况:插入和删除刚好都在最后一个位置,不需要移动其他元素,时间复杂度O(1)
最坏情况:插入和删除刚好都在第一个位置,要移动所以元素,时间复杂度O(n)
时间复杂度O((n+1)/2) = O(n)
顺序存储结构,在存、读取数据时候不管那个位置时间复杂度都是O(1),插入、删除为O(n)
说明其笔记适合元素个数比较稳定,不经常插入和删除,而更多的是存取数据
优点:
——无须为表示表中元素之间的逻辑关系而增加额外的存储空间
——可以快速存储表中的任意位置的元素
缺点:
——插入和删除操作需要移动大量的元素
——当线性表长度变化较大的时,难以确定存储空间的容量
——容易造成空间碎片
链式存储结构:用一组任意的存储单元存储线性表的数据元素,这组存储单元可以存在内存中未被占用的任意位置
(所以和顺序存储结构不同,除了本身数据信息(数据域)外,还需要存储后继位置信息(指针域),这两部分信息组成称为存储映像,称为节点(Node))
单链表——只有一个指针域,有个头和尾,尾部为NULL