目录

0——静态分配内存的顺序表和动态分配内存的顺序表的相同之处和不同之处

相同之处

不同之处

代码实现

1. 初始化   

2. 插入   

3. 按位查找   

4. 按值查找   

5. 删除   

6. 注销   

7. 打印顺序表

8. 测试代码   

9. 完整代码   

10. 运行截图


0——静态分配内存的顺序表和动态分配内存的顺序表的相同之处和不同之处

相同之处
  • 基本操作逻辑相同:无论是静态分配还是动态分配的顺序表,其核心的操作逻辑是一致的。例如插入操作都需要将插入位置之后的元素依次后移,删除操作都需要将删除位置之后的元素依次前移,查找操作也都是通过遍历或者直接定位来完成。

  • 数据元素存储方式相同:两种顺序表都是将数据元素依次存储在连续的内存空间中,都可以通过数组下标来直接访问元素,时间复杂度为 \(O(1)\)。

  • 功能用途相同:都用于实现线性表的功能,支持数据的插入、删除、查找等基本操作。

不同之处
  • 内存分配方式

    • 静态分配:在编译时就确定了顺序表的最大容量,使用数组来存储元素,数组的大小在程序运行过程中不能改变。

    • 动态分配:在程序运行时根据需要动态地分配内存空间,可以通过 mallocrealloc 等函数来调整顺序表的容量。

  • 内存管理

    • 静态分配:不需要手动管理内存,数组的内存空间由系统自动分配和释放。

    • 动态分配:需要手动管理内存,使用 malloc 分配内存,使用 free 释放内存,否则会造成内存泄漏。

  • 表长限制

    • 静态分配:顺序表的最大长度是固定的,一旦达到最大长度就无法再插入新的元素。

    • 动态分配:可以根据需要动态地调整顺序表的容量,理论上只要系统有足够的内存,就可以不断地插入新的元素。

    纯C语言代码,不涉及C++   

代码实现

1. 初始化   

#define MaxSize 50
typedef int ElemType;

typedef struct SQList {
    ElemType data[MaxSize];    //定义一个数组存放顺序表元素
    int length;                            //顺序表当前的长度(元素个数)
}SqList;                                   //给顺序表SQList起别名为SqList

void InitSqList(SqList* L) {  //初始化操作
    L->length = 0;  //顺序表初始化长度为0
}

2. 插入   

即:在第pos个位置插入value值,即在数组下标pos-1的位置插入value值

int InsertSqList(SqList* L, int pos, ElemType value) {
    //1.判断插入位置是否合法
    if (pos < 1 || pos > L->length + 1) {
        return -1; // 插入位置不合法
    }

    //2.判断顺序表存储空间是否满了
    if (L->length >= MaxSize) {
        return -2; // 顺序表空间已满
    }

    //3.将第pos个位置及往后的元素都后移一个位置,空出第pos个位置(这里采用逆序遍历)
    for (int i = L->length; i >= pos; i--) {
        L->data[i] = L->data[i - 1];
    }

    //4.插入数据
    L->data[pos - 1] = value;
    //5.表长加1
    L->length++;
    return 0; // 插入成功
}

3. 按位查找   

即:即返回第pos个位置(数组下标为pos-1)对应的value值

int findValueByPos(SqList* L, int pos, ElemType* value) {
    //1.判断要查找的位置是否合理
    if (pos < 1 || pos > L->length) {
        return -1; // 查找位置不合法
    }
    //2.查找第pos个位置对应的value值
    *value = L->data[pos - 1];
    return 0; // 查找成功
}

4. 按值查找   

即:即返回value值的位序,即第几个,下标是位序减1

int findPosByValue(SqList* L, ElemType value) {
    for (int i = 0; i < L->length; i++) {
        if (L->data[i] == value) {
            return i + 1;
        }
    }
    return -1; // 未找到该值
}

5. 删除   

即:将第pos个的值赋值给value后腾开第pos个位置
然后将第pos个后的数据都往前移一个位置,填补第pos个位置

