基本概念
线性表是具有相同数据类型的n个数据元素的有序序列
除第一个元素外,每个元素都有一个直接前驱;除最后一个元素外,每个元素都由一个直接后继
线性表特点
- 表中元素的个数有限
- 表中元素具有逻辑上的顺序性,表中元素由其先后顺序
- 表中元素都是数据元素,每个元素都是单个元素
- 表中元素的数据类型都相同,这意味着每个元素都占用相同大小的存储空间
- 表中元素具有抽象性,即仅讨论元素间的逻辑关系,而不考虑元素究竟表示什么内容。
线性表是一种逻辑结构,表示元素之间一对一的相邻关系。顺序表和链表是存储结构,两者属于不同层面的概念,因此不能混淆
线性表的实现
顺序表
特点:表中元素的逻辑顺序与其存储的物理顺序相同
顺序表分为静态分配和动态分配
- 顺序表优点
-
- 可随机访问
-
- 存储密度高
- 顺序表缺点
-
- 元素插入删除需要移动大量元素
-
- 顺序存储需要分配一段连续的存储空间,不够灵活
顺序表的实现
静态分配
typedef struct
{
int data[MaxSize];
int length;
} SeqList;
动态分配
typedef struct
{
int *data;
int MaxSize;
int length;
} SeqList;
静态顺序表初始化的时候只需令长度为0即可,
动态则需要申请空间,
void InitList(SeqList &L)
{
L.data = (int *)malloc(InitSize * sizeof(int));
L.MaxSize = InitSize;
L.length = 0;
}
常见操作
插入操作
顺序表的第i个位置插入元素,则后第i个元素及之后的元素需要向后移动一位(若i合法)
bool ListInsert(SeqList &L, int i, int e)
{
if (i < 1 || i > L.length + 1)
return false;
if (L.length > L.MaxSize)
return false;
for (int j = L.length; j >= i; j--)
{
L.data[j] = L.data[j - 1];
}
L.data[i - 1] = e;
L.length++;
return true;
}
在动态分配的顺序表中,可以扩大顺序表长度,静态分配则不可以
重新申请更大的一片空间将元素移动过去
void IncreaseSize(SeqList &L, int len)
{
int *p = L.data;
L.data = (int *)malloc((L.MaxSize + len) * sizeof(int));
for (int i = 0; i < L.length; i++)
{
L.data[i] = p[i];
}
L.MaxSize = L.MaxSize + len;
free(p);
}
删除操作和插入操作相似,删除第i个元素,将i之后元素向前移动一位,并修改线性表长度
bool ListDelete(SeqList &L, int i, int &e)
{
if (i < 1 || i > L.length)
return false;
e = L.data[i - 1];
for (int j = i; j < L.length; j++)
L.data[i - 1] = L.data[i];
L.length--;
return true;
}
查找操作就不再赘述
int LocatElem(SeqList L, int e)
{
for (int i = 0; i < L.length; i++)
if (L.data[i] == e)
return i + 1;
return 0;
}