顺序表(多文件处理-完整代码)
集成开发环境 VS 2019
参考书籍:《大话数据结构——溢彩加强版》程杰 · 著【清华大学出版社】
默认读者理解数据结构的理论知识
头文件(splist.h)
#pragma once
#include <stdio.h>
#include <stdlib.h>
//#include <assert.h> //断言
typedef int DataType; //数据类型
//布尔类型
typedef enum Boolean{
TRUE = 1,
FALSE = 0
}Boolean;
//函数的返回值状态
typedef enum StatusSqList{
OK = 1, //正确状态
ERROR = 2, //错误状态
FULL = 3, //顺序表满了
EMPTY = 4, //顺序表空了
NON_EXISTENT = 5 //当前顺序表不存在
}StatusSqList;
//结构体抽象---> 抽象为一个数组
typedef struct sqlist
{
DataType* dataMemory; //一级指针动态内存申请变成一位数组
size_t maxSize; //最大元素个数-->容量
size_t curSize; //当前元素个数
}Sqlist, * LPSqlist;
//获取操作顺序表函数返回的状态,该函数返回 Boolean 型以确定函数是否正确执行
//errorInfo 自定义打印错误信息,可传入 NULL 不自定义
//isOut 选择是否打印 errorInfo 错误信息 及 预设定的错误信息
Boolean status_info_sqlist(StatusSqList status, const char* errorInfo, Boolean isOut);
//获取顺序表中的元素个数
size_t size_sqlist(LPSqlist lpSqlist);
//判断当前顺序表中是否为空
Boolean is_empty_sqlist(LPSqlist lpSqlist);
//创建顺序表
StatusSqList create_sqlist(LPSqlist* lpSqlist, size_t maxSize);
//清空顺序表
StatusSqList clear_sqlist(LPSqlist lpSqlist);
//销毁顺序表
StatusSqList destroy_sqlist(LPSqlist* lpSqlist);
//插入数据,不排序,下标从0开始
StatusSqList insert_sqlist(LPSqlist lpSqlist, size_t index, DataType insertData);
//遍历数据
StatusSqList traverse_sqlist(LPSqlist lpSqlist);
//获取第 index 个元素,下标从0开始
StatusSqList get_data_sqlist(LPSqlist lpSqlist, size_t index, DataType* getData);
//查找某一个数据元素,并返回其位置
StatusSqList search_sqlist(LPSqlist lpSqlist, DataType data, size_t* getIndex);
//删除指定位置的数据
StatusSqList delete_sqlist(LPSqlist lpSqlist, size_t index, DataType* getDeleteData);
/**************************其他操作函数*********************************/
//插入数据并排序
StatusSqList insert_sort_sqlist(LPSqlist lpSqlist, DataType insertData);
//在头部元素插入
StatusSqList insert_front_sqlist(LPSqlist lpSqlist, DataType pushData);
//删除头部元素
StatusSqList delete_front_sqlist(LPSqlist lpSqlist, DataType* getPopData);
//在尾部元素插入
StatusSqList insert_back_sqlist(LPSqlist lpSqlist, DataType pushData);
//删除尾部元素
StatusSqList delete_back_sqlist(LPSqlist lpSqlist, DataType* getPopData);
函数的实现(splist.c)
#include "sqlist.h"
Boolean status_info_sqlist(StatusSqList status, const char* errorInfo, Boolean isOut)
{
if (isOut)
{
if (errorInfo == NULL) //不自定义错误信息
{
errorInfo = "";
}
switch (status)
{
case OK: //正确执行
return TRUE; //true 表示函数正确执行了
case ERROR:
printf("%s", errorInfo);
break;
case FULL:
printf("顺序表满了 %s", errorInfo);
break;
case EMPTY:
printf("顺序表空了 %s", errorInfo);
break;
case NON_EXISTENT:
printf("当前顺序表不存在 %s", errorInfo);
break;
}
return FALSE; //除了 OK 状态,其余状态都是错误或警告的状态
}
else
{
if (status == OK)
{
return TRUE;
}
else
{
return FALSE;
}
}
}
size_t size_sqlist(LPSqlist lpSqlist)
{
return lpSqlist->curSize;
}
Boolean is_empty_sqlist(LPSqlist lpSqlist)
{
//顺序表当前数据个数不为0
if (lpSqlist->curSize == 0)
{
return TRUE;
}
return FALSE;
}
StatusSqList clear_sqlist(LPSqlist lpSqlist)
{
if (is_empty_sqlist(lpSqlist))
{
return EMPTY;
}
//清空数据,伪清空(直接将当前数据个数清零)
lpSqlist->curSize = 0;
return OK;
}
StatusSqList create_sqlist(LPSqlist* lpSqlist, size_t maxSize)
{
*lpSqlist = (LPSqlist)malloc(sizeof(Sqlist));
//assert(lpSqlist); //断言处理
if (*lpSqlist == NULL)
{
return ERROR;
}
//指针指向一维数组
(*lpSqlist)->dataMemory = (DataType*)malloc(sizeof(DataType) * maxSize);
//assert(lpSqlist->dataMemory); //断言处理
if ((*lpSqlist)->dataMemory == NULL)
{
return ERROR;
}
(*lpSqlist)->curSize = 0; //当前元素个数
(*lpSqlist)->maxSize = maxSize; //顺序表最大元素个数
return OK;
}
StatusSqList destroy_sqlist(LPSqlist* lpSqlist)
{
//顺序表不存在
if (*lpSqlist == NULL)
{
return NON_EXISTENT;
}
//销毁顺序表中创建的数组
free((*lpSqlist)->dataMemory);
//销毁顺序表结构
free(*lpSqlist);
*lpSqlist = NULL;
return OK;
}
StatusSqList insert_sqlist(LPSqlist lpSqlist, size_t index, DataType insertData)
{
//当前表不存在
if (lpSqlist == NULL)
{
return NON_EXISTENT;
}
if (lpSqlist->curSize == lpSqlist->maxSize)
{
return FULL;
}
//插入范围错误
if (index > lpSqlist->curSize)
{
return ERROR;
}
#if 0
//*****************第一种插入方案******************
size_t pos = lpSqlist->curSize;
//1. 先将数据放在数组的最后
lpSqlist->dataMemory[pos] = insertData;
//2. 以两两数据的交换方式,从最后将新数据移动到指定位置
while (pos != index)
{
DataType tempData = lpSqlist->dataMemory[pos];
lpSqlist->dataMemory[pos] = lpSqlist->dataMemory[pos - 1];
lpSqlist->dataMemory[pos - 1] = tempData;
pos--;
}
#endif
//*****************第二种插入方案*****************
//数据元素向后移动一位,腾出要插入的数据
for (size_t i = lpSqlist->curSize; i > index; i--)
{
lpSqlist->dataMemory[i] = lpSqlist->dataMemory[i - 1];
}
lpSqlist->dataMemory[index] = insertData;
lpSqlist->curSize++; //元素个数加1
return OK;
}
StatusSqList traverse_sqlist(LPSqlist lpSqlist)
{
//顺表不存在
if (lpSqlist == NULL)
{
return NON_EXISTENT;
}
if (is_empty_sqlist(lpSqlist))
{
return EMPTY;
}
for (size_t i = 0; i < lpSqlist->curSize; i++)
{
printf("%d\t", lpSqlist->dataMemory[i]);
}
return OK;
}
StatusSqList get_data_sqlist(LPSqlist lpSqlist, size_t index, DataType* getData)
{
//当前顺序表不存在
if (lpSqlist == NULL)
{
return NON_EXISTENT;
}
if (is_empty_sqlist(lpSqlist))
{
return EMPTY;
}
//超出数据范围
if (index > lpSqlist->curSize - 1)
{
return ERROR;
}
*getData = lpSqlist->dataMemory[index];
return OK;
}
StatusSqList search_sqlist(LPSqlist lpSqlist, DataType data, size_t* getIndex)
{
//当前顺序表不存在
if (lpSqlist == NULL)
{
return NON_EXISTENT;
}
if (is_empty_sqlist(lpSqlist))
{
return EMPTY;
}
for (size_t i = 0; i < lpSqlist->curSize; i++)
{
if (lpSqlist->dataMemory[i] == data)
{
*getIndex = i;
return OK;
}
}
//都循环完了,说明没有找到指定数据
return ERROR;
}
StatusSqList delete_sqlist(LPSqlist lpSqlist, size_t index, DataType* getDeleteData)
{
//当前顺序表不存在
if (lpSqlist == NULL)
{
return NON_EXISTENT;
}
if (is_empty_sqlist(lpSqlist))
{
return EMPTY;
}
//指定删除的位置,不在范围之内
if (index > lpSqlist->curSize - 1)
{
return ERROR;
}
//若需要获取被删除的数据
if (getDeleteData != NULL)
{
*getDeleteData = lpSqlist->dataMemory[index];
}
//伪删除,从指定位置开始向前移动数据
for (size_t i = index; i < lpSqlist->curSize - 1; i++)
{
lpSqlist->dataMemory[i] = lpSqlist->dataMemory[i + 1];
}
lpSqlist->curSize--; //元素个数减1
return OK;
}
StatusSqList insert_sort_sqlist(LPSqlist lpSqlist, DataType insertData)
{
//当前顺序表不存在
if (lpSqlist == NULL)
{
return NON_EXISTENT;
}
//顺表表满了
if (lpSqlist->curSize == lpSqlist->maxSize)
{
return FULL;
}
//若为第一次插入数据
if (lpSqlist->curSize == 0)
{
lpSqlist->dataMemory[0] = insertData;
}
else
{
//1. 先将新数据存入顺序表最后一个位置
lpSqlist->dataMemory[lpSqlist->curSize] = insertData;
//2.1 将新数据域前驱数据进行比较
//2.2 小于前驱数据就两个数据位置交换
//2.3 回到2.1步骤,做重复操作,直到新数据大于或等于前驱数据为止
for (size_t i = lpSqlist->curSize; i > 0; i--)
{
if (lpSqlist->dataMemory[i] < lpSqlist->dataMemory[i - 1])
{
DataType tempData = lpSqlist->dataMemory[i];
lpSqlist->dataMemory[i] = lpSqlist->dataMemory[i - 1];
lpSqlist->dataMemory[i - 1] = tempData;
}
else //说明已经排序完成,不需要继续比较了
{
break;
}
}
}
lpSqlist->curSize++; //元素个数加1
return OK;
}
StatusSqList insert_front_sqlist(LPSqlist lpSqlist, DataType pushData)
{
return insert_sqlist(lpSqlist, 0, pushData);
}
StatusSqList delete_front_sqlist(LPSqlist lpSqlist, DataType* getPopData)
{
//delete_sqlist 函数允许 getPopData 为 NULL
return delete_sqlist(lpSqlist, 0, getPopData);;
}
StatusSqList insert_back_sqlist(LPSqlist lpSqlist, DataType pushData)
{
return insert_sqlist(lpSqlist, lpSqlist->curSize, pushData);
}
StatusSqList delete_back_sqlist(LPSqlist lpSqlist, DataType* getPopData)
{
//delete_sqlist 函数允许 getPopData 为 NULL
return delete_sqlist(lpSqlist, lpSqlist->curSize - 1, getPopData);
}
主函数测试代码
请点击链接转移到 文章末尾 查看完整代码和运行效果
代码内容说明
sqlist.h 中的一些非函数内容
下面的内容都会在函数中的用到
typedef int DataType; //数据类型
//布尔类型
typedef enum Boolean{
TRUE = 1,
FALSE = 0
}Boolean;
//函数的返回值状态
typedef enum StatusSqList{
OK = 1, //正确状态
ERROR = 2, //错误状态
FULL = 3, //顺序表满了
EMPTY = 4, //顺序表空了
NON_EXISTENT = 5 //当前顺序表不存在
}StatusSqList;
//结构体抽象---> 抽象为一个数组
typedef struct sqlist
{
DataType* dataMemory; //一级指针动态内存申请变成一位数组
size_t maxSize; //最大元素个数-->容量
size_t curSize; //当前元素个数
}Sqlist, * LPSqlist;
检测函数状态函数(status_info_sqlist)
- 原型
Boolean status_info_sqlist(StatusSqList status, const char* errorInfo, Boolean isOut);
- 函数作用和参数说明
//获取操作顺序表函数返回的状态,该函数返回 Boolean 型以确定函数是否正确执行
//可以用于调试程序,或像一个函数操作异常的判断
//返回的 Boolean 类型
//TRUE 为正确执行
//FALSE 为不正确执行
StatusSqList status
对顺序表进行操作的函数返回的状态
const char* errorInfo
自定义打印错误信息,可传入 NULL 不自定义
Boolean isOut
选择是否打印 errorInfo 错误信息 及 预设定的错误信息,TRUE(打印),FALSE(不打印)
- 联系
与自定义的枚举类型有关
//函数返回的状态
typedef enum StatusSqList{
OK = 1, //正确状态
ERROR = 2, //错误状态
FULL = 3, //顺序表满了
EMPTY = 4, //顺序表空了
NON_EXISTENT = 5 //当前顺序表不存在
}StatusSqList;
- 实现
Boolean status_info_sqlist(StatusSqList status, const char* errorInfo, Boolean isOut)
{
if (isOut)
{
if (errorInfo == NULL) //不自定义错误信息
{
errorInfo = "";
}
switch (status)
{
case OK: //正确执行
return TRUE; //true 表示函数正确执行了
case ERROR:
printf("%s", errorInfo);
break;
case FULL:
printf("顺序表满了 %s", errorInfo);
break;
case EMPTY:
printf("顺序表空了 %s", errorInfo);
break;
case NON_EXISTENT:
printf("当前顺序表不存在 %s", errorInfo);
break;
}
return FALSE; //除了 OK 状态,其余状态都是错误或警告的状态
}
else
{
if (status == OK)
{
return TRUE;
}
else
{
return FALSE;
}
}
}
万金油函数
返回顺序表的元素个数(size_sqlist)
size_t size_sqlist(LPSqlist lpSqlist)
{
return lpSqlist->curSize;
}
判断顺序表是否为空表(is_empty_sqlist)
Boolean is_empty_sqlist(LPSqlist lpSqlist)
{
//顺序表当前数据个数不为0
if (lpSqlist->curSize == 0)
{
return TRUE;
}
return FALSE;
}
创建顺序表(create_sqlist)
StatusSqList create_sqlist(LPSqlist* lpSqlist, size_t maxSize)
{
*lpSqlist = (LPSqlist)malloc(sizeof(Sqlist));
//assert(lpSqlist); //断言处理
if (*lpSqlist == NULL)
{
return ERROR; //返回错误状态
}
//指针指向一维数组,大小: maxSize
(*lpSqlist)->dataMemory = (DataType*)malloc(sizeof(DataType) * maxSize);
//assert(lpSqlist->dataMemory); //断言处理
if ((*lpSqlist)->dataMemory == NULL)
{
return ERROR;
}
(*lpSqlist)->curSize = 0; //当前元素个数
(*lpSqlist)->maxSize = maxSize; //顺序表最大元素个数
return OK;
}
清空顺序表(clear_sqlist)
StatusSqList clear_sqlist(LPSqlist lpSqlist)
{
if (is_empty(lpSqlist))
{
return EMPTY; //返回顺序表空状态
}
//清空数据,伪清空(直接将当前数据个数清零)
lpSqlist->curSize = 0;
return OK;
}
销毁顺序表(destroy_sqlist)
StatusSqList destroy_sqlist(LPSqlist* lpSqlist)
{
//顺序表不存在
if (*lpSqlist == NULL)
{
return NON_EXISTENT;
}
//销毁顺序表中创建的数组
free((*lpSqlist)->dataMemory);
//销毁顺序表结构
free(*lpSqlist);
*lpSqlist = NULL;
return OK;
}
插入元素(insert_sqlist)
StatusSqList insert_sqlist(LPSqlist lpSqlist, size_t index, DataType insertData)
{
//当前表不存在
if (lpSqlist == NULL)
{
return NON_EXISTENT;
}
if (lpSqlist->curSize == lpSqlist->maxSize)
{
return FULL; //顺序表满了
}
//插入范围错误
if (index > lpSqlist->curSize)
{
return ERROR;
}
#if 0
//*****************第一种插入方案******************
size_t pos = lpSqlist->curSize;
//1. 先将数据放在数组的最后
lpSqlist->dataMemory[pos] = insertData;
//2. 以两两数据的交换方式,从最后将新数据移动到指定位置
while (pos != index)
{
DataType tempData = lpSqlist->dataMemory[pos];
lpSqlist->dataMemory[pos] = lpSqlist->dataMemory[pos - 1];
lpSqlist->dataMemory[pos - 1] = tempData;
pos--;
}
#endif
//*****************第二种插入方案*****************
//数据元素向后移动一位,腾出要插入的数据
for (size_t i = lpSqlist->curSize; i > index; i--)
{
lpSqlist->dataMemory[i] = lpSqlist->dataMemory[i - 1];
}
lpSqlist->dataMemory[index] = insertData;
lpSqlist->curSize++; //元素个数加1
return OK;
}
遍历顺序表(traverse_sqlist)
StatusSqList traverse_sqlist(LPSqlist lpSqlist)
{
//顺表不存在
if (lpSqlist == NULL)
{
return NON_EXISTENT;
}
if (is_empty(lpSqlist))
{
return EMPTY;
}
for (size_t i = 0; i < lpSqlist->curSize; i++)
{
printf("%d\t", lpSqlist->dataMemory[i]);
}
return OK;
}
获取顺序表元素(get_data_sqlist)
注意: 获取的元素是从第 3 参数
DataType* getData
获取的
StatusSqList get_data_sqlist(LPSqlist lpSqlist, size_t index, DataType* getData)
{
//当前顺序表不存在
if (lpSqlist == NULL)
{
return NON_EXISTENT;
}
if (is_empty(lpSqlist))
{
return EMPTY;
}
//超出数据范围
if (index > lpSqlist->curSize - 1)
{
return ERROR;
}
*getData = lpSqlist->dataMemory[index];
return OK;
}
查找元素(search_sqlist)
注意: 查找到的元素的下标是通过第 3 参数
size_t* getIndex
获取
StatusSqList search_sqlist(LPSqlist lpSqlist, DataType data, size_t* getIndex)
{
//当前顺序表不存在
if (lpSqlist == NULL)
{
return NON_EXISTENT;
}
if (is_empty(lpSqlist))
{
return EMPTY;
}
for (size_t i = 0; i < lpSqlist->curSize; i++)
{
if (lpSqlist->dataMemory[i] == data)
{
*getIndex = i;
return OK;
}
}
//都循环完了,说明没有找到指定数据
return ERROR;
}
删除顺序表某一个元素(delete_sqlist)
通过第 2 参数
size_t index
(下标)指定要删除的元素通过第 3 参数
DataType* getDeleteData
获取删除元素,不获取时,传入NULL
StatusSqList delete_sqlist(LPSqlist lpSqlist, size_t index, DataType* getDeleteData)
{
//当前顺序表不存在
if (lpSqlist == NULL)
{
return NON_EXISTENT;
}
if (is_empty(lpSqlist))
{
return EMPTY;
}
//指定删除的位置,不在范围之内
if (index > lpSqlist->curSize - 1)
{
return ERROR;
}
//若需要获取被删除的数据
if (getDeleteData != NULL)
{
*getDeleteData = lpSqlist->dataMemory[index];
}
//伪删除,从指定位置开始向前移动数据
for (size_t i = index; i < lpSqlist->curSize - 1; i++)
{
lpSqlist->dataMemory[i] = lpSqlist->dataMemory[i + 1];
}
lpSqlist->curSize--; //元素个数减1
return OK;
}
其他操作函数说明
插入数据并进行排序(insert_sort_sqlist)
StatusSqList insert_sort_sqlist(LPSqlist lpSqlist, DataType insertData)
{
//当前顺序表不存在
if (lpSqlist == NULL)
{
return NON_EXISTENT;
}
//顺表表满了
if (lpSqlist->curSize == lpSqlist->maxSize)
{
return FULL;
}
//若为第一次插入数据(有些多余,其实该 if-else 的内容可以合并为 else 中的内容即可)
if (lpSqlist->curSize == 0)
{
lpSqlist->dataMemory[0] = insertData;
}
else
{
//1. 先将新数据存入顺序表最后一个位置
lpSqlist->dataMemory[lpSqlist->curSize] = insertData;
//2.1 将新数据域前驱数据进行比较
//2.2 小于前驱数据就两个数据位置交换
//2.3 回到2.1步骤,做重复操作,直到新数据大于或等于前驱数据为止
for (size_t i = lpSqlist->curSize; i > 0; i--)
{
if (lpSqlist->dataMemory[i] < lpSqlist->dataMemory[i - 1])
{
DataType tempData = lpSqlist->dataMemory[i];
lpSqlist->dataMemory[i] = lpSqlist->dataMemory[i - 1];
lpSqlist->dataMemory[i - 1] = tempData;
}
else //说明已经排序完成,不需要继续比较了
{
break;
}
}
}
lpSqlist->curSize++; //元素个数加1
return OK;
}
对顺序表的头或尾部元素的操作
头部插入元素和删除元素
StatusSqList insert_front_sqlist(LPSqlist lpSqlist, DataType pushData)
{
return insert_sqlist(lpSqlist, 0, pushData);
}
//删除的元素可以从第 3 参数 DataType* getPopData 获取,不获取时,可传入 NULL
StatusSqList delete_front_sqlist(LPSqlist lpSqlist, DataType* getPopData)
{
//delete_sqlist 函数允许 getPopData 为 NULL
return delete_sqlist(lpSqlist, 0, getPopData);;
}
尾部插入元素和删除元素
StatusSqList insert_back_sqlist(LPSqlist lpSqlist, DataType pushData)
{
return insert_sqlist(lpSqlist, lpSqlist->curSize, pushData);
}
//删除的元素可以从第 3 参数 DataType* getPopData 获取
StatusSqList delete_back_sqlist(LPSqlist lpSqlist, DataType* getPopData)
{
//delete_sqlist 函数允许 getPopData 为 NULL
return delete_sqlist(lpSqlist, lpSqlist->curSize - 1, getPopData);
}
主函数中部分函数演示
代码
#include "sqlist.h"
int main()
{
//函数返回状态
StatusSqList status;
//创建顺序表
LPSqlist lpSqlist = NULL;
status = create_sqlist(&lpSqlist, 5);
if (FALSE == status_info_sqlist(status, "创建顺序表失败\n", TRUE))
{
exit(EXIT_FAILURE);
}
//插入数据
printf("插入数据:1,2,3,4\n");
DataType insertData[4] = {1, 2, 3, 4};
for (size_t i = 0; i < 4; i++)
{
status = insert_sqlist(lpSqlist, i, insertData[i]);
if (FALSE == status_info_sqlist(status, "插入失败\n", TRUE))
{
break;
}
}
//在第0个位置插入数据
printf("在第0个位置再插入数据 10\n");
status = insert_sqlist(lpSqlist, 0, 10);
status_info_sqlist(
status,
"插入数据失败\n",
TRUE
);
//插入并排序
#if 0
//插入数据并自动排序
printf("插入数据:1,2,3,4,并自动排序\n");
for (size_t i = 4; i > 0; i--)
{
status = insert_sort_sqlist(lpSqlist, insertData[i - 1]);
if (FALSE == status_info_sqlist(status, "插入数据(带排序)失败", TRUE))
{
break;
}
}
//再插入一个数据
printf("再插入一个数据 0\n");
status = insert_sort_sqlist(lpSqlist, 0)
status_info_sqlist(
status,
"插入数据(带排序)失败",
TRUE
);
#endif
//遍历数据
printf("遍历数据:\n");
traverse_sqlist(lpSqlist);
printf("\n\n");
//获取数据
printf("获取第0个数据:");
if (!is_empty_sqlist(lpSqlist))
{
DataType getData = 0;
get_data_sqlist(lpSqlist, 0, &getData);
printf("%d ", getData);
}
else
{
printf("数据为空,获取数据失败");
}
printf("\n\n");
//查找数据
printf("查找数据 10:");
size_t index;
status = search_sqlist(lpSqlist, 10, &index);
if (status_info_sqlist(status,"查找失败",TRUE))
{
printf("找到对应的下标是 %d", index); //打印获取到的下标
}
printf("\n\n");
//删除数据
printf("删除第0个数据:");
delete_sqlist(lpSqlist, 0, NULL);
traverse_sqlist(lpSqlist);
printf("\n\n");
//销毁顺序表
status = destroy_sqlist(&lpSqlist);
status_info_sqlist(status, "销毁顺序表失败", TRUE);
return 0;
}
结果
插入数据:1,2,3,4
在第0个位置再插入数据 10
遍历数据:
10 1 2 3 4
获取第0个数据:10
查找数据 10:找到对应的下标是 0
删除第0个数据:1 2 3 4