线性表——数据结构
线性表的定义
线性表(List):零个或多个数据元素的有限序列。
元素之间是有序的,若存在多个元素,则第一个元素无前驱,最后一个元素无后继,其他每个元素都有且只有一个前驱和后继。
线性表的顺序存储
指的是用一段地址连续的存储单元依次存储线性表的数据元素。
顺序存储结构
#define MAXSIZE 20 //初始存储空间分配量
typedef int Type;
typedef struct
{
Type data[MAXSIZE]; //数组存储元素
int length; //线性表当前长度
}SqList;
顺序结构的操作
获取元素操作
即返回线性表L中第i个位置的元素,只要i在数组下标的范围内,就是把数组第i-1个下标的值返回。
#define TRUE 1
#define FALSE 0
//获取元素操作
int GetElem(SqList L, int i, Type *e)
{
if (L.length == 0)//线性表为空
return FALSE;
if (i < 1 || i > L.length)//i不在范围内
return FALSE;
*e = L.data[i - 1];//数组下标从0开始,线性表第i个位置元素的下标为i-1
return TRUE;
}
插入操作
即在线性表L的第i个位置插入新元素e,只要插入的位置合理,从最后一个元素开始向前到第i个元素位置,分别将它们都向后移动一个位置,将插入元素填入位置i处。
//插入操作
int ListInsert(SqList *L, int i, Type e)
{
int j;
if (L->length == MAXSIZE)//线性表已满
return FALSE;
if (i<1 || i>L->length)//插入位置不合理
return FALSE;`
if (i <= L->length)//插入位置不在表尾
{
for (j = L->length - 1; j >= i - 1; j--)
{
L->data[j + 1] = L->data[j];//插入位置后的元素都往后移动一位
}
}
L->data[i - 1] = e;//插入新元素
L->length++;//表长加一
return TRUE;
}
删除操作
即删除线性表L第i个位置的元素,只要删除位置合理,从删除位置开始到最后一个元素,分别将它们都向前移动一个位置。
//删除操作
int ListDelete(SqList *L, int i)
{
int j;
if (L->length == 0)//线性表为空
return FALSE;
if (i<1 || i>L->length)//删除位置不合理
return FALSE;
if (i < L->length)//删除位置不在表尾
{
for (j = i; j < L->length; j++)
{
L->data[j - 1] = L->data[j];//将删除位置后的元素前移一个位置
}
}
L->length--;//表长减一
return TRUE;
}
线性表顺序存储的优缺点
-
优点
不需要为表示表中元素之间的逻辑关系而增加额外的存储空间;
可以快速的存取表中任意位置的元素;
-
缺点
插入和删除操作需要移动大量元素;
当线性表长度变化较大时,难以确定存储空间的容量;
动态数组实现线性表的顺序存储
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLDataType;
// 顺序表的动态存储
typedef struct SeqList
{
SLDataType* array; // 指向动态开辟的数组
int size; // 有效数据个数
int capicity; // 容量空间的大小
}SeqList;
// 顺序表初始化
void SeqListInit(SeqList* psl)
{
assert(psl);
psl->array = NULL;
psl->capicity = 0;
psl->size = 0;
}
// 顺序表销毁
void SeqListDestory(SeqList* psl)
{
assert(psl);
free(psl->array);
psl->array = NULL;
psl->capicity = psl->size = 0;
}
// 顺序表打印
void SeqListPrint(SeqList* psl)
{
assert(psl);
for (int i = 0; i < psl->size; i++)
{
printf("%d ", psl->array[i]);
}
printf("\n");
}
// 检查空间,如果满了,进行增容
void CheckCapacity(SeqList* psl)
{
assert(psl);
if (psl->size == psl->capicity)
{
int newcapicity = psl->capicity * 2;
psl->array = (SLDataType*)realloc(psl->array, sizeof(SLDataType)*newcapicity);
psl->capicity = newcapicity;
}
}
// 顺序表尾插
void SeqListPushBack(SeqList* psl, SLDataType x)
{
assert(psl);
SeqListInsert(psl, psl->size, x);
}
// 顺序表尾删
void SeqListPopBack(SeqList* psl)
{
assert(psl);
SeqListErase(psl, psl->size);
}
// 顺序表头插
void SeqListPushFront(SeqList* psl, SLDataType x)
{
assert(psl);
SeqListInsert(psl, 0, x);
}
// 顺序表头删
void SeqListPopFront(SeqList* psl)
{
assert(psl);
SeqListErase(psl, 0);
}
// 顺序表查找
int SeqListFind(SeqList* psl, SLDataType x)
{
assert(psl);
for (int i = 0; i < psl->size; i++)
{
if (psl->array[i] == x)
{
return i;
}
}
return -1;
}
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* psl, int pos, SLDataType x)
{
assert(psl);
assert(pos<=psl->size);
CheckCapacity(psl);//检查线性表是否已满,若满了则进行扩容操作
int end = psl->size;
while (end > pos)
{
psl->array[end] = psl->array[end - 1];
end--;
}
psl->array[pos] = x;
psl->size++;
}
// 顺序表删除pos位置的值
void SeqListErase(SeqList* psl, int pos)
{
assert(psl);
assert(pos<psl->size);
int start = pos + 1;
while (start < psl->size)
{
psl->array[start - 1] = psl->array[start];
start++;
}
psl->size--;
}