顺序表的简单实现
抽象数据类型 ADT 线性表——顺序表(SequenceList)
特点
- 线性表的数据元素是一个集合{a_1, a_2, a_3, …, a_n},数据元素的类型:DataType(int, char, 自定义…)
- 存在唯一一个被称作“第一个”的数据元素
- 存在唯一一个被称作“最后一个”的数据元素
- 除了第一个元素a_1外,每个元素有且只有一个直接的前驱元素
- 除了最后一个元素a_n外,每个元素有且只有一个直接的后继元素
- 每个数据元素之间是一对一的关系
基本操作的函数名称及参数:
Operation
//初始化线性表:创建一个空的线性表List
InitList(*List) //使用指针进行值的操作
//在线性表List的index下标处插入元素elem
InsertElement(*List, index, elem)
//删除线性表List中下标为index的元素,并返回删除元素的指针e
DeleteElement(*List, index, *elem)
//在线性表List中查找是否存在数据元素e,存在则返回该元素在表中的下标,不存在返回-1
ExsitElement(*List, elem)
//返回线性表的长度
GetLength(*List)
//判断线性表是否为空
IsEmpty(*List)
//清空线性表
ClearList(*List)
//返回线性表中下标为index的数据元素
GetElement(*List, index, *elem)
endADT
一、准备数据
- 描述线性表的顺序存储结构需要三个属性:
- 存储空间的起始位置
- 线性表的最大存储容量
- 线性表的当前长度
(一)定义步骤
1. 定义线性表的最大存储空间和相关数据
#define MAX_SIZE 255
#define TRUE 1
#define FALSE 0
#define NO_FOUND -1
2.线性表里需要有统一类型的元素集合
typedef int ElemType;
typedef struct {
int id;
char * name;
}ElemType;
3.定义顺序表结构
typedef struct{
ElemType datas[MAX_SIZE];
int length;
}SeqList;
(二)具体函数实现
1.初始化
void InitList(SeqList * seqList, ElemType * elemArray, int length)
{
if(length > MAX_SIZE){
printf("超出了顺序表的最大容量,初始化失败!");
return;
}
seqList->length = 0;
for (int i = 0; i < length; ++i) {
//每次循环都在下标为i的位置插入一个元素
InsertElement(seqList, i, elemArray[i]);
}
}
2.插入元素
void InsertElement(SeqList * seqList, int index, ElemType element)
{
if(seqList->length + 1 > MAX_SIZE){
printf("顺序表已满,插入元素失败!\n");
return;
}
if(index < 0 || index > MAX_SIZE - 1){
printf("只能在允许的范围内插入元素[0, %d]", MAX_SIZE - 1);
return;
}
if(index > seqList->length){
printf("下标超过顺序的当前长度,无法插入!");
return;
}
//操作
for (int i = seqList->length - 1; i >= index; i--) {
seqList->data[i + 1] = seqList->data[i];
}
seqList->data[index] = element;
seqList->length++;
}
应当完成的操作
- 验证插入操作后元素空间是否超过最大空间
- index 的值是否合法,index ∈ [0, MAX_SIZE-1]
- 插入的index在 length 之内
- 从第length-1的下标开始,到index为止,前面一个元素赋值给后一个元素
- 将要插入的值赋值给第index个元素
- 顺序表长度+1
3.查找元素
ElemType * GetElement(SeqList * seqList, int index)
{
//1、判断顺序表是否为空
if(IsEmpty(seqList) == TRUE){
printf("顺序表为空,查找失败!\n");
return NULL;
}
//2、判断下标是否越界
if(index < 0 || index >= seqList->length){
printf("下标越界,无法找到对应的元素\n");
return NULL;
}
//3、查找
ElemType * find_elem = &seqList->data[index];
return find_elem;
}
4.删除元素
ElemType * DeleteElement(SeqList * seqList, int index)
{
//1、判断顺序表是否为空
if(IsEmpty(seqList) == TRUE){
printf("顺序表为空,删除失败!\n");
return NULL;
}
//2、判断下标是否越界
if(index < 0 || index >= seqList->length){
printf("下标越界,无法删除该元素\n");
return NULL;
}
//3、找到对应下标的元素,将其保存以便返回
ElemType * del_elem = (ElemType*) malloc(sizeof(ElemType));
//定义查找方法,以副本的方式保存将要删除的元素
*del_elem = *GetElement(seqList, index);
//4、删除对应下标的元素,从index开始,到length-1为止,后面的元素覆盖前面的元素
for (int i = index; i < seqList->length; ++i) {
seqList->data[i] = seqList->data[i+1];
}
//5、顺序表的长度-1
seqList->length--;
return del_elem;
}
应当完成的操作
- 判断顺序表是否为空
- 判断下标是否越界
- 找到对应下标的元素,将其保存以便返回
- 删除对应下标的元素,从index开始,到length-1为止,后面的元素覆盖前面的元素
- 顺序表的长度-1
5.顺序表的其他操作
//判空
int IsEmpty(SeqList * seqList)
{
return GetLength(seqList) == 0 ? TRUE : FALSE;
}
//返回顺序表的长度
int GetLength(SeqList * seqList)
{
return seqList == 0 ? 0 : seqList->length;
}
//打印
void PrintList(SeqList * seqList)
{
int len = seqList->length;
for (int i = 0; i < len; ++i) {
if(i == 0){
printf("顺序表中的元素有:{ [%d, %s],", seqList->data[i].id, seqList->data[i].name);
} else if(i == (len - 1)){
printf("[%d, %s] }\n", seqList->data[i].id, seqList->data[i].name);
} else{
printf("[%d, %s],", seqList->data[i].id, seqList->data[i].name);
}
}
}
//清空顺序表
void ClearList(SeqList * seqList)
{
if(seqList == NULL)
return;
seqList->length = 0;
}
//是否存在
int ExistElement(SeqList * seqList, ElemType * elem)
{
//1、判断顺序表是否为空
if(IsEmpty(seqList) == TRUE){
printf("顺序表为空,不存在该元素!\n");
return -1;
}
//2、查找
int len = GetLength(seqList);
for (int i = 0; i < len; ++i) {
if((elem->id == seqList->data[i].id) && elem->name == seqList->data[i].name){
return i;
}
}
return NO_FOUND;
}
(三)测试代码
1.测试数据
ElemType array[] = {
{1, "辉夜"},
{2, "羽衣"},
{3, "宇智波斑"},
{4, "羽村"},
{5, "漩涡鸣人"},
{6, "宇智波佐助"}
};
2.测试函数
void testSeqList()
{
SeqList seqList;
InitList(&seqList, array, sizeof(array) / sizeof(array[0]));
PrintList(&seqList);
printf("顺序表的长度是:%d\n", GetLength(&seqList));
ElemType person = array[0];
ExistElement(&seqList, &person) != NO_FOUND ? printf("该元素存在\n") : printf("该元素不存在\n");
ElemType * delElement;
delElement = DeleteElement(&seqList, 0);
printf("删除后:\n");
PrintList(&seqList);
printf("删除的元素是:\n");
printf("[%d, %s]\n", delElement->id, delElement->name);
//释放内存
free(delElement);
ExistElement(&seqList, &person) != NO_FOUND ? printf("该元素存在\n") : printf("该元素不存在\n");
}
运行结果
顺序表中的元素有:{ [1, 辉夜],[2, 羽衣],[3, 宇智波斑],[4, 羽村],[5, 漩涡鸣人],[6, 宇智波佐助] }
顺序表的长度是:6
该元素存在
删除后:
顺序表中的元素有:{ [2, 羽衣],[3, 宇智波斑],[4, 羽村],[5, 漩涡鸣人],[6, 宇智波佐助] }
删除的元素是:
[1, 辉夜]
该元素不存在