顺序表(动态扩容)

顺序表的介绍

顺序表的特点

元素连续排列,在中间进行插入(删除)时,之后的元素都会后移(前移)->增删比较慢,但是查找比较快。
动态扩容的实现思路:

  • 扩容时机:执行insert操作时,如果当前顺序表的长度和容量已经相等——没有剩余的位置供新元素插入,那么就需要进行扩容操作。
  • 扩容方法:开辟一块儿更大的空间,把原来的元素拷贝到新空间中,再把原来的空间释放掉,然后把表的指针指向新空间。(在C语言中可以使用realloc())

各个函数的介绍

首先,在定义顺序表时,我们使用了一个结构体来表示它,包括以下几个成员变量:

  • data: 一个指向整型数组的指针,用于存储顺序表中的元素
  • length: 当前顺序表的长度,即元素的个数
  • capacity: 当前分配的内存空间大小,即可以容纳的元素个数

接下来,我们介绍每个函数的作用:

  1. InitSeqList(SeqList* list): 初始化顺序表

    • 参数:指向顺序表的指针
    • 功能:分配初始内存空间,并将长度、容量初始化为0
  2. IsEmpty(SeqList list): 判断顺序表是否为空

    • 参数:顺序表
    • 返回值:若顺序表为空,则返回1;否则返回0
  3. GetLength(SeqList list): 获取顺序表长度

    • 参数:顺序表
    • 返回值:顺序表的长度
  4. Insert(SeqList* list, int pos, int value): 插入元素到顺序表指定位置

    • 参数:指向顺序表的指针,要插入的位置,要插入的值
    • 返回值:若插入成功,则返回1;否则返回0
    • 功能:在指定位置插入元素,并根据需要进行动态扩容
  5. Delete(SeqList* list, int pos): 删除顺序表指定位置的元素

    • 参数:指向顺序表的指针,要删除的位置
    • 返回值:若删除成功,则返回1;否则返回0
    • 功能:删除指定位置的元素,并根据需要进行动态缩容
  6. GetElement(SeqList list, int pos): 获取顺序表指定位置的元素

    • 参数:顺序表,要获取元素的位置
    • 返回值:指定位置的元素值,若位置不合法则返回-1
  7. DestroySeqList(SeqList* list): 销毁顺序表,释放内存

    • 参数:指向顺序表的指针
    • 功能:释放顺序表占用的内存空间
  8. WriteList(SeqList* list, const char* fileName): 将顺序表的数据写入文件

    • 参数:指向顺序表的指针,文件名
    • 返回值:若写入成功,则返回1;否则返回0
    • 功能:将顺序表中的每个元素依次写入文件中,用于持久化保存数据
  9. ReadList(SeqList* list, const char* fileName): 读取顺序表的数据

    • 参数:指向顺序表的指针,文件名
    • 返回值:若读取成功,则返回1;否则返回0
    • 功能:从文件中读取数据,并插入到顺序表中,用于加载保存的数据

最后,在main函数中,我们演示了如何使用这些函数来操作顺序表。首先,我们创建一个顺序表并进行初始化,然后在指定位置插入元素,删除元素,写入文件,读取文件,获取指定位置的元素等。最后,我们销毁顺序表,释放内存。

通过以上介绍,我们可以看到,这个顺序表实现了基本的插入、删除、获取元素等操作,还包括了动态扩容和缩容的功能,以及将数据持久化保存到文件和从文件中加载数据的功能。这样,我们就可以方便地对顺序表进行操作和管理。

实例代码

c语言版:

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

#define INIT_SIZE 10    // 初始分配的内存空间大小
#define INCREMENT 5     // 每次扩容增加的内存空间大小
#define FILE_NAME "text.txt"
typedef struct {
    int* data;          // 顺序表指针
    int length;         // 当前长度
    int capacity;       // 当前分配的内存空间大小
} SeqList;

// 初始化顺序表
void InitSeqList(SeqList* list)
{
    list->data = (int*)malloc(INIT_SIZE * sizeof(int));   // 分配初始内存空间
    if (!list->data) {
        printf("内存分配失败\n");
        exit(1);
    }

    list->length = 0;       // 长度初始化为0
    list->capacity = INIT_SIZE;     // 初始容量
}

