//
// Created by steve xiaohu zhao on 2025/1/20.
//
/**
*
* 线性表的顺序存储结构实现
* 特点:逻辑上相邻的元素,物理上也相邻
*
*/
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100 // 定义线性表的最大长度
// 1. 定义图书结构体 Book
typedef struct {
char no[20]; // 图书 ISBN 号
char name[50]; // 图书名称
float price; // 图书价格
} Book; // 定义图书结构体
// 2. 定义线性表结构体 SqList
typedef struct {
Book *elements; // 存储空间基址
int length; // 当前长度(图书表中当前图书个数)
} SqList; // 定义线性表结构体
// 3. 初始化线性表, 顺序表的初始化操作就是构造一个空的顺序表
int initList(SqList *L) {
L->elements = (Book *) malloc(MAXSIZE * sizeof(Book)); // 为顺序表分配存储空间
if (!L->elements) {
return -1; // 存储分配失败
}
L->length = 0; // 空表长度为0
return 0; // 初始化成功
}
// 4. 销毁线性表
void destroyList(SqList *L) {
free(L->elements); // 释放存储空间
L->length = 0; // 线性表长度清零
}
// 5. 清空线性表
void clearList(SqList *L) {
L->length = 0; // 线性表长度清零
}
// 6. 判断线性表是否为空
int listEmpty(SqList L) {
return L.length == 0; // 线性表为空返回1,否则返回0
}
// 7. 获取线性表的长度
int listLength(SqList L) {
return L.length; // 返回线性表的长度
}
// 8. 获取线性表中第 i 个元素,注意:这里的 i 是第几个元素,不是数组下表
int getElem(SqList L, int i, Book *e) {
if (i < 1 || i > L.length) {
return -1; // i 值不合法
}
*e = L.elements[i - 1]; // 将第 i 个元素的值赋给 e
return 0; // 获取成功
}
// 9. 按值查找,查找线性表中是否存在元素 e
// 顺序表查找的时间复杂度为 O(n),比较的次数平均为 (n+1)/2
int locateElem(SqList L, Book e) {
for (int i = 0; i < L.length; i++) {
// 如果两个元素的 ISBN 号相同,则认为这两个元素相等
// 如果两个元素相等,则返回元素 e 在线性表中的位置
// 此处的 i 表示元素的索引,i + 1 表示元素在线性表中的位置
if (L.elements[i].no == e.no) {
return i + 1; // 返回元素 e 在线性表中的位置
}
}
// 因为位置是从 1 开始的,所以返回 0 表示不存在元素 e
return 0; // 线性表中不存在元素 e
}
// 10. 插入元素, 在线性表的第 i 个位置插入元素 e, 注意:这里的 i 是第几个元素,不是数组下表
// 在第 i 个元素位置插入元素 e,表示要在第 i - 1 个索引处插入元素 e
// 顺序表插入的平均时间复杂度为 O(n), 移动元素的次数平均为 n/2
int listInsert(SqList *L, int i, Book e) {
if (i < 1 || i > L->length + 1) {
return -1; // i 值不合法
}
// 如果线性表已满,则无法插入元素(此处没有处理线性表扩充的问题)
if (L->length >= MAXSIZE) {
return -1; // 线性表已满
}
// 从最后一个元素索引开始,直到第 i - 1 个索引处,将元素依次后移
for (int j = L->length - 1; j >= i - 1; j--) {
L->elements[j + 1] = L->elements[j]; // 将第 i 个元素及之后的元素后移
}
L->elements[i - 1] = e; // 在位置 i 插入元素 e
L->length++; // 线性表长度加 1
return 0; // 插入成功
}
// 11. 删除元素, 删除线性表的第 i 个元素,并将删除的元素赋值给 e
// 顺序表删除的平均时间复杂度为 O(n), 移动元素的次数平均为 (n-1)/2
int listDelete(SqList *L, int i, Book *e) {
if (i < 1 || i > L->length) {
return -1; // i 值不合法
}
*e = L->elements[i - 1]; // 将删除的元素赋值给 e
// 从第 i 个元素索引开始,直到最后一个元素索引处,将元素依次前移
// 注意:这里的 i 是第几个元素,不是数组下标
for (int j = i; j < L->length; j++) {
L->elements[j - 1] = L->elements[j]; // 将第 i 个元素之后的元素前移
}
L->length--; // 线性表长度减 1
return 0; // 删除成功
}
// 12. 打印线性表中的所有元素
void listPrint(SqList L) {
for (int i = 0; i < L.length; i++) {
printf("第 %d 个元素的 ISBN 号:%s, 名称:%s, 价格:%.2f\n", i + 1, L.elements[i].no, L.elements[i].name,
L.elements[i].price);
}
}
// 13. 测试线性表的顺序存储结构
int testSqList() {
SqList L; // 定义一个线性表
Book e; // 定义一个图书元素
// 初始化线性表
if (initList(&L) == -1) {
printf("初始化线性表失败!\n");
return -1;
}
// 判断线性表是否为空
printf("线性表是否为空:%d\n", listEmpty(L));
// 插入元素
Book book1 = {"1001", "C 语言程序设计", 35.5};
listInsert(&L, 1, book1);
Book book2 = {"1002", "数据结构", 45.5};
listInsert(&L, 2, book2);
Book book3 = {"1003", "计算机网络", 55.5};
listInsert(&L, 3, book3);
Book book4 = {"1004", "操作系统", 65.5};
listInsert(&L, 4, book4);
Book book5 = {"1005", "数据库系统", 75.5};
listInsert(&L, 5, book5);
// 插入到第 2 个位置
Book book6 = {"1006", "计算机组成原理", 85.5};
listInsert(&L, 2, book6);
// 打印线性表中的所有元素
listPrint(L);
// 获取线性表的长度
printf("线性表的长度:%d\n", listLength(L));
// 获取线性表中第 3 个元素
getElem(L, 3, &e);
printf("第 3 个元素的 ISBN 号:%s, 名称:%s, 价格:%.2f\n", e.no, e.name, e.price);
// 按值查找元素
Book model = {"1003", "计算机网络", 55.5};
printf("元素 %s 在线性表中的位置:%d\n", model.no, locateElem(L, model));
// 删除元素
listDelete(&L, 3, &e);
printf("删除的元素的 ISBN 号:%s, 名称:%s, 价格:%.2f\n", e.no, e.name, e.price);
// 打印线性表中的所有元素
listPrint(L);
// 清空线性表
clearList(&L);
// 获取线性表的长度
printf("线性表的长度:%d\n", listLength(L));
// 销毁线性表
destroyList(&L);
// 返回 0 表示测试成功
return 0;
}
int main(int argc, const char *argv[]) {
// 测试线性表的顺序存储结构
testSqList();
return 0;
}
标签:return,线性表,int,元素,C语言,length,Book,顺序存储
From: https://www.cnblogs.com/zxhoo/p/18681402