博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

C语言实现顺序存储线性表

Posted on 2025-01-20 14:58  steve.z  阅读(56)  评论(0)    收藏  举报

//
// 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;
}