// 判断顺序表是否为空
int IsEmpty(SeqList list)
{
    return list.length == 0;    // 长度为0表示为空
}

// 获取顺序表长度
int GetLength(SeqList list)
{
    return list.length;
}

// 插入元素到顺序表指定位置
int Insert(SeqList* list, int pos, int value)
{
    if (pos < 1 || pos > list->length + 1) {
        // 位置不合法
        return 0;
    }

    if (list->length >= list->capacity) {
        // 如果当前内存空间已满,则进行扩容
        int* newData = (int*)realloc(list->data, (list->capacity + INCREMENT) * sizeof(int));
        if (!newData) {
            printf("内存分配失败\n");
            return 0;
        }

        list->data = newData;
        list->capacity += INCREMENT;    // 更新容量
    }

    // 将pos及之后的元素向后移动一位
    for (int i = list->length; i >= pos; i--) {
        list->data[i] = list->data[i - 1];
    }

    list->data[pos - 1] = value;    // 在pos-1位置插入新元素
    list->length++;                 // 长度加1

    return 1;
}

// 删除顺序表指定位置的元素
int Delete(SeqList* list, int pos)
{
    if (pos < 1 || pos > list->length) {
        // 位置不合法
        return 0;
    }

    // 将pos之后的元素向前移动一位
    for (int i = pos - 1; i < list->length - 1; i++) {
        list->data[i] = list->data[i + 1];
    }

    list->length--; // 长度减1

    if (list->capacity - list->length >= INCREMENT) {
        // 如果剩余空间过多,则进行缩容
        int* newData = (int*)realloc(list->data, (list->capacity - INCREMENT) * sizeof(int));
        if (!newData && list->length > 0) {
            printf("内存分配失败\n");
            return 0;
        }

        list->data = newData;
        list->capacity -= INCREMENT;    // 更新容量
    }

    return 1;
}

// 获取顺序表指定位置的元素
int GetElement(SeqList list, int pos)
{
    if (pos < 1 || pos > list.length) {
        // 位置不合法
        return -1;
    }

    return list.data[pos - 1];   // 返回指定位置的元素值
}

// 销毁顺序表,释放内存
void DestroySeqList(SeqList* list)
{
    free(list->data);
    list->data = NULL;
    list->length = 0;
    list->capacity = 0;
}

// 将顺序表的数据写入文件
int WriteList(SeqList* list, const char* fileName) {
    FILE* fp = fopen(fileName, "wb");
    if (!fp) {
        printf("文件打开失败\n");
        return 0;
    }

    // 将顺序表中的每个元素依次写入文件中
    for (int i = 0; i < list->length; i++) {
        if (fwrite(&list->data[i], sizeof(int), 1, fp) != 1) {
            fclose(fp);
            return 0;
        }
    }

    fclose(fp);
    return 1;
}
// 读取顺序表的数据
int ReadList(SeqList* list, const char* fileName) {
    FILE* fp = fopen(fileName, "rb");
    if (!fp) {
        printf("文件打开失败\n");
        return 0;
    }

    // 读取文件中的数据,并插入到顺序表中
    int value;
    int i = 0;
    while (fread(&value, sizeof(int), 1, fp)) {
        if (!Insert(list,i++, value)) {
            fclose(fp);
            return 0;
        }
    }

    fclose(fp);
    return 1;
}
int main()
{
    SeqList list;
    InitSeqList(&list);
    const char * filename = FILE_NAME;

    // 在第一个位置插入元素10
    Insert(&list, 1, 10);

    // 在第二个位置插入元素20
    Insert(&list, 2, 20);

    // 删除第一个位置的元素
    Delete(&list, 1);
    WriteList(&list, filename);
    ReadList(&list, filename);
    // 获取第一个位置的元素
    int element = GetElement(list, 1);
    printf("First element: %d\n", element);
    
    DestroySeqList(&list);  // 销毁顺序表,释放内存

    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值