顺序表用数组存储数据元素(可以是结构体数组,也可以是结构体内的元素数组),插入和删除等等也是类似数组的操作。
顺序表优势:
1、无须为表示表中元素之间的逻辑关系而增加额外的存储关系,就是直接的顺序;
2、可以快速添加、替换表中任意位置的元素;
3、造成存储空间“碎片”(因为申请空间不是连续的,也无法对齐,会产生较多的内存“缝隙”)。
顺序表的缺陷:
1、插入和删除需要移动元素,有较大的时间复杂度;
2、线性表长度不确定时,难以确定顺序表存储空间容量。
一、插入(三种情况)
1、索引不在数组范围内或数组长度大于等于限长,无法插入,直接退出;
2、索引在数组中,需要向后移动后续的元素,腾出一个能放数据的空位;
3、索引正好在数组末尾,则不需要移动数组,直接插入。
二、删除(三种情况)
1、索引不在数组范围内或数组长度大于等于限长,无法删除,直接退出;
2、索引在数组中,需要向前移动后续的元素,把那个索引位置的元素直接覆盖掉,相当于删除了;
3、索引正好在数组末尾,则不需要移动数组,不用管,只需要把表长减小就行(相当于已经不在表中了)。
//顺序表
#include <stdio.h>
#define maxSize 20
#define OK 1
#define ERROR 0
int i = 0, j = 0, check = 0;
//定义顺序表结构体
typedef struct
{
int data[maxSize]; //存储数据元素
int length; //长度
}Sqlist;
//向链表中插入元素
int Insert(Sqlist* L, int num, int index)
{
//如果长度不在数组范围内或超出限长
if (index > L->length || index < 0 || L->length>=maxSize)
return ERROR;
//如果在中间
else if (index >= 0 && index < L->length)
{
for (i = L->length; i > index; i--) //向后移
{
L->data[i] = L->data[i - 1];
}
L->data[index] = num;
}
//在末尾插入
else
{
L->data[index] = num; //赋值
}
L->length++; //长度++
return OK;
}
//检查是否执行成功
void Check()
{
if (check == 0)
printf("执行失败!\n");
}
//遍历链表
void Print(Sqlist L)
{
for (i = 0; i < L.length; i++)
printf("%d", L.data[i]);
printf("\n");
}
//删除元素
int Delete(Sqlist* L, int index)
{
//如果长度不在数组范围内
if (index >= L->length || index < 0)
return ERROR;
//如果在中间
else if (index >= 0 && index < L->length)
{
for (i = index; i < L->length - 1; i++)
{
L->data[i] = L->data[i + 1];
}
}
//如果在末尾,不用管,只需要把表长减小就行(相当于已经不在表中了)
L->length--; //长度--
return OK;
}
int main()
{
Sqlist L; //定义链表结构体
//1、链表初始化
L.length = 0;
//2、向链表中添加元素
//在L中插入元素
for (i = 0; i < 5; i++)
{
check = Insert(&L, i + 5, i); //插值(5~9)
Check(); //检测
}
for (i = 0; i < 5; i++)
{
check = Insert(&L, i, i); //插值(0~4)
Check(); //检测
}
//删除链表对应元素
Delete(&L, 0);
//遍历链表
Print(L);
return 0;
}