线性表的顺序存储结构,指的是用一段连续的存储单元存储线性表的数据元素。
线性表特性
· 是一个序列,元素直接是有序的。
· 表中元素个数叫表长,元素个数可以有多个,也可以为0。
· 某个元素的上一个元素叫直接前驱元素,下一个元素叫直接后继元素。
顺序存储结构特点
使用数组对元素进行存储。
优点:
· 可以快速存储表中任意位置的元素的值。
· 无需为表中的逻辑关系增加额外的存储空间。
缺点:
· 插入和删除元素需移动大量的元素。
· 容易生成存储空间“碎片”。
时间复杂度
· 读取时的时间复杂度为O(1)。
· 插入、删除时的时间复杂度为O(n)。
算法实现
#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20
typedef int Status;
typedef int ElemType;
typedef struct {
ElemType data[MAXSIZE];
int length;
}SqList;
//初始化线性表
Status InitList(SqList *L)
{
L->length = 0;
return OK;
}
//判空
Status ListEmpty(SqList L)
{
if(L.length == 0)
{
return TRUE;
} else {
return FALSE;
}
}
//清空线性表
Status ClearList(SqList *L)
{
L->length = 0;
return OK;
}
//获取线性表长度
int ListLength(SqList L)
{
return L.length;
}
/**
* 获取线性表中指定位置的元素值
* @param i 获取元素位置下标
* @param e 获取元素值
*/
Status GetElem(SqList L, int i, ElemType *e)
{
if (L.length == 0 || i < 1 || i > L.length)
{
return ERROR;
}
*e = L.data[i - 1];
return OK;
}
//定位元素e在线性表中的位置
int LocateElem(SqList L, ElemType e)
{
int i;
if(L.length == 0)
{
return 0;
}
if (i >= L.length)
{
return 0;
}
for (i = 0; i < L.length; i++)
{
if(L.data[i] == e)
{
break;
}
}
return 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;
}
//插入的位置在线性表范围内
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;
}
//打印单个元素
Status visit(ElemType e)
{
printf("%d ", e);
return OK;
}
//遍历输出线性表中所有元素
Status ListTravel(SqList L)
{
int i; //用于遍历元素的下标
printf("[ ");
for (i = 0; i < L.length; i++)
{
visit(L.data[i]);
}
printf("]\n");
return OK;
}
void unionL(SqList *La, SqList Lb)
{
int i;
int La_len, Lb_len;
ElemType e;
La_len = ListLength(*La);
Lb_len = ListLength(Lb);
for (i = 1; i <= Lb_len; i++)
{
GetElem(Lb, i, &e);
if(!LocateElem(*La, e))
{
ListInsert(La, ++La_len, e);
}
}
}
int main()
{
SqList L;
SqList Lb;
Status status;
ElemType e;
int result;
int j, k;
InitList(&L);
printf("初始化线性表L后,L的长度为:%d\n", L.length);
result = ListEmpty(L);
printf("L是否为空:%s\n", result == TRUE ? "是" : "否");
for(j = 1; j <= 5; j++)
{
status = ListInsert(&L, 1, j);
}
printf("在L表头依次插入1-5后,L中的值为:");
ListTravel(L);
printf("插入5个元素后,L的长度为:%d\n", L.length);
result = ListEmpty(L);
printf("L是否为空:%s\n", result == TRUE ? "是" : "否");
status = ClearList(&L);
printf("清空线性表L后,L的长度为:%d\n", L.length);
result = ListEmpty(L);
printf("L是否为空:%s\n", result == TRUE ? "是" : "否");
//给L的表尾插入10个元素
for (j = 1; j <= 10; j++)
{
ListInsert(&L, j, j); //向线性表表尾插入值
}
printf("插入10个元素后,L中的值为:");
ListTravel(L);
printf("插入10个元素后,L的长度为:%d\n", L.length);
ListInsert(&L, 1, 33);
printf("在L表头插入元素33后,L中的值为:");
ListTravel(L);
printf("插入元素33后,L的长度为:%d\n", L.length);
GetElem(L, 5, &e);
printf("L中第5个元素的值为:%d\n", e);
for (j = 3; j <= 4; j++)
{
k = LocateElem(L, j);
if(k)
{
printf("第%d个元素的值为:%d\n", k, j);
} else {
printf("没有值为%d的元素\n", j);
}
}
k = ListLength(L);
for (j = k + 1; j >= k; j--)
{
status = ListDelete(&L, j, &e);
if (status == ERROR)
{
printf("删除第%d个元素失败\n", j);
}else{
printf("删除的第%d个元素为%d\n", j, e);
}
}
printf("删除表中元素后,L中的值为:");
ListTravel(L);
j = 5;
ListDelete(&L, j, &e);
printf("删除第%d个元素的值为:%d\n", j, e);
printf("删除第%d个元素后,L中的值为:", j);
ListTravel(L);
status = InitList(&Lb);
for (j = 6; j <= 15; j++)
{
status = ListInsert(&Lb, 1, j);
}
printf("插入10个元素后,Lb中的值为:");
ListTravel(L);
unionL(&L, Lb);
printf("合并L到Lb后,L中的值为:");
ListTravel(L);
system("pause\n");
return 0;
}
运行结果
来源:CSDN
作者:Keven Ma
链接:https://blog.csdn.net/Keven_Ma/article/details/103457764