int deleteSqList(SqList* L, int pos, ElemType* value) {
    //1.判断要删除的位置是否合理,即是否在存有数据的范围里
    if (pos < 1 || pos > L->length) {
        return -1; // 删除位置不合法
    }

    //2.判断空间是否为空
    if (L->length == 0) {
        return -2; // 顺序表空间为空
    }

    //3.将被删除的元素赋值给value
    *value = L->data[pos - 1];

    //4.将第pos个位置往后的元素都前移一个位置
    for (int i = pos; i < L->length; i++) {
        L->data[i - 1] = L->data[i];
    }

6. 注销   

注意:由于顺序表采用的是静态分配方式,L->data 是一个数组,并非动态分配的内存,所以不能使用 free(L->data) 来释放内存。同时,L 是在栈上分配的,也不能使用 free(L) 释放。

void  destroySqList(SqList* L) {
    //静态分配无需释放内存
    if (L != NULL)
    {
        L->length = 0;
    }
}

7. 打印顺序表

void printSqList(SqList* L) {  //让打印的最后一个元素末尾没有空格
    if (L->length == 0) {
        printf("当前顺序表为空!\n");
    }
    else {
        for (int i = 0; i < L->length; i++) {
            if (i == L->length - 1) {
                printf("%d", L->data[i]);
            }
            else {
                printf("%d ", L->data[i]);
            }
        }
        printf("\n");
    }
    printf("--------------------------------------------------\n");
}

8. 测试代码   

int main() {
    SqList L;
    InitSqList(&L);
    //插入数据测试
    InsertSqList(&L, 1, 18);
    InsertSqList(&L, 2, 7);
    InsertSqList(&L, 3, 34);
    printSqList1(&L);  //18 7 34

    //删除数据测试
    ElemType value;
    deleteSqList(&L, 2,&value);
    printSqList1(&L);  //18 34

    //查找位置1的值是什么
    ElemType val = findValueByPos(&L, 1);  
    printf("%d\n",val);  //18

    //查找值18在顺序表的第几个位置
    int pos = findPosByValue(&L,18);
    printf("%d\n", pos);  //1

    //销毁顺序表
    destroySqList(&L);

    return 0;
}

9. 完整代码   

#include <stdio.h>
#include <stdlib.h>

/*
    静态分配的顺序表
*/

#define MaxSize 50
typedef int ElemType;

typedef struct SQList {
    ElemType data[MaxSize];  //定义一个数组存放顺序表元素
    int length;              //顺序表当前的长度(元素个数)
} SqList; //给顺序表SQList起别名为SqList

//操作1——初始化
void InitSqList(SqList* L) {
    L->length = 0;  //顺序表初始化长度为0
}

//操作2——插入:在第pos个位置插入value值,即在数组下标pos-1的位置插入value值
int InsertSqList(SqList* L, int pos, ElemType value) {
    //1.判断插入位置是否合法
    if (pos < 1 || pos > L->length + 1) {
        return -1; // 插入位置不合法
    }

    //2.判断顺序表存储空间是否满了
    if (L->length >= MaxSize) {
        return -2; // 顺序表空间已满
    }

    //3.将第pos个位置及往后的元素都后移一个位置,空出第pos个位置(这里采用逆序遍历)
    for (int i = L->length; i >= pos; i--) {
        L->data[i] = L->data[i - 1];
    }

    //4.插入数据
    L->data[pos - 1] = value;
    //5.表长加1
    L->length++;
    return 0; // 插入成功
}

//操作3——按位查找,即返回第pos个位置对应的value值
int findValueByPos(SqList* L, int pos, ElemType* value) {
    //1.判断要查找的位置是否合理
    if (pos < 1 || pos > L->length) {
        return -1; // 查找位置不合法
    }
    //2.查找第pos个位置对应的value值
    *value = L->data[pos - 1];
    return 0; // 查找成功
}

//操作4——按值查找,即返回value值的位序,即第几个,下标加1
int findPosByValue(SqList* L, ElemType value) {
    for (int i = 0; i < L->length; i++) {
        if (L->data[i] == value) {
            return i + 1;
        }
    }
    return -1; // 未找到该值
}

//操作5——删除:将第pos个的值赋值给value后腾开第pos个位置
// 然后将第pos个后的都数据往前移一个位置,填补第pos个位置
int deleteSqList(SqList* L, int pos, ElemType* value) {
    //1.判断要删除的位置是否合理,即是否在存有数据的范围里
    if (pos < 1 || pos > L->length) {
        return -1; // 删除位置不合法
    }

    //2.判断空间是否为空
    if (L->length == 0) {
        return -2; // 顺序表空间为空
    }

    //3.将被删除的元素赋值给value
    *value = L->data[pos - 1];

    //4.将第pos个位置往后的元素都前移一个位置
    for (int i = pos; i < L->length; i++) {
        L->data[i - 1] = L->data[i];
    }

    //4.表长减1
    L->length--;
    return 0; // 删除成功
}

//操作6——注销
void destroySqList(SqList* L) {
    //静态分配无需释放内存
    if (L != NULL) {
        L->length = 0;
    }
}

//操作7——打印顺序表里存放的数据
void printSqList(SqList* L) {
    if (L->length == 0) {
        printf("当前顺序表为空!\n");
    }
    else {
        for (int i = 0; i < L->length; i++) {
            if (i == L->length - 1) {
                printf("%d", L->data[i]);
            }
            else {
                printf("%d ", L->data[i]);
            }
        }
        printf("\n");
    }
    printf("--------------------------------------------------\n");
}

//测试
int main() {
    SqList L;
    InitSqList(&L);
    //插入数据测试
    if (InsertSqList(&L, 1, 18) != 0) {
        printf("插入失败!\n");
    }
    if (InsertSqList(&L, 2, 7) != 0) {
        printf("插入失败!\n");
    }
    if (InsertSqList(&L, 3, 34) != 0) {
        printf("插入失败!\n");
    }
    printSqList(&L);  //18 7 34

    //删除数据测试
    ElemType value;
    if (deleteSqList(&L, 2, &value) != 0) {
        printf("删除失败!\n");
    }
    printSqList(&L);  //18 34

    //查找位置1的值是什么
    ElemType val;
    if (findValueByPos(&L, 1, &val) == 0) {
        printf("%d\n", val);  //18
    }
    else {
        printf("查找失败!\n");
    }

    //查找值18在顺序表的第几个位置
    int pos = findPosByValue(&L, 18);
    if (pos != -1) {
        printf("%d\n", pos);  //1
    }
    else {
        printf("未找到该值!\n");
    }

    //销毁顺序表
    destroySqList(&L);

    return 0;
}

10. 运行截图

文章如有出错不足处,欢迎评论区指出,如果觉得文章不错,就给我点个赞吧,谢谢!

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